s4:samldb LDB module - assign better memory contexts on two places
[mat/samba.git] / source4 / dsdb / samdb / ldb_modules / samldb.c
index 021be263000f57a47c4b774aacb43fad3e44e979..0e4d852d1562b243dfa68dceb0b7eaf64d997d5d 100644 (file)
@@ -59,11 +59,8 @@ struct samldb_ctx {
        /* the resulting message */
        struct ldb_message *msg;
 
-       /* holds a generic dn */
-       struct ldb_dn *dn;
-
        /* used in "samldb_find_for_defaultObjectCategory" */
-       struct ldb_dn *res_dn;
+       struct ldb_dn *dn, *res_dn;
 
        /* all the async steps necessary to complete the operation */
        struct samldb_step *steps;
@@ -262,12 +259,20 @@ 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) {
                        return ret;
                }
+       } else if (!ldb_request_get_control(ac->req, LDB_CONTROL_RELAX_OID)) {
+               ldb_set_errstring(ldb,
+                                 "The primary group isn't settable on add operations!");
+               return LDB_ERR_UNWILLING_TO_PERFORM;
        }
 
        sid = dom_sid_add_rid(ac, samdb_domain_sid(ldb), rid);
@@ -275,8 +280,8 @@ static int samldb_check_primaryGroupID(struct samldb_ctx *ac)
                return ldb_operr(ldb);
        }
 
