[SCM] Samba Shared Repository - branch v4-18-test updated

Jule Anger janger at samba.org
Mon Jun 19 10:30:02 UTC 2023


The branch, v4-18-test has been updated
       via  a6edfaa4985 python:safe_tarfile: Improve safe extract()
       via  b7cad429a52 python:safe_tarfile: Implement safer extractall()
       via  eff4e88d2cc python:safe_tarfile: Set extraction_filter for pythons providing it
       via  4a79ee44c31 python:tests: Adopt safe_tarfile for extraction_filter raises
       via  d2c86925f62 s3/utils: avoid erronous NO MEMORY detection
      from  c7e3c042fbc smbcacls/smbcquotas: check for valid UNC path

https://git.samba.org/?p=samba.git;a=shortlog;h=v4-18-test


- Log -----------------------------------------------------------------
commit a6edfaa498552dcef704bda0c6fcb7b14c88bdcc
Author: Andreas Schneider <asn at samba.org>
Date:   Tue Jun 6 15:38:12 2023 +0200

    python:safe_tarfile: Improve safe extract()
    
    This also checks for symlinks and hardlinks.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=15390
    
    Signed-off-by: Andreas Schneider <asn at samba.org>
    Reviewed-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    (cherry picked from commit 1f74f9f366d7f107a89220a4a5951bc4daf18025)
    
    Autobuild-User(v4-18-test): Jule Anger <janger at samba.org>
    Autobuild-Date(v4-18-test): Mon Jun 19 10:29:13 UTC 2023 on atb-devel-224

commit b7cad429a52857ac8a1d1685c732f4c746e7c339
Author: Andreas Schneider <asn at samba.org>
Date:   Tue Jun 6 15:30:20 2023 +0200

    python:safe_tarfile: Implement safer extractall()
    
    This also checks for symlinks and hardlinks.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=15390
    
    Signed-off-by: Andreas Schneider <asn at samba.org>
    Reviewed-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    (cherry picked from commit 431f7698e48387413aac586c7a939a1682464681)

commit eff4e88d2cc01d60a8ad03108f0d5691bde0e976
Author: Andreas Schneider <asn at samba.org>
Date:   Tue Jun 6 15:29:06 2023 +0200

    python:safe_tarfile: Set extraction_filter for pythons providing it
    
    It should be available for Python >= 3.11.4 but also has been
    backported.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=15390
    
    Signed-off-by: Andreas Schneider <asn at samba.org>
    Reviewed-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    (cherry picked from commit 8c90c66a9a409d807dad56822540509c9813425b)

commit 4a79ee44c311f1a78de9fc9d2b8bc73fb4987719
Author: Andreas Schneider <asn at samba.org>
Date:   Tue Jun 6 16:06:57 2023 +0200

    python:tests: Adopt safe_tarfile for extraction_filter raises
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=15390
    
    Signed-off-by: Andreas Schneider <asn at samba.org>
    Reviewed-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    (cherry picked from commit ebaa00816259cbae5c45ebf0ba5fb260b09e4695)

commit d2c86925f62012f0fe017a16ce4cef5fd47e17c3
Author: Noel Power <noel.power at suse.com>
Date:   Fri Jun 2 14:27:55 2023 +0100

    s3/utils: avoid erronous NO MEMORY detection
    
    since 5cc3c1b5f6b0289f91c01b20989558badc28fd61 if we don't have
    a realm specified either on cmdline or in conf file we try to
    copy (talloc_strdup) a NULL variable which triggers a NO_MEMORY
    error when we check the result of the copy
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=15384
    
    Signed-off-by: Noel Power <noel.power at suse.com>
    Reviewed-by: Stefan Metzmacher <metze at samba.org>
    
    Autobuild-User(master): Stefan Metzmacher <metze at samba.org>
    Autobuild-Date(master): Sun Jun  4 12:42:16 UTC 2023 on atb-devel-224
    
    (cherry picked from commit 22ab42c1007775abca0b578744d4c18a85cda627)

-----------------------------------------------------------------------

Summary of changes:
 python/samba/safe_tarfile.py       | 73 ++++++++++++++++++++++++++++++++------
 python/samba/tests/safe_tarfile.py | 27 ++++++++++----
 source3/utils/net_ads.c            | 10 +++---
 3 files changed, 89 insertions(+), 21 deletions(-)


Changeset truncated at 500 lines:

diff --git a/python/samba/safe_tarfile.py b/python/samba/safe_tarfile.py
index cc19770d73f..7a2b0382a79 100644
--- a/python/samba/safe_tarfile.py
+++ b/python/samba/safe_tarfile.py
@@ -15,6 +15,9 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 
+import os
+import tarfile
+from pathlib import Path
 from tarfile import ExtractError, TarInfo, TarFile as UnsafeTarFile
 
 
