diff options
| -rw-r--r-- | source4/dsdb/samdb/ldb_modules/schema_fsmo.c | 77 | ||||
| -rw-r--r-- | source4/dsdb/samdb/ldb_modules/simple_ldap_map.c | 4 | ||||
| -rw-r--r-- | source4/dsdb/schema/schema.h | 9 | ||||
| -rw-r--r-- | source4/dsdb/schema/schema_init.c | 306 | ||||
| -rw-r--r-- | source4/setup/schema_samba4.ldif | 158 | ||||
| -rw-r--r-- | source4/setup/slapd.conf | 2 | ||||
| -rw-r--r-- | source4/utils/ad2oLschema.c | 344 | 
7 files changed, 511 insertions, 389 deletions
diff --git a/source4/dsdb/samdb/ldb_modules/schema_fsmo.c b/source4/dsdb/samdb/ldb_modules/schema_fsmo.c index 6f65c199ba..a397228723 100644 --- a/source4/dsdb/samdb/ldb_modules/schema_fsmo.c +++ b/source4/dsdb/samdb/ldb_modules/schema_fsmo.c @@ -37,17 +37,8 @@ static int schema_fsmo_init(struct ldb_module *module)  	TALLOC_CTX *mem_ctx;  	struct ldb_dn *schema_dn;  	struct dsdb_schema *schema; -	struct ldb_result *schema_res; -	struct ldb_result *a_res; -	struct ldb_result *c_res;  	char *error_string = NULL;  	int ret; -	static const char *schema_attrs[] = { -		"prefixMap", -		"schemaInfo", -		"fSMORoleOwner", -		NULL -	};  	if (dsdb_get_schema(module->ldb)) {  		return ldb_next_init(module); @@ -67,83 +58,25 @@ static int schema_fsmo_init(struct ldb_module *module)  		return LDB_ERR_OPERATIONS_ERROR;  	} -	/* -	 * setup the prefix mappings and schema info -	 */ -	ret = ldb_search(module->ldb, schema_dn, -			 LDB_SCOPE_BASE, -			 NULL, schema_attrs, -			 &schema_res); +	ret = dsdb_schema_from_schema_dn(mem_ctx, module->ldb, +					 lp_iconv_convenience(ldb_get_opaque(module->ldb, "loadparm")), +					 schema_dn, &schema, &error_string); +  	if (ret == LDB_ERR_NO_SUCH_OBJECT) {  		ldb_reset_err_string(module->ldb);  		ldb_debug(module->ldb, LDB_DEBUG_WARNING,  			  "schema_fsmo_init: no schema head present: (skip schema loading)\n");  		talloc_free(mem_ctx);  		return ldb_next_init(module); -	} else if (ret != LDB_SUCCESS) { -		ldb_asprintf_errstring(module->ldb,  -				       "schema_fsmo_init: failed to search the schema head: %s", -				       ldb_errstring(module->ldb)); -		talloc_free(mem_ctx); -		return ret; -	} -	talloc_steal(mem_ctx, schema_res); -	if (schema_res->count == 0) { -		ldb_debug(module->ldb, LDB_DEBUG_WARNING, -			  "schema_fsmo_init: no schema head present: (skip schema loading)\n"); -		talloc_free(mem_ctx); -		return ldb_next_init(module); -	} else if (schema_res->count > 1) { -		ldb_debug_set(module->ldb, LDB_DEBUG_FATAL, -			      "schema_fsmo_init: [%u] schema heads found on a base search", -			      schema_res->count); -		talloc_free(mem_ctx); -		return LDB_ERR_CONSTRAINT_VIOLATION; -	} - -	/* -	 * load the attribute definitions -	 */ -	ret = ldb_search(module->ldb, schema_dn, -			 LDB_SCOPE_ONELEVEL, -			 "(objectClass=attributeSchema)", NULL, -			 &a_res); -	if (ret != LDB_SUCCESS) { -		ldb_asprintf_errstring(module->ldb,  -				       "schema_fsmo_init: failed to search attributeSchema objects: %s", -				       ldb_errstring(module->ldb)); -		talloc_free(mem_ctx); -		return ret; -	} -	talloc_steal(mem_ctx, a_res); - -	/* -	 * load the objectClass definitions -	 */ -	ret = ldb_search(module->ldb, schema_dn, -			 LDB_SCOPE_ONELEVEL, -			 "(objectClass=classSchema)", NULL, -			 &c_res); -	if (ret != LDB_SUCCESS) { -		ldb_asprintf_errstring(module->ldb,  -				       "schema_fsmo_init: failed to search classSchema objects: %s", -				       ldb_errstring(module->ldb)); -		talloc_free(mem_ctx); -		return ret;  	} -	talloc_steal(mem_ctx, c_res); -	ret = dsdb_schema_from_ldb_results(mem_ctx, module->ldb, -					   lp_iconv_convenience(ldb_get_opaque(module->ldb, "loadparm")), -					   schema_res, a_res, c_res, &schema, &error_string);  	if (ret != LDB_SUCCESS) {  		ldb_asprintf_errstring(module->ldb,   				       "schema_fsmo_init: dsdb_schema load failed: %s",  				       error_string);  		talloc_free(mem_ctx); -		return ret;  	} -	 +  	/* dsdb_set_schema() steal schema into the ldb_context */  	ret = dsdb_set_schema(module->ldb, schema);  	if (ret != LDB_SUCCESS) { diff --git a/source4/dsdb/samdb/ldb_modules/simple_ldap_map.c b/source4/dsdb/samdb/ldb_modules/simple_ldap_map.c index 101ca67dee..e5541ea255 100644 --- a/source4/dsdb/samdb/ldb_modules/simple_ldap_map.c +++ b/source4/dsdb/samdb/ldb_modules/simple_ldap_map.c @@ -676,7 +676,7 @@ static int entryuuid_init(struct ldb_module *module)  	struct map_private *map_private;  	struct entryuuid_private *entryuuid_private; -	ret = ldb_map_init(module, entryuuid_attributes, entryuuid_objectclasses, entryuuid_wildcard_attributes, "extensibleObject", NULL); +	ret = ldb_map_init(module, entryuuid_attributes, entryuuid_objectclasses, entryuuid_wildcard_attributes, "samba4Top", NULL);          if (ret != LDB_SUCCESS)                  return ret; @@ -697,7 +697,7 @@ static int nsuniqueid_init(struct ldb_module *module)  	struct map_private *map_private;  	struct entryuuid_private *entryuuid_private; -	ret = ldb_map_init(module, nsuniqueid_attributes, NULL, nsuniqueid_wildcard_attributes, "extensibleObject", NULL); +	ret = ldb_map_init(module, nsuniqueid_attributes, NULL, nsuniqueid_wildcard_attributes, "samba4Top", NULL);          if (ret != LDB_SUCCESS)                  return ret; diff --git a/source4/dsdb/schema/schema.h b/source4/dsdb/schema/schema.h index 6fce354f7c..66cc867a19 100644 --- a/source4/dsdb/schema/schema.h +++ b/source4/dsdb/schema/schema.h @@ -158,6 +158,15 @@ struct dsdb_schema {  	struct smb_iconv_convenience *iconv_convenience;  }; +enum dsdb_attr_list_query { +	DSDB_SCHEMA_ALL_MAY, +	DSDB_SCHEMA_ALL_MUST, +	DSDB_SCHEMA_SYS_MAY, +	DSDB_SCHEMA_SYS_MUST, +	DSDB_SCHEMA_MAY, +	DSDB_SCHEMA_MUST +}; +  #include "dsdb/schema/proto.h"  #endif /* _DSDB_SCHEMA_H */ diff --git a/source4/dsdb/schema/schema_init.c b/source4/dsdb/schema/schema_init.c index 826f91b5f0..3a6a8f5553 100644 --- a/source4/dsdb/schema/schema_init.c +++ b/source4/dsdb/schema/schema_init.c @@ -2,8 +2,8 @@     Unix SMB/CIFS mplementation.     DSDB schema header -   Copyright (C) Stefan Metzmacher <metze@samba.org> 2006 -   Copyright (C) Andrew Bartlett <abartlet@samba.org> 2007 +   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 @@ -624,7 +624,7 @@ int dsdb_schema_from_ldb_results(TALLOC_CTX *mem_ctx, struct ldb_context *ldb,  		status = dsdb_attribute_from_ldb(schema, attrs_res->msgs[i], sa, sa);  		if (!W_ERROR_IS_OK(status)) {  			*error_string = talloc_asprintf(mem_ctx,  -				      "schema_fsmo_init: failed to load attriute definition: %s:%s", +				      "schema_fsmo_init: failed to load attribute definition: %s:%s",  				      ldb_dn_get_linearized(attrs_res->msgs[i]->dn),  				      win_errstr(status));  			talloc_free(mem_ctx); @@ -670,6 +670,191 @@ int dsdb_schema_from_ldb_results(TALLOC_CTX *mem_ctx, struct ldb_context *ldb,  	return LDB_SUCCESS;  } +/* This recursive load of the objectClasses presumes that they + * everything is in a strict subClassOf hirarchy.   + * + * We load this in order so we produce certain outputs (such as the + * exported schema for openldap, and sorted objectClass attribute) 'in + * order' */ + +static int fetch_oc_recursive(struct ldb_context *ldb, struct ldb_dn *schemadn,  +			      TALLOC_CTX *mem_ctx,  +			      struct ldb_result *search_from, +			      struct ldb_result *res_list) +{ +	int i; +	int ret = 0; +	for (i=0; i < search_from->count; i++) { +		struct ldb_result *res; +		const char *name = ldb_msg_find_attr_as_string(search_from->msgs[i],  +							       "lDAPDisplayname", NULL); + +		ret = ldb_search_exp_fmt(ldb, mem_ctx, &res, +					schemadn, LDB_SCOPE_SUBTREE, NULL, +					"(&(&(objectClass=classSchema)(subClassOf=%s))(!(lDAPDisplayName=%s)))", +					name, name); +		if (ret != LDB_SUCCESS) { +			printf("Search failed: %s\n", ldb_errstring(ldb)); +			return ret; +		} +		 +		res_list->msgs = talloc_realloc(res_list, res_list->msgs,  +						struct ldb_message *, res_list->count + 2); +		if (!res_list->msgs) { +			return LDB_ERR_OPERATIONS_ERROR; +		} +		res_list->msgs[res_list->count] = talloc_move(res_list,  +							      &search_from->msgs[i]); +		res_list->count++; +		res_list->msgs[res_list->count] = NULL; + +		if (res->count > 0) { +			ret = fetch_oc_recursive(ldb, schemadn, mem_ctx, res, res_list);  +		} +		if (ret != LDB_SUCCESS) { +			return ret; +		} +	} +	return ret; +} + +static int fetch_objectclass_schema(struct ldb_context *ldb, struct ldb_dn *schemadn,  +				    TALLOC_CTX *mem_ctx,  +				    struct ldb_result **objectclasses_res) +{ +	TALLOC_CTX *local_ctx = talloc_new(mem_ctx); +	struct ldb_result *top_res, *ret_res; +	int ret; +	if (!local_ctx) { +		return LDB_ERR_OPERATIONS_ERROR; +	} +	 +	/* Downlaod 'top' */ +	ret = ldb_search(ldb, schemadn, LDB_SCOPE_SUBTREE,  +			 "(&(objectClass=classSchema)(lDAPDisplayName=top))",  +			 NULL, &top_res); +	if (ret != LDB_SUCCESS) { +		printf("Search failed: %s\n", ldb_errstring(ldb)); +		return LDB_ERR_OPERATIONS_ERROR; +	} + +	talloc_steal(local_ctx, top_res); + +	if (top_res->count != 1) { +		return LDB_ERR_OPERATIONS_ERROR; +	} + +	ret_res = talloc_zero(local_ctx, struct ldb_result); +	if (!ret_res) { +		return LDB_ERR_OPERATIONS_ERROR; +	} + +	ret = fetch_oc_recursive(ldb, schemadn, local_ctx, top_res, ret_res);  + +	if (ret != LDB_SUCCESS) { +		printf("Search failed: %s\n", ldb_errstring(ldb)); +		return LDB_ERR_OPERATIONS_ERROR; +	} + +	*objectclasses_res = talloc_move(mem_ctx, &ret_res); +	return ret; +} + +int dsdb_schema_from_schema_dn(TALLOC_CTX *mem_ctx, struct ldb_context *ldb, +			       struct smb_iconv_convenience *iconv_convenience,  +			       struct ldb_dn *schema_dn, +			       struct dsdb_schema **schema, +			       char **error_string_out)  +{ +	TALLOC_CTX *tmp_ctx; +	char *error_string; +	int ret; + +	struct ldb_result *schema_res; +	struct ldb_result *a_res; +	struct ldb_result *c_res; +	static const char *schema_attrs[] = { +		"prefixMap", +		"schemaInfo", +		"fSMORoleOwner", +		NULL +	}; + +	tmp_ctx = talloc_new(mem_ctx); +	if (!tmp_ctx) { +		dsdb_oom(error_string_out, mem_ctx); +		return LDB_ERR_OPERATIONS_ERROR; +	} + +	/* +	 * setup the prefix mappings and schema info +	 */ +	ret = ldb_search(ldb, schema_dn, +			 LDB_SCOPE_BASE, +			 NULL, schema_attrs, +			 &schema_res); +	if (ret == LDB_ERR_NO_SUCH_OBJECT) { +		talloc_free(tmp_ctx); +		return ret; +	} else if (ret != LDB_SUCCESS) { +		*error_string_out = talloc_asprintf(mem_ctx,  +				       "dsdb_schema: failed to search the schema head: %s", +				       ldb_errstring(ldb)); +		talloc_free(tmp_ctx); +		return ret; +	} +	talloc_steal(tmp_ctx, schema_res); +	if (schema_res->count != 1) { +		*error_string_out = talloc_asprintf(mem_ctx,  +			      "dsdb_schema: [%u] schema heads found on a base search", +			      schema_res->count); +		talloc_free(tmp_ctx); +		return LDB_ERR_CONSTRAINT_VIOLATION; +	} + +	/* +	 * load the attribute definitions +	 */ +	ret = ldb_search(ldb, schema_dn, +			 LDB_SCOPE_ONELEVEL, +			 "(objectClass=attributeSchema)", NULL, +			 &a_res); +	if (ret != LDB_SUCCESS) { +		*error_string_out = talloc_asprintf(mem_ctx,  +				       "dsdb_schema: failed to search attributeSchema objects: %s", +				       ldb_errstring(ldb)); +		talloc_free(tmp_ctx); +		return ret; +	} +	talloc_steal(tmp_ctx, a_res); + +	/* +	 * load the objectClass definitions +	 */ +	ret = fetch_objectclass_schema(ldb, schema_dn, tmp_ctx, &c_res); +	if (ret != LDB_SUCCESS) { +		*error_string_out = talloc_asprintf(mem_ctx,  +				       "Failed to fetch objectClass schema elements: %s\n", ldb_errstring(ldb)); +		talloc_free(tmp_ctx); +		return ret; +	} + +	ret = dsdb_schema_from_ldb_results(tmp_ctx, ldb, +					   lp_iconv_convenience(ldb_get_opaque(ldb, "loadparm")), +					   schema_res, a_res, c_res, schema, &error_string); +	if (ret != LDB_SUCCESS) { +		*error_string_out = talloc_asprintf(mem_ctx,  +						    "dsdb_schema load failed: %s", +						    error_string); +		talloc_free(tmp_ctx); +		return ret; +	} +	talloc_steal(mem_ctx, *schema); +	talloc_free(tmp_ctx); + +	return LDB_SUCCESS; +}	 +  static const struct {  	const char *name; @@ -1167,6 +1352,13 @@ const char *dsdb_lDAPDisplayName_by_id(const struct dsdb_schema *schema,  	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; @@ -1187,6 +1379,114 @@ WERROR dsdb_linked_attribute_lDAPDisplayName_list(const struct dsdb_schema *sche  	return WERR_OK;  } +static 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; +} + +char **dsdb_full_attribute_list_internal(TALLOC_CTX *mem_ctx, 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 **recursive_list; + +	for (i=0; class_list && class_list[i]; i++) { +		class = dsdb_class_by_lDAPDisplayName(schema, class_list[i]); +		 +		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; +		} + +		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, 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  diff --git a/source4/setup/schema_samba4.ldif b/source4/setup/schema_samba4.ldif index 7146091c8e..8128c43ac4 100644 --- a/source4/setup/schema_samba4.ldif +++ b/source4/setup/schema_samba4.ldif @@ -125,21 +125,23 @@ attributeID: 1.3.6.1.4.1.7165.4.1.7  attributeSyntax: 2.5.5.4  oMSyntax: 20 - -dn: CN=unixName,${SCHEMADN} -cn: unixName -name: unixName -objectClass: top -objectClass: attributeSchema -lDAPDisplayName: unixName -isSingleValued: TRUE -systemFlags: 16 -systemOnly: FALSE -schemaIDGUID: bf9679f2-0de6-11d0-a285-00aa003049e2 -adminDisplayName: Unix-Name -attributeID: 1.3.6.1.4.1.7165.4.1.9 -attributeSyntax: 2.5.5.4 -oMSyntax: 20 +# +# Not used anymore +# +#dn: CN=unixName,${SCHEMADN} +#cn: unixName +#name: unixName +#objectClass: top +#objectClass: attributeSchema +#lDAPDisplayName: unixName +#isSingleValued: TRUE +#systemFlags: 16 +#systemOnly: FALSE +#schemaIDGUID: bf9679f2-0de6-11d0-a285-00aa003049e2 +#adminDisplayName: Unix-Name +#attributeID: 1.3.6.1.4.1.7165.4.1.9 +#attributeSyntax: 2.5.5.4 +#oMSyntax: 20  #  # Not used anymore @@ -175,7 +177,6 @@ oMSyntax: 20  #Allocated: (ditContentRules) samba4DitContentRules: 1.3.6.1.4.1.7165.4.255.6  #Allocated: (attributeTypes) samba4AttributeTypes: 1.3.6.1.4.1.7165.4.255.7 -  #  # Fedora DS uses this attribute, and we need to set it via our module stack  # @@ -226,9 +227,132 @@ objectClassCategory: 1  lDAPDisplayName: samba4LocalDomain  schemaIDGUID: 07be1647-8310-4fba-91ae-34e55d5a8293  systemOnly: FALSE -systemAuxiliaryClass: samDomainBase +systemAuxiliaryClass: samDomain  defaultSecurityDescriptor: D:(A;;RPLCLORC;;;DA)(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;SY)(A;;RPLCLORC;;;AU)  systemFlags: 16  defaultHidingValue: TRUE  defaultObjectCategory: CN=Builtin-Domain,${SCHEMADN} + +dn: CN=Samba4Top,${SCHEMADN} +objectClass: top +objectClass: classSchema +subClassOf: top +governsID: 1.3.6.1.4.1.7165.4.2.1 +mayContain: msDS-ObjectReferenceBL +rDNAttID: cn +showInAdvancedViewOnly: TRUE +adminDisplayName: Samba4TopTop +adminDescription: Attributes used in top in Samba4 that OpenLDAP does not +objectClassCategory: 3 +lDAPDisplayName: samba4Top +schemaIDGUID: 073598d0-635b-4685-a929-da731b98d84e +systemOnly: TRUE +systemPossSuperiors: lostAndFound +systemMayContain: url +systemMayContain: wWWHomePage +systemMayContain: wellKnownObjects +systemMayContain: wbemPath +systemMayContain: uSNSource +systemMayContain: uSNLastObjRem +systemMayContain: USNIntersite +systemMayContain: uSNDSALastObjRemoved +systemMayContain: systemFlags +systemMayContain: subRefs +systemMayContain: siteObjectBL +systemMayContain: serverReferenceBL +systemMayContain: sDRightsEffective +systemMayContain: revision +systemMayContain: repsTo +systemMayContain: repsFrom +systemMayContain: directReports +systemMayContain: replUpToDateVector +systemMayContain: replPropertyMetaData +systemMayContain: name +systemMayContain: queryPolicyBL +systemMayContain: proxyAddresses +systemMayContain: proxiedObjectName +systemMayContain: possibleInferiors +systemMayContain: partialAttributeSet +systemMayContain: partialAttributeDeletionList +systemMayContain: otherWellKnownObjects +systemMayContain: objectVersion +systemMayContain: nonSecurityMemberBL +systemMayContain: netbootSCPBL +systemMayContain: ownerBL +systemMayContain: msDS-ReplValueMetaData +systemMayContain: msDS-ReplAttributeMetaData +systemMayContain: msDS-NonMembersBL +systemMayContain: msDS-NCReplOutboundNeighbors +systemMayContain: msDS-NCReplInboundNeighbors +systemMayContain: msDS-NCReplCursors +systemMayContain: msDS-TasksForAzRoleBL +systemMayContain: msDS-TasksForAzTaskBL +systemMayContain: msDS-OperationsForAzRoleBL +systemMayContain: msDS-OperationsForAzTaskBL +systemMayContain: msDS-MembersForAzRoleBL +systemMayContain: msDs-masteredBy +systemMayContain: mS-DS-ConsistencyGuid +systemMayContain: mS-DS-ConsistencyChildCount +systemMayContain: msDS-Approx-Immed-Subordinates +systemMayContain: msCOM-PartitionSetLink +systemMayContain: msCOM-UserLink +systemMayContain: masteredBy +systemMayContain: managedObjects +systemMayContain: lastKnownParent +systemMayContain: isPrivilegeHolder +systemMayContain: isDeleted +systemMayContain: isCriticalSystemObject +systemMayContain: showInAdvancedViewOnly +systemMayContain: fSMORoleOwner +systemMayContain: fRSMemberReferenceBL +systemMayContain: frsComputerReferenceBL +systemMayContain: fromEntry +systemMayContain: flags +systemMayContain: extensionName +systemMayContain: dSASignature +systemMayContain: dSCorePropagationData +systemMayContain: displayNamePrintable +systemMayContain: displayName +systemMayContain: description +systemMayContain: cn +systemMayContain: canonicalName +systemMayContain: bridgeheadServerListBL +systemMayContain: allowedChildClassesEffective +systemMayContain: allowedChildClasses +systemMayContain: allowedAttributesEffective +systemMayContain: allowedAttributes +systemMayContain: adminDisplayName +systemMayContain: adminDescription +systemMustContain: objectCategory +systemMustContain: nTSecurityDescriptor +systemMustContain: instanceType +systemAuxiliaryClass: samba4TopExtra +defaultSecurityDescriptor: D:(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;DA)(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;SY)(A;;RPLCLORC;;;AU) +systemFlags: 16 +defaultHidingValue: TRUE +objectCategory: CN=Class-Schema,${SCHEMADN} +defaultObjectCategory: CN=Samba4Top,${SCHEMADN} + + +dn: CN=Samba4TopExtra,${SCHEMADN} +objectClass: top +objectClass: classSchema +subClassOf: top +governsID: 1.3.6.1.4.1.7165.4.2.3 +rDNAttID: cn +showInAdvancedViewOnly: TRUE +adminDisplayName: Samba4TopExtra +adminDescription: Attributes used in top in Samba4 that OpenLDAP does not +objectClassCategory: 2 +lDAPDisplayName: samba4TopExtra +schemaIDGUID: 073598d0-635b-4685-a929-da731b98d84e +systemOnly: TRUE +mayContain: privilege +systemPossSuperiors: lostAndFound +defaultSecurityDescriptor: D:(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;DA)(A;;RPWPCRCCDCLCLORCWOWDSDDTSW;;;SY)(A;;RPLCLORC;;;AU) +systemFlags: 16 +defaultHidingValue: TRUE +objectCategory: CN=Class-Schema,${SCHEMADN} +defaultObjectCategory: CN=Samba4TopExtra,${SCHEMADN} + diff --git a/source4/setup/slapd.conf b/source4/setup/slapd.conf index cdf9ff79a9..15b9d3104e 100644 --- a/source4/setup/slapd.conf +++ b/source4/setup/slapd.conf @@ -71,8 +71,6 @@ index objectCategory eq  index member eq  index uidNumber eq  index gidNumber eq -index unixName eq -index privilege eq  index nCName eq  index lDAPDisplayName eq  index subClassOf eq diff --git a/source4/utils/ad2oLschema.c b/source4/utils/ad2oLschema.c index 879b1a7213..51b03b8e8f 100644 --- a/source4/utils/ad2oLschema.c +++ b/source4/utils/ad2oLschema.c @@ -67,114 +67,13 @@ static void usage(void)  	exit(1);  } -static int fetch_attrs_schema(struct ldb_context *ldb, struct ldb_dn *schemadn, -			      TALLOC_CTX *mem_ctx,  -			      struct ldb_result **attrs_res) -{ -	int ret; - -	/* Downlaod schema */ -	ret = ldb_search(ldb, schemadn, LDB_SCOPE_SUBTREE,  -			 "objectClass=attributeSchema",  -			 NULL, attrs_res); -	if (ret != LDB_SUCCESS) { -		printf("Search failed: %s\n", ldb_errstring(ldb)); -		return LDB_ERR_OPERATIONS_ERROR; -	} -	 -	return ret; -} - -static int fetch_oc_recursive(struct ldb_context *ldb, struct ldb_dn *schemadn,  -			      TALLOC_CTX *mem_ctx,  -			      struct ldb_result *search_from, -			      struct ldb_result *res_list) -{ -	int i; -	int ret = 0; -	for (i=0; i < search_from->count; i++) { -		struct ldb_result *res; -		const char *name = ldb_msg_find_attr_as_string(search_from->msgs[i],  -							       "lDAPDisplayname", NULL); - -		ret = ldb_search_exp_fmt(ldb, mem_ctx, &res, -					schemadn, LDB_SCOPE_SUBTREE, NULL, -					"(&(&(objectClass=classSchema)(subClassOf=%s))(!(lDAPDisplayName=%s)))", -					name, name); -		if (ret != LDB_SUCCESS) { -			printf("Search failed: %s\n", ldb_errstring(ldb)); -			return ret; -		} -		 -		res_list->msgs = talloc_realloc(res_list, res_list->msgs,  -						struct ldb_message *, res_list->count + 2); -		if (!res_list->msgs) { -			return LDB_ERR_OPERATIONS_ERROR; -		} -		res_list->msgs[res_list->count] = talloc_move(res_list,  -							      &search_from->msgs[i]); -		res_list->count++; -		res_list->msgs[res_list->count] = NULL; - -		if (res->count > 0) { -			ret = fetch_oc_recursive(ldb, schemadn, mem_ctx, res, res_list);  -		} -		if (ret != LDB_SUCCESS) { -			return ret; -		} -	} -	return ret; -} - -static int fetch_objectclass_schema(struct ldb_context *ldb, struct ldb_dn *schemadn,  -				    TALLOC_CTX *mem_ctx,  -				    struct ldb_result **objectclasses_res) -{ -	TALLOC_CTX *local_ctx = talloc_new(mem_ctx); -	struct ldb_result *top_res, *ret_res; -	int ret; -	if (!local_ctx) { -		return LDB_ERR_OPERATIONS_ERROR; -	} -	 -	/* Downlaod 'top' */ -	ret = ldb_search(ldb, schemadn, LDB_SCOPE_SUBTREE,  -			 "(&(objectClass=classSchema)(lDAPDisplayName=top))",  -			 NULL, &top_res); -	if (ret != LDB_SUCCESS) { -		printf("Search failed: %s\n", ldb_errstring(ldb)); -		return LDB_ERR_OPERATIONS_ERROR; -	} - -	talloc_steal(local_ctx, top_res); - -	if (top_res->count != 1) { -		return LDB_ERR_OPERATIONS_ERROR; -	} - -	ret_res = talloc_zero(local_ctx, struct ldb_result); -	if (!ret_res) { -		return LDB_ERR_OPERATIONS_ERROR; -	} - -	ret = fetch_oc_recursive(ldb, schemadn, local_ctx, top_res, ret_res);  - -	if (ret != LDB_SUCCESS) { -		printf("Search failed: %s\n", ldb_errstring(ldb)); -		return LDB_ERR_OPERATIONS_ERROR; -	} - -	*objectclasses_res = talloc_move(mem_ctx, &ret_res); -	return ret; -} - -static struct ldb_dn *find_schema_dn(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, -				     struct ldb_result **schema_res)  +static struct ldb_dn *find_schema_dn(struct ldb_context *ldb, TALLOC_CTX *mem_ctx)   {  	const char *rootdse_attrs[] = {"schemaNamingContext", NULL};  	struct ldb_dn *schemadn;  	struct ldb_dn *basedn = ldb_dn_new(mem_ctx, ldb, NULL);  	struct ldb_result *rootdse_res; +	struct ldb_result *schema_res;  	int ldb_ret;  	if (!basedn) { @@ -186,126 +85,42 @@ static struct ldb_dn *find_schema_dn(struct ldb_context *ldb, TALLOC_CTX *mem_ct  	if (ldb_ret != LDB_SUCCESS) {  		ldb_ret = ldb_search(ldb, basedn, LDB_SCOPE_SUBTREE,   				 "(&(objectClass=dMD)(cn=Schema))",  -				 NULL, schema_res); +				 NULL, &schema_res);  		if (ldb_ret) {  			printf("cn=Schema Search failed: %s\n", ldb_errstring(ldb));  			return NULL;  		} -		talloc_steal(mem_ctx, *schema_res); +		talloc_steal(mem_ctx, schema_res); -		if ((*schema_res)->count != 1) { +		if (schema_res->count != 1) { +			talloc_free(schema_res);  			printf("Failed to find rootDSE");  			return NULL;  		} -		schemadn = talloc_steal(mem_ctx, (*schema_res)->msgs[0]->dn); +		schemadn = talloc_steal(mem_ctx, schema_res->msgs[0]->dn); +		talloc_free(schema_res);  		return schemadn; -		  	} -	talloc_steal(mem_ctx, rootdse_res); -  	if (rootdse_res->count != 1) {  		printf("Failed to find rootDSE"); +		talloc_free(rootdse_res);  		return NULL;  	}  	/* Locate schema */  	schemadn = ldb_msg_find_attr_as_dn(ldb, mem_ctx, rootdse_res->msgs[0], "schemaNamingContext"); -	if (!schemadn) { -		return NULL; -	} +	talloc_free(rootdse_res); -	ldb_ret = ldb_search(ldb, schemadn, LDB_SCOPE_BASE,  -			     "(&(objectClass=dMD)(cn=Schema))",  -			     NULL, schema_res); -	if (ldb_ret) { -		printf("cn=Schema Search failed: %s\n", ldb_errstring(ldb)); +	if (!schemadn) {  		return NULL;  	} -	 -	talloc_steal(mem_ctx, *schema_res); -	if ((*schema_res)->count != 1) { -		printf("Failed to find rootDSE"); -		return NULL; -	} -	talloc_free(rootdse_res);  	return schemadn;  } -static bool merge_attr_list(TALLOC_CTX *mem_ctx,  -			    struct ldb_message_element *attrs, struct ldb_message_element *new_attrs)  -{ -	struct ldb_val *values; -	if (!new_attrs) { -		return true; -	} - -	values = talloc_realloc(mem_ctx,  -				attrs->values, struct ldb_val, attrs->num_values + new_attrs->num_values); -	 -	attrs->values = values; - -	memcpy(&attrs->values[attrs->num_values], new_attrs->values, sizeof(*new_attrs->values) * new_attrs->num_values); -	attrs->num_values = attrs->num_values + new_attrs->num_values; - -	/* Add sort and unique implementation here */ - -	return true; -} - -static bool find_aux_classes(TALLOC_CTX *mem_ctx, struct ldb_context *ldb, struct ldb_dn *schema_dn, -			     struct ldb_message_element *aux_class, struct ldb_message_element *must,  -			     struct ldb_message_element *sys_must, struct ldb_message_element *may,  -			     struct ldb_message_element *sys_may)  -{ -	int i, ret; -	struct ldb_message *msg; -	struct ldb_result *res; - -	for (i=0; aux_class && i < aux_class->num_values; i++) { -		ret = ldb_search_exp_fmt(ldb, mem_ctx, &res, -					 schema_dn, LDB_SCOPE_SUBTREE, NULL, -					 "(&(objectClass=classSchema)(lDAPDisplayName=%s))", -					 aux_class->values[i].data); -		if (ret != LDB_SUCCESS) { -			return false; -		} - -		msg = res->msgs[0]; - -		if (!merge_attr_list(mem_ctx, must, ldb_msg_find_element(msg, "mustContain"))) { -			return false; -		} -		if (!merge_attr_list(mem_ctx, sys_must,  ldb_msg_find_element(msg, "systemMustContain"))) { -			return false; -		} -		if (!merge_attr_list(mem_ctx, may, ldb_msg_find_element(msg, "mayContain"))) { -			return false; -		} -		if (!merge_attr_list(mem_ctx, sys_may, ldb_msg_find_element(msg, "systemMayContain"))) { -			return false; -		} -		 -		 -		if (res->count == 0) { -			return false; -		} - -		if (!find_aux_classes(mem_ctx, ldb, schema_dn, -				      ldb_msg_find_element(msg, "auxiliaryClass"), must, sys_must, may, sys_may)) { -			return false; -		} -		if (!find_aux_classes(mem_ctx, ldb, schema_dn, -				      ldb_msg_find_element(msg, "systemAuxiliaryClass"), must, sys_must, may, sys_may)) { -			return false; -		} -	} -	return true; -} -  #define IF_NULL_FAIL_RET(x) do {     \  		if (!x) {		\ @@ -332,13 +147,14 @@ static struct schema_conv process_convert(struct ldb_context *ldb, enum convert_  		char *new_attr;  	} *attr_map = NULL;  	int num_attr_maps = 0;	 -	struct ldb_result *schema_res, *attrs_res, *objectclasses_res; +	struct dsdb_class *objectclass; +	struct dsdb_attribute *attribute;  	struct ldb_dn *schemadn;  	struct schema_conv ret;  	struct dsdb_schema *schema;  	char *error_string; -	int ldb_ret, i; +	int ldb_ret;  	ret.count = 0;  	ret.skipped = 0; @@ -389,31 +205,16 @@ static struct schema_conv process_convert(struct ldb_context *ldb, enum convert_  		}  	} -	schemadn = find_schema_dn(ldb, mem_ctx, &schema_res); +	schemadn = find_schema_dn(ldb, mem_ctx);  	if (!schemadn) {  		printf("Failed to find schema DN: %s\n", ldb_errstring(ldb));  		ret.failures = 1;  		return ret;  	} -	ldb_ret = fetch_attrs_schema(ldb, schemadn, mem_ctx, &attrs_res); -	if (ldb_ret != LDB_SUCCESS) { -		printf("Failed to fetch attribute schema: %s\n", ldb_errstring(ldb)); -		ret.failures = 1; -		return ret; -	} - - -	ldb_ret = fetch_objectclass_schema(ldb, schemadn, mem_ctx, &objectclasses_res); -	if (ldb_ret != LDB_SUCCESS) { -		printf("Failed to fetch objectClass schema elements: %s\n", ldb_errstring(ldb)); -		ret.failures = 1; -		return ret; -	} -	 -	ldb_ret = dsdb_schema_from_ldb_results(mem_ctx, ldb, -					       lp_iconv_convenience(cmdline_lp_ctx), -					       schema_res, attrs_res, objectclasses_res, &schema, &error_string); +	ldb_ret = dsdb_schema_from_schema_dn(mem_ctx, ldb, +					     lp_iconv_convenience(cmdline_lp_ctx), +					     schemadn, &schema, &error_string);  	if (ldb_ret != LDB_SUCCESS) {  		printf("Failed to load schema: %s\n", error_string);  		ret.failures = 1; @@ -428,24 +229,17 @@ static struct schema_conv process_convert(struct ldb_context *ldb, enum convert_  		break;  	} -	for (i=0; i < attrs_res->count; i++) { -		struct ldb_message *msg = attrs_res->msgs[i]; +	for (attribute=schema->attributes; attribute; attribute = attribute->next) { +		const char *name = attribute->lDAPDisplayName; +		const char *description = attribute->adminDescription; +		const char *oid = attribute->attributeID_oid; +		const char *syntax = attribute->attributeSyntax_oid; +		bool single_value = attribute->isSingleValued; -		const char *name = ldb_msg_find_attr_as_string(msg, "lDAPDisplayName", NULL); -		const char *description = ldb_msg_find_attr_as_string(msg, "description", NULL); -		const char *oid = ldb_msg_find_attr_as_string(msg, "attributeID", NULL); -		const char *syntax = ldb_msg_find_attr_as_string(msg, "attributeSyntax", NULL); -		bool single_value = ldb_msg_find_attr_as_bool(msg, "isSingleValued", false);  		const struct syntax_map *map = find_syntax_map_by_ad_oid(syntax);  		char *schema_entry = NULL;  		int j; -		if (!name) { -			printf("Failed to find lDAPDisplayName for schema DN: %s\n", ldb_dn_get_linearized(msg->dn)); -			ret.failures++; -			continue; -		} -  		/* We have been asked to skip some attributes/objectClasses */  		if (attrs_skip && str_list_check_ci(attrs_skip, name)) {  			ret.skipped++; @@ -487,9 +281,11 @@ static struct schema_conv process_convert(struct ldb_context *ldb, enum convert_  		IF_NULL_FAIL_RET(schema_entry);  		if (description) { +#if 0 /* If you want to re-enable this, you must first figure out a sane escaping of ' in the description */  			schema_entry = talloc_asprintf_append(schema_entry,  -							      "  DESC %s\n", description); +							      "  DESC '%s'\n", description);  			IF_NULL_FAIL_RET(schema_entry); +#endif  		}  		if (map) { @@ -539,59 +335,31 @@ static struct schema_conv process_convert(struct ldb_context *ldb, enum convert_  		ret.count++;  	} -	for (i=0; i < objectclasses_res->count; i++) { -		struct ldb_message *msg = objectclasses_res->msgs[i]; -		const char *name = ldb_msg_find_attr_as_string(msg, "lDAPDisplayName", NULL); -		const char *description = ldb_msg_find_attr_as_string(msg, "description", NULL); -		const char *oid = ldb_msg_find_attr_as_string(msg, "governsID", NULL); -		const char *subClassOf = ldb_msg_find_attr_as_string(msg, "subClassOf", NULL); -		int objectClassCategory = ldb_msg_find_attr_as_int(msg, "objectClassCategory", 0); -		struct ldb_message_element *must = ldb_msg_find_element(msg, "mustContain"); -		struct ldb_message_element *sys_must = ldb_msg_find_element(msg, "systemMustContain"); -		struct ldb_message_element *may = ldb_msg_find_element(msg, "mayContain"); -		struct ldb_message_element *sys_may = ldb_msg_find_element(msg, "systemMayContain"); -		struct ldb_message_element *aux_class = ldb_msg_find_element(msg, "auxiliaryClass"); -		struct ldb_message_element *sys_aux_class = ldb_msg_find_element(msg, "systemAuxiliaryClass"); +	/* This is already sorted to have 'top' and similar classes first */ +	for (objectclass=schema->classes; objectclass; objectclass = objectclass->next) { +		const char *name = objectclass->lDAPDisplayName; +		const char *description = objectclass->adminDescription; +		const char *oid = objectclass->governsID_oid; +		const char *subClassOf = objectclass->subClassOf; +		int objectClassCategory = objectclass->objectClassCategory; +		char **must; +		char **may;  		char *schema_entry = NULL; +		const char *objectclass_name_as_list[] = { +			objectclass->lDAPDisplayName, +			NULL +		};  		int j; - -		if (!name) { -			printf("Failed to find lDAPDisplayName for schema DN: %s\n", ldb_dn_get_linearized(msg->dn)); -			ret.failures++; -			continue; -		} - +		  		/* We have been asked to skip some attributes/objectClasses */  		if (attrs_skip && str_list_check_ci(attrs_skip, name)) {  			ret.skipped++;  			continue;  		} -		if (must == NULL) { -			must = talloc_zero(mem_ctx, struct ldb_message_element); -		} - -		if (may == NULL) { -			may = talloc_zero(mem_ctx, struct ldb_message_element); -		} - -		if (sys_must == NULL) { -			sys_must = talloc_zero(mem_ctx, struct ldb_message_element); -		} - -		if (sys_may == NULL) { -			sys_may = talloc_zero(mem_ctx, struct ldb_message_element); -		} +		may = dsdb_full_attribute_list(mem_ctx, schema, objectclass_name_as_list, DSDB_SCHEMA_ALL_MAY); -		if (!find_aux_classes(mem_ctx, ldb, schemadn, aux_class, must, sys_must, may, sys_may)) { -			ret.failures++; -			continue; -		} - -		if (!find_aux_classes(mem_ctx, ldb, schemadn, sys_aux_class, must, sys_must, may, sys_may)) { -			ret.failures++; -			continue; -		} +		must = dsdb_full_attribute_list(mem_ctx, schema, objectclass_name_as_list, DSDB_SCHEMA_ALL_MUST);  		/* We might have been asked to remap this oid, due to a conflict */  		for (j=0; oid_map && oid_map[j].old_oid; j++) { @@ -635,7 +403,7 @@ static struct schema_conv process_convert(struct ldb_context *ldb, enum convert_  		if (description) {  			schema_entry = talloc_asprintf_append(schema_entry,  -							      "  DESC %s\n", description); +							      "  DESC '%s'\n", description);  			IF_NULL_FAIL_RET(schema_entry);  		} @@ -666,9 +434,9 @@ static struct schema_conv process_convert(struct ldb_context *ldb, enum convert_  #define APPEND_ATTRS(attributes) \  		do {						\  			int k;						\ -			for (k=0; attributes && k < attributes->num_values; k++) { \ +			for (k=0; attributes && attributes[k]; k++) { \  				int attr_idx; \ -				const char *attr_name = (const char *)attributes->values[k].data;  \ +				const char *attr_name = attributes[k];  \  				/* We might have been asked to remap this name, due to a conflict */ \  				for (attr_idx=0; attr_name && attr_map && attr_map[attr_idx].old_attr; attr_idx++) { \  					if (strcasecmp(attr_name, attr_map[attr_idx].old_attr) == 0) { \ @@ -681,7 +449,7 @@ static struct schema_conv process_convert(struct ldb_context *ldb, enum convert_  								      " %s", \  								      attr_name); \  				IF_NULL_FAIL_RET(schema_entry);		\ -				if (k != (attributes->num_values - 1)) { \ +				if (attributes[k+1]) { \  					schema_entry = talloc_asprintf_append(schema_entry, \  									      " $"); \  					IF_NULL_FAIL_RET(schema_entry);	\ @@ -694,35 +462,25 @@ static struct schema_conv process_convert(struct ldb_context *ldb, enum convert_  			}						\  		} while (0) -		if ((must && must->values) || (sys_must && sys_must->values)) { +		if (must) {  			schema_entry = talloc_asprintf_append(schema_entry,   							      "  MUST (");  			IF_NULL_FAIL_RET(schema_entry);  			APPEND_ATTRS(must); -			if (must && must->values && sys_must && sys_must->values) { -				schema_entry = talloc_asprintf_append(schema_entry, \ -								      " $"); \ -			} -			APPEND_ATTRS(sys_must); -			 +  			schema_entry = talloc_asprintf_append(schema_entry,   							      " )\n");  			IF_NULL_FAIL_RET(schema_entry);  		} -		if ((may && may->values) || (sys_may && sys_may->values)) { +		if (may) {  			schema_entry = talloc_asprintf_append(schema_entry,   							      "  MAY (");  			IF_NULL_FAIL_RET(schema_entry);  			APPEND_ATTRS(may); -			if (may && may->values && sys_may && sys_may->values) { -				schema_entry = talloc_asprintf_append(schema_entry, \ -								      " $"); \ -			} -			APPEND_ATTRS(sys_may); -			 +  			schema_entry = talloc_asprintf_append(schema_entry,   							      " )\n");  			IF_NULL_FAIL_RET(schema_entry);  | 
