The branch, master has been updated
       via  9401189 s4:samldb LDB module - make the "userAccountControl" and 
"groupType" modify handlers separate functions
       via  098ea71 s4:samldb LDB module - add a new function which handles 
special cases for single-valued attribute on SAM modifications
       via  095c8b2 s4:samldb LDB module - primary group change - free 
temporary messages to save memory
      from  c0ebf5d s4:sam.py - add a short double swap "primaryGroupID" test

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


- Log -----------------------------------------------------------------
commit 9401189d5435632bcc6a177845ce03beaa804113
Author: Matthias Dieter Wallnöfer <m...@samba.org>
Date:   Sat Oct 30 19:56:54 2010 +0200

    s4:samldb LDB module - make the "userAccountControl" and "groupType" modify 
handlers separate functions
    
    It's easier to maintain afterwards
    
    Autobuild-User: Matthias Dieter Wallnöfer <m...@samba.org>
    Autobuild-Date: Sat Oct 30 19:07:20 UTC 2010 on sn-devel-104

commit 098ea71728eb6389ff4c5314d17df533f79a07a8
Author: Matthias Dieter Wallnöfer <m...@samba.org>
Date:   Sat Oct 30 19:37:30 2010 +0200

    s4:samldb LDB module - add a new function which handles special cases for 
single-valued attribute on SAM modifications
    
    This saves quiet some work.

commit 095c8b2078128838f6b830613e80cbdcf49e10cf
Author: Matthias Dieter Wallnöfer <m...@samba.org>
Date:   Sat Oct 30 19:56:24 2010 +0200

    s4:samldb LDB module - primary group change - free temporary messages to 
save memory

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

Summary of changes:
 source4/dsdb/samdb/ldb_modules/samldb.c |  380 ++++++++++++++++++------------
 1 files changed, 228 insertions(+), 152 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 44c8fee..9b6d6e0 100644
--- a/source4/dsdb/samdb/ldb_modules/samldb.c
+++ b/source4/dsdb/samdb/ldb_modules/samldb.c
@@ -751,6 +751,53 @@ static int samldb_schema_info_update(struct samldb_ctx *ac)
 }
 
 /*
+ * Gets back a single-valued attribute by the rules of the SAM triggers when
+ * performing a modify operation
+ */
+static int samldb_get_single_valued_attr(struct samldb_ctx *ac,
+                                        const char *attr_name,
+                                        struct ldb_message_element **attr)
+{
+       struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
+       struct ldb_message_element *el = NULL;
+       unsigned int i;
+
+       /* We've to walk over all modification entries and consider the
+        * "attr_name" 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.
+        */
+       for (i = 0; i < ac->msg->num_elements; i++) {
+               if (ldb_attr_cmp(ac->msg->elements[i].name, attr_name) != 0) {
+                       continue;
+               }
+
+               el = &ac->msg->elements[i];
+               if (LDB_FLAG_MOD_TYPE(el->flags) == LDB_FLAG_MOD_ADD) {
+                       ldb_asprintf_errstring(ldb,
+                                              "samldb: attribute '%s' already 
exists!",
+                                              attr_name);
+                       return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
+               }
+               if (LDB_FLAG_MOD_TYPE(el->flags) == LDB_FLAG_MOD_DELETE) {
+                       ldb_asprintf_errstring(ldb,
+                                              "samldb: attribute '%s' cannot 
be deleted!",
+                                              attr_name);
+                       return LDB_ERR_UNWILLING_TO_PERFORM;
+               }
+       }
+
+       *attr = el;
+       return LDB_SUCCESS;
+}
+
+/*
  * "Objectclass" trigger (MS-SAMR 3.1.1.8.1)
  *
  * Has to be invoked on "add" and "modify" operations on "user", "computer" and
@@ -1002,41 +1049,17 @@ 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;
-               }
+       ret = samldb_get_single_valued_attr(ac, "primaryGroupID", &el);
+       if (ret != LDB_SUCCESS) {
+               return ret;
        }
        if (el == NULL) {
+               /* we are not affected */
                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,
@@ -1109,7 +1132,7 @@ 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);
+               msg = ldb_msg_new(ac->msg);
                if (msg == NULL) {
                        return ldb_module_oom(ac->module);
                }
@@ -1125,9 +1148,10 @@ static int samldb_prim_group_change(struct samldb_ctx 
*ac)
                if (ret != LDB_SUCCESS) {
                        return ret;
                }
+               talloc_free(msg);
 
                /* Add a "member" attribute for the previous primary group */
-               msg = talloc_zero(ac, struct ldb_message);
+               msg = ldb_msg_new(ac->msg);
                if (msg == NULL) {
                        return ldb_module_oom(ac->module);
                }
