[SCM] Samba Shared Repository - branch master updated
Andrew Bartlett
abartlet at samba.org
Tue Oct 4 03:49:01 UTC 2022
The branch, master has been updated
via 37406b9d97f CVE-2007-4559 python: ensure sanity in our tarfiles
via 6a5d03e2f7b samba-tool: Use authentication file to pass credentials
via bff2bc9c7d6 python-drs: Add client-side debug and fallback for GET_ANC
via 483c48f52d6 s4-libnet: Add messages to object count mismatch failures
via b0bbc94d412 selftest: Enable "old Samba" mode regarding GET_ANC/GET_TGT
via 314bc44fa9b s4-rpc_server:getncchanges Add "old Samba" mode regarding GET_ANC/GET_TGT
via 7ff743d65dc selftest: Add tests for GetNCChanges GET_ANC using samba-tool drs clone-dc-database
via 62b426243f4 selftest: Prepare for "old Samba" mode regarding getncchanges GET_ANC/GET_TGT
from a91fa70ad56 tevent: Fix flag clearing
https://git.samba.org/?p=samba.git;a=shortlog;h=master
- Log -----------------------------------------------------------------
commit 37406b9d97f123576c811b9fe22b39b02af62f83
Author: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Date: Fri Sep 23 12:32:25 2022 +1200
CVE-2007-4559 python: ensure sanity in our tarfiles
Python's tarfile module is not very careful about paths that step out
of the target directory. We can be a bit better at little cost.
This was reported in 2007[1], and has recently been publicised [2, for
example].
We were informed of this bug in December 2021 by Luis Alberto López
Alvar, but decided then that there were no circumstances under which
this was a security concern. That is, if you can alter the backup
files, you can already do worse things. But there is a case to guard
against an administrator being tricked into trying to restore a file
that isn't based on a real backup.
[1] https://nvd.nist.gov/vuln/detail/CVE-2007-4559
[2] https://www.theregister.com/2022/09/22/python_vulnerability_tarfile/
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15185
Signed-off-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Reviewed-by: Andrew Bartlett <abartlet at samba.org>
Autobuild-User(master): Andrew Bartlett <abartlet at samba.org>
Autobuild-Date(master): Tue Oct 4 03:48:43 UTC 2022 on sn-devel-184
commit 6a5d03e2f7bfa84eea1f1c44604ab70b1257d349
Author: Nikola Radovanovic <nikoladsp at gmail.com>
Date: Fri Sep 30 09:38:12 2022 +0200
samba-tool: Use authentication file to pass credentials
In order not to pass credentials in clear-text directly over command line, this is a patch to store username/password/domain in a file and use it during domain join for example.
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15031
Signed-off-by: Nikola Radovanovic <radovanovic.extern at univention.de>
Reviewed-by: Andrew Bartlett <abartlet at samba.org>
Reviewed-by: Joseph Sutton <josephsutton at catalyst.net.nz>
commit bff2bc9c7d69ec2fbe9339c2353a0a846182f1ea
Author: Andrew Bartlett <abartlet at samba.org>
Date: Thu Sep 15 17:10:24 2022 +1200
python-drs: Add client-side debug and fallback for GET_ANC
Samba 4.5 and earlier will fail to do GET_ANC correctly and will not
replicate non-critical parents of objects with isCriticalSystemObject=TRUE
when DRSUAPI_DRS_CRITICAL_ONLY is set.
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15189
Signed-off-by: Andrew Bartlett <abartlet at samba.org>
Reviewed-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
commit 483c48f52d6ff5e8149ed12bfeb2b6608c946f01
Author: Andrew Bartlett <abartlet at samba.org>
Date: Tue Sep 20 13:37:30 2022 +1200
s4-libnet: Add messages to object count mismatch failures
This helps explain these better than WERR_GEN_FAILURE.
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15189
Signed-off-by: Andrew Bartlett <abartlet at samba.org>
Reviewed-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
commit b0bbc94d4124d63b1d5a35ccbc88ffd51d520ba0
Author: Andrew Bartlett <abartlet at samba.org>
Date: Thu Sep 29 14:54:14 2022 +1300
selftest: Enable "old Samba" mode regarding GET_ANC/GET_TGT
The chgdcpass server now emulates older verions of Samba that
fail to implement DRSUAPI_DRS_GET_ANC correctly and totally fails to support
DRSUAPI_DRS_GET_TGT.
We now show this is in effect by the fact that tests now fail.
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15189
Signed-off-by: Andrew Bartlett <abartlet at samba.org>
Reviewed-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
commit 314bc44fa9b8fc99c80bfcfff71f2cec67bbda36
Author: Andrew Bartlett <abartlet at samba.org>
Date: Thu Sep 29 14:53:38 2022 +1300
s4-rpc_server:getncchanges Add "old Samba" mode regarding GET_ANC/GET_TGT
This emulates older verions of Samba that fail to implement
DRSUAPI_DRS_GET_ANC correctly and totally fails to support
DRSUAPI_DRS_GET_TGT.
This will allow testing of a client-side fallback, allowing migration
from sites that run very old Samba versions over DRSUAPI (currently
the only option is to attempt an in-place upgrade).
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15189
Signed-off-by: Andrew Bartlett <abartlet at samba.org>
Reviewed-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
commit 7ff743d65dcf27ffe0c6861720e8ce531bfa378d
Author: Andrew Bartlett <abartlet at samba.org>
Date: Thu Sep 29 03:05:03 2022 +0000
selftest: Add tests for GetNCChanges GET_ANC using samba-tool drs clone-dc-database
This test, compared with the direct to RPC tests, will succeed, then fail once the
server is changed to emulate Samba 4.5 and and again succeed once the python code
changes to allow skipping the DRSUAPI_DRS_CRITICAL_ONLY step
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15189
Signed-off-by: Andrew Bartlett <abartlet at samba.org>
Reviewed-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
commit 62b426243f4eaa4978c249b6e6ce90d35aeaefe4
Author: Andrew Bartlett <abartlet at samba.org>
Date: Thu Sep 15 09:36:45 2022 +1200
selftest: Prepare for "old Samba" mode regarding getncchanges GET_ANC/GET_TGT
The chgdcpass environment will emulate older verions of Samba
that fail to implement DRSUAPI_DRS_GET_ANC correctly and
totally fails to support DRSUAPI_DRS_GET_TGT.
This will allow testing of a client-side fallback, allowing migration
from sites that run very old Samba versions over DRSUAPI (currently
the only option is to attempt an in-place upgrade).
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15189
Signed-off-by: Andrew Bartlett <abartlet at samba.org>
Reviewed-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
-----------------------------------------------------------------------
Summary of changes:
docs-xml/manpages/samba-tool.8.xml | 2 +
python/samba/drs_utils.py | 47 +++++++++-
python/samba/getopt.py | 10 +++
python/samba/join.py | 54 ++++++++++--
python/samba/netcmd/domain_backup.py | 2 +-
python/samba/ntacls.py | 3 +-
python/samba/safe_tarfile.py | 43 ++++++++++
python/samba/tests/cred_opt.py | 99 ++++++++++++++++++++++
python/samba/tests/domain_backup.py | 2 +-
python/samba/tests/domain_backup_offline.py | 3 +-
python/samba/tests/safe_tarfile.py | 67 +++++++++++++++
selftest/knownfail.d/samba-4.5-emulation | 4 +
selftest/target/Samba4.pm | 12 +++
selftest/tests.py | 1 +
source4/dsdb/repl/replicated_objects.c | 11 +++
source4/rpc_server/drsuapi/getncchanges.c | 52 ++++++++++--
source4/selftest/tests.py | 23 +++--
.../torture/drs/python/samba_tool_drs_critical.py | 98 +++++++++++++++++++++
18 files changed, 505 insertions(+), 28 deletions(-)
create mode 100644 python/samba/safe_tarfile.py
create mode 100644 python/samba/tests/safe_tarfile.py
create mode 100644 selftest/knownfail.d/samba-4.5-emulation
create mode 100644 source4/torture/drs/python/samba_tool_drs_critical.py
Changeset truncated at 500 lines:
diff --git a/docs-xml/manpages/samba-tool.8.xml b/docs-xml/manpages/samba-tool.8.xml
index 60f3a5f06ed..965b9d6357c 100644
--- a/docs-xml/manpages/samba-tool.8.xml
+++ b/docs-xml/manpages/samba-tool.8.xml
@@ -62,6 +62,8 @@
&cmdline.common.credentials.usekrb5ccache;
+ &cmdline.common.credentials.authenticationfile;
+
<varlistentry>
<term>--ipaddress=IPADDRESS</term>
<listitem><para>
diff --git a/python/samba/drs_utils.py b/python/samba/drs_utils.py
index a71da6eedd3..6399e5f7fbc 100644
--- a/python/samba/drs_utils.py
+++ b/python/samba/drs_utils.py
@@ -204,6 +204,44 @@ class drs_Replicate(object):
supports_ext & DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V10 and
(req.more_flags & drsuapi.DRSUAPI_DRS_GET_TGT) == 0)
+ @staticmethod
+ def _should_calculate_missing_anc_locally(error_code, req):
+ # If the error indicates we fail to resolve the parent object
+ # for a new object, then we assume we are replicating from a
+ # buggy server (Samba 4.5 and earlier) that doesn't really
+ # understand how to implement GET_ANC
+
+ return ((error_code == werror.WERR_DS_DRA_MISSING_PARENT) and
+ (req.replica_flags & drsuapi.DRSUAPI_DRS_GET_ANC) != 0)
+
+
+ def _calculate_missing_anc_locally(self, ctr):
+ self.guids_seen = set()
+
+ # walk objects in ctr, add to guid_seen as we see them
+ # note if an object doesn't have a parent
+
+ object_to_check = ctr.first_object
+
+ while True:
+ if object_to_check is None:
+ break
+
+ self.guids_seen.add(str(object_to_check.object.identifier.guid))
+
+ if object_to_check.parent_object_guid is not None \
+ and object_to_check.parent_object_guid \
+ != misc.GUID("00000000-0000-0000-0000-000000000000") \
+ and str(object_to_check.parent_object_guid) not in self.guids_seen:
+ obj_dn = ldb.Dn(self.samdb, object_to_check.object.identifier.dn)
+ parent_dn = obj_dn.parent()
+ print(f"Object {parent_dn} with "
+ f"GUID {object_to_check.parent_object_guid} "
+ "was not sent by the server in this chunk")
+
+ object_to_check = object_to_check.next_object
+
+
def process_chunk(self, level, ctr, schema, req_level, req, first_chunk):
'''Processes a single chunk of received replication data'''
# pass the replication into the py_net.c python bindings for processing
@@ -326,8 +364,13 @@ class drs_Replicate(object):
# of causing the DC to restart the replication from scratch)
first_chunk = True
continue
- else:
- raise e
+
+ if self._should_calculate_missing_anc_locally(e.args[0],
+ req):
+ print("Missing parent object - calculating missing objects locally")
+
+ self._calculate_missing_anc_locally(ctr)
+ raise e
first_chunk = False
num_objects += ctr.object_count
diff --git a/python/samba/getopt.py b/python/samba/getopt.py
index 9e35273381f..ff8aead3f8d 100644
--- a/python/samba/getopt.py
+++ b/python/samba/getopt.py
@@ -192,6 +192,10 @@ class CredentialsOptions(optparse.OptionGroup):
action="callback", type=str,
help="Kerberos Credentials cache",
callback=self._set_krb5_ccache)
+ self._add_option("-A", "--authentication-file", metavar="AUTHFILE",
+ action="callback", type=str,
+ help="Authentication file",
+ callback=self._set_auth_file)
# LEGACY
self._add_option("-k", "--kerberos", metavar="KERBEROS",
@@ -293,6 +297,12 @@ class CredentialsOptions(optparse.OptionGroup):
self.creds.set_kerberos_state(MUST_USE_KERBEROS)
self.creds.set_named_ccache(arg)
+ def _set_auth_file(self, option, opt_str, arg, parser):
+ if os.path.exists(arg):
+ self.creds.parse_file(arg)
+ self.ask_for_password = False
+ self.machine_pass = False
+
def get_credentials(self, lp, fallback_machine=False):
"""Obtain the credentials set on the command-line.
diff --git a/python/samba/join.py b/python/samba/join.py
index 97561323f21..650bb5a08ae 100644
--- a/python/samba/join.py
+++ b/python/samba/join.py
@@ -968,17 +968,53 @@ class DCJoinContext(object):
destination_dsa_guid, rodc=ctx.RODC,
replica_flags=ctx.replica_flags)
if not ctx.subdomain:
- # Replicate first the critical object for the basedn
- if not ctx.domain_replica_flags & drsuapi.DRSUAPI_DRS_CRITICAL_ONLY:
- print("Replicating critical objects from the base DN of the domain")
- ctx.domain_replica_flags |= drsuapi.DRSUAPI_DRS_CRITICAL_ONLY
+ # Replicate first the critical objects for the basedn
+
+ # We do this to match Windows. The default case is to
+ # do a critical objects replication, then a second
+ # with all objects.
+
+ print("Replicating critical objects from the base DN of the domain")
+ try:
repl.replicate(ctx.base_dn, source_dsa_invocation_id,
destination_dsa_guid, rodc=ctx.RODC,
- replica_flags=ctx.domain_replica_flags)
- ctx.domain_replica_flags ^= drsuapi.DRSUAPI_DRS_CRITICAL_ONLY
- repl.replicate(ctx.base_dn, source_dsa_invocation_id,
- destination_dsa_guid, rodc=ctx.RODC,
- replica_flags=ctx.domain_replica_flags)
+ replica_flags=ctx.domain_replica_flags | drsuapi.DRSUAPI_DRS_CRITICAL_ONLY)
+ except WERRORError as e:
+
+ if e.args[0] == werror.WERR_DS_DRA_MISSING_PARENT:
+ ctx.logger.warning("First pass of replication with "
+ "DRSUAPI_DRS_CRITICAL_ONLY "
+ "not possible due to a missing parent object. "
+ "This is typical of a Samba "
+ "4.5 or earlier server. "
+ "We will replicate the all objects instead.")
+ else:
+ raise
+
+ # Now replicate all the objects in the domain (unless
+ # we were run with --critical-only).
+ #
+ # Doing the replication of users as a second pass
+ # matches more closely the Windows behaviour, which is
+ # actually to do this on first startup.
+ #
+ # Use --critical-only if you want that (but you don't
+ # really, it is better to see any errors here).
+ if not ctx.domain_replica_flags & drsuapi.DRSUAPI_DRS_CRITICAL_ONLY:
+ try:
+ repl.replicate(ctx.base_dn, source_dsa_invocation_id,
+ destination_dsa_guid, rodc=ctx.RODC,
+ replica_flags=ctx.domain_replica_flags)
+ except WERRORError as e:
+
+ if e.args[0] == werror.WERR_DS_DRA_MISSING_PARENT and \
+ ctx.domain_replica_flags & drsuapi.DRSUAPI_DRS_CRITICAL_ONLY:
+ ctx.logger.warning("Replication with DRSUAPI_DRS_CRITICAL_ONLY "
+ "failed due to a missing parent object. "
+ "This may be a Samba 4.5 or earlier server "
+ "and is not compatible with --critical-only")
+ raise
+
print("Done with always replicated NC (base, config, schema)")
# At this point we should already have an entry in the ForestDNS
diff --git a/python/samba/netcmd/domain_backup.py b/python/samba/netcmd/domain_backup.py
index 9c2c9e421f8..9eaba7dea1d 100644
--- a/python/samba/netcmd/domain_backup.py
+++ b/python/samba/netcmd/domain_backup.py
@@ -18,7 +18,6 @@
import datetime
import os
import sys
-import tarfile
import logging
import shutil
import tempfile
@@ -56,6 +55,7 @@ from samba import sites
from samba.dsdb import _dsdb_load_udv_v2
from samba.ndr import ndr_pack
from samba.credentials import SMB_SIGNING_REQUIRED
+from samba import safe_tarfile as tarfile
# work out a SID (based on a free RID) to use when the domain gets restored.
diff --git a/python/samba/ntacls.py b/python/samba/ntacls.py
index f35be48c30b..d2fe6ed911e 100644
--- a/python/samba/ntacls.py
+++ b/python/samba/ntacls.py
@@ -19,7 +19,6 @@
import os
-import tarfile
import tempfile
import shutil
@@ -34,6 +33,8 @@ from samba.samba3 import libsmb_samba_internal as libsmb
from samba.logger import get_samba_logger
from samba import NTSTATUSError
from samba.auth_util import system_session_unix
+from samba import safe_tarfile as tarfile
+
# don't include volumes
SMB_FILE_ATTRIBUTE_FLAGS = libsmb.FILE_ATTRIBUTE_SYSTEM | \
diff --git a/python/samba/safe_tarfile.py b/python/samba/safe_tarfile.py
new file mode 100644
index 00000000000..cc19770d73f
--- /dev/null
+++ b/python/samba/safe_tarfile.py
@@ -0,0 +1,43 @@
+# Unix SMB/CIFS implementation.
+# Copyright (C) Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+
+from tarfile import ExtractError, TarInfo, TarFile as UnsafeTarFile
+
+
+class TarFile(UnsafeTarFile):
+ """This TarFile implementation is trying to ameliorate CVE-2007-4559,
+ where tarfile.TarFiles can step outside of the target directory
+ using '../../'.
+ """
+
+ def extract(self, member, path="", set_attrs=True, *, numeric_owner=False):
+ if isinstance(member, TarInfo):
+ name = member.name
+ else:
+ name = member
+
+ if '../' in name:
+ raise ExtractError(f"'../' is not allowed in path '{name}'")
+
+ if name.startswith('/'):
+ raise ExtractError(f"path '{name}' should not start with '/'")
+
+ super().extract(member, path, set_attrs=set_attrs,
+ numeric_owner=numeric_owner)
+
+
+open = TarFile.open
diff --git a/python/samba/tests/cred_opt.py b/python/samba/tests/cred_opt.py
index 91ca68085b7..82c6434d9c8 100644
--- a/python/samba/tests/cred_opt.py
+++ b/python/samba/tests/cred_opt.py
@@ -20,6 +20,8 @@
"""
import optparse
+import os
+from contextlib import contextmanager
from samba.getopt import CredentialsOptions
import samba.tests
import setproctitle
@@ -28,6 +30,19 @@ import sys
password_opt = '--password=super_secret_password'
clear_password_opt = '--password=xxx'
+ at contextmanager
+def auth_fle_opt(auth_file_path, long_opt=True):
+ old_argv = list(sys.argv)
+ try:
+ if long_opt:
+ sys.argv.append('--authentication-file=%s' % auth_file_path)
+ else:
+ sys.argv.append('-A')
+ sys.argv.append(auth_file_path)
+ yield
+ finally:
+ sys.argv = old_argv
+
class CredentialsOptionsTests(samba.tests.TestCase):
def setUp(self):
@@ -48,3 +63,87 @@ class CredentialsOptionsTests(samba.tests.TestCase):
super(samba.tests.TestCase, self).tearDown()
setproctitle.setproctitle(self.old_proctitle)
sys.argv.pop()
+
+class AuthenticationFileTests(samba.tests.TestCaseInTempDir):
+
+ def setUp(self):
+ super(AuthenticationFileTests, self).setUp()
+
+ self.parser = optparse.OptionParser()
+ self.credopts = CredentialsOptions(self.parser)
+ self.parser.add_option_group(self.credopts)
+
+ self.auth_file_name = os.path.join(self.tempdir, 'auth.txt')
+
+ self.realm = 'realm.example.com'
+ self.domain = 'dom'
+ self.password = 'pass'
+ self.username = 'user'
+
+ auth_file_fd = open(self.auth_file_name, 'x')
+ auth_file_fd.write('realm=%s\n' % self.realm)
+ auth_file_fd.write('domain=%s\n' % self.domain)
+ auth_file_fd.write('username=%s\n' % self.username)
+ auth_file_fd.write('password=%s\n' % self.password)
+ auth_file_fd.close()
+
+ def tearDown(self):
+ super(AuthenticationFileTests, self).tearDown()
+
+ os.unlink(self.auth_file_name)
+
+ def test_long_option_valid_path(self):
+ with auth_fle_opt(self.auth_file_name):
+ self.parser.parse_args()
+ credopts = self.credopts
+ creds = credopts.creds
+
+ self.assertFalse(credopts.ask_for_password)
+ self.assertFalse(credopts.machine_pass)
+
+ self.assertEqual(self.username, creds.get_username())
+ self.assertEqual(self.password, creds.get_password())
+ self.assertEqual(self.domain.upper(), creds.get_domain())
+ self.assertEqual(self.realm.upper(), creds.get_realm())
+
+ def test_long_option_invalid_path(self):
+ with auth_fle_opt(self.auth_file_name + '.dontexist'):
+ self.parser.parse_args()
+ credopts = self.credopts
+ creds = credopts.creds
+
+ self.assertTrue(credopts.ask_for_password)
+ self.assertFalse(credopts.machine_pass)
+
+ self.assertIsNone(creds.get_username())
+ self.assertIsNone(creds.get_password())
+ self.assertIsNone(creds.get_domain())
+ self.assertIsNone(creds.get_realm())
+
+ def test_short_option_valid_path(self):
+ with auth_fle_opt(self.auth_file_name, long_opt=False):
+ self.parser.parse_args()
+ credopts = self.credopts
+ creds = credopts.creds
+
+ self.assertFalse(credopts.ask_for_password)
+ self.assertFalse(credopts.machine_pass)
+
+ self.assertEqual(self.username, creds.get_username())
+ self.assertEqual(self.password, creds.get_password())
+ self.assertEqual(self.domain.upper(), creds.get_domain())
+ self.assertEqual(self.realm.upper(), creds.get_realm())
+
+ def test_short_option_invalid_path(self):
+ with auth_fle_opt(self.auth_file_name + '.dontexist', long_opt=False):
+ self.parser.parse_args()
+ credopts = self.credopts
+ creds = credopts.creds
+
+ self.assertTrue(credopts.ask_for_password)
+ self.assertFalse(credopts.machine_pass)
+
+ self.assertIsNone(creds.get_username())
+ self.assertIsNone(creds.get_password())
+ self.assertIsNone(creds.get_domain())
+ self.assertIsNone(creds.get_realm())
diff --git a/python/samba/tests/domain_backup.py b/python/samba/tests/domain_backup.py
index 2a5df739d2c..b890a1030b7 100644
--- a/python/samba/tests/domain_backup.py
+++ b/python/samba/tests/domain_backup.py
@@ -15,7 +15,6 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
from samba import provision, param
-import tarfile
import os
import shutil
from samba.tests import (env_loadparm, create_test_ou, BlackboxProcessError,
@@ -28,6 +27,7 @@ from samba.netcmd.fsmo import get_fsmo_roleowner
import re
from samba import sites
from samba.dsdb import _dsdb_load_udv_v2
+from samba import safe_tarfile as tarfile
def get_prim_dom(secrets_path, lp):
diff --git a/python/samba/tests/domain_backup_offline.py b/python/samba/tests/domain_backup_offline.py
index ad371680779..b764fcd049b 100644
--- a/python/samba/tests/domain_backup_offline.py
+++ b/python/samba/tests/domain_backup_offline.py
@@ -15,7 +15,6 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
-import tarfile
import os
import shutil
import tempfile
@@ -25,6 +24,8 @@ from samba.param import LoadParm
from samba.join import join_DC
from samba.credentials import Credentials
from samba.logger import get_samba_logger
+from samba import safe_tarfile as tarfile
+
# The backup tests require that a completely clean LoadParm object gets used
# for the restore. Otherwise the same global LP gets re-used, and the LP
diff --git a/python/samba/tests/safe_tarfile.py b/python/samba/tests/safe_tarfile.py
new file mode 100644
index 00000000000..40aa9e17d4a
--- /dev/null
+++ b/python/samba/tests/safe_tarfile.py
@@ -0,0 +1,67 @@
+# Unix SMB/CIFS implementation.
+# Copyright (C) Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+import tarfile
+from samba import safe_tarfile
+import tempfile
+
+import os
+from samba.tests import TestCaseInTempDir
+
+
+def filterer(prefix):
+ def f(info):
+ info.name = prefix + info.name
+ return info
+ return f
+
+
+class SafeTarFileTestCase(TestCaseInTempDir):
+
+ def test_dots(self):
+ filename = os.path.join(self.tempdir, 'x')
+ tarname = os.path.join(self.tempdir, 'tar.tar')
+ f = open(filename, 'w')
+ f.write('x')
+ f.close()
+
+ tf = tarfile.open(tarname, 'w')
+ tf.add(filename, filter=filterer('../../'))
+ tf.close()
+
+ stf = safe_tarfile.open(tarname)
+
+ self.assertRaises(tarfile.ExtractError,
+ stf.extractall,
+ tarname)
+ self.rm_files('x', 'tar.tar')
+
+ def test_slash(self):
+ filename = os.path.join(self.tempdir, 'x')
+ tarname = os.path.join(self.tempdir, 'tar.tar')
+ f = open(filename, 'w')
+ f.write('x')
+ f.close()
+
+ tf = tarfile.open(tarname, 'w')
+ tf.add(filename, filter=filterer('/'))
+ tf.close()
+
+ stf = safe_tarfile.open(tarname)
+ self.assertRaises(tarfile.ExtractError,
+ stf.extractall,
+ tarname)
+
+ self.rm_files('x', 'tar.tar')
diff --git a/selftest/knownfail.d/samba-4.5-emulation b/selftest/knownfail.d/samba-4.5-emulation
new file mode 100644
--
Samba Shared Repository
More information about the samba-cvs
mailing list