From 07dc80dd9a21df820a3de3ea0cb1768c74aeab9d Mon Sep 17 00:00:00 2001 From: SomberNight Date: Sun, 4 Feb 2024 08:54:40 +0000 Subject: [PATCH] qml wizard: stricter validation for new wallet name user on bitcointalk [0] tried to create wallet with name "w/o 2FA". Before this, one would only get an error after the last page of the wizard. With this, the "Next" button does not even get enabled if the name does not look ok. (and as in comment, maybe we should be even stricter re what is allowed) [0]: https://bitcointalk.org/index.php?topic=5483514.msg63584789#msg63584789 --- .../qml/components/wizard/WCWalletName.qml | 2 +- electrum/gui/qml/qewizard.py | 28 ++++++++++++++++++- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/electrum/gui/qml/components/wizard/WCWalletName.qml b/electrum/gui/qml/components/wizard/WCWalletName.qml index 581547c18..4a9cad5a7 100644 --- a/electrum/gui/qml/components/wizard/WCWalletName.qml +++ b/electrum/gui/qml/components/wizard/WCWalletName.qml @@ -5,7 +5,7 @@ import QtQuick.Controls import org.electrum 1.0 WizardComponent { - valid: wallet_name.text.length > 0 && !Daemon.availableWallets.wallet_name_exists(wallet_name.text) + valid: wiz.isValidNewWalletName(wallet_name.text) function apply() { wizard_data['wallet_name'] = wallet_name.text diff --git a/electrum/gui/qml/qewizard.py b/electrum/gui/qml/qewizard.py index dd15c1764..c35709c02 100644 --- a/electrum/gui/qml/qewizard.py +++ b/electrum/gui/qml/qewizard.py @@ -6,6 +6,8 @@ from PyQt6.QtCore import pyqtProperty, pyqtSignal, pyqtSlot, QObject from electrum.logging import get_logger from electrum import mnemonic from electrum.wizard import NewWalletWizard, ServerConnectWizard +from electrum.storage import WalletStorage, StorageReadWriteError +from electrum.util import WalletFileException if TYPE_CHECKING: from electrum.gui.qml.qedaemon import QEDaemon @@ -116,6 +118,30 @@ class QENewWalletWizard(NewWalletWizard, QEAbstractWizard): 'message': validation_message } + def _wallet_path_from_wallet_name(self, wallet_name: str) -> str: + return os.path.join(self._qedaemon.daemon.config.get_datadir_wallet_path(), wallet_name) + + @pyqtSlot(str, result=bool) + def isValidNewWalletName(self, wallet_name: str) -> bool: + if not wallet_name: + return False + if self._qedaemon.availableWallets.wallet_name_exists(wallet_name): + return False + wallet_path = self._wallet_path_from_wallet_name(wallet_name) + # note: we should probably restrict wallet names to be alphanumeric (plus underscore, etc)... + # wallet_name might contain ".." (etc) and hence sketchy path traversals are possible. + # Anyway, this at least validates that the path looks sane to the filesystem: + try: + temp_storage = WalletStorage(wallet_path) + except (StorageReadWriteError, WalletFileException) as e: + return False + except Exception as e: + self._logger.exception("") + return False + if temp_storage.file_exists(): + return False + return True + @pyqtSlot('QJSValue', bool, str) def createStorage(self, js_data, single_password_enabled, single_password): self._logger.info('Creating wallet from wizard data') @@ -125,7 +151,7 @@ class QENewWalletWizard(NewWalletWizard, QEAbstractWizard): data['encrypt'] = True data['password'] = single_password - path = os.path.join(os.path.dirname(self._qedaemon.daemon.config.get_wallet_path()), data['wallet_name']) + path = self._wallet_path_from_wallet_name(data['wallet_name']) try: self.create_storage(path, data)