summaryrefslogtreecommitdiff
path: root/source4/dsdb/samdb/samdb.c
diff options
context:
space:
mode:
Diffstat (limited to 'source4/dsdb/samdb/samdb.c')
-rw-r--r--source4/dsdb/samdb/samdb.c182
1 files changed, 155 insertions, 27 deletions
diff --git a/source4/dsdb/samdb/samdb.c b/source4/dsdb/samdb/samdb.c
index ba73a039af..2136294661 100644
--- a/source4/dsdb/samdb/samdb.c
+++ b/source4/dsdb/samdb/samdb.c
@@ -4,7 +4,9 @@
interface functions for the sam database
Copyright (C) Andrew Tridgell 2004
-
+ Copyright (C) Volker Lendecke 2004
+ Copyright (C) Andrew Bartlett <abartlet@samba.org> 2006
+
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
@@ -25,6 +27,7 @@
#include "librpc/gen_ndr/ndr_misc.h"
#include "librpc/gen_ndr/ndr_security.h"
#include "lib/ldb/include/ldb.h"
+#include "lib/ldb/include/ldb_private.h"
#include "lib/ldb/include/ldb_errors.h"
#include "libcli/security/security.h"
#include "auth/credentials/credentials.h"
@@ -621,51 +624,121 @@ uint16_t samdb_result_acct_flags(struct ldb_message *msg, const char *attr)
return samdb_uf2acb(userAccountControl);
}
+
+/* Find an attribute, with a particular value */
+struct ldb_message_element *samdb_find_attribute(struct ldb_context *ldb,
+ const struct ldb_message *msg,
+ const char *name, const char *value)
+{
+ int i;
+ struct ldb_message_element *el = ldb_msg_find_element(msg, name);
+ struct ldb_val v;
+
+ v.data = discard_const_p(uint8_t, value);
+ v.length = strlen(value);
+
+ if (!el) {
+ return NULL;
+ }
+
+ for (i=0;i<el->num_values;i++) {
+ if (strcasecmp(value, (char *)el->values[i].data) == 0) {
+ return el;
+ }
+ }
+
+ return NULL;
+}
+
+int samdb_find_or_add_value(struct ldb_context *ldb, struct ldb_message *msg, const char *name, const char *set_value)
+{
+ if (samdb_find_attribute(ldb, msg, name, set_value) == NULL) {
+ return samdb_msg_add_string(ldb, msg, msg, name, set_value);
+ }
+ return LDB_SUCCESS;
+}
+
+int samdb_find_or_add_attribute(struct ldb_context *ldb, struct ldb_message *msg, const char *name, const char *set_value)
+{
+ struct ldb_message_element *el;
+
+ el = ldb_msg_find_element(msg, name);
+ if (el) {
+ return LDB_SUCCESS;
+ }
+
+ return samdb_msg_add_string(ldb, msg, msg, name, set_value);
+}
+
+
/*
copy from a template record to a message
*/
-int samdb_copy_template(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx,
- struct ldb_message *msg, const char *expression)
+int samdb_copy_template(struct ldb_context *ldb,
+ struct ldb_message *msg, const char *filter)
{
- struct ldb_message **res, *t;
+ struct ldb_result *res;
+ struct ldb_message *t;
int ret, i, j;
- struct ldb_dn *basedn = ldb_dn_explode(msg, "cn=Templates");
+ struct ldb_dn *basedn = ldb_dn_explode(ldb, "cn=Templates");
/* pull the template record */
- ret = gendb_search(sam_ldb, mem_ctx, basedn, &res, NULL, "%s", expression);
- if (ret != 1) {
- DEBUG(1,("samdb: ERROR: template '%s' matched %d records\n",
- expression, ret));
- return -1;
+ ret = ldb_search(ldb, basedn, LDB_SCOPE_SUBTREE, filter, NULL, &res);
+ talloc_free(basedn);
+ if (ret != LDB_SUCCESS) {
+ return ret;
+ }
+ if (res->count != 1) {
+ ldb_set_errstring(ldb, talloc_asprintf(ldb, "samdb_copy_template: ERROR: template '%s' matched %d records, expected 1\n", filter,
+ res->count));
+ talloc_free(res);
+ return LDB_ERR_OPERATIONS_ERROR;
}
- t = res[0];
+ t = res->msgs[0];
- for (i=0;i<t->num_elements;i++) {
+ 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) {
+ strcasecmp(el->name, "sAMAccountName") == 0 ||
+ strcasecmp(el->name, "objectGUID") == 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;
+ for (j = 0; j < el->num_values; j++) {
+ if (strcasecmp(el->name, "objectClass") == 0) {
+ if (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, "foreignSecurityPrincipalTemplate") == 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;
+ }
+ ret = samdb_find_or_add_value(ldb, msg, el->name,
+ (char *)el->values[j].data);
+ if (ret) {
+ ldb_set_errstring(ldb, talloc_asprintf(ldb, "Adding objectClass %s failed.\n", el->values[j].data));
+ talloc_free(res);
+ return ret;
+ }
+ } else {
+ ret = samdb_find_or_add_attribute(ldb, msg, el->name,
+ (char *)el->values[j].data);
+ if (ret) {
+ ldb_set_errstring(ldb, talloc_asprintf(ldb, "Adding attribute %s failed.\n", el->name));
+ talloc_free(res);
+ return ret;
+ }
}
- samdb_msg_add_string(sam_ldb, mem_ctx, msg, el->name,
- (char *)el->values[j].data);
}
}
- return 0;
+ talloc_free(res);
+
+ return LDB_SUCCESS;
}
@@ -678,7 +751,7 @@ int samdb_msg_add_string(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struc
char *s = talloc_strdup(mem_ctx, str);
char *a = talloc_strdup(mem_ctx, attr_name);
if (s == NULL || a == NULL) {
- return -1;
+ return LDB_ERR_OPERATIONS_ERROR;
}
return ldb_msg_add_string(msg, a, s);
}
@@ -1446,3 +1519,58 @@ NTSTATUS security_token_create(TALLOC_CTX *mem_ctx,
}
+NTSTATUS samdb_create_foreign_security_principal(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx,
+ struct dom_sid *sid, struct ldb_dn **ret_dn)
+{
+ struct ldb_message *msg;
+ struct ldb_dn *basedn;
+ const char *sidstr;
+ int ret;
+
+ sidstr = dom_sid_string(mem_ctx, sid);
+ NT_STATUS_HAVE_NO_MEMORY(sidstr);
+
+ /* We might have to create a ForeignSecurityPrincipal, even if this user
+ * is in our own domain */
+
+ msg = ldb_msg_new(mem_ctx);
+ if (msg == NULL) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ /* TODO: Hmmm. This feels wrong. How do I find the base dn to
+ * put the ForeignSecurityPrincipals? d_state->domain_dn does
+ * not work, this is wrong for the Builtin domain, there's no
+ * cn=For...,cn=Builtin,dc={BASEDN}. -- vl
+ */
+
+ basedn = samdb_search_dn(sam_ctx, mem_ctx, samdb_base_dn(mem_ctx),
+ "(&(objectClass=container)(cn=ForeignSecurityPrincipals))");
+
+ if (basedn == NULL) {
+ DEBUG(0, ("Failed to find DN for "
+ "ForeignSecurityPrincipal container\n"));
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+
+ /* add core elements to the ldb_message for the alias */
+ msg->dn = ldb_dn_build_child(mem_ctx, "CN", sidstr, basedn);
+ if (msg->dn == NULL)
+ return NT_STATUS_NO_MEMORY;
+
+ samdb_msg_add_string(sam_ctx, mem_ctx, msg,
+ "objectClass",
+ "foreignSecurityPrincipal");
+
+ /* create the alias */
+ ret = samdb_add(sam_ctx, mem_ctx, msg);
+ if (ret != 0) {
+ DEBUG(0,("Failed to create foreignSecurityPrincipal "
+ "record %s: %s\n",
+ ldb_dn_linearize(mem_ctx, msg->dn),
+ ldb_errstring(sam_ctx)));
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+ *ret_dn = msg->dn;
+ return NT_STATUS_OK;
+}