From 5487ee5e9c9e6ea087b778ab7d90d8c38b348017 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Sun, 27 Mar 2005 23:31:43 +0000 Subject: r6084: - Introduce the samldb module dependency on samba4 - 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. (This used to be commit fb9afcaf533a4c32547d1857306e0aece8063953) --- source4/dsdb/samdb/ldb_modules/samldb.c | 375 +++++++++++++++----------------- source4/provision.ldif | 3 +- source4/rpc_server/samr/dcesrv_samr.c | 204 +++++++---------- 3 files changed, 254 insertions(+), 328 deletions(-) diff --git a/source4/dsdb/samdb/ldb_modules/samldb.c b/source4/dsdb/samdb/ldb_modules/samldb.c index ddd878070d..7ec1ea1a29 100644 --- a/source4/dsdb/samdb/ldb_modules/samldb.c +++ b/source4/dsdb/samdb/ldb_modules/samldb.c @@ -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; } diff --git a/source4/provision.ldif b/source4/provision.ldif index d6c4e2b406..a8501c1fcc 100644 --- a/source4/provision.ldif +++ b/source4/provision.ldif @@ -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 diff --git a/source4/rpc_server/samr/dcesrv_samr.c b/source4/rpc_server/samr/dcesrv_samr.c index 41074b4128..91adc84555 100644 --- a/source4/rpc_server/samr/dcesrv_samr.c +++ b/source4/rpc_server/samr/dcesrv_samr.c @@ -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; iin.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; } -- cgit