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

Jule Anger janger at samba.org
Thu Dec 2 11:53:01 UTC 2021


The branch, v4-14-test has been updated
       via  aef700ad3c8 s3: docs-xml: Clarify the "delete veto files" paramter.
       via  b61fb49a7a9 s3: smbd: Fix logic in can_delete_directory_fsp() to cope with dangling symlinks.
       via  7034f9b765d s3: smbd: Fix logic in rmdir_internals() to cope with dangling symlinks.
       via  66d688cea2b s3: smbd: Fix rmdir_internals() to do an early return if lp_delete_veto_files() is not set.
       via  3d4761cf04d s3: VFS: xattr_tdb. Allow unlinkat to cope with dangling symlinks.
       via  37804062ea7 s3: VFS: streams_depot. Allow unlinkat to cope with dangling symlinks.
       via  67c85f0ce8e s3: smbd: Add two tests showing the ability to delete a directory containing a dangling symlink over SMB2 depends on "delete veto files" setting.
       via  db8eb865b53 s3: smbd: Add two tests showing recursive directory delete of a directory containing veto file and msdfs links over SMB2.
       via  3e8d6e681f8 CVE-2021-3670 ldap_server: Clearly log LDAP queries and timeouts
       via  3a4eb50cf74 CVE-2021-3670 dsdb/anr: Do a copy of the potentially anr query before starting to modify it
       via  d92dfb0dabf CVE-2021-3670 ldap_server: Remove duplicate print of LDAP search details
       via  08c9016cb9f CVE-2021-3670 ldb: Confirm the request has not yet timed out in ldb filter processing
       via  f9b2267c6eb CVE-2021-3670 ldap_server: Ensure value of MaxQueryDuration is greater than zero
       via  f72090064bd CVE-2021-3670 ldap_server: Set timeout on requests based on MaxQueryDuration
       via  dc71ae17782 CVE-2021-3670 tests/krb5/test_ldap.py: Add test for LDAP timeouts
      from  8ccb26c679b CVE-2020-25717: s3:auth: Fallback to a SID/UID based mapping if the named based lookup fails

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


- Log -----------------------------------------------------------------
commit aef700ad3c800dc33ccf4c470d45416c97fde210
Author: Jeremy Allison <jra at samba.org>
Date:   Mon Oct 25 12:42:02 2021 -0700

    s3: docs-xml: Clarify the "delete veto files" paramter.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=14879
    
    Signed-off-by: Jeremy Allison <jra at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>
    
    Autobuild-User(master): Ralph Böhme <slow at samba.org>
    Autobuild-Date(master): Fri Oct 29 14:57:14 UTC 2021 on sn-devel-184
    
    (cherry picked from commit 0b818c6b77e972626d0b071bebcf4ce55619fb84)
    (cherry picked from commit a549dc219cba5bd61969e4919ae4142f52c133ea)
    
    Autobuild-User(v4-14-test): Jule Anger <janger at samba.org>
    Autobuild-Date(v4-14-test): Thu Dec  2 11:52:33 UTC 2021 on sn-devel-184

commit b61fb49a7a90a4b8fb2df6b9970db9bc5e16027d
Author: Jeremy Allison <jra at samba.org>
Date:   Mon Oct 25 12:36:57 2021 -0700

    s3: smbd: Fix logic in can_delete_directory_fsp() to cope with dangling symlinks.
    
    Remove knownfail.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=14879
    
    Signed-off-by: Jeremy Allison <jra at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>
    (cherry picked from commit e9ef970eee5eca8ab3720279c54098e91d2dfda9)
    (backported from commit 5023dbc04bfad7cc39e8c4de96f40c82e7a0288e)
    [pfilipen at redhat.com: can_delete_directory_fsp() got refactored in 4.15]

commit 7034f9b765de5d9423c903761a3fe5549d7fe9a7
Author: Jeremy Allison <jra at samba.org>
Date:   Mon Oct 25 12:32:29 2021 -0700

    s3: smbd: Fix logic in rmdir_internals() to cope with dangling symlinks.
    
    Still need to add the same logic in can_delete_directory_fsp()
    before we can delete the knownfail.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=14879
    
    Signed-off-by: Jeremy Allison <jra at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>
    (cherry picked from commit 26fecad2e66e91a3913d88ee2e0889f266e91d89)
    (backported from commit 4793c4d5307472f0eb72f70f7dbf7324744e3f91)
    [pfilipen at redhat.com: rmdir_internals() got refactored in 4.15]

