sync_apply overwrites local password when encrypt-on-disk is true
This commit is contained in:
parent
1075cd9995
commit
bcd69f812e
3 changed files with 25 additions and 49 deletions
|
@ -1618,10 +1618,15 @@ class Daemon(metaclass=JSONRPCServerType):
|
||||||
return hexlify(wallet.hash).decode()
|
return hexlify(wallet.hash).decode()
|
||||||
|
|
||||||
@requires("wallet", conditions=[WALLET_IS_UNLOCKED])
|
@requires("wallet", conditions=[WALLET_IS_UNLOCKED])
|
||||||
async def jsonrpc_sync_apply(self, password, data=None, encrypt_password=None, wallet_id=None, blocking=False):
|
async def jsonrpc_sync_apply(self, password, data=None, wallet_id=None, blocking=False):
|
||||||
"""
|
"""
|
||||||
Apply incoming synchronization data, if provided, and then produce a sync hash and
|
Apply incoming synchronization data, if provided, and return a sync hash and update wallet data.
|
||||||
an encrypted wallet.
|
|
||||||
|
Wallet must be unlocked to perform this operation.
|
||||||
|
|
||||||
|
If "encrypt-on-disk" preference is True and supplied password is different from local password,
|
||||||
|
or there is no local password (because local wallet was not encrypted), then the supplied password
|
||||||
|
will be used for local encryption (overwriting previous local encryption password).
|
||||||
|
|
||||||
Usage:
|
Usage:
|
||||||
sync_apply <password> [--data=<data>] [--wallet_id=<wallet_id>] [--blocking]
|
sync_apply <password> [--data=<data>] [--wallet_id=<wallet_id>] [--blocking]
|
||||||
|
|
|
@ -82,10 +82,7 @@ class WalletEncryptionAndSynchronization(CommandTestCase):
|
||||||
daemon = self.daemon
|
daemon = self.daemon
|
||||||
wallet = daemon.wallet_manager.default_wallet
|
wallet = daemon.wallet_manager.default_wallet
|
||||||
|
|
||||||
self.assertEqual(
|
self.assertEqual(daemon.jsonrpc_wallet_status(), {'is_locked': False, 'is_encrypted': False})
|
||||||
daemon.jsonrpc_wallet_status(),
|
|
||||||
{'is_locked': False, 'is_encrypted': False}
|
|
||||||
)
|
|
||||||
self.assertIsNone(daemon.jsonrpc_preference_get(ENCRYPT_ON_DISK))
|
self.assertIsNone(daemon.jsonrpc_preference_get(ENCRYPT_ON_DISK))
|
||||||
self.assertWalletEncrypted(wallet.storage.path, False)
|
self.assertWalletEncrypted(wallet.storage.path, False)
|
||||||
|
|
||||||
|
@ -97,39 +94,23 @@ class WalletEncryptionAndSynchronization(CommandTestCase):
|
||||||
daemon.jsonrpc_wallet_decrypt() # already not encrypted
|
daemon.jsonrpc_wallet_decrypt() # already not encrypted
|
||||||
|
|
||||||
daemon.jsonrpc_wallet_encrypt('password')
|
daemon.jsonrpc_wallet_encrypt('password')
|
||||||
|
self.assertEqual(daemon.jsonrpc_wallet_status(), {'is_locked': False, 'is_encrypted': True})
|
||||||
self.assertEqual(
|
self.assertEqual(daemon.jsonrpc_preference_get(ENCRYPT_ON_DISK), {'encrypt-on-disk': True})
|
||||||
daemon.jsonrpc_wallet_status(),
|
|
||||||
{'is_locked': False, 'is_encrypted': True}
|
|
||||||
)
|
|
||||||
self.assertEqual(
|
|
||||||
daemon.jsonrpc_preference_get(ENCRYPT_ON_DISK),
|
|
||||||
{'encrypt-on-disk': True}
|
|
||||||
)
|
|
||||||
self.assertWalletEncrypted(wallet.storage.path, True)
|
self.assertWalletEncrypted(wallet.storage.path, True)
|
||||||
|
|
||||||
daemon.jsonrpc_wallet_lock()
|
daemon.jsonrpc_wallet_lock()
|
||||||
|
self.assertEqual(daemon.jsonrpc_wallet_status(), {'is_locked': True, 'is_encrypted': True})
|
||||||
|
|
||||||
self.assertEqual(
|
# can't sign transactions with locked wallet
|
||||||
daemon.jsonrpc_wallet_status(),
|
|
||||||
{'is_locked': True, 'is_encrypted': True}
|
|
||||||
)
|
|
||||||
|
|
||||||
with self.assertRaises(error.ComponentStartConditionNotMet):
|
with self.assertRaises(error.ComponentStartConditionNotMet):
|
||||||
await daemon.jsonrpc_channel_create('@foo', '1.0')
|
await daemon.jsonrpc_channel_create('@foo', '1.0')
|
||||||
|
|
||||||
daemon.jsonrpc_wallet_unlock('password')
|
daemon.jsonrpc_wallet_unlock('password')
|
||||||
|
self.assertEqual(daemon.jsonrpc_wallet_status(), {'is_locked': False, 'is_encrypted': True})
|
||||||
await daemon.jsonrpc_channel_create('@foo', '1.0')
|
await daemon.jsonrpc_channel_create('@foo', '1.0')
|
||||||
|
|
||||||
daemon.jsonrpc_wallet_decrypt()
|
daemon.jsonrpc_wallet_decrypt()
|
||||||
self.assertEqual(
|
self.assertEqual(daemon.jsonrpc_wallet_status(), {'is_locked': False, 'is_encrypted': False})
|
||||||
daemon.jsonrpc_wallet_status(),
|
self.assertEqual(daemon.jsonrpc_preference_get(ENCRYPT_ON_DISK), {'encrypt-on-disk': False})
|
||||||
{'is_locked': False, 'is_encrypted': False}
|
|
||||||
)
|
|
||||||
self.assertEqual(
|
|
||||||
daemon.jsonrpc_preference_get(ENCRYPT_ON_DISK),
|
|
||||||
{'encrypt-on-disk': False}
|
|
||||||
)
|
|
||||||
self.assertWalletEncrypted(wallet.storage.path, False)
|
self.assertWalletEncrypted(wallet.storage.path, False)
|
||||||
|
|
||||||
async def test_sync_with_encryption_and_password_change(self):
|
async def test_sync_with_encryption_and_password_change(self):
|
||||||
|
@ -137,42 +118,32 @@ class WalletEncryptionAndSynchronization(CommandTestCase):
|
||||||
wallet, wallet2 = daemon.wallet_manager.default_wallet, daemon2.wallet_manager.default_wallet
|
wallet, wallet2 = daemon.wallet_manager.default_wallet, daemon2.wallet_manager.default_wallet
|
||||||
|
|
||||||
daemon.jsonrpc_wallet_encrypt('password')
|
daemon.jsonrpc_wallet_encrypt('password')
|
||||||
|
self.assertEqual(wallet.encryption_password, 'password')
|
||||||
self.assertEqual(daemon.jsonrpc_wallet_status(), {'is_locked': False, 'is_encrypted': True})
|
|
||||||
self.assertEqual(daemon2.jsonrpc_wallet_status(), {'is_locked': False, 'is_encrypted': False})
|
|
||||||
self.assertEqual(daemon.jsonrpc_preference_get(ENCRYPT_ON_DISK), {'encrypt-on-disk': True})
|
|
||||||
self.assertIsNone(daemon2.jsonrpc_preference_get(ENCRYPT_ON_DISK))
|
|
||||||
self.assertWalletEncrypted(wallet.storage.path, True)
|
|
||||||
self.assertWalletEncrypted(wallet2.storage.path, False)
|
|
||||||
|
|
||||||
data = await daemon2.jsonrpc_sync_apply('password2')
|
data = await daemon2.jsonrpc_sync_apply('password2')
|
||||||
with self.assertRaises(ValueError): # wrong password
|
with self.assertRaises(ValueError): # wrong password
|
||||||
await daemon.jsonrpc_sync_apply('password', data=data['data'], blocking=True)
|
await daemon.jsonrpc_sync_apply('password', data=data['data'], blocking=True)
|
||||||
await daemon.jsonrpc_sync_apply('password2', data=data['data'], blocking=True)
|
await daemon.jsonrpc_sync_apply('password2', data=data['data'], blocking=True)
|
||||||
|
|
||||||
# encryption did not change from before sync_apply
|
# password changed
|
||||||
|
self.assertEqual(wallet.encryption_password, 'password2')
|
||||||
self.assertEqual(daemon.jsonrpc_wallet_status(), {'is_locked': False, 'is_encrypted': True})
|
self.assertEqual(daemon.jsonrpc_wallet_status(), {'is_locked': False, 'is_encrypted': True})
|
||||||
self.assertEqual(daemon.jsonrpc_preference_get(ENCRYPT_ON_DISK), {'encrypt-on-disk': True})
|
self.assertEqual(daemon.jsonrpc_preference_get(ENCRYPT_ON_DISK), {'encrypt-on-disk': True})
|
||||||
self.assertWalletEncrypted(wallet.storage.path, True)
|
self.assertWalletEncrypted(wallet.storage.path, True)
|
||||||
|
|
||||||
# old password is still used
|
# check new password is active
|
||||||
daemon.jsonrpc_wallet_lock()
|
|
||||||
self.assertFalse(daemon.jsonrpc_wallet_unlock('password2'))
|
|
||||||
self.assertTrue(daemon.jsonrpc_wallet_unlock('password'))
|
|
||||||
|
|
||||||
# encrypt using new password
|
|
||||||
daemon.jsonrpc_wallet_encrypt('password2')
|
|
||||||
daemon.jsonrpc_wallet_lock()
|
daemon.jsonrpc_wallet_lock()
|
||||||
self.assertFalse(daemon.jsonrpc_wallet_unlock('password'))
|
self.assertFalse(daemon.jsonrpc_wallet_unlock('password'))
|
||||||
self.assertTrue(daemon.jsonrpc_wallet_unlock('password2'))
|
self.assertTrue(daemon.jsonrpc_wallet_unlock('password2'))
|
||||||
|
|
||||||
|
# propagate disk encryption to daemon2
|
||||||
data = await daemon.jsonrpc_sync_apply('password2')
|
data = await daemon.jsonrpc_sync_apply('password2')
|
||||||
|
self.assertEqual(wallet2.encryption_password, None)
|
||||||
await daemon2.jsonrpc_sync_apply('password2', data=data['data'], blocking=True)
|
await daemon2.jsonrpc_sync_apply('password2', data=data['data'], blocking=True)
|
||||||
|
self.assertEqual(wallet.encryption_password, 'password2')
|
||||||
# wallet2 is now encrypted using new password
|
|
||||||
self.assertEqual(daemon2.jsonrpc_wallet_status(), {'is_locked': False, 'is_encrypted': True})
|
self.assertEqual(daemon2.jsonrpc_wallet_status(), {'is_locked': False, 'is_encrypted': True})
|
||||||
self.assertEqual(daemon2.jsonrpc_preference_get(ENCRYPT_ON_DISK), {'encrypt-on-disk': True})
|
self.assertEqual(daemon2.jsonrpc_preference_get(ENCRYPT_ON_DISK), {'encrypt-on-disk': True})
|
||||||
self.assertWalletEncrypted(wallet.storage.path, True)
|
self.assertWalletEncrypted(wallet2.storage.path, True)
|
||||||
|
|
||||||
daemon2.jsonrpc_wallet_lock()
|
daemon2.jsonrpc_wallet_lock()
|
||||||
self.assertTrue(daemon2.jsonrpc_wallet_unlock('password2'))
|
self.assertTrue(daemon2.jsonrpc_wallet_unlock('password2'))
|
||||||
|
|
|
@ -178,7 +178,7 @@ class Wallet:
|
||||||
added_accounts = []
|
added_accounts = []
|
||||||
decrypted_data = self.unpack(password, data)
|
decrypted_data = self.unpack(password, data)
|
||||||
self.preferences.merge(decrypted_data.get('preferences', {}))
|
self.preferences.merge(decrypted_data.get('preferences', {}))
|
||||||
if not self.encryption_password and self.preferences.get(ENCRYPT_ON_DISK, False):
|
if self.preferences.get(ENCRYPT_ON_DISK, False):
|
||||||
self.encryption_password = password
|
self.encryption_password = password
|
||||||
for account_dict in decrypted_data['accounts']:
|
for account_dict in decrypted_data['accounts']:
|
||||||
ledger = manager.get_or_create_ledger(account_dict['ledger'])
|
ledger = manager.get_or_create_ledger(account_dict['ledger'])
|
||||||
|
|
Loading…
Reference in a new issue