r6084: - Introduce the samldb module dependency on samba4
authorSimo Sorce <idra@samba.org>
Sun, 27 Mar 2005 23:31:43 +0000 (23:31 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 18:11:18 +0000 (13:11 -0500)
- This module will take care of properly filling an user or group object
  with required fields. You just need to provide the dn and the objectclass
  and a user/group get created

  Simo.

source/dsdb/samdb/ldb_modules/samldb.c
source/provision.ldif
source/rpc_server/samr/dcesrv_samr.c

index ddd878070d498f91b1b5d5fffb68f1e60f32fe15..7ec1ea1a296dfe18cd287c57a2bda977bd2c0a10 100644 (file)
@@ -1,25 +1,25 @@
 /* 
-   ldb database library
+   SAM ldb module
 
    Copyright (C) Simo Sorce  2004
 
-     ** NOTE! The following LGPL license applies to the ldb
-     ** library. This does NOT imply that all of Samba is released
-     ** under the LGPL
-   
-   This library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2 of the License, or (at your option) any later version.
+   * NOTICE: this module is NOT released under the GNU LGPL license as
+   * other ldb code. This module is release under the GNU GPL v2 or
+   * later license.
 
-   This library is distributed in the hope that it will be useful,
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+   
+   This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with this library; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
 /*
@@ -27,7 +27,7 @@
  *
  *  Component: ldb samldb module
  *
- *  Description: add object timestamping functionality
+ *  Description: add embedded user/group creation functionality
  *
  *  Author: Simo Sorce
  */
@@ -53,11 +53,10 @@ static int samldb_search(struct ldb_module *module, const char *base,
 
 static int samldb_search_free(struct ldb_module *module, struct ldb_message **res)
 {
-ldb_debug(module->ldb, LDB_DEBUG_TRACE, "samldb_search_free\n");
+       ldb_debug(module->ldb, LDB_DEBUG_TRACE, "samldb_search_free\n");
        return ldb_next_search_free(module, res);
 }
 
-
 /*
   allocate a new id, attempting to do it atomically
   return 0 on failure, the id on success
@@ -84,14 +83,15 @@ static int samldb_allocate_next_rid(struct ldb_context *ldb, TALLOC_CTX *mem_ctx
                ldb_search_free(ldb, res);
                return -1;
        }
-       talloc_steal(mem_ctx, str);
-       ldb_search_free(ldb, res);
 
        *id = strtol(str, NULL, 0);
        if ((*id)+1 == 0) {
                /* out of IDs ! */
+               ldb_debug(ldb, LDB_DEBUG_FATAL, "Are we out of valid IDs ?\n");
+               ldb_search_free(ldb, res);
                return -1;
        }
+       ldb_search_free(ldb, res);
 
        /* we do a delete and add as a single operation. That prevents
           a race */
@@ -138,11 +138,36 @@ 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)
+{
+       const char *sdn;
+       struct ldb_message **res = NULL;
+       int ret;
+
+       sdn = dn;
+       while ((sdn = strchr(sdn, ',')) != NULL) {
+
+               sdn++;
+
+               ret = ldb_search(module->ldb, sdn, LDB_SCOPE_BASE, "objectClass=domain", NULL, &res);
+               ldb_search_free(module->ldb, res);
+
+               if (ret == 1)
+                       break;
+       }
+
+       if (ret != 1) {
+               return NULL;
+       }
+
+       return talloc_strdup(mem_ctx, sdn);
+}
+
 /* search the domain related to the provided dn
    allocate a new RID for the domain
    return the new sid string
 */