commit 66d688cea2bd4071128bbaa2afd810d89daab370
Author: Jeremy Allison <jra at samba.org>
Date:   Mon Oct 25 12:21:37 2021 -0700

    s3: smbd: Fix rmdir_internals() to do an early return if lp_delete_veto_files() is not set.
    
    Fix the comments to match what the code actually does. The
    exit at the end of the scan directory loop if we find a client
    visible filename is a change in behavior, but the previous
    behavior (not exist on visible filename, but delete it) was
    a bug and in non-tested code. Now it's testd.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=14879
    
    Signed-off-by: Jeremy Allison <jra at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>
    (cherry picked from commit a37d16e7c55f85e3f2c9c8614755ea6307092d5f)
    (backported from commit e00fe095e8cf7ab54bc82870b913762d2fdddbad)
    [pfilipen at redhat.com: rmdir_internals() got refactored in 4.15]

commit 3d4761cf04ddf386e1565131351d28ca315b9626
Author: Jeremy Allison <jra at samba.org>
Date:   Mon Oct 25 12:02:43 2021 -0700

    s3: VFS: xattr_tdb. Allow unlinkat to cope with dangling symlinks.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=14879
    
    Signed-off-by: Jeremy Allison <jra at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>
    (cherry picked from commit f254be19d6501a4f573843af97963e350a9ee2ed)
    (backported from commit 0dba0917fd97e975d1daab5b0828644d026c2bc5)
    [pfilipen at redhat.com: code in 4.15 uses different variable name]

commit 37804062ea7babdd7e304343fbc054d8946170dc
Author: Jeremy Allison <jra at samba.org>
Date:   Mon Oct 25 12:01:58 2021 -0700

    s3: VFS: streams_depot. Allow unlinkat to cope with dangling symlinks.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=14879
    
    Signed-off-by: Jeremy Allison <jra at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>
    (cherry picked from commit 295d7d026babe3cd5123d0f53adcb16868907f05)
    (backported from commit 7a4173809a87350bc3580240232978042ec2ceca)
    [pfilipen at redhat.com: code in 4.15 uses different variable name]

commit 67c85f0ce8e2e8d5c4cc3a8752ac423aef3ef736
Author: Jeremy Allison <jra at samba.org>
Date:   Thu Oct 21 16:37:27 2021 -0700

    s3: smbd: Add two tests showing the ability to delete a directory containing a dangling symlink over SMB2 depends on "delete veto files" setting.
    
    Add knownfail.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=14879
    
    Signed-off-by: Jeremy Allison <jra at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>
    (cherry picked from commit 942123b95923f35a32df4196a072a3ed3468396a)
    (cherry picked from commit 359517877d6462ff4398401748f921c8b79357a6)

commit db8eb865b53daf82193bbfad7adfbf6e3f149af7
Author: Jeremy Allison <jra at samba.org>
Date:   Thu Oct 21 15:06:20 2021 -0700

    s3: smbd: Add two tests showing recursive directory delete of a directory containing veto file and msdfs links over SMB2.
    
    Add knownfail.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=14878
    
    Signed-off-by: Jeremy Allison <jra at samba.org>
    Reviewed-by: Ralph Boehme <slow at samba.org>
    (cherry picked from commit ad0082d79a681b981154747dcde5713e1933b88f)
    (cherry picked from commit dab3fa1d8c27e696afa15e071331f646e06d9706)

commit 3e8d6e681f8dbe79e4595549f78c42649b3573a2
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Thu Nov 18 16:09:47 2021 +1300

    CVE-2021-3670 ldap_server: Clearly log LDAP queries and timeouts
    
    This puts all the detail on one line so it can be searched
    by IP address and connecting SID.
    
    This relies on the anr handling as otherwise this log
    becomes the expanded query, not the original one.
    
    RN: Provide clear logs of the LDAP search and who made it, including
    a warning (at log level 3) for queries that are 1/4 of the hard timeout.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=14694
    
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    
    Autobuild-User(master): Douglas Bagnall <dbagnall at samba.org>
    Autobuild-Date(master): Thu Nov 25 02:30:42 UTC 2021 on sn-devel-184
    
    (cherry picked from commit 3507e96b3dcf0c0b8eff7b2c08ffccaf0812a393)

