From 7fc1d75cd3f87732279b38f222033ded1b00da3b Mon Sep 17 00:00:00 2001 From: Thomas Waldmann Date: Sun, 10 Apr 2022 20:58:59 +0200 Subject: [PATCH] load_key: no key is same as empty key, fixes #6441 when migrating from repokey to keyfile, we just store an empty key into the repo config, because we do not have a "delete key" RPC api. thus, empty key means "there is no key". here we fix load_key, so that it does not behave differently for no key and empty key: in both cases, it just returns an empty value. additionally, we strip the value we get from the config, so whitespace does not matter. All callers now check for the repokey not being empty, otherwise RepoKeyNotFoundError is raised. --- src/borg/crypto/key.py | 12 ++++++++---- src/borg/crypto/keymanager.py | 9 +++++++-- src/borg/repository.py | 3 ++- 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/src/borg/crypto/key.py b/src/borg/crypto/key.py index 178cd952a..57e8ceed9 100644 --- a/src/borg/crypto/key.py +++ b/src/borg/crypto/key.py @@ -789,11 +789,11 @@ class RepoKey(ID_HMAC_SHA_256, KeyfileKeyBase): def find_key(self): loc = self.repository._location.canonical_path() - try: - self.repository.load_key() - return loc - except configparser.NoOptionError: + key = self.repository.load_key() + if not key: + # if we got an empty key, it means there is no key. raise RepoKeyNotFoundError(loc) from None + return loc def get_new_target(self, args): return self.repository @@ -806,6 +806,10 @@ class RepoKey(ID_HMAC_SHA_256, KeyfileKeyBase): # what we get in target is just a repo location, but we already have the repo obj: target = self.repository key_data = target.load_key() + if not key_data: + # if we got an empty key, it means there is no key. + loc = target._location.canonical_path() + raise RepoKeyNotFoundError(loc) from None key_data = key_data.decode('utf-8') # remote repo: msgpack issue #99, getting bytes success = self._load(key_data, passphrase) if success: diff --git a/src/borg/crypto/keymanager.py b/src/borg/crypto/keymanager.py index 32dd39c04..2d41c3022 100644 --- a/src/borg/crypto/keymanager.py +++ b/src/borg/crypto/keymanager.py @@ -7,7 +7,7 @@ from hashlib import sha256 from ..helpers import Manifest, NoManifestError, Error, yes, bin_to_hex, dash_open from ..repository import Repository -from .key import KeyfileKey, KeyfileNotFoundError, KeyBlobStorage, identify_key +from .key import KeyfileKey, KeyfileNotFoundError, RepoKeyNotFoundError, KeyBlobStorage, identify_key class UnencryptedRepo(Error): @@ -56,7 +56,12 @@ class KeyManager: self.keyblob = ''.join(fd.readlines()[1:]) elif self.keyblob_storage == KeyBlobStorage.REPO: - self.keyblob = self.repository.load_key().decode() + key_data = self.repository.load_key().decode() + if not key_data: + # if we got an empty key, it means there is no key. + loc = self.repository._location.canonical_path() + raise RepoKeyNotFoundError(loc) from None + self.keyblob = key_data def store_keyblob(self, args): if self.keyblob_storage == KeyBlobStorage.KEYFILE: diff --git a/src/borg/repository.py b/src/borg/repository.py index bb67c5a3f..f9178abbc 100644 --- a/src/borg/repository.py +++ b/src/borg/repository.py @@ -338,7 +338,8 @@ class Repository: self.save_config(self.path, self.config) def load_key(self): - keydata = self.config.get('repository', 'key') + keydata = self.config.get('repository', 'key', fallback='').strip() + # note: if we return an empty string, it means there is no repo key return keydata.encode('utf-8') # remote repo: msgpack issue #99, returning bytes def get_free_nonce(self):