From 125ce23115b92045a1584f5654669180bea83067 Mon Sep 17 00:00:00 2001
From: Jeremy Allison <jra@samba.org>
Date: Tue, 25 Jul 2023 17:49:21 -0700
Subject: [PATCH 02/30] CVE-2023-3961:s3:torture: Add test
 SMB2-INVALID-PIPENAME to show we allow bad pipenames with unix separators
 through to the UNIX domain socket code.

The raw SMB2-INVALID-PIPENAME test passes against Windows 2022,
as it just returns NT_STATUS_OBJECT_NAME_NOT_FOUND.

Add the knownfail.

BUG:https://bugzilla.samba.org/show_bug.cgi?id=15422

Signed-off-by: Jeremy Allison <jra@samba.org>

[abartlet@samba.org backported to Samba 4.17 due to conflicts from
 context of other new torture tests missing in this version and
 changes in smb2cli_create() arguments]

Conflict: context adapt
Reference: https://download.samba.org/pub/samba/patches/security/samba-4.17.12-security-2023-10-10.patch
[PATCH 02/30] CVE-2023-3961:s3:torture: Add test
 SMB2-INVALID-PIPENAME to show we allow bad pipenames with unix separators
---
 selftest/knownfail.d/badpipename |   1 +
 source3/selftest/tests.py        |  15 +++++
 source3/torture/proto.h          |   1 +
 source3/torture/test_smb2.c      | 105 +++++++++++++++++++++++++++++++
 source3/torture/torture.c        |   4 ++
 5 files changed, 126 insertions(+)
 create mode 100644 selftest/knownfail.d/badpipename

diff --git a/selftest/knownfail.d/badpipename b/selftest/knownfail.d/badpipename
new file mode 100644
index 0000000..e69715f
--- /dev/null
+++ b/selftest/knownfail.d/badpipename
@@ -0,0 +1 @@
+^samba3.smbtorture_s3.smb2.SMB2-INVALID-PIPENAME.smbtorture\(fileserver\)
diff --git a/source3/selftest/tests.py b/source3/selftest/tests.py
index d4f2ea4..1fe17dd 100755
--- a/source3/selftest/tests.py
+++ b/source3/selftest/tests.py
@@ -229,6 +229,21 @@ plantestsuite("samba3.smbtorture_s3.smb1.MSDFS-ATTRIBUTE",
                 "-mNT1",
                 "-f msdfs-src1"])
 
+#
+# BUG: https://bugzilla.samba.org/show_bug.cgi?id=15422
+# Prevent bad pipenames.
+#
+plantestsuite("samba3.smbtorture_s3.smb2.SMB2-INVALID-PIPENAME",
+                "fileserver",
+                [os.path.join(samba3srcdir,
+                              "script/tests/test_smbtorture_s3.sh"),
+                'SMB2-INVALID-PIPENAME',
+                '//$SERVER_IP/tmp',
+                '$USERNAME',
+                '$PASSWORD',
+                smbtorture3,
+                "-mSMB2"])
+
 #
 # SMB2-STREAM-ACL needs to run against a special share - vfs_wo_fruit
 #
diff --git a/source3/torture/proto.h b/source3/torture/proto.h
index 551c4ea..f8d6384 100644
--- a/source3/torture/proto.h
+++ b/source3/torture/proto.h
@@ -120,6 +120,7 @@ bool run_smb2_path_slash(int dummy);
 bool run_smb2_sacl(int dummy);
 bool run_smb2_quota1(int dummy);
 bool run_smb2_stream_acl(int dummy);
+bool run_smb2_invalid_pipename(int dummy);
 bool run_list_dir_async_test(int dummy);
 bool run_delete_on_close_non_empty(int dummy);
 bool run_delete_on_close_nonwrite_delete_yes_test(int dummy);
diff --git a/source3/torture/test_smb2.c b/source3/torture/test_smb2.c
index c3f0141..f6afdf0 100644
--- a/source3/torture/test_smb2.c
+++ b/source3/torture/test_smb2.c
@@ -3608,3 +3608,108 @@ bool run_delete_on_close_nonwrite_delete_no_test(int dummy)
 	}
 	return ret;
 }
