s4:samldb LDB module - "samldb_check_primaryGroupID" - support RID derivation from...
[samba.git] / source4 / dsdb / samdb / ldb_modules / samldb.c
index e616295e3a529009174a35f20c1c9a03af542b47..7fa27e8a91fae6d8fbba60a9db4c1f14c8fd2b53 100644 (file)
@@ -259,7 +259,11 @@ static int samldb_check_primaryGroupID(struct samldb_ctx *ac)
 
        rid = samdb_result_uint(ac->msg, "primaryGroupID", (uint32_t) -1);
        if (rid == (uint32_t) -1) {
-               rid = DOMAIN_RID_USERS;
+               uint32_t uac = samdb_result_uint(ac->msg, "userAccountControl",
+                                                0);
+
+               rid = ds_uf2prim_group_rid(uac);
+
                ret = samdb_msg_add_uint(ldb, ac->msg, ac->msg,
                                         "primaryGroupID", rid);
                if (ret != LDB_SUCCESS) {
@@ -1052,47 +1056,6 @@ static int samldb_member_check(struct samldb_ctx *ac)
 }
 
 
-static int samldb_prim_group_users_check(struct samldb_ctx *ac)
-{
-       struct ldb_context *ldb;
-       struct dom_sid *sid;
-       uint32_t rid;
-       NTSTATUS status;
-       int count;
-
-       ldb = ldb_module_get_ctx(ac->module);
-
-       /* Finds out the SID/RID of the SAM object */
-       sid = samdb_search_dom_sid(ldb, ac, ac->req->op.del.dn, "objectSID",
-                                  NULL);
-       if (sid == NULL) {
-               /* No SID - it might not be a SAM object - therefore ok */
-               return LDB_SUCCESS;
-       }
-       status = dom_sid_split_rid(ac, sid, NULL, &rid);
-       if (!NT_STATUS_IS_OK(status)) {
-               return ldb_operr(ldb);
-       }
-       if (rid == 0) {
-               /* Special object (security principal?) */
-               return LDB_SUCCESS;
-       }
-
-       /* Deny delete requests from groups which are primary ones */
-       count = samdb_search_count(ldb, NULL,
-                                  "(&(primaryGroupID=%u)(objectClass=user))",
-                                  rid);
-       if (count < 0) {
-               return ldb_operr(ldb);
-       }
-       if (count > 0) {
-               return LDB_ERR_ENTRY_ALREADY_EXISTS;
-       }
-
-       return LDB_SUCCESS;
-}
-
-
 /* add */
 static int samldb_add(struct ldb_module *module, struct ldb_request *req)
 {
@@ -1114,11 +1077,9 @@ static int samldb_add(struct ldb_module *module, struct ldb_request *req)
        }
 
        /* build the new msg */
-       ac->msg = ldb_msg_copy(ac, ac->req->op.add.message);
-       if (!ac->msg) {
-               talloc_free(ac);
-               ldb_debug(ldb, LDB_DEBUG_FATAL,
-                         "samldb_add: ldb_msg_copy failed!\n");
+       req->op.add.message = ac->msg = ldb_msg_copy_shallow(req,
+                                                            req->op.add.message);
+       if (ac->msg == NULL) {
                return ldb_operr(ldb);
        }
 
@@ -1172,7 +1133,6 @@ static int samldb_modify(struct ldb_module *module, struct ldb_request *req)
 {
        struct ldb_context *ldb;
        struct samldb_ctx *ac;
-       struct ldb_message *msg;
        struct ldb_message_element *el, *el2;
        int ret;
        uint32_t account_type;
@@ -1203,35 +1163,34 @@ static int samldb_modify(struct ldb_module *module, struct ldb_request *req)
                return ldb_operr(ldb);
        }
 
-       /* TODO: do not modify original request, create a new one */
+       /* build the new msg */
+       req->op.mod.message = ac->msg = ldb_msg_copy_shallow(req,
+                                                            req->op.mod.message);
+       if (ac->msg == NULL) {
+               return ldb_operr(ldb);
+       }
 
-       el = ldb_msg_find_element(req->op.mod.message, "groupType");
+       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;
 
-               req->op.mod.message = msg = ldb_msg_copy_shallow(req,
-                       req->op.mod.message);
-
                group_type = strtoul((const char *)el->values[0].data, NULL, 0);
                account_type =  ds_gtype2atype(group_type);
-               ret = samdb_msg_add_uint(ldb, msg, msg,
+               ret = samdb_msg_add_uint(ldb, ac->msg, ac->msg,
                                         "sAMAccountType",
                                         account_type);
                if (ret != LDB_SUCCESS) {
                        return ret;
                }
-               el2 = ldb_msg_find_element(msg, "sAMAccountType");
+               el2 = ldb_msg_find_element(ac->msg, "sAMAccountType");
                el2->flags = LDB_FLAG_MOD_REPLACE;
        }
        if (el && (LDB_FLAG_MOD_TYPE(el->flags) == LDB_FLAG_MOD_DELETE)) {
                return LDB_ERR_UNWILLING_TO_PERFORM;
        }
 
-       el = ldb_msg_find_element(req->op.mod.message, "primaryGroupID");
+       el = ldb_msg_find_element(ac->msg, "primaryGroupID");
        if (el && (LDB_FLAG_MOD_TYPE(el->flags) == LDB_FLAG_MOD_REPLACE) && el->num_values == 1) {
-               req->op.mod.message = ac->msg = ldb_msg_copy_shallow(req,
-                       req->op.mod.message);
-
                ret = samldb_prim_group_change(ac);
                if (ret != LDB_SUCCESS) {
                        return ret;
@@ -1241,36 +1200,35 @@ static int samldb_modify(struct ldb_module *module, struct ldb_request *req)
                return LDB_ERR_UNWILLING_TO_PERFORM;
        }
 
-       el = ldb_msg_find_element(req->op.mod.message, "userAccountControl");
+       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;
 
-               req->op.mod.message = msg = ldb_msg_copy_shallow(req,
-                       req->op.mod.message);
-
                user_account_control = strtoul((const char *)el->values[0].data,
                        NULL, 0);
                account_type = ds_uf2atype(user_account_control);
-               ret = samdb_msg_add_uint(ldb, msg, msg,
+               ret = samdb_msg_add_uint(ldb, ac->msg, ac->msg,
                                         "sAMAccountType",
                                         account_type);
                if (ret != LDB_SUCCESS) {
                        return ret;
                }
-               el2 = ldb_msg_find_element(msg, "sAMAccountType");
+               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, msg, msg,
-                                                  "isCriticalSystemObject", "TRUE");
+                       ret = samdb_msg_add_string(ldb, ac->msg, ac->msg,
+                                                  "isCriticalSystemObject",
+                                                  "TRUE");
                        if (ret != LDB_SUCCESS) {
                                return ret;
                        }
-                       el2 = ldb_msg_find_element(msg, "isCriticalSystemObject");
+                       el2 = ldb_msg_find_element(ac->msg,
+                                                  "isCriticalSystemObject");
                        el2->flags = LDB_FLAG_MOD_REPLACE;
 
                        /* DCs have primaryGroupID of DOMAIN_RID_DCS */
-                       if (!ldb_msg_find_element(msg, "primaryGroupID")) {
+                       if (!ldb_msg_find_element(ac->msg, "primaryGroupID")) {
                                uint32_t rid;
                                if (user_account_control & UF_SERVER_TRUST_ACCOUNT) {
                                        rid = DOMAIN_RID_DCS;
@@ -1278,12 +1236,13 @@ static int samldb_modify(struct ldb_module *module, struct ldb_request *req)
                                        /* read-only DC */
                                        rid = DOMAIN_RID_READONLY_DCS;
                                }
-                               ret = samdb_msg_add_uint(ldb, msg, msg,
+                               ret = samdb_msg_add_uint(ldb, ac->msg, ac->msg,
                                                         "primaryGroupID", rid);
                                if (ret != LDB_SUCCESS) {
                                        return ret;
                                }
-                               el2 = ldb_msg_find_element(msg, "primaryGroupID");
+                               el2 = ldb_msg_find_element(ac->msg,
+                                                          "primaryGroupID");
                                el2->flags = LDB_FLAG_MOD_REPLACE;
                        }
                }
@@ -1292,21 +1251,61 @@ static int samldb_modify(struct ldb_module *module, struct ldb_request *req)
                return LDB_ERR_UNWILLING_TO_PERFORM;
        }
 
-       el = ldb_msg_find_element(req->op.mod.message, "member");
+       el = ldb_msg_find_element(ac->msg, "member");
        if (el && el->flags & (LDB_FLAG_MOD_ADD|LDB_FLAG_MOD_REPLACE) && el->num_values == 1) {
-               req->op.mod.message = ac->msg = ldb_msg_copy_shallow(req,
-                       req->op.mod.message);
-
                ret = samldb_member_check(ac);
                if (ret != LDB_SUCCESS) {
                        return ret;
                }
        }
 
+       talloc_free(ac);
+
        return ldb_next_request(module, req);
 }
 
 /* delete */
+
+static int samldb_prim_group_users_check(struct samldb_ctx *ac)
+{
+       struct ldb_context *ldb;
+       struct dom_sid *sid;
+       uint32_t rid;
+       NTSTATUS status;
+       int count;
+
+       ldb = ldb_module_get_ctx(ac->module);
+
+       /* Finds out the SID/RID of the SAM object */
+       sid = samdb_search_dom_sid(ldb, ac, ac->req->op.del.dn, "objectSID",
+                                  NULL);
+       if (sid == NULL) {
+               /* No SID - it might not be a SAM object - therefore ok */
+               return LDB_SUCCESS;
+       }
+       status = dom_sid_split_rid(ac, sid, NULL, &rid);
+       if (!NT_STATUS_IS_OK(status)) {
+               return ldb_operr(ldb);
+       }
+       if (rid == 0) {
+               /* Special object (security principal?) */
+               return LDB_SUCCESS;
+       }
+
+       /* Deny delete requests from groups which are primary ones */
+       count = samdb_search_count(ldb, NULL,
+                                  "(&(primaryGroupID=%u)(objectClass=user))",
+                                  rid);
+       if (count < 0) {
+               return ldb_operr(ldb);
+       }
+       if (count > 0) {
+               return LDB_ERR_ENTRY_ALREADY_EXISTS;
+       }
+
+       return LDB_SUCCESS;
+}
+
 static int samldb_delete(struct ldb_module *module, struct ldb_request *req)
 {
        struct samldb_ctx *ac;
@@ -1318,14 +1317,17 @@ static int samldb_delete(struct ldb_module *module, struct ldb_request *req)
        }
 
        ac = samldb_ctx_init(module, req);
-       if (ac == NULL)
+       if (ac == NULL) {
                return ldb_operr(ldb_module_get_ctx(module));
+       }
 
        ret = samldb_prim_group_users_check(ac);
        if (ret != LDB_SUCCESS) {
                return ret;
        }
 
+       talloc_free(ac);
+
        return ldb_next_request(module, req);
 }