svn commit: samba r17082 - in branches/SAMBA_4_0/source: libcli/security librpc/idl torture/rpc

vlendec at samba.org vlendec at samba.org
Mon Jul 17 08:05:03 GMT 2006


Author: vlendec
Date: 2006-07-17 08:05:02 +0000 (Mon, 17 Jul 2006)
New Revision: 17082

WebSVN: http://websvn.samba.org/cgi-bin/viewcvs.cgi?view=rev&root=samba&rev=17082

Log:
Add a test that walks and tests denying tconX access via the share security
descriptor. This is something that W2k3 does _not_ pass and probably is not
expected to, it seems the don't check access at tconX time.

Thanks to metze for the hint how in the srvsvc_NetShareInfo1501 struct the
length of the sd can be encoded in idl.

As metze says, there's probably more to the share secdesc, this needs more
testing. This one is here to walk the samba3 code.

Volker

Modified:
   branches/SAMBA_4_0/source/libcli/security/dom_sid.c
   branches/SAMBA_4_0/source/librpc/idl/srvsvc.idl
   branches/SAMBA_4_0/source/torture/rpc/rpc.c
   branches/SAMBA_4_0/source/torture/rpc/rpc.h
   branches/SAMBA_4_0/source/torture/rpc/samba3rpc.c


Changeset:
Modified: branches/SAMBA_4_0/source/libcli/security/dom_sid.c
===================================================================
--- branches/SAMBA_4_0/source/libcli/security/dom_sid.c	2006-07-17 07:45:23 UTC (rev 17081)
+++ branches/SAMBA_4_0/source/libcli/security/dom_sid.c	2006-07-17 08:05:02 UTC (rev 17082)
@@ -215,7 +215,25 @@
 	return sid;
 }
 
+/*
+  Split up a SID into its domain and RID part
+*/
+NTSTATUS dom_sid_split_rid(TALLOC_CTX *mem_ctx, const struct dom_sid *sid,
+			   struct dom_sid **domain, uint32_t *rid)
+{
+	if (sid->num_auths == 0) {
+		return NT_STATUS_INVALID_PARAMETER;
+	}
 
+	if (!(*domain = dom_sid_dup(mem_ctx, sid))) {
+		return NT_STATUS_NO_MEMORY;
+	}
+
+	(*domain)->num_auths -= 1;
+	*rid = (*domain)->sub_auths[(*domain)->num_auths];
+	return NT_STATUS_OK;
+}
+
 /*
   return True if the 2nd sid is in the domain given by the first sid
 */

Modified: branches/SAMBA_4_0/source/librpc/idl/srvsvc.idl
===================================================================
--- branches/SAMBA_4_0/source/librpc/idl/srvsvc.idl	2006-07-17 07:45:23 UTC (rev 17081)
+++ branches/SAMBA_4_0/source/librpc/idl/srvsvc.idl	2006-07-17 08:05:02 UTC (rev 17082)
@@ -502,7 +502,7 @@
 	} srvsvc_NetShareCtr1007;
 
 	typedef struct {
-		uint32 reserved;
+		[range(0,0x40000),value(ndr_size_security_descriptor(sd,ndr->flags))] uint32 sd_size;
 		[subcontext(4)] security_descriptor *sd;
 	} srvsvc_NetShareInfo1501;
 

Modified: branches/SAMBA_4_0/source/torture/rpc/rpc.c
===================================================================
--- branches/SAMBA_4_0/source/torture/rpc/rpc.c	2006-07-17 07:45:23 UTC (rev 17081)
+++ branches/SAMBA_4_0/source/torture/rpc/rpc.c	2006-07-17 08:05:02 UTC (rev 17082)
@@ -130,6 +130,8 @@
 	register_torture_op("RPC-NETLOGSAMBA3", torture_netlogon_samba3);
 	register_torture_op("RPC-SAMBA3SESSIONKEY", torture_samba3_sessionkey);
 	register_torture_op("RPC-SAMBA3-SRVSVC", torture_samba3_rpc_srvsvc);
+	register_torture_op("RPC-SAMBA3-SHARESEC",
+			    torture_samba3_rpc_sharesec);
 	register_torture_op("RPC-SAMBA3-GETUSERNAME",
 			    torture_samba3_rpc_getusername);
 	register_torture_op("RPC-DRSUAPI", torture_rpc_drsuapi);

Modified: branches/SAMBA_4_0/source/torture/rpc/rpc.h
===================================================================
--- branches/SAMBA_4_0/source/torture/rpc/rpc.h	2006-07-17 07:45:23 UTC (rev 17081)
+++ branches/SAMBA_4_0/source/torture/rpc/rpc.h	2006-07-17 08:05:02 UTC (rev 17082)
@@ -27,6 +27,7 @@
 #include "torture/rpc/drsuapi.h"
 #include "libnet/libnet_join.h"
 #include "librpc/rpc/dcerpc.h"