commit 3a4eb50cf74671de3442d179bd2d44afd5bc52c1
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Thu Nov 18 15:57:34 2021 +1300

    CVE-2021-3670 dsdb/anr: Do a copy of the potentially anr query before starting to modify it
    
    RN: Do not modify the caller-supplied memory in the anr=* handling to
    allow clear logging of the actual caller request after it has been processed.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=14694
    
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    (cherry picked from commit 5f0590362c5c0c5ee20503a67467f9be2d50e73b)

commit d92dfb0dabf9cfccb86f2b1146d6c353af2e1435
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Thu Nov 18 15:27:08 2021 +1300

    CVE-2021-3670 ldap_server: Remove duplicate print of LDAP search details
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=14694
    
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    (cherry picked from commit 2b3af3b560c9617a233c131376c870fce146c002)

commit 08c9016cb9f25105c39488770113a1b00f8a4223
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Mon Sep 27 16:47:46 2021 +1300

    CVE-2021-3670 ldb: Confirm the request has not yet timed out in ldb filter processing
    
    The LDB filter processing is where the time is spent in the LDB stack
    but the timeout event will not get run while this is ongoing, so we
    must confirm we have not yet timed out manually.
    
    RN: Ensure that the LDB request has not timed out during filter processing
    as the LDAP server MaxQueryDuration is otherwise not honoured.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=14694
    
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    (cherry picked from commit 1d5b155619bc532c46932965b215bd73a920e56f)

commit f9b2267c6eb8138fc94df7a138ad5d87526f1d79
Author: Joseph Sutton <josephsutton at catalyst.net.nz>
Date:   Tue Sep 28 17:20:43 2021 +1300

    CVE-2021-3670 ldap_server: Ensure value of MaxQueryDuration is greater than zero
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=14694
    
    Signed-off-by: Joseph Sutton <josephsutton at catalyst.net.nz>
    Reviewed-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    (cherry picked from commit e1ab0c43629686d1d2c0b0b2bcdc90057a792049)

commit f72090064bd674ea3a6d6b2e7556a9a85bb01df6
Author: Joseph Sutton <josephsutton at catalyst.net.nz>
Date:   Thu Aug 26 13:53:23 2021 +1200

    CVE-2021-3670 ldap_server: Set timeout on requests based on MaxQueryDuration
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=14694
    
    Signed-off-by: Joseph Sutton <josephsutton at catalyst.net.nz>
    Reviewed-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    (cherry picked from commit 86fe9d48883f87c928bf31ccbd275db420386803)

commit dc71ae17782ef4c6cac51e51b0b8b7ad77b556a0
Author: Joseph Sutton <josephsutton at catalyst.net.nz>
Date:   Thu Aug 26 21:18:26 2021 +1200

    CVE-2021-3670 tests/krb5/test_ldap.py: Add test for LDAP timeouts
    
    We allow a timeout of 2x over to avoid this being a flapping test.
    Samba is not very accurate on the timeout, which is not otherwise an
    issue but makes this test fail sometimes.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=14694
    
    Signed-off-by: Joseph Sutton <josephsutton at catalyst.net.nz>
    Reviewed-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    (cherry picked from commit dcfcafdbf756e12d9077ad7920eea25478c29f81)

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

