7936a1
From 83499424ab011da66ded2df441277c2b89844c7b Mon Sep 17 00:00:00 2001
7936a1
From: Jeremy Allison <jra@samba.org>
7936a1
Date: Thu, 21 Oct 2021 15:06:20 -0700
7936a1
Subject: [PATCH 1/2] s3: smbd: Add two tests showing recursive directory
7936a1
 delete of a directory containing veto file and msdfs links over SMB2.
7936a1
7936a1
Add knownfail.
7936a1
7936a1
BUG: https://bugzilla.samba.org/show_bug.cgi?id=14878
7936a1
7936a1
Signed-off-by: Jeremy Allison <jra@samba.org>
7936a1
Reviewed-by: Ralph Boehme <slow@samba.org>
7936a1
(cherry picked from commit ad0082d79a681b981154747dcde5713e1933b88f)
7936a1
---
7936a1
 selftest/knownfail.d/veto_rmdir         |   1 +
7936a1
 selftest/target/Samba3.pm               |  16 ++
7936a1
 source3/script/tests/test_veto_rmdir.sh | 217 ++++++++++++++++++++++++
7936a1
 source3/selftest/tests.py               |   3 +
7936a1
 4 files changed, 237 insertions(+)
7936a1
 create mode 100644 selftest/knownfail.d/veto_rmdir
7936a1
 create mode 100755 source3/script/tests/test_veto_rmdir.sh
7936a1
7936a1
diff --git a/selftest/knownfail.d/veto_rmdir b/selftest/knownfail.d/veto_rmdir
7936a1
new file mode 100644
7936a1
index 00000000000..ecced55d794
7936a1
--- /dev/null
7936a1
+++ b/selftest/knownfail.d/veto_rmdir
7936a1
@@ -0,0 +1 @@
7936a1
+^samba3.blackbox.test_veto_rmdir.rmdir can delete directory containing a veto file\(fileserver\)
7936a1
diff --git a/selftest/target/Samba3.pm b/selftest/target/Samba3.pm
7936a1
index fdbba8411bc..2fdab781fda 100755
7936a1
--- a/selftest/target/Samba3.pm
7936a1
+++ b/selftest/target/Samba3.pm
7936a1
@@ -1614,6 +1614,9 @@ sub setup_fileserver
7936a1
 	my $bad_iconv_sharedir="$share_dir/bad_iconv";
7936a1
 	push(@dirs, $bad_iconv_sharedir);
7936a1
 
7936a1
+	my $veto_sharedir="$share_dir/veto";
7936a1
+	push(@dirs,$veto_sharedir);
7936a1
+
7936a1
 	my $ip4 = Samba::get_ipv4_addr("FILESERVER");
7936a1
 	my $fileserver_options = "
7936a1
 	kernel change notify = yes
7936a1
@@ -1722,6 +1725,19 @@ sub setup_fileserver
7936a1
 	comment = smb username is [%U]
7936a1
 	vfs objects =
7936a1
 
7936a1
+[veto_files_nodelete]
7936a1
+	path = $veto_sharedir
7936a1
+	read only = no
7936a1
+	msdfs root = yes
7936a1
+	veto files = /veto_name*/
7936a1
+	delete veto files = no
7936a1
+
7936a1
+[veto_files_delete]
7936a1
+	path = $veto_sharedir
7936a1
+	msdfs root = yes
7936a1
+	veto files = /veto_name*/
7936a1
+	delete veto files = yes
7936a1
+
7936a1
 [homes]
7936a1
 	comment = Home directories
7936a1
 	browseable = No