@@ -24,20 +27,68 @@ class TarFile(UnsafeTarFile):
     using '../../'.
     """
 
-    def extract(self, member, path="", set_attrs=True, *, numeric_owner=False):
-        if isinstance(member, TarInfo):
-            name = member.name
-        else:
-            name = member
+    try:
+        # New in version 3.11.4 (also has been backported)
+        # https://docs.python.org/3/library/tarfile.html#tarfile.TarFile.extraction_filter
+        # https://peps.python.org/pep-0706/
+        extraction_filter = staticmethod(tarfile.data_filter)
+    except AttributeError:
+        def extract(self, member, path="", set_attrs=True, *,
+                    numeric_owner=False):
+            self._safetarfile_check()
+            super().extract(member, path, set_attrs=set_attrs,
+                            numeric_owner=numeric_owner)
 
-        if '../' in name:
-            raise ExtractError(f"'../' is not allowed in path '{name}'")
+        def extractall(self, path, members=None, *, numeric_owner=False):
+            self._safetarfile_check()
+            super().extractall(path, members,
+                               numeric_owner=numeric_owner)
 
-        if name.startswith('/'):
-            raise ExtractError(f"path '{name}' should not start with '/'")
+        def _safetarfile_check(self):
+            for tarinfo in self.__iter__():
+                if self._is_traversal_attempt(tarinfo=tarinfo):
+                    raise ExtractError(
+                        "Attempted directory traversal for "
+                        f"member: {tarinfo.name}")
+                if self._is_unsafe_symlink(tarinfo=tarinfo):
+                    raise ExtractError(
+                        "Attempted directory traversal via symlink for "
+                        f"member: {tarinfo.linkname}")
+                if self._is_unsafe_link(tarinfo=tarinfo):
+                    raise ExtractError(
+                        "Attempted directory traversal via link for "
+                        f"member: {tarinfo.linkname}")
 
-        super().extract(member, path, set_attrs=set_attrs,
-                        numeric_owner=numeric_owner)
+        def _resolve_path(self, path):
+            return os.path.realpath(os.path.abspath(path))
+
+        def _is_path_in_dir(self, path, basedir):
+            return self._resolve_path(os.path.join(basedir,
+                                      path)).startswith(basedir)
+
+        def _is_traversal_attempt(self, tarinfo):
+            if (tarinfo.name.startswith(os.sep)
+               or ".." + os.sep in tarinfo.name):
+                return True
+            return False
+
+        def _is_unsafe_symlink(self, tarinfo):
+            if tarinfo.issym():
+                symlink_file = Path(
+                    os.path.normpath(os.path.join(os.getcwd(),
+                                     tarinfo.linkname)))
+                if not self._is_path_in_dir(symlink_file, os.getcwd()):
+                    return True
+            return False
+
+        def _is_unsafe_link(self, tarinfo):
+            if tarinfo.islnk():
+                link_file = Path(
+                    os.path.normpath(os.path.join(os.getcwd(),
+                                                  tarinfo.linkname)))
+                if not self._is_path_in_dir(link_file, os.getcwd()):
+                    return True
+            return False
 
 
 open = TarFile.open
diff --git a/python/samba/tests/safe_tarfile.py b/python/samba/tests/safe_tarfile.py
index 40aa9e17d4a..cf9b725afcb 100644
--- a/python/samba/tests/safe_tarfile.py
+++ b/python/samba/tests/safe_tarfile.py
@@ -43,9 +43,16 @@ class SafeTarFileTestCase(TestCaseInTempDir):
 
         stf = safe_tarfile.open(tarname)
 
-        self.assertRaises(tarfile.ExtractError,
-                          stf.extractall,
-                          tarname)
+        # We we have data_filter, we have a patched python to address
+        # CVE-2007-4559.
+        if hasattr(tarfile, "data_filter"):
+            self.assertRaises(tarfile.OutsideDestinationError,
+                              stf.extractall,
+                              tarname)
+        else:
+            self.assertRaises(tarfile.ExtractError,
+                              stf.extractall,
+                              tarname)
         self.rm_files('x', 'tar.tar')
 
     def test_slash(self):
@@ -60,8 +67,16 @@ class SafeTarFileTestCase(TestCaseInTempDir):
         tf.close()
 
         stf = safe_tarfile.open(tarname)
-        self.assertRaises(tarfile.ExtractError,
-                          stf.extractall,
-                          tarname)
+
+        # We we have data_filter, we have a patched python to address
+        # CVE-2007-4559.
+        if hasattr(tarfile, "data_filter"):
+            self.assertRaises(NotADirectoryError,
+                              stf.extractall,
+                              tarname)
+        else:
+            self.assertRaises(tarfile.ExtractError,
+                              stf.extractall,
+                              tarname)
 
         self.rm_files('x', 'tar.tar')
diff --git a/source3/utils/net_ads.c b/source3/utils/net_ads.c
index 9ec884394eb..ff56d7f76e2 100644
--- a/source3/utils/net_ads.c
+++ b/source3/utils/net_ads.c
@@ -713,10 +713,12 @@ retry:
 	} else if (ads->auth.realm == NULL) {
 		const char *c_realm = cli_credentials_get_realm(c->creds);
 
-		ads->auth.realm = talloc_strdup(ads, c_realm);
-		if (ads->auth.realm == NULL) {
-			TALLOC_FREE(ads);
-			return ADS_ERROR(LDAP_NO_MEMORY);
+		if (c_realm != NULL) {
+			ads->auth.realm = talloc_strdup(ads, c_realm);
+			if (ads->auth.realm == NULL) {
+				TALLOC_FREE(ads);
+				return ADS_ERROR(LDAP_NO_MEMORY);
+			}
 		}
 	}
 


-- 
Samba Shared Repository



More information about the samba-cvs mailing list