diff --git a/src/borg/archive.py b/src/borg/archive.py index 5c5b8d2b6..da9d3661f 100644 --- a/src/borg/archive.py +++ b/src/borg/archive.py @@ -493,6 +493,7 @@ class Archive: self.name = name # overwritten later with name from archive metadata self.name_in_manifest = name # can differ from .name later (if borg check fixed duplicate archive names) self.comment = None + self.tam_verified = False self.numeric_ids = numeric_ids self.noatime = noatime self.noctime = noctime @@ -532,7 +533,9 @@ class Archive: def _load_meta(self, id): cdata = self.repository.get(id) _, data = self.repo_objs.parse(id, cdata) - metadata = ArchiveItem(internal_dict=msgpack.unpackb(data)) + # we do not require TAM for archives, otherwise we can not even borg list a repo with old archives. + archive, self.tam_verified = self.key.unpack_and_verify_archive(data, force_tam_not_required=True) + metadata = ArchiveItem(internal_dict=archive) if metadata.version not in (1, 2): # legacy: still need to read v1 archives raise Exception("Unknown archive metadata version") # note: metadata.items must not get written to disk! diff --git a/src/borg/crypto/key.py b/src/borg/crypto/key.py index aa46b2900..d42549c03 100644 --- a/src/borg/crypto/key.py +++ b/src/borg/crypto/key.py @@ -301,7 +301,9 @@ class KeyBase: """Unpack msgpacked *data* and return (object, did_verify).""" tam_required = self.tam_required if force_tam_not_required and tam_required: - logger.warning("Archive authentication DISABLED.") + # for a long time, borg only checked manifest for "tam_required" and + # people might have archives without TAM, so don't be too annoyingly loud here: + logger.debug("Archive authentication DISABLED.") tam_required = False data = bytearray(data) unpacker = get_limited_unpacker("archive") diff --git a/src/borg/helpers/parseformat.py b/src/borg/helpers/parseformat.py index 7297db376..65d7ac7f3 100644 --- a/src/borg/helpers/parseformat.py +++ b/src/borg/helpers/parseformat.py @@ -723,11 +723,12 @@ class ArchiveFormatter(BaseFormatter): "id": "internal ID of the archive", "hostname": "hostname of host on which this archive was created", "username": "username of user who created this archive", + "tam": "TAM authentication state of this archive", "size": "size of this archive (data plus metadata, not considering compression and deduplication)", "nfiles": "count of files in this archive", } KEY_GROUPS = ( - ("archive", "name", "comment", "id"), + ("archive", "name", "comment", "id", "tam"), ("start", "time", "end", "command_line"), ("hostname", "username"), ("size", "nfiles"), @@ -750,6 +751,7 @@ class ArchiveFormatter(BaseFormatter): "username": partial(self.get_meta, "username", ""), "comment": partial(self.get_meta, "comment", ""), "command_line": partial(self.get_meta, "command_line", ""), + "tam": self.get_tam, "size": partial(self.get_meta, "size", 0), "nfiles": partial(self.get_meta, "nfiles", 0), "end": self.get_ts_end, @@ -795,6 +797,9 @@ class ArchiveFormatter(BaseFormatter): def get_ts_end(self): return self.format_time(self.archive.ts_end) + def get_tam(self): + return "verified" if self.archive.tam_verified else "none" + def format_time(self, ts): return OutputTimestamp(ts)