summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source4/dsdb/samdb/ldb_modules/samldb.c375
-rw-r--r--source4/provision.ldif3
-rw-r--r--source4/rpc_server/samr/dcesrv_samr.c204
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; 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;
}