7936a1
diff --git a/source3/script/tests/test_veto_rmdir.sh b/source3/script/tests/test_veto_rmdir.sh
7936a1
new file mode 100755
7936a1
index 00000000000..d3df8f1bba0
7936a1
--- /dev/null
7936a1
+++ b/source3/script/tests/test_veto_rmdir.sh
7936a1
@@ -0,0 +1,217 @@
7936a1
+#!/bin/sh
7936a1
+#
7936a1
+# Check smbclient can (or cannot) delete a directory containing veto files.
7936a1
+# BUG: https://bugzilla.samba.org/show_bug.cgi?id=14878
7936a1
+#
7936a1
+
7936a1
+if [ $# -lt 6 ]; then
7936a1
+cat <
7936a1
+Usage: $0 SERVER SERVER_IP USERNAME PASSWORD SHAREPATH SMBCLIENT
7936a1
+EOF
7936a1
+exit 1;
7936a1
+fi
7936a1
+
7936a1
+SERVER=${1}
7936a1
+SERVER_IP=${2}
7936a1
+USERNAME=${3}
7936a1
+PASSWORD=${4}
7936a1
+SHAREPATH=${5}
7936a1
+SMBCLIENT=${6}
7936a1
+shift 6
7936a1
+SMBCLIENT="$VALGRIND ${SMBCLIENT}"
7936a1
+ADDARGS="$@"
7936a1
+
7936a1
+incdir=$(dirname "$0")/../../../testprogs/blackbox
7936a1
+. "$incdir"/subunit.sh
7936a1
+
7936a1
+failed=0
7936a1
+
7936a1
+rmdir_path="$SHAREPATH/dir"
7936a1
+
7936a1
+test_veto_nodelete_rmdir()
7936a1
+{
7936a1
+    local veto_path="$rmdir_path/veto_name1"
7936a1
+    local msdfs_link_path="$rmdir_path/dfs_link"
7936a1
+    local tmpfile=$PREFIX/smbclient.in.$$
7936a1
+
7936a1
+    # Create rmdir directory.
7936a1
+    mkdir -p "$rmdir_path"
7936a1
+    # Create veto file underneath.
7936a1
+    touch "$veto_path"
7936a1
+    # Create msdfs link underneath.
7936a1
+    ln -s "msdfs:$SERVER_IP\\ro-tmp" "$msdfs_link_path"
7936a1
+
7936a1
+    cat > "$tmpfile" <
7936a1
+cd dir
7936a1
+ls
7936a1
+quit
7936a1
+EOF
7936a1
+
7936a1
+    local cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT //$SERVER/veto_files_nodelete -U$USERNAME%$PASSWORD $ADDARGS < $tmpfile 2>&1'
7936a1
+    eval echo "$cmd"
7936a1
+    out=$(eval "$cmd")
7936a1
+    ret=$?
7936a1
+
7936a1
+    # Check for smbclient error.
7936a1
+    if [ $ret != 0 ] ; then
7936a1
+        echo "Failed accessing share veto_files_nodelete - $ret"
7936a1
+        echo "$out"
7936a1
+        return 1
7936a1
+    fi
7936a1
+
7936a1
+    # We should only see the dfs_link file.
7936a1
+    echo "$out" | grep dfs_link
7936a1
+    ret=$?
7936a1
+    if [ $ret -ne 0 ] ; then
7936a1
+       echo "Failed to see dfs_link in share veto_files_nodelete"
7936a1
+       echo "$out"
7936a1
+       return 1
7936a1
+    fi
7936a1
+
7936a1
+    # Now remove the dfs_link file.
7936a1
+    rm -rf "$msdfs_link_path"
7936a1
+
7936a1
+    # Try and remove the directory, should fail with NT_STATUS_DIRECTORY_NOT_EMPTY.
7936a1
+    cat > "$tmpfile" <
7936a1
+rd dir
7936a1
+quit
7936a1
+EOF
7936a1
+
7936a1
+    local cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT //$SERVER/veto_files_nodelete -U$USERNAME%$PASSWORD $ADDARGS < $tmpfile 2>&1'
7936a1
+    eval echo "$cmd"
7936a1
+    out=$(eval "$cmd")
7936a1
+    ret=$?
7936a1
+
7936a1
+    # Check for smbclient error.
7936a1
+    if [ $ret != 0 ] ; then
7936a1
+        echo "Failed accessing share veto_files_nodelete - $ret"
7936a1
+        echo "$out"
7936a1
+        return 1
7936a1
+    fi
7936a1
+
7936a1
+    # We should get NT_STATUS_DIRECTORY_NOT_EMPTY.
7936a1
+    echo "$out" | grep NT_STATUS_DIRECTORY_NOT_EMPTY
7936a1
+    ret=$?
7936a1
+    if [ $ret -ne 0 ] ; then
7936a1
+       echo "Failed to get error NT_STATUS_DIRECTORY_NOT_EMPTY in share veto_files_nodelete"
7936a1
+       echo "$out"
7936a1
+       return 1
7936a1
+    fi
7936a1
+
7936a1
+    # remove the veto file - directory should now be empty.
7936a1
+    rm -rf "$veto_path"
7936a1
+
7936a1
+    # Try and remove the directory, should now succeed.
7936a1
+    cat > "$tmpfile" <
7936a1
+rd dir
7936a1
+quit
7936a1
+EOF
7936a1
+
7936a1
+    local cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT //$SERVER/veto_files_nodelete -U$USERNAME%$PASSWORD $ADDARGS < $tmpfile 2>&1'
7936a1
+    eval echo "$cmd"
7936a1
+    out=$(eval "$cmd")
7936a1
+    ret=$?
7936a1
+
7936a1
+    # Check for smbclient error.
7936a1
+    if [ $ret != 0 ] ; then
7936a1
+        echo "Failed accessing share veto_files_nodelete - $ret"
7936a1
+        echo "$out"
7936a1
+        return 1
7936a1
+    fi
7936a1
+
7936a1
+    # We should get no NT_STATUS_ errors.
7936a1
+    echo "$out" | grep NT_STATUS_
7936a1
+    ret=$?
7936a1
+    if [ $ret -eq 0 ] ; then
7936a1
+       echo "Got error NT_STATUS_ in share veto_files_nodelete"
7936a1
+       echo "$out"
7936a1
+       return 1
7936a1
+    fi
7936a1
+
7936a1
+    return 0
7936a1
+}
7936a1
+
7936a1
+test_veto_delete_rmdir()
7936a1
+{
7936a1
+    local veto_path="$rmdir_path/veto_name1"
7936a1
+    local msdfs_link_path="$rmdir_path/dfs_link"
7936a1
+    local tmpfile=$PREFIX/smbclient.in.$$
7936a1
+
7936a1
+    # Create rmdir directory.
7936a1
+    mkdir -p "$rmdir_path"
7936a1
+    # Create veto file underneath.
7936a1
+    touch "$veto_path"
7936a1
+    # Create msdfs link underneath.
7936a1
+    ln -s "msdfs:$SERVER_IP\\ro-tmp" "$msdfs_link_path"
7936a1
+
7936a1
+    cat > "$tmpfile" <
7936a1
+cd dir
7936a1
+ls
7936a1
+quit
7936a1
+EOF
7936a1
+
7936a1
+    local cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT //$SERVER/veto_files_delete -U$USERNAME%$PASSWORD $ADDARGS < $tmpfile 2>&1'
7936a1
+    eval echo "$cmd"
7936a1
+    out=$(eval "$cmd")
7936a1
+    ret=$?
7936a1
+
7936a1
+    # Check for smbclient error.
7936a1
+    if [ $ret != 0 ] ; then
7936a1
+        echo "Failed accessing share veto_files_delete - $ret"
7936a1
+        echo "$out"
7936a1
+        return 1
7936a1
+    fi
7936a1
+
7936a1
+    # We should only see the dfs_link file.
7936a1
+    echo "$out" | grep dfs_link
7936a1
+    ret=$?
7936a1
+    if [ $ret -ne 0 ] ; then
7936a1
+       echo "Failed to see dfs_link in share veto_files_delete"
7936a1
+       echo "$out"
7936a1
+       return 1
7936a1
+    fi
7936a1
+
7936a1
+    # Now remove the dfs_link file.
7936a1
+    rm -rf "$msdfs_link_path"
7936a1
+
7936a1
+    # Try and remove the directory, should now succeed.
7936a1
+    cat > "$tmpfile" <
7936a1
+rd dir
7936a1
+quit
7936a1
+EOF
7936a1
+
7936a1
+    local cmd='CLI_FORCE_INTERACTIVE=yes $SMBCLIENT //$SERVER/veto_files_delete -U$USERNAME%$PASSWORD $ADDARGS < $tmpfile 2>&1'
7936a1
+    eval echo "$cmd"
7936a1
+    out=$(eval "$cmd")
7936a1
+    ret=$?
7936a1
+
7936a1
+    # Check for smbclient error.
7936a1
+    if [ $ret != 0 ] ; then
7936a1
+        echo "Failed accessing share veto_files_delete - $ret"
7936a1
+        echo "$out"
7936a1
+        return 1
7936a1
+    fi
7936a1
+
7936a1
+    # We should get no NT_STATUS_ errors.
7936a1
+    echo "$out" | grep NT_STATUS_
7936a1
+    ret=$?
7936a1
+    if [ $ret -eq 0 ] ; then
7936a1
+       echo "Got error NT_STATUS_ in share veto_files_delete"
7936a1
+       echo "$out"
7936a1
+       return 1
7936a1
+    fi
7936a1
+
7936a1
+    return 0
7936a1
+}
7936a1
+
7936a1
+testit "rmdir cannot delete directory containing a veto file" \
7936a1
+   test_veto_nodelete_rmdir || failed=$(expr "$failed" + 1)
7936a1
+
7936a1
+rm -rf "$rmdir_path"
7936a1
+
7936a1
+testit "rmdir can delete directory containing a veto file" \
7936a1
+   test_veto_delete_rmdir || failed=$(expr "$failed" + 1)
7936a1
+
7936a1
+rm -rf "$rmdir_path"
7936a1
+
7936a1
+exit "$failed"
7936a1
diff --git a/source3/selftest/tests.py b/source3/selftest/tests.py
7936a1
index d8f0db69b8c..24c8e0a1960 100755
7936a1
--- a/source3/selftest/tests.py
7936a1
+++ b/source3/selftest/tests.py
7936a1
@@ -539,6 +539,9 @@ for env in ["fileserver"]:
7936a1
     plantestsuite("samba3.blackbox.smbclient_iconv.CORE", env + "_smb1_done",
7936a1
                   [os.path.join(samba3srcdir, "script/tests/test_smbclient_iconv.sh"),
7936a1
                    '$SERVER', '$SERVER_IP', 'bad_iconv', '$USERNAME', '$PASSWORD', smbclient3, '-mCORE'])
7936a1
+    plantestsuite("samba3.blackbox.test_veto_rmdir", env,
7936a1
+                  [os.path.join(samba3srcdir, "script/tests/test_veto_rmdir.sh"),
7936a1
+                  '$SERVER', '$SERVER_IP', '$USERNAME', '$PASSWORD', '$LOCAL_PATH/veto', smbclient3])
7936a1
 
7936a1
     #
7936a1
     # tar command tests
7936a1
-- 
7936a1
2.30.2
7936a1
7936a1
7936a1
From d2d8a5b8df68a8adc0d7deb27f14f63e0ec7ae85 Mon Sep 17 00:00:00 2001
7936a1
From: Jeremy Allison <jra@samba.org>
7936a1
Date: Thu, 21 Oct 2021 16:18:24 -0700
7936a1
Subject: [PATCH 2/2] s3: smbd: Fix recursive directory delete of a directory
7936a1
 containing veto file and msdfs links.
7936a1
7936a1
Remove knownfail.
7936a1
7936a1
BUG: https://bugzilla.samba.org/show_bug.cgi?id=14878
7936a1
7936a1
Signed-off-by: Jeremy Allison <jra@samba.org>
7936a1
Reviewed-by: Ralph Boehme <slow@samba.org>
7936a1
(cherry picked from commit 73de1194c3c429ab93d722a852aa4f54213b112a)
7936a1
---
7936a1
 selftest/knownfail.d/veto_rmdir | 1 -
7936a1
 source3/smbd/close.c            | 2 +-
7936a1
 2 files changed, 1 insertion(+), 2 deletions(-)
7936a1
 delete mode 100644 selftest/knownfail.d/veto_rmdir
7936a1
7936a1
diff --git a/selftest/knownfail.d/veto_rmdir b/selftest/knownfail.d/veto_rmdir
7936a1
deleted file mode 100644
7936a1
index ecced55d794..00000000000
7936a1
--- a/selftest/knownfail.d/veto_rmdir
7936a1
+++ /dev/null
7936a1
@@ -1 +0,0 @@
7936a1
-^samba3.blackbox.test_veto_rmdir.rmdir can delete directory containing a veto file\(fileserver\)
7936a1
diff --git a/source3/smbd/close.c b/source3/smbd/close.c
7936a1
index 191626557dc..470ca7f1b6d 100644
7936a1
--- a/source3/smbd/close.c
7936a1
+++ b/source3/smbd/close.c
7936a1
@@ -1267,7 +1267,7 @@ static NTSTATUS rmdir_internals(TALLOC_CTX *ctx, struct files_struct *fsp)
7936a1
 
7936a1
 	/* Retry the rmdir */
7936a1
 	ret = SMB_VFS_UNLINKAT(conn,
7936a1
-			       dirfsp,
7936a1
+			       parent_fname->fsp,
7936a1
 			       at_fname,
7936a1
 			       AT_REMOVEDIR);
7936a1
 
7936a1
-- 
7936a1
2.30.2
7936a1