From d17a0058ba8492b8b3f81b6f10fc34b3e45bb8a6 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Mon, 3 Sep 2007 02:51:24 +0000 Subject: [PATCH] =?UTF-8?q?r24914:=20In=20response=20to=20bug=20#4892=20by?= =?UTF-8?q?=20Matthias=20Walln=C3=B6fer=20,=20allow?= =?UTF-8?q?=20the=20objectclass=20module=20to=20reconstruct=20the=20object?= =?UTF-8?q?class=20hierarchy,=20rather=20than=20using=20templates.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The issue being fixed in particular is that 'top' was not being set on containers. This should ensure we do this right for all objects. Andrew Bartlett --- source/dsdb/samdb/ldb_modules/objectclass.c | 46 ++++++++++++++--- source/dsdb/samdb/ldb_modules/samldb.c | 21 ++------ source/dsdb/samdb/samdb.c | 55 ++++++++------------- source/setup/provision_templates.ldif | 30 ----------- 4 files changed, 63 insertions(+), 89 deletions(-) diff --git a/source/dsdb/samdb/ldb_modules/objectclass.c b/source/dsdb/samdb/ldb_modules/objectclass.c index 04cf8efdb27..f2ca92638d9 100644 --- a/source/dsdb/samdb/ldb_modules/objectclass.c +++ b/source/dsdb/samdb/ldb_modules/objectclass.c @@ -92,6 +92,7 @@ static struct ldb_handle *oc_init_handle(struct ldb_request *req, struct ldb_mod } static int objectclass_sort(struct ldb_module *module, + struct ldb_message *msg, /* so that when we create new elements, we put it on the right parent */ TALLOC_CTX *mem_ctx, struct ldb_message_element *objectclass_element, struct class_list **sorted_out) @@ -100,7 +101,7 @@ static int objectclass_sort(struct ldb_module *module, int layer; const struct dsdb_schema *schema = dsdb_get_schema(module->ldb); struct class_list *sorted = NULL, *parent_class = NULL, - *subclass = NULL, *unsorted = NULL, *current, *poss_subclass; + *subclass = NULL, *unsorted = NULL, *current, *poss_subclass, *poss_parent, *new_parent; /* DESIGN: * * We work on 4 different 'bins' (implemented here as linked lists): @@ -149,6 +150,34 @@ static int objectclass_sort(struct ldb_module *module, } } + if (parent_class == NULL) { + current = talloc(mem_ctx, struct class_list); + current->objectclass = talloc_strdup(msg, "top"); + DLIST_ADD_END(parent_class, current, struct class_list *); + } + + /* For each object: find parent chain */ + for (current = unsorted; schema && current; current = current->next) { + const struct dsdb_class *class = dsdb_class_by_lDAPDisplayName(schema, current->objectclass); + if (!class) { + ldb_asprintf_errstring(module->ldb, "objectclass %s is not a valid objectClass in schema", current->objectclass); + return LDB_ERR_OBJECT_CLASS_VIOLATION; + } + for (poss_parent = unsorted; poss_parent; poss_parent = poss_parent->next) { + if (ldb_attr_cmp(poss_parent->objectclass, class->subClassOf) == 0) { + break; + } + } + /* If we didn't get to the end of the list, we need to add this parent */ + if (poss_parent || (ldb_attr_cmp("top", class->subClassOf) == 0)) { + continue; + } + + new_parent = talloc(mem_ctx, struct class_list); + new_parent->objectclass = talloc_strdup(msg, class->subClassOf); + DLIST_ADD_END(unsorted, new_parent, struct class_list *); + } + /* DEBUGGING aid: how many layers are we down now? */ layer = 0; do { @@ -265,11 +294,6 @@ static int objectclass_add(struct ldb_module *module, struct ldb_request *req) return LDB_ERR_OPERATIONS_ERROR; } - ret = objectclass_sort(module, mem_ctx, objectclass_element, &sorted); - if (ret != LDB_SUCCESS) { - return ret; - } - /* prepare the first operation */ down_req = talloc(req, struct ldb_request); if (down_req == NULL) { @@ -287,6 +311,12 @@ static int objectclass_add(struct ldb_module *module, struct ldb_request *req) return LDB_ERR_OPERATIONS_ERROR; } + ret = objectclass_sort(module, msg, mem_ctx, objectclass_element, &sorted); + if (ret != LDB_SUCCESS) { + talloc_free(mem_ctx); + return ret; + } + ldb_msg_remove_attr(msg, "objectClass"); ret = ldb_msg_add_empty(msg, "objectClass", 0, NULL); @@ -398,7 +428,7 @@ static int objectclass_modify(struct ldb_module *module, struct ldb_request *req return LDB_ERR_OPERATIONS_ERROR; } - ret = objectclass_sort(module, mem_ctx, objectclass_element, &sorted); + ret = objectclass_sort(module, msg, mem_ctx, objectclass_element, &sorted); if (ret != LDB_SUCCESS) { return ret; } @@ -579,7 +609,7 @@ static int objectclass_do_mod(struct ldb_handle *h) { /* modify dn */ msg->dn = ac->orig_req->op.mod.message->dn; - ret = objectclass_sort(ac->module, mem_ctx, objectclass_element, &sorted); + ret = objectclass_sort(ac->module, msg, mem_ctx, objectclass_element, &sorted); if (ret != LDB_SUCCESS) { return ret; } diff --git a/source/dsdb/samdb/ldb_modules/samldb.c b/source/dsdb/samdb/ldb_modules/samldb.c index d448e30b31b..5342c149676 100644 --- a/source/dsdb/samdb/ldb_modules/samldb.c +++ b/source/dsdb/samdb/ldb_modules/samldb.c @@ -411,7 +411,7 @@ static int samldb_fill_group_object(struct ldb_module *module, const struct ldb_ } ret = samdb_copy_template(module->ldb, msg2, - "(&(CN=TemplateGroup)(objectclass=groupTemplate))", + "group", &errstr); if (ret != 0) { @@ -476,7 +476,7 @@ static int samldb_fill_user_or_computer_object(struct ldb_module *module, const if (samdb_find_attribute(module->ldb, msg, "objectclass", "computer") != NULL) { ret = samdb_copy_template(module->ldb, msg2, - "(&(CN=TemplateComputer)(objectclass=userTemplate))", + "computer", &errstr); if (ret) { ldb_asprintf_errstring(module->ldb, @@ -486,22 +486,9 @@ static int samldb_fill_user_or_computer_object(struct ldb_module *module, const talloc_free(mem_ctx); return ret; } - - /* readd user and then computer objectclasses */ - ret = samdb_find_or_add_value(module->ldb, msg2, "objectclass", "user"); - if (ret) { - talloc_free(mem_ctx); - return ret; - } - ret = samdb_find_or_add_value(module->ldb, msg2, "objectclass", "computer"); - if (ret) { - talloc_free(mem_ctx); - return ret; - } - } else { ret = samdb_copy_template(module->ldb, msg2, - "(&(CN=TemplateUser)(objectclass=userTemplate))", + "user", &errstr); if (ret) { ldb_asprintf_errstring(module->ldb, @@ -582,7 +569,7 @@ static int samldb_fill_foreignSecurityPrincipal_object(struct ldb_module *module } ret = samdb_copy_template(module->ldb, msg2, - "(&(CN=TemplateForeignSecurityPrincipal)(objectclass=foreignSecurityPrincipalTemplate))", + "ForeignSecurityPrincipal", &errstr); if (ret != 0) { ldb_asprintf_errstring(module->ldb, diff --git a/source/dsdb/samdb/samdb.c b/source/dsdb/samdb/samdb.c index 7a20ea8665f..18669a2ae7d 100644 --- a/source/dsdb/samdb/samdb.c +++ b/source/dsdb/samdb/samdb.c @@ -680,7 +680,7 @@ int samdb_find_or_add_attribute(struct ldb_context *ldb, struct ldb_message *msg copy from a template record to a message */ int samdb_copy_template(struct ldb_context *ldb, - struct ldb_message *msg, const char *filter, + struct ldb_message *msg, const char *name, const char **errstring) { struct ldb_result *res; @@ -690,15 +690,20 @@ int samdb_copy_template(struct ldb_context *ldb, *errstring = NULL; + if (!ldb_dn_add_child_fmt(basedn, "CN=Template%s", name)) { + return LDB_ERR_OPERATIONS_ERROR; + } + /* pull the template record */ - ret = ldb_search(ldb, basedn, LDB_SCOPE_SUBTREE, filter, NULL, &res); + ret = ldb_search(ldb, basedn, LDB_SCOPE_BASE, "cn=*", NULL, &res); talloc_free(basedn); if (ret != LDB_SUCCESS) { *errstring = talloc_steal(msg, ldb_errstring(ldb)); return ret; } if (res->count != 1) { - *errstring = talloc_asprintf(msg, "samdb_copy_template: ERROR: template '%s' matched %d records, expected 1\n", filter, + *errstring = talloc_asprintf(msg, "samdb_copy_template: ERROR: template '%s' matched %d records, expected 1\n", + name, res->count); talloc_free(res); return LDB_ERR_OPERATIONS_ERROR; @@ -708,40 +713,22 @@ int samdb_copy_template(struct ldb_context *ldb, for (i = 0; i < t->num_elements; i++) { struct ldb_message_element *el = &t->elements[i]; /* some elements should not be copied from the template */ - if (strcasecmp(el->name, "cn") == 0 || - strcasecmp(el->name, "name") == 0 || - strcasecmp(el->name, "sAMAccountName") == 0 || - strcasecmp(el->name, "sAMAccountName") == 0 || - strcasecmp(el->name, "distinguishedName") == 0 || - strcasecmp(el->name, "objectGUID") == 0) { + if (ldb_attr_cmp(el->name, "cn") == 0 || + ldb_attr_cmp(el->name, "name") == 0 || + ldb_attr_cmp(el->name, "objectClass") == 0 || + ldb_attr_cmp(el->name, "sAMAccountName") == 0 || + ldb_attr_cmp(el->name, "sAMAccountName") == 0 || + ldb_attr_cmp(el->name, "distinguishedName") == 0 || + ldb_attr_cmp(el->name, "objectGUID") == 0) { continue; } for (j = 0; j < el->num_values; j++) { - if (strcasecmp(el->name, "objectClass") == 0) { - if (strcasecmp((char *)el->values[j].data, "Template") == 0 || - strcasecmp((char *)el->values[j].data, "userTemplate") == 0 || - strcasecmp((char *)el->values[j].data, "groupTemplate") == 0 || - strcasecmp((char *)el->values[j].data, "foreignSecurityPrincipalTemplate") == 0 || - strcasecmp((char *)el->values[j].data, "aliasTemplate") == 0 || - strcasecmp((char *)el->values[j].data, "trustedDomainTemplate") == 0 || - strcasecmp((char *)el->values[j].data, "secretTemplate") == 0) { - continue; - } - ret = samdb_find_or_add_value(ldb, msg, el->name, - (char *)el->values[j].data); - if (ret) { - *errstring = talloc_asprintf(msg, "Adding objectClass %s failed.\n", el->values[j].data); - talloc_free(res); - return ret; - } - } else { - ret = samdb_find_or_add_attribute(ldb, msg, el->name, - (char *)el->values[j].data); - if (ret) { - *errstring = talloc_asprintf(msg, "Adding attribute %s failed.\n", el->name); - talloc_free(res); - return ret; - } + ret = samdb_find_or_add_attribute(ldb, msg, el->name, + (char *)el->values[j].data); + if (ret) { + *errstring = talloc_asprintf(msg, "Adding attribute %s failed.\n", el->name); + talloc_free(res); + return ret; } } } diff --git a/source/setup/provision_templates.ldif b/source/setup/provision_templates.ldif index 914582eaf07..fa0718a0b7f 100644 --- a/source/setup/provision_templates.ldif +++ b/source/setup/provision_templates.ldif @@ -12,11 +12,6 @@ isCriticalSystemObject: TRUE ### dn: CN=TemplateUser,CN=Templates -objectClass: top -objectClass: person -objectClass: organizationalPerson -objectClass: Template -objectClass: userTemplate userAccountControl: 514 badPwdCount: 0 codePage: 0 @@ -31,11 +26,6 @@ logonCount: 0 sAMAccountType: 805306368 dn: CN=TemplateComputer,CN=Templates -objectClass: top -objectClass: person -objectClass: organizationalPerson -objectClass: Template -objectClass: userTemplate userAccountControl: 4098 badPwdCount: 0 codePage: 0 @@ -50,9 +40,6 @@ logonCount: 0 sAMAccountType: 805306369 dn: CN=TemplateTrustingDomain,CN=Templates -objectClass: top -objectClass: Template -objectClass: userTemplate userAccountControl: 2080 badPwdCount: 0 codePage: 0 @@ -66,38 +53,21 @@ logonCount: 0 sAMAccountType: 805306370 dn: CN=TemplateGroup,CN=Templates -objectClass: top -objectClass: Template -objectClass: groupTemplate groupType: -2147483646 sAMAccountType: 268435456 # Currently this isn't used, we don't have a way to detect it different from an incoming alias # # dn: CN=TemplateAlias,CN=Templates -# objectClass: top -# objectClass: Template -# objectClass: aliasTemplate # cn: TemplateAlias # instanceType: 4 # groupType: -2147483644 # sAMAccountType: 268435456 dn: CN=TemplateForeignSecurityPrincipal,CN=Templates -objectClass: top -objectClass: Template -objectClass: foreignSecurityPrincipalTemplate showInAdvancedViewOnly: TRUE dn: CN=TemplateSecret,CN=Templates -objectClass: top -objectClass: leaf -objectClass: Template -objectClass: secretTemplate dn: CN=TemplateTrustedDomain,CN=Templates -objectClass: top -objectClass: leaf -objectClass: Template -objectClass: trustedDomainTemplate