diff options
author | Andrew Bartlett <abartlet@samba.org> | 2008-08-15 20:40:57 +1000 |
---|---|---|
committer | Andrew Bartlett <abartlet@samba.org> | 2008-08-15 20:40:57 +1000 |
commit | 16112762e70879b50f1dfc49452d6d278bd256cf (patch) | |
tree | 19e91c832a8069686a1c5ba92cc28d73cc3ba815 /source4/dsdb | |
parent | e387677f515ee7f2c185069f8c52a3ec783041e2 (diff) | |
download | samba-16112762e70879b50f1dfc49452d6d278bd256cf.tar.gz samba-16112762e70879b50f1dfc49452d6d278bd256cf.tar.bz2 samba-16112762e70879b50f1dfc49452d6d278bd256cf.zip |
Generate the subSchema in cn=Aggregate
This reads the schema from the in-memory structure, when the magic
attributes are requested. The code is a modified version of that used
in the ad2oLschema tool (now shared).
The schema_fsmo module handles the insertion of the generated result.
As such, this commit also removes these entries from the setup/schema.ldif
Metze's previous stub of this functionality is also removed.
Andrew Bartlett
(This used to be commit c7c32ec7b42bdf0f7b669644516438c71b364e60)
Diffstat (limited to 'source4/dsdb')
-rw-r--r-- | source4/dsdb/config.mk | 3 | ||||
-rw-r--r-- | source4/dsdb/samdb/ldb_modules/schema_fsmo.c | 206 | ||||
-rw-r--r-- | source4/dsdb/schema/schema.h | 14 | ||||
-rw-r--r-- | source4/dsdb/schema/schema_constructed.c | 186 | ||||
-rw-r--r-- | source4/dsdb/schema/schema_convert.c | 160 | ||||
-rw-r--r-- | source4/dsdb/schema/schema_convert.h | 10 | ||||
-rw-r--r-- | source4/dsdb/schema/schema_description.c | 316 | ||||
-rw-r--r-- | source4/dsdb/schema/schema_init.c | 97 |
8 files changed, 758 insertions, 234 deletions
diff --git a/source4/dsdb/config.mk b/source4/dsdb/config.mk index 7b700fda22..d430c3f957 100644 --- a/source4/dsdb/config.mk +++ b/source4/dsdb/config.mk @@ -35,7 +35,8 @@ PRIVATE_DEPENDENCIES = SAMDB_COMMON NDR_DRSUAPI NDR_DRSBLOBS SAMDB_SCHEMA_OBJ_FILES = $(addprefix $(dsdbsrcdir)/schema/, \ schema_init.o \ schema_syntax.o \ - schema_constructed.o) + schema_description.o \ + schema_convert.o) $(eval $(call proto_header_template,$(dsdbsrcdir)/schema/proto.h,$(SAMDB_SCHEMA_OBJ_FILES:.o=.c))) # PUBLIC_HEADERS += dsdb/schema/schema.h diff --git a/source4/dsdb/samdb/ldb_modules/schema_fsmo.c b/source4/dsdb/samdb/ldb_modules/schema_fsmo.c index 87ada855d3..706b7b18b7 100644 --- a/source4/dsdb/samdb/ldb_modules/schema_fsmo.c +++ b/source4/dsdb/samdb/ldb_modules/schema_fsmo.c @@ -32,6 +32,40 @@ #include "lib/util/dlinklist.h" #include "param/param.h" +static int generate_objectClasses(struct ldb_context *ldb, struct ldb_message *msg, + const struct dsdb_schema *schema); +static int generate_attributeTypes(struct ldb_context *ldb, struct ldb_message *msg, + const struct dsdb_schema *schema); +static int generate_dITContentRules(struct ldb_context *ldb, struct ldb_message *msg, + const struct dsdb_schema *schema); + +static const struct { + const char *attr; + int (*fn)(struct ldb_context *, struct ldb_message *, const struct dsdb_schema *); +} generated_attrs[] = { + { + .attr = "objectClasses", + .fn = generate_objectClasses + }, + { + .attr = "attributeTypes", + .fn = generate_attributeTypes + }, + { + .attr = "dITContentRules", + .fn = generate_dITContentRules + } +}; + +struct schema_fsmo_private_data { + struct ldb_dn *aggregate_dn; +}; + +struct schema_fsmo_search_data { + struct schema_fsmo_private_data *module_context; + struct ldb_request *orig_req; +}; + static int schema_fsmo_init(struct ldb_module *module) { TALLOC_CTX *mem_ctx; @@ -39,10 +73,7 @@ static int schema_fsmo_init(struct ldb_module *module) struct dsdb_schema *schema; char *error_string = NULL; int ret; - - if (dsdb_get_schema(module->ldb)) { - return ldb_next_init(module); - } + struct schema_fsmo_private_data *data; schema_dn = samdb_schema_dn(module->ldb); if (!schema_dn) { @@ -52,6 +83,25 @@ static int schema_fsmo_init(struct ldb_module *module) return ldb_next_init(module); } + data = talloc(module, struct schema_fsmo_private_data); + if (data == NULL) { + ldb_oom(module->ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + + /* Check to see if this is a result on the CN=Aggregate schema */ + data->aggregate_dn = ldb_dn_copy(data, schema_dn); + if (!ldb_dn_add_child_fmt(data->aggregate_dn, "CN=Aggregate")) { + ldb_oom(module->ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + + module->private_data = data; + + if (dsdb_get_schema(module->ldb)) { + return ldb_next_init(module); + } + mem_ctx = talloc_new(module); if (!mem_ctx) { ldb_oom(module->ldb); @@ -208,9 +258,155 @@ static int schema_fsmo_extended(struct ldb_module *module, struct ldb_request *r return LDB_SUCCESS; } +static int generate_objectClasses(struct ldb_context *ldb, struct ldb_message *msg, + const struct dsdb_schema *schema) +{ + const struct dsdb_class *class; + int ret; + + for (class = schema->classes; class; class = class->next) { + ret = ldb_msg_add_string(msg, "objectClasses", schema_class_to_description(msg, class)); + if (ret != LDB_SUCCESS) { + return ret; + } + } + return LDB_SUCCESS; +} +static int generate_attributeTypes(struct ldb_context *ldb, struct ldb_message *msg, + const struct dsdb_schema *schema) +{ + const struct dsdb_attribute *attribute; + int ret; + + for (attribute = schema->attributes; attribute; attribute = attribute->next) { + ret = ldb_msg_add_string(msg, "attributeTypes", schema_attribute_to_description(msg, attribute)); + if (ret != LDB_SUCCESS) { + return ret; + } + } + return LDB_SUCCESS; +} + +static int generate_dITContentRules(struct ldb_context *ldb, struct ldb_message *msg, + const struct dsdb_schema *schema) +{ + const struct dsdb_class *class; + int ret; + + for (class = schema->classes; class; class = class->next) { + if (class->auxiliaryClass || class->systemAuxiliaryClass) { + char *ditcontentrule = schema_class_to_dITContentRule(msg, class, schema); + if (!ditcontentrule) { + ldb_oom(ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + ret = ldb_msg_add_steal_string(msg, "dITContentRules", ditcontentrule); + if (ret != LDB_SUCCESS) { + return ret; + } + } + } + return 0; +} + + + +/* Add objectClasses, attributeTypes and dITContentRules from the + schema object (they are not stored in the database) + */ +static int schema_fsmo_search_callback(struct ldb_context *ldb, void *context, struct ldb_reply *ares) +{ + const struct dsdb_schema *schema = dsdb_get_schema(ldb); + struct schema_fsmo_search_data *search_data = talloc_get_type(context, struct schema_fsmo_search_data); + struct ldb_request *orig_req = search_data->orig_req; + TALLOC_CTX *mem_ctx; + int i, ret; + + /* Only entries are interesting, and we handle the case of the parent seperatly */ + if (ares->type != LDB_REPLY_ENTRY) { + return orig_req->callback(ldb, orig_req->context, ares); + } + + if (ldb_dn_compare(ares->message->dn, search_data->module_context->aggregate_dn) != 0) { + talloc_free(mem_ctx); + return orig_req->callback(ldb, orig_req->context, ares); + } + + mem_ctx = talloc_new(ares); + if (!mem_ctx) { + ldb_oom(ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + + for (i=0; i < ARRAY_SIZE(generated_attrs); i++) { + if (ldb_attr_in_list(orig_req->op.search.attrs, generated_attrs[i].attr)) { + ret = generated_attrs[i].fn(ldb, ares->message, schema); + if (ret != LDB_SUCCESS) { + return ret; + } + } + } + + talloc_free(mem_ctx); + return orig_req->callback(ldb, orig_req->context, ares); +} + +/* search */ +static int schema_fsmo_search(struct ldb_module *module, struct ldb_request *req) +{ + int i, ret; + struct schema_fsmo_search_data *search_context; + struct ldb_request *down_req; + struct dsdb_schema *schema = dsdb_get_schema(module->ldb); + + if (!schema || !module->private_data) { + /* If there is no schema, there is little we can do */ + return ldb_next_request(module, req); + } + for (i=0; i < ARRAY_SIZE(generated_attrs); i++) { + if (ldb_attr_in_list(req->op.search.attrs, generated_attrs[i].attr)) { + break; + } + } + if (i == ARRAY_SIZE(generated_attrs)) { + /* No request for a generated attr found, nothing to + * see here, move along... */ + return ldb_next_request(module, req); + } + + search_context = talloc(req, struct schema_fsmo_search_data); + if (!search_context) { + ldb_oom(module->ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + down_req = talloc(req, struct ldb_request); + if (!down_req) { + ldb_oom(module->ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + + *down_req = *req; + search_context->orig_req = req; + search_context->module_context = talloc_get_type(module->private_data, struct schema_fsmo_private_data); + down_req->context = search_context; + + down_req->callback = schema_fsmo_search_callback; + + ret = ldb_next_request(module, down_req); + + /* do not free down_req as the call results may be linked to it, + * it will be freed when the upper level request get freed */ + if (ret == LDB_SUCCESS) { + req->handle = down_req->handle; + } + return ret; +} + + _PUBLIC_ const struct ldb_module_ops ldb_schema_fsmo_module_ops = { .name = "schema_fsmo", .init_context = schema_fsmo_init, .add = schema_fsmo_add, - .extended = schema_fsmo_extended + .extended = schema_fsmo_extended, + .search = schema_fsmo_search }; diff --git a/source4/dsdb/schema/schema.h b/source4/dsdb/schema/schema.h index a4e455ae33..cd714e9c61 100644 --- a/source4/dsdb/schema/schema.h +++ b/source4/dsdb/schema/schema.h @@ -168,6 +168,20 @@ enum dsdb_attr_list_query { DSDB_SCHEMA_ALL }; +enum dsdb_schema_convert_target { + TARGET_OPENLDAP, + TARGET_FEDORA_DS, + TARGET_AD_SCHEMA_SUBENTRY +}; + +struct dsdb_syntax_map { + const char *Standard_OID; + const char *AD_OID; + const char *equality; + const char *substring; + const char *comment; +}; + #include "dsdb/schema/proto.h" #endif /* _DSDB_SCHEMA_H */ diff --git a/source4/dsdb/schema/schema_constructed.c b/source4/dsdb/schema/schema_constructed.c deleted file mode 100644 index 51343817b0..0000000000 --- a/source4/dsdb/schema/schema_constructed.c +++ /dev/null @@ -1,186 +0,0 @@ -/* - Unix SMB/CIFS mplementation. - DSDB schema constructed attributes - attributeTypes, objectClasses, dITContentRules... - - Copyright (C) Stefan Metzmacher 2006 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 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 "librpc/gen_ndr/ndr_drsuapi.h" -#include "lib/ldb/include/ldb.h" -#include "system/time.h" -#include "lib/charset/charset.h" -#include "librpc/ndr/libndr.h" - -static char *dsdb_subSchema_list_append(char *v, const char *list_name) -{ - bool first = true; - uint32_t i; - const char *attrs[] = { - "attr1", - "attr2", - "attr3", - NULL - }; - - v = talloc_asprintf_append(v, "%s ( ", list_name); - if (!v) return NULL; - - for (i=0; attrs[i]; i++) { - v = talloc_asprintf_append(v, "%s%s ", - (!first ? "$ " : ""), - attrs[i]); - if (!v) return NULL; - first = false; - } - - v = talloc_asprintf_append(v, ") "); - if (!v) return NULL; - - return v; -} - -WERROR dsdb_subSchema_attributeTypes(const struct dsdb_schema *schema, - TALLOC_CTX *mem_ctx) -{ - struct ldb_message_element *e; - struct dsdb_attribute *a; - - e = talloc_zero(mem_ctx, struct ldb_message_element); - W_ERROR_HAVE_NO_MEMORY(e); - - for (a = schema->attributes; a; a = a->next) { - char *v; - - v = talloc_asprintf(e, "( %s NAME '%s' SYNTAX '%s' ", - a->attributeID_oid, a->lDAPDisplayName, - a->syntax->ldap_oid); - W_ERROR_HAVE_NO_MEMORY(v); - - if (a->isSingleValued) { - v = talloc_asprintf_append(v, "SINGLE-VALUE "); - W_ERROR_HAVE_NO_MEMORY(v); - } - - if (a->systemOnly) { - v = talloc_asprintf_append(v, "NO-USER-MODIFICATION "); - W_ERROR_HAVE_NO_MEMORY(v); - } - - v = talloc_asprintf_append(v, ")"); - W_ERROR_HAVE_NO_MEMORY(v); - - DEBUG(0,("%s\n", v)); - } - - return WERR_FOOBAR; -} - -WERROR dsdb_subSchema_objectClasses(const struct dsdb_schema *schema, - TALLOC_CTX *mem_ctx) -{ - struct ldb_message_element *e; - struct dsdb_class *c; - - e = talloc_zero(mem_ctx, struct ldb_message_element); - W_ERROR_HAVE_NO_MEMORY(e); - - for (c = schema->classes; c; c = c->next) { - const char *class_type; - char *v; - - switch (c->objectClassCategory) { - case 0: - /* - * NOTE: this is an type 88 class - * e.g. 2.5.6.6 NAME 'person' - * but w2k3 gives STRUCTURAL here! - */ - class_type = "STRUCTURAL"; - break; - case 1: - class_type = "STRUCTURAL"; - break; - case 2: - class_type = "ABSTRACT"; - break; - case 3: - class_type = "AUXILIARY"; - break; - default: - class_type = "UNKNOWN"; - break; - } - - v = talloc_asprintf(e, "( %s NAME '%s' SUB %s %s ", - c->governsID_oid, c->lDAPDisplayName, - c->subClassOf, class_type); - W_ERROR_HAVE_NO_MEMORY(v); - - v = dsdb_subSchema_list_append(v, "MUST"); - W_ERROR_HAVE_NO_MEMORY(v); - - v = dsdb_subSchema_list_append(v, "MAY"); - W_ERROR_HAVE_NO_MEMORY(v); - - v = talloc_asprintf_append(v, ")"); - W_ERROR_HAVE_NO_MEMORY(v); - - DEBUG(0,("%s\n", v)); - } - - return WERR_FOOBAR; -} - -WERROR dsdb_subSchema_dITContentRules(const struct dsdb_schema *schema, - TALLOC_CTX *mem_ctx) -{ - struct ldb_message_element *e; - struct dsdb_class *c; - - e = talloc_zero(mem_ctx, struct ldb_message_element); - W_ERROR_HAVE_NO_MEMORY(e); - - for (c = schema->classes; c; c = c->next) { - char *v; - - /* - * TODO: filter out classes without auxiliary classes - */ - - v = talloc_asprintf(e, "( %s NAME '%s' ", - c->governsID_oid, c->lDAPDisplayName); - W_ERROR_HAVE_NO_MEMORY(v); - - v = dsdb_subSchema_list_append(v, "AUX"); - W_ERROR_HAVE_NO_MEMORY(v); - - v = dsdb_subSchema_list_append(v, "MUST"); - W_ERROR_HAVE_NO_MEMORY(v); - - v = dsdb_subSchema_list_append(v, "MAY"); - W_ERROR_HAVE_NO_MEMORY(v); - - v = talloc_asprintf_append(v, ")"); - W_ERROR_HAVE_NO_MEMORY(v); - - DEBUG(0,("%s\n", v)); - } - - return WERR_FOOBAR; -} diff --git a/source4/dsdb/schema/schema_convert.c b/source4/dsdb/schema/schema_convert.c new file mode 100644 index 0000000000..673e7a3bae --- /dev/null +++ b/source4/dsdb/schema/schema_convert.c @@ -0,0 +1,160 @@ +/* + ldb database library + + Copyright (C) Simo Sorce 2005 + + 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" + +/* Shared map for converting syntax between formats */ +static const struct dsdb_syntax_map syntax_map[] = { + { + .Standard_OID = "1.3.6.1.4.1.1466.115.121.1.12", + .AD_OID = "2.5.5.1", + .equality = "distinguishedNameMatch", + .comment = "Object(DS-DN) == a DN" + }, + { + .Standard_OID = "1.3.6.1.4.1.1466.115.121.1.38", + .AD_OID = "2.5.5.2", + .equality = "objectIdentifierMatch", + .comment = "OID String" + }, + { + .Standard_OID = "1.2.840.113556.1.4.905", + .AD_OID = "2.5.5.4", + .equality = "caseIgnoreMatch", + .substring = "caseIgnoreSubstringsMatch", + .comment = "Case Insensitive String" + }, + { + .Standard_OID = "1.3.6.1.4.1.1466.115.121.1.26", + .AD_OID = "2.5.5.5", + .equality = "caseExactIA5Match", + .comment = "Printable String" + }, + { + .Standard_OID = "1.3.6.1.4.1.1466.115.121.1.36", + .AD_OID = "2.5.5.6", + .equality = "numericStringMatch", + .substring = "numericStringSubstringsMatch", + .comment = "Numeric String" + }, + { + .Standard_OID = "1.2.840.113556.1.4.903", + .AD_OID = "2.5.5.7", + .equality = "distinguishedNameMatch", + .comment = "OctetString: Binary+DN" + }, + { + .Standard_OID = "1.3.6.1.4.1.1466.115.121.1.7", + .AD_OID = "2.5.5.8", + .equality = "booleanMatch", + .comment = "Boolean" + }, + { + .Standard_OID = "1.3.6.1.4.1.1466.115.121.1.27", + .AD_OID = "2.5.5.9", + .equality = "integerMatch", + .comment = "Integer" + }, + { + .Standard_OID = "1.3.6.1.4.1.1466.115.121.1.40", + .AD_OID = "2.5.5.10", + .equality = "octetStringMatch", + .comment = "Octet String" + }, + { + .Standard_OID = "1.3.6.1.4.1.1466.115.121.1.24", + .AD_OID = "2.5.5.11", + .equality = "generalizedTimeMatch", + .comment = "Generalized Time" + }, + { + .Standard_OID = "1.3.6.1.4.1.1466.115.121.1.53", + .AD_OID = "2.5.5.11", + .equality = "generalizedTimeMatch", + .comment = "UTC Time" + }, + { + .Standard_OID = "1.3.6.1.4.1.1466.115.121.1.15", + .AD_OID = "2.5.5.12", + .equality = "caseIgnoreMatch", + .substring = "caseIgnoreSubstringsMatch", + .comment = "Directory String" + }, + { + .Standard_OID = "1.3.6.1.4.1.1466.115.121.1.43", + .AD_OID = "2.5.5.13", + .comment = "Presentation Address" + }, + { + .Standard_OID = "Not Found Yet", + .AD_OID = "2.5.5.14", + .equality = "distinguishedNameMatch", + .comment = "OctetString: String+DN" + }, + { + .Standard_OID = "1.2.840.113556.1.4.907", + .AD_OID = "2.5.5.15", + .equality = "octetStringMatch", + .comment = "NT Security Descriptor" + }, + { + .Standard_OID = "1.2.840.113556.1.4.906", + .AD_OID = "2.5.5.16", + .equality = "integerMatch", + .comment = "Large Integer" + }, + { + .Standard_OID = "1.3.6.1.4.1.1466.115.121.1.40", + .AD_OID = "2.5.5.17", + .equality = "octetStringMatch", + .comment = "Octet String - Security Identifier (SID)" + }, + { + .Standard_OID = "1.3.6.1.4.1.1466.115.121.1.26", + .AD_OID = "2.5.5.5", + .equality = "caseExactIA5Match", + .comment = "IA5 String" + }, + { .Standard_OID = NULL + } +}; + + +const struct dsdb_syntax_map *find_syntax_map_by_ad_oid(const char *ad_oid) +{ + int i; + for (i=0; syntax_map[i].Standard_OID; i++) { + if (strcasecmp(ad_oid, syntax_map[i].AD_OID) == 0) { + return &syntax_map[i]; + } + } + return NULL; +} + +const struct dsdb_syntax_map *find_syntax_map_by_standard_oid(const char *standard_oid) +{ + int i; + for (i=0; syntax_map[i].Standard_OID; i++) { + if (strcasecmp(standard_oid, syntax_map[i].Standard_OID) == 0) { + return &syntax_map[i]; + } + } + return NULL; +} diff --git a/source4/dsdb/schema/schema_convert.h b/source4/dsdb/schema/schema_convert.h new file mode 100644 index 0000000000..de379343a6 --- /dev/null +++ b/source4/dsdb/schema/schema_convert.h @@ -0,0 +1,10 @@ +struct syntax_map { + const char *Standard_OID; + const char *AD_OID; + const char *equality; + const char *substring; + const char *comment; +}; + +const struct syntax_map *find_syntax_map_by_ad_oid(const char *ad_oid); +const struct syntax_map *find_syntax_map_by_standard_oid(const char *standard_oid); diff --git a/source4/dsdb/schema/schema_description.c b/source4/dsdb/schema/schema_description.c new file mode 100644 index 0000000000..2f3acd1336 --- /dev/null +++ b/source4/dsdb/schema/schema_description.c @@ -0,0 +1,316 @@ +/* + Unix SMB/CIFS mplementation. + Print schema info into string format + + Copyright (C) Andrew Bartlett 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" + +#define IF_NULL_FAIL_RET(x) do { \ + if (!x) { \ + return NULL; \ + } \ + } while (0) + + +char *schema_attribute_description(TALLOC_CTX *mem_ctx, + enum dsdb_schema_convert_target target, + const char *seperator, + const char *oid, + const char *name, + const char *description, + const char *equality, + const char *substring, + const char *syntax, + bool single_value, bool operational) +{ + char *schema_entry = talloc_asprintf(mem_ctx, + "(%s%s%s", seperator, oid, seperator); + + schema_entry = talloc_asprintf_append(schema_entry, + "NAME '%s'%s", name, seperator); + IF_NULL_FAIL_RET(schema_entry); + + if (description) { +#if 0 + /* Need a way to escape ' characters from the description */ + schema_entry = talloc_asprintf_append(schema_entry, + "DESC '%s'%s", description, seperator); + IF_NULL_FAIL_RET(schema_entry); +#endif + } + + if (equality) { + schema_entry = talloc_asprintf_append(schema_entry, + "EQUALITY %s%s", equality, seperator); + IF_NULL_FAIL_RET(schema_entry); + } + if (substring) { + schema_entry = talloc_asprintf_append(schema_entry, + "SUBSTR %s%s", substring, seperator); + IF_NULL_FAIL_RET(schema_entry); + } + + schema_entry = talloc_asprintf_append(schema_entry, + "SYNTAX %s%s", syntax, seperator); + IF_NULL_FAIL_RET(schema_entry); + + if (single_value) { + schema_entry = talloc_asprintf_append(schema_entry, + "SINGLE-VALUE%s", seperator); + IF_NULL_FAIL_RET(schema_entry); + } + + if (operational) { + schema_entry = talloc_asprintf_append(schema_entry, + "NO-USER-MODIFICATION%s", seperator); + IF_NULL_FAIL_RET(schema_entry); + } + + schema_entry = talloc_asprintf_append(schema_entry, + ")"); + return schema_entry; +} + +char *schema_attribute_to_description(TALLOC_CTX *mem_ctx, const struct dsdb_attribute *attribute) +{ + char *schema_description; + const struct dsdb_syntax_map *map = find_syntax_map_by_ad_oid(attribute->attributeSyntax_oid); + const char *syntax = map ? map->Standard_OID : attribute->attributeSyntax_oid; + TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); + if (!tmp_ctx) { + return NULL; + } + + + schema_description + = schema_attribute_description(mem_ctx, + TARGET_AD_SCHEMA_SUBENTRY, + " ", + attribute->attributeID_oid, + attribute->lDAPDisplayName, + NULL, NULL, NULL, talloc_asprintf(tmp_ctx, "'%s'", syntax), + attribute->isSingleValued, + attribute->systemOnly); + talloc_free(tmp_ctx); + return schema_description; +} + +#define APPEND_ATTRS(attributes) \ + do { \ + int k; \ + for (k=0; attributes && attributes[k]; k++) { \ + const char *attr_name = attributes[k]; \ + \ + schema_entry = talloc_asprintf_append(schema_entry, \ + "%s ", \ + attr_name); \ + IF_NULL_FAIL_RET(schema_entry); \ + if (attributes[k+1]) { \ + IF_NULL_FAIL_RET(schema_entry); \ + if (target == TARGET_OPENLDAP && ((k+1)%5 == 0)) { \ + schema_entry = talloc_asprintf_append(schema_entry, \ + "$%s ", seperator); \ + IF_NULL_FAIL_RET(schema_entry); \ + } else { \ + schema_entry = talloc_asprintf_append(schema_entry, \ + "$ "); \ + } \ + } \ + } \ + } while (0) + + +/* Print a schema class or dITContentRule as a string. + * + * To print a scheam class, specify objectClassCategory but not auxillary_classes + * To print a dITContentRule, specify auxillary_classes but set objectClassCategory == -1 + * + */ + +char *schema_class_description(TALLOC_CTX *mem_ctx, + enum dsdb_schema_convert_target target, + const char *seperator, + const char *oid, + const char *name, + const char **auxillary_classes, + const char *description, + const char *subClassOf, + int objectClassCategory, + char **must, + char **may) +{ + char *schema_entry = talloc_asprintf(mem_ctx, + "(%s%s%s", seperator, oid, seperator); + + IF_NULL_FAIL_RET(schema_entry); + + schema_entry = talloc_asprintf_append(schema_entry, + "NAME '%s'%s", name, seperator); + IF_NULL_FAIL_RET(schema_entry); + + if (description) { + schema_entry = talloc_asprintf_append(schema_entry, + "DESC '%s'%s", description, seperator); + IF_NULL_FAIL_RET(schema_entry); + } + + if (auxillary_classes) { + schema_entry = talloc_asprintf_append(schema_entry, + "AUX ( "); + IF_NULL_FAIL_RET(schema_entry); + + APPEND_ATTRS(auxillary_classes); + + schema_entry = talloc_asprintf_append(schema_entry, + ")%s", seperator); + IF_NULL_FAIL_RET(schema_entry); + } + + if (subClassOf) { + schema_entry = talloc_asprintf_append(schema_entry, + "SUP %s%s", subClassOf, seperator); + IF_NULL_FAIL_RET(schema_entry); + } + + switch (objectClassCategory) { + case -1: + break; + /* Dummy case for when used for printing ditContentRules */ + case 0: + /* + * NOTE: this is an type 88 class + * e.g. 2.5.6.6 NAME 'person' + * but w2k3 gives STRUCTURAL here! + */ + schema_entry = talloc_asprintf_append(schema_entry, + "STRUCTURAL%s", seperator); + IF_NULL_FAIL_RET(schema_entry); + break; + case 1: + schema_entry = talloc_asprintf_append(schema_entry, + "STRUCTURAL%s", seperator); + IF_NULL_FAIL_RET(schema_entry); + break; + case 2: + schema_entry = talloc_asprintf_append(schema_entry, + "ABSTRACT%s", seperator); + IF_NULL_FAIL_RET(schema_entry); + break; + case 3: + schema_entry = talloc_asprintf_append(schema_entry, + "AUXILIARY%s", seperator); + IF_NULL_FAIL_RET(schema_entry); + break; + } + + if (must) { + schema_entry = talloc_asprintf_append(schema_entry, + "MUST ( "); + IF_NULL_FAIL_RET(schema_entry); + + APPEND_ATTRS(must); + + schema_entry = talloc_asprintf_append(schema_entry, + ")%s", seperator); + IF_NULL_FAIL_RET(schema_entry); + } + + if (may) { + schema_entry = talloc_asprintf_append(schema_entry, + "MAY ( "); + IF_NULL_FAIL_RET(schema_entry); + + APPEND_ATTRS(may); + + schema_entry = talloc_asprintf_append(schema_entry, + ")%s", seperator); + IF_NULL_FAIL_RET(schema_entry); + } + + schema_entry = talloc_asprintf_append(schema_entry, + ")"); + return schema_entry; +} + +char *schema_class_to_description(TALLOC_CTX *mem_ctx, const struct dsdb_class *class) +{ + char *schema_description; + TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); + if (!tmp_ctx) { + return NULL; + } + + schema_description + = schema_class_description(mem_ctx, + TARGET_AD_SCHEMA_SUBENTRY, + " ", + class->governsID_oid, + class->lDAPDisplayName, + NULL, + NULL, + class->subClassOf, + class->objectClassCategory, + dsdb_attribute_list(tmp_ctx, + class, DSDB_SCHEMA_ALL_MUST), + dsdb_attribute_list(tmp_ctx, + class, DSDB_SCHEMA_ALL_MAY)); + talloc_free(tmp_ctx); + return schema_description; +} +char *schema_class_to_dITContentRule(TALLOC_CTX *mem_ctx, const struct dsdb_class *class, + const struct dsdb_schema *schema) +{ + int i; + char *schema_description; + char **aux_class_list = NULL; + char **attrs; + char **must_attr_list = NULL; + char **may_attr_list = NULL; + TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); + const struct dsdb_class *aux_class; + if (!tmp_ctx) { + return NULL; + } + + aux_class_list = merge_attr_list(tmp_ctx, aux_class_list, class->systemAuxiliaryClass); + aux_class_list = merge_attr_list(tmp_ctx, aux_class_list, class->auxiliaryClass); + + for (i=0; aux_class_list && aux_class_list[i]; i++) { + aux_class = dsdb_class_by_lDAPDisplayName(schema, aux_class_list[i]); + + attrs = dsdb_attribute_list(mem_ctx, aux_class, DSDB_SCHEMA_ALL_MUST); + must_attr_list = merge_attr_list(mem_ctx, must_attr_list, attrs); + + attrs = dsdb_attribute_list(mem_ctx, aux_class, DSDB_SCHEMA_ALL_MAY); + may_attr_list = merge_attr_list(mem_ctx, may_attr_list, attrs); + } + + schema_description + = schema_class_description(mem_ctx, + TARGET_AD_SCHEMA_SUBENTRY, + " ", + class->governsID_oid, + class->lDAPDisplayName, + (const char **)aux_class_list, + NULL, + class->subClassOf, + -1, must_attr_list, may_attr_list); + talloc_free(tmp_ctx); + return schema_description; +} diff --git a/source4/dsdb/schema/schema_init.c b/source4/dsdb/schema/schema_init.c index 85fdbe9e87..65df25ca3f 100644 --- a/source4/dsdb/schema/schema_init.c +++ b/source4/dsdb/schema/schema_init.c @@ -1599,8 +1599,8 @@ 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 **merge_attr_list(TALLOC_CTX *mem_ctx, + char **attrs, const char **new_attrs) { char **ret_attrs; int i; @@ -1618,60 +1618,73 @@ static char **merge_attr_list(TALLOC_CTX *mem_ctx, 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, - const struct dsdb_schema *schema, - const char **class_list, - enum dsdb_attr_list_query query) +/* + 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]); - 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; - } + 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, @@ -1682,7 +1695,7 @@ char **dsdb_full_attribute_list_internal(TALLOC_CTX *mem_ctx, 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); } |