r8660: Use templates for the initial provision of user and computer accounts.
[kai/samba.git] / source / dsdb / samdb / ldb_modules / samldb.c
index a392f978652b8d215c9af8af7e5f67261f6bde91..40b6b72713392a267c9eb6a22e514a00d23b2e69 100644 (file)
@@ -35,7 +35,8 @@
 #include "includes.h"
 #include "lib/ldb/include/ldb.h"
 #include "lib/ldb/include/ldb_private.h"
-#include <time.h>
+#include "system/time.h"
+#include "librpc/gen_ndr/ndr_security.h"
 
 #define SAM_ACCOUNT_NAME_BASE "$000000-000000000000"
 
@@ -51,6 +52,14 @@ 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,
+                               enum ldb_scope scope, struct ldb_parse_tree *tree,
+                               const char * const *attrs, struct ldb_message ***res)
+{
+       ldb_debug(module->ldb, LDB_DEBUG_TRACE, "samldb_search\n");
+       return ldb_next_search_bytree(module, base, scope, tree, attrs, res);
+}
+
 /*
   allocate a new id, attempting to do it atomically
   return 0 on failure, the id on success
@@ -136,7 +145,7 @@ static char *samldb_search_domain(struct ldb_module *module, TALLOC_CTX *mem_ctx
 {
        const char *sdn;
        struct ldb_message **res = NULL;
-       int ret;
+       int ret = 0;
 
        sdn = dn;
        while ((sdn = strchr(sdn, ',')) != NULL) {
@@ -161,14 +170,15 @@ static char *samldb_search_domain(struct ldb_module *module, TALLOC_CTX *mem_ctx
    allocate a new RID for the domain
    return the new sid string
 */
