[SCM] Samba Shared Repository - branch master updated

Matthias Dieter Wallnöfer mdw at samba.org
Sat Oct 30 12:16:01 MDT 2010


The branch, master has been updated
       via  c0ebf5d s4:sam.py - add a short double swap "primaryGroupID" test
       via  98fefa8 s4:samldb LDB module - adapt the "samldb_prim_group_change" trigger to support multiple "primaryGroupID" modification entries
       via  02355fc s4:samr RPC server - the LDB error codes for adding or deleting a group member have changed
       via  c664f01 s4:sam.py - enhance "member" tests
       via  4987467 s4:samldb LDB module - "member" trigger
       via  5a2c3ad s4:rpc_server/common.h - quiet compilation warnings
      from  b548674 provision: fix wrong tests

http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit c0ebf5d7435c3c4968eefafc6c566dc818e600a0
Author: Matthias Dieter Wallnöfer <mdw at samba.org>
Date:   Sat Oct 30 17:48:51 2010 +0200

    s4:sam.py - add a short double swap "primaryGroupID" test
    
    It's not really meaningful but can happen.
    
    Autobuild-User: Matthias Dieter Wallnöfer <mdw at samba.org>
    Autobuild-Date: Sat Oct 30 18:15:31 UTC 2010 on sn-devel-104

commit 98fefa8a017bbb67f6c33080c8a80c77c34e42b8
Author: Matthias Dieter Wallnöfer <mdw at samba.org>
Date:   Sat Oct 30 17:43:17 2010 +0200

    s4:samldb LDB module - adapt the "samldb_prim_group_change" trigger to support multiple "primaryGroupID" modification entries

commit 02355fc6fd176312b61198e626cfe1fbb1ed5ac5
Author: Matthias Dieter Wallnöfer <mdw at samba.org>
Date:   Sat Oct 30 18:32:43 2010 +0200

    s4:samr RPC server - the LDB error codes for adding or deleting a group member have changed

commit c664f010d387af483dce41816d5d222bd8d84f46
Author: Matthias Dieter Wallnöfer <mdw at samba.org>
Date:   Sat Oct 30 18:09:12 2010 +0200

    s4:sam.py - enhance "member" tests

commit 4987467b785a5870cb338881c8916b4268006cd6
Author: Matthias Dieter Wallnöfer <mdw at samba.org>
Date:   Sat Oct 30 17:12:48 2010 +0200

    s4:samldb LDB module - "member" trigger
    
    - adapt the "samldb_member_check" trigger to support multiple "member"
      modification entries. There can exist special modification messages which
      delete and add members in one operation
    - support the right error codes when modifications do fail
      (ERR_ENTRY_ALREADY_EXISTS, ERR_UNWILLING_TO_PERFORM)

commit 5a2c3ad2fa198b260bd8f0934fad0e3113c9f670
Author: Matthias Dieter Wallnöfer <mdw at samba.org>
Date:   Sat Oct 30 17:55:56 2010 +0200

    s4:rpc_server/common.h - quiet compilation warnings

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

Summary of changes:
 source4/dsdb/samdb/ldb_modules/samldb.c |  172 ++++++++++++++++++++++---------
 source4/dsdb/tests/python/sam.py        |   44 ++++++++
 source4/rpc_server/common/common.h      |    2 +
 source4/rpc_server/samr/dcesrv_samr.c   |    6 +-
 4 files changed, 172 insertions(+), 52 deletions(-)


Changeset truncated at 500 lines:

diff --git a/source4/dsdb/samdb/ldb_modules/samldb.c b/source4/dsdb/samdb/ldb_modules/samldb.c
index 924c05e..44c8fee 100644
--- a/source4/dsdb/samdb/ldb_modules/samldb.c
+++ b/source4/dsdb/samdb/ldb_modules/samldb.c
@@ -1002,8 +1002,41 @@ static int samldb_prim_group_change(struct samldb_ctx *ac)
 	uint32_t rid;
 	struct dom_sid *sid;
 	struct ldb_dn *prev_prim_group_dn, *new_prim_group_dn;
