ldb: Add ldb_oom() calls in a couple of places.
[ira/wip.git] / source / dsdb / samdb / ldb_modules / samldb.c
index c054feadcee34b1e98e0c5f355dc30f6ddd076e6..baf419c750def7db6486ab1c11c45a2ad819a7cc 100644 (file)
  */
 
 #include "includes.h"
-#include "libcli/ldap/ldap.h"
+#include "libcli/ldap/ldap_ndr.h"
 #include "lib/ldb/include/ldb_errors.h"
+#include "lib/ldb/include/ldb.h"
 #include "lib/ldb/include/ldb_private.h"
 #include "dsdb/samdb/samdb.h"
 #include "libcli/security/security.h"
 #include "librpc/gen_ndr/ndr_security.h"
-#include "db_wrap.h"
+#include "util/util_ldb.h"
 
 int samldb_notice_sid(struct ldb_module *module, 
                      TALLOC_CTX *mem_ctx, const struct dom_sid *sid);
@@ -47,10 +48,11 @@ int samldb_notice_sid(struct ldb_module *module,
 static bool samldb_msg_add_sid(struct ldb_module *module, struct ldb_message *msg, const char *name, const struct dom_sid *sid)
 {
        struct ldb_val v;
-       NTSTATUS status;
-       status = ndr_push_struct_blob(&v, msg, sid, 
-                                     (ndr_push_flags_fn_t)ndr_push_dom_sid);
-       if (!NT_STATUS_IS_OK(status)) {
+       enum ndr_err_code ndr_err;
+
+       ndr_err = ndr_push_struct_blob(&v, msg, NULL, sid,
+                                      (ndr_push_flags_fn_t)ndr_push_dom_sid);
+       if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
                return false;
        }
        return (ldb_msg_add_value(msg, name, &v, NULL) == 0);
@@ -70,7 +72,7 @@ static int samldb_set_next_rid(struct ldb_context *ldb, TALLOC_CTX *mem_ctx,
 
        if (new_id == 0) {
                /* out of IDs ! */
-               ldb_debug(ldb, LDB_DEBUG_FATAL, "Are we out of valid IDs ?\n");
+               ldb_set_errstring(ldb, "Are we out of valid IDs ?\n");
                return LDB_ERR_OPERATIONS_ERROR;
        }
 
@@ -79,6 +81,7 @@ static int samldb_set_next_rid(struct ldb_context *ldb, TALLOC_CTX *mem_ctx,
        ZERO_STRUCT(msg);
        msg.dn = ldb_dn_copy(mem_ctx, dn);
        if (!msg.dn) {
+               ldb_oom(ldb);
                return LDB_ERR_OPERATIONS_ERROR;
        }
        msg.num_elements = 2;
@@ -89,6 +92,7 @@ static int samldb_set_next_rid(struct ldb_context *ldb, TALLOC_CTX *mem_ctx,
        els[0].flags = LDB_FLAG_MOD_DELETE;
        els[0].name = talloc_strdup(mem_ctx, "nextRid");
        if (!els[0].name) {
+               ldb_oom(ldb);
                return LDB_ERR_OPERATIONS_ERROR;
        }
 
@@ -99,12 +103,14 @@ static int samldb_set_next_rid(struct ldb_context *ldb, TALLOC_CTX *mem_ctx,
 
        vals[0].data = (uint8_t *)talloc_asprintf(mem_ctx, "%u", old_id);
        if (!vals[0].data) {
+               ldb_oom(ldb);
                return LDB_ERR_OPERATIONS_ERROR;
        }
        vals[0].length = strlen((char *)vals[0].data);
 
        vals[1].data = (uint8_t *)talloc_asprintf(mem_ctx, "%u", new_id);
        if (!vals[1].data) {
+               ldb_oom(ldb);
                return LDB_ERR_OPERATIONS_ERROR;
        }
        vals[1].length = strlen((char *)vals[1].data);
@@ -189,24 +195,16 @@ static int samldb_allocate_next_rid(struct ldb_module *module, TALLOC_CTX *mem_c
 */
 static int samldb_get_new_sid(struct ldb_module *module, 
                              TALLOC_CTX *mem_ctx, struct ldb_dn *obj_dn,
+                             struct ldb_dn *dom_dn, 
                              struct dom_sid **sid)
 {
        const char * const attrs[2] = { "objectSid", NULL };
        struct ldb_result *res = NULL;
-       struct ldb_dn *dom_dn;
        int ret;
        struct dom_sid *dom_sid;
 
        /* get the domain component part of the provided dn */
 
-       dom_dn = samdb_search_for_parent_domain(module->ldb, mem_ctx, obj_dn);
-       if (dom_dn == NULL) {
-               ldb_asprintf_errstring(module->ldb,
-                                       "Invalid dn (%s) not child of a domain object!\n",
-                                       ldb_dn_get_linearized(obj_dn));
-               return LDB_ERR_CONSTRAINT_VIOLATION;
-       }
-
        /* find the domain sid */
 
        ret = ldb_search(module->ldb, dom_dn, LDB_SCOPE_BASE, "objectSid=*", attrs, &res);
@@ -337,13 +335,14 @@ int samldb_notice_sid(struct ldb_module *module,
 }
 
 static int samldb_handle_sid(struct ldb_module *module, 
-                                        TALLOC_CTX *mem_ctx, struct ldb_message *msg2)
+                            TALLOC_CTX *mem_ctx, struct ldb_message *msg2,
+                            struct ldb_dn *parent_dn)
 {
        int ret;
        
        struct dom_sid *sid = samdb_result_dom_sid(mem_ctx, msg2, "objectSid");
        if (sid == NULL) { 
-               ret = samldb_get_new_sid(module, msg2, msg2->dn, &sid);
+               ret = samldb_get_new_sid(module, msg2, msg2->dn, parent_dn, &sid);
                if (ret != 0) {
                        return ret;
                }
@@ -360,31 +359,35 @@ static int samldb_handle_sid(struct ldb_module *module,
        return ret;
 }
 
-static char *samldb_generate_samAccountName(struct ldb_module *module, TALLOC_CTX *mem_ctx) 
+static int samldb_generate_samAccountName(struct ldb_module *module, TALLOC_CTX *mem_ctx, 
+                                         struct ldb_dn *dom_dn, char **name) 
 {
-       char *name;
        const char *attrs[] = { NULL };
-       struct ldb_message **msgs;
+       struct ldb_result *res;
        int ret;
        
        /* Format: $000000-000000000000 */
        
        do {
-               name = talloc_asprintf(mem_ctx, "$%.6X-%.6X%.6X", (unsigned int)random(), (unsigned int)random(), (unsigned int)random());
+               *name = talloc_asprintf(mem_ctx, "$%.6X-%.6X%.6X", (unsigned int)random(), (unsigned int)random(), (unsigned int)random());
                /* TODO: Figure out exactly what this is meant to conflict with */
-               ret = gendb_search(module->ldb,
-                                  mem_ctx, NULL, &msgs, attrs,
-                                  "samAccountName=%s",
-                                  ldb_binary_encode_string(mem_ctx, name));
-               if (ret == 0) {
+               ret = ldb_search_exp_fmt(module->ldb,
+                                        mem_ctx, &res, dom_dn, LDB_SCOPE_SUBTREE, attrs,
+                                        "samAccountName=%s",
+                                        ldb_binary_encode_string(mem_ctx, *name));
+               if (ret != LDB_SUCCESS) {
+                       ldb_asprintf_errstring(module->ldb, "samldb: Failure searching to determine if samAccountName %s is unique: %s",
+                                              *name, ldb_errstring(module->ldb));
+                       return ret;
+               }
+
+               if (res->count == 0) {
+                       talloc_free(res);
                        /* Great. There are no conflicting users/groups/etc */
-                       return name;
-               } else if (ret == -1) {
-                       /* Bugger, there is a problem, and we don't know what it is until gendb_search improves */
-                       return NULL;
+                       return LDB_SUCCESS;
                } else {
-                       talloc_free(name);
-                        /* gah, there are conflicting sids, lets move around the loop again... */
+                       talloc_free(*name);
+                        /* gah, there is a conflicting name, lets move around the loop again... */
                }
        } while (1);
 }
@@ -393,8 +396,9 @@ static int samldb_fill_group_object(struct ldb_module *module, const struct ldb_
                                                    struct ldb_message **ret_msg)
 {
        int ret;
-       const char *name;
+       char *name;
        struct ldb_message *msg2;
+       struct ldb_dn *dom_dn;
        const char *rdn_name;
        TALLOC_CTX *mem_ctx = talloc_new(msg);
        const char *errstr;
@@ -427,12 +431,19 @@ static int samldb_fill_group_object(struct ldb_module *module, const struct ldb_
                return LDB_ERR_CONSTRAINT_VIOLATION;
        }
 
+       ret = samdb_search_for_parent_domain(module->ldb, mem_ctx, msg2->dn, &dom_dn, &errstr);
+       if (ret != LDB_SUCCESS) {
+               ldb_asprintf_errstring(module->ldb,
+                                      "samldb_fill_group_object: %s", errstr);
+               return ret;
+       }
+
        /* Generate a random name, if no samAccountName was supplied */
        if (ldb_msg_find_element(msg2, "samAccountName") == NULL) {
-               name = samldb_generate_samAccountName(module, mem_ctx);
-               if (!name) {
+               ret = samldb_generate_samAccountName(module, mem_ctx, dom_dn, &name);
+               if (ret != LDB_SUCCESS) {
                        talloc_free(mem_ctx);
-                       return LDB_ERR_OPERATIONS_ERROR;
+                       return ret;
                }
                ret = samdb_find_or_add_attribute(module->ldb, msg2, "sAMAccountName", name);
                if (ret) {
@@ -442,7 +453,7 @@ static int samldb_fill_group_object(struct ldb_module *module, const struct ldb_
        }
        
        /* Manage SID allocation, conflicts etc */
-       ret = samldb_handle_sid(module, mem_ctx, msg2); 
+       ret = samldb_handle_sid(module, mem_ctx, msg2, dom_dn); 
 
        if (ret == LDB_SUCCESS) {
                talloc_steal(msg, msg2);
@@ -458,6 +469,7 @@ static int samldb_fill_user_or_computer_object(struct ldb_module *module, const
        int ret;
        char *name;
        struct ldb_message *msg2;
+       struct ldb_dn *dom_dn;
        const char *rdn_name;
        TALLOC_CTX *mem_ctx = talloc_new(msg);
        const char *errstr;
@@ -468,7 +480,7 @@ static int samldb_fill_user_or_computer_object(struct ldb_module *module, const
        /* build the new msg */
        msg2 = ldb_msg_copy(mem_ctx, msg);
        if (!msg2) {
-               ldb_debug(module->ldb, LDB_DEBUG_FATAL, "samldb_fill_group_object: ldb_msg_copy failed!\n");
+               ldb_debug(module->ldb, LDB_DEBUG_FATAL, "samldb_fill_user_or_computer_object: ldb_msg_copy failed!\n");
                talloc_free(mem_ctx);
                return LDB_ERR_OPERATIONS_ERROR;
        }
@@ -513,11 +525,18 @@ static int samldb_fill_user_or_computer_object(struct ldb_module *module, const
                return LDB_ERR_CONSTRAINT_VIOLATION;
        }
 
+       ret = samdb_search_for_parent_domain(module->ldb, mem_ctx, msg2->dn, &dom_dn, &errstr);
+       if (ret != LDB_SUCCESS) {
+               ldb_asprintf_errstring(module->ldb,
+                                      "samldb_fill_user_or_computer_object: %s", errstr);
+               return ret;
+       }
+
        if (ldb_msg_find_element(msg2, "samAccountName") == NULL) {
-               name = samldb_generate_samAccountName(module, mem_ctx);
-               if (!name) {
+               ret = samldb_generate_samAccountName(module, mem_ctx, dom_dn, &name);
+               if (ret != LDB_SUCCESS) {
                        talloc_free(mem_ctx);
-                       return LDB_ERR_OPERATIONS_ERROR;
+                       return ret;
                }
                ret = samdb_find_or_add_attribute(module->ldb, msg2, "sAMAccountName", name);
                if (ret) {
@@ -531,7 +550,7 @@ static int samldb_fill_user_or_computer_object(struct ldb_module *module, const
        */
 
        /* Manage SID allocation, conflicts etc */
-       ret = samldb_handle_sid(module, mem_ctx, msg2); 
+       ret = samldb_handle_sid(module, mem_ctx, msg2, dom_dn); 
 
        /* TODO: objectCategory, userAccountControl, badPwdCount, codePage, countryCode, badPasswordTime, lastLogoff, lastLogon, pwdLastSet, primaryGroupID, accountExpires, logonCount */