From 3dc2fc03f08e4327a3eb5e1ed36f2a1bbb86cb09 Mon Sep 17 00:00:00 2001 From: Thomas Waldmann Date: Sat, 5 Mar 2016 00:54:19 +0100 Subject: [PATCH] added retry counter for passwords, fixes #703 --- borg/key.py | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/borg/key.py b/borg/key.py index 6e56de199..cf7f72a78 100644 --- a/borg/key.py +++ b/borg/key.py @@ -18,6 +18,10 @@ import msgpack PREFIX = b'\0' * 8 +class PasswordRetriesExceeded(Error): + """exceeded the maximum password retries""" + + class UnsupportedPayloadError(Error): """Unsupported payload type {}. A newer version is required to access this repository.""" @@ -185,7 +189,7 @@ class Passphrase(str): passphrase = cls.env_passphrase() if passphrase is not None: return passphrase - while True: + for retry in range(1, 11): passphrase = cls.getpass('Enter new passphrase: ') if allow_empty or passphrase: passphrase2 = cls.getpass('Enter same passphrase again: ') @@ -196,6 +200,8 @@ class Passphrase(str): print('Passphrases do not match', file=sys.stderr) else: print('Passphrase must not be blank', file=sys.stderr) + else: + raise PasswordRetriesExceeded def __repr__(self): return '' @@ -231,7 +237,7 @@ class PassphraseKey(AESKeyBase): passphrase = Passphrase.env_passphrase() if passphrase is None: passphrase = Passphrase.getpass(prompt) - while True: + for retry in range(1, 3): key.init(repository, passphrase) try: key.decrypt(None, manifest_data) @@ -240,6 +246,8 @@ class PassphraseKey(AESKeyBase): return key except IntegrityError: passphrase = Passphrase.getpass(prompt) + else: + raise PasswordRetriesExceeded def change_passphrase(self): class ImmutablePassphraseError(Error): @@ -259,8 +267,12 @@ class KeyfileKeyBase(AESKeyBase): target = key.find_key() prompt = 'Enter passphrase for key %s: ' % target passphrase = Passphrase.env_passphrase(default='') - while not key.load(target, passphrase): + for retry in range(1, 4): + if key.load(target, passphrase): + break passphrase = Passphrase.getpass(prompt) + else: + raise PasswordRetriesExceeded num_blocks = num_aes_blocks(len(manifest_data) - 41) key.init_ciphers(PREFIX + long_to_bytes(key.extract_nonce(manifest_data) + num_blocks)) return key