+	unsigned int i;
 	int ret;
 
+	/* We've to walk over all modification entries and consider the
+	 * "primaryGroupID" ones.
+	 *
+	 * 1.) Add operations aren't allowed and there is returned
+	 *     "ATTRIBUTE_OR_VALUE_EXISTS".
+	 * 2.) Replace operations are allowed but the last one is taken
+	 * 3.) Delete operations are also not allowed and there is returned
+	 *     "UNWILLING_TO_PERFORM".
+	 *
+	 * If "el" is afterwards NULL then that means we've nothing to do here.
+	 */
+	el = NULL;
+	for (i = 0; i < ac->msg->num_elements; i++) {
+		if (ldb_attr_cmp(ac->msg->elements[i].name,
+				 "primaryGroupID") != 0) {
+			continue;
+		}
+
+		el = &ac->msg->elements[i];
+		if (LDB_FLAG_MOD_TYPE(el->flags) == LDB_FLAG_MOD_ADD) {
+			return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
+		}
+		if (LDB_FLAG_MOD_TYPE(el->flags) == LDB_FLAG_MOD_DELETE) {
+			return LDB_ERR_UNWILLING_TO_PERFORM;
+		}
+	}
+	if (el == NULL) {
+		return LDB_SUCCESS;
+	}
+
+	/* Okay, now for sure we are performing a "primaryGroupID" replace */
+
 	/* Fetch informations from the existing object */
 
 	ret = ldb_search(ldb, ac, &res, ac->msg->dn, LDB_SCOPE_BASE, attrs,
@@ -1033,9 +1066,20 @@ static int samldb_prim_group_change(struct samldb_ctx *ac)
 		return ldb_operr(ldb);
 	}
 
-	/* Finds out the DN of the new primary group */
+	/* Finds out the DN of the new primary group
+	 * Notice: in order to parse the primary group ID correctly we create
+	 * a temporary message here. */
 
-	rid = ldb_msg_find_attr_as_uint(ac->msg, "primaryGroupID", (uint32_t) -1);
+	msg = ldb_msg_new(ac->msg);
+	if (msg == NULL) {
+		return ldb_module_oom(ac->module);
+	}
+	ret = ldb_msg_add(msg, el, 0);
+	if (ret != LDB_SUCCESS) {
+		return ret;
+	}
+	rid = ldb_msg_find_attr_as_uint(msg, "primaryGroupID", (uint32_t) -1);
+	talloc_free(msg);
 	if (rid == (uint32_t) -1) {
 		/* we aren't affected of any primary group change */
 		return LDB_SUCCESS;
@@ -1066,6 +1110,9 @@ static int samldb_prim_group_change(struct samldb_ctx *ac)
 
 		/* Remove the "member" attribute on the new primary group */
 		msg = talloc_zero(ac, struct ldb_message);
+		if (msg == NULL) {
+			return ldb_module_oom(ac->module);
+		}
 		msg->dn = new_prim_group_dn;
 
 		ret = samdb_msg_add_delval(ldb, msg, msg, "member",
@@ -1081,6 +1128,9 @@ static int samldb_prim_group_change(struct samldb_ctx *ac)
 
 		/* Add a "member" attribute for the previous primary group */
 		msg = talloc_zero(ac, struct ldb_message);
+		if (msg == NULL) {
+			return ldb_module_oom(ac->module);
+		}
 		msg->dn = prev_prim_group_dn;
 
 		ret = samdb_msg_add_addval(ldb, msg, msg, "member",
@@ -1095,6 +1145,8 @@ static int samldb_prim_group_change(struct samldb_ctx *ac)
 		}
 	}
 
+	talloc_free(res);
+
 	return LDB_SUCCESS;
 }
 