-       prim_group_dn = samdb_search_dn(ldb, ac, NULL, "(objectSID=%s)",
-                                       dom_sid_string(ac, sid));
+       prim_group_dn = samdb_search_dn(ldb, ac, NULL, "(objectSid=%s)",
+                                       ldap_encode_ndr_dom_sid(ac, sid));
        if (prim_group_dn == NULL) {
                ldb_asprintf_errstring(ldb,
                                       "Failed to find primary group with RID %u!",
@@ -356,6 +361,7 @@ static int samldb_rodc_add(struct samldb_ctx *ac)
        struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
        unsigned krbtgt_number, i_start, i;
        int ret;
+       char *newpass;
 
        /* find a unused msDC-SecondaryKrbTgtNumber */
        i_start = generate_random() & 0xFFFF;
@@ -397,109 +403,50 @@ found:
                return ldb_operr(ldb);
        }
 
-       return samldb_next_step(ac);
-}
-
-
-/*
- * samldb_find_for_defaultObjectCategory (async)
- */
-
-static int samldb_find_for_defaultObjectCategory_callback(struct ldb_request *req,
-                                                         struct ldb_reply *ares)
-{
-       struct ldb_context *ldb;
-       struct samldb_ctx *ac;
-       int ret;
-
-       ac = talloc_get_type(req->context, struct samldb_ctx);
-       ldb = ldb_module_get_ctx(ac->module);
-
-       if (!ares) {
-               ret = LDB_ERR_OPERATIONS_ERROR;
-               goto done;
-       }
-       if (ares->error != LDB_SUCCESS) {
-               if (ares->error == LDB_ERR_NO_SUCH_OBJECT) {
-                       if (ldb_request_get_control(ac->req,
-                                                   LDB_CONTROL_RELAX_OID) != NULL) {
-                               /* Don't be pricky when the DN doesn't exist */
-                               /* if we have the RELAX control specified */
-                               ac->res_dn = req->op.search.base;
-                               return samldb_next_step(ac);
-                       } else {
-                               ldb_set_errstring(ldb,
-                                       "samldb_find_defaultObjectCategory: "
-                                       "Invalid DN for 'defaultObjectCategory'!");
-                               ares->error = LDB_ERR_CONSTRAINT_VIOLATION;
-                       }
-               }
-
-               return ldb_module_done(ac->req, ares->controls,
-                                       ares->response, ares->error);
-       }
-
-       switch (ares->type) {
-       case LDB_REPLY_ENTRY:
-               ac->res_dn = talloc_steal(ac, ares->message->dn);
-
-               ret = LDB_SUCCESS;
-               break;
-
-       case LDB_REPLY_REFERRAL:
-               /* ignore */
-               talloc_free(ares);
-               ret = LDB_SUCCESS;
-               break;
-
-       case LDB_REPLY_DONE:
-               talloc_free(ares);
-
-               if (ac->res_dn != NULL) {
-                       /* when found go on */
-                       ret = samldb_next_step(ac);
-               } else {
-                       ret = LDB_ERR_OPERATIONS_ERROR;
-               }
-               break;
+       newpass = generate_random_password(ac, 128, 255);
+       if (newpass == NULL) {
+               return ldb_operr(ldb);
        }
 
-done:
+       ret = ldb_msg_add_steal_string(ac->msg, "clearTextPassword", newpass);
        if (ret != LDB_SUCCESS) {
-               return ldb_module_done(ac->req, NULL, NULL, ret);
+               return ldb_operr(ldb);
        }
 
-       return LDB_SUCCESS;
+       return samldb_next_step(ac);
 }
 
 static int samldb_find_for_defaultObjectCategory(struct samldb_ctx *ac)
 {
-       struct ldb_context *ldb;
-       struct ldb_request *req;
-       static const char *no_attrs[] = { NULL };
+       struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
+       struct ldb_result *res;
+       const char *no_attrs[] = { NULL };
         int ret;
 
-       ldb = ldb_module_get_ctx(ac->module);
-
        ac->res_dn = NULL;
 
-       ret = ldb_build_search_req(&req, ldb, ac,
-                                  ac->dn, LDB_SCOPE_BASE,
-                                  "(objectClass=classSchema)", no_attrs,
-                                  NULL, ac,
-                                  samldb_find_for_defaultObjectCategory_callback,
-                                  ac->req);
-       if (ret != LDB_SUCCESS) {
-               return ret;
+       ret = dsdb_module_search(ac->module, ac, &res,
+                                ac->dn, LDB_SCOPE_BASE, no_attrs,
+                                DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT | DSDB_FLAG_NEXT_MODULE,
+                                "(objectClass=classSchema)");
+       if (ret == LDB_ERR_NO_SUCH_OBJECT) {
+               /* Don't be pricky when the DN doesn't exist if we have the */
+               /* RELAX control specified */
+               if (ldb_request_get_control(ac->req,
+                                           LDB_CONTROL_RELAX_OID) == NULL) {
+                       ldb_set_errstring(ldb,
+                                         "samldb_find_defaultObjectCategory: "
+                                         "Invalid DN for 'defaultObjectCategory'!");
+                       return LDB_ERR_CONSTRAINT_VIOLATION;
+               }
        }
-
-       ret = dsdb_request_add_controls(req,
-                                       DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT);
-       if (ret != LDB_SUCCESS) {
+       if ((ret != LDB_ERR_NO_SUCH_OBJECT) && (ret != LDB_SUCCESS)) {
                return ret;
        }
 
-       return ldb_next_request(ac->module, req);
+       ac->res_dn = ac->dn;
+
+       return samldb_next_step(ac);
 }
 
 /**
@@ -636,6 +583,7 @@ static int samldb_add_entry(struct samldb_ctx *ac)
                                ac->req->controls,
                                ac, samldb_add_entry_callback,
                                ac->req);
+       LDB_REQ_SET_LOCATION(req);
        if (ret != LDB_SUCCESS) {
                return ret;
        }
@@ -773,7 +721,7 @@ static int samldb_fill_object(struct samldb_ctx *ac, const char *type)
                         * caller. Use the entry DN for it. */
                        ac->dn = ac->msg->dn;
 
-                       ret = samdb_msg_add_string(ldb, ac, ac->msg,
+                       ret = samdb_msg_add_string(ldb, ac->msg, ac->msg,
                                                   "defaultObjectCategory",
                                                   ldb_dn_get_linearized(ac->dn));
                        if (ret != LDB_SUCCESS) {
@@ -797,7 +745,7 @@ static int samldb_fill_object(struct samldb_ctx *ac, const char *type)
                if (!ldb_msg_find_element(ac->msg, "lDAPDisplayName")) {
                        /* the RDN has prefix "CN" */
                        ret = ldb_msg_add_string(ac->msg, "lDAPDisplayName",
-                               samdb_cn_to_lDAPDisplayName(ac,
+                               samdb_cn_to_lDAPDisplayName(ac->msg,
                                        (const char *) rdn_value->data));
                        if (ret != LDB_SUCCESS) {
                                ldb_oom(ldb);
@@ -867,7 +815,7 @@ static int samldb_fill_object(struct samldb_ctx *ac, const char *type)
        lp_ctx = talloc_get_type(ldb_get_opaque(ldb, "loadparm"),
                 struct loadparm_context);
 
-       /* don't allow objectSID to be specified without the RELAX control */
+       /* don't allow objectSid to be specified without the RELAX control */
        sid = samdb_result_dom_sid(ac, ac->msg, "objectSid");
        if (sid && !ldb_request_get_control(ac->req, LDB_CONTROL_RELAX_OID) &&
            !dsdb_module_am_system(ac->module)) {
@@ -997,8 +945,8 @@ static int samldb_prim_group_change(struct samldb_ctx *ac)
                return ldb_operr(ldb);
        }
 
-       prev_prim_group_dn = samdb_search_dn(ldb, ac, NULL, "(objectSID=%s)",
-                                            dom_sid_string(ac, sid));
+       prev_prim_group_dn = samdb_search_dn(ldb, ac, NULL, "(objectSid=%s)",
+                                            ldap_encode_ndr_dom_sid(ac, sid));
        if (prev_prim_group_dn == NULL) {
                return ldb_operr(ldb);
        }
@@ -1016,8 +964,8 @@ static int samldb_prim_group_change(struct samldb_ctx *ac)
                return ldb_operr(ldb);
        }
 
-       new_prim_group_dn = samdb_search_dn(ldb, ac, NULL, "(objectSID=%s)",
-                                           dom_sid_string(ac, sid));
+       new_prim_group_dn = samdb_search_dn(ldb, ac, NULL, "(objectSid=%s)",
+                                           ldap_encode_ndr_dom_sid(ac, sid));
        if (new_prim_group_dn == NULL) {
                /* Here we know if the specified new primary group candidate is
                 * valid or not. */
@@ -1109,8 +1057,8 @@ static int samldb_member_check(struct samldb_ctx *ac)
                        return ldb_operr(ldb);
                }
 
-               group_dn = samdb_search_dn(ldb, ac, NULL, "(objectSID=%s)",
-                                          dom_sid_string(ac, sid));
+               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);
                }
@@ -1124,47 +1072,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)
 {
@@ -1340,24 +1247,19 @@ static int samldb_modify(struct ldb_module *module, struct ldb_request *req)
                        }
                        el2 = ldb_msg_find_element(msg, "isCriticalSystemObject");
                        el2->flags = LDB_FLAG_MOD_REPLACE;
+               }
+
+               if (!ldb_msg_find_element(msg, "primaryGroupID")) {
+                       uint32_t rid = ds_uf2prim_group_rid(user_account_control);
 
-                       /* DCs have primaryGroupID of DOMAIN_RID_DCS */
-                       if (!ldb_msg_find_element(msg, "primaryGroupID")) {
-                               uint32_t rid;
-                               if (user_account_control & UF_SERVER_TRUST_ACCOUNT) {
-                                       rid = DOMAIN_RID_DCS;
-                               } else {
-                                       /* read-only DC */
-                                       rid = DOMAIN_RID_READONLY_DCS;
-                               }
-                               ret = samdb_msg_add_uint(ldb, msg, msg,
-                                                        "primaryGroupID", rid);
-                               if (ret != LDB_SUCCESS) {
-                                       return ret;
-                               }
-                               el2 = ldb_msg_find_element(msg, "primaryGroupID");
-                               el2->flags = LDB_FLAG_MOD_REPLACE;
+                       ret = samdb_msg_add_uint(ldb, msg, msg,
+                                                "primaryGroupID", rid);
+                       if (ret != LDB_SUCCESS) {
+                               return ret;
                        }
+                       el2 = ldb_msg_find_element(msg,
+                                                  "primaryGroupID");
+                       el2->flags = LDB_FLAG_MOD_REPLACE;
                }
        }
        if (el && (LDB_FLAG_MOD_TYPE(el->flags) == LDB_FLAG_MOD_DELETE)) {
@@ -1379,6 +1281,47 @@ static int samldb_modify(struct ldb_module *module, struct ldb_request *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;
@@ -1390,17 +1333,22 @@ 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);
 }
 
+/* extended */
+
 static int samldb_extended_allocate_rid_pool(struct ldb_module *module, struct ldb_request *req)
 {
        struct ldb_context *ldb = ldb_module_get_ctx(module);