+#include "libcli/raw/libcliraw.h"
 #include "torture/rpc/proto.h"
 
 #endif /* __TORTURE_RPC_H__ */

Modified: branches/SAMBA_4_0/source/torture/rpc/samba3rpc.c
===================================================================
--- branches/SAMBA_4_0/source/torture/rpc/samba3rpc.c	2006-07-17 07:45:23 UTC (rev 17081)
+++ branches/SAMBA_4_0/source/torture/rpc/samba3rpc.c	2006-07-17 08:05:02 UTC (rev 17082)
@@ -888,7 +888,7 @@
 }
 
 /*
- * Do a couple of channel protected Netlogon ops: Interactive and Network
+ * Do a couple of schannel protected Netlogon ops: Interactive and Network
  * login, and change the wks password
  */
 
@@ -1513,6 +1513,49 @@
 }
 
 /*
+ * Do a tcon, given a session
+ */
+
+NTSTATUS secondary_tcon(TALLOC_CTX *mem_ctx,
+			struct smbcli_session *session,
+			const char *sharename,
+			struct smbcli_tree **res)
+{
+	struct smbcli_tree *result;
+	TALLOC_CTX *tmp_ctx;
+	union smb_tcon tcon;
+	NTSTATUS status;
+
+	if (!(tmp_ctx = talloc_new(mem_ctx))) {
+		return NT_STATUS_NO_MEMORY;
+	}
+
+	if (!(result = smbcli_tree_init(session, mem_ctx, False))) {
+		talloc_free(tmp_ctx);
+		return NT_STATUS_NO_MEMORY;
+	}
+
+	tcon.generic.level = RAW_TCON_TCONX;
+	tcon.tconx.in.flags = 0;
+	tcon.tconx.in.password = data_blob(NULL, 0);
+	tcon.tconx.in.path = sharename;
+	tcon.tconx.in.device = "?????";
+
+	status = smb_raw_tcon(result, tmp_ctx, &tcon);
+	if (!NT_STATUS_IS_OK(status)) {
+		d_printf("smb_raw_tcon failed: %s\n", nt_errstr(status));
+		talloc_free(tmp_ctx);
+		return status;
+	}
+
+	result->tid = tcon.tconx.out.tid;
+	result = talloc_steal(mem_ctx, result);
+	talloc_free(tmp_ctx);
+	*res = result;
+	return NT_STATUS_OK;
+}
+
+/*
  * Test the getusername behaviour
  */
 
@@ -1607,7 +1650,6 @@
 		struct smbcli_session *session2;
 		struct smb_composite_sesssetup setup;
 		struct smbcli_tree *tree;
-		union smb_tcon tcon;
 
 		session2 = smbcli_session_init(cli->transport, mem_ctx, False);
 		if (session2 == NULL) {
@@ -1628,32 +1670,20 @@
 			goto done;
 		}
 
-		if (!(tree = smbcli_tree_init(session2, mem_ctx, False))) {
-			d_printf("smbcli_tree_init failed\n");
+		if (!NT_STATUS_IS_OK(secondary_tcon(mem_ctx, session2,
+						    "IPC$", &tree))) {
+			d_printf("secondary_tcon failed\n");
 			ret = False;
 			goto done;
 		}
 
-		tcon.generic.level = RAW_TCON_TCONX;
-		tcon.tconx.in.flags = 0;
-		tcon.tconx.in.password = data_blob(NULL, 0);
-		tcon.tconx.in.path = "IPC$";
-		tcon.tconx.in.device = "?????";
-	
-		status = smb_raw_tcon(tree, mem_ctx, &tcon);
-		if (!NT_STATUS_IS_OK(status)) {
-			d_printf("smb_raw_tcon failed\n");
-			ret = False;
-			goto done;
-		}
-
-		tree->tid = tcon.tconx.out.tid;
-
 		if (!(user_sid = whoami(mem_ctx, tree))) {
 			d_printf("whoami on user connection failed\n");
 			ret = False;
 			goto delete;
 		}
+
+		talloc_free(tree);
 	}
 
 	d_printf("Created %s, found %s\n",
@@ -1800,3 +1830,244 @@
 	talloc_free(mem_ctx);
 	return ret;
 }