@@ -1113,55 +1165,86 @@ static int samldb_prim_group_trigger(struct samldb_ctx *ac)
 
 static int samldb_member_check(struct samldb_ctx *ac)
 {
-	struct ldb_context *ldb;
+	struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
 	struct ldb_message_element *el;
 	struct ldb_dn *member_dn, *group_dn;
 	uint32_t prim_group_rid;
 	struct dom_sid *sid;
-	unsigned int i;
-
-	ldb = ldb_module_get_ctx(ac->module);
-
-	el = ldb_msg_find_element(ac->msg, "member");
-	if (el == NULL) {
-		/* we aren't affected */
-		return LDB_SUCCESS;
-	}
+	unsigned int i, j;
+	int cnt;
 
-	for (i = 0; i < el->num_values; i++) {
-		/* Denies to add "member"s to groups which are primary ones
-		 * for them */
-		member_dn = ldb_dn_from_ldb_val(ac, ldb, &el->values[i]);
-		if (!ldb_dn_validate(member_dn)) {
-			return ldb_operr(ldb);
-		}
-
-		prim_group_rid = samdb_search_uint(ldb, ac, (uint32_t) -1,
-						   member_dn, "primaryGroupID",
-						   NULL);
-		if (prim_group_rid == (uint32_t) -1) {
-			/* the member hasn't to be a user account -> therefore
-			 * no check needed in this case. */
+	/* We've to walk over all modification entries and consider the "member"
+	 * ones. */
+	for (i = 0; i < ac->msg->num_elements; i++) {
+		if (ldb_attr_cmp(ac->msg->elements[i].name, "member") != 0) {
 			continue;
 		}
 
-		sid = dom_sid_add_rid(ac, samdb_domain_sid(ldb),
-				      prim_group_rid);
-		if (sid == NULL) {
-			return ldb_operr(ldb);
-		}
-
-		group_dn = samdb_search_dn(ldb, ac, NULL, "(objectSid=%s)",
-					   ldap_encode_ndr_dom_sid(ac, sid));
-		if (group_dn == NULL) {
-			return ldb_operr(ldb);
-		}
+		el = &ac->msg->elements[i];
+		for (j = 0; j < el->num_values; j++) {
+			member_dn = ldb_dn_from_ldb_val(ac, ldb,
+							&el->values[j]);
+			if (!ldb_dn_validate(member_dn)) {
+				return ldb_operr(ldb);
+			}
 
-		if (ldb_dn_compare(group_dn, ac->msg->dn) == 0) {
-			if (LDB_FLAG_MOD_TYPE(el->flags)
+			/* The "member" attribute can be modified with the
+			 * following restrictions (beside a valid DN):
+			 *
+			 * - "add" operations can only be performed when the
+			 *   member still doesn't exist - if not then return
+			 *   ERR_ENTRY_ALREADY_EXISTS (not
+			 *   ERR_ATTRIBUTE_OR_VALUE_EXISTS!)
+			 * - "delete" operations can only be performed when the
+			 *   member does exist - if not then return
+			 *   ERR_UNWILLING_TO_PERFORM (not
+			 *   ERR_NO_SUCH_ATTRIBUTE!)
+			 * - primary group check
+			 */
+			cnt = samdb_search_count(ldb, ac, ac->msg->dn,
+						 "(member=%s)",
+						 ldb_dn_get_linearized(member_dn));
+			if (cnt < 0) {
+				return ldb_operr(ldb);
+			}
+			if ((cnt > 0) && (LDB_FLAG_MOD_TYPE(el->flags)
+			    == LDB_FLAG_MOD_ADD)) {
+				return LDB_ERR_ENTRY_ALREADY_EXISTS;
+			}
+			if ((cnt == 0) && LDB_FLAG_MOD_TYPE(el->flags)
 			    == LDB_FLAG_MOD_DELETE) {
 				return LDB_ERR_UNWILLING_TO_PERFORM;
-			} else {
+			}
+
+			/* Denies to add "member"s to groups which are primary
+			 * ones for them - in this case return
+			 * ERR_ENTRY_ALREADY_EXISTS. */
+
+			prim_group_rid = samdb_search_uint(ldb, ac,
+							   (uint32_t) -1,
+							   member_dn,
+							   "primaryGroupID",
+							   NULL);
+			if (prim_group_rid == (uint32_t) -1) {
+				/* the member hasn't to be a user account ->
+				 * therefore no check needed in this case. */
+				continue;
+			}
+
+			sid = dom_sid_add_rid(ac, samdb_domain_sid(ldb),
+					      prim_group_rid);
+			if (sid == NULL) {
+				return ldb_operr(ldb);
+			}
+
+			group_dn = samdb_search_dn(ldb, ac, NULL,
+						   "(objectSid=%s)",
+						   ldap_encode_ndr_dom_sid(ac, sid));
+			if (group_dn == NULL) {
+				return ldb_operr(ldb);
+			}
+
+			if (ldb_dn_compare(group_dn, ac->msg->dn) == 0) {
 				return LDB_ERR_ENTRY_ALREADY_EXISTS;
 			}
 		}
@@ -1393,19 +1476,12 @@ static int samldb_modify(struct ldb_module *module, struct ldb_request *req)
 	}
 
 	el = ldb_msg_find_element(ac->msg, "primaryGroupID");
-	if (el && (LDB_FLAG_MOD_TYPE(el->flags) == LDB_FLAG_MOD_REPLACE)
-	    && el->num_values == 1) {
-		modified = true;
-
+	if (el != NULL) {
 		ret = samldb_prim_group_change(ac);
 		if (ret != LDB_SUCCESS) {
 			return ret;
 		}
 	}
-	el = ldb_msg_find_element(ac->msg, "primaryGroupID");
-	if (el && (LDB_FLAG_MOD_TYPE(el->flags) == LDB_FLAG_MOD_DELETE)) {
-		return LDB_ERR_UNWILLING_TO_PERFORM;
-	}
 
 	el = ldb_msg_find_element(ac->msg, "userAccountControl");
 	if (el && (LDB_FLAG_MOD_TYPE(el->flags) == LDB_FLAG_MOD_REPLACE)
diff --git a/source4/dsdb/tests/python/sam.py b/source4/dsdb/tests/python/sam.py
index 43e57f9..bbcc4a8 100755
--- a/source4/dsdb/tests/python/sam.py
+++ b/source4/dsdb/tests/python/sam.py
@@ -402,6 +402,15 @@ class SamTests(unittest.TestCase):
           FLAG_MOD_REPLACE, "primaryGroupID")
         ldb.modify(m)
 
+        # Swap the groups (does not really make sense but does the same)
+        m = Message()
+        m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
+        m["primaryGroupID"] = MessageElement(str(group_rid_1),
+          FLAG_MOD_REPLACE, "primaryGroupID")
+        m["primaryGroupID"] = MessageElement(str(group_rid_2),
+          FLAG_MOD_REPLACE, "primaryGroupID")
+        ldb.modify(m)
+
         # Old primary group should contain a "member" attribute for the user,
         # the new shouldn't contain anymore one
         res1 = ldb.search("cn=ldaptestgroup, cn=users," + self.base_dn,
@@ -427,6 +436,17 @@ class SamTests(unittest.TestCase):
         except LdbError, (num, _):
             self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
 
+        # Delete invalid group member
+        m = Message()
+        m.dn = Dn(ldb, "cn=ldaptestgroup2,cn=users," + self.base_dn)
+        m["member"] = MessageElement("cn=ldaptestuser1,cn=users," + self.base_dn,
+                                     FLAG_MOD_DELETE, "member")
+        try:
+            ldb.modify(m)
+            self.fail()
+        except LdbError, (num, _):
+            self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
+
         # Also this should be denied
         try:
             ldb.add({
@@ -455,6 +475,17 @@ class SamTests(unittest.TestCase):
                                      FLAG_MOD_ADD, "member")
         ldb.modify(m)
 
+        # Already added
+        m = Message()
+        m.dn = Dn(ldb, "cn=ldaptestgroup2,cn=users," + self.base_dn)
+        m["member"] = MessageElement("cn=ldaptestuser,cn=users," + self.base_dn,
+                                     FLAG_MOD_ADD, "member")
+        try:
+            ldb.modify(m)
+            self.fail()
+        except LdbError, (num, _):
+            self.assertEquals(num, ERR_ENTRY_ALREADY_EXISTS)
+
         # Invalid member
         m = Message()
         m.dn = Dn(ldb, "cn=ldaptestgroup2,cn=users," + self.base_dn)
@@ -478,6 +509,19 @@ class SamTests(unittest.TestCase):
         except LdbError, (num, _):
             self.assertEquals(num, ERR_NO_SUCH_OBJECT)
 
+        # Invalid member
+        m = Message()
+        m.dn = Dn(ldb, "cn=ldaptestgroup2,cn=users," + self.base_dn)
+        m["member"] = MessageElement("cn=ldaptestuser,cn=users," + self.base_dn,
+                                     FLAG_MOD_REPLACE, "member")
+        m["member"] = MessageElement("cn=ldaptestuser1,cn=users," + self.base_dn,
+                                     FLAG_MOD_ADD, "member")
+        try:
+            ldb.modify(m)
+            self.fail()
+        except LdbError, (num, _):
+            self.assertEquals(num, ERR_NO_SUCH_OBJECT)
+
         m = Message()
         m.dn = Dn(ldb, "cn=ldaptestgroup2,cn=users," + self.base_dn)
         m["member"] = MessageElement(["cn=ldaptestuser,cn=users," + self.base_dn,
diff --git a/source4/rpc_server/common/common.h b/source4/rpc_server/common/common.h
index 3f3275b..240ef29 100644
--- a/source4/rpc_server/common/common.h
+++ b/source4/rpc_server/common/common.h
@@ -24,10 +24,12 @@
 #define _DCERPC_SERVER_COMMON_H_
 
 struct share_config;
+struct dcesrv_connection;
 struct dcesrv_context;
 struct dcesrv_context;
 struct dcesrv_call_state;
 struct ndr_interface_table;
+struct ncacn_packet;
 
 struct dcerpc_server_info { 
 	const char *domain_name;
diff --git a/source4/rpc_server/samr/dcesrv_samr.c b/source4/rpc_server/samr/dcesrv_samr.c
index 3c08851..dbc9c1e 100644
--- a/source4/rpc_server/samr/dcesrv_samr.c
+++ b/source4/rpc_server/samr/dcesrv_samr.c
@@ -1994,7 +1994,6 @@ static NTSTATUS dcesrv_samr_AddGroupMember(struct dcesrv_call_state *dce_call, T
 	switch (ret) {
 	case LDB_SUCCESS:
 		return NT_STATUS_OK;
-	case LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS:
 	case LDB_ERR_ENTRY_ALREADY_EXISTS:
 		return NT_STATUS_MEMBER_IN_GROUP;
 	case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
@@ -2099,7 +2098,7 @@ static NTSTATUS dcesrv_samr_DeleteGroupMember(struct dcesrv_call_state *dce_call
 	switch (ret) {
 	case LDB_SUCCESS:
 		return NT_STATUS_OK;
-	case LDB_ERR_NO_SUCH_ATTRIBUTE:
+	case LDB_ERR_UNWILLING_TO_PERFORM:
 		return NT_STATUS_MEMBER_NOT_IN_GROUP;
 	case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
 		return NT_STATUS_ACCESS_DENIED;
@@ -2468,7 +2467,6 @@ static NTSTATUS dcesrv_samr_AddAliasMember(struct dcesrv_call_state *dce_call, T
 	switch (ret) {
 	case LDB_SUCCESS:
 		return NT_STATUS_OK;
-	case LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS:
 	case LDB_ERR_ENTRY_ALREADY_EXISTS:
 		return NT_STATUS_MEMBER_IN_GROUP;
 	case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
@@ -2521,7 +2519,7 @@ static NTSTATUS dcesrv_samr_DeleteAliasMember(struct dcesrv_call_state *dce_call
 	switch (ret) {
 	case LDB_SUCCESS:
 		return NT_STATUS_OK;
-	case LDB_ERR_NO_SUCH_ATTRIBUTE:
+	case LDB_ERR_UNWILLING_TO_PERFORM:
 		return NT_STATUS_MEMBER_NOT_IN_GROUP;
 	case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
 		return NT_STATUS_ACCESS_DENIED;


-- 
Samba Shared Repository


More information about the samba-cvs mailing list