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 <m...@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 <m...@samba.org>
    Autobuild-Date: Sat Oct 30 18:15:31 UTC 2010 on sn-devel-104

commit 98fefa8a017bbb67f6c33080c8a80c77c34e42b8
Author: Matthias Dieter Wallnöfer <m...@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 <m...@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 <m...@samba.org>
Date:   Sat Oct 30 18:09:12 2010 +0200

    s4:sam.py - enhance "member" tests

commit 4987467b785a5870cb338881c8916b4268006cd6
Author: Matthias Dieter Wallnöfer <m...@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 <m...@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

Reply via email to