Package: release.debian.org User: release.debian....@packages.debian.org Usertags: unblock Severity: normal
Please unblock package samba This is an update from 4.13.4 to 4.13.5 (requested in #984863). [ Reason ] This is a stability fixes release. Full list of changes: o Trever L. Adams <trever.ad...@gmail.com> * BUG 14634: s3:modules:vfs_virusfilter: Recent talloc changes cause infinite start-up failure. o Jeremy Allison <j...@samba.org> * BUG 13992: s3: libsmb: Add missing cli_tdis() in error path if encryption setup failed on temp proxy connection. * BUG 14604: smbd: In conn_force_tdis_done() when forcing a connection closed force a full reload of services. o Andrew Bartlett <abart...@samba.org> * BUG 14593: dbcheck: Check Deleted Objects and reduce noise in reports about expired tombstones. o Ralph Boehme <s...@samba.org * BUG 14503: s3: Fix fcntl waf configure check. * BUG 14602: s3/auth: Implement "winbind:ignore domains". * BUG 14617: smbd: Use fsp->conn->session_info for the initial delete-on-close token. o Peter Eriksson <p...@lysator.liu.se> * BUG 14648: s3: VFS: nfs4_acls. Add missing TALLOC_FREE(frame) in error path. o Björn Jacke <b...@sernet.de> * BUG 14624: classicupgrade: Treat old never expires value right. o Volker Lendecke <v...@samba.org> * BUG 14636: g_lock: Fix uninitalized variable reads. o Stefan Metzmacher <me...@samba.org> * BUG 13898: s3:pysmbd: Fix fd leak in py_smbd_create_file(). o Andreas Schneider <a...@samba.org> * BUG 14625: lib:util: Avoid free'ing our own pointer. o Paul Wise <pa...@bonedaddy.net> * BUG 12505: HEIMDAL: krb5_storage_free(NULL) should work. [ Impact ] At least Paul Wise is affected. See: https://bugzilla.samba.org/show_bug.cgi?id=13992 https://bugzilla.samba.org/show_bug.cgi?id=12505 [ Tests ] As is every samba release, the testsuite is improved. I've also tested the package. [ Risks ] [ Checklist ] [ ] all changes are documented in the d/changelog I forgot samba was a key package, so the changelog is not complete. The missing pieces are above. [x] I reviewed all changes and I approve them [x] attach debdiff against the package in testing Attached are releavant changes (removing diff in the doc about the version). [ Other info ] I may ask another unblock request before the bullseye release if samba 4.13.6+ is released. unblock samba/2:4.13.5+dfsg-1
diff --git a/Makefile b/Makefile index 0b7b0ae8866..7f5960d5191 100644 --- a/Makefile +++ b/Makefile @@ -15,6 +15,9 @@ uninstall: test: $(WAF) test $(TEST_OPTIONS) +testonly: + $(WAF) testonly $(TEST_OPTIONS) + perftest: $(WAF) test --perf-test $(TEST_OPTIONS) diff --git a/VERSION b/VERSION index 130087004f0..c24df6ba32e 100644 --- a/VERSION +++ b/VERSION @@ -25,7 +25,7 @@ ######################################################## SAMBA_VERSION_MAJOR=4 SAMBA_VERSION_MINOR=13 -SAMBA_VERSION_RELEASE=4 +SAMBA_VERSION_RELEASE=5 ######################################################## # If a official release has a serious bug # diff --git a/WHATSNEW.txt b/WHATSNEW.txt index 544f4377bfd..8b8c349eaa5 100644 --- a/WHATSNEW.txt +++ b/WHATSNEW.txt @@ -1,3 +1,79 @@ + ============================== + Release Notes for Samba 4.13.5 + March 09, 2021 + ============================== + + +This is the latest stable release of the Samba 4.13 release series. + + +Changes since 4.13.4 +-------------------- + +o Trever L. Adams <trever.ad...@gmail.com> + * BUG 14634: s3:modules:vfs_virusfilter: Recent talloc changes cause infinite + start-up failure. + +o Jeremy Allison <j...@samba.org> + * BUG 13992: s3: libsmb: Add missing cli_tdis() in error path if encryption + setup failed on temp proxy connection. + * BUG 14604: smbd: In conn_force_tdis_done() when forcing a connection closed + force a full reload of services. + +o Andrew Bartlett <abart...@samba.org> + * BUG 14593: dbcheck: Check Deleted Objects and reduce noise in reports about + expired tombstones. + +o Ralph Boehme <s...@samba.org + * BUG 14503: s3: Fix fcntl waf configure check. + * BUG 14602: s3/auth: Implement "winbind:ignore domains". + * BUG 14617: smbd: Use fsp->conn->session_info for the initial + delete-on-close token. + +o Peter Eriksson <p...@lysator.liu.se> + * BUG 14648: s3: VFS: nfs4_acls. Add missing TALLOC_FREE(frame) in error + path. + +o Björn Jacke <b...@sernet.de> + * BUG 14624: classicupgrade: Treat old never expires value right. + +o Volker Lendecke <v...@samba.org> + * BUG 14636: g_lock: Fix uninitalized variable reads. + +o Stefan Metzmacher <me...@samba.org> + * BUG 13898: s3:pysmbd: Fix fd leak in py_smbd_create_file(). + +o Andreas Schneider <a...@samba.org> + * BUG 14625: lib:util: Avoid free'ing our own pointer. + +o Paul Wise <pa...@bonedaddy.net> + * BUG 12505: HEIMDAL: krb5_storage_free(NULL) should work. + + +####################################### +Reporting bugs & Development Discussion +####################################### + +Please discuss this release on the samba-technical mailing list or by +joining the #samba-technical IRC channel on irc.freenode.net. + +If you do report problems then please try to send high quality +feedback. If you don't provide vital information to help us track down +the problem then you will probably be ignored. All bug reports should +be filed under the Samba 4.1 and newer product in the project's Bugzilla +database (https://bugzilla.samba.org/). + + +====================================================================== +== Our Code, Our Bugs, Our Responsibility. +== The Samba Team +====================================================================== + + +Release notes for older releases follow: +---------------------------------------- + + ============================== Release Notes for Samba 4.13.4 January 26, 2021 @@ -65,8 +141,7 @@ database (https://bugzilla.samba.org/). ====================================================================== -Release notes for older releases follow: ----------------------------------------- +---------------------------------------------------------------------- ============================== diff --git a/lib/util/memcache.c b/lib/util/memcache.c index 1e616bd0e9a..7b0b27eaddb 100644 --- a/lib/util/memcache.c +++ b/lib/util/memcache.c @@ -223,14 +223,25 @@ static void memcache_delete_element(struct memcache *cache, TALLOC_FREE(e); } -static void memcache_trim(struct memcache *cache) +static void memcache_trim(struct memcache *cache, struct memcache_element *e) { + struct memcache_element *tail = NULL; + if (cache->max_size == 0) { return; } - while ((cache->size > cache->max_size) && DLIST_TAIL(cache->mru)) { - memcache_delete_element(cache, DLIST_TAIL(cache->mru)); + for (tail = DLIST_TAIL(cache->mru); + (cache->size > cache->max_size) && (tail != NULL); + tail = DLIST_TAIL(cache->mru)) + { + if (tail == e) { + tail = DLIST_PREV(tail); + if (tail == NULL) { + break; + } + } + memcache_delete_element(cache, tail); } } @@ -351,7 +362,7 @@ void memcache_add(struct memcache *cache, enum memcache_number n, memcpy(&mtv, cache_value.data, sizeof(mtv)); cache->size += mtv.len; } - memcache_trim(cache); + memcache_trim(cache, e); } void memcache_add_talloc(struct memcache *cache, enum memcache_number n, diff --git a/lib/util/tests/test_memcache.c b/lib/util/tests/test_memcache.c new file mode 100644 index 00000000000..8a3997817c1 --- /dev/null +++ b/lib/util/tests/test_memcache.c @@ -0,0 +1,161 @@ +/* + * Unix SMB/CIFS implementation. + * + * Copyright (C) 2021 Andreas Schneider <a...@samba.org> + * + * 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/>. + */ + +#include <stdarg.h> +#include <stddef.h> +#include <stdint.h> +#include <setjmp.h> +#include <cmocka.h> + +#include "lib/replace/replace.h" +#include "lib/util/talloc_stack.h" +#include "lib/util/memcache.h" + +static int setup_talloc_context(void **state) +{ + TALLOC_CTX *frame = talloc_stackframe(); + + *state = frame; + return 0; +} + +static int teardown_talloc_context(void **state) +{ + TALLOC_CTX *frame = *state; + TALLOC_FREE(frame); + return 0; +} + +static void torture_memcache_init(void **state) +{ + TALLOC_CTX *mem_ctx = *state; + struct memcache *cache = NULL; + + cache = memcache_init(mem_ctx, 0); + assert_non_null(cache); + + TALLOC_FREE(cache); + + cache = memcache_init(mem_ctx, 10); + assert_non_null(cache); + + TALLOC_FREE(cache); +} + +static void torture_memcache_add_lookup_delete(void **state) +{ + TALLOC_CTX *mem_ctx = *state; + struct memcache *cache = NULL; + DATA_BLOB key1, key2; + char *path1 = NULL, *path2 = NULL; + + cache = memcache_init(mem_ctx, 0); + assert_non_null(cache); + + key1 = data_blob_const("key1", 4); + path1 = talloc_strdup(mem_ctx, "/tmp/one"); + assert_non_null(path1); + + key2 = data_blob_const("key2", 4); + path2 = talloc_strdup(mem_ctx, "/tmp/two"); + assert_non_null(path1); + + memcache_add_talloc(cache, GETWD_CACHE, key1, &path1); + assert_null(path1); + + memcache_add_talloc(cache, GETWD_CACHE, key2, &path2); + assert_null(path2); + + path1 = memcache_lookup_talloc(cache, GETWD_CACHE, key1); + assert_non_null(path1); + assert_string_equal(path1, "/tmp/one"); + + path2 = memcache_lookup_talloc(cache, GETWD_CACHE, key2); + assert_non_null(path2); + assert_string_equal(path2, "/tmp/two"); + + memcache_delete(cache, GETWD_CACHE, key1); + path1 = memcache_lookup_talloc(cache, GETWD_CACHE, key1); + assert_null(path1); + + memcache_flush(cache, GETWD_CACHE); + path2 = memcache_lookup_talloc(cache, GETWD_CACHE, key2); + assert_null(path2); + + TALLOC_FREE(path1); + TALLOC_FREE(path2); + TALLOC_FREE(cache); +} + +static void torture_memcache_add_oversize(void **state) +{ + TALLOC_CTX *mem_ctx = *state; + struct memcache *cache = NULL; + DATA_BLOB key1, key2; + char *path1 = NULL, *path2 = NULL; + + cache = memcache_init(mem_ctx, 10); + assert_non_null(cache); + + key1 = data_blob_const("key1", 4); + path1 = talloc_strdup(mem_ctx, "/tmp/one"); + assert_non_null(path1); + + key2 = data_blob_const("key2", 4); + path2 = talloc_strdup(mem_ctx, "/tmp/two"); + assert_non_null(path1); + + memcache_add_talloc(cache, GETWD_CACHE, key1, &path1); + assert_null(path1); + + memcache_add_talloc(cache, GETWD_CACHE, key2, &path2); + assert_null(path2); + + path1 = memcache_lookup_talloc(cache, GETWD_CACHE, key1); + assert_null(path1); + + path2 = memcache_lookup_talloc(cache, GETWD_CACHE, key2); + assert_non_null(path2); + assert_string_equal(path2, "/tmp/two"); + + TALLOC_FREE(path1); + TALLOC_FREE(path2); + TALLOC_FREE(cache); +} + +int main(int argc, char *argv[]) +{ + int rc; + const struct CMUnitTest tests[] = { + cmocka_unit_test(torture_memcache_init), + cmocka_unit_test(torture_memcache_add_lookup_delete), + cmocka_unit_test(torture_memcache_add_oversize), + }; + + if (argc == 2) { + cmocka_set_test_filter(argv[1]); + } + cmocka_set_message_output(CM_OUTPUT_SUBUNIT); + + rc = cmocka_run_group_tests(tests, + setup_talloc_context, + teardown_talloc_context); + + return rc; +} diff --git a/lib/util/wscript_build b/lib/util/wscript_build index bf3e44bf1d2..5a8a04965ec 100644 --- a/lib/util/wscript_build +++ b/lib/util/wscript_build @@ -310,4 +310,10 @@ else: source='tests/test_util.c', deps='cmocka replace talloc samba-util', local_include=False, - for_selftest=True); + for_selftest=True) + + bld.SAMBA_BINARY('test_memcache', + source='tests/test_memcache.c', + deps='cmocka replace talloc samba-util', + local_include=False, + for_selftest=True) diff --git a/python/samba/dbchecker.py b/python/samba/dbchecker.py index 593aa8cf6d2..d12833d9390 100644 --- a/python/samba/dbchecker.py +++ b/python/samba/dbchecker.py @@ -1819,6 +1819,11 @@ newSuperior: %s""" % (str(from_dn), str(to_rdn), str(to_base))) # old static provision dumps return False + if dn in self.deleted_objects_containers: + # The Deleted Objects container will look like an expired + # tombstone + return False + repl = ndr_unpack(drsblobs.replPropertyMetaDataBlob, repl_val) isDeleted = self.find_repl_attid(repl, drsuapi.DRSUAPI_ATTID_isDeleted) @@ -1832,7 +1837,25 @@ newSuperior: %s""" % (str(from_dn), str(to_rdn), str(to_base))) if delta <= tombstone_delta: return False - self.report("SKIPING: object %s is an expired tombstone" % dn) + expunge_time = delete_time + tombstone_delta + + delta_days = delta / (24 * 60 * 60) + + if delta_days <= 2: + self.report("SKIPPING additional checks on object " + "%s which very recently " + "became an expired tombstone (normal)" % dn) + self.report("INFO: it is expected this will be expunged " + "by the next daily task some time after %s, " + "%d hours ago" + % (time.ctime(expunge_time), delta // (60 * 60))) + else: + self.report("SKIPPING: object %s is an expired tombstone" % dn) + self.report("INFO: it was expected this object would have " + "been expunged soon after" + "%s, %d days ago" + % (time.ctime(expunge_time), delta_days)) + self.report("isDeleted: attid=0x%08x version=%d invocation=%s usn=%s (local=%s) at %s" % ( isDeleted.attid, isDeleted.version, diff --git a/python/samba/upgrade.py b/python/samba/upgrade.py index 8511bed2868..dff856a8d7c 100644 --- a/python/samba/upgrade.py +++ b/python/samba/upgrade.py @@ -74,7 +74,7 @@ def import_sam_policy(samdb, policy, logger): if 'maximum password age' in policy: max_pw_age_unix = policy['maximum password age'] - if max_pw_age_unix == -1 or max_pw_age_unix == 0: + if max_pw_age_unix == -1 or max_pw_age_unix == 0 or max_pw_age_unix == 0xFFFFFFFF: max_pw_age_nt = -0x8000000000000000 else: max_pw_age_nt = int(-max_pw_age_unix * (1e7)) diff --git a/script/autobuild.py b/script/autobuild.py index 0ab04eb7c26..0f837d0c109 100755 --- a/script/autobuild.py +++ b/script/autobuild.py @@ -4,7 +4,7 @@ # released under GNU GPL v3 or later from __future__ import print_function -from subprocess import call, check_call, check_output, Popen, PIPE +from subprocess import call, check_call, check_output, Popen, PIPE, CalledProcessError import os import tarfile import sys @@ -860,6 +860,17 @@ def run_cmd(cmd, dir=".", show=None, output=False, checkfail=True): else: return call(cmd, shell=True, cwd=dir) +def rmdir_force(dirname, re_raise=True): + try: + run_cmd("test -d %s && chmod -R +w %s; rm -rf %s" % ( + dirname, dirname, dirname), output=True, show=True) + except CalledProcessError as e: + do_print("Failed: '%s'" % (str(e))) + run_cmd("tree %s" % dirname, output=True, show=True) + if re_raise: + raise + return False + return True class builder(object): '''handle build of one directory''' @@ -882,8 +893,8 @@ class builder(object): self.test_source_dir = "%s/%s" % (testbase, self.tag) self.cwd = "%s/%s" % (self.test_source_dir, self.dir) self.prefix = "%s/%s" % (test_prefix, self.tag) - run_cmd("rm -rf %s" % self.test_source_dir) - run_cmd("rm -rf %s" % self.prefix) + rmdir_force(self.test_source_dir) + rmdir_force(self.prefix) if cp: run_cmd("cp -R -a -l %s %s" % (test_master, self.test_source_dir), dir=test_master, show=True) else: @@ -893,8 +904,8 @@ class builder(object): def start_next(self): if self.next == len(self.sequence): if not options.nocleanup: - run_cmd("rm -rf %s" % self.test_source_dir) - run_cmd("rm -rf %s" % self.prefix) + rmdir_force(self.test_source_dir) + rmdir_force(self.prefix) do_print('%s: Completed OK' % self.name) self.done = True return @@ -1018,7 +1029,7 @@ class buildlist(object): 'df -m %s' % testbase]: try: out = run_cmd(cmd, output=True, checkfail=False) - except subprocess.CalledProcessError as e: + except CalledProcessError as e: out = "<failed: %s>" % str(e) print('### %s' % cmd, file=f) print(out, file=f) @@ -1048,14 +1059,23 @@ class buildlist(object): self.tail_proc = Popen(cmd, close_fds=True) -def cleanup(): +def cleanup(do_raise=False): if options.nocleanup: return run_cmd("stat %s || true" % test_tmpdir, show=True) run_cmd("stat %s" % testbase, show=True) do_print("Cleaning up %r" % cleanup_list) for d in cleanup_list: - run_cmd("rm -rf %s" % d) + ok = rmdir_force(d, re_raise=False) + if ok: + continue + if os.path.isdir(d): + do_print("Killing, waiting and retry") + run_cmd("killbysubdir %s > /dev/null 2>&1" % d, checkfail=False) + else: + do_print("Waiting and retry") + time.sleep(1) + rmdir_force(d, re_raise=do_raise) def daemonize(logfile): @@ -1321,7 +1341,7 @@ while True: (status, failed_task, failed_stage, failed_tag, errstr) = blist.run() if status != 0 or errstr != "retry": break - cleanup() + cleanup(do_raise=True) except Exception: cleanup() raise diff --git a/selftest/selftest.pl b/selftest/selftest.pl index d14df92a11c..258a8437922 100755 --- a/selftest/selftest.pl +++ b/selftest/selftest.pl @@ -280,7 +280,7 @@ my $bindir_abs = abs_path($bindir); my $torture_maxtime = ($ENV{TORTURE_MAXTIME} or 1200); $prefix =~ s+//+/+; -$prefix =~ s+/./+/+; +$prefix =~ s+/\./+/+; $prefix =~ s+/$++; die("using an empty prefix isn't allowed") unless $prefix ne ""; @@ -312,7 +312,6 @@ $ENV{PREFIX} = $prefix; $ENV{PREFIX_ABS} = $prefix_abs; $ENV{SRCDIR} = $srcdir; $ENV{SRCDIR_ABS} = $srcdir_abs; -$ENV{GNUPGHOME} = "$srcdir_abs/selftest/gnupg"; $ENV{BINDIR} = $bindir_abs; my $tls_enabled = not $opt_quick; @@ -693,6 +692,9 @@ $ENV{RESOLV_CONF} = "${selftest_resolv_conf_path}.global"; my $selftest_krbt_ccache_path = "$tmpdir_abs/selftest.krb5_ccache"; $ENV{KRB5CCNAME} = "FILE:${selftest_krbt_ccache_path}.global"; +my $selftest_gnupghome_path = "$tmpdir_abs/selftest.no.gnupg"; +$ENV{GNUPGHOME} = "${selftest_gnupghome_path}.global"; + my @available = (); foreach my $fn (@testlists) { foreach (read_testlist($fn)) { @@ -829,6 +831,7 @@ sub setup_env($$) $ENV{RESOLV_CONF} = "${selftest_resolv_conf_path}.${envname}/ignore"; $ENV{KRB5CCNAME} = "FILE:${selftest_krbt_ccache_path}.${envname}/ignore"; + $ENV{GNUPGHOME} = "${selftest_gnupghome_path}.${envname}/ignore"; if (defined(get_running_env($envname))) { $testenv_vars = get_running_env($envname); diff --git a/selftest/target/Samba.pm b/selftest/target/Samba.pm index 6118f2e243a..d47f933376e 100644 --- a/selftest/target/Samba.pm +++ b/selftest/target/Samba.pm @@ -280,6 +280,30 @@ EOF umask $oldumask; } +sub copy_gnupg_home($) +{ + my ($ctx) = @_; + + my $gnupg_srcdir = "$ENV{SRCDIR_ABS}/selftest/gnupg"; + my @files = ( + "gpg.conf", + "pubring.gpg", + "secring.gpg", + "trustdb.gpg", + ); + + my $oldumask = umask; + umask 0077; + mkdir($ctx->{gnupghome}, 0777); + umask 0177; + foreach my $file (@files) { + my $srcfile = "${gnupg_srcdir}/${file}"; + my $dstfile = "$ctx->{gnupghome}/${file}"; + copy_file_content(${srcfile}, ${dstfile}); + } + umask $oldumask; +} + sub mk_krb5_conf($$) { my ($ctx) = @_; @@ -672,6 +696,7 @@ sub get_env_for_process RESOLV_CONF => $env_vars->{RESOLV_CONF}, KRB5_CONFIG => $env_vars->{KRB5_CONFIG}, KRB5CCNAME => "$env_vars->{KRB5_CCACHE}.$proc_name", + GNUPGHOME => $env_vars->{GNUPGHOME}, SELFTEST_WINBINDD_SOCKET_DIR => $env_vars->{SELFTEST_WINBINDD_SOCKET_DIR}, NMBD_SOCKET_DIR => $env_vars->{NMBD_SOCKET_DIR}, NSS_WRAPPER_PASSWD => $env_vars->{NSS_WRAPPER_PASSWD}, @@ -857,6 +882,7 @@ my @exported_envvars = ( # misc stuff "KRB5_CONFIG", "KRB5CCNAME", + "GNUPGHOME", "SELFTEST_WINBINDD_SOCKET_DIR", "NMBD_SOCKET_DIR", "LOCAL_PATH", diff --git a/selftest/target/Samba3.pm b/selftest/target/Samba3.pm index e141f102ef1..c15057fa80b 100755 --- a/selftest/target/Samba3.pm +++ b/selftest/target/Samba3.pm @@ -723,6 +723,7 @@ sub provision_ad_member my $ret = $self->provision( prefix => $prefix, domain => $dcvars->{DOMAIN}, + realm => $dcvars->{REALM}, server => "LOCALADMEMBER", password => "loCalMemberPass", extra_options => $member_options, @@ -873,6 +874,7 @@ sub setup_ad_member_rfc2307 my $ret = $self->provision( prefix => $prefix, domain => $dcvars->{DOMAIN}, + realm => $dcvars->{REALM}, server => "RFC2307MEMBER", password => "loCalMemberPass", extra_options => $member_options, @@ -970,6 +972,7 @@ sub setup_ad_member_idmap_rid my $ret = $self->provision( prefix => $prefix, domain => $dcvars->{DOMAIN}, + realm => $dcvars->{REALM}, server => "IDMAPRIDMEMBER", password => "loCalMemberPass", extra_options => $member_options, @@ -1067,6 +1070,7 @@ sub setup_ad_member_idmap_ad my $ret = $self->provision( prefix => $prefix, domain => $dcvars->{DOMAIN}, + realm => $dcvars->{REALM}, server => "IDMAPADMEMBER", password => "loCalMemberPass", extra_options => $member_options, @@ -1727,12 +1731,22 @@ $ret->{USERNAME} = KTEST\\Administrator sub setup_maptoguest { my ($self, $path) = @_; + my $prefix_abs = abs_path($path); + my $libdir="$prefix_abs/lib"; + my $share_dir="$prefix_abs/share"; + my $errorinjectconf="$libdir/error_inject.conf"; print "PROVISIONING maptoguest..."; my $options = " map to guest = bad user ntlm auth = yes + +[force_user_error_inject] + path = $share_dir + vfs objects = acl_xattr fake_acls xattr_tdb error_inject + force user = user1 + include = $errorinjectconf "; my $vars = $self->provision( @@ -1930,6 +1944,7 @@ sub provision($$) my $prefix = $args{prefix}; my $domain = $args{domain}; + my $realm = $args{realm}; my $server = $args{server}; my $password = $args{password}; my $extra_options = $args{extra_options}; @@ -1947,6 +1962,12 @@ sub provision($$) my %createuser_env = (); my $server_ip = Samba::get_ipv4_addr($server); my $server_ipv6 = Samba::get_ipv6_addr($server); + my $dns_domain; + if (defined($realm)) { + $dns_domain = lc($realm); + } else { + $dns_domain = "samba.example.com"; + } my $unix_name = ($ENV{USER} or $ENV{LOGNAME} or `PATH=/usr/ucb:$ENV{PATH} whoami`); chomp $unix_name; @@ -2926,8 +2947,8 @@ force_user:x:$gid_force_user: warn("Unable to open $nss_wrapper_hosts"); return undef; } - print HOSTS "${server_ip} ${hostname}.samba.example.com ${hostname}\n"; - print HOSTS "${server_ipv6} ${hostname}.samba.example.com ${hostname}\n"; + print HOSTS "${server_ip} ${hostname}.${dns_domain} ${hostname}\n"; + print HOSTS "${server_ipv6} ${hostname}.${dns_domain} ${hostname}\n"; close(HOSTS); $resolv_conf = "$privatedir/no_resolv.conf" unless defined($resolv_conf); diff --git a/selftest/target/Samba4.pm b/selftest/target/Samba4.pm index 649e923ff9a..77bd741d476 100755 --- a/selftest/target/Samba4.pm +++ b/selftest/target/Samba4.pm @@ -17,7 +17,6 @@ use SocketWrapper; use target::Samba; use target::Samba3; use Archive::Tar; -use File::Path 'make_path'; sub new($$$$$) { my ($classname, $SambaCtx, $bindir, $srcdir, $server_maxtime) = @_; @@ -161,19 +160,7 @@ sub wait_for_start($$) my $max_wait = 60; # Add hosts file for name lookups - my $cmd = "NSS_WRAPPER_HOSTS='$testenv_vars->{NSS_WRAPPER_HOSTS}' "; - if (defined($testenv_vars->{RESOLV_WRAPPER_CONF})) { - $cmd .= "RESOLV_WRAPPER_CONF='$testenv_vars->{RESOLV_WRAPPER_CONF}' "; - } else { - $cmd .= "RESOLV_WRAPPER_HOSTS='$testenv_vars->{RESOLV_WRAPPER_HOSTS}' "; - } - $cmd .= "RESOLV_CONF='$testenv_vars->{RESOLV_CONF}' "; - if (defined($testenv_vars->{GNUTLS_FORCE_FIPS_MODE})) { - $cmd .= "GNUTLS_FORCE_FIPS_MODE=$testenv_vars->{GNUTLS_FORCE_FIPS_MODE} "; - } - if (defined($testenv_vars->{OPENSSL_FORCE_FIPS_MODE})) { - $cmd .= "OPENSSL_FORCE_FIPS_MODE=$testenv_vars->{OPENSSL_FORCE_FIPS_MODE} "; - } + my $cmd = $self->get_cmd_env_vars($testenv_vars); $cmd .= "$ldbsearch "; $cmd .= "$testenv_vars->{CONFIGURATION} "; @@ -281,7 +268,7 @@ sub setup_dns_hub_internal($$$) my ($self, $hostname, $prefix) = @_; my $STDIN_READER; - unless(-d $prefix or make_path($prefix, 0777)) { + unless(-d $prefix or mkdir($prefix, 0777)) { warn("Unable to create $prefix"); return undef; } @@ -356,6 +343,10 @@ sub setup_dns_hub my $hostname = "rootdnsforwarder"; + unless(-d $prefix or mkdir($prefix, 0777)) { + warn("Unable to create $prefix"); + return undef; + } my $env = $self->setup_dns_hub_internal("$hostname", "$prefix/$hostname"); $self->{dns_hub_env} = $env; @@ -375,10 +366,44 @@ sub get_dns_hub_env($) return undef; } +sub return_env_value +{ + my ($env, $overwrite, $key) = @_; + + if (defined($overwrite) and defined($overwrite->{$key})) { + return $overwrite->{$key}; + } + + if (defined($env->{$key})) { + return $env->{$key}; + } + + return undef; +} + # Returns the environmental variables that we pass to samba-tool commands sub get_cmd_env_vars { - my ($self, $localenv) = @_; + my ($self, $givenenv, $overwrite) = @_; + + my @keys = ( + "NSS_WRAPPER_HOSTS", + "SOCKET_WRAPPER_DEFAULT_IFACE", + "RESOLV_CONF", + "RESOLV_WRAPPER_CONF", + "RESOLV_WRAPPER_HOSTS", + "GNUTLS_FORCE_FIPS_MODE", + "OPENSSL_FORCE_FIPS_MODE", + "KRB5_CONFIG", + "KRB5_CCACHE", + "GNUPGHOME", + ); + + my $localenv = undef; + foreach my $key (@keys) { + my $v = return_env_value($givenenv, $overwrite, $key); + $localenv->{$key} = $v if defined($v); + } my $cmd_env = "NSS_WRAPPER_HOSTS='$localenv->{NSS_WRAPPER_HOSTS}' "; $cmd_env .= "SOCKET_WRAPPER_DEFAULT_IFACE=\"$localenv->{SOCKET_WRAPPER_DEFAULT_IFACE}\" "; @@ -393,9 +418,10 @@ sub get_cmd_env_vars if (defined($localenv->{OPENSSL_FORCE_FIPS_MODE})) { $cmd_env .= "OPENSSL_FORCE_FIPS_MODE=$localenv->{OPENSSL_FORCE_FIPS_MODE} "; } - $cmd_env .= " KRB5_CONFIG=\"$localenv->{KRB5_CONFIG}\" "; + $cmd_env .= "KRB5_CONFIG=\"$localenv->{KRB5_CONFIG}\" "; $cmd_env .= "KRB5CCNAME=\"$localenv->{KRB5_CCACHE}\" "; $cmd_env .= "RESOLV_CONF=\"$localenv->{RESOLV_CONF}\" "; + $cmd_env .= "GNUPGHOME=\"$localenv->{GNUPGHOME}\" "; return $cmd_env; } @@ -565,6 +591,7 @@ sub provision_raw_prepare($$$$$$$$$$$$$$) $ctx->{krb5_conf} = "$ctx->{etcdir}/krb5.conf"; $ctx->{krb5_ccache} = "$prefix_abs/krb5_ccache"; $ctx->{mitkdc_conf} = "$ctx->{etcdir}/mitkdc.conf"; + $ctx->{gnupghome} = "$prefix_abs/gnupg"; $ctx->{privatedir} = "$prefix_abs/private"; $ctx->{binddnsdir} = "$prefix_abs/bind-dns"; $ctx->{ncalrpcdir} = "$prefix_abs/ncalrpc"; @@ -608,8 +635,9 @@ sub provision_raw_prepare($$$$$$$$$$$$$$) $ctx->{smb_conf_extra_options} = ""; my @provision_options = (); + push (@provision_options, "GNUPGHOME=\"$ctx->{gnupghome}\""); push (@provision_options, "KRB5_CONFIG=\"$ctx->{krb5_conf}\""); - push (@provision_options, "KRB5_CCACHE=\"$ctx->{krb5_ccache}\""); + push (@provision_options, "KRB5CCNAME=\"$ctx->{krb5_ccache}\""); push (@provision_options, "NSS_WRAPPER_PASSWD=\"$ctx->{nsswrap_passwd}\""); push (@provision_options, "NSS_WRAPPER_GROUP=\"$ctx->{nsswrap_group}\""); push (@provision_options, "NSS_WRAPPER_HOSTS=\"$ctx->{nsswrap_hosts}\""); @@ -700,6 +728,7 @@ sub provision_raw_step1($$) return undef; } + Samba::copy_gnupg_home($ctx); Samba::prepare_keyblobs($ctx); my $crlfile = "$ctx->{tlsdir}/crl.pem"; $crlfile = "" unless -e ${crlfile}; @@ -843,6 +872,7 @@ nogroup:x:65534:nobody # Note that we have SERVER_X and DC_SERVER_X variables (which have the same # value initially). In a 2 DC setup, $DC_SERVER_X will always be the PDC. my $ret = { + GNUPGHOME => $ctx->{gnupghome}, KRB5_CONFIG => $ctx->{krb5_conf}, KRB5_CCACHE => $ctx->{krb5_ccache}, MITKDC_CONFIG => $ctx->{mitkdc_conf}, @@ -922,11 +952,10 @@ sub provision_raw_step2($$$) return undef; } + my $cmd_env = $self->get_cmd_env_vars($ret); + my $testallowed_account = "testallowed"; - my $samba_tool_cmd = ""; - $samba_tool_cmd .= "RESOLV_CONF=\"$ret->{RESOLV_CONF}\" "; - $samba_tool_cmd .= "KRB5_CONFIG=\"$ret->{KRB5_CONFIG}\" "; - $samba_tool_cmd .= "KRB5CCNAME=\"$ret->{KRB5_CCACHE}\" "; + my $samba_tool_cmd = ${cmd_env}; $samba_tool_cmd .= Samba::bindir_path($self, "samba-tool") . " user create --configfile=$ctx->{smb_conf} $testallowed_account $ctx->{password}"; unless (system($samba_tool_cmd) == 0) { @@ -935,10 +964,7 @@ sub provision_raw_step2($$$) } my $srv_account = "srv_account"; - $samba_tool_cmd = ""; - $samba_tool_cmd .= "RESOLV_CONF=\"$ret->{RESOLV_CONF}\" "; - $samba_tool_cmd .= "KRB5_CONFIG=\"$ret->{KRB5_CONFIG}\" "; - $samba_tool_cmd .= "KRB5CCNAME=\"$ret->{KRB5_CCACHE}\" "; + $samba_tool_cmd = ${cmd_env}; $samba_tool_cmd .= Samba::bindir_path($self, "samba-tool") . " user create --configfile=$ctx->{smb_conf} $srv_account $ctx->{password}"; unless (system($samba_tool_cmd) == 0) { @@ -946,10 +972,7 @@ sub provision_raw_step2($$$) return undef; } - $samba_tool_cmd = ""; - $samba_tool_cmd .= "RESOLV_CONF=\"$ret->{RESOLV_CONF}\" "; - $samba_tool_cmd .= "KRB5_CONFIG=\"$ret->{KRB5_CONFIG}\" "; - $samba_tool_cmd .= "KRB5CCNAME=\"$ret->{KRB5_CCACHE}\" "; + $samba_tool_cmd = ${cmd_env}; $samba_tool_cmd .= Samba::bindir_path($self, "samba-tool") . " spn add HOST/$srv_account --configfile=$ctx->{smb_conf} $srv_account"; unless (system($samba_tool_cmd) == 0) { @@ -957,10 +980,7 @@ sub provision_raw_step2($$$) return undef; } - my $ldbmodify = ""; - $ldbmodify .= "RESOLV_CONF=\"$ret->{RESOLV_CONF}\" "; - $ldbmodify .= "KRB5_CONFIG=\"$ret->{KRB5_CONFIG}\" "; - $ldbmodify .= "KRB5CCNAME=\"$ret->{KRB5_CCACHE}\" "; + my $ldbmodify = ${cmd_env}; $ldbmodify .= Samba::bindir_path($self, "ldbmodify"); $ldbmodify .= " --configfile=$ctx->{smb_conf}"; my $base_dn = "DC=".join(",DC=", split(/\./, $ctx->{realm})); @@ -991,10 +1011,7 @@ servicePrincipalName: host/testallowed "; close(LDIF); - $samba_tool_cmd = ""; - $samba_tool_cmd .= "RESOLV_CONF=\"$ret->{RESOLV_CONF}\" "; - $samba_tool_cmd .= "KRB5_CONFIG=\"$ret->{KRB5_CONFIG}\" "; - $samba_tool_cmd .= "KRB5CCNAME=\"$ret->{KRB5_CCACHE}\" "; + $samba_tool_cmd = ${cmd_env}; $samba_tool_cmd .= Samba::bindir_path($self, "samba-tool") . " user create --configfile=$ctx->{smb_conf} testdenied $ctx->{password}"; unless (system($samba_tool_cmd) == 0) { @@ -1012,10 +1029,7 @@ userPrincipalName: testdenied_upn\@$ctx->{realm}.upn "; close(LDIF); - $samba_tool_cmd = ""; - $samba_tool_cmd .= "RESOLV_CONF=\"$ret->{RESOLV_CONF}\" "; - $samba_tool_cmd .= "KRB5_CONFIG=\"$ret->{KRB5_CONFIG}\" "; - $samba_tool_cmd .= "KRB5CCNAME=\"$ret->{KRB5_CCACHE}\" "; + $samba_tool_cmd = ${cmd_env}; $samba_tool_cmd .= Samba::bindir_path($self, "samba-tool") . " user create --configfile=$ctx->{smb_conf} testupnspn $ctx->{password}"; unless (system($samba_tool_cmd) == 0) { @@ -1035,10 +1049,7 @@ servicePrincipalName: http/testupnspn.$ctx->{dnsname} "; close(LDIF); - $samba_tool_cmd = ""; - $samba_tool_cmd .= "RESOLV_CONF=\"$ret->{RESOLV_CONF}\" "; - $samba_tool_cmd .= "KRB5_CONFIG=\"$ret->{KRB5_CONFIG}\" "; - $samba_tool_cmd .= "KRB5CCNAME=\"$ret->{KRB5_CCACHE}\" "; + $samba_tool_cmd = ${cmd_env}; $samba_tool_cmd .= Samba::bindir_path($self, "samba-tool") . " group addmembers --configfile=$ctx->{smb_conf} 'Allowed RODC Password Replication Group' '$testallowed_account'"; unless (system($samba_tool_cmd) == 0) { @@ -1050,11 +1061,8 @@ servicePrincipalName: http/testupnspn.$ctx->{dnsname} my $user_account_array = ["alice", "bob", "jane", "joe"]; foreach my $user_account (@{$user_account_array}) { - my $samba_tool_cmd = ""; + my $samba_tool_cmd = ${cmd_env}; - $samba_tool_cmd .= "RESOLV_CONF=\"$ret->{RESOLV_CONF}\" "; - $samba_tool_cmd .= "KRB5_CONFIG=\"$ret->{KRB5_CONFIG}\" "; - $samba_tool_cmd .= "KRB5CCNAME=\"$ret->{KRB5_CCACHE}\" "; $samba_tool_cmd .= Samba::bindir_path($self, "samba-tool") . " user create --configfile=$ctx->{smb_conf} $user_account Secret007"; unless (system($samba_tool_cmd) == 0) { @@ -1066,10 +1074,8 @@ servicePrincipalName: http/testupnspn.$ctx->{dnsname} my $group_array = ["Samba Users"]; foreach my $group (@{$group_array}) { - my $samba_tool_cmd = ""; + my $samba_tool_cmd = ${cmd_env}; - $samba_tool_cmd .= "KRB5_CONFIG=\"$ret->{KRB5_CONFIG}\" "; - $samba_tool_cmd .= "KRB5CCNAME=\"$ret->{KRB5_CCACHE}\" "; $samba_tool_cmd .= Samba::bindir_path($self, "samba-tool") . " group add --configfile=$ctx->{smb_conf} \"$group\""; unless (system($samba_tool_cmd) == 0) { @@ -1079,12 +1085,10 @@ servicePrincipalName: http/testupnspn.$ctx->{dnsname} } # Add user joe to group "Samba Users" - $samba_tool_cmd = ""; my $group = "Samba Users"; my $user_account = "joe"; - $samba_tool_cmd .= "KRB5_CONFIG=\"$ret->{KRB5_CONFIG}\" "; - $samba_tool_cmd .= "KRB5CCNAME=\"$ret->{KRB5_CCACHE}\" "; + $samba_tool_cmd = ${cmd_env}; $samba_tool_cmd .= Samba::bindir_path($self, "samba-tool") . " group addmembers --configfile=$ctx->{smb_conf} \"$group\" $user_account"; unless (system($samba_tool_cmd) == 0) { @@ -1092,12 +1096,10 @@ servicePrincipalName: http/testupnspn.$ctx->{dnsname} return undef; } - $samba_tool_cmd = ""; $group = "Samba Users"; $user_account = "joe"; - $samba_tool_cmd .= "KRB5_CONFIG=\"$ret->{KRB5_CONFIG}\" "; - $samba_tool_cmd .= "KRB5CCNAME=\"$ret->{KRB5_CCACHE}\" "; + $samba_tool_cmd = ${cmd_env}; $samba_tool_cmd .= Samba::bindir_path($self, "samba-tool") . " user setprimarygroup --configfile=$ctx->{smb_conf} $user_account \"$group\""; unless (system($samba_tool_cmd) == 0) { @@ -1106,10 +1108,7 @@ servicePrincipalName: http/testupnspn.$ctx->{dnsname} } # Change the userPrincipalName for jane - $ldbmodify = ""; - $ldbmodify .= "RESOLV_CONF=\"$ret->{RESOLV_CONF}\" "; - $ldbmodify .= "KRB5_CONFIG=\"$ret->{KRB5_CONFIG}\" "; - $ldbmodify .= "KRB5CCNAME=\"$ret->{KRB5_CCACHE}\" "; + $ldbmodify = ${cmd_env}; $ldbmodify .= Samba::bindir_path($self, "ldbmodify"); $ldbmodify .= " --configfile=$ctx->{smb_conf}"; $base_dn = "DC=".join(",DC=", split(/\./, $ctx->{realm})); @@ -1409,12 +1408,13 @@ sub provision_rpc_proxy($$$) return undef; } + # Prepare a context of the DC, but using the local CCACHE. + my $overwrite = undef; + $overwrite->{KRB5_CCACHE} = $ret->{KRB5_CCACHE}; + my $dc_cmd_env = $self->get_cmd_env_vars($dcvars, $overwrite); + # Setting up delegation runs in the context of the DC for now - $cmd = ""; - $cmd .= "SOCKET_WRAPPER_DEFAULT_IFACE=\"$dcvars->{SOCKET_WRAPPER_DEFAULT_IFACE}\" "; - $cmd .= "KRB5_CONFIG=\"$dcvars->{KRB5_CONFIG}\" "; - $cmd .= "KRB5CCNAME=\"$ret->{KRB5_CCACHE}\" "; - $cmd .= "RESOLV_CONF=\"$dcvars->{RESOLV_CONF}\" "; + $cmd = $dc_cmd_env; $cmd .= "$samba_tool delegation for-any-protocol '$ret->{NETBIOSNAME}\$' on"; $cmd .= " $dcvars->{CONFIGURATION}"; print $cmd; @@ -1425,11 +1425,7 @@ sub provision_rpc_proxy($$$) } # Setting up delegation runs in the context of the DC for now - $cmd = ""; - $cmd .= "SOCKET_WRAPPER_DEFAULT_IFACE=\"$dcvars->{SOCKET_WRAPPER_DEFAULT_IFACE}\" "; - $cmd .= "KRB5_CONFIG=\"$dcvars->{KRB5_CONFIG}\" "; - $cmd .= "KRB5CCNAME=\"$ret->{KRB5_CCACHE}\" "; - $cmd .= "RESOLV_CONF=\"$dcvars->{RESOLV_CONF}\" "; + $cmd = $dc_cmd_env; $cmd .= "$samba_tool delegation add-service '$ret->{NETBIOSNAME}\$' cifs/$dcvars->{SERVER}"; $cmd .= " $dcvars->{CONFIGURATION}"; @@ -1824,9 +1820,7 @@ sub provision_rodc($$$) # This ensures deterministic behaviour for tests that want to have the 'testallowed account' # user password verified on the RODC my $testallowed_account = "testallowed account"; - $cmd = "KRB5_CONFIG=\"$ret->{KRB5_CONFIG}\" "; - $cmd .= "KRB5CCNAME=\"$ret->{KRB5_CCACHE}\" "; - $cmd .= "RESOLV_CONF=\"$ret->{RESOLV_CONF}\" "; + $cmd = $self->get_cmd_env_vars($ret); $cmd .= "$samba_tool rodc preload '$testallowed_account' $ret->{CONFIGURATION}"; $cmd .= " --server=$dcvars->{DC_SERVER}"; @@ -2502,14 +2496,10 @@ sub setup_promoted_dc # force source and replicated DC to update repsTo/repsFrom # for vampired partitions my $samba_tool = Samba::bindir_path($self, "samba-tool"); - my $cmd = "NSS_WRAPPER_HOSTS='$env->{NSS_WRAPPER_HOSTS}' "; + my $cmd = $self->get_cmd_env_vars($env); # as 'vampired' dc may add data in its local replica # we need to synchronize data between DCs my $base_dn = "DC=".join(",DC=", split(/\./, $dc_vars->{REALM})); - $cmd = "SOCKET_WRAPPER_DEFAULT_IFACE=\"$env->{SOCKET_WRAPPER_DEFAULT_IFACE}\""; - $cmd .= " KRB5_CONFIG=\"$env->{KRB5_CONFIG}\""; - $cmd .= "KRB5CCNAME=\"$env->{KRB5_CCACHE}\" "; - $cmd .= "RESOLV_CONF=\"$env->{RESOLV_CONF}\" "; $cmd .= " $samba_tool drs replicate $env->{DC_SERVER} $env->{SERVER}"; $cmd .= " $dc_vars->{CONFIGURATION}"; $cmd .= " -U$dc_vars->{DC_USERNAME}\%$dc_vars->{DC_PASSWORD}"; @@ -2545,14 +2535,9 @@ sub setup_rodc } my $samba_tool = Samba::bindir_path($self, "samba-tool"); - my $cmd = ""; + my $cmd = $self->get_cmd_env_vars($env); my $base_dn = "DC=".join(",DC=", split(/\./, $dc_vars->{REALM})); - $cmd .= "NSS_WRAPPER_HOSTS='$env->{NSS_WRAPPER_HOSTS}' "; - $cmd .= "SOCKET_WRAPPER_DEFAULT_IFACE=\"$env->{SOCKET_WRAPPER_DEFAULT_IFACE}\""; - $cmd .= " KRB5_CONFIG=\"$env->{KRB5_CONFIG}\""; - $cmd .= "KRB5CCNAME=\"$env->{KRB5_CCACHE}\" "; - $cmd .= "RESOLV_CONF=\"$env->{RESOLV_CONF}\" "; $cmd .= " $samba_tool drs replicate $env->{SERVER} $env->{DC_SERVER}"; $cmd .= " $dc_vars->{CONFIGURATION}"; $cmd .= " -U$dc_vars->{DC_USERNAME}\%$dc_vars->{DC_PASSWORD}"; @@ -2857,16 +2842,7 @@ sub setup_schema_pair_dc ""); my $samba_tool = Samba::bindir_path($self, "samba-tool"); - my $cmd_vars = "NSS_WRAPPER_HOSTS='$env->{NSS_WRAPPER_HOSTS}' "; - $cmd_vars .= "SOCKET_WRAPPER_DEFAULT_IFACE=\"$env->{SOCKET_WRAPPER_DEFAULT_IFACE}\" "; - if (defined($env->{RESOLV_WRAPPER_CONF})) { - $cmd_vars .= "RESOLV_WRAPPER_CONF=\"$env->{RESOLV_WRAPPER_CONF}\" "; - } else { - $cmd_vars .= "RESOLV_WRAPPER_HOSTS=\"$env->{RESOLV_WRAPPER_HOSTS}\" "; - } - $cmd_vars .= "KRB5_CONFIG=\"$env->{KRB5_CONFIG}\" "; - $cmd_vars .= "KRB5CCNAME=\"$env->{KRB5_CCACHE}\" "; - $cmd_vars .= "RESOLV_CONF=\"$env->{RESOLV_CONF}\" "; + my $cmd_vars = $self->get_cmd_env_vars($env); my $join_cmd = $cmd_vars; $join_cmd .= "$samba_tool domain join $env->{CONFIGURATION} $dcvars->{REALM} DC --realm=$dcvars->{REALM}"; @@ -3008,17 +2984,10 @@ sub create_backup my ($self, $env, $dcvars, $backupdir, $backup_cmd) = @_; # get all the env variables we pass in with the samba-tool command - my $cmd_env = "NSS_WRAPPER_HOSTS='$env->{NSS_WRAPPER_HOSTS}' "; - $cmd_env .= "SOCKET_WRAPPER_DEFAULT_IFACE=\"$env->{SOCKET_WRAPPER_DEFAULT_IFACE}\" "; - if (defined($env->{RESOLV_WRAPPER_CONF})) { - $cmd_env .= "RESOLV_WRAPPER_CONF=\"$env->{RESOLV_WRAPPER_CONF}\" "; - } else { - $cmd_env .= "RESOLV_WRAPPER_HOSTS=\"$env->{RESOLV_WRAPPER_HOSTS}\" "; - } - $cmd_env .= "RESOLV_CONF=\"$env->{RESOLV_CONF}\" "; # Note: use the backupfrom-DC's krb5.conf to do the backup - $cmd_env .= " KRB5_CONFIG=\"$dcvars->{KRB5_CONFIG}\" "; - $cmd_env .= "KRB5CCNAME=\"$env->{KRB5_CCACHE}\" "; + my $overwrite = undef; + $overwrite->{KRB5_CONFIG} = $dcvars->{KRB5_CONFIG}; + my $cmd_env = $self->get_cmd_env_vars($env, $overwrite); # use samba-tool to create a backup from the 'backupfromdc' DC my $cmd = ""; diff --git a/selftest/tests.py b/selftest/tests.py index 6918e1306c3..2b65943b2ed 100644 --- a/selftest/tests.py +++ b/selftest/tests.py @@ -398,6 +398,8 @@ plantestsuite("samba.unittests.util_paths", "none", [os.path.join(bindir(), "default/lib/util/test_util_paths")]) plantestsuite("samba.unittests.util", "none", [os.path.join(bindir(), "default/lib/util/test_util")]) +plantestsuite("samba.unittests.memcache", "none", + [os.path.join(bindir(), "default/lib/util/test_memcache")]) plantestsuite("samba.unittests.ntlm_check", "none", [os.path.join(bindir(), "default/libcli/auth/test_ntlm_check")]) plantestsuite("samba.unittests.gnutls", "none", diff --git a/source3/auth/auth_util.c b/source3/auth/auth_util.c index 9427c05f573..4686b29111e 100644 --- a/source3/auth/auth_util.c +++ b/source3/auth/auth_util.c @@ -485,6 +485,14 @@ NTSTATUS create_local_token(TALLOC_CTX *mem_ctx, return NT_STATUS_LOGON_FAILURE; } + if (!is_allowed_domain(server_info->info3->base.logon_domain.string)) { + DBG_NOTICE("Authentication failed for user [%s] " + "from firewalled domain [%s]\n", + server_info->info3->base.account_name.string, + server_info->info3->base.logon_domain.string); + return NT_STATUS_AUTHENTICATION_FIREWALL_FAILED; + } + if (server_info->cached_session_info != NULL) { session_info = copy_session_info(mem_ctx, server_info->cached_session_info); diff --git a/source3/include/proto.h b/source3/include/proto.h index 12aa392abae..de5d1be5208 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -322,6 +322,7 @@ struct passwd *Get_Pwnam_alloc(TALLOC_CTX *mem_ctx, const char *user); /* The following definitions come from lib/util_names.c */ const char *get_global_sam_name(void); const char *my_sam_name(void); +bool is_allowed_domain(const char *domain_name); /* The following definitions come from lib/util.c */ diff --git a/source3/lib/g_lock.c b/source3/lib/g_lock.c index c36539393e1..36b527706da 100644 --- a/source3/lib/g_lock.c +++ b/source3/lib/g_lock.c @@ -646,8 +646,8 @@ static void g_lock_lock_retry(struct tevent_req *subreq) struct g_lock_lock_state *state = tevent_req_data( req, struct g_lock_lock_state); struct g_lock_lock_fn_state fn_state; - struct server_id blocker; - bool blockerdead; + struct server_id blocker = { .pid = 0 }; + bool blockerdead = false; NTSTATUS status; status = dbwrap_watched_watch_recv(subreq, &blockerdead, &blocker); diff --git a/source3/lib/util_names.c b/source3/lib/util_names.c index 15236c913df..630a25875c7 100644 --- a/source3/lib/util_names.c +++ b/source3/lib/util_names.c @@ -182,3 +182,23 @@ const char *my_sam_name(void) return lp_workgroup(); } + +bool is_allowed_domain(const char *domain_name) +{ + const char **ignored_domains = NULL; + const char **dom = NULL; + + ignored_domains = lp_parm_string_list(-1, + "winbind", + "ignore domains", + NULL); + + for (dom = ignored_domains; dom != NULL && *dom != NULL; dom++) { + if (gen_fnmatch(*dom, domain_name) == 0) { + DBG_NOTICE("Ignoring domain '%s'\n", domain_name); + return false; + } + } + + return true; +} diff --git a/source3/libsmb/clidfs.c b/source3/libsmb/clidfs.c index 4495a027830..3cc52cc5ac9 100644 --- a/source3/libsmb/clidfs.c +++ b/source3/libsmb/clidfs.c @@ -1230,6 +1230,7 @@ bool cli_check_msdfs_proxy(TALLOC_CTX *ctx, if (force_encrypt) { status = cli_cm_force_encryption_creds(cli, creds, "IPC$"); if (!NT_STATUS_IS_OK(status)) { + cli_tdis(cli); cli_state_restore_tcon(cli, orig_tcon); return false; } diff --git a/source3/libsmb/clientgen.c b/source3/libsmb/clientgen.c index 4412651f505..8ded372d0ba 100644 --- a/source3/libsmb/clientgen.c +++ b/source3/libsmb/clientgen.c @@ -352,11 +352,37 @@ uint32_t cli_state_set_tid(struct cli_state *cli, uint32_t tid) struct smbXcli_tcon *cli_state_save_tcon(struct cli_state *cli) { + /* + * Note. This used to make a deep copy of either + * cli->smb2.tcon or cli->smb1.tcon, but this leaves + * the original pointer in place which will then get + * TALLOC_FREE()'d when the new connection is made on + * this cli_state. + * + * As there may be pipes open on the old connection with + * talloc'ed state allocated using the tcon pointer as a + * parent we can't deep copy and then free this as that + * closes the open pipes. + * + * This call is used to temporarily swap out a tcon pointer + * to allow a new tcon on the same cli_state. + * + * Just return the raw pointer and set the old value to NULL. + * We know we MUST be calling cli_state_restore_tcon() below + * to restore before closing the session. + * + * See BUG: https://bugzilla.samba.org/show_bug.cgi?id=13992 + */ + struct smbXcli_tcon *tcon_ret = NULL; + if (smbXcli_conn_protocol(cli->conn) >= PROTOCOL_SMB2_02) { - return smbXcli_tcon_copy(cli, cli->smb2.tcon); + tcon_ret = cli->smb2.tcon; + cli->smb2.tcon = NULL; /* *Not* TALLOC_FREE(). */ } else { - return smbXcli_tcon_copy(cli, cli->smb1.tcon); + tcon_ret = cli->smb1.tcon; + cli->smb1.tcon = NULL; /* *Not* TALLOC_FREE(). */ } + return tcon_ret; } void cli_state_restore_tcon(struct cli_state *cli, struct smbXcli_tcon *tcon) diff --git a/source3/locking/share_mode_lock.c b/source3/locking/share_mode_lock.c index 1c4d3a42221..d4c27e4d654 100644 --- a/source3/locking/share_mode_lock.c +++ b/source3/locking/share_mode_lock.c @@ -2256,7 +2256,7 @@ static bool share_mode_entry_do( struct locking_tdb_data *ltdb = NULL; size_t idx; bool found = false; - bool modified; + bool modified = false; struct share_mode_entry e; uint8_t *e_ptr = NULL; bool have_share_modes; diff --git a/source3/modules/nfs4_acls.c b/source3/modules/nfs4_acls.c index 7f32e681694..c7808037a09 100644 --- a/source3/modules/nfs4_acls.c +++ b/source3/modules/nfs4_acls.c @@ -997,6 +997,7 @@ NTSTATUS smb_set_nt_acl_nfs4(vfs_handle_struct *handle, files_struct *fsp, } if (security_descriptor_with_ms_nfs(psd)) { + TALLOC_FREE(frame); return NT_STATUS_OK; } diff --git a/source3/modules/vfs_error_inject.c b/source3/modules/vfs_error_inject.c index 04880ffd5ab..d8731c29610 100644 --- a/source3/modules/vfs_error_inject.c +++ b/source3/modules/vfs_error_inject.c @@ -30,6 +30,7 @@ struct unix_error_map { { "ESTALE", ESTALE }, { "EBADF", EBADF }, { "EINTR", EINTR }, + { "EACCES", EACCES }, }; static int find_unix_error_from_string(const char *err_str) @@ -122,10 +123,46 @@ static int vfs_error_inject_openat(struct vfs_handle_struct *handle, return SMB_VFS_NEXT_OPENAT(handle, dirfsp, smb_fname, fsp, flags, mode); } +static int vfs_error_inject_unlinkat(struct vfs_handle_struct *handle, + struct files_struct *dirfsp, + const struct smb_filename *smb_fname, + int flags) +{ + struct smb_filename *parent_fname = NULL; + int error = inject_unix_error("unlinkat", handle); + int ret; + bool ok; + + if (error == 0) { + return SMB_VFS_NEXT_UNLINKAT(handle, dirfsp, smb_fname, flags); + } + + ok = parent_smb_fname(talloc_tos(), smb_fname, &parent_fname, NULL); + if (!ok) { + return -1; + } + + ret = SMB_VFS_STAT(handle->conn, parent_fname); + if (ret != 0) { + TALLOC_FREE(parent_fname); + return -1; + } + + if (parent_fname->st.st_ex_uid == get_current_uid(dirfsp->conn)) { + TALLOC_FREE(parent_fname); + return SMB_VFS_NEXT_UNLINKAT(handle, dirfsp, smb_fname, flags); + } + + TALLOC_FREE(parent_fname); + errno = error; + return -1; +} + static struct vfs_fn_pointers vfs_error_inject_fns = { .chdir_fn = vfs_error_inject_chdir, .pwrite_fn = vfs_error_inject_pwrite, .openat_fn = vfs_error_inject_openat, + .unlinkat_fn = vfs_error_inject_unlinkat, }; static_decl_vfs; diff --git a/source3/modules/vfs_virusfilter.c b/source3/modules/vfs_virusfilter.c index dc3f040363d..466aec920be 100644 --- a/source3/modules/vfs_virusfilter.c +++ b/source3/modules/vfs_virusfilter.c @@ -267,18 +267,21 @@ static int virusfilter_vfs_connect( infected_file_command = lp_parm_const_string( snum, "virusfilter", "infected file command", NULL); - config->infected_file_command = talloc_strdup(config, infected_file_command); - if (config->infected_file_command == NULL) { - DBG_ERR("virusfilter-vfs: out of memory!\n"); - return -1; + if (infected_file_command != NULL) { + config->infected_file_command = talloc_strdup(config, infected_file_command); + if (config->infected_file_command == NULL) { + DBG_ERR("virusfilter-vfs: out of memory!\n"); + return -1; + } } - scan_error_command = lp_parm_const_string( snum, "virusfilter", "scan error command", NULL); - config->scan_error_command = talloc_strdup(config, scan_error_command); - if (config->scan_error_command == NULL) { - DBG_ERR("virusfilter-vfs: out of memory!\n"); - return -1; + if (scan_error_command != NULL) { + config->scan_error_command = talloc_strdup(config, scan_error_command); + if (config->scan_error_command == NULL) { + DBG_ERR("virusfilter-vfs: out of memory!\n"); + return -1; + } } config->block_access_on_error = lp_parm_bool( @@ -290,10 +293,12 @@ static int virusfilter_vfs_connect( quarantine_dir = lp_parm_const_string( snum, "virusfilter", "quarantine directory", tmp ? tmp : "/tmp/.quarantine"); - config->quarantine_dir = talloc_strdup(config, quarantine_dir); - if (config->quarantine_dir == NULL) { - DBG_ERR("virusfilter-vfs: out of memory!\n"); - return -1; + if (quarantine_dir != NULL) { + config->quarantine_dir = talloc_strdup(config, quarantine_dir); + if (config->quarantine_dir == NULL) { + DBG_ERR("virusfilter-vfs: out of memory!\n"); + return -1; + } } if (tmp != config->quarantine_dir) { @@ -311,42 +316,50 @@ static int virusfilter_vfs_connect( quarantine_prefix = lp_parm_const_string( snum, "virusfilter", "quarantine prefix", VIRUSFILTER_DEFAULT_QUARANTINE_PREFIX); - config->quarantine_prefix = talloc_strdup(config, quarantine_prefix); - if (config->quarantine_prefix == NULL) { - DBG_ERR("virusfilter-vfs: out of memory!\n"); - return -1; + if (quarantine_prefix != NULL) { + config->quarantine_prefix = talloc_strdup(config, quarantine_prefix); + if (config->quarantine_prefix == NULL) { + DBG_ERR("virusfilter-vfs: out of memory!\n"); + return -1; + } } quarantine_suffix = lp_parm_const_string( snum, "virusfilter", "quarantine suffix", VIRUSFILTER_DEFAULT_QUARANTINE_SUFFIX); - config->quarantine_suffix = talloc_strdup(config, quarantine_suffix); - if (config->quarantine_suffix == NULL) { - DBG_ERR("virusfilter-vfs: out of memory!\n"); - return -1; + if (quarantine_suffix != NULL) { + config->quarantine_suffix = talloc_strdup(config, quarantine_suffix); + if (config->quarantine_suffix == NULL) { + DBG_ERR("virusfilter-vfs: out of memory!\n"); + return -1; + } } /* * Make sure prefixes and suffixes do not contain directory * delimiters */ - sret = strstr(config->quarantine_prefix, "/"); - if (sret != NULL) { - DBG_ERR("quarantine prefix must not contain directory " - "delimiter(s) such as '/' (%s replaced with %s)\n", - config->quarantine_prefix, - VIRUSFILTER_DEFAULT_QUARANTINE_PREFIX); - config->quarantine_prefix = - VIRUSFILTER_DEFAULT_QUARANTINE_PREFIX; - } - sret = strstr(config->quarantine_suffix, "/"); - if (sret != NULL) { - DBG_ERR("quarantine suffix must not contain directory " - "delimiter(s) such as '/' (%s replaced with %s)\n", - config->quarantine_suffix, - VIRUSFILTER_DEFAULT_QUARANTINE_SUFFIX); - config->quarantine_suffix = - VIRUSFILTER_DEFAULT_QUARANTINE_SUFFIX; + if (config->quarantine_prefix != NULL) { + sret = strstr(config->quarantine_prefix, "/"); + if (sret != NULL) { + DBG_ERR("quarantine prefix must not contain directory " + "delimiter(s) such as '/' (%s replaced with %s)\n", + config->quarantine_prefix, + VIRUSFILTER_DEFAULT_QUARANTINE_PREFIX); + config->quarantine_prefix = + VIRUSFILTER_DEFAULT_QUARANTINE_PREFIX; + } + } + if (config->quarantine_suffix != NULL) { + sret = strstr(config->quarantine_suffix, "/"); + if (sret != NULL) { + DBG_ERR("quarantine suffix must not contain directory " + "delimiter(s) such as '/' (%s replaced with %s)\n", + config->quarantine_suffix, + VIRUSFILTER_DEFAULT_QUARANTINE_SUFFIX); + config->quarantine_suffix = + VIRUSFILTER_DEFAULT_QUARANTINE_SUFFIX; + } } config->quarantine_keep_tree = lp_parm_bool( @@ -358,42 +371,50 @@ static int virusfilter_vfs_connect( rename_prefix = lp_parm_const_string( snum, "virusfilter", "rename prefix", VIRUSFILTER_DEFAULT_RENAME_PREFIX); - config->rename_prefix = talloc_strdup(config, rename_prefix); - if (config->rename_prefix == NULL) { - DBG_ERR("virusfilter-vfs: out of memory!\n"); - return -1; + if (rename_prefix != NULL) { + config->rename_prefix = talloc_strdup(config, rename_prefix); + if (config->rename_prefix == NULL) { + DBG_ERR("virusfilter-vfs: out of memory!\n"); + return -1; + } } rename_suffix = lp_parm_const_string( snum, "virusfilter", "rename suffix", VIRUSFILTER_DEFAULT_RENAME_SUFFIX); - config->rename_suffix = talloc_strdup(config, rename_suffix); - if (config->rename_suffix == NULL) { - DBG_ERR("virusfilter-vfs: out of memory!\n"); - return -1; + if (rename_suffix != NULL) { + config->rename_suffix = talloc_strdup(config, rename_suffix); + if (config->rename_suffix == NULL) { + DBG_ERR("virusfilter-vfs: out of memory!\n"); + return -1; + } } /* * Make sure prefixes and suffixes do not contain directory * delimiters */ - sret = strstr(config->rename_prefix, "/"); - if (sret != NULL) { - DBG_ERR("rename prefix must not contain directory " - "delimiter(s) such as '/' (%s replaced with %s)\n", - config->rename_prefix, - VIRUSFILTER_DEFAULT_RENAME_PREFIX); - config->rename_prefix = - VIRUSFILTER_DEFAULT_RENAME_PREFIX; - } - sret = strstr(config->rename_suffix, "/"); - if (sret != NULL) { - DBG_ERR("rename suffix must not contain directory " - "delimiter(s) such as '/' (%s replaced with %s)\n", - config->rename_suffix, - VIRUSFILTER_DEFAULT_RENAME_SUFFIX); - config->rename_suffix = - VIRUSFILTER_DEFAULT_RENAME_SUFFIX; + if (config->rename_prefix != NULL) { + sret = strstr(config->rename_prefix, "/"); + if (sret != NULL) { + DBG_ERR("rename prefix must not contain directory " + "delimiter(s) such as '/' (%s replaced with %s)\n", + config->rename_prefix, + VIRUSFILTER_DEFAULT_RENAME_PREFIX); + config->rename_prefix = + VIRUSFILTER_DEFAULT_RENAME_PREFIX; + } + } + if (config->rename_suffix != NULL) { + sret = strstr(config->rename_suffix, "/"); + if (sret != NULL) { + DBG_ERR("rename suffix must not contain directory " + "delimiter(s) such as '/' (%s replaced with %s)\n", + config->rename_suffix, + VIRUSFILTER_DEFAULT_RENAME_SUFFIX); + config->rename_suffix = + VIRUSFILTER_DEFAULT_RENAME_SUFFIX; + } } config->infected_open_errno = lp_parm_int( @@ -410,10 +431,12 @@ static int virusfilter_vfs_connect( socket_path = lp_parm_const_string( snum, "virusfilter", "socket path", NULL); - config->socket_path = talloc_strdup(config, socket_path); - if (config->socket_path == NULL) { - DBG_ERR("virusfilter-vfs: out of memory!\n"); - return -1; + if (socket_path != NULL) { + config->socket_path = talloc_strdup(config, socket_path); + if (config->socket_path == NULL) { + DBG_ERR("virusfilter-vfs: out of memory!\n"); + return -1; + } } /* canonicalize socket_path */ diff --git a/source3/script/tests/test_force_user_unlink.sh b/source3/script/tests/test_force_user_unlink.sh new file mode 100755 index 00000000000..86076535497 --- /dev/null +++ b/source3/script/tests/test_force_user_unlink.sh @@ -0,0 +1,40 @@ +#!/bin/sh +# +# Test unlink on share with "force user" +# +# Copyright (C) 2021 Ralph Boehme + +incdir=$(dirname $0)/../../../testprogs/blackbox +. $incdir/subunit.sh +. $incdir/common_test_fns.inc + +smbclient="$BINDIR/smbclient" +error_inject_conf=$(dirname ${SMB_CONF_PATH})/error_inject.conf +failed=0 + +test_forced_user_can_delete() { + out=$($smbclient -U $DOMAIN/$USERNAME%$PASSWORD //$SERVER_IP/force_user_error_inject -c "rm dir/file") + if [ $? -ne 0 ] ; then + echo $out + return 1 + fi + tmp=$(echo $out | grep NT_STATUS_ ) + if [ $? -eq 0 ] ; then + return 1 + fi + return 0 +} + +echo "error_inject:unlinkat = EACCES" > ${error_inject_conf} + +$smbclient -U $DOMAIN/$USERNAME%$PASSWORD //$SERVER_IP/force_user_error_inject -c "mkdir dir" || failed=`expr $failed + 1` +$smbclient -U $DOMAIN/$USERNAME%$PASSWORD //$SERVER_IP/force_user_error_inject -c "put WHATSNEW.txt dir/file" || failed=`expr $failed + 1` + +testit "test_forced_user_can_delete" test_forced_user_can_delete || failed=`expr $failed + 1` + +rm ${error_inject_conf} + +# Clean up after ourselves. +$smbclient -U $DOMAIN/$USERNAME%$PASSWORD //$SERVER_IP/force_user_error_inject -c "del dir/file; rmdir dir" + +testok $0 $failed diff --git a/source3/script/tests/test_net_rpc_share_allowedusers.sh b/source3/script/tests/test_net_rpc_share_allowedusers.sh index 5dd382d4c51..d22c7580681 100755 --- a/source3/script/tests/test_net_rpc_share_allowedusers.sh +++ b/source3/script/tests/test_net_rpc_share_allowedusers.sh @@ -26,5 +26,25 @@ testit_grep "net_rpc_share_allowedusers" '^print\$$' $net usersidlist | $VALGRIN testit_grep "net_rpc_share_allowedusers" '^print\$$' $net usersidlist | $VALGRIND $net rpc share allowedusers -S$SERVER -U$USERNAME%$PASSWORD $ADDARGS - 'print$' || failed=`expr $failed + 1` # Check user "user1" is allowed to read share "tmp". testit_grep "net_rpc_share_allowedusers" '^ user1$' $net usersidlist | $VALGRIND $net rpc share allowedusers -S$SERVER -U$USERNAME%$PASSWORD $ADDARGS || failed=`expr $failed + 1` +# +# Subtle extra test for bug https://bugzilla.samba.org/show_bug.cgi?id=13992 +# +# '^ user1$' must appear MORE THAN ONCE, as it can read more than one +# share. The previous test found user1, but only once as the bug only +# allows reading the security descriptor for one share, and we were +# unlucky that the first share security descriptor returned allows +# user1 to read from it. +# +subunit_start_test "net_rpc_share_allowedusers" +multi_userout=`$net usersidlist | $VALGRIND $net rpc share allowedusers -S$SERVER -U$USERNAME%$PASSWORD $ADDARGS` +num_matches=`echo "$multi_userout" | grep -c '^ user1$'` +if [ "$num_matches" -gt "1" ] +then + subunit_pass_test "net_rpc_share_allowedusers" +else + echo "net_rpc_share_allowedusers only found $num_matches shares readable by user1. Should be greater than one.\n" + failed=`expr $failed + 1` + echo "$multi_userout" | subunit_fail_test "net_rpc_share_allowedusers" +fi testok $0 $failed diff --git a/source3/script/tests/test_winbind_ignore_domains.sh b/source3/script/tests/test_winbind_ignore_domains.sh new file mode 100755 index 00000000000..adce8abb09c --- /dev/null +++ b/source3/script/tests/test_winbind_ignore_domains.sh @@ -0,0 +1,104 @@ +#!/bin/sh + +incdir=`dirname $0`/../../../testprogs/blackbox +. $incdir/subunit.sh +. $incdir/common_test_fns.inc + +failed=0 + +smbclient="$BINDIR/smbclient" +smbcontrol="$BINDIR/smbcontrol" +ldbmodify="$BINDIR/ldbmodify" +ldbsearch="$BINDIR/ldbsearch" +wbinfo="$BINDIR/wbinfo" +global_inject_conf=$(dirname $SMB_CONF_PATH)/global_inject.conf +SERVER_FQDN=$(echo "$SERVER.$REALM" | awk '{print tolower($0)}') + +TRUST_BASE_DN=$($ldbsearch -H ldap://$TRUST_SERVER -b "" -s base defaultNamingContext | awk '/^defaultNamingContext/ {print $2}') +if [ $? -ne 0 ] ; then + echo "Could not find trusted base DN" | subunit_fail_test "test_idmap_ad" + exit 1 +fi + +# +# Add POSIX ids to trusted domain +# +add_posix_ids() { +cat <<EOF | $ldbmodify -H ldap://$TRUST_SERVER \ + -U "$TRUST_DOMAIN\Administrator%$TRUST_PASSWORD" +dn: CN=Administrator,CN=Users,$TRUST_BASE_DN +changetype: modify +add: uidNumber +uidNumber: 2500000 +EOF + +cat <<EOF | $ldbmodify -H ldap://$TRUST_SERVER \ + -U "$TRUST_DOMAIN\Administrator%$TRUST_PASSWORD" +dn: CN=Domain Users,CN=Users,$TRUST_BASE_DN +changetype: modify +add: gidNumber +gidNumber: 2500001 +EOF + +cat <<EOF | $ldbmodify -H ldap://$TRUST_SERVER \ + -U "$TRUST_DOMAIN\Administrator%$TRUST_PASSWORD" +dn: CN=Domain Admins,CN=Users,$TRUST_BASE_DN +changetype: modify +add: gidNumber +gidNumber: 2500002 +EOF +} + +# +# Remove POSIX ids from trusted domain +# +remove_posix_ids() { +cat <<EOF | $ldbmodify -H ldap://$TRUST_SERVER \ + -U "$TRUST_DOMAIN\Administrator%$TRUST_PASSWORD" +dn: CN=Administrator,CN=Users,$TRUST_BASE_DN +changetype: modify +delete: uidNumber +uidNumber: 2500000 +EOF + +cat <<EOF | $ldbmodify -H ldap://$TRUST_SERVER \ + -U "$TRUST_DOMAIN\Administrator%$TRUST_PASSWORD" +dn: CN=Domain Users,CN=Users,$TRUST_BASE_DN +changetype: modify +delete: gidNumber +gidNumber: 2500001 +EOF + +cat <<EOF | $ldbmodify -H ldap://$TRUST_SERVER \ + -U "$TRUST_DOMAIN\Administrator%$TRUST_PASSWORD" +dn: CN=Domain Admins,CN=Users,$TRUST_BASE_DN +changetype: modify +delete: gidNumber +gidNumber: 2500002 +EOF +} + +add_posix_ids + +echo "" > $global_inject_conf +$smbcontrol winbindd reload-config +$wbinfo -p + +test_smbclient "test_winbind_ignore_domains_ok_ntlm_ip" "ls" "//$SERVER_IP/tmp" -U $TRUST_DOMAIN/$TRUST_USERNAME%$TRUST_PASSWORD || failed=`expr $failed + 1` +test_smbclient "test_winbind_ignore_domains_ok_ntlm_fqdn" "ls" "//$SERVER_FQDN/tmp" -U $TRUST_DOMAIN/$TRUST_USERNAME%$TRUST_PASSWORD || failed=`expr $failed + 1` +test_smbclient "test_winbind_ignore_domains_ok_krb5" "ls" "//$SERVER_FQDN/tmp" -U $TRUST_USERNAME@$TRUST_REALM%$TRUST_PASSWORD -k || failed=`expr $failed + 1` + +echo "winbind:ignore domains = $TRUST_DOMAIN" > $global_inject_conf +$smbcontrol winbindd reload-config +$wbinfo -p + +test_smbclient_expect_failure "test_winbind_ignore_domains_fail_ntlm_ip" "ls" "//$SERVER_IP/tmp" -U $TRUST_DOMAIN/$TRUST_USERNAME%$TRUST_PASSWORD || failed=`expr $failed + 1` +test_smbclient_expect_failure "test_winbind_ignore_domains_fail_ntlm_fqdn" "ls" "//$SERVER_FQDN/tmp" -U $TRUST_DOMAIN/$TRUST_USERNAME%$TRUST_PASSWORD || failed=`expr $failed + 1` +test_smbclient_expect_failure "test_winbind_ignore_domains_fail_krb5" "ls" "//$SERVER_FQDN/tmp" -U $TRUST_USERNAME@$TRUST_REALM%$TRUST_PASSWORD -k || failed=`expr $failed + 1` + +echo "" > $global_inject_conf +$smbcontrol winbindd reload-config +$wbinfo -p +remove_posix_ids + +testok $0 $failed diff --git a/source3/selftest/tests.py b/source3/selftest/tests.py index 27dc7587b17..47e914b1009 100755 --- a/source3/selftest/tests.py +++ b/source3/selftest/tests.py @@ -487,13 +487,13 @@ for env in ["fileserver"]: [os.path.join(samba3srcdir, "script/tests/test_smbclient_tarmode.pl"), '-n', '$SERVER', '-i', '$SERVER_IP', '-s', 'tarmode2', '-u', '$USERNAME', '-p', '$PASSWORD', '-l', '$LOCAL_PATH/tarmode2', - '-d', '$PREFIX', '-b', smbclient3, + '-d', 'smbclient_tar.NT1', '-b', smbclient3, '--subunit', '--', configuration, '-mNT1']) plantestsuite("samba3.blackbox.smbclient_tar.SMB3", env, [os.path.join(samba3srcdir, "script/tests/test_smbclient_tarmode.pl"), '-n', '$SERVER', '-i', '$SERVER_IP', '-s', 'tarmode2', '-u', '$USERNAME', '-p', '$PASSWORD', '-l', '$LOCAL_PATH/tarmode2', - '-d', '$PREFIX', '-b', smbclient3, + '-d', 'smbclient_tar.SMB3', '-b', smbclient3, '--subunit', '--', configuration, '-mSMB3']) for env in ["fileserver:local"]: @@ -991,6 +991,9 @@ plantestsuite("samba3.blackbox.smbd_no_krb5", "ad_member:local", [os.path.join(samba3srcdir, "script/tests/test_smbd_no_krb5.sh"), smbclient3, '$SERVER', "$DC_USERNAME", "$DC_PASSWORD", "$PREFIX"]) +plantestsuite("samba3.blackbox.winbind_ignore_domain", "ad_member_idmap_ad:local", + [os.path.join(samba3srcdir, "script/tests/test_winbind_ignore_domains.sh")]) + plantestsuite("samba3.blackbox.durable_v2_delay", "simpleserver:local", [os.path.join(samba3srcdir, "script/tests/test_durable_handle_reconnect.sh")]) @@ -1122,6 +1125,11 @@ plantestsuite( "", "-b $PREFIX/clusteredmember_smb1/unclists/tmp.txt -N 5 -o 10"]) +plantestsuite("samba3.blackbox.force-user-unlink", + "maptoguest:local", + [os.path.join(samba3srcdir, + "script/tests/test_force_user_unlink.sh")]) + def planclusteredmembertestsuite(tname, prefix): '''Define a clustered test for the clusteredmember environment''' diff --git a/source3/smbd/close.c b/source3/smbd/close.c index 9974877edc2..43762555b35 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -341,21 +341,13 @@ static NTSTATUS close_remove_share_mode(files_struct *fsp, if (fsp->fsp_flags.initial_delete_on_close && !is_delete_on_close_set(lck, fsp->name_hash)) { - struct auth_session_info *session_info = NULL; - /* Initial delete on close was set and no one else * wrote a real delete on close. */ - status = smbXsrv_session_info_lookup(conn->sconn->client, - fsp->vuid, - &session_info); - if (!NT_STATUS_IS_OK(status)) { - return NT_STATUS_INTERNAL_ERROR; - } fsp->fsp_flags.delete_on_close = true; set_delete_on_close_lck(fsp, lck, - session_info->security_token, - session_info->unix_token); + fsp->conn->session_info->security_token, + fsp->conn->session_info->unix_token); } delete_file = is_delete_on_close_set(lck, fsp->name_hash) && @@ -1176,24 +1168,15 @@ static NTSTATUS close_directory(struct smb_request *req, files_struct *fsp, } if (fsp->fsp_flags.initial_delete_on_close) { - struct auth_session_info *session_info = NULL; - /* Initial delete on close was set - for * directories we don't care if anyone else * wrote a real delete on close. */ - status = smbXsrv_session_info_lookup(fsp->conn->sconn->client, - fsp->vuid, - &session_info); - if (!NT_STATUS_IS_OK(status)) { - return NT_STATUS_INTERNAL_ERROR; - } - send_stat_cache_delete_message(fsp->conn->sconn->msg_ctx, fsp->fsp_name->base_name); set_delete_on_close_lck(fsp, lck, - session_info->security_token, - session_info->unix_token); + fsp->conn->session_info->security_token, + fsp->conn->session_info->unix_token); fsp->fsp_flags.delete_on_close = true; } diff --git a/source3/smbd/conn_idle.c b/source3/smbd/conn_idle.c index ca697383877..56a6ef896fb 100644 --- a/source3/smbd/conn_idle.c +++ b/source3/smbd/conn_idle.c @@ -273,5 +273,13 @@ static void conn_force_tdis_done(struct tevent_req *req) * uid in the meantime. Ensure we're still root. */ change_to_root_user(); - reload_services(sconn, conn_snum_used, true); + /* + * Use 'false' in the last parameter (test) to force + * a full reload of services. Prevents + * reload_services caching the fact it's + * been called multiple times in a row. + * See BUG: https://bugzilla.samba.org/show_bug.cgi?id=14604 + * for details. + */ + reload_services(sconn, conn_snum_used, false); } diff --git a/source3/smbd/pysmbd.c b/source3/smbd/pysmbd.c index dd4a70ca256..2081a75d52c 100644 --- a/source3/smbd/pysmbd.c +++ b/source3/smbd/pysmbd.c @@ -1144,9 +1144,12 @@ static PyObject *py_smbd_create_file(PyObject *self, PyObject *args, PyObject *k if (!NT_STATUS_IS_OK(status)) { DBG_ERR("init_files_struct failed: %s\n", nt_errstr(status)); + } else if (fsp != NULL) { + SMB_VFS_CLOSE(fsp); } TALLOC_FREE(frame); + PyErr_NTSTATUS_NOT_OK_RAISE(status); Py_RETURN_NONE; } diff --git a/source3/torture/test_smb2.c b/source3/torture/test_smb2.c index d5023d88cfd..3e25a562bd6 100644 --- a/source3/torture/test_smb2.c +++ b/source3/torture/test_smb2.c @@ -188,11 +188,11 @@ bool run_smb2_basic(int dummy) cli->timeout, cli->smb2.session, cli->smb2.tcon); + cli_state_restore_tcon(cli, saved_tcon); if (!NT_STATUS_IS_OK(status)) { printf("smb2cli_tdis returned %s\n", nt_errstr(status)); return false; } - cli_state_restore_tcon(cli, saved_tcon); status = smb2cli_tdis(cli->conn, cli->timeout, diff --git a/source3/torture/torture.c b/source3/torture/torture.c index 2a3133373e9..5e263797730 100644 --- a/source3/torture/torture.c +++ b/source3/torture/torture.c @@ -1343,6 +1343,7 @@ static bool run_tcon_test(int dummy) if (!NT_STATUS_IS_OK(status)) { printf("%s refused 2nd tree connect (%s)\n", host, nt_errstr(status)); + cli_state_restore_tcon(cli, orig_tcon); cli_shutdown(cli); return False; } @@ -1395,6 +1396,8 @@ static bool run_tcon_test(int dummy) status = cli_close(cli, fnum1); if (!NT_STATUS_IS_OK(status)) { printf("close failed (%s)\n", nt_errstr(status)); + cli_state_restore_tcon(cli, orig_tcon); + cli_shutdown(cli); return False; } @@ -1403,6 +1406,8 @@ static bool run_tcon_test(int dummy) status = cli_tdis(cli); if (!NT_STATUS_IS_OK(status)) { printf("secondary tdis failed (%s)\n", nt_errstr(status)); + cli_state_restore_tcon(cli, orig_tcon); + cli_shutdown(cli); return False; } @@ -11714,7 +11719,7 @@ static bool run_uid_regression_test(int dummy) int16_t old_vuid; int32_t old_cnum; bool correct = True; - struct smbXcli_tcon *orig_tcon = NULL; + struct smbXcli_tcon *tcon_copy = NULL; NTSTATUS status; printf("starting uid regression test\n"); @@ -11755,8 +11760,20 @@ static bool run_uid_regression_test(int dummy) } old_cnum = cli_state_get_tid(cli); - orig_tcon = cli_state_save_tcon(cli); - if (orig_tcon == NULL) { + /* + * This is an SMB1-only test. + * Copy the tcon, not "save/restore". + * + * In SMB1 the cli_tdis() below frees + * cli->smb1.tcon so we need a copy + * of the struct to put back for the + * second tdis call with invalid vuid. + * + * This is a test-only hack. Real client code + * uses cli_state_save_tcon()/cli_state_restore_tcon(). + */ + tcon_copy = smbXcli_tcon_copy(cli, cli->smb1.tcon); + if (tcon_copy == NULL) { correct = false; goto out; } @@ -11772,11 +11789,11 @@ static bool run_uid_regression_test(int dummy) } else { d_printf("First tdis failed (%s)\n", nt_errstr(status)); correct = false; - cli_state_restore_tcon(cli, orig_tcon); + cli->smb1.tcon = tcon_copy; goto out; } - cli_state_restore_tcon(cli, orig_tcon); + cli->smb1.tcon = tcon_copy; cli_state_set_uid(cli, old_vuid); cli_state_set_tid(cli, old_cnum); diff --git a/source3/winbindd/winbindd.c b/source3/winbindd/winbindd.c index 1e08237905a..bc5aec92385 100644 --- a/source3/winbindd/winbindd.c +++ b/source3/winbindd/winbindd.c @@ -102,7 +102,7 @@ struct imessaging_context *winbind_imessaging_context(void) /* Reload configuration */ -static bool reload_services_file(const char *lfile) +bool winbindd_reload_services_file(const char *lfile) { const struct loadparm_substitution *lp_sub = loadparm_s3_global_substitution(); @@ -117,15 +117,15 @@ static bool reload_services_file(const char *lfile) TALLOC_FREE(fname); } + reopen_logs(); + ret = lp_load_global(get_dyn_CONFIGFILE()); + /* if this is a child, restore the logfile to the special name - <domain>, idmap, etc. */ if (lfile && *lfile) { lp_set_logfile(lfile); } - reopen_logs(); - ret = lp_load_global(get_dyn_CONFIGFILE()); - reopen_logs(); load_interfaces(); winbindd_setup_max_fds(); @@ -156,7 +156,7 @@ static void winbindd_status(void) /* Flush client cache */ -static void flush_caches(void) +void winbindd_flush_caches(void) { /* We need to invalidate cached user list entries on a SIGHUP otherwise cached access denied errors due to restrict anonymous @@ -363,7 +363,7 @@ static void winbindd_sig_hup_handler(struct tevent_context *ev, DEBUG(1,("Reloading services after SIGHUP\n")); flush_caches_noinit(); - reload_services_file(file); + winbindd_reload_services_file(file); } bool winbindd_setup_sig_hup_handler(const char *lfile) @@ -447,18 +447,6 @@ static bool winbindd_setup_sig_usr2_handler(void) return true; } -/* React on 'smbcontrol winbindd reload-config' in the same way as on SIGHUP*/ -static void msg_reload_services(struct messaging_context *msg, - void *private_data, - uint32_t msg_type, - struct server_id server_id, - DATA_BLOB *data) -{ - /* Flush various caches */ - flush_caches(); - reload_services_file((const char *) private_data); -} - /* React on 'smbcontrol winbindd shutdown' in the same way as on SIGTERM*/ static void msg_shutdown(struct messaging_context *msg, void *private_data, @@ -1420,7 +1408,8 @@ static void winbindd_register_handlers(struct messaging_context *msg_ctx, /* React on 'smbcontrol winbindd reload-config' in the same way as to SIGHUP signal */ messaging_register(msg_ctx, NULL, - MSG_SMB_CONF_UPDATED, msg_reload_services); + MSG_SMB_CONF_UPDATED, + winbindd_msg_reload_services_parent); messaging_register(msg_ctx, NULL, MSG_SHUTDOWN, msg_shutdown); @@ -1811,7 +1800,7 @@ int main(int argc, const char **argv) exit(1); } - if (!reload_services_file(NULL)) { + if (!winbindd_reload_services_file(NULL)) { DEBUG(0, ("error opening config file\n")); exit(1); } diff --git a/source3/winbindd/winbindd_dual.c b/source3/winbindd/winbindd_dual.c index 47efe988d65..b1c86b2979c 100644 --- a/source3/winbindd/winbindd_dual.c +++ b/source3/winbindd/winbindd_dual.c @@ -927,6 +927,39 @@ void winbind_disconnect_dc_parent(struct messaging_context *msg_ctx, forall_children(winbind_msg_relay_fn, &state); } +static void winbindd_msg_reload_services_child(struct messaging_context *msg, + void *private_data, + uint32_t msg_type, + struct server_id server_id, + DATA_BLOB *data) +{ + DBG_DEBUG("Got reload-config message\n"); + winbindd_reload_services_file((const char *)private_data); +} + +/* React on 'smbcontrol winbindd reload-config' in the same way as on SIGHUP*/ +void winbindd_msg_reload_services_parent(struct messaging_context *msg, + void *private_data, + uint32_t msg_type, + struct server_id server_id, + DATA_BLOB *data) +{ + struct winbind_msg_relay_state state = { + .msg_ctx = msg, + .msg_type = msg_type, + .data = data, + }; + + DBG_DEBUG("Got reload-config message\n"); + + /* Flush various caches */ + winbindd_flush_caches(); + + winbindd_reload_services_file((const char *)private_data); + + forall_children(winbind_msg_relay_fn, &state); +} + /* Set our domains as offline and forward the offline message to our children. */ struct winbind_msg_on_offline_state { @@ -1760,6 +1793,10 @@ static bool fork_domain_child(struct winbindd_child *child) messaging_register(global_messaging_context(), NULL, MSG_WINBIND_DISCONNECT_DC, winbind_msg_disconnect_dc); + messaging_register(global_messaging_context(), + override_logfile ? NULL : child->logfilename, + MSG_SMB_CONF_UPDATED, + winbindd_msg_reload_services_child); primary_domain = find_our_domain(); diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index b5850a33b0f..c49033b375d 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -2403,6 +2403,15 @@ process_result: goto done; } + if (!is_allowed_domain(info3->base.logon_domain.string)) { + DBG_NOTICE("Authentication failed for user [%s] " + "from firewalled domain [%s]\n", + info3->base.account_name.string, + info3->base.logon_domain.string); + result = NT_STATUS_AUTHENTICATION_FIREWALL_FAILED; + goto done; + } + result = append_auth_data(state->mem_ctx, state->response, state->request->flags, validation_level, @@ -2756,6 +2765,16 @@ enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain, goto done; } + if (!is_allowed_domain(info3->base.logon_domain.string)) { + DBG_NOTICE("Authentication failed for user [%s] " + "from firewalled domain [%s]\n", + info3->base.account_name.string, + info3->base.logon_domain.string); + state->response->data.auth.authoritative = true; + result = NT_STATUS_AUTHENTICATION_FIREWALL_FAILED; + goto done; + } + result = append_auth_data(state->mem_ctx, state->response, state->request->flags, validation_level, @@ -2824,6 +2843,14 @@ enum winbindd_result winbindd_dual_pam_chauthtok(struct winbindd_domain *contact goto done; } + if (!is_allowed_domain(domain)) { + DBG_NOTICE("Authentication failed for user [%s] " + "from firewalled domain [%s]\n", + user, domain); + result = NT_STATUS_AUTHENTICATION_FIREWALL_FAILED; + goto done; + } + /* Change password */ oldpass = state->request->data.chauthtok.oldpass; @@ -3085,6 +3112,15 @@ enum winbindd_result winbindd_dual_pam_chng_pswd_auth_crap(struct winbindd_domai fstrcpy(domain,lp_workgroup()); } + if (!is_allowed_domain(domain)) { + DBG_NOTICE("Authentication failed for user [%s] " + "from firewalled domain [%s]\n", + state->request->data.chng_pswd_auth_crap.user, + domain); + result = NT_STATUS_AUTHENTICATION_FIREWALL_FAILED; + goto done; + } + if(!*user) { fstrcpy(user, state->request->data.chng_pswd_auth_crap.user); } @@ -3287,6 +3323,14 @@ NTSTATUS winbindd_pam_auth_pac_verify(struct winbindd_cli_state *state, return result; } + if (!is_allowed_domain(info6->base.logon_domain.string)) { + DBG_NOTICE("Authentication failed for user [%s] " + "from firewalled domain [%s]\n", + info6->base.account_name.string, + info6->base.logon_domain.string); + return NT_STATUS_AUTHENTICATION_FIREWALL_FAILED; + } + result = map_info6_to_validation(state->mem_ctx, info6, &validation_level, diff --git a/source3/winbindd/winbindd_proto.h b/source3/winbindd/winbindd_proto.h index 2a829b0171a..6d4ffa726f1 100644 --- a/source3/winbindd/winbindd_proto.h +++ b/source3/winbindd/winbindd_proto.h @@ -31,6 +31,8 @@ bool winbindd_setup_sig_hup_handler(const char *lfile); bool winbindd_use_idmap_cache(void); bool winbindd_use_cache(void); char *get_winbind_priv_pipe_dir(void); +void winbindd_flush_caches(void); +bool winbindd_reload_services_file(const char *lfile); /* The following definitions come from winbindd/winbindd_ads.c */ @@ -341,6 +343,11 @@ void winbind_msg_ip_dropped_parent(struct messaging_context *msg_ctx, uint32_t msg_type, struct server_id server_id, DATA_BLOB *data); +void winbindd_msg_reload_services_parent(struct messaging_context *msg, + void *private_data, + uint32_t msg_type, + struct server_id server_id, + DATA_BLOB *data); NTSTATUS winbindd_reinit_after_fork(const struct winbindd_child *myself, const char *logfilename); struct winbindd_domain *wb_child_domain(void); diff --git a/source3/winbindd/winbindd_util.c b/source3/winbindd/winbindd_util.c index c2f02b74211..bec706f87de 100644 --- a/source3/winbindd/winbindd_util.c +++ b/source3/winbindd/winbindd_util.c @@ -123,8 +123,6 @@ static NTSTATUS add_trusted_domain(const char *domain_name, struct winbindd_domain **_d) { struct winbindd_domain *domain = NULL; - const char **ignored_domains = NULL; - const char **dom = NULL; int role = lp_server_role(); struct dom_sid_buf buf; @@ -133,12 +131,8 @@ static NTSTATUS add_trusted_domain(const char *domain_name, return NT_STATUS_INVALID_PARAMETER; } - ignored_domains = lp_parm_string_list(-1, "winbind", "ignore domains", NULL); - for (dom=ignored_domains; dom && *dom; dom++) { - if (gen_fnmatch(*dom, domain_name) == 0) { - DEBUG(2,("Ignoring domain '%s'\n", domain_name)); - return NT_STATUS_NO_SUCH_DOMAIN; - } + if (!is_allowed_domain(domain_name)) { + return NT_STATUS_NO_SUCH_DOMAIN; } /* diff --git a/source3/wscript b/source3/wscript index 9920432a360..563854c1d23 100644 --- a/source3/wscript +++ b/source3/wscript @@ -1244,7 +1244,7 @@ err: int main(void) { - uint64_t *hint, get_hint; + uint64_t hint, get_hint; int fd; fd = open(DATA, O_RDONLY | O_CREAT | O_EXCL); @@ -1252,8 +1252,8 @@ int main(void) goto err; } - *hint = RWH_WRITE_LIFE_SHORT; - int ret = fcntl(fd, F_SET_RW_HINT, hint); + hint = RWH_WRITE_LIFE_SHORT; + int ret = fcntl(fd, F_SET_RW_HINT, &hint); if (ret == -1) { goto err; } @@ -1267,8 +1267,8 @@ int main(void) goto err; } - *hint = RWH_WRITE_LIFE_EXTREME; - ret = fcntl(fd, F_SET_FILE_RW_HINT, hint); + hint = RWH_WRITE_LIFE_EXTREME; + ret = fcntl(fd, F_SET_FILE_RW_HINT, &hint); if (ret == -1) { goto err; } diff --git a/source4/heimdal/lib/krb5/store.c b/source4/heimdal/lib/krb5/store.c index 17de78e9e74..31afb23c983 100644 --- a/source4/heimdal/lib/krb5/store.c +++ b/source4/heimdal/lib/krb5/store.c @@ -270,6 +270,8 @@ krb5_storage_get_eof_code(krb5_storage *sp) KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL krb5_storage_free(krb5_storage *sp) { + if (sp == NULL) + return 0; if(sp->free) (*sp->free)(sp); free(sp->data); diff --git a/source4/selftest/provisions/release-4-5-0-pre1/expected-dbcheck-link-output-lost-deleted-user3.txt b/source4/selftest/provisions/release-4-5-0-pre1/expected-dbcheck-link-output-lost-deleted-user3.txt index d014bfacae2..ea9b630df08 100644 --- a/source4/selftest/provisions/release-4-5-0-pre1/expected-dbcheck-link-output-lost-deleted-user3.txt +++ b/source4/selftest/provisions/release-4-5-0-pre1/expected-dbcheck-link-output-lost-deleted-user3.txt @@ -1,19 +1,19 @@ Checking 232 objects -SKIPING: object CN=fred\0ADEL:2301a64c-1122-5566-851e-12d4a711cfb4,OU=removed,DC=release-4-5-0-pre1,DC=samba,DC=corp is an expired tombstone +SKIPPING: object CN=fred\0ADEL:2301a64c-1122-5566-851e-12d4a711cfb4,OU=removed,DC=release-4-5-0-pre1,DC=samba,DC=corp is an expired tombstone isDeleted: attid=0x00020030 version=1 invocation=4e4496a3-7fb8-4f97-8a33-d238db8b5e2d usn=3746 (local=3746) at Wed Jun 29 04:36:39 2016 -SKIPING: object CN=fred\0ADEL:2301a64c-5b42-4ca8-851e-12d4a711cfb4,CN=Deleted Objects,DC=release-4-5-0-pre1,DC=samba,DC=corp is an expired tombstone +SKIPPING: object CN=fred\0ADEL:2301a64c-5b42-4ca8-851e-12d4a711cfb4,CN=Deleted Objects,DC=release-4-5-0-pre1,DC=samba,DC=corp is an expired tombstone isDeleted: attid=0x00020030 version=1 invocation=4e4496a3-7fb8-4f97-8a33-d238db8b5e2d usn=3746 (local=3746) at Wed Jun 29 04:36:39 2016 -SKIPING: object CN=dsg\0ADEL:6d66d0ef-cad7-4e5d-b1b6-4a233a21c269,CN=Deleted Objects,DC=release-4-5-0-pre1,DC=samba,DC=corp is an expired tombstone +SKIPPING: object CN=dsg\0ADEL:6d66d0ef-cad7-4e5d-b1b6-4a233a21c269,CN=Deleted Objects,DC=release-4-5-0-pre1,DC=samba,DC=corp is an expired tombstone isDeleted: attid=0x00020030 version=1 invocation=4e4496a3-7fb8-4f97-8a33-d238db8b5e2d usn=3734 (local=3734) at Wed Jun 29 04:34:32 2016 -SKIPING: object CN=udg\0ADEL:7cff5537-51b1-4d26-a295-0225dbea8525,CN=Deleted Objects,DC=release-4-5-0-pre1,DC=samba,DC=corp is an expired tombstone +SKIPPING: object CN=udg\0ADEL:7cff5537-51b1-4d26-a295-0225dbea8525,CN=Deleted Objects,DC=release-4-5-0-pre1,DC=samba,DC=corp is an expired tombstone isDeleted: attid=0x00020030 version=1 invocation=4e4496a3-7fb8-4f97-8a33-d238db8b5e2d usn=3739 (local=3739) at Wed Jun 29 04:34:34 2016 -SKIPING: object CN=usg\0ADEL:d012e8f5-a4bd-40ea-a2a1-68ff2508847d,CN=Deleted Objects,DC=release-4-5-0-pre1,DC=samba,DC=corp is an expired tombstone +SKIPPING: object CN=usg\0ADEL:d012e8f5-a4bd-40ea-a2a1-68ff2508847d,CN=Deleted Objects,DC=release-4-5-0-pre1,DC=samba,DC=corp is an expired tombstone isDeleted: attid=0x00020030 version=1 invocation=4e4496a3-7fb8-4f97-8a33-d238db8b5e2d usn=3736 (local=3736) at Wed Jun 29 04:34:33 2016 -SKIPING: object CN=ddg\0ADEL:fb8c2fe3-5448-43de-99f9-e1d3b9357cfc,CN=Deleted Objects,DC=release-4-5-0-pre1,DC=samba,DC=corp is an expired tombstone +SKIPPING: object CN=ddg\0ADEL:fb8c2fe3-5448-43de-99f9-e1d3b9357cfc,CN=Deleted Objects,DC=release-4-5-0-pre1,DC=samba,DC=corp is an expired tombstone isDeleted: attid=0x00020030 version=1 invocation=4e4496a3-7fb8-4f97-8a33-d238db8b5e2d usn=3737 (local=3737) at Wed Jun 29 04:34:34 2016 -SKIPING: object CN=gsg\0ADEL:91aa85cc-fc19-4b8c-9fc7-aaba425439c7,CN=Deleted Objects,DC=release-4-5-0-pre1,DC=samba,DC=corp is an expired tombstone +SKIPPING: object CN=gsg\0ADEL:91aa85cc-fc19-4b8c-9fc7-aaba425439c7,CN=Deleted Objects,DC=release-4-5-0-pre1,DC=samba,DC=corp is an expired tombstone isDeleted: attid=0x00020030 version=1 invocation=4e4496a3-7fb8-4f97-8a33-d238db8b5e2d usn=3735 (local=3735) at Wed Jun 29 04:34:33 2016 -SKIPING: object CN=gdg\0ADEL:e0f581e7-14ee-4fc2-839c-8f46f581c72a,CN=Deleted Objects,DC=release-4-5-0-pre1,DC=samba,DC=corp is an expired tombstone +SKIPPING: object CN=gdg\0ADEL:e0f581e7-14ee-4fc2-839c-8f46f581c72a,CN=Deleted Objects,DC=release-4-5-0-pre1,DC=samba,DC=corp is an expired tombstone isDeleted: attid=0x00020030 version=1 invocation=4e4496a3-7fb8-4f97-8a33-d238db8b5e2d usn=3738 (local=3738) at Wed Jun 29 04:34:34 2016 NOTICE: found 8 expired tombstones, 'samba' will remove them daily, 'samba-tool domain tombstones expunge' would do that immediately. Checked 232 objects (0 errors) diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py index 3a903a7eee0..258c9122edc 100755 --- a/source4/selftest/tests.py +++ b/source4/selftest/tests.py @@ -561,7 +561,8 @@ if have_gnutls_crypto_policies: plantestsuite("samba3.wbinfo_simple.fips.%s" % t, "ad_member_fips:local", [os.path.join(srcdir(), "nsswitch/tests/test_wbinfo_simple.sh"), t]) plantestsuite("samba4.wbinfo_name_lookup.fips", "ad_member_fips", [os.path.join(srcdir(), "nsswitch/tests/test_wbinfo_name_lookup.sh"), '$DOMAIN', '$REALM', '$DC_USERNAME']) -plantestsuite_loadlist("samba4.rpc.echo against NetBIOS alias", "ad_dc_ntvfs", [valgrindify(smbtorture4), "$LISTOPT", "$LOADLIST", 'ncacn_np:$NETBIOSALIAS', '-U$DOMAIN/$USERNAME%$PASSWORD', 'rpc.echo']) +plansmbtorture4testsuite('rpc.echo', "ad_dc_ntvfs", ['ncacn_np:$NETBIOSALIAS', '-U$DOMAIN/$USERNAME%$PASSWORD'], "samba4.rpc.echo against NetBIOS alias") + # json tests hook into ``chgdcpass'' to make them run in contributor CI on # gitlab planpythontestsuite("chgdcpass", "samba.tests.blackbox.netads_json") diff --git a/testprogs/blackbox/dbcheck-links.sh b/testprogs/blackbox/dbcheck-links.sh index ead59d691e0..f00fe46c2de 100755 --- a/testprogs/blackbox/dbcheck-links.sh +++ b/testprogs/blackbox/dbcheck-links.sh @@ -42,7 +42,7 @@ dbcheck() { if [ "$?" != "$2" ]; then return 1 fi - sort $tmpfile > $tmpfile.sorted + sort $tmpfile | grep -v "^INFO:" > $tmpfile.sorted sort $release_dir/expected-dbcheck-link-output${1}.txt > $tmpfile.expected diff -u $tmpfile.sorted $tmpfile.expected if [ "$?" != "0" ]; then diff --git a/testprogs/blackbox/dbcheck-oldrelease.sh b/testprogs/blackbox/dbcheck-oldrelease.sh index 9e9924654be..64c08c57981 100755 --- a/testprogs/blackbox/dbcheck-oldrelease.sh +++ b/testprogs/blackbox/dbcheck-oldrelease.sh @@ -297,6 +297,17 @@ dbcheck_objectclass() { fi } +# This should 'fail', because it returns the number of wrong records, which it must if we did not skip the deleted objects +dbcheck_deleted_objects() { + if [ x$RELEASE = x"alpha13" ]; then + basedn=$($ldbsearch -H tdb://$PREFIX_ABS/${RELEASE}/private/sam.ldb -s base -b "" defaultNamingContext| grep -i defaultNamingContext| cut -d\ -f 2) + + $PYTHON $BINDIR/samba-tool dbcheck -H tdb://$PREFIX_ABS/${RELEASE}/private/sam.ldb "cn=deleted objects,$basedn" --scope base $@ + else + return 1 + fi +} + # This should 'fail', because it returns the number of modified records dbcheck() { $PYTHON $BINDIR/samba-tool dbcheck --selftest-check-expired-tombstones --cross-ncs --fix --yes -H tdb://$PREFIX_ABS/${RELEASE}/private/sam.ldb $@ @@ -488,6 +499,7 @@ testit $RELEASE undump || failed=`expr $failed + 1` testit "reindex" reindex || failed=`expr $failed + 1` testit "current_version_mod" do_current_version_mod || failed=`expr $failed + 1` testit "check_expected_before_values" check_expected_before_values || failed=`expr $failed + 1` +testit_expect_failure "dbcheck_deleted_objects" dbcheck_deleted_objects || failed=`expr $failed + 1` testit_expect_failure "dbcheck_objectclass" dbcheck_objectclass || failed=`expr $failed + 1` testit_expect_failure "dbcheck" dbcheck || failed=`expr $failed + 1` testit "check_expected_after_values" check_expected_after_values || failed=`expr $failed + 1`