r9793: Be more verbose, check for errors in upgrade script.
[sfrench/samba-autobuild/.git] / source4 / dsdb / samdb / ldb_modules / samldb.c
index 7b82621c8da5ff99df8ee2fb059915f86d620d56..3266c89e2d3cfacdee66b67b1ec23aedfcc423e7 100644 (file)
@@ -44,7 +44,7 @@ struct private_data {
        const char *error_string;
 };
 
-static int samldb_search(struct ldb_module *module, const char *base,
+static int samldb_search(struct ldb_module *module, const struct ldb_dn *base,
                                  enum ldb_scope scope, const char *expression,
                                  const char * const *attrs, struct ldb_message ***res)
 {
@@ -52,7 +52,7 @@ static int samldb_search(struct ldb_module *module, const char *base,
        return ldb_next_search(module, base, scope, expression, attrs, res);
 }
 
-static int samldb_search_bytree(struct ldb_module *module, const char *base,
+static int samldb_search_bytree(struct ldb_module *module, const struct ldb_dn *base,
                                enum ldb_scope scope, struct ldb_parse_tree *tree,
                                const char * const *attrs, struct ldb_message ***res)
 {
@@ -65,7 +65,7 @@ static int samldb_search_bytree(struct ldb_module *module, const char *base,
   return 0 on failure, the id on success
 */
 static int samldb_allocate_next_rid(struct ldb_context *ldb, TALLOC_CTX *mem_ctx,
-                                  const char *dn, uint32_t *id)
+                                  const struct ldb_dn *dn, uint32_t *id)
 {
        const char * const attrs[2] = { "nextRid", NULL };
        struct ldb_message **res = NULL;
@@ -82,7 +82,7 @@ static int samldb_allocate_next_rid(struct ldb_context *ldb, TALLOC_CTX *mem_ctx
        }
        str = ldb_msg_find_string(res[0], "nextRid", NULL);
        if (str == NULL) {
-               ldb_debug(ldb, LDB_DEBUG_FATAL, "attribute nextRid not found in %s\n", dn);
+               ldb_debug(ldb, LDB_DEBUG_FATAL, "attribute nextRid not found in %s\n", ldb_dn_linearize(res, dn));
                talloc_free(res);
                return -1;
        }
@@ -99,7 +99,7 @@ static int samldb_allocate_next_rid(struct ldb_context *ldb, TALLOC_CTX *mem_ctx
        /* we do a delete and add as a single operation. That prevents
           a race */
        ZERO_STRUCT(msg);
-       msg.dn = talloc_strdup(mem_ctx, dn);
+       msg.dn = ldb_dn_copy(mem_ctx, dn);
        if (!msg.dn) {
                return -1;
        }
@@ -141,29 +141,35 @@ static int samldb_allocate_next_rid(struct ldb_context *ldb, TALLOC_CTX *mem_ctx
        return 0;
 }
 
-static char *samldb_search_domain(struct ldb_module *module, TALLOC_CTX *mem_ctx, const char *dn)
+static struct ldb_dn *samldb_search_domain(struct ldb_module *module, TALLOC_CTX *mem_ctx, const struct ldb_dn *dn)
 {
-       const char *sdn;
+       TALLOC_CTX *local_ctx;
+       struct ldb_dn *sdn;
        struct ldb_message **res = NULL;
        int ret = 0;
 
-       sdn = dn;
-       while ((sdn = strchr(sdn, ',')) != NULL) {
-
-               sdn++;
+       local_ctx = talloc_named(mem_ctx, 0, "samldb_search_domain memory conext");
+       if (local_ctx == NULL) return NULL;
 
+       sdn = ldb_dn_copy(local_ctx, dn);
+       do {
                ret = ldb_search(module->ldb, sdn, LDB_SCOPE_BASE, "objectClass=domain", NULL, &res);
                talloc_free(res);
 
                if (ret == 1)
                        break;
-       }
+
+       } while ((sdn = ldb_dn_get_parent(local_ctx, sdn)));
 
        if (ret != 1) {
+               talloc_free(local_ctx);
                return NULL;
        }
 
-       return talloc_strdup(mem_ctx, sdn);
+       talloc_steal(mem_ctx, sdn);
+       talloc_free(local_ctx);
+
+       return sdn;
 }
 
 /* search the domain related to the provided dn
@@ -171,11 +177,11 @@ static char *samldb_search_domain(struct ldb_module *module, TALLOC_CTX *mem_ctx
    return the new sid string
 */
 static struct dom_sid *samldb_get_new_sid(struct ldb_module *module, 
-                                         TALLOC_CTX *mem_ctx, const char *obj_dn)
+                                         TALLOC_CTX *mem_ctx, const struct ldb_dn *obj_dn)
 {
        const char * const attrs[2] = { "objectSid", NULL };
        struct ldb_message **res = NULL;
-       const char *dom_dn;
+       const struct ldb_dn *dom_dn;
        uint32_t rid;
        int ret, tries = 10;
        struct dom_sid *dom_sid, *obj_sid;
@@ -190,7 +196,7 @@ static struct dom_sid *samldb_get_new_sid(struct ldb_module *module,
        
        dom_dn = samldb_search_domain(module, mem_ctx, obj_dn);
        if (dom_dn == NULL) {
-               ldb_debug(module->ldb, LDB_DEBUG_FATAL, "Invalid dn (%s) not child of a domain object!\n", obj_dn);
+               ldb_debug(module->ldb, LDB_DEBUG_FATAL, "Invalid dn (%s) not child of a domain object!\n", ldb_dn_linearize(mem_ctx, obj_dn));
                return NULL;
        }
 
@@ -221,7 +227,7 @@ static struct dom_sid *samldb_get_new_sid(struct ldb_module *module,
                }
        }
        if (ret != 0) {
-               ldb_debug(module->ldb, LDB_DEBUG_FATAL, "Failed to increment nextRid of %s\n", dom_dn);
+               ldb_debug(module->ldb, LDB_DEBUG_FATAL, "Failed to increment nextRid of %s\n", ldb_dn_linearize(mem_ctx, dom_dn));
                talloc_free(res);
                return NULL;
        }
@@ -243,32 +249,6 @@ static char *samldb_generate_samAccountName(const void *mem_ctx) {
        return name;
 }
 
-static BOOL samldb_get_rdn_and_basedn(void *mem_ctx, const char *dn, struct ldb_dn_component **rdn, char **base_dn)
-{
-       struct ldb_dn *dn_exploded = ldb_dn_explode(mem_ctx, dn);
-       struct ldb_dn base_dn_exploded;
-
-       if (!dn_exploded) {
-               return False;
-       }
-       
-       if (dn_exploded->comp_num < 1) {
-               return False;
-       }
-       
-       if (dn_exploded->comp_num < 2) {
-               *base_dn = NULL;
-       } else {
-               base_dn_exploded.comp_num = dn_exploded->comp_num - 1;
-               base_dn_exploded.components = &dn_exploded->components[1];
-               
-               *base_dn = ldb_dn_linearize(mem_ctx, &base_dn_exploded);
-       }
-
-       *rdn = &dn_exploded->components[0];
-       return True;
-}
-
 /* if value is not null also check for attribute to have exactly that value */
 static struct ldb_message_element *samldb_find_attribute(const struct ldb_message *msg, const char *name, const char *value)
 {
@@ -355,7 +335,7 @@ static int samldb_copy_template(struct ldb_module *module, struct ldb_message *m
                            (strcasecmp((char *)el->values[j].data, "Template") == 0 ||
                             strcasecmp((char *)el->values[j].data, "userTemplate") == 0 ||
                             strcasecmp((char *)el->values[j].data, "groupTemplate") == 0 ||
-                            strcasecmp((char *)el->values[j].data, "foreignSecurityTemplate") == 0 ||
+                            strcasecmp((char *)el->values[j].data, "foreignSecurityPrincipalTemplate") == 0 ||
                             strcasecmp((char *)el->values[j].data, "aliasTemplate") == 0 || 
                             strcasecmp((char *)el->values[j].data, "trustedDomainTemplate") == 0 || 
                             strcasecmp((char *)el->values[j].data, "secretTemplate") == 0)) {
@@ -381,7 +361,6 @@ static struct ldb_message *samldb_fill_group_object(struct ldb_module *module, c
        struct ldb_message *msg2;
        struct ldb_message_element *attribute;
        struct ldb_dn_component *rdn;
-       char *basedn;
 
        if (samldb_find_attribute(msg, "objectclass", "group") == NULL) {
                return NULL;
@@ -401,8 +380,8 @@ static struct ldb_message *samldb_fill_group_object(struct ldb_module *module, c
                return NULL;
        }
 
-       if ( ! samldb_get_rdn_and_basedn(msg2, msg2->dn, &rdn, &basedn)) {
-               ldb_debug(module->ldb, LDB_DEBUG_FATAL, "samldb_fill_group_object: Bad DN (%s)!\n", msg2->dn);
+       if ((rdn = ldb_dn_get_rdn(msg2, msg2->dn)) == NULL) {
+               ldb_debug(module->ldb, LDB_DEBUG_FATAL, "samldb_fill_group_object: Bad DN (%s)!\n", ldb_dn_linearize(msg2, msg2->dn));
                return NULL;
        }
        if (strcasecmp(rdn->name, "cn") != 0) {
@@ -438,7 +417,6 @@ static struct ldb_message *samldb_fill_user_or_computer_object(struct ldb_module
        struct ldb_message *msg2;
        struct ldb_message_element *attribute;
        struct ldb_dn_component *rdn;
-       char *basedn;
 
        if ((samldb_find_attribute(msg, "objectclass", "user") == NULL) && 
            (samldb_find_attribute(msg, "objectclass", "computer") == NULL)) {
@@ -466,7 +444,7 @@ static struct ldb_message *samldb_fill_user_or_computer_object(struct ldb_module
                }
        }
 
-       if ( ! samldb_get_rdn_and_basedn(msg2, msg2->dn, &rdn, &basedn)) {
+       if ((rdn = ldb_dn_get_rdn(msg2, msg2->dn)) == NULL) {
                return NULL;
        }
        if (strcasecmp(rdn->name, "cn") != 0) {
@@ -503,6 +481,58 @@ static struct ldb_message *samldb_fill_user_or_computer_object(struct ldb_module
        return msg2;
 }
 
+static struct ldb_message *samldb_fill_foreignSecurityPrincipal_object(struct ldb_module *module, const struct ldb_message *msg)
+{
+       struct ldb_message *msg2;
+       struct ldb_message_element *attribute;
+       struct ldb_dn_component *rdn;
+
+       if (samldb_find_attribute(msg, "objectclass", "foreignSecurityPrincipal") == NULL) {
+               return NULL;
+       }
+
+       ldb_debug(module->ldb, LDB_DEBUG_TRACE, "samldb_fill_foreignSecurityPrincipal_object\n");
+
+       /* build the new msg */
+       msg2 = ldb_msg_copy(module->ldb, msg);
+       if (!msg2) {
+               ldb_debug(module->ldb, LDB_DEBUG_FATAL, "samldb_fill_foreignSecurityPrincpal_object: ldb_msg_copy failed!\n");
+               return NULL;
+       }
+
+       talloc_steal(msg, msg2);
+
+       if (samldb_copy_template(module, msg2, "(&(CN=TemplateForeignSecurityPrincipal)(objectclass=foreignSecurityPrincipalTemplate))") != 0) {
+               ldb_debug(module->ldb, LDB_DEBUG_WARNING, "samldb_fill_foreignSecurityPrincipal_object: Error copying template!\n");
+               return NULL;
+       }
+
+       if ((rdn = ldb_dn_get_rdn(msg2, msg2->dn)) == NULL) {
+               ldb_debug(module->ldb, LDB_DEBUG_FATAL, "samldb_fill_foreignSecurityPrincipal_object: Bad DN (%s)!\n", ldb_dn_linearize(msg2, msg2->dn));
+               return NULL;
+       }
+       if (strcasecmp(rdn->name, "cn") != 0) {
+               ldb_debug(module->ldb, LDB_DEBUG_FATAL, "samldb_fill_foreignSecurityPrincipal_object: Bad RDN (%s) for foreignSecurityPrincpal!\n", rdn->name);
+               return NULL;
+       }
+
+       if ((attribute = samldb_find_attribute(msg2, "objectSid", NULL)) == NULL ) {
+               struct dom_sid *sid = dom_sid_parse_talloc(msg2, rdn->value.data);
+               if (sid == NULL) {
+                       ldb_debug(module->ldb, LDB_DEBUG_FATAL, "samldb_fill_foreignSecurityPrincipal_object: internal error! Can't parse sid in CN\n");
+                       return NULL;
+               }
+
+               if (!samldb_msg_add_sid(module, msg2, "objectSid", sid)) {
+                       talloc_free(sid);
+                       return NULL;
+               }
+               talloc_free(sid);
+       }
+
+       return msg2;
+}
+
 /* add_record */
 static int samldb_add_record(struct ldb_module *module, const struct ldb_message *msg)
 {
@@ -511,7 +541,8 @@ static int samldb_add_record(struct ldb_module *module, const struct ldb_message
 
        ldb_debug(module->ldb, LDB_DEBUG_TRACE, "samldb_add_record\n");
 
-       if (msg->dn[0] == '@') { /* do not manipulate our control entries */
+       
+       if (ldb_dn_is_special(msg->dn)) { /* do not manipulate our control entries */
                return ldb_next_add_record(module, msg);
        }
 
@@ -523,6 +554,11 @@ static int samldb_add_record(struct ldb_module *module, const struct ldb_message
                msg2 = samldb_fill_group_object(module, msg);
        }
 
+       /* perhaps a foreignSecurityPrincipal? */
+       if ( ! msg2 ) {
+               msg2 = samldb_fill_foreignSecurityPrincipal_object(module, msg);
+       }
+
        if (msg2) {
                ret = ldb_next_add_record(module, msg2);
        } else {
@@ -539,13 +575,13 @@ static int samldb_modify_record(struct ldb_module *module, const struct ldb_mess
        return ldb_next_modify_record(module, msg);
 }
 
-static int samldb_delete_record(struct ldb_module *module, const char *dn)
+static int samldb_delete_record(struct ldb_module *module, const struct ldb_dn *dn)
 {
        ldb_debug(module->ldb, LDB_DEBUG_TRACE, "samldb_delete_record\n");
        return ldb_next_delete_record(module, dn);
 }
 
-static int samldb_rename_record(struct ldb_module *module, const char *olddn, const char *newdn)
+static int samldb_rename_record(struct ldb_module *module, const struct ldb_dn *olddn, const struct ldb_dn *newdn)
 {
        ldb_debug(module->ldb, LDB_DEBUG_TRACE, "samldb_rename_record\n");
        return ldb_next_rename_record(module, olddn, newdn);