Browse Source

Merge pull request #7583 from ThomasWaldmann/security-dir-in-data

put security infos into data dir, fixes #5760
TW 2 years ago
parent
commit
7a13a98f04

+ 16 - 7
docs/faq.rst

@@ -410,13 +410,6 @@ How important is the $HOME/.config/borg directory?
 
 The Borg config directory has content that you should take care of:
 
-``security`` subdirectory
-  Each directory here represents one Borg repository by its ID and contains the last known status.
-  If a repository's status is different from this information at the beginning of BorgBackup
-  operation, Borg outputs warning messages and asks for confirmation, so make sure you do not lose
-  or manipulate these files. However, apart from those warnings, a loss of these files can be
-  recovered.
-
 ``keys`` subdirectory
   All your borg keyfile keys are stored in this directory. Please note that
   borg repokey keys are stored inside the repository. You MUST make sure to have an
@@ -426,6 +419,22 @@ The Borg config directory has content that you should take care of:
 
 Make sure that only you have access to the Borg config directory.
 
+.. _home_data_borg:
+
+How important is the $HOME/.local/share/borg directory?
+-------------------------------------------------------
+
+The Borg data directory has content that you should take care of:
+
+``security`` subdirectory
+  Each directory here represents one Borg repository by its ID and contains the last known status.
+  If a repository's status is different from this information at the beginning of BorgBackup
+  operation, Borg outputs warning messages and asks for confirmation, so make sure you do not lose
+  or manipulate these files. However, apart from those warnings, a loss of these files can be
+  recovered.
+
+Make sure that only you have access to the Borg data directory.
+
 .. _cache_security:
 
 Do I need to take security precautions regarding the cache?

+ 7 - 3
docs/usage/general/environment.rst.inc

@@ -145,10 +145,14 @@ Directories and files:
         `XDG env var`_ ``XDG_CONFIG_HOME`` is set, then ``$XDG_CONFIG_HOME/borg`` is being used instead.
         This directory contains all borg configuration directories, see the FAQ
         for a security advisory about the data in this directory: :ref:`home_config_borg`
+    BORG_DATA_DIR
+        Defaults to ``$BORG_BASE_DIR/.local/share/borg``. If ``BORG_BASE_DIR`` is not explicitly set while
+        `XDG env var`_ ``XDG_DATA_HOME`` is set, then ``$XDG_DATA_HOME/borg`` is being used instead.
+        This directory contains all borg data directories, see the FAQ
+        for a security advisory about the data in this directory: :ref:`home_data_borg`
     BORG_SECURITY_DIR
-        Defaults to ``$BORG_CONFIG_DIR/security``.
-        This directory contains information borg uses to track its usage of NONCES ("numbers used
-        once" - usually in encryption context) and other security relevant data.
+        Defaults to ``$BORG_DATA_DIR/security``.
+        This directory contains security relevant data.
     BORG_KEYS_DIR
         Defaults to ``$BORG_CONFIG_DIR/keys``.
         This directory contains keys for encrypted repositories.

+ 2 - 2
src/borg/cache.py

@@ -62,7 +62,7 @@ class SecurityManager:
 
     def __init__(self, repository):
         self.repository = repository
-        self.dir = get_security_dir(repository.id_str)
+        self.dir = get_security_dir(repository.id_str, legacy=(repository.version == 1))
         self.cache_dir = cache_dir(repository)
         self.key_type_file = os.path.join(self.dir, "key-type")
         self.location_file = os.path.join(self.dir, "location")
@@ -71,7 +71,7 @@ class SecurityManager:
     @staticmethod
     def destroy(repository, path=None):
         """destroy the security dir for ``repository`` or at ``path``"""
-        path = path or get_security_dir(repository.id_str)
+        path = path or get_security_dir(repository.id_str, legacy=(repository.version == 1))
         if os.path.exists(path):
             shutil.rmtree(path)
 

+ 1 - 1
src/borg/crypto/key.py

@@ -114,7 +114,7 @@ def key_factory(repository, manifest_chunk, *, ro_cls=RepoObj):
 
 
 def tam_required_file(repository):
-    security_dir = get_security_dir(bin_to_hex(repository.id))
+    security_dir = get_security_dir(bin_to_hex(repository.id), legacy=(repository.version == 1))
     return os.path.join(security_dir, "tam_required")
 
 

+ 14 - 1
src/borg/helpers/fs.py

@@ -85,14 +85,27 @@ def get_security_dir(repository_id=None, *, legacy=False):
     """Determine where to store local security information."""
     security_dir = os.environ.get("BORG_SECURITY_DIR")
     if security_dir is None:
+        get_dir = get_config_dir if legacy else get_data_dir
         # note: do not just give this as default to the environment.get(), see issue #5979.
-        security_dir = os.path.join(get_config_dir(legacy=legacy), "security")
+        security_dir = os.path.join(get_dir(legacy=legacy), "security")
     if repository_id:
         security_dir = os.path.join(security_dir, repository_id)
     ensure_dir(security_dir)
     return security_dir
 
 
+def get_data_dir(*, legacy=False):
+    """Determine where to store borg changing data on the client"""
+    assert legacy is False, "there is no legacy variant of the borg data dir"
+    data_dir = os.environ.get(
+        "BORG_DATA_DIR", join_base_dir(".local", "share", "borg", legacy=legacy) or platformdirs.user_data_dir("borg")
+    )
+
+    # Create path if it doesn't exist yet
+    ensure_dir(data_dir)
+    return data_dir
+
+
 def get_cache_dir(*, legacy=False):
     """Determine where to repository keys and cache"""
 

+ 6 - 4
src/borg/testsuite/helpers.py

@@ -740,11 +740,13 @@ def test_get_security_dir(monkeypatch):
         monkeypatch.setenv("BORG_SECURITY_DIR", "/var/tmp")
         assert get_security_dir() == "/var/tmp"
     else:
-        monkeypatch.delenv("XDG_CONFIG_HOME", raising=False)
+        monkeypatch.delenv("XDG_DATA_HOME", raising=False)
         monkeypatch.delenv("BORG_SECURITY_DIR", raising=False)
-        assert get_security_dir() == os.path.join(home_dir, ".config", "borg", "security")
-        assert get_security_dir(repository_id="1234") == os.path.join(home_dir, ".config", "borg", "security", "1234")
-        monkeypatch.setenv("XDG_CONFIG_HOME", "/var/tmp/.config")
+        assert get_security_dir() == os.path.join(home_dir, ".local", "share", "borg", "security")
+        assert get_security_dir(repository_id="1234") == os.path.join(
+            home_dir, ".local", "share", "borg", "security", "1234"
+        )
+        monkeypatch.setenv("XDG_DATA_HOME", "/var/tmp/.config")
         assert get_security_dir() == os.path.join("/var/tmp/.config", "borg", "security")
         monkeypatch.setenv("BORG_SECURITY_DIR", "/var/tmp")
         assert get_security_dir() == "/var/tmp"

+ 1 - 0
src/borg/testsuite/key.py

@@ -115,6 +115,7 @@ class TestKey:
         _location = _Location()
         id = bytes(32)
         id_str = bin_to_hex(id)
+        version = 2
 
         def save_key(self, data):
             self.key_data = data