From 0e7b3eba0bee9d717fdc7f023e242daadaca6859 Mon Sep 17 00:00:00 2001 From: CharlVS <77973576+CharlVS@users.noreply.github.com> Date: Wed, 28 Aug 2024 12:57:05 +0200 Subject: [PATCH 1/2] Restrict wallet creation with config flag KDF startup throws an error if the `allow_registrations` config value is false and the seed is unknown (no name provided) or if a name is provided and it has not been registered before. This is used to emulate the sign-in vs register behaviour a typical auth service would provide. --- mm2src/mm2_core/src/mm_ctx.rs | 3 ++ mm2src/mm2_main/src/lp_wallet.rs | 32 +++++++++++++++---- .../src/lp_wallet/mnemonics_storage.rs | 11 +++++++ .../src/lp_wallet/mnemonics_wasm_db.rs | 11 +++++++ 4 files changed, 51 insertions(+), 6 deletions(-) diff --git a/mm2src/mm2_core/src/mm_ctx.rs b/mm2src/mm2_core/src/mm_ctx.rs index e891f0b649..13ea39bdd0 100644 --- a/mm2src/mm2_core/src/mm_ctx.rs +++ b/mm2src/mm2_core/src/mm_ctx.rs @@ -246,6 +246,9 @@ impl MmCtx { #[cfg(not(target_arch = "wasm32"))] pub fn is_https(&self) -> bool { self.conf["https"].as_bool().unwrap_or(false) } + /// Whether or not new wallets can be created. + pub fn allow_registrations(&self) -> bool { self.conf["allow_registrations"].as_bool().unwrap_or(true) } + /// SANs for self-signed certificate generation. #[cfg(not(target_arch = "wasm32"))] pub fn alt_names(&self) -> Result, String> { diff --git a/mm2src/mm2_main/src/lp_wallet.rs b/mm2src/mm2_main/src/lp_wallet.rs index 19ac357cab..8e75e83637 100644 --- a/mm2src/mm2_main/src/lp_wallet.rs +++ b/mm2src/mm2_main/src/lp_wallet.rs @@ -43,6 +43,8 @@ pub enum WalletInitError { fmt = "Passphrase doesn't match the one from file, please create a new wallet if you want to use a new passphrase" )] PassphraseMismatch, + #[display(fmt = "Error initializing wallet. Wallet mnemonic/name is unknown and wallet creation is disabled")] + WalletCreationNotAllowed, #[display(fmt = "Error generating or decrypting mnemonic: {}", _0)] MnemonicError(String), #[display(fmt = "Error initializing crypto context: {}", _0)] @@ -171,13 +173,17 @@ async fn retrieve_or_create_passphrase( // If an existing passphrase is found, return it Ok(Some(passphrase_from_file)) }, - None => { - // If no passphrase is found, generate a new one + None if ctx.allow_registrations() => { + // If no passphrase is found and registrations are allowed, generate a new one let new_passphrase = generate_mnemonic(ctx)?.to_string(); // Encrypt and save the new passphrase encrypt_and_save_passphrase(ctx, wallet_name, &new_passphrase, wallet_password).await?; Ok(Some(new_passphrase)) }, + None => { + // If no passphrase is found and registrations are not allowed, return an error + Err(WalletInitError::WalletCreationNotAllowed.into()) + }, } } @@ -193,11 +199,15 @@ async fn confirm_or_encrypt_and_store_passphrase( // If an existing passphrase is found and it matches the provided passphrase, return it Ok(Some(passphrase_from_file)) }, - None => { - // If no passphrase is found in the file, encrypt and save the provided passphrase + None if ctx.allow_registrations() => { + // If no passphrase is found in the file and registrations are allowed, encrypt and save the provided passphrase encrypt_and_save_passphrase(ctx, wallet_name, passphrase, wallet_password).await?; Ok(Some(passphrase.to_string())) }, + None => { + // If no passphrase is found and registrations are not allowed, return an error + Err(WalletInitError::WalletCreationNotAllowed.into()) + }, _ => { // If an existing passphrase is found and it does not match the provided passphrase, return an error Err(WalletInitError::PassphraseMismatch.into()) @@ -220,12 +230,16 @@ async fn decrypt_validate_or_save_passphrase( // If an existing passphrase is found and it matches the decrypted passphrase, return it Ok(Some(decrypted_passphrase)) }, - None => { + None if ctx.allow_registrations() => { save_encrypted_passphrase(ctx, wallet_name, &encrypted_passphrase_data) .await .mm_err(|e| WalletInitError::WalletsStorageError(e.to_string()))?; Ok(Some(decrypted_passphrase)) }, + None => { + // If no passphrase is found and registrations are not allowed, return an error + Err(WalletInitError::WalletCreationNotAllowed.into()) + }, _ => { // If an existing passphrase is found and it does not match the decrypted passphrase, return an error Err(WalletInitError::PassphraseMismatch.into()) @@ -258,8 +272,14 @@ async fn process_passphrase_logic( match (wallet_name, passphrase) { (None, None) => Ok(None), // Legacy approach for passphrase, no `wallet_name` is needed in the config, in this case the passphrase is not encrypted and saved. - (None, Some(Passphrase::Decrypted(passphrase))) => Ok(Some(passphrase)), // Importing an encrypted passphrase without a wallet name is not supported since it's not possible to save the passphrase. + (None, Some(Passphrase::Decrypted(passphrase))) => { + if ctx.allow_registrations() { + Ok(Some(passphrase)) + } else { + Err(WalletInitError::WalletCreationNotAllowed.into()) + } + }, (None, Some(Passphrase::Encrypted(_))) => Err(WalletInitError::FieldNotFoundInConfig { field: "wallet_name".to_owned(), } diff --git a/mm2src/mm2_main/src/lp_wallet/mnemonics_storage.rs b/mm2src/mm2_main/src/lp_wallet/mnemonics_storage.rs index 3cf40e61fb..1558cff803 100644 --- a/mm2src/mm2_main/src/lp_wallet/mnemonics_storage.rs +++ b/mm2src/mm2_main/src/lp_wallet/mnemonics_storage.rs @@ -25,6 +25,17 @@ pub(super) async fn save_encrypted_passphrase( encrypted_passphrase_data: &EncryptedData, ) -> WalletsStorageResult<()> { let wallet_path = ctx.wallet_file_path(wallet_name); + + // Check if the wallet file already exists + if !wallet_path.exists() { + // If it doesn't exist and registrations are not allowed, return an error + if !ctx.allow_registrations() { + return Err(MmError::new(WalletsStorageError::Internal( + "Wallet creation is not allowed. Registrations are disabled.".to_string(), + ))); + } + } + ensure_file_is_writable(&wallet_path).map_to_mm(WalletsStorageError::FsWriteError)?; mm2_io::fs::write_json(encrypted_passphrase_data, &wallet_path, true) .await diff --git a/mm2src/mm2_main/src/lp_wallet/mnemonics_wasm_db.rs b/mm2src/mm2_main/src/lp_wallet/mnemonics_wasm_db.rs index 40daa62029..62d1328630 100644 --- a/mm2src/mm2_main/src/lp_wallet/mnemonics_wasm_db.rs +++ b/mm2src/mm2_main/src/lp_wallet/mnemonics_wasm_db.rs @@ -103,6 +103,17 @@ pub(super) async fn save_encrypted_passphrase( let transaction = db.transaction().await?; let table = transaction.table::().await?; + // Check if the wallet already exists + let existing_wallet = table + .get_item_by_unique_index("wallet_name", wallet_name.to_string()) + .await?; + + if existing_wallet.is_none() && !ctx.allow_registrations() { + return Err(MmError::new(WalletsDBError::Internal( + "Wallet creation is not allowed. Registrations are disabled.".to_string(), + ))); + } + let mnemonics_table_item = MnemonicsTable { wallet_name: wallet_name.to_string(), encrypted_mnemonic: serde_json::to_string(encrypted_passphrase_data).map_err(|e| { From f44f78bcc02704925cc12e0335db5653a226123e Mon Sep 17 00:00:00 2001 From: "Charl (Nitride)" <77973576+CharlVS@users.noreply.github.com> Date: Fri, 30 Aug 2024 12:29:36 +0200 Subject: [PATCH 2/2] Update mm2src/mm2_main/src/lp_wallet.rs Co-authored-by: Samuel Onoja --- mm2src/mm2_main/src/lp_wallet.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/mm2src/mm2_main/src/lp_wallet.rs b/mm2src/mm2_main/src/lp_wallet.rs index 8e75e83637..7393171cdd 100644 --- a/mm2src/mm2_main/src/lp_wallet.rs +++ b/mm2src/mm2_main/src/lp_wallet.rs @@ -230,13 +230,13 @@ async fn decrypt_validate_or_save_passphrase( // If an existing passphrase is found and it matches the decrypted passphrase, return it Ok(Some(decrypted_passphrase)) }, - None if ctx.allow_registrations() => { - save_encrypted_passphrase(ctx, wallet_name, &encrypted_passphrase_data) - .await - .mm_err(|e| WalletInitError::WalletsStorageError(e.to_string()))?; - Ok(Some(decrypted_passphrase)) - }, None => { + if ctx.allow_registrations() { + save_encrypted_passphrase(ctx, wallet_name, &encrypted_passphrase_data) + .await + .mm_err(|e| WalletInitError::WalletsStorageError(e.to_string()))?; + return Ok(Some(decrypted_passphrase)); + } // If no passphrase is found and registrations are not allowed, return an error Err(WalletInitError::WalletCreationNotAllowed.into()) },