@@ -1143,6 +1167,7 @@ static int samldb_prim_group_change(struct samldb_ctx *ac)
                if (ret != LDB_SUCCESS) {
                        return ret;
                }
+               talloc_free(msg);
        }
 
        talloc_free(res);
@@ -1163,6 +1188,169 @@ static int samldb_prim_group_trigger(struct samldb_ctx 
*ac)
        return ret;
 }
 
+static int samldb_user_account_control_change(struct samldb_ctx *ac)
+{
+       struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
+       uint32_t user_account_control, account_type;
+       struct ldb_message_element *el;
+       struct ldb_message *tmp_msg;
+       int ret;
+
+       ret = samldb_get_single_valued_attr(ac, "userAccountControl", &el);
+       if (ret != LDB_SUCCESS) {
+               return ret;
+       }
+       if (el == NULL) {
+               /* we are not affected */
+               return LDB_SUCCESS;
+       }
+
+       /* Create a temporary message for fetching the "userAccountControl" */
+       tmp_msg = ldb_msg_new(ac->msg);
+       if (tmp_msg == NULL) {
+               return ldb_module_oom(ac->module);
+       }
+       ret = ldb_msg_add(tmp_msg, el, 0);
+       if (ret != LDB_SUCCESS) {
+               return ret;
+       }
+       user_account_control = ldb_msg_find_attr_as_uint(tmp_msg,
+                                                        "userAccountControl",
+                                                        0);
+       talloc_free(tmp_msg);
+
+       /* Temporary duplicate accounts aren't allowed */
+       if ((user_account_control & UF_TEMP_DUPLICATE_ACCOUNT) != 0) {
+               return LDB_ERR_OTHER;
+       }
+
+       account_type = ds_uf2atype(user_account_control);
+       if (account_type == 0) {
+               ldb_set_errstring(ldb, "samldb: Unrecognized account type!");
+               return LDB_ERR_UNWILLING_TO_PERFORM;
+       }
+       ret = samdb_msg_add_uint(ldb, ac->msg, ac->msg, "sAMAccountType",
+                                account_type);
+       if (ret != LDB_SUCCESS) {
+               return ret;
+       }
+       el = ldb_msg_find_element(ac->msg, "sAMAccountType");
+       el->flags = LDB_FLAG_MOD_REPLACE;
+
+       if (user_account_control
+           & (UF_SERVER_TRUST_ACCOUNT | UF_PARTIAL_SECRETS_ACCOUNT)) {
+               ret = samdb_msg_add_string(ldb, ac->msg, ac->msg,
+                                          "isCriticalSystemObject", "TRUE");
+               if (ret != LDB_SUCCESS) {
+                       return ret;
+               }
+               el = ldb_msg_find_element(ac->msg,
+                                          "isCriticalSystemObject");
+               el->flags = LDB_FLAG_MOD_REPLACE;
+       }
+
+       if (!ldb_msg_find_element(ac->msg, "primaryGroupID")) {
+               uint32_t rid = ds_uf2prim_group_rid(user_account_control);
+               ret = samdb_msg_add_uint(ldb, ac->msg, ac->msg,
+                                        "primaryGroupID", rid);
+               if (ret != LDB_SUCCESS) {
+                       return ret;
+               }
+               el = ldb_msg_find_element(ac->msg,
+                                          "primaryGroupID");
+               el->flags = LDB_FLAG_MOD_REPLACE;
+       }
+
+       return LDB_SUCCESS;
+}
+
+static int samldb_group_type_change(struct samldb_ctx *ac)
+{
+       struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
+       uint32_t group_type, old_group_type, account_type;
+       struct ldb_message_element *el;
+       struct ldb_message *tmp_msg;
+       int ret;
+
+       ret = samldb_get_single_valued_attr(ac, "groupType", &el);
+       if (ret != LDB_SUCCESS) {
+               return ret;
+       }
+       if (el == NULL) {
+               /* we are not affected */
+               return LDB_SUCCESS;
+       }
+
+       /* Create a temporary message for fetching the "groupType" */
+       tmp_msg = ldb_msg_new(ac->msg);
+       if (tmp_msg == NULL) {
+               return ldb_module_oom(ac->module);
+       }
+       ret = ldb_msg_add(tmp_msg, el, 0);
+       if (ret != LDB_SUCCESS) {
+               return ret;
+       }
+       group_type = ldb_msg_find_attr_as_uint(tmp_msg, "groupType", 0);
+       talloc_free(tmp_msg);
+
+       old_group_type = samdb_search_uint(ldb, ac, 0, ac->msg->dn,
+                                          "groupType", NULL);
+       if (old_group_type == 0) {
+               return ldb_operr(ldb);
+       }
+
+       /* Group type switching isn't so easy as it seems: We can only
+        * change in this directions: global <-> universal <-> local
+        * On each step also the group type itself
+        * (security/distribution) is variable. */
+
+       switch (group_type) {
+       case GTYPE_SECURITY_GLOBAL_GROUP:
+       case GTYPE_DISTRIBUTION_GLOBAL_GROUP:
+               /* change to "universal" allowed */
+               if ((old_group_type == GTYPE_SECURITY_DOMAIN_LOCAL_GROUP) ||
+                   (old_group_type == GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP)) {
+                       return LDB_ERR_UNWILLING_TO_PERFORM;
+               }
+       break;
+
+       case GTYPE_SECURITY_UNIVERSAL_GROUP:
+       case GTYPE_DISTRIBUTION_UNIVERSAL_GROUP:
+               /* each change allowed */
+       break;
+
+       case GTYPE_SECURITY_DOMAIN_LOCAL_GROUP:
+       case GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP:
+               /* change to "universal" allowed */
+               if ((old_group_type == GTYPE_SECURITY_GLOBAL_GROUP) ||
+                   (old_group_type == GTYPE_DISTRIBUTION_GLOBAL_GROUP)) {
+                       return LDB_ERR_UNWILLING_TO_PERFORM;
+               }
+       break;
+
+       case GTYPE_SECURITY_BUILTIN_LOCAL_GROUP:
+       default:
+               /* we don't allow this "groupType" values */
+               return LDB_ERR_UNWILLING_TO_PERFORM;
+       break;
+       }
+
+       account_type =  ds_gtype2atype(group_type);
+       if (account_type == 0) {
+               ldb_set_errstring(ldb, "samldb: Unrecognized account type!");
+               return LDB_ERR_UNWILLING_TO_PERFORM;
+       }
+       ret = samdb_msg_add_uint(ldb, ac->msg, ac->msg, "sAMAccountType",
+                                account_type);
+       if (ret != LDB_SUCCESS) {
+               return ret;
+       }
+       el = ldb_msg_find_element(ac->msg, "sAMAccountType");
+       el->flags = LDB_FLAG_MOD_REPLACE;
+
+       return LDB_SUCCESS;
+}
+
 static int samldb_member_check(struct samldb_ctx *ac)
 {
        struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
@@ -1354,10 +1542,9 @@ static int samldb_modify(struct ldb_module *module, 
struct ldb_request *req)
 {
        struct ldb_context *ldb;
        struct samldb_ctx *ac;
-       struct ldb_message_element *el, *el2;
+       struct ldb_message_element *el;
        bool modified = false;
        int ret;
-       uint32_t account_type;
 
        if (ldb_dn_is_special(req->op.mod.message->dn)) {
                /* do not manipulate our control entries */
@@ -1406,75 +1593,6 @@ static int samldb_modify(struct ldb_module *module, 
struct ldb_request *req)
                return ldb_operr(ldb);
        }
 
-       el = ldb_msg_find_element(ac->msg, "groupType");
-       if (el && (LDB_FLAG_MOD_TYPE(el->flags) == LDB_FLAG_MOD_REPLACE)
-           && el->num_values == 1) {
-               uint32_t group_type, old_group_type;
-
-               modified = true;
-
-               group_type = ldb_msg_find_attr_as_uint(ac->msg, "groupType", 0);
-               old_group_type = samdb_search_uint(ldb, ac, 0, ac->msg->dn,
-                                                  "groupType", NULL);
-               if (old_group_type == 0) {
-                       return ldb_operr(ldb);
-               }
-
-               /* Group type switching isn't so easy as it seems: We can only
-                * change in this directions: global <-> universal <-> local
-                * On each step also the group type itself
-                * (security/distribution) is variable. */
-
-               switch (group_type) {
-               case GTYPE_SECURITY_GLOBAL_GROUP:
-               case GTYPE_DISTRIBUTION_GLOBAL_GROUP:
-                       /* change to "universal" allowed */
-                       if ((old_group_type == 
GTYPE_SECURITY_DOMAIN_LOCAL_GROUP) ||
-                           (old_group_type == 
GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP)) {
-                               return LDB_ERR_UNWILLING_TO_PERFORM;
-                       }
-               break;
-
-               case GTYPE_SECURITY_UNIVERSAL_GROUP:
-               case GTYPE_DISTRIBUTION_UNIVERSAL_GROUP:
-                       /* each change allowed */
-               break;
-
-               case GTYPE_SECURITY_DOMAIN_LOCAL_GROUP:
-               case GTYPE_DISTRIBUTION_DOMAIN_LOCAL_GROUP:
-                       /* change to "universal" allowed */
-                       if ((old_group_type == GTYPE_SECURITY_GLOBAL_GROUP) ||
-                           (old_group_type == 
GTYPE_DISTRIBUTION_GLOBAL_GROUP)) {
-                               return LDB_ERR_UNWILLING_TO_PERFORM;
-                       }
-               break;
-
-               case GTYPE_SECURITY_BUILTIN_LOCAL_GROUP:
-               default:
-                       /* we don't allow this "groupType" values */
-                       return LDB_ERR_UNWILLING_TO_PERFORM;
-               break;
-               }
-
-               account_type =  ds_gtype2atype(group_type);
-               if (account_type == 0) {
-                       ldb_set_errstring(ldb, "samldb: Unrecognized account 
type!");
-                       return LDB_ERR_UNWILLING_TO_PERFORM;
-               }
-               ret = samdb_msg_add_uint(ldb, ac->msg, ac->msg,
-                                        "sAMAccountType",
-                                        account_type);
-               if (ret != LDB_SUCCESS) {
-                       return ret;
-               }
-               el2 = ldb_msg_find_element(ac->msg, "sAMAccountType");
-               el2->flags = LDB_FLAG_MOD_REPLACE;
-       }
-       el = ldb_msg_find_element(ac->msg, "groupType");
-       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, "primaryGroupID");
        if (el != NULL) {
                ret = samldb_prim_group_change(ac);
@@ -1484,64 +1602,22 @@ static int samldb_modify(struct ldb_module *module, 
struct ldb_request *req)
        }
 
        el = ldb_msg_find_element(ac->msg, "userAccountControl");
-       if (el && (LDB_FLAG_MOD_TYPE(el->flags) == LDB_FLAG_MOD_REPLACE)
-           && el->num_values == 1) {
-               uint32_t user_account_control;
-
+       if (el != NULL) {
                modified = true;
-
-               user_account_control = ldb_msg_find_attr_as_uint(ac->msg,
-                                                                
"userAccountControl",
-                                                                0);
-
-               /* Temporary duplicate accounts aren't allowed */
-               if ((user_account_control & UF_TEMP_DUPLICATE_ACCOUNT) != 0) {
-                       return LDB_ERR_OTHER;
-               }
-
-               account_type = ds_uf2atype(user_account_control);
-               if (account_type == 0) {
-                       ldb_set_errstring(ldb, "samldb: Unrecognized account 
type!");
-                       return LDB_ERR_UNWILLING_TO_PERFORM;
-               }
-               ret = samdb_msg_add_uint(ldb, ac->msg, ac->msg,
-                                        "sAMAccountType",
-                                        account_type);
+               ret = samldb_user_account_control_change(ac);
                if (ret != LDB_SUCCESS) {
                        return ret;
                }
-               el2 = ldb_msg_find_element(ac->msg, "sAMAccountType");
-               el2->flags = LDB_FLAG_MOD_REPLACE;
-
-               if (user_account_control & (UF_SERVER_TRUST_ACCOUNT | 
UF_PARTIAL_SECRETS_ACCOUNT)) {
-                       ret = samdb_msg_add_string(ldb, ac->msg, ac->msg,
-                                                  "isCriticalSystemObject",
-                                                  "TRUE");
-                       if (ret != LDB_SUCCESS) {
-                               return ret;
-                       }
-                       el2 = ldb_msg_find_element(ac->msg,
-                                                  "isCriticalSystemObject");
-                       el2->flags = LDB_FLAG_MOD_REPLACE;
-               }
-
-               if (!ldb_msg_find_element(ac->msg, "primaryGroupID")) {
-                       uint32_t rid = 
ds_uf2prim_group_rid(user_account_control);
+       }
 
-                       ret = samdb_msg_add_uint(ldb, ac->msg, ac->msg,
-                                                "primaryGroupID", rid);
-                       if (ret != LDB_SUCCESS) {
-                               return ret;
-                       }
-                       el2 = ldb_msg_find_element(ac->msg,
-                                                  "primaryGroupID");
-                       el2->flags = LDB_FLAG_MOD_REPLACE;
+       el = ldb_msg_find_element(ac->msg, "groupType");
+       if (el != NULL) {
+               modified = true;
+               ret = samldb_group_type_change(ac);
+               if (ret != LDB_SUCCESS) {
+                       return ret;
                }
        }
-       el = ldb_msg_find_element(ac->msg, "userAccountControl");
-       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, "member");
        if (el != NULL) {


-- 
Samba Shared Repository

Reply via email to