-static char *samldb_get_new_sid(struct ldb_module *module, TALLOC_CTX *mem_ctx, const char *obj_dn)
+static struct dom_sid *samldb_get_new_sid(struct ldb_module *module, 
+                                         TALLOC_CTX *mem_ctx, const char *obj_dn)
 {
        const char * const attrs[2] = { "objectSid", NULL };
        struct ldb_message **res = NULL;
-       const char *dom_dn, *dom_sid;
-       char *obj_sid;
+       const char *dom_dn;
        uint32_t rid;
        int ret, tries = 10;
+       struct dom_sid *dom_sid, *obj_sid;
 
        /* get the domain component part of the provided dn */
 
@@ -189,11 +199,11 @@ static char *samldb_get_new_sid(struct ldb_module *module, TALLOC_CTX *mem_ctx,
        ret = ldb_search(module->ldb, dom_dn, LDB_SCOPE_BASE, "objectSid=*", attrs, &res);
        if (ret != 1) {
                ldb_debug(module->ldb, LDB_DEBUG_FATAL, "samldb_get_new_sid: error retrieving domain sid!\n");
-               if (res) talloc_free(res);
+               talloc_free(res);
                return NULL;
        }
 
-       dom_sid = ldb_msg_find_string(res[0], "objectSid", NULL);
+       dom_sid = samdb_result_dom_sid(res, res[0], "objectSid");
        if (dom_sid == NULL) {
                ldb_debug(module->ldb, LDB_DEBUG_FATAL, "samldb_get_new_sid: error retrieving domain sid!\n");
                talloc_free(res);
@@ -217,12 +227,10 @@ static char *samldb_get_new_sid(struct ldb_module *module, TALLOC_CTX *mem_ctx,
        }
 
        /* return the new object sid */
-
-       obj_sid = talloc_asprintf(mem_ctx, "%s-%u", dom_sid, rid);
+       obj_sid = dom_sid_add_rid(mem_ctx, dom_sid, rid);
 
        talloc_free(res);
 
-
        return obj_sid;
 }
 
@@ -299,6 +307,18 @@ static BOOL samldb_msg_add_string(struct ldb_module *module, struct ldb_message
        return True;
 }
 
+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)) {
+               return -1;
+       }
+       return (ldb_msg_add_value(module->ldb, msg, name, &v) == 0);
+}
+
 static BOOL samldb_find_or_add_attribute(struct ldb_module *module, struct ldb_message *msg, const char *name, const char *value, const char *set_value)
 {
        if (samldb_find_attribute(msg, name, value) == NULL) {
@@ -316,7 +336,7 @@ static int samldb_copy_template(struct ldb_module *module, struct ldb_message *m
        /* pull the template record */
        ret = ldb_search(module->ldb, NULL, LDB_SCOPE_SUBTREE, filter, NULL, &res);
        if (ret != 1) {
-               ldb_debug(module->ldb, LDB_DEBUG_FATAL, "samldb: ERROR: template '%s' matched %d records\n", filter, ret);
+               ldb_debug(module->ldb, LDB_DEBUG_WARNING, "samldb: ERROR: template '%s' matched %d records\n", filter, ret);
                return -1;
        }
        t = res[0];
@@ -326,7 +346,8 @@ static int samldb_copy_template(struct ldb_module *module, struct ldb_message *m
                /* some elements should not be copied from the template */
                if (strcasecmp(el->name, "cn") == 0 ||
                    strcasecmp(el->name, "name") == 0 ||
-                   strcasecmp(el->name, "sAMAccountName") == 0) {
+                   strcasecmp(el->name, "sAMAccountName") == 0 ||
+                   strcasecmp(el->name, "objectGUID") == 0) {
                        continue;
                }
                for (j = 0; j < el->num_values; j++) {
@@ -359,7 +380,7 @@ static struct ldb_message *samldb_fill_group_object(struct ldb_module *module, c
 {
        struct ldb_message *msg2;
        struct ldb_message_element *attribute;
-       char *rdn, *basedn, *sidstr;
+       char *rdn, *basedn;
 
        if (samldb_find_attribute(msg, "objectclass", "group") == NULL) {
                return NULL;
@@ -374,8 +395,8 @@ static struct ldb_message *samldb_fill_group_object(struct ldb_module *module, c
                return NULL;
        }
 
-       if (samldb_copy_template(module, msg2, "(&(name=TemplateGroup)(objectclass=groupTemplate))") != 0) {
-               ldb_debug(module->ldb, LDB_DEBUG_FATAL, "samldb_fill_group_object: Error copying template!\n");
+       if (samldb_copy_template(module, msg2, "(&(CN=TemplateGroup)(objectclass=groupTemplate))") != 0) {
+               ldb_debug(module->ldb, LDB_DEBUG_WARNING, "samldb_fill_group_object: Error copying template!\n");
                return NULL;
        }
 
@@ -410,23 +431,23 @@ static struct ldb_message *samldb_fill_group_object(struct ldb_module *module, c
        }
 
        if ((attribute = samldb_find_attribute(msg2, "objectSid", NULL)) == NULL ) {
-
-               if ((sidstr = samldb_get_new_sid(module, msg2, msg2->dn)) == NULL) {
+               struct dom_sid *sid = samldb_get_new_sid(module, msg2, msg2->dn);
+               if (sid == NULL) {
                        ldb_debug(module->ldb, LDB_DEBUG_FATAL, "samldb_fill_group_object: internal error! Can't generate new sid\n");
                        return NULL;
                }
 
-               if ( ! samldb_msg_add_string(module, msg2, "objectSid", sidstr)) {
+               if (!samldb_msg_add_sid(module, msg2, "objectSid", sid)) {
+                       talloc_free(sid);
                        return NULL;
                }
+               talloc_free(sid);
        }
 
        if ( ! samldb_find_or_add_attribute(module, msg2, "sAMAccountName", NULL, samldb_generate_samAccountName(msg2))) {
                return NULL;
        }
 
-       /* TODO: objectGUID */
-
        talloc_steal(msg, msg2);
 
        return msg2;
@@ -436,9 +457,10 @@ static struct ldb_message *samldb_fill_user_or_computer_object(struct ldb_module
 {
        struct ldb_message *msg2;
        struct ldb_message_element *attribute;
-       char *rdn, *basedn, *sidstr;
+       char *rdn, *basedn;
 
-       if ((samldb_find_attribute(msg, "objectclass", "user") == NULL) && (samldb_find_attribute(msg, "objectclass", "computer") == NULL)) {
+       if ((samldb_find_attribute(msg, "objectclass", "user") == NULL) && 
+           (samldb_find_attribute(msg, "objectclass", "computer") == NULL)) {
                return NULL;
        }
 
@@ -451,9 +473,16 @@ static struct ldb_message *samldb_fill_user_or_computer_object(struct ldb_module
                return NULL;
        }
 
-       if (samldb_copy_template(module, msg2, "(&(name=TemplateUser)(objectclass=userTemplate))") != 0) {
-               ldb_debug(module->ldb, LDB_DEBUG_FATAL, "samldb_fill_user_or_computer_object: Error copying template!\n");
-               return NULL;
+       if (samldb_find_attribute(msg, "objectclass", "computer") == NULL) {
+               if (samldb_copy_template(module, msg2, "(&(CN=TemplateMemberServer)(objectclass=userTemplate))") != 0) {
+                       ldb_debug(module->ldb, LDB_DEBUG_WARNING, "samldb_fill_user_or_computer_object: Error copying computer template!\n");
+                       return NULL;
+               }
+       } else {
+               if (samldb_copy_template(module, msg2, "(&(CN=TemplateUser)(objectclass=userTemplate))") != 0) {
+                       ldb_debug(module->ldb, LDB_DEBUG_WARNING, "samldb_fill_user_or_computer_object: Error copying user template!\n");
+                       return NULL;
+               }
        }
 
        if ( ! samldb_get_rdn_and_basedn(msg2, msg2->dn, &rdn, &basedn)) {
@@ -492,24 +521,25 @@ static struct ldb_message *samldb_fill_user_or_computer_object(struct ldb_module
        }
 
        if ((attribute = samldb_find_attribute(msg2, "objectSid", NULL)) == NULL ) {
-
-               if ((sidstr = samldb_get_new_sid(module, msg2, msg2->dn)) == NULL) {
+               struct dom_sid *sid;
+               sid = samldb_get_new_sid(module, msg2, msg2->dn);
+               if (sid == NULL) {
                        ldb_debug(module->ldb, LDB_DEBUG_FATAL, "samldb_fill_user_or_computer_object: internal error! Can't generate new sid\n");
                        return NULL;
                }
 
-               if ( ! samldb_msg_add_string(module, msg2, "objectSid", sidstr)) {
+               if ( ! samldb_msg_add_sid(module, msg2, "objectSid", sid)) {
+                       talloc_free(sid);
                        return NULL;
                }
+               talloc_free(sid);
        }
 
        if ( ! samldb_find_or_add_attribute(module, msg2, "sAMAccountName", NULL, samldb_generate_samAccountName(msg2))) {
                return NULL;
        }
 
-       /* TODO: objectGUID, objectCategory, userAccountControl, badPwdCount, codePage, countryCode, badPasswordTime, lastLogoff, lastLogon, pwdLastSet, primaryGroupID, accountExpires, logonCount */
-
-       talloc_steal(msg, msg2);
+       /* TODO: objectCategory, userAccountControl, badPwdCount, codePage, countryCode, badPasswordTime, lastLogoff, lastLogon, pwdLastSet, primaryGroupID, accountExpires, logonCount */
 
        return msg2;
 }
@@ -599,15 +629,16 @@ static int samldb_destructor(void *module_ctx)
 }
 
 static const struct ldb_module_ops samldb_ops = {
-       "samldb",
-       samldb_search,
-       samldb_add_record,
-       samldb_modify_record,
-       samldb_delete_record,
-       samldb_rename_record,
-       samldb_lock,
-       samldb_unlock,
-       samldb_errstring
+       .name          = "samldb",
+       .search        = samldb_search,
+       .search_bytree = samldb_search_bytree,
+       .add_record    = samldb_add_record,
+       .modify_record = samldb_modify_record,
+       .delete_record = samldb_delete_record,
+       .rename_record = samldb_rename_record,
+       .named_lock    = samldb_lock,
+       .named_unlock  = samldb_unlock,
+       .errstring     = samldb_errstring
 };