Summary of changes:
 docs-xml/smbdotconf/filename/deletevetofiles.xml   |   9 +-
 lib/ldb/ldb_key_value/ldb_kv.c                     |   2 +
 lib/ldb/ldb_key_value/ldb_kv.h                     |  10 +
 lib/ldb/ldb_key_value/ldb_kv_index.c               |  41 +++
 lib/ldb/ldb_key_value/ldb_kv_search.c              |  33 +-
 selftest/target/Samba3.pm                          |  20 ++
 source3/modules/vfs_streams_depot.c                |  10 +
 source3/modules/vfs_xattr_tdb.c                    |  10 +
 .../tests/test_delete_veto_files_only_rmdir.sh     | 183 +++++++++++
 source3/script/tests/test_veto_rmdir.sh            | 217 +++++++++++++
 source3/selftest/tests.py                          |   6 +
 source3/smbd/close.c                               | 334 ++++++++++++++-------
 source3/smbd/dir.c                                 |  97 ++++++
 source4/dsdb/samdb/ldb_modules/anr.c               |  73 ++++-
 source4/dsdb/tests/python/large_ldap.py            |  63 ++++
 source4/ldap_server/ldap_backend.c                 | 136 +++++++--
 source4/ldap_server/ldap_server.c                  |   4 +-
 17 files changed, 1096 insertions(+), 152 deletions(-)
 create mode 100755 source3/script/tests/test_delete_veto_files_only_rmdir.sh
 create mode 100755 source3/script/tests/test_veto_rmdir.sh


Changeset truncated at 500 lines:

diff --git a/docs-xml/smbdotconf/filename/deletevetofiles.xml b/docs-xml/smbdotconf/filename/deletevetofiles.xml
index 581dc05396d..570d4ac60a0 100644
--- a/docs-xml/smbdotconf/filename/deletevetofiles.xml
+++ b/docs-xml/smbdotconf/filename/deletevetofiles.xml
@@ -4,9 +4,12 @@
                  xmlns:samba="http://www.samba.org/samba/DTD/samba-doc">
 <description>
 	<para>This option is used when Samba is attempting to 
-	delete a directory that contains one or more vetoed directories 
-	(see the <smbconfoption name="veto files"/>
-	option).  If this option is set to <constant>no</constant> (the default) then if a vetoed 
+	delete a directory that contains one or more vetoed files
+	or directories or non-visible files or directories (such
+	as dangling symlinks that point nowhere).
+	(see the <smbconfoption name="veto files"/>, <smbconfoption name="hide special files"/>,
+	<smbconfoption name="hide unreadable"/>, <smbconfoption name="hide unwriteable files"/>
+	options).  If this option is set to <constant>no</constant> (the default) then if a vetoed
 	directory contains any non-vetoed files or directories then the 
 	directory delete will fail. This is usually what you want.</para>
 
diff --git a/lib/ldb/ldb_key_value/ldb_kv.c b/lib/ldb/ldb_key_value/ldb_kv.c
index ed0f760b5a2..aea6f0c1be0 100644
--- a/lib/ldb/ldb_key_value/ldb_kv.c
+++ b/lib/ldb/ldb_key_value/ldb_kv.c
@@ -2078,6 +2078,8 @@ static int ldb_kv_handle_request(struct ldb_module *module,
 		}
 	}
 
+	ac->timeout_timeval = tv;
+
 	/* set a spy so that we do not try to use the request context
 	 * if it is freed before ltdb_callback fires */
 	ac->spy = talloc(req, struct ldb_kv_req_spy);
