mirror of
https://github.com/borgbackup/borg.git
synced 2025-02-24 07:01:59 +00:00
check: try harder to create the key, fixes #5719
the old code did just 1 attempt to detect the repo decryption key. if the first chunkid we got from the chunks hashtable iterator was accidentally the id of the chunk we intentionally corrupted in test_delete_double_force, setup of the key failed and that made the test crash. in practice, this could of course also happen if chunks are corrupted, thus we now do many retries with other chunks before giving up. error handling was improved: do not return None (instead of a key), it just leads to weird crashes elsewhere, but fail early with IntegrityError and a reasonable error msg. rename method to make_key to avoid confusion with borg.crypto.key.identify_key.
This commit is contained in:
parent
e7c2506a7f
commit
53830ecae9
1 changed files with 20 additions and 10 deletions
|
@ -21,7 +21,7 @@
|
|||
from . import xattr
|
||||
from .chunker import get_chunker, Chunk
|
||||
from .cache import ChunkListEntry
|
||||
from .crypto.key import key_factory, AEADKeyBase
|
||||
from .crypto.key import key_factory, UnsupportedPayloadError, AEADKeyBase
|
||||
from .compress import Compressor, CompressionSpec
|
||||
from .constants import * # NOQA
|
||||
from .crypto.low_level import IntegrityError as IntegrityErrorBase
|
||||
|
@ -1630,7 +1630,7 @@ def check(
|
|||
if not self.chunks:
|
||||
logger.error("Repository contains no apparent data at all, cannot continue check/repair.")
|
||||
return False
|
||||
self.key = self.identify_key(repository)
|
||||
self.key = self.make_key(repository)
|
||||
if verify_data:
|
||||
self.verify_data()
|
||||
if Manifest.MANIFEST_ID not in self.chunks:
|
||||
|
@ -1670,14 +1670,24 @@ def init_chunks(self):
|
|||
for id_ in result:
|
||||
self.chunks[id_] = init_entry
|
||||
|
||||
def identify_key(self, repository):
|
||||
try:
|
||||
some_chunkid, _ = next(self.chunks.iteritems())
|
||||
except StopIteration:
|
||||
# repo is completely empty, no chunks
|
||||
return None
|
||||
cdata = repository.get(some_chunkid)
|
||||
return key_factory(repository, cdata)
|
||||
def make_key(self, repository):
|
||||
attempt = 0
|
||||
for chunkid, _ in self.chunks.iteritems():
|
||||
attempt += 1
|
||||
if attempt > 999:
|
||||
# we did a lot of attempts, but could not create the key via key_factory, give up.
|
||||
break
|
||||
cdata = repository.get(chunkid)
|
||||
try:
|
||||
return key_factory(repository, cdata)
|
||||
except UnsupportedPayloadError:
|
||||
# we get here, if the cdata we got has a corrupted key type byte
|
||||
pass # ignore it, just try the next chunk
|
||||
if attempt == 0:
|
||||
msg = "make_key: repository has no chunks at all!"
|
||||
else:
|
||||
msg = "make_key: failed to create the key (tried %d chunks)" % attempt
|
||||
raise IntegrityError(msg)
|
||||
|
||||
def verify_data(self):
|
||||
logger.info("Starting cryptographic data integrity verification...")
|
||||
|
|
Loading…
Reference in a new issue