1
0
mirror of https://github.com/samba-team/samba.git synced 2025-02-04 17:47:26 +03:00

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 commit is contained in:
Simo Sorce 2005-03-27 23:31:43 +00:00 committed by Gerald (Jerry) Carter
parent 258c04e367
commit fb9afcaf53
3 changed files with 255 additions and 329 deletions

View 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
* 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 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 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.
This library is distributed in the hope that it will be useful,
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;
char *aname = talloc_strdup(msg, name);
char *aval = talloc_strdup(msg, value);
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;
}
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")) {
if ( ! samldb_find_or_add_attribute(module, msg2, "sAMAccountName", NULL, samldb_generate_samAccountName(msg2))) {
return NULL;
}
if ( ! samldb_find_or_add_attribute(msg2, "sAMAccountName", NULL, samldb_generate_samAccountName(msg2))) {
return NULL;
}
/* TODO: objectGUID */
if ( ! samldb_find_or_add_attribute(msg2, "sAMAccountType", NULL, "0x10000000")) {
return NULL;
}
if ( ! samldb_find_or_add_attribute(msg2, "groupType", NULL, "0x80000002")) {
return NULL;
}
if ( ! samldb_find_or_add_attribute(msg2, "objectCategory", NULL, "foo")) { /* keep the schema module happy :) */
return NULL;
}
/* 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);
if (!msg2) {
ldb_debug(module->ldb, LDB_DEBUG_FATAL, "samldb_manage_user_object: talloc failed!\n");
return NULL;
}
ldb_debug(module->ldb, LDB_DEBUG_TRACE, "samldb_fill_user_or_computer_object\n");
/* 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);
msg2 = ldb_msg_copy(module->ldb, msg);
if (!msg2) {
ldb_debug(module->ldb, LDB_DEBUG_FATAL, "samldb_fill_group_object: ldb_msg_copy failed!\n");
return NULL;
}
for (i = 0; i < msg2->num_elements; i++) {
msg2->elements[i] = msg->elements[i];
if (samldb_copy_template(module, msg2, "(&(name=TemplateUser)(objectclass=userTemplate))") != 0) {
ldb_debug(module->ldb, LDB_DEBUG_FATAL, "samldb_fill_user_or_computer_object: Error copying template!\n");
return NULL;
}
if ( ! samldb_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);
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", "top", "top")) {
talloc_free(msg2);
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);
if ( ! samldb_find_or_add_attribute(module, msg2, "sAMAccountName", NULL, samldb_generate_samAccountName(msg2))) {
return NULL;
}
if ( ! samldb_find_or_add_attribute(msg2, "sAMAccountName", NULL, samldb_generate_samAccountName(msg2))) {
talloc_free(msg2);
return NULL;
}
/* TODO: objectGUID, objectCategory, userAccountControl, badPwdCount, codePage, countryCode, badPasswordTime, lastLogoff, lastLogon, pwdLastSet, primaryGroupID, accountExpires, logonCount */
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, 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;
}

View 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

View 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;
}