mirror of
https://github.com/borgbackup/borg.git
synced 2025-02-24 15:12:00 +00:00
always implicitly require archive TAMs
they must be there since the upgrade to borg 1.2.6 (or other borg versions that also have a fix for CVE-2023-36811).
This commit is contained in:
parent
21d4407170
commit
2d78fa89a5
5 changed files with 13 additions and 34 deletions
|
@ -493,7 +493,7 @@ def __init__(
|
|||
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.tam_verified = True
|
||||
self.numeric_ids = numeric_ids
|
||||
self.noatime = noatime
|
||||
self.noctime = noctime
|
||||
|
@ -533,8 +533,7 @@ def __init__(
|
|||
def _load_meta(self, id):
|
||||
cdata = self.repository.get(id)
|
||||
_, data = self.repo_objs.parse(id, cdata)
|
||||
# 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)
|
||||
archive, _ = self.key.unpack_and_verify_archive(data)
|
||||
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")
|
||||
|
@ -1998,7 +1997,7 @@ def valid_archive(obj):
|
|||
# **after** doing the low-level checks and having a strong indication that we
|
||||
# are likely looking at an archive item here, also check the TAM authentication:
|
||||
try:
|
||||
archive, verified, _ = self.key.unpack_and_verify_archive(data, force_tam_not_required=False)
|
||||
archive, _ = self.key.unpack_and_verify_archive(data)
|
||||
except IntegrityError as integrity_error:
|
||||
# TAM issues - do not accept this archive!
|
||||
# either somebody is trying to attack us with a fake archive data or
|
||||
|
@ -2269,7 +2268,7 @@ def valid_item(obj):
|
|||
del self.manifest.archives[info.name]
|
||||
continue
|
||||
try:
|
||||
archive, verified, salt = self.key.unpack_and_verify_archive(data, force_tam_not_required=False)
|
||||
archive, salt = self.key.unpack_and_verify_archive(data)
|
||||
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
|
||||
|
|
|
@ -755,7 +755,7 @@ def fetch_and_build_idx(archive_id, decrypted_repository, chunk_idx):
|
|||
nonlocal processed_item_metadata_chunks
|
||||
csize, data = decrypted_repository.get(archive_id)
|
||||
chunk_idx.add(archive_id, 1, len(data))
|
||||
archive, verified, _ = self.key.unpack_and_verify_archive(data, force_tam_not_required=True)
|
||||
archive, _ = self.key.unpack_and_verify_archive(data)
|
||||
archive = ArchiveItem(internal_dict=archive)
|
||||
if archive.version not in (1, 2): # legacy
|
||||
raise Exception("Unknown archive metadata version")
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
from ..constants import * # NOQA
|
||||
from ..helpers import StableDict
|
||||
from ..helpers import Error, IntegrityError
|
||||
from ..helpers import get_keys_dir, get_security_dir
|
||||
from ..helpers import get_keys_dir
|
||||
from ..helpers import get_limited_unpacker
|
||||
from ..helpers import bin_to_hex
|
||||
from ..helpers.passphrase import Passphrase, PasswordRetriesExceeded, PassphraseWrong
|
||||
|
@ -276,37 +276,21 @@ def unpack_and_verify_manifest(self, data):
|
|||
logger.debug("TAM-verified manifest")
|
||||
return unpacked
|
||||
|
||||
def unpack_and_verify_archive(self, data, force_tam_not_required=False):
|
||||
"""Unpack msgpacked *data* and return (object, did_verify)."""
|
||||
tam_required = self.tam_required
|
||||
if force_tam_not_required and tam_required:
|
||||
# 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
|
||||
def unpack_and_verify_archive(self, data):
|
||||
"""Unpack msgpacked *data* and return (object, salt)."""
|
||||
data = bytearray(data)
|
||||
unpacker = get_limited_unpacker("archive")
|
||||
unpacker.feed(data)
|
||||
unpacked = unpacker.unpack()
|
||||
if "tam" not in unpacked:
|
||||
if tam_required:
|
||||
archive_name = unpacked.get("name", "<unknown>")
|
||||
raise ArchiveTAMRequiredError(archive_name)
|
||||
else:
|
||||
logger.debug("Archive TAM not found and not required")
|
||||
return unpacked, False, None
|
||||
archive_name = unpacked.get("name", "<unknown>")
|
||||
raise ArchiveTAMRequiredError(archive_name)
|
||||
tam = unpacked.pop("tam", None)
|
||||
if not isinstance(tam, dict):
|
||||
raise ArchiveTAMInvalid()
|
||||
tam_type = tam.get("type", "<none>")
|
||||
if tam_type != "HKDF_HMAC_SHA512":
|
||||
if tam_required:
|
||||
raise TAMUnsupportedSuiteError(repr(tam_type))
|
||||
else:
|
||||
logger.debug(
|
||||
"Ignoring archive TAM made with unsupported suite, since TAM is not required: %r", tam_type
|
||||
)
|
||||
return unpacked, False, None
|
||||
raise TAMUnsupportedSuiteError(repr(tam_type))
|
||||
tam_hmac = tam.get("hmac")
|
||||
tam_salt = tam.get("salt")
|
||||
if not isinstance(tam_salt, (bytes, str)) or not isinstance(tam_hmac, (bytes, str)):
|
||||
|
@ -320,7 +304,7 @@ def unpack_and_verify_archive(self, data, force_tam_not_required=False):
|
|||
if not hmac.compare_digest(calculated_hmac, tam_hmac):
|
||||
raise ArchiveTAMInvalid()
|
||||
logger.debug("TAM-verified archive")
|
||||
return unpacked, True, tam_salt
|
||||
return unpacked, tam_salt
|
||||
|
||||
|
||||
class PlaintextKey(KeyBase):
|
||||
|
|
|
@ -425,9 +425,6 @@ def test_check_rebuild_refcounts(archiver):
|
|||
repository = Repository(archiver.repository_path, exclusive=True)
|
||||
with repository:
|
||||
write_archive_without_tam(repository, "archive_no_tam")
|
||||
output = cmd(archiver, "rlist", "--format='{name} tam:{tam}{NL}'")
|
||||
assert "archive_tam tam:verified" in output # good
|
||||
assert "archive_no_tam tam:none" in output # could be borg < 1.0.9 archive or fake
|
||||
cmd(archiver, "check", "--repair")
|
||||
output = cmd(archiver, "rlist", "--format='{name} tam:{tam}{NL}'")
|
||||
assert "archive_tam tam:verified" in output # TAM-verified archive still there
|
||||
|
|
|
@ -352,8 +352,7 @@ def test_round_trip_archive(self, key):
|
|||
unpacked = msgpack.unpackb(blob)
|
||||
assert unpacked["tam"]["type"] == "HKDF_HMAC_SHA512"
|
||||
|
||||
unpacked, verified, _ = key.unpack_and_verify_archive(blob)
|
||||
assert verified
|
||||
unpacked, _ = key.unpack_and_verify_archive(blob)
|
||||
assert unpacked["foo"] == "bar"
|
||||
assert "tam" not in unpacked
|
||||
|
||||
|
|
Loading…
Reference in a new issue