+
+static struct security_descriptor *get_sharesec(TALLOC_CTX *mem_ctx,
+						struct smbcli_session *sess,
+						const char *sharename)
+{
+	struct smbcli_tree *tree;
+	TALLOC_CTX *tmp_ctx;
+	struct dcerpc_pipe *p;
+	NTSTATUS status;
+	struct srvsvc_NetShareGetInfo r;
+	struct security_descriptor *result;
+
+	if (!(tmp_ctx = talloc_new(mem_ctx))) {
+		d_printf("talloc_new failed\n");
+		return NULL;
+	}
+
+	if (!NT_STATUS_IS_OK(secondary_tcon(tmp_ctx, sess, "IPC$", &tree))) {
+		d_printf("secondary_tcon failed\n");
+		talloc_free(tmp_ctx);
+		return NULL;
+	}
+
+	if (!(p = pipe_bind_smb(mem_ctx, tree, "\\pipe\\srvsvc",
+				&dcerpc_table_srvsvc))) {
+		d_printf("could not bind to srvsvc pipe\n");
+		talloc_free(tmp_ctx);
+		return NULL;
+	}
+
+#if 0
+	p->conn->flags |= DCERPC_DEBUG_PRINT_IN | DCERPC_DEBUG_PRINT_OUT;
+#endif
+
+	r.in.server_unc = talloc_asprintf(tmp_ctx, "\\\\%s",
+					  dcerpc_server_name(p));
+	r.in.share_name = sharename;
+	r.in.level = 502;
+
+	status = dcerpc_srvsvc_NetShareGetInfo(p, tmp_ctx, &r);
+	if (!NT_STATUS_IS_OK(status)) {
+		d_printf("srvsvc_NetShareGetInfo failed: %s\n",
+			 nt_errstr(status));
+		talloc_free(tmp_ctx);
+		return NULL;
+	}
+
+	result = talloc_steal(mem_ctx, r.out.info.info502->sd);
+	talloc_free(tmp_ctx);
+	return result;
+}
+
+static NTSTATUS set_sharesec(TALLOC_CTX *mem_ctx,
+			     struct smbcli_session *sess,
+			     const char *sharename,
+			     struct security_descriptor *sd)
+{
+	struct smbcli_tree *tree;
+	TALLOC_CTX *tmp_ctx;
+	struct dcerpc_pipe *p;
+	NTSTATUS status;
+	struct srvsvc_NetShareInfo1501 i;
+	struct srvsvc_NetShareSetInfo r;
+	uint32_t error = 0;
+
+	if (!(tmp_ctx = talloc_new(mem_ctx))) {
+		d_printf("talloc_new failed\n");
+		return NT_STATUS_NO_MEMORY;
+	}
+
+	if (!NT_STATUS_IS_OK(secondary_tcon(tmp_ctx, sess, "IPC$", &tree))) {
+		d_printf("secondary_tcon failed\n");
+		talloc_free(tmp_ctx);
+		return NT_STATUS_UNSUCCESSFUL;
+	}
+
+	if (!(p = pipe_bind_smb(mem_ctx, tree, "\\pipe\\srvsvc",
+				&dcerpc_table_srvsvc))) {
+		d_printf("could not bind to srvsvc pipe\n");
+		talloc_free(tmp_ctx);
+		return NT_STATUS_UNSUCCESSFUL;
+	}
+
+#if 0
+	p->conn->flags |= DCERPC_DEBUG_PRINT_IN | DCERPC_DEBUG_PRINT_OUT;
+#endif
+
+	r.in.server_unc = talloc_asprintf(tmp_ctx, "\\\\%s",
+					  dcerpc_server_name(p));
+	r.in.share_name = sharename;
+	r.in.level = 1501;
+	i.sd = sd;
+	r.in.info.info1501 = &i;
+	r.in.parm_error = &error;
+
+	status = dcerpc_srvsvc_NetShareSetInfo(p, tmp_ctx, &r);
+	if (!NT_STATUS_IS_OK(status)) {
+		d_printf("srvsvc_NetShareGetInfo failed: %s\n",
+			 nt_errstr(status));
+	}
+
+	talloc_free(tmp_ctx);
+	return status;
+}
+
+BOOL try_tcon(TALLOC_CTX *mem_ctx,
+	      struct security_descriptor *orig_sd,
+	      struct smbcli_session *session,
+	      const char *sharename, const struct dom_sid *user_sid,
+	      unsigned int access, NTSTATUS expected_tcon,
+	      NTSTATUS expected_mkdir)
+{
+	TALLOC_CTX *tmp_ctx;
+	struct smbcli_tree *rmdir_tree, *tree;
+	struct dom_sid *domain_sid;
+	uint32_t rid;
+	struct security_descriptor *sd;
+	NTSTATUS status;
+	BOOL ret = True;
+
+	if (!(tmp_ctx = talloc_new(mem_ctx))) {
+		d_printf("talloc_new failed\n");
+		return False;
+	}
+
+	status = secondary_tcon(tmp_ctx, session, sharename, &rmdir_tree);
+	if (!NT_STATUS_IS_OK(status)) {
+		d_printf("first tcon to delete dir failed\n");
+		talloc_free(tmp_ctx);
+		return False;
+	}
+
+	smbcli_rmdir(rmdir_tree, "sharesec_testdir");
+
+	if (!NT_STATUS_IS_OK(dom_sid_split_rid(tmp_ctx, user_sid,
+					       &domain_sid, &rid))) {
+		d_printf("dom_sid_split_rid failed\n");
+		talloc_free(tmp_ctx);
+		return False;
+	}
+
+	sd = security_descriptor_create(
+		tmp_ctx, "S-1-5-32-544",
+		dom_sid_string(mem_ctx, dom_sid_add_rid(mem_ctx, domain_sid,
+							DOMAIN_RID_USERS)),
+		dom_sid_string(mem_ctx, user_sid),
+		SEC_ACE_TYPE_ACCESS_ALLOWED, access, 0, NULL);
+	if (sd == NULL) {
+		d_printf("security_descriptor_create failed\n");
+		talloc_free(tmp_ctx);
+                return False;
+        }
+
+	status = set_sharesec(mem_ctx, session, sharename, sd);
+	if (!NT_STATUS_IS_OK(status)) {
+		d_printf("custom set_sharesec failed: %s\n",
+			 nt_errstr(status));
+		talloc_free(tmp_ctx);
+                return False;
+	}
+
+	status = secondary_tcon(tmp_ctx, session, sharename, &tree);
+	if (!NT_STATUS_EQUAL(status, expected_tcon)) {
+		d_printf("Expected %s, got %s\n", nt_errstr(expected_tcon),
+			 nt_errstr(status));
+		ret = False;
+		goto done;
+	}
+
+	if (!NT_STATUS_IS_OK(status)) {
+		/* An expected non-access, no point in trying to write */
+		goto done;
+	}
+
+	status = smbcli_mkdir(tree, "sharesec_testdir");
+	if (!NT_STATUS_EQUAL(status, expected_mkdir)) {
+		d_printf("Expected %s, got %s\n", nt_errstr(expected_mkdir),
+			 nt_errstr(status));
+		ret = False;
+	}
+
+ done:
+	smbcli_rmdir(rmdir_tree, "sharesec_testdir");
+
+	status = set_sharesec(mem_ctx, session, sharename, orig_sd);
+	if (!NT_STATUS_IS_OK(status)) {
+		d_printf("custom set_sharesec failed: %s\n",
+			 nt_errstr(status));
+		talloc_free(tmp_ctx);
+                return False;
+	}
+
+	talloc_free(tmp_ctx);
+	return ret;
+}
+
+BOOL torture_samba3_rpc_sharesec(struct torture_context *torture)
+{
+	TALLOC_CTX *mem_ctx;
+	BOOL ret = True;
+	struct smbcli_state *cli;
+	struct security_descriptor *sd;
+	struct dom_sid *user_sid;
+
+	if (!(mem_ctx = talloc_new(torture))) {
+		return False;
+	}
+
+	if (!(torture_open_connection_share(
+		      mem_ctx, &cli, lp_parm_string(-1, "torture", "host"),
+		      "IPC$", NULL))) {
+		d_printf("IPC$ connection failed\n");
+		talloc_free(mem_ctx);
+		return False;
+	}
+
+	if (!(user_sid = whoami(mem_ctx, cli->tree))) {
+		d_printf("whoami failed\n");
+		talloc_free(mem_ctx);
+		return False;
+	}
+
+	sd = get_sharesec(mem_ctx, cli->session, lp_parm_string(-1, "torture",
+								"share"));
+
+	ret &= try_tcon(mem_ctx, sd, cli->session,
+			lp_parm_string(-1, "torture", "share"),
+			user_sid, 0, NT_STATUS_ACCESS_DENIED, NT_STATUS_OK);
+
+	ret &= try_tcon(mem_ctx, sd, cli->session,
+			lp_parm_string(-1, "torture", "share"),
+			user_sid, SEC_FILE_READ_DATA, NT_STATUS_OK,
+			NT_STATUS_NETWORK_ACCESS_DENIED);
+
+	ret &= try_tcon(mem_ctx, sd, cli->session,
+			lp_parm_string(-1, "torture", "share"),
+			user_sid, SEC_FILE_ALL, NT_STATUS_OK, NT_STATUS_OK);
+
+	talloc_free(mem_ctx);
+	return ret;
+}



More information about the samba-cvs mailing list