+
+bool run_smb2_invalid_pipename(int dummy)
+{
+	struct cli_state *cli = NULL;
+	NTSTATUS status;
+	uint64_t fid_persistent = 0;
+	uint64_t fid_volatile = 0;
+	const char *unknown_pipe = "badpipe";
+	const char *invalid_pipe = "../../../../../../../../../badpipe";
+
+	printf("Starting SMB2-INVALID-PIPENAME\n");
+
+	if (!torture_init_connection(&cli)) {
+		return false;
+	}
+
+	status = smbXcli_negprot(cli->conn,
+				cli->timeout,
+				PROTOCOL_SMB2_02,
+				PROTOCOL_SMB3_11);
+	if (!NT_STATUS_IS_OK(status)) {
+		printf("smbXcli_negprot returned %s\n", nt_errstr(status));
+		return false;
+	}
+
+	status = cli_session_setup_creds(cli, torture_creds);
+	if (!NT_STATUS_IS_OK(status)) {
+		printf("cli_session_setup returned %s\n", nt_errstr(status));
+		return false;
+	}
+
+	status = cli_tree_connect(cli, "IPC$", "?????", NULL);
+	if (!NT_STATUS_IS_OK(status)) {
+		printf("cli_tree_connect returned %s\n", nt_errstr(status));
+		return false;
+	}
+
+	/* Try and connect to an unknown pipename. */
+	status = smb2cli_create(cli->conn,
+				cli->timeout,
+				cli->smb2.session,
+				cli->smb2.tcon,
+				unknown_pipe,
+				SMB2_OPLOCK_LEVEL_NONE, /* oplock_level, */
+				SMB2_IMPERSONATION_IMPERSONATION, /* impersonation_level, */
+				SEC_STD_SYNCHRONIZE|
+					SEC_FILE_READ_DATA|
+					SEC_FILE_WRITE_DATA|
+					SEC_FILE_READ_ATTRIBUTE, /* desired_access, */
+				FILE_ATTRIBUTE_NORMAL, /* file_attributes, */
+				FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, /* share_access, */
+				FILE_CREATE, /* create_disposition, */
+				0, /* create_options, */
+				NULL, /* smb2_create_blobs *blobs */
+				&fid_persistent,
+				&fid_volatile,
+				NULL, /* struct smb_create_returns * */
+				talloc_tos(), /* mem_ctx. */
+				NULL); /* struct smb2_create_blobs */
+	/* We should get NT_STATUS_OBJECT_NAME_NOT_FOUND */
+	if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
+		printf("%s:%d smb2cli_create on name %s returned %s\n",
+			__FILE__,
+			__LINE__,
+			unknown_pipe,
+			nt_errstr(status));
+		return false;
+	}
+
+	/* Try and connect to an invalid pipename containing unix separators. */
+	status = smb2cli_create(cli->conn,
+				cli->timeout,
+				cli->smb2.session,
+				cli->smb2.tcon,
+				invalid_pipe,
+				SMB2_OPLOCK_LEVEL_NONE, /* oplock_level, */
+				SMB2_IMPERSONATION_IMPERSONATION, /* impersonation_level, */
+				SEC_STD_SYNCHRONIZE|
+					SEC_FILE_READ_DATA|
+					SEC_FILE_WRITE_DATA|
+					SEC_FILE_READ_ATTRIBUTE, /* desired_access, */
+				FILE_ATTRIBUTE_NORMAL, /* file_attributes, */
+				FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, /* share_access, */
+				FILE_CREATE, /* create_disposition, */
+				0, /* create_options, */
+				NULL, /* smb2_create_blobs *blobs */
+				&fid_persistent,
+				&fid_volatile,
+				NULL, /* struct smb_create_returns * */
+				talloc_tos(), /* mem_ctx. */
+				NULL); /* struct smb2_create_blobs */
+	/*
+	 * We should still get NT_STATUS_OBJECT_NAME_NOT_FOUND
+	 * (tested against Windows 2022).
+	 */
+	if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
+		printf("%s:%d smb2cli_create on name %s returned %s\n",
+			__FILE__,
+			__LINE__,
+			invalid_pipe,
+			nt_errstr(status));
+		return false;
+	}
+	return true;
+}
diff --git a/source3/torture/torture.c b/source3/torture/torture.c
index af28b17..922a1bb 100644
--- a/source3/torture/torture.c
+++ b/source3/torture/torture.c
@@ -15592,6 +15592,10 @@ static struct {
 		.name  = "readdir-timestamp",
 		.fn    = run_readdir_timestamp,
 	},
+	{
+		.name  = "SMB2-INVALID-PIPENAME",
+		.fn    = run_smb2_invalid_pipename,
+	},
 	{
 		.name = NULL,
 	},
-- 
2.33.0