-static char *samldb_get_new_sid(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, const char *obj_dn)
+static char *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;
@@ -159,44 +184,41 @@ static char *samldb_get_new_sid(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, co
        /* FIXME: "dc=" is probably not utf8 safe either,
           we need a multibyte safe substring search function here */
        
-       dom_dn = strstr(obj_dn, "dc=");
+       dom_dn = samldb_search_domain(module, mem_ctx, obj_dn);
        if (dom_dn == NULL) {
-               ldb_debug(ldb, LDB_DEBUG_FATAL, "Invalid dn (%s)!\n", obj_dn);
+               ldb_debug(module->ldb, LDB_DEBUG_FATAL, "Invalid dn (%s) not child of a domain object!\n", obj_dn);
                return NULL;
        }
 
        /* find the domain sid */
 
-       ret = ldb_search(ldb, dom_dn, LDB_SCOPE_BASE, "objectSid=*", attrs, &res);
+       ret = ldb_search(module->ldb, dom_dn, LDB_SCOPE_BASE, "objectSid=*", attrs, &res);
        if (ret != 1) {
-               ldb_debug(ldb, LDB_DEBUG_FATAL, "samldb_get_new_sid: error retrieving domain sid!\n");
-               if (res) ldb_search_free(ldb, res);
+               ldb_debug(module->ldb, LDB_DEBUG_FATAL, "samldb_get_new_sid: error retrieving domain sid!\n");
+               if (res) ldb_search_free(module->ldb, res);
                return NULL;
        }
 
        dom_sid = ldb_msg_find_string(res[0], "objectSid", NULL);
        if (dom_sid == NULL) {
-               ldb_debug(ldb, LDB_DEBUG_FATAL, "samldb_get_new_sid: error retrieving domain sid!\n");
-               ldb_search_free(ldb, res);
+               ldb_debug(module->ldb, LDB_DEBUG_FATAL, "samldb_get_new_sid: error retrieving domain sid!\n");
+               ldb_search_free(module->ldb, res);
                return NULL;
        }
 
-       talloc_steal(mem_ctx, dom_sid);
-       ldb_search_free(ldb, res);
-
        /* allocate a new Rid for the domain */
 
-
        /* we need to try multiple times to cope with two account
           creations at the same time */
        while (tries--) {
-               ret = samldb_allocate_next_rid(ldb, mem_ctx, dom_dn, &rid);
+               ret = samldb_allocate_next_rid(module->ldb, mem_ctx, dom_dn, &rid);
                if (ret != 1) {
                        break;
                }
        }
        if (ret != 0) {
-               ldb_debug(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", dom_dn);
+               ldb_search_free(module->ldb, res);
                return NULL;
        }
 
@@ -204,6 +226,8 @@ static char *samldb_get_new_sid(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, co
 
        obj_sid = talloc_asprintf(mem_ctx, "%s-%u", dom_sid, rid);
 
+       ldb_search_free(module->ldb, res);
+
        return obj_sid;
 }
 
@@ -224,13 +248,8 @@ static BOOL samldb_get_rdn_and_basedn(const void *mem_ctx, const char *dn, char
        if ( ! p ) {
                return False;
        }
-       /* clear separator */
-       *p = '\0';
 
-       *rdn = talloc_strdup(mem_ctx, dn);
-
-       /* put back separator */
-       *p = ',';
+       *rdn = talloc_strndup(mem_ctx, dn, p - dn);
 
        if ( ! *rdn) {
                return False;
@@ -268,287 +287,234 @@ static struct ldb_message_element *samldb_find_attribute(const struct ldb_messag
        return NULL;
 }
 
-static BOOL samldb_add_attribute(struct ldb_message *msg, const char *name, const char *value)
+static BOOL samldb_msg_add_string(struct ldb_module *module, struct ldb_message *msg, const char *name, const char *value)
 {
-       struct ldb_message_element *attr;
-       int i;
-
-       attr = samldb_find_attribute(msg, name, NULL);
-       if ( ! attr) {
-               msg->num_elements++;
-               msg->elements = talloc_realloc(msg, msg->elements, struct ldb_message_element, msg->num_elements);
-               if ( ! msg->elements ) {
-                       return False;
-               }
-               attr = &msg->elements[msg->num_elements - 1];
-
-               attr->name = talloc_strdup(msg, name);
-               if ( ! attr->name ) {
-                       return False;
-               }
-               attr->flags = 0;
-               attr->num_values = 0;
-               attr->values = NULL;
-       }
+       char *aname = talloc_strdup(msg, name);
+       char *aval = talloc_strdup(msg, value);
 
-       i = attr->num_values;
-       attr->num_values++;
-       attr->values = talloc_realloc(msg, attr->values, struct ldb_val, attr->num_values);
-       if ( ! attr->values ){
+       if (aname == NULL || aval == NULL) {
+               ldb_debug(module->ldb, LDB_DEBUG_FATAL, "samldb_msg_add_string: talloc_strdup failed!\n");
                return False;
        }
 
-       attr->values[i].data = talloc_strdup(msg, value);
-       attr->values[i].length = strlen(value);
-
-       if ( ! attr->values[i].data) {
+       if (ldb_msg_add_string(module->ldb, msg, aname, aval) != 0) {
                return False;
        }
 
        return True;
 }
 
-static BOOL samldb_find_or_add_attribute(struct ldb_message *msg, const char *name, const char *value, const char *set_value)
+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) {
-               if ( ! samldb_add_attribute(msg, name, set_value)) {
-                       return False;
-               }
+               return samldb_msg_add_string(module, msg, name, set_value);
        }
        return True;
 }
 
-static struct ldb_message *samldb_manage_group_object(struct ldb_module *module, const struct ldb_message *msg)
+static int samldb_copy_template(struct ldb_module *module, struct ldb_message *msg, const char *filter)
+{
+       struct ldb_message **res, *t;
+       int ret, i, j;
+       
+
+       /* 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);
+               return -1;
+       }
+       t = res[0];
+
+       for (i = 0; i < t->num_elements; i++) {
+               struct ldb_message_element *el = &t->elements[i];
+               /* 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) {
+                       continue;
+               }
+               for (j = 0; j < el->num_values; j++) {
+                       if (strcasecmp(el->name, "objectClass") == 0 &&
+                           (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, "aliasTemplate") == 0 || 
+                            strcasecmp((char *)el->values[j].data, "trustedDomainTemplate") == 0 || 
+                            strcasecmp((char *)el->values[j].data, "secretTemplate") == 0)) {
+                               continue;
+                       }
+                       if ( ! samldb_find_or_add_attribute(module, msg, el->name, 
+                                                           NULL,
+                                                           (char *)el->values[j].data)) {
+                               ldb_debug(module->ldb, LDB_DEBUG_FATAL, "Attribute adding failed...\n");
+                               ldb_search_free(module->ldb, res);
+                               return -1;
+                       }
+               }
+       }
+
+       ldb_search_free(module->ldb, res);
+
+       return 0;
+}
+
+static struct ldb_message *samldb_fill_group_object(struct ldb_module *module, const struct ldb_message *msg)
 {
        struct ldb_message *msg2;
        struct ldb_message_element *attribute;
-       char *rdn, *basedn;
-       int i;
+       char *rdn, *basedn, *sidstr;
 
        if (samldb_find_attribute(msg, "objectclass", "group") == NULL) {
                return NULL;
        }
 
-       msg2 = talloc(module, struct ldb_message);
+       ldb_debug(module->ldb, LDB_DEBUG_TRACE, "samldb_fill_group_object\n");
+
+       /* build the new msg */
+       msg2 = ldb_msg_copy(module->ldb, msg);
        if (!msg2) {
-               ldb_debug(module->ldb, LDB_DEBUG_FATAL, "samldb_manage_group_object: talloc failed!\n");
+               ldb_debug(module->ldb, LDB_DEBUG_FATAL, "samldb_fill_group_object: ldb_msg_copy failed!\n");
                return NULL;
        }
 
-       /* build the new msg */
-       msg2->dn = msg->dn;
-       msg2->num_elements = msg->num_elements;
-       msg2->private_data = msg->private_data;
-       msg2->elements = talloc_array(msg2, struct ldb_message_element, msg2->num_elements);
-       if (! msg2->elements) {
-               ldb_debug(module->ldb, LDB_DEBUG_FATAL, "samldb_manage_group_object: talloc_array failed!\n");
-               talloc_free(msg2);
+       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");
                return NULL;
        }
-       for (i = 0; i < msg2->num_elements; i++) {
-               msg2->elements[i] = msg->elements[i];
-       }
 
        if ( ! samldb_get_rdn_and_basedn(msg2, msg2->dn, &rdn, &basedn)) {
-               talloc_free(msg2);
+               ldb_debug(module->ldb, LDB_DEBUG_FATAL, "samldb_fill_group_object: Bad DN (%s)!\n", msg2->dn);
                return NULL;
        }
        if (strncasecmp(rdn, "cn", 2) != 0) {
-               ldb_debug(module->ldb, LDB_DEBUG_FATAL, "samldb_manage_group_object: Bad RDN (%s) for group!\n", rdn);
-               talloc_free(msg2);
-               return NULL;
-       }
-
-       if (! samldb_find_or_add_attribute(msg2, "objectclass", "top", "top")) {
-               talloc_free(msg2);
+               ldb_debug(module->ldb, LDB_DEBUG_FATAL, "samldb_fill_group_object: Bad RDN (%s) for group!\n", rdn);
                return NULL;
        }
 
        if ((attribute = samldb_find_attribute(msg2, "cn", NULL)) != NULL) {
-               if (strcasecmp(rdn, attribute->values[0].data) != 0) {
-                       ldb_debug(module->ldb, LDB_DEBUG_FATAL, "samldb_manage_group_object: Bad Attribute Syntax for CN\n");
-                       talloc_free(msg2);
+               if (strcasecmp(&rdn[3], attribute->values[0].data) != 0) {
+                       ldb_debug(module->ldb, LDB_DEBUG_FATAL, "samldb_fill_group_object: Bad Attribute Syntax for CN\n");
                        return NULL;
                }
        } else { /* FIXME: remove this if ldb supports natively aliasing between the rdn and the "cn" attribute */
-               if ( ! samldb_add_attribute(msg2, "cn", &rdn[3])) {
-                       talloc_free(msg2);
+               if ( ! samldb_msg_add_string(module, msg2, "cn", &rdn[3])) {
                        return NULL;
                }
        }
 
        if ((attribute = samldb_find_attribute(msg2, "name", NULL)) != NULL) {
-               if (strcasecmp(rdn, attribute->values[0].data) != 0) {
-                       ldb_debug(module->ldb, LDB_DEBUG_FATAL, "samldb_manage_group_object: Bad Attribute Syntax for name\n");
-                       talloc_free(msg2);
+               if (strcasecmp(&rdn[3], attribute->values[0].data) != 0) {
                        return NULL;
                }
        } else { /* FIXME: remove this if ldb supports natively aliasing between the rdn and the "name" attribute */
-               if ( ! samldb_add_attribute(msg2, "name", &rdn[3])) {
-                       talloc_free(msg2);
+               if ( ! samldb_msg_add_string(module, msg2, "name", &rdn[3])) {
                        return NULL;
                }
        }
 
        if ((attribute = samldb_find_attribute(msg2, "objectSid", NULL)) == NULL ) {
-               char *sidstr;
 
-               if ((sidstr = samldb_get_new_sid(module->ldb, msg2, msg2->dn)) == NULL) {
-                       ldb_debug(module->ldb, LDB_DEBUG_FATAL, "samldb_manage_group_object: internal error! Can't generate new sid\n");
-                       talloc_free(msg2);
+               if ((sidstr = samldb_get_new_sid(module, msg2, msg2->dn)) == NULL) {
+                       ldb_debug(module->ldb, LDB_DEBUG_FATAL, "samldb_fill_group_object: internal error! Can't generate new sid\n");
                        return NULL;
                }
-               
-               if ( ! samldb_add_attribute(msg2, "objectSid", sidstr)) {
-                       talloc_free(msg2);
+
+               if ( ! samldb_msg_add_string(module, msg2, "objectSid", sidstr)) {
                        return NULL;
                }
        }
 
-       if ( ! samldb_find_or_add_attribute(msg2, "instanceType", NULL, "4")) {
-               return NULL;
-       }
-
-       if ( ! samldb_find_or_add_attribute(msg2, "sAMAccountName", NULL, samldb_generate_samAccountName(msg2))) {
-               return NULL;
-       }
-
-       if ( ! samldb_find_or_add_attribute(msg2, "sAMAccountType", NULL, "0x10000000")) {
-               return NULL;
-       }
-
-       if ( ! samldb_find_or_add_attribute(msg2, "groupType", NULL, "0x80000002")) {
+       if ( ! samldb_find_or_add_attribute(module, msg2, "sAMAccountName", NULL, samldb_generate_samAccountName(msg2))) {
                return NULL;
        }
 
-       if ( ! samldb_find_or_add_attribute(msg2, "objectCategory", NULL, "foo")) { /* keep the schema module happy :) */
-               return NULL;
-       }
+       /* TODO: objectGUID */
 
-       /* TODO: objectGUID, objectSid, objectCategory */
-       /* need a way to lock a new Sid */
+       talloc_steal(msg, msg2);
 
        return msg2;
 }
 
-static struct ldb_message *samldb_manage_user_object(struct ldb_module *module, const struct ldb_message *msg)
+static struct ldb_message *samldb_fill_user_or_computer_object(struct ldb_module *module, const struct ldb_message *msg)
 {
        struct ldb_message *msg2;
        struct ldb_message_element *attribute;
-       char *rdn, *basedn;
-       int i;
+       char *rdn, *basedn, *sidstr;
 
-       if (samldb_find_attribute(msg, "objectclass", "user") == NULL) {
+       if ((samldb_find_attribute(msg, "objectclass", "user") == NULL) && (samldb_find_attribute(msg, "objectclass", "computer") == NULL)) {
                return NULL;
        }
 
-       msg2 = talloc(module, struct ldb_message);
+       ldb_debug(module->ldb, LDB_DEBUG_TRACE, "samldb_fill_user_or_computer_object\n");
+
+       /* build the new msg */
+       msg2 = ldb_msg_copy(module->ldb, msg);
        if (!msg2) {
-               ldb_debug(module->ldb, LDB_DEBUG_FATAL, "samldb_manage_user_object: talloc failed!\n");
+               ldb_debug(module->ldb, LDB_DEBUG_FATAL, "samldb_fill_group_object: ldb_msg_copy failed!\n");
                return NULL;
        }
 
-       /* build the new msg */
-       msg2->dn = msg->dn;
-       msg2->num_elements = msg->num_elements;
-       msg2->private_data = msg->private_data;
-       msg2->elements = talloc_array(msg2, struct ldb_message_element, msg2->num_elements);
-       if (! msg2->elements) {
-               ldb_debug(module->ldb, LDB_DEBUG_FATAL, "samldb_manage_user_object: talloc_array failed!\n");
-               talloc_free(msg2);
+       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;
        }
-       for (i = 0; i < msg2->num_elements; i++) {
-               msg2->elements[i] = msg->elements[i];
-       }
 
        if ( ! samldb_get_rdn_and_basedn(msg2, msg2->dn, &rdn, &basedn)) {
-               talloc_free(msg2);
                return NULL;
        }
        if (strncasecmp(rdn, "cn", 2) != 0) {
-               ldb_debug(module->ldb, LDB_DEBUG_FATAL, "samldb_manage_group_object: Bad RDN (%s) for group!\n", rdn);
-               talloc_free(msg2);
-               return NULL;
-       }
-
-
-       if ( ! samldb_find_or_add_attribute(msg2, "objectclass", "top", "top")) {
-               talloc_free(msg2);
+               ldb_debug(module->ldb, LDB_DEBUG_FATAL, "samldb_fill_user_or_computer_object: Bad RDN (%s) for group!\n", rdn);
                return NULL;
        }
 
-       if ( ! samldb_find_or_add_attribute(msg2, "objectclass", "person", "person")) {
-               talloc_free(msg2);
-               return NULL;
-       }
-
-       if ( ! samldb_find_or_add_attribute(msg2, "objectclass", "organizationalPerson", "organizationalPerson")) {
-               talloc_free(msg2);
+       /* if the only attribute was: "objectclass: computer", then make sure we also add "user" objectclass */
+       if ( ! samldb_find_or_add_attribute(module, msg2, "objectclass", "user", "user")) {
                return NULL;
        }
 
        if ((attribute = samldb_find_attribute(msg2, "cn", NULL)) != NULL) {
-               if (strcasecmp(rdn, attribute->values[0].data) != 0) {
-                       ldb_debug(module->ldb, LDB_DEBUG_FATAL, "samldb_manage_user_object: Bad Attribute Syntax for CN\n");
-                       talloc_free(msg2);
+               if (strcasecmp(&rdn[3], attribute->values[0].data) != 0) {
+                       ldb_debug(module->ldb, LDB_DEBUG_FATAL, "samldb_fill_user_or_computer_object: Bad Attribute Syntax for CN\n");
                        return NULL;
                }
        } else { /* FIXME: remove this if ldb supports natively aliasing between the rdn and the "cn" attribute */
-               if ( ! samldb_add_attribute(msg2, "cn", &rdn[3])) {
-                       talloc_free(msg2);
+               if ( ! samldb_msg_add_string(module, msg2, "cn", &rdn[3])) {
                        return NULL;
                }
        }
 
        if ((attribute = samldb_find_attribute(msg2, "name", NULL)) != NULL) {
-               if (strcasecmp(rdn, attribute->values[0].data) != 0) {
-                       ldb_debug(module->ldb, LDB_DEBUG_FATAL, "samldb_manage_user_object: Bad Attribute Syntax for name\n");
-                       talloc_free(msg2);
+               if (strcasecmp(&rdn[3], attribute->values[0].data) != 0) {
+                       ldb_debug(module->ldb, LDB_DEBUG_FATAL, "samldb_fill_user_or_computer_object: Bad Attribute Syntax for name\n");
                        return NULL;
                }
        } else { /* FIXME: remove this if ldb supports natively aliasing between the rdn and the "name" attribute */
-               if ( ! samldb_add_attribute(msg2, "name", &rdn[3])) {
-                       talloc_free(msg2);
+               if ( ! samldb_msg_add_string(module, msg2, "name", &rdn[3])) {
                        return NULL;
                }
        }
 
        if ((attribute = samldb_find_attribute(msg2, "objectSid", NULL)) == NULL ) {
-               char *sidstr;
 
-               if ((sidstr = samldb_get_new_sid(module->ldb, msg2, msg2->dn)) == NULL) {
-                       ldb_debug(module->ldb, LDB_DEBUG_FATAL, "samldb_manage_user_object: internal error! Can't generate new sid\n");
-                       talloc_free(msg2);
+               if ((sidstr = samldb_get_new_sid(module, msg2, msg2->dn)) == 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_add_attribute(msg2, "objectSid", sidstr)) {
-                       talloc_free(msg2);
+
+               if ( ! samldb_msg_add_string(module, msg2, "objectSid", sidstr)) {
                        return NULL;
                }
        }
 
-       if ( ! samldb_find_or_add_attribute(msg2, "instanceType", NULL, "4")) {
-               talloc_free(msg2);
-               return NULL;
-       }
-
-       if ( ! samldb_find_or_add_attribute(msg2, "sAMAccountName", NULL, samldb_generate_samAccountName(msg2))) {
-               talloc_free(msg2);
+       if ( ! samldb_find_or_add_attribute(module, msg2, "sAMAccountName", NULL, samldb_generate_samAccountName(msg2))) {
                return NULL;
        }
 
-       if ( ! samldb_find_or_add_attribute(msg2, "sAMAccountType", NULL, "0x30000000")) {
-               talloc_free(msg2);
-               return NULL;
-       }
-
-       if ( ! samldb_find_or_add_attribute(msg2, "objectCategory", NULL, "foo")) { /* keep the schema module happy :) */
-               return NULL;
-       }
+       /* TODO: objectGUID, objectCategory, userAccountControl, badPwdCount, codePage, countryCode, badPasswordTime, lastLogoff, lastLogon, pwdLastSet, primaryGroupID, accountExpires, logonCount */
 
-       /* TODO: objectGUID, objectSid, objectCategory, userAccountControl, badPwdCount, codePage, countryCode, badPasswordTime, lastLogoff, lastLogon, pwdLastSet, primaryGroupID, accountExpires, logonCount */
+       talloc_steal(msg, msg2);
 
        return msg2;
 }
@@ -565,17 +531,16 @@ static int samldb_add_record(struct ldb_module *module, const struct ldb_message
                return ldb_next_add_record(module, msg);
        }
 
-       /* is group?  add all group relevant missing objects */
-       msg2 = samldb_manage_group_object(module, msg);
+       /* is user or computer?  add all relevant missing objects */
+       msg2 = samldb_fill_user_or_computer_object(module, msg);
 
-       /* is user? add all user relevant missing objects */
+       /* is group? add all relevant missing objects */
        if ( ! msg2 ) {
-               msg2 = samldb_manage_user_object(module, msg);
+               msg2 = samldb_fill_group_object(module, msg);
        }
 
        if (msg2) {
                ret = ldb_next_add_record(module, msg2);
-               talloc_free(msg2);
        } else {
                ret = ldb_next_add_record(module, msg);
        }
@@ -633,7 +598,7 @@ static const char *samldb_errstring(struct ldb_module *module)
 
 static int samldb_destructor(void *module_ctx)
 {
-       struct ldb_module *ctx = module_ctx;
+       /* struct ldb_module *ctx = module_ctx; */
        /* put your clean-up functions here */
        return 0;
 }
index d6c4e2b406e82ba755cb781a41d382a3b4ecba3b..a8501c1fccf9199c720790ddf8e81e80a265f6b2 100644 (file)
@@ -12,6 +12,7 @@ dn: @ATTRIBUTES
 realm: CASE_INSENSITIVE
 userPrincipalName: CASE_INSENSITIVE
 servicePrincipalName: CASE_INSENSITIVE
+cn: CASE_INSENSITIVE
 name: CASE_INSENSITIVE WILDCARD
 dn: CASE_INSENSITIVE WILDCARD
 sAMAccountName: CASE_INSENSITIVE WILDCARD
@@ -39,7 +40,7 @@ template: groupTemplate
 #Add modules to the list to activate them by default
 #beware often order is important
 dn: @MODULES
-@LIST: timestamps
+@LIST: samldb,timestamps
 
 ###############################
 # Domain Naming Context
index 41074b4128a78f606ed9ee33580bf3093a202622..91adc8455521aab7f00082e595fbebdc896f8e00 100644 (file)
@@ -469,11 +469,10 @@ static NTSTATUS samr_CreateDomainGroup(struct dcesrv_call_state *dce_call, TALLO
        struct dcesrv_handle *h;
        const char *name;
        struct ldb_message *msg;
-       uint32_t rid;
+       struct dom_sid *sid;
        const char *groupname, *sidstr;
        struct dcesrv_handle *g_handle;
        int ret;
-       NTSTATUS status;
 
        ZERO_STRUCTP(r->out.group_handle);
        *r->out.rid = 0;
@@ -502,38 +501,14 @@ static NTSTATUS samr_CreateDomainGroup(struct dcesrv_call_state *dce_call, TALLO
                return NT_STATUS_NO_MEMORY;
        }
 
-       /* pull in all the template attributes */
-       ret = samdb_copy_template(d_state->sam_ctx, mem_ctx, msg, 
-                                 "(&(name=TemplateGroup)(objectclass=groupTemplate))");
-       if (ret != 0) {
-               DEBUG(0,("Failed to load TemplateGroup from samdb\n"));
-               return NT_STATUS_INTERNAL_DB_CORRUPTION;
-       }
-
-       /* allocate a rid */
-       status = samdb_allocate_next_id(d_state->sam_ctx, mem_ctx, 
-                                       d_state->domain_dn, "nextRid", &rid);
-       if (!NT_STATUS_IS_OK(status)) {
-               return status;
-       }
-
-       /* and the group SID */
-       sidstr = talloc_asprintf(mem_ctx, "%s-%u", d_state->domain_sid, rid);
-       if (!sidstr) {
-               return NT_STATUS_NO_MEMORY;
-       }
-
        /* add core elements to the ldb_message for the user */
        msg->dn = talloc_asprintf(mem_ctx, "CN=%s,CN=Users,%s", groupname,
                                  d_state->domain_dn);
        if (!msg->dn) {
                return NT_STATUS_NO_MEMORY;
        }
-       samdb_msg_add_string(d_state->sam_ctx, mem_ctx, msg, "name", groupname);
-       samdb_msg_add_string(d_state->sam_ctx, mem_ctx, msg, "cn", groupname);
        samdb_msg_add_string(d_state->sam_ctx, mem_ctx, msg, "sAMAccountName", groupname);
        samdb_msg_add_string(d_state->sam_ctx, mem_ctx, msg, "objectClass", "group");
-       samdb_msg_add_string(d_state->sam_ctx, mem_ctx, msg, "objectSid", sidstr);
                             
        /* create the group */
        ret = samdb_add(d_state->sam_ctx, mem_ctx, msg);
@@ -550,7 +525,16 @@ static NTSTATUS samr_CreateDomainGroup(struct dcesrv_call_state *dce_call, TALLO
        a_state->access_mask = r->in.access_mask;
        a_state->domain_state = talloc_reference(a_state, d_state);
        a_state->account_dn = talloc_steal(a_state, msg->dn);
-       a_state->account_sid = talloc_steal(a_state, sidstr);
+
+       /* retrieve the sidstring for the group just created */
+       sidstr = samdb_search_string(d_state->sam_ctx, a_state, NULL, 
+                                  "objectSid",
+                                  "dn=%s",
+                                  msg->dn);
+       if (sidstr == NULL) {
+               return NT_STATUS_UNSUCCESSFUL;
+       }
+
        a_state->account_name = talloc_strdup(a_state, groupname);
        if (!a_state->account_name) {
                return NT_STATUS_NO_MEMORY;
@@ -565,7 +549,12 @@ static NTSTATUS samr_CreateDomainGroup(struct dcesrv_call_state *dce_call, TALLO
        g_handle->data = talloc_steal(g_handle, a_state);
 
        *r->out.group_handle = g_handle->wire_handle;
-       *r->out.rid = rid;      
+
+       sid = dom_sid_parse_talloc(mem_ctx, sidstr);
+       if (!sid)
+               return NT_STATUS_UNSUCCESSFUL;
+
+       *r->out.rid = sid->sub_auths[sid->num_auths-1];
 
        return NT_STATUS_OK;
 }
@@ -692,12 +681,11 @@ static NTSTATUS samr_CreateUser2(struct dcesrv_call_state *dce_call, TALLOC_CTX
        struct dcesrv_handle *h;
        const char *name;
        struct ldb_message *msg;
-       uint32_t rid;
+       struct dom_sid *sid;
        const char *account_name, *sidstr;
        struct dcesrv_handle *u_handle;
        int ret;
-       NTSTATUS status;
-       const char *container, *additional_class=NULL;
+       const char *container, *class=NULL;
 
        ZERO_STRUCTP(r->out.user_handle);
        *r->out.access_granted = 0;
@@ -728,83 +716,32 @@ static NTSTATUS samr_CreateUser2(struct dcesrv_call_state *dce_call, TALLOC_CTX
 
        /* This must be one of these values *only* */
        if (r->in.acct_flags == ACB_NORMAL) {
-               /* pull in all the template attributes */
-               ret = samdb_copy_template(d_state->sam_ctx, mem_ctx, msg, 
-                                         "(&(name=TemplateUser)(objectclass=userTemplate))");
-               if (ret != 0) {
-                       DEBUG(0,("Failed to load TemplateUser from samdb\n"));
-                       return NT_STATUS_INTERNAL_DB_CORRUPTION;
-               }
-
                container = "Users";
+               class = "user";
 
        } else if (r->in.acct_flags == ACB_WSTRUST) {
-               /* pull in all the template attributes */
-               ret = samdb_copy_template(d_state->sam_ctx, mem_ctx, msg, 
-                                         "(&(name=TemplateMemberServer)(objectclass=userTemplate))");
-               if (ret != 0) {
-                       DEBUG(0,("Failed to load TemplateMemberServer from samdb\n"));
-                       return NT_STATUS_INTERNAL_DB_CORRUPTION;
-               }
-
                container = "Computers";
-               additional_class = "computer";
+               class = "computer";
 
        } else if (r->in.acct_flags == ACB_SVRTRUST) {
-               /* pull in all the template attributes */
-               ret = samdb_copy_template(d_state->sam_ctx, mem_ctx, msg, 
-                                         "(&(name=TemplateDomainController)(objectclass=userTemplate))");
-               if (ret != 0) {
-                       DEBUG(0,("Failed to load TemplateDomainController from samdb\n"));
-                       return NT_STATUS_INTERNAL_DB_CORRUPTION;
-               }
-
                container = "Domain Controllers";
-               additional_class = "computer";
+               class = "computer";
 
        } else if (r->in.acct_flags == ACB_DOMTRUST) {
-               /* pull in all the template attributes */
-               ret = samdb_copy_template(d_state->sam_ctx, mem_ctx, msg, 
-                                         "(&(name=TemplateTrustingDomain)(objectclass=userTemplate))");
-               if (ret != 0) {
-                       DEBUG(0,("Failed to load TemplateTrustingDomain from samdb\n"));
-                       return NT_STATUS_INTERNAL_DB_CORRUPTION;
-               }
-
                container = "Users";
-               additional_class = "computer";
+               class = "computer";
 
        } else {
                return NT_STATUS_INVALID_PARAMETER;
        }
 
-       /* allocate a rid */
-       status = samdb_allocate_next_id(d_state->sam_ctx, mem_ctx, 
-                                       d_state->domain_dn, "nextRid", &rid);
-       if (!NT_STATUS_IS_OK(status)) {
-               return status;
-       }
-
-       /* and the users SID */
-       sidstr = talloc_asprintf(mem_ctx, "%s-%u", d_state->domain_sid, rid);
-       if (!sidstr) {
-               return NT_STATUS_NO_MEMORY;
-       }
-
        /* add core elements to the ldb_message for the user */
        msg->dn = talloc_asprintf(mem_ctx, "CN=%s,CN=%s,%s", account_name, container, d_state->domain_dn);
        if (!msg->dn) {
                return NT_STATUS_NO_MEMORY;             
        }
-       samdb_msg_add_string(d_state->sam_ctx, mem_ctx, msg, "name", account_name);
-       samdb_msg_add_string(d_state->sam_ctx, mem_ctx, msg, "cn", account_name);
        samdb_msg_add_string(d_state->sam_ctx, mem_ctx, msg, "sAMAccountName", account_name);
-       samdb_msg_add_string(d_state->sam_ctx, mem_ctx, msg, "objectClass", "user");
-       if (additional_class) {
-               samdb_msg_add_string(d_state->sam_ctx, mem_ctx, msg, "objectClass", additional_class);
-       }
-       samdb_msg_add_string(d_state->sam_ctx, mem_ctx, msg, "objectSid", sidstr);
-
+       samdb_msg_add_string(d_state->sam_ctx, mem_ctx, msg, "objectClass", class);
        /* create the user */
        ret = samdb_add(d_state->sam_ctx, mem_ctx, msg);
        if (ret != 0) {
@@ -820,7 +757,16 @@ static NTSTATUS samr_CreateUser2(struct dcesrv_call_state *dce_call, TALLOC_CTX
        a_state->access_mask = r->in.access_mask;
        a_state->domain_state = talloc_reference(a_state, d_state);
        a_state->account_dn = talloc_steal(a_state, msg->dn);
-       a_state->account_sid = talloc_steal(a_state, sidstr);
+
+       /* retrieve the sidstring for the group just created */
+       sidstr = samdb_search_string(d_state->sam_ctx, a_state, NULL, 
+                                  "objectSid",
+                                  "dn=%s",
+                                  msg->dn);
+       if (sidstr == NULL) {
+               return NT_STATUS_UNSUCCESSFUL;
+       }
+
        a_state->account_name = talloc_strdup(a_state, account_name);
        if (!a_state->account_name) {
                return NT_STATUS_NO_MEMORY;
@@ -836,7 +782,12 @@ static NTSTATUS samr_CreateUser2(struct dcesrv_call_state *dce_call, TALLOC_CTX
 
        *r->out.user_handle = u_handle->wire_handle;
        *r->out.access_granted = 0xf07ff; /* TODO: fix access mask calculations */
-       *r->out.rid = rid;      
+
+       sid = dom_sid_parse_talloc(mem_ctx, sidstr);
+       if (!sid)
+               return NT_STATUS_UNSUCCESSFUL;
+
+       *r->out.rid = sid->sub_auths[sid->num_auths-1];
 
        return NT_STATUS_OK;
 }
@@ -953,10 +904,9 @@ static NTSTATUS samr_CreateDomAlias(struct dcesrv_call_state *dce_call, TALLOC_C
        struct dcesrv_handle *h;
        const char *aliasname, *name, *sidstr;
        struct ldb_message *msg;
-       uint32_t rid;
+       struct dom_sid *sid;
        struct dcesrv_handle *a_handle;
        int ret;
-       NTSTATUS status;
 
        ZERO_STRUCTP(r->out.alias_handle);
        *r->out.rid = 0;
@@ -974,7 +924,7 @@ static NTSTATUS samr_CreateDomAlias(struct dcesrv_call_state *dce_call, TALLOC_C
        /* Check if alias already exists */
        name = samdb_search_string(d_state->sam_ctx, mem_ctx, NULL,
                                   "sAMAccountName",
-                                  "(&(sAMAccountName=%s)(objectclass=group))",
+                                  "(&pAMAccountName=%s)(objectclass=group))",
                                   aliasname);
 
        if (name != NULL) {
@@ -986,28 +936,6 @@ static NTSTATUS samr_CreateDomAlias(struct dcesrv_call_state *dce_call, TALLOC_C
                return NT_STATUS_NO_MEMORY;
        }
 
-       /* pull in all the template attributes */
-       ret = samdb_copy_template(d_state->sam_ctx, mem_ctx, msg, 
-                                 "(&(name=TemplateAlias)"
-                                 "(objectclass=aliasTemplate))");
-       if (ret != 0) {
-               DEBUG(0,("Failed to load TemplateAlias from samdb\n"));
-               return NT_STATUS_INTERNAL_DB_CORRUPTION;
-       }
-
-       /* allocate a rid */
-       status = samdb_allocate_next_id(d_state->sam_ctx, mem_ctx, 
-                                       d_state->domain_dn, "nextRid", &rid);
-       if (!NT_STATUS_IS_OK(status)) {
-               return status;
-       }
-
-       /* and the group SID */
-       sidstr = talloc_asprintf(mem_ctx, "%s-%u", d_state->domain_sid, rid);
-       if (!sidstr) {
-               return NT_STATUS_NO_MEMORY;
-       }
-
        /* add core elements to the ldb_message for the alias */
        msg->dn = talloc_asprintf(mem_ctx, "CN=%s,CN=Users,%s", aliasname,
                                 d_state->domain_dn);
@@ -1015,11 +943,9 @@ static NTSTATUS samr_CreateDomAlias(struct dcesrv_call_state *dce_call, TALLOC_C
                return NT_STATUS_NO_MEMORY;
        }
 
-       samdb_msg_add_string(d_state->sam_ctx, mem_ctx, msg, "name", aliasname);
-       samdb_msg_add_string(d_state->sam_ctx, mem_ctx, msg, "cn", aliasname);
        samdb_msg_add_string(d_state->sam_ctx, mem_ctx, msg, "sAMAccountName", aliasname);
        samdb_msg_add_string(d_state->sam_ctx, mem_ctx, msg, "objectClass", "group");
-       samdb_msg_add_string(d_state->sam_ctx, mem_ctx, msg, "objectSid", sidstr);
+       samdb_msg_add_string(d_state->sam_ctx, mem_ctx, msg, "groupType", "0x80000004");
 
        /* create the alias */
        ret = samdb_add(d_state->sam_ctx, mem_ctx, msg);
@@ -1037,7 +963,16 @@ static NTSTATUS samr_CreateDomAlias(struct dcesrv_call_state *dce_call, TALLOC_C
        a_state->access_mask = r->in.access_mask;
        a_state->domain_state = talloc_reference(a_state, d_state);
        a_state->account_dn = talloc_steal(a_state, msg->dn);
-       a_state->account_sid = talloc_steal(a_state, sidstr);
+
+       /* retrieve the sidstring for the group just created */
+       sidstr = samdb_search_string(d_state->sam_ctx, a_state, NULL, 
+                                  "objectSid",
+                                  "dn=%s",
+                                  msg->dn);
+       if (sidstr == NULL) {
+               return NT_STATUS_UNSUCCESSFUL;
+       }
+
        a_state->account_name = talloc_strdup(a_state, aliasname);
        if (!a_state->account_name) {
                return NT_STATUS_NO_MEMORY;
@@ -1051,7 +986,12 @@ static NTSTATUS samr_CreateDomAlias(struct dcesrv_call_state *dce_call, TALLOC_C
        a_handle->data = talloc_steal(a_handle, a_state);
 
        *r->out.alias_handle = a_handle->wire_handle;
-       *r->out.rid = rid;
+
+       sid = dom_sid_parse_talloc(mem_ctx, sidstr);
+       if (!sid)
+               return NT_STATUS_UNSUCCESSFUL;
+
+       *r->out.rid = sid->sub_auths[sid->num_auths-1];
 
        return NT_STATUS_OK;
 }
@@ -1337,7 +1277,7 @@ static NTSTATUS samr_LookupRids(struct dcesrv_call_state *dce_call, TALLOC_CTX *
 {
        struct dcesrv_handle *h;
        struct samr_domain_state *d_state;
-       int i;
+       int i, total;
        NTSTATUS status = NT_STATUS_OK;
        struct samr_String *names;
        uint32_t *ids;
@@ -1358,6 +1298,8 @@ static NTSTATUS samr_LookupRids(struct dcesrv_call_state *dce_call, TALLOC_CTX *
        if ((names == NULL) || (ids == NULL))
                return NT_STATUS_NO_MEMORY;
 
+       total = 0;
+
        for (i=0; i<r->in.num_rids; i++) {
                struct ldb_message **res;
                int count;
@@ -1372,13 +1314,14 @@ static NTSTATUS samr_LookupRids(struct dcesrv_call_state *dce_call, TALLOC_CTX *
                                     "(objectSid=%s-%u)", d_state->domain_sid,
                                     r->in.rids[i]);
                if (count != 1) {
+                       names[i].string = NULL;
                        status = STATUS_SOME_UNMAPPED;
                        continue;
                }
 
                names[i].string = samdb_result_string(res[0], "sAMAccountName",
                                                      NULL);
-               
+
                atype = samdb_result_uint(res[0], "sAMAccountType", 0);
                if (atype == 0) {
                        status = STATUS_SOME_UNMAPPED;
@@ -2063,7 +2006,24 @@ static NTSTATUS samr_SetAliasInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX
 static NTSTATUS samr_DeleteDomAlias(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
                       struct samr_DeleteDomAlias *r)
 {
-       DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
+       struct dcesrv_handle *h;
+       struct samr_account_state *a_state;
+       int ret;
+
+        *r->out.alias_handle = *r->in.alias_handle;
+
+       DCESRV_PULL_HANDLE(h, r->in.alias_handle, SAMR_HANDLE_ALIAS);
+
+       a_state = h->data;
+
+       ret = samdb_delete(a_state->sam_ctx, mem_ctx, a_state->account_dn);
+       if (ret != 0) {
+               return NT_STATUS_UNSUCCESSFUL;
+       }
+
+       ZERO_STRUCTP(r->out.alias_handle);
+
+       return NT_STATUS_OK;
 }