diff --git a/lib/ldb/ldb_key_value/ldb_kv.h b/lib/ldb/ldb_key_value/ldb_kv.h
index f9dffae2dcf..ac474b04b4c 100644
--- a/lib/ldb/ldb_key_value/ldb_kv.h
+++ b/lib/ldb/ldb_key_value/ldb_kv.h
@@ -152,6 +152,16 @@ struct ldb_kv_context {
 	struct ldb_module *module;
 	struct ldb_request *req;
 
+	/*
+	 * Required as we might not get to the event loop before the
+	 * timeout, so we need some old-style cooperative multitasking
+	 * here.
+	 */
+	struct timeval timeout_timeval;
+
+	/* Used to throttle calls to gettimeofday() */
+	size_t timeout_counter;
+
 	bool request_terminated;
 	struct ldb_kv_req_spy *spy;
 
diff --git a/lib/ldb/ldb_key_value/ldb_kv_index.c b/lib/ldb/ldb_key_value/ldb_kv_index.c
index 1cc042aa84f..d70e5f619ef 100644
--- a/lib/ldb/ldb_key_value/ldb_kv_index.c
+++ b/lib/ldb/ldb_key_value/ldb_kv_index.c
@@ -2352,6 +2352,47 @@ static int ldb_kv_index_filter(struct ldb_kv_private *ldb_kv,
 	for (i = 0; i < num_keys; i++) {
 		int ret;
 		bool matched;
+
+		/*
+		 * Check the time every 64 records, to reduce calls to
+		 * gettimeofday().  This is a compromise, not all
+		 * calls to ldb_match_message() will take the same
+		 * time, most will run quickly but by luck it might be
+		 * possible to have 64 records that are slow, doing a
+		 * recursive search via LDAP_MATCHING_RULE_IN_CHAIN.
+		 *
+		 * Thankfully this is after index processing so only
+		 * on the subset that matches some index (but still
+		 * possibly a big one like objectclass=user)
+		 */
+		if (i % 64 == 0) {
+			struct timeval now = tevent_timeval_current();
+			int timeval_cmp = tevent_timeval_compare(&ac->timeout_timeval,
+								 &now);
+
+			/*
+			 * The search has taken too long.  This is the
+			 * most likely place for our time to expire,
+			 * as we are checking the records after the
+			 * index set intersection.  This is now the
+			 * slow process of checking if the records
+			 * actually match.
+			 *
+			 * The tevent based timeout is not likely to
+			 * be hit, sadly, as we don't run an event
+			 * loop.
+			 *
+			 * While we are indexed and most of the work
+			 * should have been done already, the
+			 * ldb_match_* calls can be quite expensive if
+			 * the caller uses LDAP_MATCHING_RULE_IN_CHAIN
+			 */
+			if (timeval_cmp <= 0) {
+				talloc_free(keys);
+				return LDB_ERR_TIME_LIMIT_EXCEEDED;
+			}
+		}
+
 		msg = ldb_msg_new(ac);
 		if (!msg) {
 			talloc_free(keys);
diff --git a/lib/ldb/ldb_key_value/ldb_kv_search.c b/lib/ldb/ldb_key_value/ldb_kv_search.c
index a0e1762bc90..46031b99c16 100644
--- a/lib/ldb/ldb_key_value/ldb_kv_search.c
+++ b/lib/ldb/ldb_key_value/ldb_kv_search.c
@@ -314,7 +314,8 @@ static int search_func(_UNUSED_ struct ldb_kv_private *ldb_kv,
 	struct ldb_context *ldb;
 	struct ldb_kv_context *ac;
 	struct ldb_message *msg, *filtered_msg;
-	int ret;
+	struct timeval now;
+	int ret, timeval_cmp;
 	bool matched;
 
 	ac = talloc_get_type(state, struct ldb_kv_context);
@@ -341,6 +342,36 @@ static int search_func(_UNUSED_ struct ldb_kv_private *ldb_kv,
 		return 0;
 	}
 
+	/*
+	 * Check the time every 64 records, to reduce calls to
+	 * gettimeofday().  This is a compromise, not all calls to
+	 * ldb_match_message() will take the same time, most will fail
+	 * quickly but by luck it might be possible to have 64 records
+	 * that are slow, doing a recursive search via
+	 * LDAP_MATCHING_RULE_IN_CHAIN.
+	 */
+	if (ac->timeout_counter++ % 64 == 0) {
+		now = tevent_timeval_current();
+		timeval_cmp = tevent_timeval_compare(&ac->timeout_timeval,
+						     &now);
+
+		/*
+		 * The search has taken too long.  This is the most
+		 * likely place for our time to expire, as we are in
+		 * an un-indexed search and we return the data from
+		 * within this loop.  The tevent based timeout is not
+		 * likely to be hit, sadly.
+		 *
+		 * ldb_match_msg_error() can be quite expensive if a
+		 * LDAP_MATCHING_RULE_IN_CHAIN extended match was
+		 * specified.
+		 */
+		if (timeval_cmp <= 0) {
+			ac->error = LDB_ERR_TIME_LIMIT_EXCEEDED;
+			return -1;
+		}
+	}
+
 	msg = ldb_msg_new(ac);
 	if (!msg) {
 		ac->error = LDB_ERR_OPERATIONS_ERROR;
diff --git a/selftest/target/Samba3.pm b/selftest/target/Samba3.pm
index 14a1f1223b1..588d7779dd4 100755
--- a/selftest/target/Samba3.pm
+++ b/selftest/target/Samba3.pm
@@ -1460,6 +1460,9 @@ sub setup_fileserver
 	my $bad_iconv_sharedir="$share_dir/bad_iconv";
 	push(@dirs, $bad_iconv_sharedir);
 
+	my $veto_sharedir="$share_dir/veto";
+	push(@dirs,$veto_sharedir);
+
 	my $ip4 = Samba::get_ipv4_addr("FILESERVER");
 	my $fileserver_options = "
 	kernel change notify = yes
@@ -1568,6 +1571,23 @@ sub setup_fileserver
 	comment = smb username is [%U]
 	vfs objects =
 
+[veto_files_nodelete]
+	path = $veto_sharedir
+	read only = no
+	msdfs root = yes
+	veto files = /veto_name*/
+	delete veto files = no
+
+[veto_files_delete]
+	path = $veto_sharedir
+	msdfs root = yes
+	veto files = /veto_name*/
+	delete veto files = yes
+
+[delete_veto_files_only]
+	path = $veto_sharedir
+	delete veto files = yes
+
 [homes]
 	comment = Home directories
 	browseable = No
diff --git a/source3/modules/vfs_streams_depot.c b/source3/modules/vfs_streams_depot.c
index a5e02d5a069..dd6376e5fd0 100644
--- a/source3/modules/vfs_streams_depot.c
+++ b/source3/modules/vfs_streams_depot.c
@@ -739,6 +739,16 @@ static int streams_depot_unlink_internal(vfs_handle_struct *handle,
 		ret = SMB_VFS_NEXT_LSTAT(handle, smb_fname_base);
 	} else {
 		ret = SMB_VFS_NEXT_STAT(handle, smb_fname_base);
+		if (ret == -1 && (errno == ENOENT || errno == ELOOP)) {
+			if (VALID_STAT(smb_fname->st) &&
+					S_ISLNK(smb_fname->st.st_ex_mode)) {
+				/*
+				 * Original name was a link - Could be
+				 * trying to remove a dangling symlink.
+				 */
+				ret = SMB_VFS_NEXT_LSTAT(handle, smb_fname_base);
+			}
+		}
 	}
 
 	if (ret == -1) {
diff --git a/source3/modules/vfs_xattr_tdb.c b/source3/modules/vfs_xattr_tdb.c
index d89a1dd0d7d..e06ff9639f1 100644
--- a/source3/modules/vfs_xattr_tdb.c
+++ b/source3/modules/vfs_xattr_tdb.c
@@ -639,6 +639,16 @@ static int xattr_tdb_unlinkat(vfs_handle_struct *handle,
 		ret = SMB_VFS_NEXT_LSTAT(handle, smb_fname_tmp);
 	} else {
 		ret = SMB_VFS_NEXT_STAT(handle, smb_fname_tmp);
+		if (ret == -1 && (errno == ENOENT || errno == ELOOP)) {
+			if (VALID_STAT(smb_fname->st) &&
+					S_ISLNK(smb_fname->st.st_ex_mode)) {
+				/*
+				 * Original name was a link - Could be
+				 * trying to remove a dangling symlink.
+				 */
+				ret = SMB_VFS_NEXT_LSTAT(handle, smb_fname_tmp);
+			}
+		}
 	}
 	if (ret == -1) {
 		goto out;
diff --git a/source3/script/tests/test_delete_veto_files_only_rmdir.sh b/source3/script/tests/test_delete_veto_files_only_rmdir.sh
new file mode 100755
index 00000000000..d2c3b2198f7
--- /dev/null
+++ b/source3/script/tests/test_delete_veto_files_only_rmdir.sh
@@ -0,0 +1,183 @@
+#!/bin/sh
+#
+# Check smbclient can (or cannot) delete a directory containing dangling symlinks.
+# BUG: https://bugzilla.samba.org/show_bug.cgi?id=14879
+#
+
+if [ $# -lt 6 ]; then
+cat <<EOF
+Usage: $0 SERVER SERVER_IP USERNAME PASSWORD SHAREPATH SMBCLIENT
+EOF
+exit 1;
+fi
+
+SERVER=${1}
+SERVER_IP=${2}
+USERNAME=${3}
+PASSWORD=${4}
+SHAREPATH=${5}
+SMBCLIENT=${6}
+shift 6
+SMBCLIENT="$VALGRIND ${SMBCLIENT}"
+ADDARGS="$@"
+
+incdir=$(dirname "$0")/../../../testprogs/blackbox
+. $incdir/subunit.sh
+
+failed=0
+
+rmdir_path="$SHAREPATH/dir"
+
+#
+# Using the share "[delete_veto_files_only]" we CAN delete
+# a directory containing only a dangling symlink.
+#
+test_dangle_symlink_delete_veto_rmdir()
+{
+    local dangle_symlink_path="$rmdir_path/bad_link"
+    local tmpfile=$PREFIX/smbclient.in.$$
+
+    # Create rmdir directory.
+    mkdir -p "$rmdir_path"
+    # Create dangling symlink underneath.
+    ln -s "nowhere-foo" "$dangle_symlink_path"
+
+    cat > "$tmpfile" <<EOF
+cd dir
+ls
+quit
+EOF
+
+    local cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT //$SERVER/delete_veto_files_only -U$USERNAME%$PASSWORD $ADDARGS < $tmpfile 2>&1'
+    eval echo "$cmd"
+    out=$(eval "$cmd")
+    ret=$?
+
+    # Check for smbclient error.
+    if [ $ret != 0 ] ; then
+        echo "Failed accessing share delete_veto_files_only - $ret"
+        echo "$out"
+        return 1
+    fi
+
+    # We should NOT see the dangling symlink file.
+    echo "$out" | grep bad_link
+    ret=$?
+    if [ $ret -eq 0 ] ; then
+       echo "Saw dangling symlink bad_link in share delete_veto_files_only"
+       echo "$out"
+       return 1
+    fi
+
+    # Try and remove the directory, should succeed.
+    cat > "$tmpfile" <<EOF
+rd dir
+quit
+EOF
+
+    local cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT //$SERVER/delete_veto_files_only -U$USERNAME%$PASSWORD $ADDARGS < $tmpfile 2>&1'
+    eval echo "$cmd"
+    out=$(eval "$cmd")
+    ret=$?
+
+    # Check for smbclient error.
+    if [ $ret != 0 ] ; then
+        echo "Failed accessing share delete_veto_files_only - $ret"
+        echo "$out"
+        return 1
+    fi
+
+    # We should get no NT_STATUS_ errors.
+    echo "$out" | grep NT_STATUS_
+    ret=$?
+    if [ $ret -eq 0 ] ; then
+       echo "Got error NT_STATUS_ in share delete_veto_files_only"
+       echo "$out"
+       return 1
+    fi
+
+    return 0
+}
+
+#
+# Using the share "[veto_files_nodelete]" we CANNOT delete
+# a directory containing only a dangling symlink.
+#
+test_dangle_symlink_veto_files_nodelete()
+{
+    local dangle_symlink_path="$rmdir_path/bad_link"
+    local tmpfile=$PREFIX/smbclient.in.$$
+
+    # Create rmdir directory.
+    mkdir -p "$rmdir_path"
+    # Create dangling symlink underneath.
+    ln -s "nowhere-foo" "$dangle_symlink_path"
+
+    cat > "$tmpfile" <<EOF
+cd dir
+ls
+quit
+EOF
+
+    local cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT //$SERVER/veto_files_nodelete -U$USERNAME%$PASSWORD $ADDARGS < $tmpfile 2>&1'
+    eval echo "$cmd"
+    out=$(eval "$cmd")
+    ret=$?
+
+    # Check for smbclient error.
+    if [ $ret != 0 ] ; then
+        echo "Failed accessing share veto_files_nodelete - $ret"
+        echo "$out"
+        return 1
+    fi
+
+    # We should NOT see the dangling symlink file.
+    echo "$out" | grep bad_link
+    ret=$?
+    if [ $ret -eq 0 ] ; then
+       echo "Saw dangling symlink bad_link in share veto_files_nodelete"
+       echo "$out"
+       return 1
+    fi
+
+    # Try and remove the directory, should fail with DIRECTORY_NOT_EMPTY.
+    cat > "$tmpfile" <<EOF
+rd dir
+quit
+EOF
+
+    local cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT //$SERVER/veto_files_nodelete -U$USERNAME%$PASSWORD $ADDARGS < $tmpfile 2>&1'
+    eval echo "$cmd"
+    out=$(eval "$cmd")
+    ret=$?
+
+    # Check for smbclient error.
+    if [ $ret != 0 ] ; then
+        echo "Failed accessing share veto_files_nodelete - $ret"
+        echo "$out"
+        return 1
+    fi
+
+    # We should get NT_STATUS_DIRECTORY_NOT_EMPTY errors.
+    echo "$out" | grep NT_STATUS_DIRECTORY_NOT_EMPTY
+    ret=$?
+    if [ $ret -ne 0 ] ; then
+       echo "Should get NT_STATUS_DIRECTORY_NOT_EMPTY in share veto_files_nodelete"
+       echo "$out"
+       return 1
+    fi
+
+    return 0
+}
+
+
+testit "rmdir can delete directory containing dangling symlink" \
+   test_dangle_symlink_delete_veto_rmdir || failed=$(expr "$failed" + 1)
+
+rm -rf "$rmdir_path"
+
+testit "rmdir cannot delete directory delete_veto_files_no containing dangling symlink" \
+   test_dangle_symlink_veto_files_nodelete || failed=$(expr "$failed" + 1)
+
+rm -rf "$rmdir_path"
+exit "$failed"
diff --git a/source3/script/tests/test_veto_rmdir.sh b/source3/script/tests/test_veto_rmdir.sh
new file mode 100755
index 00000000000..d3df8f1bba0
--- /dev/null
+++ b/source3/script/tests/test_veto_rmdir.sh
@@ -0,0 +1,217 @@
+#!/bin/sh
+#
+# Check smbclient can (or cannot) delete a directory containing veto files.
+# BUG: https://bugzilla.samba.org/show_bug.cgi?id=14878
+#
+
+if [ $# -lt 6 ]; then
+cat <<EOF
+Usage: $0 SERVER SERVER_IP USERNAME PASSWORD SHAREPATH SMBCLIENT
+EOF
+exit 1;
+fi
+
+SERVER=${1}
+SERVER_IP=${2}
+USERNAME=${3}
+PASSWORD=${4}
+SHAREPATH=${5}
+SMBCLIENT=${6}
+shift 6
+SMBCLIENT="$VALGRIND ${SMBCLIENT}"
+ADDARGS="$@"
+
+incdir=$(dirname "$0")/../../../testprogs/blackbox
+. "$incdir"/subunit.sh
+
+failed=0
+
+rmdir_path="$SHAREPATH/dir"
+
+test_veto_nodelete_rmdir()
+{
+    local veto_path="$rmdir_path/veto_name1"
+    local msdfs_link_path="$rmdir_path/dfs_link"
+    local tmpfile=$PREFIX/smbclient.in.$$
+
+    # Create rmdir directory.
+    mkdir -p "$rmdir_path"
+    # Create veto file underneath.
+    touch "$veto_path"
+    # Create msdfs link underneath.
+    ln -s "msdfs:$SERVER_IP\\ro-tmp" "$msdfs_link_path"
+
+    cat > "$tmpfile" <<EOF
+cd dir
+ls
+quit
+EOF
+
+    local cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT //$SERVER/veto_files_nodelete -U$USERNAME%$PASSWORD $ADDARGS < $tmpfile 2>&1'
+    eval echo "$cmd"
+    out=$(eval "$cmd")
+    ret=$?
+
+    # Check for smbclient error.
+    if [ $ret != 0 ] ; then
+        echo "Failed accessing share veto_files_nodelete - $ret"
+        echo "$out"
+        return 1
+    fi
+
+    # We should only see the dfs_link file.
+    echo "$out" | grep dfs_link
+    ret=$?
+    if [ $ret -ne 0 ] ; then
+       echo "Failed to see dfs_link in share veto_files_nodelete"
+       echo "$out"
+       return 1


-- 
Samba Shared Repository



More information about the samba-cvs mailing list