summaryrefslogtreecommitdiff
path: root/source4
diff options
context:
space:
mode:
Diffstat (limited to 'source4')
-rw-r--r--source4/cldap_server/netlogon.c52
-rw-r--r--source4/dsdb/common/flags.h11
-rw-r--r--source4/dsdb/config.mk2
-rw-r--r--source4/dsdb/samdb/ldb_modules/anr.c44
-rw-r--r--source4/dsdb/samdb/ldb_modules/linked_attributes.c8
-rw-r--r--source4/dsdb/samdb/ldb_modules/normalise.c2
-rw-r--r--source4/dsdb/samdb/ldb_modules/partition.c2
-rw-r--r--source4/dsdb/samdb/ldb_modules/samldb.c4
-rw-r--r--source4/dsdb/samdb/ldb_modules/schema_syntax.c2
-rw-r--r--source4/dsdb/samdb/ldb_modules/simple_ldap_map.c2
-rw-r--r--source4/dsdb/schema/schema_init.c545
-rw-r--r--source4/dsdb/schema/schema_query.c344
-rw-r--r--source4/dsdb/schema/schema_set.c434
-rw-r--r--source4/lib/charset/charset.h1
-rw-r--r--source4/lib/charset/util_unistr.c17
-rw-r--r--source4/lib/ldb-samba/ldif_handlers.c58
-rw-r--r--source4/lib/ldb/common/attrib_handlers.c27
-rw-r--r--source4/lib/ldb/common/ldb_attributes.c4
-rw-r--r--source4/lib/ldb/common/ldb_dn.c23
-rw-r--r--source4/lib/ldb/common/ldb_msg.c6
-rw-r--r--source4/lib/ldb/common/ldb_utf8.c12
-rw-r--r--source4/lib/ldb/include/ldb.h9
-rw-r--r--source4/lib/ldb/include/ldb_private.h9
-rw-r--r--source4/lib/ldb/ldb_tdb/ldb_index.c2
-rw-r--r--source4/lib/ldb/modules/operational.c6
-rwxr-xr-xsource4/lib/ldb/tests/python/ldap.py14
-rw-r--r--source4/lib/ldb/tools/ldbtest.c2
-rw-r--r--source4/lib/ldb_wrap.c12
-rw-r--r--source4/lib/ldb_wrap.h2
-rw-r--r--source4/lib/util/data_blob.c2
-rw-r--r--source4/lib/util/util_ldb.c4
-rw-r--r--source4/lib/util/util_ldb.h2
-rw-r--r--source4/libcli/security/dom_sid.c15
-rw-r--r--source4/librpc/idl/nbt.idl8
-rw-r--r--source4/scripting/python/samba/provision.py46
-rwxr-xr-xsource4/setup/provision-backend2
-rw-r--r--source4/setup/provision_index.ldif19
-rw-r--r--source4/setup/provision_init.ldif7
-rw-r--r--source4/torture/ldap/cldap.c146
39 files changed, 1186 insertions, 721 deletions
diff --git a/source4/cldap_server/netlogon.c b/source4/cldap_server/netlogon.c
index f263f33d48..d4242061f4 100644
--- a/source4/cldap_server/netlogon.c
+++ b/source4/cldap_server/netlogon.c
@@ -71,6 +71,7 @@ NTSTATUS fill_netlogon_samlogon_response(struct ldb_context *sam_ctx,
struct ldb_dn *partitions_basedn;
struct interface *ifaces;
bool user_known;
+ NTSTATUS status;
partitions_basedn = samdb_partitions_dn(sam_ctx, mem_ctx);
@@ -87,7 +88,7 @@ NTSTATUS fill_netlogon_samlogon_response(struct ldb_context *sam_ctx,
partitions_basedn, LDB_SCOPE_ONELEVEL,
ref_attrs,
"(&(&(objectClass=crossRef)(dnsRoot=%s))(nETBIOSName=*))",
- domain);
+ ldb_binary_encode_string(mem_ctx, domain));
if (ret != LDB_SUCCESS) {
DEBUG(2,("Unable to find referece to '%s' in sam: %s\n",
@@ -126,7 +127,7 @@ NTSTATUS fill_netlogon_samlogon_response(struct ldb_context *sam_ctx,
partitions_basedn, LDB_SCOPE_ONELEVEL,
ref_attrs,
"(&(objectClass=crossRef)(ncName=*)(nETBIOSName=%s))",
- netbios_domain);
+ ldb_binary_encode_string(mem_ctx, netbios_domain));
if (ret != LDB_SUCCESS) {
DEBUG(2,("Unable to find referece to '%s' in sam: %s\n",
@@ -161,17 +162,45 @@ NTSTATUS fill_netlogon_samlogon_response(struct ldb_context *sam_ctx,
ref_res = NULL;
if (domain_guid) {
+ struct GUID binary_guid;
+ struct ldb_val guid_val;
+ enum ndr_err_code ndr_err;
+
+ /* By this means, we ensure we don't have funny stuff in the GUID */
+
+ status = GUID_from_string(domain_guid, &binary_guid);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ /* And this gets the result into the binary format we want anyway */
+ ndr_err = ndr_push_struct_blob(&guid_val, mem_ctx, NULL, &binary_guid,
+ (ndr_push_flags_fn_t)ndr_push_GUID);
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
ret = ldb_search_exp_fmt(sam_ctx, mem_ctx, &dom_res,
NULL, LDB_SCOPE_SUBTREE,
dom_attrs,
- "(&(objectClass=domainDNS)(objectGUID=%s))",
- domain_guid);
+ "(&(objectCategory=Domain-DNS)(objectGUID=%s))",
+ ldb_binary_encode(mem_ctx, guid_val));
} else { /* domain_sid case */
+ struct dom_sid *sid;
+ struct ldb_val sid_val;
+ enum ndr_err_code ndr_err;
+
+ /* Rather than go via the string, just push into the NDR form */
+ ndr_err = ndr_push_struct_blob(&sid_val, mem_ctx, NULL, &sid,
+ (ndr_push_flags_fn_t)ndr_push_dom_sid);
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
ret = ldb_search_exp_fmt(sam_ctx, mem_ctx, &dom_res,
NULL, LDB_SCOPE_SUBTREE,
dom_attrs,
- "(&(objectClass=domainDNS)(objectSID=%s))",
- dom_sid_string(mem_ctx, domain_sid));
+ "(&(objectCategory=Domain-DNS)(objectSID=%s))",
+ ldb_binary_encode(mem_ctx, sid_val));
}
if (ret != LDB_SUCCESS) {
@@ -237,7 +266,8 @@ NTSTATUS fill_netlogon_samlogon_response(struct ldb_context *sam_ctx,
"(&(objectClass=user)(samAccountName=%s)"
"(!(userAccountControl:" LDB_OID_COMPARATOR_AND ":=%u))"
"(userAccountControl:" LDB_OID_COMPARATOR_OR ":=%u))",
- user, UF_ACCOUNTDISABLE, samdb_acb2uf(acct_control));
+ ldb_binary_encode_string(mem_ctx, user),
+ UF_ACCOUNTDISABLE, samdb_acb2uf(acct_control));
if (ret != LDB_SUCCESS) {
DEBUG(2,("Unable to find referece to user '%s' with ACB 0x%8x under %s: %s\n",
user, acct_control, ldb_dn_get_linearized(dom_res->msgs[0]->dn),
@@ -256,7 +286,8 @@ NTSTATUS fill_netlogon_samlogon_response(struct ldb_context *sam_ctx,
server_type =
NBT_SERVER_DS | NBT_SERVER_TIMESERV |
NBT_SERVER_CLOSEST | NBT_SERVER_WRITABLE |
- NBT_SERVER_GOOD_TIMESERV;
+ NBT_SERVER_GOOD_TIMESERV | NBT_SERVER_DS_DNS_CONTR |
+ NBT_SERVER_DS_DNS_DOMAIN;
if (samdb_is_pdc(sam_ctx)) {
server_type |= NBT_SERVER_PDC;
@@ -274,6 +305,10 @@ NTSTATUS fill_netlogon_samlogon_response(struct ldb_context *sam_ctx,
server_type |= NBT_SERVER_KDC;
}
+ if (!ldb_dn_compare_base(ldb_get_root_basedn(sam_ctx), ldb_get_default_basedn(sam_ctx))) {
+ server_type |= NBT_SERVER_DS_DNS_FOREST;
+ }
+
pdc_name = talloc_asprintf(mem_ctx, "\\\\%s", lp_netbios_name(lp_ctx));
domain_uuid = samdb_result_guid(dom_res->msgs[0], "objectGUID");
realm = samdb_result_string(ref_res->msgs[0], "dnsRoot", lp_realm(lp_ctx));
@@ -285,6 +320,7 @@ NTSTATUS fill_netlogon_samlogon_response(struct ldb_context *sam_ctx,
flatname = samdb_result_string(ref_res->msgs[0], "nETBIOSName",
lp_workgroup(lp_ctx));
+ /* FIXME: Hardcoded site names */
server_site = "Default-First-Site-Name";
client_site = "Default-First-Site-Name";
load_interfaces(mem_ctx, lp_interfaces(lp_ctx), &ifaces);
diff --git a/source4/dsdb/common/flags.h b/source4/dsdb/common/flags.h
index e8802fdf9c..bdd61a363c 100644
--- a/source4/dsdb/common/flags.h
+++ b/source4/dsdb/common/flags.h
@@ -119,6 +119,17 @@
#define SYSTEM_FLAG_CONFIG_ALLOW_RENAME 0x40000000
#define SYSTEM_FLAG_DISALLOW_DELTE 0x80000000
+#define SEARCH_FLAG_ATTINDEX 0x0000001
+#define SEARCH_FLAG_PDNTATTINDEX 0x0000002
+#define SEARCH_FLAG_ANR 0x0000004
+#define SEARCH_FLAG_PRESERVEONDELETE 0x0000008
+#define SEARCH_FLAG_COPY 0x0000010
+#define SEARCH_FLAG_TUPLEINDEX 0x0000020
+#define SEARCH_FLAG_SUBTREEATTRINDEX 0x0000040
+#define SEARCH_FLAG_CONFIDENTIAL 0x0000080
+#define SEARCH_FLAG_NEVERVALUEAUDIT 0x0000100
+#define SEARCH_FLAG_RODC_ATTRIBUTE 0x0000200
+
#define DS_BEHAVIOR_WIN2000 0
#define DS_BEHAVIOR_WIN2003_INTERIM 1
#define DS_BEHAVIOR_WIN2003 2
diff --git a/source4/dsdb/config.mk b/source4/dsdb/config.mk
index ae35078537..63e8a77ce4 100644
--- a/source4/dsdb/config.mk
+++ b/source4/dsdb/config.mk
@@ -34,6 +34,8 @@ PRIVATE_DEPENDENCIES = SAMDB_COMMON NDR_DRSUAPI NDR_DRSBLOBS
SAMDB_SCHEMA_OBJ_FILES = $(addprefix $(dsdbsrcdir)/schema/, \
schema_init.o \
+ schema_set.o \
+ schema_query.o \
schema_syntax.o \
schema_description.o)
diff --git a/source4/dsdb/samdb/ldb_modules/anr.c b/source4/dsdb/samdb/ldb_modules/anr.c
index 1252c9ee42..4e2c527fe9 100644
--- a/source4/dsdb/samdb/ldb_modules/anr.c
+++ b/source4/dsdb/samdb/ldb_modules/anr.c
@@ -146,7 +146,7 @@ struct ldb_parse_tree *anr_replace_callback(TALLOC_CTX *mem_ctx,
op = LDB_OP_SUBSTRING;
}
for (cur = schema->attributes; cur; cur = cur->next) {
- if (!(cur->searchFlags & 0x4)) continue;
+ if (!(cur->searchFlags & SEARCH_FLAG_ANR)) continue;
match_tree = make_match_tree(module, mem_ctx, op, cur->lDAPDisplayName, match);
if (tree) {
@@ -224,30 +224,26 @@ struct ldb_parse_tree *anr_replace_subtrees(struct ldb_parse_tree *tree,
void *context)
{
int i;
+ struct ldb_parse_tree *tmp;
+
switch (tree->operation) {
case LDB_OP_AND:
case LDB_OP_OR:
for (i=0;i<tree->u.list.num_elements;i++) {
- tree->u.list.elements[i] = anr_replace_subtrees(tree->u.list.elements[i],
- attr, callback, context);
- if (!tree->u.list.elements[i]) {
- return NULL;
- }
+ tmp = anr_replace_subtrees(tree->u.list.elements[i],
+ attr, callback, context);
+ if (tmp) tree->u.list.elements[i] = tmp;
}
break;
case LDB_OP_NOT:
- tree->u.isnot.child = anr_replace_subtrees(tree->u.isnot.child, attr, callback, context);
- if (!tree->u.isnot.child) {
- return NULL;
- }
+ tmp = anr_replace_subtrees(tree->u.isnot.child, attr, callback, context);
+ if (tmp) tree->u.isnot.child = tmp;
break;
case LDB_OP_EQUALITY:
if (ldb_attr_cmp(tree->u.equality.attr, attr) == 0) {
- tree = callback(tree, &tree->u.equality.value,
+ tmp = callback(tree, &tree->u.equality.value,
context);
- if (!tree) {
- return NULL;
- }
+ if (tmp) tree = tmp;
}
break;
case LDB_OP_SUBSTRING:
@@ -256,10 +252,8 @@ struct ldb_parse_tree *anr_replace_subtrees(struct ldb_parse_tree *tree,
tree->u.substring.end_with_wildcard == 1 &&
tree->u.substring.chunks[0] != NULL &&
tree->u.substring.chunks[1] == NULL) {
- tree = callback(tree, tree->u.substring.chunks[0], context);
- if (!tree) {
- return NULL;
- }
+ tmp = callback(tree, tree->u.substring.chunks[0], context);
+ if (tmp) tree = tmp;
}
}
break;
@@ -280,17 +274,29 @@ static int anr_search(struct ldb_module *module, struct ldb_request *req)
context->module = module;
context->found_anr = false;
+#if 0
+ printf("oldanr : %s\n", ldb_filter_from_tree (0, req->op.search.tree));
+#endif
+
/* Yes, this is a problem with req->op.search.tree being const... */
anr_tree = anr_replace_subtrees(req->op.search.tree, "anr", anr_replace_callback, context);
if (!anr_tree) {
+ talloc_free(context);
return LDB_ERR_OPERATIONS_ERROR;
}
if (context->found_anr) {
/* The above function modifies the tree if it finds "anr", so no
* point just setting this on the down_req */
+#if 0
+ printf("newtree: %s\n", ldb_filter_from_tree (0, anr_tree));
+#endif
req->op.search.tree = talloc_steal(req, anr_tree);
-
+ } else {
+ if (anr_tree != req->op.search.tree) {
+ talloc_free(anr_tree);
+ }
+ talloc_free(context);
}
return ldb_next_request(module, req);
}
diff --git a/source4/dsdb/samdb/ldb_modules/linked_attributes.c b/source4/dsdb/samdb/ldb_modules/linked_attributes.c
index 04b9987071..e64472432d 100644
--- a/source4/dsdb/samdb/ldb_modules/linked_attributes.c
+++ b/source4/dsdb/samdb/ldb_modules/linked_attributes.c
@@ -160,7 +160,7 @@ static int setup_modifies(struct ldb_context *ldb, TALLOC_CTX *mem_ctx,
ldb_oom(ldb);
return LDB_ERR_OPERATIONS_ERROR;
}
- new_msg->dn = ldb_dn_new(new_msg, ldb, (char *)el->values[j].data);
+ new_msg->dn = ldb_dn_from_ldb_val(new_msg, ldb, &el->values[j]);
if (!new_msg->dn) {
ldb_asprintf_errstring(ldb,
"attribute %s value %s was not a valid DN", msg->elements[i].name,
@@ -330,7 +330,7 @@ static int linked_attributes_mod_replace_search_callback(struct ldb_context *ldb
/* Add all the existing elements, marking as 'proposed for delete' by setting .add = false */
for (i=0; i < search_el->num_values; i++) {
merged_list = talloc_realloc(ares, merged_list, struct merge, size + 1);
- merged_list[size].dn = ldb_dn_new(merged_list, ldb, (char *)search_el->values[i].data);
+ merged_list[size].dn = ldb_dn_from_ldb_val(merged_list, ldb, &search_el->values[i]);
merged_list[size].add = false;
merged_list[size].ignore = false;
size++;
@@ -339,7 +339,7 @@ static int linked_attributes_mod_replace_search_callback(struct ldb_context *ldb
/* Add all the new replacement elements, marking as 'proposed for add' by setting .add = true */
for (i=0; i < ac2->el->num_values; i++) {
merged_list = talloc_realloc(ares, merged_list, struct merge, size + 1);
- merged_list[size].dn = ldb_dn_new(merged_list, ldb, (char *)ac2->el->values[i].data);
+ merged_list[size].dn = ldb_dn_from_ldb_val(merged_list, ldb, &ac2->el->values[i]);
merged_list[size].add = true;
merged_list[size].ignore = false;
size++;
@@ -610,7 +610,7 @@ static int linked_attributes_modify(struct ldb_module *module, struct ldb_reques
ldb_oom(module->ldb);
return LDB_ERR_OPERATIONS_ERROR;
}
- new_msg->dn = ldb_dn_new(new_msg, module->ldb, (char *)el->values[j].data);
+ new_msg->dn = ldb_dn_from_ldb_val(new_msg, module->ldb, &el->values[j]);
if (!new_msg->dn) {
ldb_asprintf_errstring(module->ldb,
"attribute %s value %s was not a valid DN", req->op.mod.message->elements[i].name,
diff --git a/source4/dsdb/samdb/ldb_modules/normalise.c b/source4/dsdb/samdb/ldb_modules/normalise.c
index 8de9e33002..3306fd3c33 100644
--- a/source4/dsdb/samdb/ldb_modules/normalise.c
+++ b/source4/dsdb/samdb/ldb_modules/normalise.c
@@ -112,7 +112,7 @@ static int normalise_search_callback(struct ldb_context *ldb, void *context, str
}
for (j = 0; j < ares->message->elements[i].num_values; j++) {
const char *dn_str;
- struct ldb_dn *dn = ldb_dn_new(mem_ctx, ldb, (const char *)ares->message->elements[i].values[j].data);
+ struct ldb_dn *dn = ldb_dn_from_ldb_val(mem_ctx, ldb, &ares->message->elements[i].values[j]);
if (!dn) {
talloc_free(mem_ctx);
return LDB_ERR_OPERATIONS_ERROR;
diff --git a/source4/dsdb/samdb/ldb_modules/partition.c b/source4/dsdb/samdb/ldb_modules/partition.c
index 9285d6d0d8..9cae6ab7b5 100644
--- a/source4/dsdb/samdb/ldb_modules/partition.c
+++ b/source4/dsdb/samdb/ldb_modules/partition.c
@@ -925,7 +925,7 @@ static int partition_init(struct ldb_module *module)
}
for (i=0; i < replicate_attributes->num_values; i++) {
- data->replicate[i] = ldb_dn_new(data->replicate, module->ldb, (const char *)replicate_attributes->values[i].data);
+ data->replicate[i] = ldb_dn_from_ldb_val(data->replicate, module->ldb, &replicate_attributes->values[i]);
if (!ldb_dn_validate(data->replicate[i])) {
ldb_asprintf_errstring(module->ldb,
"partition_init: "
diff --git a/source4/dsdb/samdb/ldb_modules/samldb.c b/source4/dsdb/samdb/ldb_modules/samldb.c
index 88590f306b..bd491bd011 100644
--- a/source4/dsdb/samdb/ldb_modules/samldb.c
+++ b/source4/dsdb/samdb/ldb_modules/samldb.c
@@ -768,6 +768,10 @@ static int samldb_modify(struct ldb_module *module, struct ldb_request *req)
struct ldb_message_element *el, *el2;
int ret;
unsigned int group_type, user_account_control, account_type;
+ if (ldb_dn_is_special(req->op.mod.message->dn)) { /* do not manipulate our control entries */
+ return ldb_next_request(module, req);
+ }
+
if (ldb_msg_find_element(req->op.mod.message, "sAMAccountType") != NULL) {
ldb_asprintf_errstring(module->ldb, "sAMAccountType must not be specified");
return LDB_ERR_UNWILLING_TO_PERFORM;
diff --git a/source4/dsdb/samdb/ldb_modules/schema_syntax.c b/source4/dsdb/samdb/ldb_modules/schema_syntax.c
index d800e4b6d2..ab9f32c913 100644
--- a/source4/dsdb/samdb/ldb_modules/schema_syntax.c
+++ b/source4/dsdb/samdb/ldb_modules/schema_syntax.c
@@ -248,7 +248,7 @@ static int schema_validate_dn(struct ldb_context *ldb, struct ldb_val *val, int
struct ldb_dn *dn;
int ret = LDB_SUCCESS;
- dn = ldb_dn_new(ldb, ldb, (const char *)val->data);
+ dn = ldb_dn_from_ldb_val(ldb, ldb, val);
if ( ! ldb_dn_validate(dn)) {
ret = LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
}
diff --git a/source4/dsdb/samdb/ldb_modules/simple_ldap_map.c b/source4/dsdb/samdb/ldb_modules/simple_ldap_map.c
index 6e967aab2f..8f92995145 100644
--- a/source4/dsdb/samdb/ldb_modules/simple_ldap_map.c
+++ b/source4/dsdb/samdb/ldb_modules/simple_ldap_map.c
@@ -154,7 +154,7 @@ static struct ldb_val objectCategory_always_dn(struct ldb_module *module, TALLOC
struct ldb_val out = data_blob(NULL, 0);
const struct ldb_schema_attribute *a = ldb_schema_attribute_by_name(module->ldb, "objectCategory");
- dn = ldb_dn_new(ctx, module->ldb, val->data);
+ dn = ldb_dn_from_ldb_val(ctx, module->ldb, val);
if (dn && ldb_dn_validate(dn)) {
talloc_free(dn);
return val_copy(module, ctx, val);
diff --git a/source4/dsdb/schema/schema_init.c b/source4/dsdb/schema/schema_init.c
index 73be580347..3ed7daee59 100644
--- a/source4/dsdb/schema/schema_init.c
+++ b/source4/dsdb/schema/schema_init.c
@@ -1409,548 +1409,3 @@ WERROR dsdb_class_from_drsuapi(struct dsdb_schema *schema,
return WERR_OK;
}
-const struct dsdb_attribute *dsdb_attribute_by_attributeID_id(const struct dsdb_schema *schema,
- uint32_t id)
-{
- struct dsdb_attribute *cur;
-
- /*
- * 0xFFFFFFFF is used as value when no mapping table is available,
- * so don't try to match with it
- */
- if (id == 0xFFFFFFFF) return NULL;
-
- /* TODO: add binary search */
- for (cur = schema->attributes; cur; cur = cur->next) {
- if (cur->attributeID_id != id) continue;
-
- return cur;
- }
-
- return NULL;
-}
-
-const struct dsdb_attribute *dsdb_attribute_by_attributeID_oid(const struct dsdb_schema *schema,
- const char *oid)
-{
- struct dsdb_attribute *cur;
-
- if (!oid) return NULL;
-
- /* TODO: add binary search */
- for (cur = schema->attributes; cur; cur = cur->next) {
- if (strcmp(cur->attributeID_oid, oid) != 0) continue;
-
- return cur;
- }
-
- return NULL;
-}
-
-const struct dsdb_attribute *dsdb_attribute_by_lDAPDisplayName(const struct dsdb_schema *schema,
- const char *name)
-{
- struct dsdb_attribute *cur;
-
- if (!name) return NULL;
-
- /* TODO: add binary search */
- for (cur = schema->attributes; cur; cur = cur->next) {
- if (strcasecmp(cur->lDAPDisplayName, name) != 0) continue;
-
- return cur;
- }
-
- return NULL;
-}
-
-const struct dsdb_attribute *dsdb_attribute_by_linkID(const struct dsdb_schema *schema,
- int linkID)
-{
- struct dsdb_attribute *cur;
-
- /* TODO: add binary search */
- for (cur = schema->attributes; cur; cur = cur->next) {
- if (cur->linkID != linkID) continue;
-
- return cur;
- }
-
- return NULL;
-}
-
-const struct dsdb_class *dsdb_class_by_governsID_id(const struct dsdb_schema *schema,
- uint32_t id)
-{
- struct dsdb_class *cur;
-
- /*
- * 0xFFFFFFFF is used as value when no mapping table is available,
- * so don't try to match with it
- */
- if (id == 0xFFFFFFFF) return NULL;
-
- /* TODO: add binary search */
- for (cur = schema->classes; cur; cur = cur->next) {
- if (cur->governsID_id != id) continue;
-
- return cur;
- }
-
- return NULL;
-}
-
-const struct dsdb_class *dsdb_class_by_governsID_oid(const struct dsdb_schema *schema,
- const char *oid)
-{
- struct dsdb_class *cur;
-
- if (!oid) return NULL;
-
- /* TODO: add binary search */
- for (cur = schema->classes; cur; cur = cur->next) {
- if (strcmp(cur->governsID_oid, oid) != 0) continue;
-
- return cur;
- }
-
- return NULL;
-}
-
-const struct dsdb_class *dsdb_class_by_lDAPDisplayName(const struct dsdb_schema *schema,
- const char *name)
-{
- struct dsdb_class *cur;
-
- if (!name) return NULL;
-
- /* TODO: add binary search */
- for (cur = schema->classes; cur; cur = cur->next) {
- if (strcasecmp(cur->lDAPDisplayName, name) != 0) continue;
-
- return cur;
- }
-
- return NULL;
-}
-
-const struct dsdb_class *dsdb_class_by_cn(const struct dsdb_schema *schema,
- const char *cn)
-{
- struct dsdb_class *cur;
-
- if (!cn) return NULL;
-
- /* TODO: add binary search */
- for (cur = schema->classes; cur; cur = cur->next) {
- if (strcasecmp(cur->cn, cn) != 0) continue;
-
- return cur;
- }
-
- return NULL;
-}
-
-const char *dsdb_lDAPDisplayName_by_id(const struct dsdb_schema *schema,
- uint32_t id)
-{
- const struct dsdb_attribute *a;
- const struct dsdb_class *c;
-
- /* TODO: add binary search */
- a = dsdb_attribute_by_attributeID_id(schema, id);
- if (a) {
- return a->lDAPDisplayName;
- }
-
- c = dsdb_class_by_governsID_id(schema, id);
- if (c) {
- return c->lDAPDisplayName;
- }
-
- return NULL;
-}
-
-/**
- Return a list of linked attributes, in lDAPDisplayName format.
-
- This may be used to determine if a modification would require
- backlinks to be updated, for example
-*/
-
-WERROR dsdb_linked_attribute_lDAPDisplayName_list(const struct dsdb_schema *schema, TALLOC_CTX *mem_ctx, const char ***attr_list_ret)
-{
- const char **attr_list = NULL;
- struct dsdb_attribute *cur;
- int i = 0;
- for (cur = schema->attributes; cur; cur = cur->next) {
- if (cur->linkID == 0) continue;
-
- attr_list = talloc_realloc(mem_ctx, attr_list, const char *, i+2);
- if (!attr_list) {
- return WERR_NOMEM;
- }
- attr_list[i] = cur->lDAPDisplayName;
- i++;
- }
- attr_list[i] = NULL;
- *attr_list_ret = attr_list;
- return WERR_OK;
-}
-
-char **merge_attr_list(TALLOC_CTX *mem_ctx,
- char **attrs, const char **new_attrs)
-{
- char **ret_attrs;
- int i;
- size_t new_len, orig_len = str_list_length((const char **)attrs);
- if (!new_attrs) {
- return attrs;
- }
-
- ret_attrs = talloc_realloc(mem_ctx,
- attrs, char *, orig_len + str_list_length(new_attrs) + 1);
- if (ret_attrs) {
- for (i=0; i < str_list_length(new_attrs); i++) {
- ret_attrs[orig_len + i] = new_attrs[i];
- }
- new_len = orig_len + str_list_length(new_attrs);
-
- ret_attrs[new_len] = NULL;
- }
-
- return ret_attrs;
-}
-
-/*
- Return a merged list of the attributes of exactly one class (not
- considering subclasses, auxillary classes etc)
-*/
-
-char **dsdb_attribute_list(TALLOC_CTX *mem_ctx, const struct dsdb_class *class, enum dsdb_attr_list_query query)
-{
- char **attr_list = NULL;
- switch (query) {
- case DSDB_SCHEMA_ALL_MAY:
- attr_list = merge_attr_list(mem_ctx, attr_list, class->mayContain);
- attr_list = merge_attr_list(mem_ctx, attr_list, class->systemMayContain);
- break;
-
- case DSDB_SCHEMA_ALL_MUST:
- attr_list = merge_attr_list(mem_ctx, attr_list, class->mustContain);
- attr_list = merge_attr_list(mem_ctx, attr_list, class->systemMustContain);
- break;
-
- case DSDB_SCHEMA_SYS_MAY:
- attr_list = merge_attr_list(mem_ctx, attr_list, class->systemMayContain);
- break;
-
- case DSDB_SCHEMA_SYS_MUST:
- attr_list = merge_attr_list(mem_ctx, attr_list, class->systemMustContain);
- break;
-
- case DSDB_SCHEMA_MAY:
- attr_list = merge_attr_list(mem_ctx, attr_list, class->mayContain);
- break;
-
- case DSDB_SCHEMA_MUST:
- attr_list = merge_attr_list(mem_ctx, attr_list, class->mustContain);
- break;
-
- case DSDB_SCHEMA_ALL:
- attr_list = merge_attr_list(mem_ctx, attr_list, class->mayContain);
- attr_list = merge_attr_list(mem_ctx, attr_list, class->systemMayContain);
- attr_list = merge_attr_list(mem_ctx, attr_list, class->mustContain);
- attr_list = merge_attr_list(mem_ctx, attr_list, class->systemMustContain);
- break;
- }
- return attr_list;
-}
-
-static char **dsdb_full_attribute_list_internal(TALLOC_CTX *mem_ctx,
- const struct dsdb_schema *schema,
- const char **class_list,
- enum dsdb_attr_list_query query)
-{
- int i;
- const struct dsdb_class *class;
-
- char **attr_list = NULL;
- char **this_class_list;
- char **recursive_list;
-
- for (i=0; class_list && class_list[i]; i++) {
- class = dsdb_class_by_lDAPDisplayName(schema, class_list[i]);
-
- this_class_list = dsdb_attribute_list(mem_ctx, class, query);
- attr_list = merge_attr_list(mem_ctx, attr_list, (const char **)this_class_list);
-
- recursive_list = dsdb_full_attribute_list_internal(mem_ctx, schema,
- class->systemAuxiliaryClass,
- query);
-
- attr_list = merge_attr_list(mem_ctx, attr_list, (const char **)recursive_list);
-
- recursive_list = dsdb_full_attribute_list_internal(mem_ctx, schema,
- class->auxiliaryClass,
- query);
-
- attr_list = merge_attr_list(mem_ctx, attr_list, (const char **)recursive_list);
-
- }
- return attr_list;
-}
-
-char **dsdb_full_attribute_list(TALLOC_CTX *mem_ctx,
- const struct dsdb_schema *schema,
- const char **class_list,
- enum dsdb_attr_list_query query)
-{
- char **attr_list = dsdb_full_attribute_list_internal(mem_ctx, schema, class_list, query);
- size_t new_len = str_list_length((const char **)attr_list);
-
- /* Remove duplicates */
- if (new_len > 1) {
- int i;
- qsort(attr_list, new_len,
- sizeof(*attr_list),
- (comparison_fn_t)strcasecmp);
-
- for (i=1 ; i < new_len; i++) {
- char **val1 = &attr_list[i-1];
- char **val2 = &attr_list[i];
- if (ldb_attr_cmp(*val1, *val2) == 0) {
- memmove(val1, val2, (new_len - i) * sizeof( *attr_list));
- new_len--;
- i--;
- }
- }
- }
- return attr_list;
-}
-/**
- * Attach the schema to an opaque pointer on the ldb, so ldb modules
- * can find it
- */
-
-int dsdb_set_schema(struct ldb_context *ldb, struct dsdb_schema *schema)
-{
- int ret;
-
- ret = ldb_set_opaque(ldb, "dsdb_schema", schema);
- if (ret != LDB_SUCCESS) {
- return ret;
- }
-
- talloc_steal(ldb, schema);
-
- return LDB_SUCCESS;
-}
-
-/**
- * Global variable to hold one copy of the schema, used to avoid memory bloat
- */
-static struct dsdb_schema *global_schema;
-
-/**
- * Make this ldb use the 'global' schema, setup to avoid having multiple copies in this process
- */
-int dsdb_set_global_schema(struct ldb_context *ldb)
-{
- int ret;
- if (!global_schema) {
- return LDB_SUCCESS;
- }
- ret = ldb_set_opaque(ldb, "dsdb_schema", global_schema);
- if (ret != LDB_SUCCESS) {
- return ret;
- }
-
- /* Keep a reference to this schema, just incase the global copy is replaced */
- if (talloc_reference(ldb, global_schema) == NULL) {
- return LDB_ERR_OPERATIONS_ERROR;
- }
-
- return LDB_SUCCESS;
-}
-
-/**
- * Find the schema object for this ldb
- */
-
-struct dsdb_schema *dsdb_get_schema(struct ldb_context *ldb)
-{
- const void *p;
- struct dsdb_schema *schema;
-
- /* see if we have a cached copy */
- p = ldb_get_opaque(ldb, "dsdb_schema");
- if (!p) {
- return NULL;
- }
-
- schema = talloc_get_type(p, struct dsdb_schema);
- if (!schema) {
- return NULL;
- }
-
- return schema;
-}
-
-/**
- * Make the schema found on this ldb the 'global' schema
- */
-
-void dsdb_make_schema_global(struct ldb_context *ldb)
-{
- struct dsdb_schema *schema = dsdb_get_schema(ldb);
- if (!schema) {
- return;
- }
-
- if (global_schema) {
- talloc_unlink(talloc_autofree_context(), schema);
- }
-
- talloc_steal(talloc_autofree_context(), schema);
- global_schema = schema;
-
- dsdb_set_global_schema(ldb);
-}
-
-
-/**
- * Rather than read a schema from the LDB itself, read it from an ldif
- * file. This allows schema to be loaded and used while adding the
- * schema itself to the directory.
- */
-
-WERROR dsdb_attach_schema_from_ldif_file(struct ldb_context *ldb, const char *pf, const char *df)
-{
- struct ldb_ldif *ldif;
- struct ldb_message *msg;
- TALLOC_CTX *mem_ctx;
- WERROR status;
- int ret;
- struct dsdb_schema *schema;
- const struct ldb_val *prefix_val;
- const struct ldb_val *info_val;
- struct ldb_val info_val_default;
-
- mem_ctx = talloc_new(ldb);
- if (!mem_ctx) {
- goto nomem;
- }
-
- schema = dsdb_new_schema(mem_ctx, lp_iconv_convenience(ldb_get_opaque(ldb, "loadparm")));
-
- schema->fsmo.we_are_master = true;
- schema->fsmo.master_dn = ldb_dn_new_fmt(schema, ldb, "@PROVISION_SCHEMA_MASTER");
- if (!schema->fsmo.master_dn) {
- goto nomem;
- }
-
- /*
- * load the prefixMap attribute from pf
- */
- ldif = ldb_ldif_read_string(ldb, &pf);
- if (!ldif) {
- status = WERR_INVALID_PARAM;
- goto failed;
- }
- talloc_steal(mem_ctx, ldif);
-
- msg = ldb_msg_canonicalize(ldb, ldif->msg);
- if (!msg) {
- goto nomem;
- }
- talloc_steal(mem_ctx, msg);
- talloc_free(ldif);
-
- prefix_val = ldb_msg_find_ldb_val(msg, "prefixMap");
- if (!prefix_val) {
- status = WERR_INVALID_PARAM;
- goto failed;
- }
-
- info_val = ldb_msg_find_ldb_val(msg, "schemaInfo");
- if (!info_val) {
- info_val_default = strhex_to_data_blob("FF0000000000000000000000000000000000000000");
- if (!info_val_default.data) {
- goto nomem;
- }
- talloc_steal(mem_ctx, info_val_default.data);
- info_val = &info_val_default;
- }
-
- status = dsdb_load_oid_mappings_ldb(schema, prefix_val, info_val);
- if (!W_ERROR_IS_OK(status)) {
- goto failed;
- }
-
- /*
- * load the attribute and class definitions outof df
- */
- while ((ldif = ldb_ldif_read_string(ldb, &df))) {
- bool is_sa;
- bool is_sc;
-
- talloc_steal(mem_ctx, ldif);
-
- msg = ldb_msg_canonicalize(ldb, ldif->msg);
- if (!msg) {
- goto nomem;
- }
-
- talloc_steal(mem_ctx, msg);
- talloc_free(ldif);
-
- is_sa = ldb_msg_check_string_attribute(msg, "objectClass", "attributeSchema");
- is_sc = ldb_msg_check_string_attribute(msg, "objectClass", "classSchema");
-
- if (is_sa) {
- struct dsdb_attribute *sa;
-
- sa = talloc_zero(schema, struct dsdb_attribute);
- if (!sa) {
- goto nomem;
- }
-
- status = dsdb_attribute_from_ldb(schema, msg, sa, sa);
- if (!W_ERROR_IS_OK(status)) {
- goto failed;
- }
-
- DLIST_ADD_END(schema->attributes, sa, struct dsdb_attribute *);
- } else if (is_sc) {
- struct dsdb_class *sc;
-
- sc = talloc_zero(schema, struct dsdb_class);
- if (!sc) {
- goto nomem;
- }
-
- status = dsdb_class_from_ldb(schema, msg, sc, sc);
- if (!W_ERROR_IS_OK(status)) {
- goto failed;
- }
-
- DLIST_ADD_END(schema->classes, sc, struct dsdb_class *);
- }
- }
-
- ret = dsdb_set_schema(ldb, schema);
- if (ret != LDB_SUCCESS) {
- status = WERR_FOOBAR;
- goto failed;
- }
-
- goto done;
-
-nomem:
- status = WERR_NOMEM;
-failed:
-done:
- talloc_free(mem_ctx);
- return status;
-}
diff --git a/source4/dsdb/schema/schema_query.c b/source4/dsdb/schema/schema_query.c
new file mode 100644
index 0000000000..ca26ffd206
--- /dev/null
+++ b/source4/dsdb/schema/schema_query.c
@@ -0,0 +1,344 @@
+/*
+ Unix SMB/CIFS mplementation.
+ DSDB schema header
+
+ Copyright (C) Stefan Metzmacher <metze@samba.org> 2006-2007
+ Copyright (C) Andrew Bartlett <abartlet@samba.org> 2006-2008
+
+ 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 3 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include "includes.h"
+#include "dsdb/samdb/samdb.h"
+
+const struct dsdb_attribute *dsdb_attribute_by_attributeID_id(const struct dsdb_schema *schema,
+ uint32_t id)
+{
+ struct dsdb_attribute *cur;
+
+ /*
+ * 0xFFFFFFFF is used as value when no mapping table is available,
+ * so don't try to match with it
+ */
+ if (id == 0xFFFFFFFF) return NULL;
+
+ /* TODO: add binary search */
+ for (cur = schema->attributes; cur; cur = cur->next) {
+ if (cur->attributeID_id != id) continue;
+
+ return cur;
+ }
+
+ return NULL;
+}
+
+const struct dsdb_attribute *dsdb_attribute_by_attributeID_oid(const struct dsdb_schema *schema,
+ const char *oid)
+{
+ struct dsdb_attribute *cur;
+
+ if (!oid) return NULL;
+
+ /* TODO: add binary search */
+ for (cur = schema->attributes; cur; cur = cur->next) {
+ if (strcmp(cur->attributeID_oid, oid) != 0) continue;
+
+ return cur;
+ }
+
+ return NULL;
+}
+
+const struct dsdb_attribute *dsdb_attribute_by_lDAPDisplayName(const struct dsdb_schema *schema,
+ const char *name)
+{
+ struct dsdb_attribute *cur;
+
+ if (!name) return NULL;
+
+ /* TODO: add binary search */
+ for (cur = schema->attributes; cur; cur = cur->next) {
+ if (strcasecmp(cur->lDAPDisplayName, name) != 0) continue;
+
+ return cur;
+ }
+
+ return NULL;
+}
+
+const struct dsdb_attribute *dsdb_attribute_by_linkID(const struct dsdb_schema *schema,
+ int linkID)
+{
+ struct dsdb_attribute *cur;
+
+ /* TODO: add binary search */
+ for (cur = schema->attributes; cur; cur = cur->next) {
+ if (cur->linkID != linkID) continue;
+
+ return cur;
+ }
+
+ return NULL;
+}
+
+const struct dsdb_class *dsdb_class_by_governsID_id(const struct dsdb_schema *schema,
+ uint32_t id)
+{
+ struct dsdb_class *cur;
+
+ /*
+ * 0xFFFFFFFF is used as value when no mapping table is available,
+ * so don't try to match with it
+ */
+ if (id == 0xFFFFFFFF) return NULL;
+
+ /* TODO: add binary search */
+ for (cur = schema->classes; cur; cur = cur->next) {
+ if (cur->governsID_id != id) continue;
+
+ return cur;
+ }
+
+ return NULL;
+}
+
+const struct dsdb_class *dsdb_class_by_governsID_oid(const struct dsdb_schema *schema,
+ const char *oid)
+{
+ struct dsdb_class *cur;
+
+ if (!oid) return NULL;
+
+ /* TODO: add binary search */
+ for (cur = schema->classes; cur; cur = cur->next) {
+ if (strcmp(cur->governsID_oid, oid) != 0) continue;
+
+ return cur;
+ }
+
+ return NULL;
+}
+
+const struct dsdb_class *dsdb_class_by_lDAPDisplayName(const struct dsdb_schema *schema,
+ const char *name)
+{
+ struct dsdb_class *cur;
+
+ if (!name) return NULL;
+
+ /* TODO: add binary search */
+ for (cur = schema->classes; cur; cur = cur->next) {
+ if (strcasecmp(cur->lDAPDisplayName, name) != 0) continue;
+
+ return cur;
+ }
+
+ return NULL;
+}
+
+const struct dsdb_class *dsdb_class_by_cn(const struct dsdb_schema *schema,
+ const char *cn)
+{
+ struct dsdb_class *cur;
+
+ if (!cn) return NULL;
+
+ /* TODO: add binary search */
+ for (cur = schema->classes; cur; cur = cur->next) {
+ if (strcasecmp(cur->cn, cn) != 0) continue;
+
+ return cur;
+ }
+
+ return NULL;
+}
+
+const char *dsdb_lDAPDisplayName_by_id(const struct dsdb_schema *schema,
+ uint32_t id)
+{
+ const struct dsdb_attribute *a;
+ const struct dsdb_class *c;
+
+ /* TODO: add binary search */
+ a = dsdb_attribute_by_attributeID_id(schema, id);
+ if (a) {
+ return a->lDAPDisplayName;
+ }
+
+ c = dsdb_class_by_governsID_id(schema, id);
+ if (c) {
+ return c->lDAPDisplayName;
+ }
+
+ return NULL;
+}
+
+/**
+ Return a list of linked attributes, in lDAPDisplayName format.
+
+ This may be used to determine if a modification would require
+ backlinks to be updated, for example
+*/
+
+WERROR dsdb_linked_attribute_lDAPDisplayName_list(const struct dsdb_schema *schema, TALLOC_CTX *mem_ctx, const char ***attr_list_ret)
+{
+ const char **attr_list = NULL;
+ struct dsdb_attribute *cur;
+ int i = 0;
+ for (cur = schema->attributes; cur; cur = cur->next) {
+ if (cur->linkID == 0) continue;
+
+ attr_list = talloc_realloc(mem_ctx, attr_list, const char *, i+2);
+ if (!attr_list) {
+ return WERR_NOMEM;
+ }
+ attr_list[i] = cur->lDAPDisplayName;
+ i++;
+ }
+ attr_list[i] = NULL;
+ *attr_list_ret = attr_list;
+ return WERR_OK;
+}
+
+char **merge_attr_list(TALLOC_CTX *mem_ctx,
+ char **attrs, const char **new_attrs)
+{
+ char **ret_attrs;
+ int i;
+ size_t new_len, orig_len = str_list_length((const char **)attrs);
+ if (!new_attrs) {
+ return attrs;
+ }
+
+ ret_attrs = talloc_realloc(mem_ctx,
+ attrs, char *, orig_len + str_list_length(new_attrs) + 1);
+ if (ret_attrs) {
+ for (i=0; i < str_list_length(new_attrs); i++) {
+ ret_attrs[orig_len + i] = new_attrs[i];
+ }
+ new_len = orig_len + str_list_length(new_attrs);
+
+ ret_attrs[new_len] = NULL;
+ }
+
+ return ret_attrs;
+}
+
+/*
+ Return a merged list of the attributes of exactly one class (not
+ considering subclasses, auxillary classes etc)
+*/
+
+char **dsdb_attribute_list(TALLOC_CTX *mem_ctx, const struct dsdb_class *class, enum dsdb_attr_list_query query)
+{
+ char **attr_list = NULL;
+ switch (query) {
+ case DSDB_SCHEMA_ALL_MAY:
+ attr_list = merge_attr_list(mem_ctx, attr_list, class->mayContain);
+ attr_list = merge_attr_list(mem_ctx, attr_list, class->systemMayContain);
+ break;
+
+ case DSDB_SCHEMA_ALL_MUST:
+ attr_list = merge_attr_list(mem_ctx, attr_list, class->mustContain);
+ attr_list = merge_attr_list(mem_ctx, attr_list, class->systemMustContain);
+ break;
+
+ case DSDB_SCHEMA_SYS_MAY:
+ attr_list = merge_attr_list(mem_ctx, attr_list, class->systemMayContain);
+ break;
+
+ case DSDB_SCHEMA_SYS_MUST:
+ attr_list = merge_attr_list(mem_ctx, attr_list, class->systemMustContain);
+ break;
+
+ case DSDB_SCHEMA_MAY:
+ attr_list = merge_attr_list(mem_ctx, attr_list, class->mayContain);
+ break;
+
+ case DSDB_SCHEMA_MUST:
+ attr_list = merge_attr_list(mem_ctx, attr_list, class->mustContain);
+ break;
+
+ case DSDB_SCHEMA_ALL:
+ attr_list = merge_attr_list(mem_ctx, attr_list, class->mayContain);
+ attr_list = merge_attr_list(mem_ctx, attr_list, class->systemMayContain);
+ attr_list = merge_attr_list(mem_ctx, attr_list, class->mustContain);
+ attr_list = merge_attr_list(mem_ctx, attr_list, class->systemMustContain);
+ break;
+ }
+ return attr_list;
+}
+
+static char **dsdb_full_attribute_list_internal(TALLOC_CTX *mem_ctx,
+ const struct dsdb_schema *schema,
+ const char **class_list,
+ enum dsdb_attr_list_query query)
+{
+ int i;
+ const struct dsdb_class *class;
+
+ char **attr_list = NULL;
+ char **this_class_list;
+ char **recursive_list;
+
+ for (i=0; class_list && class_list[i]; i++) {
+ class = dsdb_class_by_lDAPDisplayName(schema, class_list[i]);
+
+ this_class_list = dsdb_attribute_list(mem_ctx, class, query);
+ attr_list = merge_attr_list(mem_ctx, attr_list, (const char **)this_class_list);
+
+ recursive_list = dsdb_full_attribute_list_internal(mem_ctx, schema,
+ class->systemAuxiliaryClass,
+ query);
+
+ attr_list = merge_attr_list(mem_ctx, attr_list, (const char **)recursive_list);
+
+ recursive_list = dsdb_full_attribute_list_internal(mem_ctx, schema,
+ class->auxiliaryClass,
+ query);
+
+ attr_list = merge_attr_list(mem_ctx, attr_list, (const char **)recursive_list);
+
+ }
+ return attr_list;
+}
+
+char **dsdb_full_attribute_list(TALLOC_CTX *mem_ctx,
+ const struct dsdb_schema *schema,
+ const char **class_list,
+ enum dsdb_attr_list_query query)
+{
+ char **attr_list = dsdb_full_attribute_list_internal(mem_ctx, schema, class_list, query);
+ size_t new_len = str_list_length((const char **)attr_list);
+
+ /* Remove duplicates */
+ if (new_len > 1) {
+ int i;
+ qsort(attr_list, new_len,
+ sizeof(*attr_list),
+ (comparison_fn_t)strcasecmp);
+
+ for (i=1 ; i < new_len; i++) {
+ char **val1 = &attr_list[i-1];
+ char **val2 = &attr_list[i];
+ if (ldb_attr_cmp(*val1, *val2) == 0) {
+ memmove(val1, val2, (new_len - i) * sizeof( *attr_list));
+ new_len--;
+ i--;
+ }
+ }
+ }
+ return attr_list;
+}
diff --git a/source4/dsdb/schema/schema_set.c b/source4/dsdb/schema/schema_set.c
new file mode 100644
index 0000000000..0ca26c0fc7
--- /dev/null
+++ b/source4/dsdb/schema/schema_set.c
@@ -0,0 +1,434 @@
+/*
+ Unix SMB/CIFS mplementation.
+ DSDB schema header
+
+ Copyright (C) Stefan Metzmacher <metze@samba.org> 2006-2007
+ Copyright (C) Andrew Bartlett <abartlet@samba.org> 2006-2008
+
+ 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 3 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include "includes.h"
+#include "dsdb/samdb/samdb.h"
+#include "lib/ldb/include/ldb_errors.h"
+#include "lib/ldb/include/ldb_private.h"
+#include "lib/util/dlinklist.h"
+#include "param/param.h"
+
+
+static int dsdb_schema_set_attributes(struct ldb_context *ldb, struct dsdb_schema *schema, bool write_attributes)
+{
+ int ret = LDB_SUCCESS;
+ struct ldb_result *res;
+ struct ldb_result *res_idx;
+ struct dsdb_attribute *attr;
+ struct ldb_message *mod_msg;
+ TALLOC_CTX *mem_ctx = talloc_new(ldb);
+
+ struct ldb_message *msg;
+ struct ldb_message *msg_idx;
+
+ if (!mem_ctx) {
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ msg = ldb_msg_new(mem_ctx);
+ if (!msg) {
+ ldb_oom(ldb);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+ msg_idx = ldb_msg_new(mem_ctx);
+ if (!msg_idx) {
+ ldb_oom(ldb);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+ msg->dn = ldb_dn_new(msg, ldb, "@ATTRIBUTES");
+ if (!msg->dn) {
+ ldb_oom(ldb);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+ msg_idx->dn = ldb_dn_new(msg, ldb, "@INDEXLIST");
+ if (!msg_idx->dn) {
+ ldb_oom(ldb);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ for (attr = schema->attributes; attr; attr = attr->next) {
+ const struct ldb_schema_syntax *s;
+ const char *syntax = attr->syntax->ldb_syntax;
+ if (!syntax) {
+ syntax = attr->syntax->ldap_oid;
+ }
+
+ /* Write out a rough approximation of the schema as an @ATTRIBUTES value, for bootstrapping */
+ if (strcmp(syntax, LDB_SYNTAX_INTEGER) == 0) {
+ ret = ldb_msg_add_string(msg, attr->lDAPDisplayName, "INTEGER");
+ } else if (strcmp(syntax, LDB_SYNTAX_DIRECTORY_STRING) == 0) {
+ ret = ldb_msg_add_string(msg, attr->lDAPDisplayName, "CASE_INSENSITIVE");
+ }
+ if (ret != LDB_SUCCESS) {
+ return ret;
+ }
+
+ if (attr->searchFlags & SEARCH_FLAG_ATTINDEX) {
+ ret = ldb_msg_add_string(msg_idx, "@IDXATTR", attr->lDAPDisplayName);
+ if (ret != LDB_SUCCESS) {
+ return ret;
+ }
+ }
+
+ if (!attr->syntax) {
+ continue;
+ }
+
+ ret = ldb_schema_attribute_add(ldb, attr->lDAPDisplayName, LDB_ATTR_FLAG_FIXED,
+ syntax);
+ if (ret != LDB_SUCCESS) {
+ s = ldb_samba_syntax_by_name(ldb, attr->syntax->ldap_oid);
+ if (s) {
+ ret = ldb_schema_attribute_add_with_syntax(ldb, attr->lDAPDisplayName, LDB_ATTR_FLAG_FIXED, s);
+ } else {
+ ret = LDB_SUCCESS; /* Nothing to do here */
+ }
+ }
+
+ if (ret != LDB_SUCCESS) {
+ return ret;
+ }
+ }
+
+ if (!write_attributes) {
+ talloc_free(mem_ctx);
+ return ret;
+ }
+
+
+ ret = ldb_transaction_start(ldb);
+ if (ret != LDB_SUCCESS) {
+ return ret;
+ }
+
+ /* Try to avoid churning the attributes too much - we only want to do this if they have changed */
+ ret = ldb_search_exp_fmt(ldb, mem_ctx, &res, msg->dn, LDB_SCOPE_BASE, NULL, "dn=%s", ldb_dn_get_linearized(msg->dn));
+ if (ret == LDB_ERR_NO_SUCH_OBJECT) {
+ ret = ldb_add(ldb, msg);
+ } else if (ret != LDB_SUCCESS) {
+ talloc_free(mem_ctx);
+ ldb_transaction_cancel(ldb);
+ return ret;
+ } else {
+
+ if (res->count != 1) {
+ talloc_free(mem_ctx);
+ ldb_transaction_cancel(ldb);
+ return LDB_ERR_NO_SUCH_OBJECT;
+ }
+
+ ret = LDB_SUCCESS;
+ /* Annoyingly added to our search results */
+ ldb_msg_remove_attr(res->msgs[0], "distinguishedName");
+
+ mod_msg = ldb_msg_diff(ldb, res->msgs[0], msg);
+ if (mod_msg->num_elements > 0) {
+ ret = ldb_modify(ldb, mod_msg);
+ }
+ }
+
+ if (ret == LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS) {
+ /* We might be on a read-only DB */
+ talloc_free(mem_ctx);
+ ret = ldb_transaction_cancel(ldb);
+ return ret;
+ } else if (ret != LDB_SUCCESS) {
+ ldb_transaction_cancel(ldb);
+ return ret;
+ }
+
+ /* Now write out the indexs, as found in the schema (if they have changed) */
+
+ ret = ldb_search_exp_fmt(ldb, mem_ctx, &res_idx, msg_idx->dn, LDB_SCOPE_BASE, NULL, "dn=%s", ldb_dn_get_linearized(msg_idx->dn));
+ if (ret == LDB_ERR_NO_SUCH_OBJECT) {
+ ret = ldb_add(ldb, msg_idx);
+ } else if (ret != LDB_SUCCESS) {
+ talloc_free(mem_ctx);
+ ldb_transaction_cancel(ldb);
+ return ret;
+ } else {
+ if (res_idx->count != 1) {
+ talloc_free(mem_ctx);
+ ldb_transaction_cancel(ldb);
+ return LDB_ERR_NO_SUCH_OBJECT;
+ }
+
+ /* Annoyingly added to our search results */
+ ldb_msg_remove_attr(res_idx->msgs[0], "distinguishedName");
+
+ mod_msg = ldb_msg_diff(ldb, res_idx->msgs[0], msg_idx);
+ if (mod_msg->num_elements > 0) {
+ ret = ldb_modify(ldb, mod_msg);
+ }
+ }
+ if (ret == LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS) {
+ /* We might be on a read-only DB */
+ talloc_free(mem_ctx);
+ return ldb_transaction_cancel(ldb);
+ } else if (ret == LDB_SUCCESS) {
+ ret = ldb_transaction_commit(ldb);
+ } else {
+ ldb_transaction_cancel(ldb);
+ }
+ talloc_free(mem_ctx);
+ return ret;
+}
+
+
+/**
+ * Attach the schema to an opaque pointer on the ldb, so ldb modules
+ * can find it
+ */
+
+int dsdb_set_schema(struct ldb_context *ldb, struct dsdb_schema *schema)
+{
+ int ret;
+
+ ret = ldb_set_opaque(ldb, "dsdb_schema", schema);
+ if (ret != LDB_SUCCESS) {
+ return ret;
+ }
+
+ /* Set the new attributes based on the new schema */
+ ret = dsdb_schema_set_attributes(ldb, schema, true);
+ if (ret != LDB_SUCCESS) {
+ return ret;
+ }
+
+ talloc_steal(ldb, schema);
+
+ return LDB_SUCCESS;
+}
+
+/**
+ * Global variable to hold one copy of the schema, used to avoid memory bloat
+ */
+static struct dsdb_schema *global_schema;
+
+/**
+ * Make this ldb use the 'global' schema, setup to avoid having multiple copies in this process
+ */
+int dsdb_set_global_schema(struct ldb_context *ldb)
+{
+ int ret;
+ if (!global_schema) {
+ return LDB_SUCCESS;
+ }
+ ret = ldb_set_opaque(ldb, "dsdb_schema", global_schema);
+ if (ret != LDB_SUCCESS) {
+ return ret;
+ }
+
+ /* Set the new attributes based on the new schema */
+ ret = dsdb_schema_set_attributes(ldb, global_schema, false);
+ if (ret != LDB_SUCCESS) {
+ return ret;
+ }
+
+ /* Keep a reference to this schema, just incase the global copy is replaced */
+ if (talloc_reference(ldb, global_schema) == NULL) {
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ return LDB_SUCCESS;
+}
+
+/**
+ * Find the schema object for this ldb
+ */
+
+struct dsdb_schema *dsdb_get_schema(struct ldb_context *ldb)
+{
+ const void *p;
+ struct dsdb_schema *schema;
+
+ /* see if we have a cached copy */
+ p = ldb_get_opaque(ldb, "dsdb_schema");
+ if (!p) {
+ return NULL;
+ }
+
+ schema = talloc_get_type(p, struct dsdb_schema);
+ if (!schema) {
+ return NULL;
+ }
+
+ return schema;
+}
+
+/**
+ * Make the schema found on this ldb the 'global' schema
+ */
+
+void dsdb_make_schema_global(struct ldb_context *ldb)
+{
+ struct dsdb_schema *schema = dsdb_get_schema(ldb);
+ if (!schema) {
+ return;
+ }
+
+ if (global_schema) {
+ talloc_unlink(talloc_autofree_context(), schema);
+ }
+
+ talloc_steal(talloc_autofree_context(), schema);
+ global_schema = schema;
+
+ dsdb_set_global_schema(ldb);
+}
+
+
+/**
+ * Rather than read a schema from the LDB itself, read it from an ldif
+ * file. This allows schema to be loaded and used while adding the
+ * schema itself to the directory.
+ */
+
+WERROR dsdb_attach_schema_from_ldif_file(struct ldb_context *ldb, const char *pf, const char *df)
+{
+ struct ldb_ldif *ldif;
+ struct ldb_message *msg;
+ TALLOC_CTX *mem_ctx;
+ WERROR status;
+ int ret;
+ struct dsdb_schema *schema;
+ const struct ldb_val *prefix_val;
+ const struct ldb_val *info_val;
+ struct ldb_val info_val_default;
+
+ mem_ctx = talloc_new(ldb);
+ if (!mem_ctx) {
+ goto nomem;
+ }
+
+ schema = dsdb_new_schema(mem_ctx, lp_iconv_convenience(ldb_get_opaque(ldb, "loadparm")));
+
+ schema->fsmo.we_are_master = true;
+ schema->fsmo.master_dn = ldb_dn_new_fmt(schema, ldb, "@PROVISION_SCHEMA_MASTER");
+ if (!schema->fsmo.master_dn) {
+ goto nomem;
+ }
+
+ /*
+ * load the prefixMap attribute from pf
+ */
+ ldif = ldb_ldif_read_string(ldb, &pf);
+ if (!ldif) {
+ status = WERR_INVALID_PARAM;
+ goto failed;
+ }
+ talloc_steal(mem_ctx, ldif);
+
+ msg = ldb_msg_canonicalize(ldb, ldif->msg);
+ if (!msg) {
+ goto nomem;
+ }
+ talloc_steal(mem_ctx, msg);
+ talloc_free(ldif);
+
+ prefix_val = ldb_msg_find_ldb_val(msg, "prefixMap");
+ if (!prefix_val) {
+ status = WERR_INVALID_PARAM;
+ goto failed;
+ }
+
+ info_val = ldb_msg_find_ldb_val(msg, "schemaInfo");
+ if (!info_val) {
+ info_val_default = strhex_to_data_blob("FF0000000000000000000000000000000000000000");
+ if (!info_val_default.data) {
+ goto nomem;
+ }
+ talloc_steal(mem_ctx, info_val_default.data);
+ info_val = &info_val_default;
+ }
+
+ status = dsdb_load_oid_mappings_ldb(schema, prefix_val, info_val);
+ if (!W_ERROR_IS_OK(status)) {
+ goto failed;
+ }
+
+ /*
+ * load the attribute and class definitions outof df
+ */
+ while ((ldif = ldb_ldif_read_string(ldb, &df))) {
+ bool is_sa;
+ bool is_sc;
+
+ talloc_steal(mem_ctx, ldif);
+
+ msg = ldb_msg_canonicalize(ldb, ldif->msg);
+ if (!msg) {
+ goto nomem;
+ }
+
+ talloc_steal(mem_ctx, msg);
+ talloc_free(ldif);
+
+ is_sa = ldb_msg_check_string_attribute(msg, "objectClass", "attributeSchema");
+ is_sc = ldb_msg_check_string_attribute(msg, "objectClass", "classSchema");
+
+ if (is_sa) {
+ struct dsdb_attribute *sa;
+
+ sa = talloc_zero(schema, struct dsdb_attribute);
+ if (!sa) {
+ goto nomem;
+ }
+
+ status = dsdb_attribute_from_ldb(schema, msg, sa, sa);
+ if (!W_ERROR_IS_OK(status)) {
+ goto failed;
+ }
+
+ DLIST_ADD_END(schema->attributes, sa, struct dsdb_attribute *);
+ } else if (is_sc) {
+ struct dsdb_class *sc;
+
+ sc = talloc_zero(schema, struct dsdb_class);
+ if (!sc) {
+ goto nomem;
+ }
+
+ status = dsdb_class_from_ldb(schema, msg, sc, sc);
+ if (!W_ERROR_IS_OK(status)) {
+ goto failed;
+ }
+
+ DLIST_ADD_END(schema->classes, sc, struct dsdb_class *);
+ }
+ }
+
+ ret = dsdb_set_schema(ldb, schema);
+ if (ret != LDB_SUCCESS) {
+ status = WERR_FOOBAR;
+ goto failed;
+ }
+
+ goto done;
+
+nomem:
+ status = WERR_NOMEM;
+failed:
+done:
+ talloc_free(mem_ctx);
+ return status;
+}
diff --git a/source4/lib/charset/charset.h b/source4/lib/charset/charset.h
index baa7df532b..c49745cd7f 100644
--- a/source4/lib/charset/charset.h
+++ b/source4/lib/charset/charset.h
@@ -97,6 +97,7 @@ size_t count_chars_w(const char *s, char c);
void strupper_m(char *s);
void strlower_m(char *s);
char *strupper_talloc(TALLOC_CTX *ctx, const char *src);
+char *strupper_talloc_n(TALLOC_CTX *ctx, const char *src, size_t n);
char *strlower_talloc(TALLOC_CTX *ctx, const char *src);
bool strhasupper(const char *string);
bool strhaslower(const char *string);
diff --git a/source4/lib/charset/util_unistr.c b/source4/lib/charset/util_unistr.c
index 19a4f3236c..09ec7b0471 100644
--- a/source4/lib/charset/util_unistr.c
+++ b/source4/lib/charset/util_unistr.c
@@ -518,8 +518,9 @@ _PUBLIC_ char *strlower_talloc(TALLOC_CTX *ctx, const char *src)
/**
Convert a string to UPPER case, allocated with talloc
+ source length limited to n bytes
**/
-_PUBLIC_ char *strupper_talloc(TALLOC_CTX *ctx, const char *src)
+_PUBLIC_ char *strupper_talloc_n(TALLOC_CTX *ctx, const char *src, size_t n)
{
size_t size=0;
char *dest;
@@ -531,12 +532,12 @@ _PUBLIC_ char *strupper_talloc(TALLOC_CTX *ctx, const char *src)
/* this takes advantage of the fact that upper/lower can't
change the length of a character by more than 1 byte */
- dest = talloc_array(ctx, char, 2*(strlen(src))+1);
+ dest = talloc_array(ctx, char, 2*(n+1));
if (dest == NULL) {
return NULL;
}
- while (*src) {
+ while (*src && n--) {
size_t c_size;
codepoint_t c = next_codepoint(iconv_convenience, src, &c_size);
src += c_size;
@@ -562,6 +563,16 @@ _PUBLIC_ char *strupper_talloc(TALLOC_CTX *ctx, const char *src)
}
/**
+ Convert a string to UPPER case, allocated with talloc
+**/
+_PUBLIC_ char *strupper_talloc(TALLOC_CTX *ctx, const char *src)
+{
+ return strupper_talloc_n(ctx, src, src?strlen(src):0);
+}
+
+
+
+/**
Convert a string to lower case.
**/
_PUBLIC_ void strlower_m(char *s)
diff --git a/source4/lib/ldb-samba/ldif_handlers.c b/source4/lib/ldb-samba/ldif_handlers.c
index 22a57da10b..a16582d294 100644
--- a/source4/lib/ldb-samba/ldif_handlers.c
+++ b/source4/lib/ldb-samba/ldif_handlers.c
@@ -38,7 +38,7 @@ static int ldif_read_objectSid(struct ldb_context *ldb, void *mem_ctx,
{
enum ndr_err_code ndr_err;
struct dom_sid *sid;
- sid = dom_sid_parse_talloc(mem_ctx, (const char *)in->data);
+ sid = dom_sid_parse_length(mem_ctx, in);
if (sid == NULL) {
return -1;
}
@@ -70,12 +70,11 @@ static int ldif_write_objectSid(struct ldb_context *ldb, void *mem_ctx,
talloc_free(sid);
return -1;
}
- out->data = (uint8_t *)dom_sid_string(mem_ctx, sid);
+ *out = data_blob_string_const(dom_sid_string(mem_ctx, sid));
talloc_free(sid);
if (out->data == NULL) {
return -1;
}
- out->length = strlen((const char *)out->data);
return 0;
}
@@ -97,13 +96,14 @@ static int ldb_comparison_objectSid(struct ldb_context *ldb, void *mem_ctx,
const struct ldb_val *v1, const struct ldb_val *v2)
{
if (ldb_comparision_objectSid_isString(v1) && ldb_comparision_objectSid_isString(v2)) {
- return strcmp((const char *)v1->data, (const char *)v2->data);
+ return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
} else if (ldb_comparision_objectSid_isString(v1)
&& !ldb_comparision_objectSid_isString(v2)) {
struct ldb_val v;
int ret;
if (ldif_read_objectSid(ldb, mem_ctx, v1, &v) != 0) {
- return -1;
+ /* Perhaps not a string after all */
+ return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
}
ret = ldb_comparison_binary(ldb, mem_ctx, &v, v2);
talloc_free(v.data);
@@ -113,7 +113,8 @@ static int ldb_comparison_objectSid(struct ldb_context *ldb, void *mem_ctx,
struct ldb_val v;
int ret;
if (ldif_read_objectSid(ldb, mem_ctx, v2, &v) != 0) {
- return -1;
+ /* Perhaps not a string after all */
+ return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
}
ret = ldb_comparison_binary(ldb, mem_ctx, v1, &v);
talloc_free(v.data);
@@ -129,7 +130,11 @@ static int ldb_canonicalise_objectSid(struct ldb_context *ldb, void *mem_ctx,
const struct ldb_val *in, struct ldb_val *out)
{
if (ldb_comparision_objectSid_isString(in)) {
- return ldif_read_objectSid(ldb, mem_ctx, in, out);
+ if (ldif_read_objectSid(ldb, mem_ctx, in, out) != 0) {
+ /* Perhaps not a string after all */
+ return ldb_handler_copy(ldb, mem_ctx, in, out);
+ }
+ return 0;
}
return ldb_handler_copy(ldb, mem_ctx, in, out);
}
@@ -141,10 +146,16 @@ static int ldif_read_objectGUID(struct ldb_context *ldb, void *mem_ctx,
const struct ldb_val *in, struct ldb_val *out)
{
struct GUID guid;
+ char *guid_string;
NTSTATUS status;
enum ndr_err_code ndr_err;
+ guid_string = talloc_strndup(mem_ctx, (const char *)in->data, in->length);
+ if (!guid_string) {
+ return -1;
+ }
- status = GUID_from_string((const char *)in->data, &guid);
+ status = GUID_from_string(guid_string, &guid);
+ talloc_free(guid_string);
if (!NT_STATUS_IS_OK(status)) {
return -1;
}
@@ -203,13 +214,14 @@ static int ldb_comparison_objectGUID(struct ldb_context *ldb, void *mem_ctx,
const struct ldb_val *v1, const struct ldb_val *v2)
{
if (ldb_comparision_objectGUID_isString(v1) && ldb_comparision_objectGUID_isString(v2)) {
- return strcmp((const char *)v1->data, (const char *)v2->data);
+ return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
} else if (ldb_comparision_objectGUID_isString(v1)
&& !ldb_comparision_objectGUID_isString(v2)) {
struct ldb_val v;
int ret;
if (ldif_read_objectGUID(ldb, mem_ctx, v1, &v) != 0) {
- return -1;
+ /* Perhaps it wasn't a valid string after all */
+ return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
}
ret = ldb_comparison_binary(ldb, mem_ctx, &v, v2);
talloc_free(v.data);
@@ -219,7 +231,8 @@ static int ldb_comparison_objectGUID(struct ldb_context *ldb, void *mem_ctx,
struct ldb_val v;
int ret;
if (ldif_read_objectGUID(ldb, mem_ctx, v2, &v) != 0) {
- return -1;
+ /* Perhaps it wasn't a valid string after all */
+ return ldb_comparison_binary(ldb, mem_ctx, v1, v2);
}
ret = ldb_comparison_binary(ldb, mem_ctx, v1, &v);
talloc_free(v.data);
@@ -235,7 +248,11 @@ static int ldb_canonicalise_objectGUID(struct ldb_context *ldb, void *mem_ctx,
const struct ldb_val *in, struct ldb_val *out)
{
if (ldb_comparision_objectGUID_isString(in)) {
- return ldif_read_objectGUID(ldb, mem_ctx, in, out);
+ if (ldif_read_objectGUID(ldb, mem_ctx, in, out) != 0) {
+ /* Perhaps it wasn't a valid string after all */
+ return ldb_handler_copy(ldb, mem_ctx, in, out);
+ }
+ return 0;
}
return ldb_handler_copy(ldb, mem_ctx, in, out);
}
@@ -314,7 +331,7 @@ static int ldif_canonicalise_objectCategory(struct ldb_context *ldb, void *mem_c
}
return LDB_SUCCESS;
}
- dn1 = ldb_dn_new(tmp_ctx, ldb, (char *)in->data);
+ dn1 = ldb_dn_from_ldb_val(tmp_ctx, ldb, in);
if ( ! ldb_dn_validate(dn1)) {
const char *lDAPDisplayName = talloc_strndup(tmp_ctx, (char *)in->data, in->length);
class = dsdb_class_by_lDAPDisplayName(schema, lDAPDisplayName);
@@ -617,19 +634,6 @@ static const struct {
{ "fRSReplicaSetGUID", LDB_SYNTAX_SAMBA_GUID },
{ "netbootGUID", LDB_SYNTAX_SAMBA_GUID },
{ "objectCategory", LDB_SYNTAX_SAMBA_OBJECT_CATEGORY },
- { "member", LDB_SYNTAX_DN },
- { "memberOf", LDB_SYNTAX_DN },
- { "nCName", LDB_SYNTAX_DN },
- { "schemaNamingContext", LDB_SYNTAX_DN },
- { "configurationNamingContext", LDB_SYNTAX_DN },
- { "rootDomainNamingContext", LDB_SYNTAX_DN },
- { "defaultNamingContext", LDB_SYNTAX_DN },
- { "subRefs", LDB_SYNTAX_DN },
- { "dMDLocation", LDB_SYNTAX_DN },
- { "serverReference", LDB_SYNTAX_DN },
- { "masteredBy", LDB_SYNTAX_DN },
- { "msDs-masteredBy", LDB_SYNTAX_DN },
- { "fSMORoleOwner", LDB_SYNTAX_DN },
{ "prefixMap", LDB_SYNTAX_SAMBA_PREFIX_MAP }
};
@@ -669,7 +673,7 @@ int ldb_register_samba_handlers(struct ldb_context *ldb)
return -1;
}
- ret = ldb_schema_attribute_add_with_syntax(ldb, samba_attributes[i].name, 0, s);
+ ret = ldb_schema_attribute_add_with_syntax(ldb, samba_attributes[i].name, LDB_ATTR_FLAG_FIXED, s);
if (ret != LDB_SUCCESS) {
return ret;
}
diff --git a/source4/lib/ldb/common/attrib_handlers.c b/source4/lib/ldb/common/attrib_handlers.c
index 8ed2763d4d..fb57e2dadc 100644
--- a/source4/lib/ldb/common/attrib_handlers.c
+++ b/source4/lib/ldb/common/attrib_handlers.c
@@ -55,11 +55,12 @@ int ldb_handler_fold(struct ldb_context *ldb, void *mem_ctx,
{
char *s, *t;
int l;
+
if (!in || !out || !(in->data)) {
return -1;
}
- out->data = (uint8_t *)ldb_casefold(ldb, mem_ctx, (const char *)(in->data));
+ out->data = (uint8_t *)ldb_casefold(ldb, mem_ctx, (const char *)(in->data), in->length);
if (out->data == NULL) {
ldb_debug(ldb, LDB_DEBUG_ERROR, "ldb_handler_fold: unable to casefold string [%s]", in->data);
return -1;
@@ -153,13 +154,14 @@ int ldb_comparison_fold(struct ldb_context *ldb, void *mem_ctx,
const struct ldb_val *v1, const struct ldb_val *v2)
{
const char *s1=(const char *)v1->data, *s2=(const char *)v2->data;
+ size_t n1 = v1->length, n2 = v2->length;
const char *u1, *u2;
char *b1, *b2;
int ret;
- while (*s1 == ' ') s1++;
- while (*s2 == ' ') s2++;
+ while (*s1 == ' ' && n1) { s1++; n1--; };
+ while (*s2 == ' ' && n2) { s2++; n2--; };
/* TODO: make utf8 safe, possibly with helper function from application */
- while (*s1 && *s2) {
+ while (*s1 && *s2 && n1 && n2) {
/* the first 127 (0x7F) chars are ascii and utf8 guarantes they
* never appear in multibyte sequences */
if (((unsigned char)s1[0]) & 0x80) goto utf8str;
@@ -167,10 +169,11 @@ int ldb_comparison_fold(struct ldb_context *ldb, void *mem_ctx,
if (toupper((unsigned char)*s1) != toupper((unsigned char)*s2))
break;
if (*s1 == ' ') {
- while (s1[0] == s1[1]) s1++;
- while (s2[0] == s2[1]) s2++;
+ while (s1[0] == s1[1] && n1) { s1++; n1--; }
+ while (s2[0] == s2[1] && n2) { s2++; n2--; }
}
s1++; s2++;
+ n1--; n2--;
}
if (! (*s1 && *s2)) {
/* check for trailing spaces only if one of the pointers
@@ -178,15 +181,18 @@ int ldb_comparison_fold(struct ldb_context *ldb, void *mem_ctx,
* can mistakenly match.
* ex. "domain users" <-> "domainUpdates"
*/
- while (*s1 == ' ') s1++;
- while (*s2 == ' ') s2++;
+ while (*s1 == ' ') { s1++; n1--; }
+ while (*s2 == ' ') { s2++; n2--; }
+ }
+ if (n1 != n2) {
+ return n1 - n2;
}
return (int)(toupper(*s1)) - (int)(toupper(*s2));
utf8str:
/* no need to recheck from the start, just from the first utf8 char found */
- b1 = ldb_casefold(ldb, mem_ctx, s1);
- b2 = ldb_casefold(ldb, mem_ctx, s2);
+ b1 = ldb_casefold(ldb, mem_ctx, s1, n1);
+ b2 = ldb_casefold(ldb, mem_ctx, s2, n2);
if (b1 && b2) {
/* Both strings converted correctly */
@@ -221,6 +227,7 @@ utf8str:
return ret;
}
+
/*
canonicalise a attribute in DN format
*/
diff --git a/source4/lib/ldb/common/ldb_attributes.c b/source4/lib/ldb/common/ldb_attributes.c
index 3b9d01682c..747f241781 100644
--- a/source4/lib/ldb/common/ldb_attributes.c
+++ b/source4/lib/ldb/common/ldb_attributes.c
@@ -51,6 +51,10 @@ int ldb_schema_attribute_add_with_syntax(struct ldb_context *ldb,
int i, n;
struct ldb_schema_attribute *a;
+ if (!syntax) {
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
n = ldb->schema.num_attributes + 1;
a = talloc_realloc(ldb, ldb->schema.attributes,
diff --git a/source4/lib/ldb/common/ldb_dn.c b/source4/lib/ldb/common/ldb_dn.c
index 08911344b7..c0d36cfbf3 100644
--- a/source4/lib/ldb/common/ldb_dn.c
+++ b/source4/lib/ldb/common/ldb_dn.c
@@ -71,7 +71,7 @@ struct ldb_dn {
};
/* strdn may be NULL */
-struct ldb_dn *ldb_dn_new(void *mem_ctx, struct ldb_context *ldb, const char *strdn)
+struct ldb_dn *ldb_dn_from_ldb_val(void *mem_ctx, struct ldb_context *ldb, const struct ldb_val *strdn)
{
struct ldb_dn *dn;
@@ -82,27 +82,27 @@ struct ldb_dn *ldb_dn_new(void *mem_ctx, struct ldb_context *ldb, const char *st
dn->ldb = ldb;
- if (strdn) {
- if (strdn[0] == '@') {
+ if (strdn->data && strdn->length) {
+ if (strdn->data[0] == '@') {
dn->special = true;
}
- if (strncasecmp(strdn, "<GUID=", 6) == 0) {
+ if (strdn->length >= 6 && strncasecmp((const char *)strdn->data, "<GUID=", 6) == 0) {
/* this is special DN returned when the
* exploded_dn control is used */
dn->special = true;
/* FIXME: add a GUID string to ldb_dn structure */
- } else if (strncasecmp(strdn, "<SID=", 8) == 0) {
+ } else if (strdn->length >= 8 && strncasecmp((const char *)strdn->data, "<SID=", 8) == 0) {
/* this is special DN returned when the
* exploded_dn control is used */
dn->special = true;
/* FIXME: add a SID string to ldb_dn structure */
- } else if (strncasecmp(strdn, "<WKGUID=", 8) == 0) {
+ } else if (strdn->length >= 8 && strncasecmp((const char *)strdn->data, "<WKGUID=", 8) == 0) {
/* this is special DN returned when the
* exploded_dn control is used */
dn->special = true;
/* FIXME: add a WKGUID string to ldb_dn structure */
}
- dn->linearized = talloc_strdup(dn, strdn);
+ dn->linearized = talloc_strndup(dn, (const char *)strdn->data, strdn->length);
} else {
dn->linearized = talloc_strdup(dn, "");
}
@@ -115,6 +115,15 @@ failed:
return NULL;
}
+/* strdn may be NULL */
+struct ldb_dn *ldb_dn_new(void *mem_ctx, struct ldb_context *ldb, const char *strdn)
+{
+ struct ldb_val blob;
+ blob.data = strdn;
+ blob.length = strdn ? strlen(strdn) : 0;
+ return ldb_dn_from_ldb_val(mem_ctx, ldb, &blob);
+}
+
struct ldb_dn *ldb_dn_new_fmt(void *mem_ctx, struct ldb_context *ldb, const char *new_fmt, ...)
{
struct ldb_dn *dn;
diff --git a/source4/lib/ldb/common/ldb_msg.c b/source4/lib/ldb/common/ldb_msg.c
index c1ea9db56b..2f5fe1d18c 100644
--- a/source4/lib/ldb/common/ldb_msg.c
+++ b/source4/lib/ldb/common/ldb_msg.c
@@ -389,10 +389,10 @@ int ldb_msg_find_attr_as_bool(const struct ldb_message *msg,
if (!v || !v->data) {
return default_value;
}
- if (strcasecmp((const char *)v->data, "FALSE") == 0) {
+ if (v->length == 5 && strncasecmp((const char *)v->data, "FALSE", 5) == 0) {
return 0;
}
- if (strcasecmp((const char *)v->data, "TRUE") == 0) {
+ if (v->length == 4 && strncasecmp((const char *)v->data, "TRUE", 4) == 0) {
return 1;
}
return default_value;
@@ -421,7 +421,7 @@ struct ldb_dn *ldb_msg_find_attr_as_dn(struct ldb_context *ldb,
if (!v || !v->data) {
return NULL;
}
- res_dn = ldb_dn_new(mem_ctx, ldb, (const char *)v->data);
+ res_dn = ldb_dn_from_ldb_val(mem_ctx, ldb, v);
if ( ! ldb_dn_validate(res_dn)) {
talloc_free(res_dn);
return NULL;
diff --git a/source4/lib/ldb/common/ldb_utf8.c b/source4/lib/ldb/common/ldb_utf8.c
index b7b4a60122..69ee2b6964 100644
--- a/source4/lib/ldb/common/ldb_utf8.c
+++ b/source4/lib/ldb/common/ldb_utf8.c
@@ -40,8 +40,8 @@
function to handle utf8 caseless comparisons
*/
void ldb_set_utf8_fns(struct ldb_context *ldb,
- void *context,
- char *(*casefold)(void *, void *, const char *))
+ void *context,
+ char *(*casefold)(void *, void *, const char *, size_t))
{
if (context)
ldb->utf8_fns.context = context;
@@ -53,10 +53,10 @@ void ldb_set_utf8_fns(struct ldb_context *ldb,
a simple case folding function
NOTE: does not handle UTF8
*/
-char *ldb_casefold_default(void *context, void *mem_ctx, const char *s)
+char *ldb_casefold_default(void *context, void *mem_ctx, const char *s, size_t n)
{
int i;
- char *ret = talloc_strdup(mem_ctx, s);
+ char *ret = talloc_strndup(mem_ctx, s, n);
if (!s) {
errno = ENOMEM;
return NULL;
@@ -72,9 +72,9 @@ void ldb_set_utf8_default(struct ldb_context *ldb)
ldb_set_utf8_fns(ldb, NULL, ldb_casefold_default);
}
-char *ldb_casefold(struct ldb_context *ldb, void *mem_ctx, const char *s)
+char *ldb_casefold(struct ldb_context *ldb, void *mem_ctx, const char *s, size_t n)
{
- return ldb->utf8_fns.casefold(ldb->utf8_fns.context, mem_ctx, s);
+ return ldb->utf8_fns.casefold(ldb->utf8_fns.context, mem_ctx, s, n);
}
/*
diff --git a/source4/lib/ldb/include/ldb.h b/source4/lib/ldb/include/ldb.h
index 7ce6103422..937029f52c 100644
--- a/source4/lib/ldb/include/ldb.h
+++ b/source4/lib/ldb/include/ldb.h
@@ -203,7 +203,7 @@ struct ldb_debug_ops {
*/
struct ldb_utf8_fns {
void *context;
- char *(*casefold)(void *context, TALLOC_CTX *mem_ctx, const char *s);
+ char *(*casefold)(void *context, TALLOC_CTX *mem_ctx, const char *s, size_t n);
};
/**
@@ -1216,7 +1216,7 @@ void ldb_set_utf8_default(struct ldb_context *ldb);
\note The default function is not yet UTF8 aware. Provide your own
set of functions through ldb_set_utf8_fns()
*/
-char *ldb_casefold(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, const char *s);
+char *ldb_casefold(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, const char *s, size_t n);
/**
Check the attribute name is valid according to rfc2251
@@ -1381,6 +1381,7 @@ int ldb_base64_decode(char *s);
struct ldb_dn *ldb_dn_new(TALLOC_CTX *mem_ctx, struct ldb_context *ldb, const char *dn);
struct ldb_dn *ldb_dn_new_fmt(TALLOC_CTX *mem_ctx, struct ldb_context *ldb, const char *new_fmt, ...) PRINTF_ATTRIBUTE(3,4);
+struct ldb_dn *ldb_dn_from_ldb_val(void *mem_ctx, struct ldb_context *ldb, const struct ldb_val *strdn);
bool ldb_dn_validate(struct ldb_dn *dn);
char *ldb_dn_escape_value(TALLOC_CTX *mem_ctx, struct ldb_val value);
@@ -1602,8 +1603,8 @@ int ldb_set_debug(struct ldb_context *ldb,
this allows the user to set custom utf8 function for error reporting
*/
void ldb_set_utf8_fns(struct ldb_context *ldb,
- void *context,
- char *(*casefold)(void *, void *, const char *));
+ void *context,
+ char *(*casefold)(void *, void *, const char *, size_t n));
/**
this sets up debug to print messages on stderr
diff --git a/source4/lib/ldb/include/ldb_private.h b/source4/lib/ldb/include/ldb_private.h
index d7c2efe8a1..e1026ab781 100644
--- a/source4/lib/ldb/include/ldb_private.h
+++ b/source4/lib/ldb/include/ldb_private.h
@@ -91,13 +91,6 @@ struct ldb_schema {
/* attribute handling table */
unsigned num_attributes;
struct ldb_schema_attribute *attributes;
-
- /* objectclass information */
- unsigned num_classes;
- struct ldb_subclass {
- char *name;
- char **subclasses;
- } *classes;
};
/*
@@ -242,7 +235,7 @@ int save_controls(struct ldb_control *exclude, struct ldb_request *req, struct l
int check_critical_controls(struct ldb_control **controls);
/* The following definitions come from lib/ldb/common/ldb_utf8.c */
-char *ldb_casefold_default(void *context, void *mem_ctx, const char *s);
+char *ldb_casefold_default(void *context, void *mem_ctx, const char *s, size_t n);
void ldb_msg_remove_element(struct ldb_message *msg, struct ldb_message_element *el);
diff --git a/source4/lib/ldb/ldb_tdb/ldb_index.c b/source4/lib/ldb/ldb_tdb/ldb_index.c
index 1b6d9feed6..269305a468 100644
--- a/source4/lib/ldb/ldb_tdb/ldb_index.c
+++ b/source4/lib/ldb/ldb_tdb/ldb_index.c
@@ -767,7 +767,7 @@ int ltdb_search_indexed(struct ldb_handle *handle)
if ((ac->scope == LDB_SCOPE_ONELEVEL && (idxattr+idxone == 0)) ||
(ac->scope == LDB_SCOPE_SUBTREE && idxattr == 0)) {
- /* no indexs? must do full search */
+ /* no indexes? must do full search */
return LDB_ERR_OPERATIONS_ERROR;
}
diff --git a/source4/lib/ldb/modules/operational.c b/source4/lib/ldb/modules/operational.c
index 7dc4ae08c3..a59e81becd 100644
--- a/source4/lib/ldb/modules/operational.c
+++ b/source4/lib/ldb/modules/operational.c
@@ -291,12 +291,6 @@ static int operational_init(struct ldb_module *ctx)
{
int ret = 0;
- /* setup some standard attribute handlers */
- ret |= ldb_schema_attribute_add(ctx->ldb, "whenCreated", 0, LDB_SYNTAX_UTC_TIME);
- ret |= ldb_schema_attribute_add(ctx->ldb, "whenChanged", 0, LDB_SYNTAX_UTC_TIME);
- ret |= ldb_schema_attribute_add(ctx->ldb, "subschemaSubentry", 0, LDB_SYNTAX_DN);
- ret |= ldb_schema_attribute_add(ctx->ldb, "structuralObjectClass", 0, LDB_SYNTAX_OBJECTCLASS);
-
if (ret != 0) {
return ret;
}
diff --git a/source4/lib/ldb/tests/python/ldap.py b/source4/lib/ldb/tests/python/ldap.py
index 13d4adf6d4..11a824a549 100755
--- a/source4/lib/ldb/tests/python/ldap.py
+++ b/source4/lib/ldb/tests/python/ldap.py
@@ -331,15 +331,15 @@ servicePrincipalName: host/ldaptest2computer29
print "Testing Ambigious Name Resolution"
# Testing ldb.search for (&(anr=ldap testy)(objectClass=user))
res = ldb.search(expression="(&(anr=ldap testy)(objectClass=user))")
- self.assertEquals(len(res), 3, "Could not find (&(anr=ldap testy)(objectClass=user))")
+ self.assertEquals(len(res), 3, "Found only %d of 3 for (&(anr=ldap testy)(objectClass=user))" % len(res))
# Testing ldb.search for (&(anr=testy ldap)(objectClass=user))
res = ldb.search(expression="(&(anr=testy ldap)(objectClass=user))")
- self.assertEquals(len(res), 2, "Found only %d for (&(anr=testy ldap)(objectClass=user))" % len(res))
+ self.assertEquals(len(res), 2, "Found only %d of 2 for (&(anr=testy ldap)(objectClass=user))" % len(res))
# Testing ldb.search for (&(anr=ldap)(objectClass=user))
res = ldb.search(expression="(&(anr=ldap)(objectClass=user))")
- self.assertEquals(len(res), 4, "Found only %d for (&(anr=ldap)(objectClass=user))" % len(res))
+ self.assertEquals(len(res), 4, "Found only %d of 4 for (&(anr=ldap)(objectClass=user))" % len(res))
# Testing ldb.search for (&(anr==ldap)(objectClass=user))
res = ldb.search(expression="(&(anr==ldap)(objectClass=user))")
@@ -353,13 +353,13 @@ servicePrincipalName: host/ldaptest2computer29
res = ldb.search(expression="(&(anr=testy)(objectClass=user))")
self.assertEquals(len(res), 2, "Found only %d for (&(anr=testy)(objectClass=user))" % len(res))
- # Testing ldb.search for (&(anr=ldap testy)(objectClass=user))
+ # Testing ldb.search for (&(anr=testy ldap)(objectClass=user))
res = ldb.search(expression="(&(anr=testy ldap)(objectClass=user))")
- self.assertEquals(len(res), 2, "Found only %d for (&(anr=ldap testy)(objectClass=user))" % len(res))
+ self.assertEquals(len(res), 2, "Found only %d for (&(anr=testy ldap)(objectClass=user))" % len(res))
- # Testing ldb.search for (&(anr==ldap testy)(objectClass=user))
+ # Testing ldb.search for (&(anr==testy ldap)(objectClass=user))
res = ldb.search(expression="(&(anr==testy ldap)(objectClass=user))")
- self.assertEquals(len(res), 1, "Found only %d for (&(anr==ldap testy)(objectClass=user))" % len(res))
+ self.assertEquals(len(res), 1, "Found only %d for (&(anr==testy ldap)(objectClass=user))" % len(res))
self.assertEquals(str(res[0].dn), ("CN=ldaptestuser,CN=Users," + self.base_dn))
self.assertEquals(res[0]["cn"][0], "ldaptestuser")
diff --git a/source4/lib/ldb/tools/ldbtest.c b/source4/lib/ldb/tools/ldbtest.c
index 6d141478ad..169ff02da1 100644
--- a/source4/lib/ldb/tools/ldbtest.c
+++ b/source4/lib/ldb/tools/ldbtest.c
@@ -93,7 +93,7 @@ static void add_records(struct ldb_context *ldb,
el[2].name = talloc_strdup(tmp_ctx, "uid");
el[2].num_values = 1;
el[2].values = vals[2];
- vals[2][0].data = (uint8_t *)ldb_casefold(ldb, tmp_ctx, name);
+ vals[2][0].data = (uint8_t *)ldb_casefold(ldb, tmp_ctx, name, strlen(name));
vals[2][0].length = strlen((char *)vals[2][0].data);
el[3].flags = 0;
diff --git a/source4/lib/ldb_wrap.c b/source4/lib/ldb_wrap.c
index 883597108a..6c683a1e33 100644
--- a/source4/lib/ldb_wrap.c
+++ b/source4/lib/ldb_wrap.c
@@ -147,17 +147,21 @@ struct ldb_context *ldb_wrap_connect(TALLOC_CTX *mem_ctx,
talloc_free(ldb);
return NULL;
}
-
- if (lp_ctx != NULL && strcmp(lp_sam_url(lp_ctx), url) == 0) {
- dsdb_set_global_schema(ldb);
- }
+ /* This must be done before we load the schema, as these
+ * handlers for objectSid and objectGUID etc must take
+ * precedence over the 'binary attribute' declaration in the
+ * schema */
ret = ldb_register_samba_handlers(ldb);
if (ret == -1) {
talloc_free(ldb);
return NULL;
}
+ if (lp_ctx != NULL && strcmp(lp_sam_url(lp_ctx), url) == 0) {
+ dsdb_set_global_schema(ldb);
+ }
+
ldb_set_debug(ldb, ldb_wrap_debug, NULL);
ldb_set_utf8_fns(ldb, NULL, wrap_casefold);
diff --git a/source4/lib/ldb_wrap.h b/source4/lib/ldb_wrap.h
index e626b6ef8a..f2982302ab 100644
--- a/source4/lib/ldb_wrap.h
+++ b/source4/lib/ldb_wrap.h
@@ -29,7 +29,7 @@ struct cli_credentials;
struct loadparm_context;
struct event_context;
-char *wrap_casefold(void *context, void *mem_ctx, const char *s);
+char *wrap_casefold(void *context, void *mem_ctx, const char *s, size_t n);
struct ldb_context *ldb_wrap_connect(TALLOC_CTX *mem_ctx,
struct event_context *ev,
diff --git a/source4/lib/util/data_blob.c b/source4/lib/util/data_blob.c
index b258e47bba..57b34b7ae7 100644
--- a/source4/lib/util/data_blob.c
+++ b/source4/lib/util/data_blob.c
@@ -176,7 +176,7 @@ _PUBLIC_ DATA_BLOB data_blob_string_const(const char *str)
{
DATA_BLOB blob;
blob.data = discard_const_p(uint8_t, str);
- blob.length = strlen(str);
+ blob.length = str ? strlen(str) : 0;
return blob;
}
diff --git a/source4/lib/util/util_ldb.c b/source4/lib/util/util_ldb.c
index 0a7433696e..fab729c036 100644
--- a/source4/lib/util/util_ldb.c
+++ b/source4/lib/util/util_ldb.c
@@ -125,9 +125,9 @@ int gendb_add_ldif(struct ldb_context *ldb, const char *ldif_string)
return ret;
}
-char *wrap_casefold(void *context, void *mem_ctx, const char *s)
+char *wrap_casefold(void *context, void *mem_ctx, const char *s, size_t n)
{
- return strupper_talloc(mem_ctx, s);
+ return strupper_talloc_n(mem_ctx, s, n);
}
diff --git a/source4/lib/util/util_ldb.h b/source4/lib/util/util_ldb.h
index 030ba7ebee..43f98ae1a9 100644
--- a/source4/lib/util/util_ldb.h
+++ b/source4/lib/util/util_ldb.h
@@ -22,6 +22,6 @@ int gendb_search_dn(struct ldb_context *ldb,
struct ldb_message ***res,
const char * const *attrs);
int gendb_add_ldif(struct ldb_context *ldb, const char *ldif_string);
-char *wrap_casefold(void *context, void *mem_ctx, const char *s);
+char *wrap_casefold(void *context, void *mem_ctx, const char *s, size_t n);
#endif /* __LIB_UTIL_UTIL_LDB_H__ */
diff --git a/source4/libcli/security/dom_sid.c b/source4/libcli/security/dom_sid.c
index f5457e7e0e..1a7519e362 100644
--- a/source4/libcli/security/dom_sid.c
+++ b/source4/libcli/security/dom_sid.c
@@ -152,6 +152,21 @@ struct dom_sid *dom_sid_parse_talloc(TALLOC_CTX *mem_ctx, const char *sidstr)
}
/*
+ convert a string to a dom_sid, returning a talloc'd dom_sid
+*/
+struct dom_sid *dom_sid_parse_length(TALLOC_CTX *mem_ctx, const DATA_BLOB *sid)
+{
+ struct dom_sid *ret;
+ char *p = talloc_strndup(mem_ctx, sid->data, sid->length);
+ if (!p) {
+ return NULL;
+ }
+ ret = dom_sid_parse_talloc(mem_ctx, p);
+ talloc_free(p);
+ return ret;
+}
+
+/*
copy a dom_sid structure
*/
struct dom_sid *dom_sid_dup(TALLOC_CTX *mem_ctx, const struct dom_sid *dom_sid)
diff --git a/source4/librpc/idl/nbt.idl b/source4/librpc/idl/nbt.idl
index a6d0245455..63be489e0d 100644
--- a/source4/librpc/idl/nbt.idl
+++ b/source4/librpc/idl/nbt.idl
@@ -353,7 +353,13 @@ interface nbt
NBT_SERVER_TIMESERV = 0x00000040,
NBT_SERVER_CLOSEST = 0x00000080,
NBT_SERVER_WRITABLE = 0x00000100,
- NBT_SERVER_GOOD_TIMESERV = 0x00000200
+ NBT_SERVER_GOOD_TIMESERV = 0x00000200,
+ NBT_SERVER_NDNC = 0x00000400,
+ NBT_SERVER_SEL_SEC_DOM_6 = 0x00000800,
+ NBT_SERVER_FUL_SEC_DOM_6 = 0x00001000,
+ NBT_SERVER_DS_DNS_CONTR = 0x04000000,
+ NBT_SERVER_DS_DNS_DOMAIN = 0x02000000,
+ NBT_SERVER_DS_DNS_FOREST = 0x01000000
} nbt_server_type;
typedef [bitmap32bit,public] bitmap {
diff --git a/source4/scripting/python/samba/provision.py b/source4/scripting/python/samba/provision.py
index 0855efe3bb..9c2a208460 100644
--- a/source4/scripting/python/samba/provision.py
+++ b/source4/scripting/python/samba/provision.py
@@ -745,12 +745,6 @@ def setup_samdb(path, setup_path, session_info, credentials, lp,
samdb = SamDB(path, session_info=session_info,
credentials=credentials, lp=lp)
- if fill == FILL_DRS:
- # We want to finish here, but setup the index before we do so
- message("Setting up sam.ldb index")
- samdb.load_ldif_file_add(setup_path("provision_index.ldif"))
- return samdb
-
message("Pre-loading the Samba 4 and AD schema")
samdb.set_domain_sid(domainsid)
if serverrole == "domain controller":
@@ -886,9 +880,6 @@ def setup_samdb(path, setup_path, session_info, credentials, lp,
domainsid=domainsid, policyguid=policyguid,
setup_path=setup_path)
- #We want to setup the index last, as adds are faster unindexed
- message("Setting up sam.ldb index")
- samdb.load_ldif_file_add(setup_path("provision_index.ldif"))
except:
samdb.transaction_cancel()
raise
@@ -1281,39 +1272,38 @@ def provision_backend(setup_dir=None, message=None,
mmr_syncrepl_user_config = ""
if ol_mmr_urls is not None:
- mmr_hosts=filter(None,ol_mmr_urls.split(' '))
- if (len(mmr_hosts) == 1):
- mmr_hosts=filter(None,ol_mmr_urls.split(','))
+ url_list=filter(None,ol_mmr_urls.split(' '))
+ if (len(url_list) == 1):
+ url_list=filter(None,ol_mmr_urls.split(','))
mmr_on_config = "MirrorMode On"
-
- z=0
- for i in mmr_hosts:
- z=z+1
+ serverid=0
+ for url in url_list:
+ serverid=serverid+1
mmr_serverids_config += read_and_sub_file(setup_path("mmr_serverids.conf"),
- { "SERVERID" : str(z),
- "LDAPSERVER" : i })
-
- z=z+1
+ { "SERVERID" : str(serverid),
+ "LDAPSERVER" : url })
+ rid=serverid*10
+ rid=rid+1
mmr_syncrepl_schema_config += read_and_sub_file(setup_path("mmr_syncrepl.conf"),
- { "RID" : str(z),
+ { "RID" : str(rid),
"MMRDN": names.schemadn,
- "LDAPSERVER" : i,
+ "LDAPSERVER" : url,
"MMR_PASSWORD": adminpass})
- z=z+1
+ rid=rid+1
mmr_syncrepl_config_config += read_and_sub_file(setup_path("mmr_syncrepl.conf"),
- { "RID" : str(z),
+ { "RID" : str(rid),
"MMRDN": names.configdn,
- "LDAPSERVER" : i,
+ "LDAPSERVER" : url,
"MMR_PASSWORD": adminpass})
- z=z+1
+ rid=rid+1
mmr_syncrepl_user_config += read_and_sub_file(setup_path("mmr_syncrepl.conf"),
- { "RID" : str(z),
+ { "RID" : str(rid),
"MMRDN": names.domaindn,
- "LDAPSERVER" : i,
+ "LDAPSERVER" : url,
"MMR_PASSWORD": adminpass })
diff --git a/source4/setup/provision-backend b/source4/setup/provision-backend
index 049b8752a6..0943da29b6 100755
--- a/source4/setup/provision-backend
+++ b/source4/setup/provision-backend
@@ -65,7 +65,7 @@ parser.add_option("--server-role", type="choice", metavar="ROLE",
parser.add_option("--targetdir", type="string", metavar="DIR",
help="Set target directory")
parser.add_option("--ol-mmr-urls", type="string", metavar="LDAPSERVER",
- help="List of LDAP-URLS separated with whitespaces for Use with OpenLDAP-MMR")
+ help="List of LDAP-URLS [ ldap://<FQDN>:port/ (where port != 389) ] separated with whitespaces for use with OpenLDAP-MMR")
opts = parser.parse_args()[0]
diff --git a/source4/setup/provision_index.ldif b/source4/setup/provision_index.ldif
deleted file mode 100644
index 95970817f3..0000000000
--- a/source4/setup/provision_index.ldif
+++ /dev/null
@@ -1,19 +0,0 @@
-dn: @INDEXLIST
-@IDXATTR: name
-@IDXATTR: cn
-@IDXATTR: userPrincipalName
-@IDXATTR: servicePrincipalName
-@IDXATTR: sAMAccountName
-@IDXATTR: objectSid
-@IDXATTR: objectCategory
-@IDXATTR: member
-@IDXATTR: uidNumber
-@IDXATTR: gidNumber
-@IDXATTR: unixName
-@IDXATTR: privilege
-@IDXATTR: nCName
-@IDXATTR: lDAPDisplayName
-@IDXATTR: subClassOf
-@IDXATTR: dnsRoot
-@IDXATTR: nETBIOSName
-@IDXATTR: objectGUID
diff --git a/source4/setup/provision_init.ldif b/source4/setup/provision_init.ldif
index 65a12f1afa..a6c591dd51 100644
--- a/source4/setup/provision_init.ldif
+++ b/source4/setup/provision_init.ldif
@@ -1,3 +1,8 @@
+#These attributes are only used as far as the bootstrapping of the
+# schema. After that, the attributes from the schema are used.
+#
+# Therefore, they must strictly match the schema
+
dn: @ATTRIBUTES
userPrincipalName: CASE_INSENSITIVE
servicePrincipalName: CASE_INSENSITIVE
@@ -7,6 +12,8 @@ nETBIOSName: CASE_INSENSITIVE
cn: CASE_INSENSITIVE
dc: CASE_INSENSITIVE
name: CASE_INSENSITIVE
+lDAPDisplayName: CASE_INSENSITIVE
+subClassOf: CASE_INSENSITIVE
dn: CASE_INSENSITIVE
sAMAccountName: CASE_INSENSITIVE
objectClass: CASE_INSENSITIVE
diff --git a/source4/torture/ldap/cldap.c b/source4/torture/ldap/cldap.c
index 1631297793..3730193c86 100644
--- a/source4/torture/ldap/cldap.c
+++ b/source4/torture/ldap/cldap.c
@@ -228,6 +228,75 @@ static bool test_cldap_netlogon(struct torture_context *tctx, const char *dest)
}
/*
+ test cldap netlogon server type flags
+*/
+static bool test_cldap_netlogon_flags(struct torture_context *tctx,
+ const char *dest)
+{
+ struct cldap_socket *cldap;
+ NTSTATUS status;
+ struct cldap_netlogon search;
+ struct netlogon_samlogon_response n1;
+ uint32_t server_type;
+
+ cldap = cldap_socket_init(tctx, tctx->ev, lp_iconv_convenience(tctx->lp_ctx));
+
+ printf("Printing out netlogon server type flags:\n");
+
+ ZERO_STRUCT(search);
+ search.in.dest_address = dest;
+ search.in.dest_port = lp_cldap_port(tctx->lp_ctx);
+ search.in.acct_control = -1;
+ search.in.version = NETLOGON_NT_VERSION_5 | NETLOGON_NT_VERSION_5EX;
+ search.in.map_response = true;
+
+ status = cldap_netlogon(cldap, tctx, &search);
+ CHECK_STATUS(status, NT_STATUS_OK);
+
+ n1 = search.out.netlogon;
+ if (n1.ntver == NETLOGON_NT_VERSION_5)
+ server_type = n1.nt5.server_type;
+ else if (n1.ntver == NETLOGON_NT_VERSION_5EX)
+ server_type = n1.nt5_ex.server_type;
+
+ printf("The word is: %i\n", server_type);
+ if (server_type & NBT_SERVER_PDC)
+ printf("NBT_SERVER_PDC ");
+ if (server_type & NBT_SERVER_GC)
+ printf("NBT_SERVER_GC ");
+ if (server_type & NBT_SERVER_LDAP)
+ printf("NBT_SERVER_LDAP ");
+ if (server_type & NBT_SERVER_DS)
+ printf("NBT_SERVER_DS ");
+ if (server_type & NBT_SERVER_KDC)
+ printf("NBT_SERVER_KDC ");
+ if (server_type & NBT_SERVER_TIMESERV)
+ printf("NBT_SERVER_TIMESERV ");
+ if (server_type & NBT_SERVER_CLOSEST)
+ printf("NBT_SERVER_CLOSEST ");
+ if (server_type & NBT_SERVER_WRITABLE)
+ printf("NBT_SERVER_WRITABLE ");
+ if (server_type & NBT_SERVER_GOOD_TIMESERV)
+ printf("NBT_SERVER_GOOD_TIMESERV ");
+ if (server_type & NBT_SERVER_NDNC)
+ printf("NBT_SERVER_NDNC ");
+ if (server_type & NBT_SERVER_SEL_SEC_DOM_6)
+ printf("NBT_SERVER_SEL_SEC_DOM_6 ");
+ if (server_type & NBT_SERVER_FUL_SEC_DOM_6)
+ printf("NBT_SERVER_FUL_SEC_DOM_6 ");
+ if (server_type & NBT_SERVER_DS_DNS_CONTR)
+ printf("NBT_SERVER_DS_DNS_CONTR ");
+ if (server_type & NBT_SERVER_DS_DNS_DOMAIN)
+ printf("NBT_SERVER_DS_DNS_DOMAIN ");
+ if (server_type & NBT_SERVER_DS_DNS_FOREST)
+ printf("NBT_SERVER_DS_DNS_FOREST ");
+
+ printf("\n");
+
+ return true;
+}
+
+/*
convert a ldap result message to a ldb message. This allows us to
use the convenient ldif dump routines in ldb to print out cldap
search results
@@ -266,6 +335,81 @@ static void cldap_dump_results(struct cldap_search *search)
talloc_free(ldb);
}
+
+/*
+ test cldap netlogon server type flag "NBT_SERVER_DS_DNS_FOREST"
+*/
+static bool test_cldap_netlogon_flag_ds_dns_forest(struct torture_context *tctx,
+ const char *dest)
+{
+ struct cldap_socket *cldap;
+ NTSTATUS status;
+ struct cldap_netlogon search;
+ uint32_t server_type;
+ struct netlogon_samlogon_response n1;
+
+ bool result = true;
+
+ cldap = cldap_socket_init(tctx, tctx->ev, lp_iconv_convenience(tctx->lp_ctx));
+
+ printf("Testing netlogon server type flag NBT_SERVER_DS_DNS_FOREST: ");
+
+ ZERO_STRUCT(search);
+ search.in.dest_address = dest;
+ search.in.dest_port = lp_cldap_port(tctx->lp_ctx);
+ search.in.acct_control = -1;
+ search.in.version = NETLOGON_NT_VERSION_5 | NETLOGON_NT_VERSION_5EX;
+ search.in.map_response = true;
+
+ status = cldap_netlogon(cldap, tctx, &search);
+ CHECK_STATUS(status, NT_STATUS_OK);
+
+ n1 = search.out.netlogon;
+ if (n1.ntver == NETLOGON_NT_VERSION_5)
+ server_type = n1.nt5.server_type;
+ else if (n1.ntver == NETLOGON_NT_VERSION_5EX)
+ server_type = n1.nt5_ex.server_type;
+
+ if (server_type & NBT_SERVER_DS_DNS_FOREST) {
+ struct cldap_search search2;
+ const char *attrs[] = { "defaultNamingContext", "rootDomainNamingContext",
+ NULL };
+ struct ldb_context *ldb;
+ struct ldb_message *msg;
+
+ /* Trying to fetch the attributes "defaultNamingContext" and
+ "rootDomainNamingContext" */
+ ZERO_STRUCT(search2);
+ search2.in.dest_address = dest;
+ search2.in.dest_port = lp_cldap_port(tctx->lp_ctx);
+ search2.in.timeout = 10;
+ search2.in.retries = 3;
+ search2.in.filter = "(objectclass=*)";
+ search2.in.attributes = attrs;
+
+ status = cldap_search(cldap, tctx, &search2);
+ CHECK_STATUS(status, NT_STATUS_OK);
+
+ ldb = ldb_init(NULL, NULL);
+
+ msg = ldap_msg_to_ldb(ldb, ldb, search2.out.response);
+
+ /* Try to compare the two attributes */
+ if (ldb_msg_element_compare(ldb_msg_find_element(msg, attrs[0]),
+ ldb_msg_find_element(msg, attrs[1])))
+ result = false;
+
+ talloc_free(ldb);
+ }
+
+ if (result)
+ printf("passed\n");
+ else
+ printf("failed\n");
+
+ return result;
+}
+
/*
test generic cldap operations
*/
@@ -343,6 +487,8 @@ bool torture_cldap(struct torture_context *torture)
const char *host = torture_setting_string(torture, "host", NULL);
ret &= test_cldap_netlogon(torture, host);
+ ret &= test_cldap_netlogon_flags(torture, host);
+ ret &= test_cldap_netlogon_flag_ds_dns_forest(torture, host);
ret &= test_cldap_generic(torture, host);
return ret;