summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--python/samba/tests/reparsepoints.py167
-rw-r--r--selftest/skip1
-rwxr-xr-xsource3/selftest/tests.py1
3 files changed, 169 insertions, 0 deletions
diff --git a/python/samba/tests/reparsepoints.py b/python/samba/tests/reparsepoints.py
new file mode 100644
index 00000000000..07abdb03975
--- /dev/null
+++ b/python/samba/tests/reparsepoints.py
@@ -0,0 +1,167 @@
+# Unix SMB/CIFS implementation.
+# Copyright Volker Lendecke <vl@samba.org> 2022
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+
+from samba.samba3 import libsmb_samba_internal as libsmb
+from samba import (ntstatus,NTSTATUSError)
+from samba.dcerpc import security as sec
+from samba import reparse_symlink
+import samba.tests.libsmb
+
+class ReparsePoints(samba.tests.libsmb.LibsmbTests):
+
+ def connection(self):
+ share = samba.tests.env_get_var_value("SHARENAME")
+ smb1 = samba.tests.env_get_var_value("SMB1", allow_missing=True)
+ conn = libsmb.Conn(
+ self.server_ip,
+ share,
+ self.lp,
+ self.creds,
+ force_smb1=smb1)
+ return conn
+
+ def clean_file(self, conn, filename):
+ try:
+ conn.unlink(filename)
+ except NTSTATUSError as e:
+ err = e.args[0]
+ ok = (err == ntstatus.NT_STATUS_OBJECT_NAME_NOT_FOUND)
+ ok |= (err == ntstatus.NT_STATUS_OBJECT_PATH_NOT_FOUND)
+ if not ok:
+ raise
+
+ def test_error_not_a_reparse_point(self):
+ conn = self.connection()
+ filename = 'reparse'
+ self.clean_file(conn, filename)
+
+ fd = conn.create(
+ filename,
+ DesiredAccess=sec.SEC_FILE_WRITE_ATTRIBUTE,
+ CreateDisposition=libsmb.FILE_CREATE)
+
+ with self.assertRaises(NTSTATUSError) as e:
+ conn.fsctl(fd, libsmb.FSCTL_GET_REPARSE_POINT, b'', 1024)
+ self.assertEqual(e.args[0], ntstatus.NT_STATUS_NOT_A_REPARSE_POINT)
+
+ conn.close(fd)
+
+ self.clean_file(conn, filename)
+
+ def test_create_reparse(self):
+ conn = self.connection()
+ filename = 'reparse'
+ self.clean_file(conn, filename)
+
+ fd = conn.create(
+ filename,
+ DesiredAccess=sec.SEC_FILE_WRITE_ATTRIBUTE,
+ CreateDisposition=libsmb.FILE_CREATE)
+ b = reparse_symlink.put(0x80000025, 0, b'asdfasdfasdfasdfasdfasdf')
+ conn.fsctl(fd, libsmb.FSCTL_SET_REPARSE_POINT, b, 0)
+ b = reparse_symlink.put(0x80000026, 0, b'asdfasdfasdfasdfasdfasdf')
+ conn.fsctl(fd, libsmb.FSCTL_SET_REPARSE_POINT, b, 0)
+
+ # Show that directories can carry reparse points
+
+ def test_create_reparse_directory(self):
+ conn = self.connection()
+ dirname = "reparse_dir"
+
+ self.clean_file(conn, dirname)
+
+ fd = conn.create(
+ dirname,
+ DesiredAccess=sec.SEC_FILE_WRITE_ATTRIBUTE|
+ sec.SEC_STD_DELETE,
+ CreateDisposition=libsmb.FILE_CREATE,
+ CreateOptions=libsmb.FILE_DIRECTORY_FILE)
+ b = reparse_symlink.put(0x80000025, 0, b'asdfasdfasdfasdfasdfasdf')
+ conn.fsctl(fd, libsmb.FSCTL_SET_REPARSE_POINT, b, 0)
+ conn.delete_on_close(fd, 1)
+
+ # Only empty directories can carry reparse points
+
+ def test_create_reparse_nonempty_directory(self):
+ conn = self.connection()
+ dirname = "reparse_dir"
+ filename = f'{dirname}\\file.txt'
+
+ self.clean_file(conn, filename)
+ self.clean_file(conn, dirname)
+
+ dir_fd = conn.create(
+ dirname,
+ DesiredAccess=sec.SEC_FILE_WRITE_ATTRIBUTE|
+ sec.SEC_STD_DELETE,
+ CreateDisposition=libsmb.FILE_CREATE,
+ CreateOptions=libsmb.FILE_DIRECTORY_FILE)
+ fd = conn.create(
+ filename,
+ DesiredAccess=sec.SEC_FILE_WRITE_ATTRIBUTE|
+ sec.SEC_STD_DELETE,
+ CreateDisposition=libsmb.FILE_CREATE)
+
+ b = reparse_symlink.put(0x80000025, 0, b'asdf')
+ try:
+ conn.fsctl(dir_fd, libsmb.FSCTL_SET_REPARSE_POINT, b, 0)
+ except NTSTATUSError as e:
+ err = e.args[0]
+ ok = (err == ntstatus.NT_STATUS_DIRECTORY_NOT_EMPTY)
+ if not ok:
+ raise
+
+ conn.delete_on_close(fd, 1)
+ conn.close(fd)
+ conn.delete_on_close(dir_fd, 1)
+ conn.close(dir_fd)
+
+ # Show that reparse point opens respect share modes
+
+ def test_reparse_share_modes(self):
+ conn = self.connection()
+ filename = 'reparse'
+ self.clean_file(conn, filename)
+
+ fd = conn.create(
+ filename,
+ DesiredAccess=sec.SEC_FILE_WRITE_ATTRIBUTE,
+ CreateDisposition=libsmb.FILE_CREATE)
+ b = reparse_symlink.put(0x80000025, 0, b'asdfasdfasdfasdfasdfasdf')
+ conn.fsctl(fd, libsmb.FSCTL_SET_REPARSE_POINT, b, 0)
+ conn.close(fd);
+
+ fd1 = conn.create(
+ filename,
+ DesiredAccess=sec.SEC_FILE_READ_DATA|sec.SEC_STD_DELETE,
+ CreateDisposition=libsmb.FILE_OPEN,
+ CreateOptions=libsmb.FILE_OPEN_REPARSE_POINT)
+
+ with self.assertRaises(NTSTATUSError) as e:
+ fd2 = conn.create(
+ filename,
+ DesiredAccess=sec.SEC_FILE_READ_DATA,
+ CreateDisposition=libsmb.FILE_OPEN,
+ CreateOptions=libsmb.FILE_OPEN_REPARSE_POINT)
+ self.assertEqual(e.args[0], ntstatus.NT_STATUS_SHARING_VIOLATION)
+
+ conn.delete_on_close(fd1, 1);
+ conn.close(fd1)
+
+if __name__ == '__main__':
+ import unittest
+ unittest.main()
diff --git a/selftest/skip b/selftest/skip
index d5cc786f8a5..321a09e988b 100644
--- a/selftest/skip
+++ b/selftest/skip
@@ -148,3 +148,4 @@ bench # don't run benchmarks in our selftest
^samba4.smb2.mangle.*\(ad_dc_ntvfs\)$ # Ignore ad_dc_ntvfs since this is a new test
^samba4.smb2.tcon.*\(ad_dc_ntvfs\)$ # Ignore ad_dc_ntvfs since this is a new test
^samba4.smb2.mkdir.*\(ad_dc_ntvfs\)$ # Ignore ad_dc_ntvfs since this is a new test
+^samba.tests.reparsepoints.*
diff --git a/source3/selftest/tests.py b/source3/selftest/tests.py
index f6cc6e0c639..dceed0e0072 100755
--- a/source3/selftest/tests.py
+++ b/source3/selftest/tests.py
@@ -1687,3 +1687,4 @@ for t in CLUSTERED_LOCAL_TESTS:
"-N 1000 -o 2000"])
planpythontestsuite("fileserver", "samba.tests.smb3unix")
+planpythontestsuite("fileserver", "samba.tests.reparsepoints")