diff options
| author | Andrew Tridgell <tridge@samba.org> | 2008-08-22 17:37:43 +1000 | 
|---|---|---|
| committer | Andrew Tridgell <tridge@samba.org> | 2008-08-22 17:37:43 +1000 | 
| commit | 0a27ff953e17670aecc7aedb56c0f872cc4bb75d (patch) | |
| tree | 18ed167d94e1a50acf04bc22fc6d8f01bf7f1a5f | |
| parent | 8acc7f7da7718c7750387c1043391618be46e15b (diff) | |
| parent | cc43037f19056ed24d7fffa54456d597c63ad105 (diff) | |
| download | samba-0a27ff953e17670aecc7aedb56c0f872cc4bb75d.tar.gz samba-0a27ff953e17670aecc7aedb56c0f872cc4bb75d.tar.bz2 samba-0a27ff953e17670aecc7aedb56c0f872cc4bb75d.zip  | |
Merge branch 'abartlet-4-0-local' into v4-0-test
(This used to be commit 469fac2669991b130dec219e1a109a8b2ce224be)
38 files changed, 1183 insertions, 720 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..04fcd66b6e 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,10 @@ 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 ldb_handler_copy(ldb, mem_ctx, in, out);  } @@ -141,10 +145,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, 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 +213,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 +230,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 +247,10 @@ 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 ldb_handler_copy(ldb, mem_ctx, in, out);  } @@ -314,7 +329,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 +632,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 +671,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/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;  | 
