check: rebuild_refcounts verify and recreate TAM

This part of the archive checker recreates the Archive
items (always, just in case some missing chunks needed
repairing).

When loading the Archive item, we now verify the TAM.
When saving the (potentially modified) Archive item,
we now (re-)generate the TAM.

Archives without a valid TAM are dropped rather than TAM-authenticated
when saving them. There shouldn't be any archives without a valid TAM:

- borg writes an archive TAM since long (1.0.9)
- users are expected to TAM-authenticate archives created
  by older borg when upgrading.

Also:

Archive.set_meta: TAM-authenticate new archive

This is also used by Archive.rename and .recreate.
This commit is contained in:
Thomas Waldmann 2023-06-16 21:56:06 +02:00
parent d2f653e816
commit 52483b26d0
No known key found for this signature in database
GPG Key ID: 243ACFA951F78E01
1 changed files with 13 additions and 3 deletions

View File

@ -815,7 +815,7 @@ Utilization of max. archive size: {csize_max:.0%}
def set_meta(self, key, value):
metadata = self._load_meta(self.id)
setattr(metadata, key, value)
data = msgpack.packb(metadata.as_dict(), unicode_errors='surrogateescape')
data = self.key.pack_and_authenticate_metadata(metadata.as_dict(), context=b'archive')
new_id = self.key.id_hash(data)
self.cache.add_chunk(new_id, data, self.stats)
self.manifest.archives[self.name] = (new_id, metadata.time)
@ -1683,7 +1683,17 @@ class ArchiveChecker:
self.error_found = True
del self.manifest.archives[info.name]
continue
archive = ArchiveItem(internal_dict=msgpack.unpackb(data))
try:
archive, verified = self.key.unpack_and_verify_archive(data, force_tam_not_required=False)
except IntegrityError as integrity_error:
# looks like there is a TAM issue with this archive, this might be an attack!
# when upgrading to borg 1.2.5, users are expected to TAM-authenticate all archives they
# trust, so there shouldn't be any without TAM.
logger.error('Archive TAM authentication issue for archive %s: %s', info.name, integrity_error)
self.error_found = True
del self.manifest.archives[info.name]
continue
archive = ArchiveItem(internal_dict=archive)
if archive.version != 1:
raise Exception('Unknown archive metadata version')
archive.cmdline = [safe_decode(arg) for arg in archive.cmdline]
@ -1697,7 +1707,7 @@ class ArchiveChecker:
for previous_item_id in archive.items:
mark_as_possibly_superseded(previous_item_id)
archive.items = items_buffer.chunks
data = msgpack.packb(archive.as_dict(), unicode_errors='surrogateescape')
data = self.key.pack_and_authenticate_metadata(archive.as_dict(), context=b'archive')
new_archive_id = self.key.id_hash(data)
cdata = self.key.encrypt(data)
add_reference(new_archive_id, len(data), len(cdata), cdata)