diff options
author | Jeremy Allison <jra@samba.org> | 2009-04-09 22:46:59 -0700 |
---|---|---|
committer | Jeremy Allison <jra@samba.org> | 2009-04-09 22:46:59 -0700 |
commit | 7f10bf980edef3ace1522d0c9c082b35e225c950 (patch) | |
tree | d4e9af21de194cca812e754b28f9358a3651f4ce /source4/dsdb/schema | |
parent | f8f68703da58cf7f61b655b48bbbc45cda647748 (diff) | |
parent | f930f504e1d5e78d2f6f36cab9ce36dbeb34e955 (diff) | |
download | samba-7f10bf980edef3ace1522d0c9c082b35e225c950.tar.gz samba-7f10bf980edef3ace1522d0c9c082b35e225c950.tar.bz2 samba-7f10bf980edef3ace1522d0c9c082b35e225c950.zip |
Merge branch 'master' of ssh://jra@git.samba.org/data/git/samba
Diffstat (limited to 'source4/dsdb/schema')
-rw-r--r-- | source4/dsdb/schema/schema.h | 21 | ||||
-rw-r--r-- | source4/dsdb/schema/schema_convert_to_ol.c | 350 | ||||
-rw-r--r-- | source4/dsdb/schema/schema_inferiors.c | 190 | ||||
-rw-r--r-- | source4/dsdb/schema/schema_init.c | 167 | ||||
-rw-r--r-- | source4/dsdb/schema/schema_query.c | 145 | ||||
-rw-r--r-- | source4/dsdb/schema/schema_set.c | 227 | ||||
-rw-r--r-- | source4/dsdb/schema/schema_syntax.c | 13 |
7 files changed, 903 insertions, 210 deletions
diff --git a/source4/dsdb/schema/schema.h b/source4/dsdb/schema/schema.h index f7d59a7c39..e15f65a0a1 100644 --- a/source4/dsdb/schema/schema.h +++ b/source4/dsdb/schema/schema.h @@ -91,6 +91,7 @@ struct dsdb_attribute { /* internal stuff */ const struct dsdb_syntax *syntax; + const struct ldb_schema_attribute *ldb_schema_attribute; }; struct dsdb_class { @@ -131,6 +132,11 @@ struct dsdb_class { bool defaultHidingValue; bool isDefunct; bool systemOnly; + + char **supclasses; + char **subclasses; + char **subclasses_direct; + char **posssuperiors; }; struct dsdb_schema_oid_prefix { @@ -156,6 +162,21 @@ struct dsdb_schema { struct dsdb_attribute *attributes; struct dsdb_class *classes; + /* lists of classes sorted by various attributes, for faster + access */ + uint32_t num_classes; + struct dsdb_class **classes_by_lDAPDisplayName; + struct dsdb_class **classes_by_governsID_id; + struct dsdb_class **classes_by_governsID_oid; + struct dsdb_class **classes_by_cn; + + /* lists of attributes sorted by various fields */ + uint32_t num_attributes; + struct dsdb_attribute **attributes_by_lDAPDisplayName; + struct dsdb_attribute **attributes_by_attributeID_id; + struct dsdb_attribute **attributes_by_attributeID_oid; + struct dsdb_attribute **attributes_by_linkID; + struct { bool we_are_master; struct ldb_dn *master_dn; diff --git a/source4/dsdb/schema/schema_convert_to_ol.c b/source4/dsdb/schema/schema_convert_to_ol.c new file mode 100644 index 0000000000..ebcb7ade59 --- /dev/null +++ b/source4/dsdb/schema/schema_convert_to_ol.c @@ -0,0 +1,350 @@ +/* + schema conversion routines + + 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 "ldb.h" +#include "dsdb/samdb/samdb.h" +#include "system/locale.h" + +#define SEPERATOR "\n " + +struct attr_map { + char *old_attr; + char *new_attr; +}; + +struct oid_map { + char *old_oid; + char *new_oid; +}; + +static char *print_schema_recursive(char *append_to_string, struct dsdb_schema *schema, const char *print_class, + enum dsdb_schema_convert_target target, + const char **attrs_skip, const struct attr_map *attr_map, const struct oid_map *oid_map) +{ + char *out = append_to_string; + const struct dsdb_class *objectclass; + objectclass = dsdb_class_by_lDAPDisplayName(schema, print_class); + if (!objectclass) { + DEBUG(0, ("Cannot find class %s in schema\n", print_class)); + return NULL; + } + + do { + TALLOC_CTX *mem_ctx = talloc_new(append_to_string); + const char *name = objectclass->lDAPDisplayName; + const char *oid = objectclass->governsID_oid; + const char *subClassOf = objectclass->subClassOf; + int objectClassCategory = objectclass->objectClassCategory; + const char **must; + const char **may; + char *schema_entry = NULL; + const char *objectclass_name_as_list[] = { + objectclass->lDAPDisplayName, + NULL + }; + int j; + int attr_idx; + + if (!mem_ctx) { + DEBUG(0, ("Failed to create new talloc context\n")); + return NULL; + } + + /* We have been asked to skip some attributes/objectClasses */ + if (attrs_skip && str_list_check_ci(attrs_skip, name)) { + continue; + } + + /* We might have been asked to remap this oid, due to a conflict */ + for (j=0; oid_map && oid_map[j].old_oid; j++) { + if (strcasecmp(oid, oid_map[j].old_oid) == 0) { + oid = oid_map[j].new_oid; + break; + } + } + + /* We might have been asked to remap this name, due to a conflict */ + for (j=0; name && attr_map && attr_map[j].old_attr; j++) { + if (strcasecmp(name, attr_map[j].old_attr) == 0) { + name = attr_map[j].new_attr; + break; + } + } + + may = dsdb_full_attribute_list(mem_ctx, schema, objectclass_name_as_list, DSDB_SCHEMA_ALL_MAY); + + for (j=0; may && may[j]; j++) { + /* We might have been asked to remap this name, due to a conflict */ + for (attr_idx=0; attr_map && attr_map[attr_idx].old_attr; attr_idx++) { + if (strcasecmp(may[j], attr_map[attr_idx].old_attr) == 0) { + may[j] = attr_map[attr_idx].new_attr; + break; + } + } + } + + must = dsdb_full_attribute_list(mem_ctx, schema, objectclass_name_as_list, DSDB_SCHEMA_ALL_MUST); + + for (j=0; must && must[j]; j++) { + /* We might have been asked to remap this name, due to a conflict */ + for (attr_idx=0; attr_map && attr_map[attr_idx].old_attr; attr_idx++) { + if (strcasecmp(must[j], attr_map[attr_idx].old_attr) == 0) { + must[j] = attr_map[attr_idx].new_attr; + break; + } + } + } + + schema_entry = schema_class_description(mem_ctx, target, + SEPERATOR, + oid, + name, + NULL, + subClassOf, + objectClassCategory, + must, + may, + NULL); + if (schema_entry == NULL) { + DEBUG(0, ("failed to generate schema description for %s\n", name)); + return NULL; + } + + switch (target) { + case TARGET_OPENLDAP: + out = talloc_asprintf_append(out, "objectclass %s\n\n", schema_entry); + break; + case TARGET_FEDORA_DS: + out = talloc_asprintf_append(out, "objectClasses: %s\n", schema_entry); + break; + } + talloc_free(mem_ctx); + } while (0); + + + for (objectclass=schema->classes; objectclass; objectclass = objectclass->next) { + if (ldb_attr_cmp(objectclass->subClassOf, print_class) == 0 + && ldb_attr_cmp(objectclass->lDAPDisplayName, print_class) != 0) { + out = print_schema_recursive(out, schema, objectclass->lDAPDisplayName, + target, attrs_skip, attr_map, oid_map); + } + } + return out; +} + +/* Routine to linearise our internal schema into the format that + OpenLDAP and Fedora DS use for their backend. + + The 'mappings' are of a format like: + +#Standard OpenLDAP attributes +labeledURI +#The memberOf plugin provides this attribute +memberOf +#These conflict with OpenLDAP builtins +attributeTypes:samba4AttributeTypes +2.5.21.5:1.3.6.1.4.1.7165.4.255.7 + +*/ + + +char *dsdb_convert_schema_to_openldap(struct ldb_context *ldb, char *target_str, const char *mappings) +{ + /* Read list of attributes to skip, OIDs to map */ + TALLOC_CTX *mem_ctx = talloc_new(ldb); + char *line; + char *out; + const char **attrs_skip = NULL; + int num_skip = 0; + struct oid_map *oid_map = NULL; + int num_oid_maps = 0; + struct attr_map *attr_map = NULL; + int num_attr_maps = 0; + struct dsdb_attribute *attribute; + struct dsdb_schema *schema; + enum dsdb_schema_convert_target target; + + char *next_line = talloc_strdup(mem_ctx, mappings); + + if (!target_str || strcasecmp(target_str, "openldap") == 0) { + target = TARGET_OPENLDAP; + } else if (strcasecmp(target_str, "fedora-ds") == 0) { + target = TARGET_FEDORA_DS; + } else { + DEBUG(0, ("Invalid target type for schema conversion %s\n", target_str)); + return NULL; + } + + /* The mappings are line-seperated, and specify details such as OIDs to skip etc */ + while (1) { + line = next_line; + next_line = strchr(line, '\n'); + if (!next_line) { + break; + } + next_line[0] = '\0'; + next_line++; + + /* Blank Line */ + if (line[0] == '\0') { + continue; + } + /* Comment */ + if (line[0] == '#') { + continue; + } + + if (isdigit(line[0])) { + char *p = strchr(line, ':'); + if (!p) { + DEBUG(0, ("schema mapping file line has OID but no OID to map to: %s\n", line)); + return NULL; + } + p[0] = '\0'; + p++; + oid_map = talloc_realloc(mem_ctx, oid_map, struct oid_map, num_oid_maps + 2); + trim_string(line, " ", " "); + oid_map[num_oid_maps].old_oid = talloc_strdup(oid_map, line); + trim_string(p, " ", " "); + oid_map[num_oid_maps].new_oid = p; + num_oid_maps++; + oid_map[num_oid_maps].old_oid = NULL; + } else { + char *p = strchr(line, ':'); + if (p) { + /* remap attribute/objectClass */ + p[0] = '\0'; + p++; + attr_map = talloc_realloc(mem_ctx, attr_map, struct attr_map, num_attr_maps + 2); + trim_string(line, " ", " "); + attr_map[num_attr_maps].old_attr = talloc_strdup(attr_map, line); + trim_string(p, " ", " "); + attr_map[num_attr_maps].new_attr = p; + num_attr_maps++; + attr_map[num_attr_maps].old_attr = NULL; + } else { + /* skip attribute/objectClass */ + attrs_skip = talloc_realloc(mem_ctx, attrs_skip, const char *, num_skip + 2); + trim_string(line, " ", " "); + attrs_skip[num_skip] = talloc_strdup(attrs_skip, line); + num_skip++; + attrs_skip[num_skip] = NULL; + } + } + } + + schema = dsdb_get_schema(ldb); + if (!schema) { + DEBUG(0, ("No schema on ldb to convert!\n")); + return NULL; + } + + switch (target) { + case TARGET_OPENLDAP: + out = talloc_strdup(mem_ctx, ""); + break; + case TARGET_FEDORA_DS: + out = talloc_strdup(mem_ctx, "dn: cn=schema\n"); + break; + } + + for (attribute=schema->attributes; attribute; attribute = attribute->next) { + const char *name = attribute->lDAPDisplayName; + const char *oid = attribute->attributeID_oid; + const char *syntax = attribute->attributeSyntax_oid; + const char *equality = NULL, *substring = NULL; + bool single_value = attribute->isSingleValued; + + char *schema_entry = NULL; + int j; + + /* We have been asked to skip some attributes/objectClasses */ + if (attrs_skip && str_list_check_ci(attrs_skip, name)) { + continue; + } + + /* We might have been asked to remap this oid, due to a conflict */ + for (j=0; oid && oid_map && oid_map[j].old_oid; j++) { + if (strcasecmp(oid, oid_map[j].old_oid) == 0) { + oid = oid_map[j].new_oid; + break; + } + } + + if (attribute->syntax) { + /* We might have been asked to remap this oid, + * due to a conflict, or lack of + * implementation */ + syntax = attribute->syntax->ldap_oid; + /* We might have been asked to remap this oid, due to a conflict */ + for (j=0; syntax && oid_map && oid_map[j].old_oid; j++) { + if (strcasecmp(syntax, oid_map[j].old_oid) == 0) { + syntax = oid_map[j].new_oid; + break; + } + } + + equality = attribute->syntax->equality; + substring = attribute->syntax->substring; + } + + /* We might have been asked to remap this name, due to a conflict */ + for (j=0; name && attr_map && attr_map[j].old_attr; j++) { + if (strcasecmp(name, attr_map[j].old_attr) == 0) { + name = attr_map[j].new_attr; + break; + } + } + + schema_entry = schema_attribute_description(mem_ctx, + target, + SEPERATOR, + oid, + name, + equality, + substring, + syntax, + single_value, + false, + NULL, NULL, + NULL, NULL, + false, false); + + if (schema_entry == NULL) { + DEBUG(0, ("failed to generate attribute description for %s\n", name)); + return NULL; + } + + switch (target) { + case TARGET_OPENLDAP: + out = talloc_asprintf_append(out, "attributetype %s\n\n", schema_entry); + break; + case TARGET_FEDORA_DS: + out = talloc_asprintf_append(out, "attributeTypes: %s\n", schema_entry); + break; + } + } + + out = print_schema_recursive(out, schema, "top", target, attrs_skip, attr_map, oid_map); + + return out; +} + diff --git a/source4/dsdb/schema/schema_inferiors.c b/source4/dsdb/schema/schema_inferiors.c new file mode 100644 index 0000000000..28f44ab263 --- /dev/null +++ b/source4/dsdb/schema/schema_inferiors.c @@ -0,0 +1,190 @@ +/* + Unix SMB/CIFS mplementation. + + implement possibleInferiors calculation + + Copyright (C) Andrew Tridgell 2009 + Copyright (C) Andrew Bartlett <abartlet@samba.org> 2009 + + 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/>. + +*/ +/* + This module is a C implementation of the logic in the + dsdb/samdb/ldb_modules/tests/possibleInferiors.py code + + To understand the C code, please see the python code first + */ + +#include "includes.h" +#include "dsdb/samdb/samdb.h" + + +/* + create the SUPCLASSES() list + */ +static char **schema_supclasses(struct dsdb_schema *schema, struct dsdb_class *schema_class) +{ + char **list; + + if (schema_class->supclasses) { + return schema_class->supclasses; + } + + list = str_list_make(schema_class, NULL, NULL); + if (list == NULL) { + DEBUG(0,(__location__ " out of memory\n")); + return NULL; + } + + /* Cope with 'top SUP top', ie top is subClassOf top */ + if (strcmp(schema_class->lDAPDisplayName, schema_class->subClassOf) == 0) { + schema_class->supclasses = list; + return list; + } + + if (schema_class->subClassOf) { + const char **list2; + list = str_list_add_const(list, schema_class->subClassOf); + + list2 = schema_supclasses(schema, + discard_const_p(struct dsdb_class, + dsdb_class_by_lDAPDisplayName(schema, + schema_class->subClassOf))); + list = str_list_append_const(list, list2); + } + + schema_class->supclasses = str_list_unique(list); + + return list; +} + +/* + this one is used internally + matches SUBCLASSES() python function + */ +static char **schema_subclasses(struct dsdb_schema *schema, TALLOC_CTX *mem_ctx, char **oclist) +{ + char **list = str_list_make(mem_ctx, NULL, NULL); + int i; + + for (i=0; oclist && oclist[i]; i++) { + struct dsdb_class *schema_class = dsdb_class_by_lDAPDisplayName(schema, oclist[i]); + list = str_list_append_const(list, schema_class->subclasses); + } + return list; +} + + +/* + equivalent of the POSSSUPERIORS() python function + */ +static char **schema_posssuperiors(struct dsdb_schema *schema, + struct dsdb_class *schema_class) +{ + if (schema_class->posssuperiors == NULL) { + char **list2 = str_list_make(schema_class, NULL, NULL); + char **list3; + int i; + + list2 = str_list_append_const(list2, schema_class->systemPossSuperiors); + list2 = str_list_append_const(list2, schema_class->possSuperiors); + list3 = schema_supclasses(schema, schema_class); + for (i=0; list3 && list3[i]; i++) { + struct dsdb_class *class2 = dsdb_class_by_lDAPDisplayName(schema, list3[i]); + list2 = str_list_append_const(list2, schema_posssuperiors(schema, class2)); + } + list2 = str_list_append_const(list2, schema_subclasses(schema, list2, list2)); + + schema_class->posssuperiors = str_list_unique(list2); + } + + return schema_class->posssuperiors; +} + +static char **schema_subclasses_recurse(struct dsdb_schema *schema, struct dsdb_class *schema_class) +{ + char **list = str_list_copy_const(schema_class, schema_class->subclasses_direct); + int i; + for (i=0;list && list[i]; i++) { + struct dsdb_class *schema_class2 = dsdb_class_by_lDAPDisplayName(schema, list[i]); + if (schema_class != schema_class2) { + list = str_list_append_const(list, schema_subclasses_recurse(schema, schema_class2)); + } + } + return list; +} + +static void schema_create_subclasses(struct dsdb_schema *schema) +{ + struct dsdb_class *schema_class; + + for (schema_class=schema->classes; schema_class; schema_class=schema_class->next) { + struct dsdb_class *schema_class2 = dsdb_class_by_lDAPDisplayName(schema, schema_class->subClassOf); + if (schema_class != schema_class2) { + if (schema_class2->subclasses_direct == NULL) { + schema_class2->subclasses_direct = str_list_make(schema_class2, NULL, NULL); + } + schema_class2->subclasses_direct = str_list_add_const(schema_class2->subclasses_direct, + schema_class->lDAPDisplayName); + } + } + + for (schema_class=schema->classes; schema_class; schema_class=schema_class->next) { + schema_class->subclasses = str_list_unique(schema_subclasses_recurse(schema, schema_class)); + } +} + +static void schema_fill_possible_inferiors(struct dsdb_schema *schema, struct dsdb_class *schema_class) +{ + struct dsdb_class *c2; + + for (c2=schema->classes; c2; c2=c2->next) { + char **superiors = schema_posssuperiors(schema, c2); + if (c2->systemOnly == false + && c2->objectClassCategory != 2 + && c2->objectClassCategory != 3 + && str_list_check(superiors, schema_class->lDAPDisplayName)) { + if (schema_class->possibleInferiors == NULL) { + schema_class->possibleInferiors = str_list_make(schema_class, NULL, NULL); + } + schema_class->possibleInferiors = str_list_add_const(schema_class->possibleInferiors, + c2->lDAPDisplayName); + } + } + schema_class->possibleInferiors = str_list_unique(schema_class->possibleInferiors); +} + +void schema_fill_constructed(struct dsdb_schema *schema) +{ + struct dsdb_class *schema_class; + + schema_create_subclasses(schema); + + for (schema_class=schema->classes; schema_class; schema_class=schema_class->next) { + schema_fill_possible_inferiors(schema, schema_class); + } + + /* free up our internal cache elements */ + for (schema_class=schema->classes; schema_class; schema_class=schema_class->next) { + talloc_free(schema_class->supclasses); + talloc_free(schema_class->subclasses_direct); + talloc_free(schema_class->subclasses); + talloc_free(schema_class->posssuperiors); + schema_class->supclasses = NULL; + schema_class->subclasses_direct = NULL; + schema_class->subclasses = NULL; + schema_class->posssuperiors = NULL; + } +} diff --git a/source4/dsdb/schema/schema_init.c b/source4/dsdb/schema/schema_init.c index a67aecd1e8..3a65c474fb 100644 --- a/source4/dsdb/schema/schema_init.c +++ b/source4/dsdb/schema/schema_init.c @@ -28,6 +28,7 @@ #include "librpc/gen_ndr/ndr_drsuapi.h" #include "librpc/gen_ndr/ndr_drsblobs.h" #include "param/param.h" +#include "lib/ldb/include/ldb_module.h" struct dsdb_schema *dsdb_new_schema(TALLOC_CTX *mem_ctx, struct smb_iconv_convenience *iconv_convenience) { @@ -582,6 +583,48 @@ WERROR dsdb_read_prefixes_from_ldb(TALLOC_CTX *mem_ctx, struct ldb_context *ldb, return WERR_OK; } + +/* + setup the ldb_schema_attribute field for a dsdb_attribute + */ +static int dsdb_schema_setup_ldb_schema_attribute(struct ldb_context *ldb, + struct dsdb_attribute *attr) +{ + const char *syntax = attr->syntax->ldb_syntax; + const struct ldb_schema_syntax *s; + struct ldb_schema_attribute *a; + + if (!syntax) { + syntax = attr->syntax->ldap_oid; + } + + s = ldb_samba_syntax_by_lDAPDisplayName(ldb, attr->lDAPDisplayName); + if (s == NULL) { + s = ldb_samba_syntax_by_name(ldb, syntax); + } + if (s == NULL) { + s = ldb_standard_syntax_by_name(ldb, syntax); + } + + if (s == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + + attr->ldb_schema_attribute = a = talloc(attr, struct ldb_schema_attribute); + if (attr->ldb_schema_attribute == NULL) { + ldb_oom(ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + + a->name = attr->lDAPDisplayName; + a->flags = 0; + a->syntax = s; + + return LDB_SUCCESS; +} + + + #define GET_STRING_LDB(msg, attr, mem_ctx, p, elem, strict) do { \ (p)->elem = samdb_result_string(msg, attr, NULL);\ if (strict && (p)->elem == NULL) { \ @@ -676,7 +719,8 @@ WERROR dsdb_read_prefixes_from_ldb(TALLOC_CTX *mem_ctx, struct ldb_context *ldb, }\ } while (0) -WERROR dsdb_attribute_from_ldb(const struct dsdb_schema *schema, +WERROR dsdb_attribute_from_ldb(struct ldb_context *ldb, + const struct dsdb_schema *schema, struct ldb_message *msg, TALLOC_CTX *mem_ctx, struct dsdb_attribute *attr) @@ -745,6 +789,10 @@ WERROR dsdb_attribute_from_ldb(const struct dsdb_schema *schema, return WERR_DS_ATT_SCHEMA_REQ_SYNTAX; } + if (dsdb_schema_setup_ldb_schema_attribute(ldb, attr) != LDB_SUCCESS) { + return WERR_DS_ATT_SCHEMA_REQ_SYNTAX; + } + return WERR_OK; } @@ -788,7 +836,6 @@ WERROR dsdb_class_from_ldb(const struct dsdb_schema *schema, GET_STRING_LIST_LDB(msg, "systemPossSuperiors", mem_ctx, obj, systemPossSuperiors, false); GET_STRING_LIST_LDB(msg, "possSuperiors", mem_ctx, obj, possSuperiors, false); - GET_STRING_LIST_LDB(msg, "possibleInferiors", mem_ctx, obj, possibleInferiors, false); GET_STRING_LDB(msg, "defaultSecurityDescriptor", mem_ctx, obj, defaultSecurityDescriptor, false); @@ -808,6 +855,12 @@ WERROR dsdb_class_from_ldb(const struct dsdb_schema *schema, #define dsdb_oom(error_string, mem_ctx) *error_string = talloc_asprintf(mem_ctx, "dsdb out of memory at %s:%d\n", __FILE__, __LINE__) +/* + Create a DSDB schema from the ldb results provided. This is called + directly when the schema is provisioned from an on-disk LDIF file, or + from dsdb_schema_from_schema_dn below +*/ + int dsdb_schema_from_ldb_results(TALLOC_CTX *mem_ctx, struct ldb_context *ldb, struct smb_iconv_convenience *iconv_convenience, struct ldb_result *schema_res, @@ -861,7 +914,7 @@ int dsdb_schema_from_ldb_results(TALLOC_CTX *mem_ctx, struct ldb_context *ldb, return LDB_ERR_OPERATIONS_ERROR; } - status = dsdb_attribute_from_ldb(schema, attrs_res->msgs[i], sa, sa); + status = dsdb_attribute_from_ldb(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 attribute definition: %s:%s", @@ -908,96 +961,9 @@ 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(ldb, mem_ctx, &res, - schemadn, LDB_SCOPE_SUBTREE, NULL, - "(&(&(objectClass=classSchema)(subClassOf=%s))(!(lDAPDisplayName=%s)))", - name, name); - if (ret != LDB_SUCCESS) { - 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, - char **error_string) -{ - 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; - } - - /* Download 'top' */ - ret = ldb_search(ldb, local_ctx, &top_res, - schemadn, LDB_SCOPE_SUBTREE, NULL, - "(&(objectClass=classSchema)(lDAPDisplayName=top))"); - if (ret != LDB_SUCCESS) { - *error_string = talloc_asprintf(mem_ctx, - "dsdb_schema: failed to search for top classSchema object: %s", - ldb_errstring(ldb)); - return ret; - } - - if (top_res->count != 1) { - *error_string = talloc_asprintf(mem_ctx, - "dsdb_schema: failed to find top classSchema object"); - return LDB_ERR_NO_SUCH_OBJECT; - } - - 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) { - return ret; - } - - *objectclasses_res = talloc_move(mem_ctx, &ret_res); - return ret; -} +/* + Given an LDB, and the DN, return a populated schema +*/ int dsdb_schema_from_schema_dn(TALLOC_CTX *mem_ctx, struct ldb_context *ldb, struct smb_iconv_convenience *iconv_convenience, @@ -1065,10 +1031,13 @@ int dsdb_schema_from_schema_dn(TALLOC_CTX *mem_ctx, struct ldb_context *ldb, /* * load the objectClass definitions */ - ret = fetch_objectclass_schema(ldb, schema_dn, tmp_ctx, &c_res, &error_string); + ret = ldb_search(ldb, tmp_ctx, &c_res, + schema_dn, LDB_SCOPE_ONELEVEL, NULL, + "(objectClass=classSchema)"); if (ret != LDB_SUCCESS) { *error_string_out = talloc_asprintf(mem_ctx, - "Failed to fetch objectClass schema elements: %s", error_string); + "dsdb_schema: failed to search attributeSchema objects: %s", + ldb_errstring(ldb)); talloc_free(tmp_ctx); return ret; } @@ -1353,7 +1322,8 @@ static struct drsuapi_DsReplicaAttribute *dsdb_find_object_attr_name(struct dsdb }\ } while (0) -WERROR dsdb_attribute_from_drsuapi(struct dsdb_schema *schema, +WERROR dsdb_attribute_from_drsuapi(struct ldb_context *ldb, + struct dsdb_schema *schema, struct drsuapi_DsReplicaObject *r, TALLOC_CTX *mem_ctx, struct dsdb_attribute *attr) @@ -1412,6 +1382,10 @@ WERROR dsdb_attribute_from_drsuapi(struct dsdb_schema *schema, return WERR_DS_ATT_SCHEMA_REQ_SYNTAX; } + if (dsdb_schema_setup_ldb_schema_attribute(ldb, attr) != LDB_SUCCESS) { + return WERR_DS_ATT_SCHEMA_REQ_SYNTAX; + } + return WERR_OK; } @@ -1451,7 +1425,6 @@ WERROR dsdb_class_from_drsuapi(struct dsdb_schema *schema, GET_STRING_LIST_DS(schema, r, "systemPossSuperiors", mem_ctx, obj, systemPossSuperiors, false); GET_STRING_LIST_DS(schema, r, "possSuperiors", mem_ctx, obj, possSuperiors, false); - GET_STRING_LIST_DS(schema, r, "possibleInferiors", mem_ctx, obj, possibleInferiors, false); GET_STRING_DS(schema, r, "defaultSecurityDescriptor", mem_ctx, obj, defaultSecurityDescriptor, false); diff --git a/source4/dsdb/schema/schema_query.c b/source4/dsdb/schema/schema_query.c index 00de0f8983..f894ef5b1e 100644 --- a/source4/dsdb/schema/schema_query.c +++ b/source4/dsdb/schema/schema_query.c @@ -23,10 +23,44 @@ #include "includes.h" #include "dsdb/samdb/samdb.h" +/* a binary array search, where the array is an array of pointers to structures, + and we want to find a match for 'target' on 'field' in those structures. + + Inputs: + array: base pointer to an array of structures + arrray_size: number of elements in the array + field: the name of the field in the structure we are keying off + target: the field value we are looking for + comparison_fn: the comparison function + result: where the result of the search is put + + if the element is found, then 'result' is set to point to the found array element. If not, + then 'result' is set to NULL. + + The array is assumed to be sorted by the same comparison_fn as the + search (with, for example, qsort) + */ +#define BINARY_ARRAY_SEARCH(array, array_size, field, target, comparison_fn, result) do { \ + int32_t _b, _e; \ + (result) = NULL; \ + for (_b = 0, _e = (array_size)-1; _b <= _e; ) { \ + int32_t _i = (_b+_e)/2; \ + int _r = comparison_fn(target, array[_i]->field); \ + if (_r == 0) { (result) = array[_i]; break; } \ + if (_r < 0) _e = _i - 1; else _b = _i + 1; \ + } } while (0) + + +static int uint32_cmp(uint32_t c1, uint32_t c2) +{ + return c1 - c2; +} + + const struct dsdb_attribute *dsdb_attribute_by_attributeID_id(const struct dsdb_schema *schema, uint32_t id) { - struct dsdb_attribute *cur; + struct dsdb_attribute *c; /* * 0xFFFFFFFF is used as value when no mapping table is available, @@ -34,69 +68,49 @@ const struct dsdb_attribute *dsdb_attribute_by_attributeID_id(const struct dsdb_ */ 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; + BINARY_ARRAY_SEARCH(schema->attributes_by_attributeID_id, + schema->num_attributes, attributeID_id, id, uint32_cmp, c); + return c; } const struct dsdb_attribute *dsdb_attribute_by_attributeID_oid(const struct dsdb_schema *schema, const char *oid) { - struct dsdb_attribute *cur; + struct dsdb_attribute *c; 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; + BINARY_ARRAY_SEARCH(schema->attributes_by_attributeID_oid, + schema->num_attributes, attributeID_oid, oid, strcasecmp, c); + return c; } const struct dsdb_attribute *dsdb_attribute_by_lDAPDisplayName(const struct dsdb_schema *schema, const char *name) { - struct dsdb_attribute *cur; + struct dsdb_attribute *c; 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; + BINARY_ARRAY_SEARCH(schema->attributes_by_lDAPDisplayName, + schema->num_attributes, lDAPDisplayName, name, strcasecmp, c); + return c; } 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; + struct dsdb_attribute *c; - return cur; - } - - return NULL; + BINARY_ARRAY_SEARCH(schema->attributes_by_linkID, + schema->num_attributes, linkID, linkID, uint32_cmp, c); + return c; } const struct dsdb_class *dsdb_class_by_governsID_id(const struct dsdb_schema *schema, uint32_t id) { - struct dsdb_class *cur; + struct dsdb_class *c; /* * 0xFFFFFFFF is used as value when no mapping table is available, @@ -104,65 +118,39 @@ const struct dsdb_class *dsdb_class_by_governsID_id(const struct dsdb_schema *sc */ 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; + BINARY_ARRAY_SEARCH(schema->classes_by_governsID_id, + schema->num_classes, governsID_id, id, uint32_cmp, c); + return c; } const struct dsdb_class *dsdb_class_by_governsID_oid(const struct dsdb_schema *schema, const char *oid) { - struct dsdb_class *cur; - + struct dsdb_class *c; 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; + BINARY_ARRAY_SEARCH(schema->classes_by_governsID_oid, + schema->num_classes, governsID_oid, oid, strcasecmp, c); + return c; } const struct dsdb_class *dsdb_class_by_lDAPDisplayName(const struct dsdb_schema *schema, const char *name) { - struct dsdb_class *cur; - + struct dsdb_class *c; 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; + BINARY_ARRAY_SEARCH(schema->classes_by_lDAPDisplayName, + schema->num_classes, lDAPDisplayName, name, strcasecmp, c); + return c; } const struct dsdb_class *dsdb_class_by_cn(const struct dsdb_schema *schema, const char *cn) { - struct dsdb_class *cur; - + struct dsdb_class *c; 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; + BINARY_ARRAY_SEARCH(schema->classes_by_cn, + schema->num_classes, cn, cn, strcasecmp, c); + return c; } const char *dsdb_lDAPDisplayName_by_id(const struct dsdb_schema *schema, @@ -171,7 +159,6 @@ const char *dsdb_lDAPDisplayName_by_id(const struct dsdb_schema *schema, 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; diff --git a/source4/dsdb/schema/schema_set.c b/source4/dsdb/schema/schema_set.c index 6abd8a8f88..dcaeb4fc89 100644 --- a/source4/dsdb/schema/schema_set.c +++ b/source4/dsdb/schema/schema_set.c @@ -26,6 +26,21 @@ #include "lib/ldb/include/ldb_module.h" #include "param/param.h" +/* + override the name to attribute handler function + */ +const struct ldb_schema_attribute *dsdb_attribute_handler_override(struct ldb_context *ldb, + void *private_data, + const char *name) +{ + struct dsdb_schema *schema = talloc_get_type_abort(private_data, struct dsdb_schema); + const struct dsdb_attribute *a = dsdb_attribute_by_lDAPDisplayName(schema, name); + if (a == NULL) { + /* this will fall back to ldb internal handling */ + return NULL; + } + return a->ldb_schema_attribute; +} static int dsdb_schema_set_attributes(struct ldb_context *ldb, struct dsdb_schema *schema, bool write_attributes) { @@ -34,11 +49,18 @@ static int dsdb_schema_set_attributes(struct ldb_context *ldb, struct dsdb_schem struct ldb_result *res_idx; struct dsdb_attribute *attr; struct ldb_message *mod_msg; - TALLOC_CTX *mem_ctx = talloc_new(ldb); - + TALLOC_CTX *mem_ctx; struct ldb_message *msg; struct ldb_message *msg_idx; + /* setup our own attribute name to schema handler */ + ldb_schema_attribute_set_override_handler(ldb, dsdb_attribute_handler_override, schema); + + if (!write_attributes) { + return ret; + } + + mem_ctx = talloc_new(ldb); if (!mem_ctx) { return LDB_ERR_OPERATIONS_ERROR; } @@ -46,27 +68,27 @@ static int dsdb_schema_set_attributes(struct ldb_context *ldb, struct dsdb_schem msg = ldb_msg_new(mem_ctx); if (!msg) { ldb_oom(ldb); - return LDB_ERR_OPERATIONS_ERROR; + goto op_error; } msg_idx = ldb_msg_new(mem_ctx); if (!msg_idx) { ldb_oom(ldb); - return LDB_ERR_OPERATIONS_ERROR; + goto op_error; } msg->dn = ldb_dn_new(msg, ldb, "@ATTRIBUTES"); if (!msg->dn) { ldb_oom(ldb); - return LDB_ERR_OPERATIONS_ERROR; + goto op_error; } msg_idx->dn = ldb_dn_new(msg, ldb, "@INDEXLIST"); if (!msg_idx->dn) { ldb_oom(ldb); - return LDB_ERR_OPERATIONS_ERROR; + goto op_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; } @@ -87,33 +109,13 @@ static int dsdb_schema_set_attributes(struct ldb_context *ldb, struct dsdb_schem break; } } - - 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) { - break; - } } - if (!write_attributes || ret != LDB_SUCCESS) { + if (ret != LDB_SUCCESS) { talloc_free(mem_ctx); return ret; } - /* Try to avoid churning the attributes too much - we only want to do this if they have changed */ ret = ldb_search(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) { @@ -165,8 +167,165 @@ static int dsdb_schema_set_attributes(struct ldb_context *ldb, struct dsdb_schem } talloc_free(mem_ctx); return ret; + +op_error: + talloc_free(mem_ctx); + return LDB_ERR_OPERATIONS_ERROR; } +static int dsdb_compare_class_by_lDAPDisplayName(struct dsdb_class **c1, struct dsdb_class **c2) +{ + return strcasecmp((*c1)->lDAPDisplayName, (*c2)->lDAPDisplayName); +} +static int dsdb_compare_class_by_governsID_id(struct dsdb_class **c1, struct dsdb_class **c2) +{ + return (*c1)->governsID_id - (*c2)->governsID_id; +} +static int dsdb_compare_class_by_governsID_oid(struct dsdb_class **c1, struct dsdb_class **c2) +{ + return strcasecmp((*c1)->governsID_oid, (*c2)->governsID_oid); +} +static int dsdb_compare_class_by_cn(struct dsdb_class **c1, struct dsdb_class **c2) +{ + return strcasecmp((*c1)->cn, (*c2)->cn); +} + +static int dsdb_compare_attribute_by_lDAPDisplayName(struct dsdb_attribute **a1, struct dsdb_attribute **a2) +{ + return strcasecmp((*a1)->lDAPDisplayName, (*a2)->lDAPDisplayName); +} +static int dsdb_compare_attribute_by_attributeID_id(struct dsdb_attribute **a1, struct dsdb_attribute **a2) +{ + return (*a1)->attributeID_id - (*a2)->attributeID_id; +} +static int dsdb_compare_attribute_by_attributeID_oid(struct dsdb_attribute **a1, struct dsdb_attribute **a2) +{ + return strcasecmp((*a1)->attributeID_oid, (*a2)->attributeID_oid); +} +static int dsdb_compare_attribute_by_linkID(struct dsdb_attribute **a1, struct dsdb_attribute **a2) +{ + return (*a1)->linkID - (*a2)->linkID; +} + +/* + create the sorted accessor arrays for the schema + */ +static int dsdb_setup_sorted_accessors(struct ldb_context *ldb, + struct dsdb_schema *schema) +{ + struct dsdb_class *cur; + struct dsdb_attribute *a; + uint32_t i; + + talloc_free(schema->classes_by_lDAPDisplayName); + talloc_free(schema->classes_by_governsID_id); + talloc_free(schema->classes_by_governsID_oid); + talloc_free(schema->classes_by_cn); + + /* count the classes */ + for (i=0, cur=schema->classes; cur; i++, cur=cur->next) /* noop */ ; + schema->num_classes = i; + + /* setup classes_by_* */ + schema->classes_by_lDAPDisplayName = talloc_array(schema, struct dsdb_class *, i); + schema->classes_by_governsID_id = talloc_array(schema, struct dsdb_class *, i); + schema->classes_by_governsID_oid = talloc_array(schema, struct dsdb_class *, i); + schema->classes_by_cn = talloc_array(schema, struct dsdb_class *, i); + if (schema->classes_by_lDAPDisplayName == NULL || + schema->classes_by_governsID_id == NULL || + schema->classes_by_governsID_oid == NULL || + schema->classes_by_cn == NULL) { + goto failed; + } + + for (i=0, cur=schema->classes; cur; i++, cur=cur->next) { + schema->classes_by_lDAPDisplayName[i] = cur; + schema->classes_by_governsID_id[i] = cur; + schema->classes_by_governsID_oid[i] = cur; + schema->classes_by_cn[i] = cur; + } + + /* sort the arrays */ + qsort(schema->classes_by_lDAPDisplayName, schema->num_classes, + sizeof(struct dsdb_class *), QSORT_CAST dsdb_compare_class_by_lDAPDisplayName); + qsort(schema->classes_by_governsID_id, schema->num_classes, + sizeof(struct dsdb_class *), QSORT_CAST dsdb_compare_class_by_governsID_id); + qsort(schema->classes_by_governsID_oid, schema->num_classes, + sizeof(struct dsdb_class *), QSORT_CAST dsdb_compare_class_by_governsID_oid); + qsort(schema->classes_by_cn, schema->num_classes, + sizeof(struct dsdb_class *), QSORT_CAST dsdb_compare_class_by_cn); + + /* now build the attribute accessor arrays */ + talloc_free(schema->attributes_by_lDAPDisplayName); + talloc_free(schema->attributes_by_attributeID_id); + talloc_free(schema->attributes_by_attributeID_oid); + talloc_free(schema->attributes_by_linkID); + + /* count the attributes */ + for (i=0, a=schema->attributes; a; i++, a=a->next) /* noop */ ; + schema->num_attributes = i; + + /* setup attributes_by_* */ + schema->attributes_by_lDAPDisplayName = talloc_array(schema, struct dsdb_attribute *, i); + schema->attributes_by_attributeID_id = talloc_array(schema, struct dsdb_attribute *, i); + schema->attributes_by_attributeID_oid = talloc_array(schema, struct dsdb_attribute *, i); + schema->attributes_by_linkID = talloc_array(schema, struct dsdb_attribute *, i); + if (schema->attributes_by_lDAPDisplayName == NULL || + schema->attributes_by_attributeID_id == NULL || + schema->attributes_by_attributeID_oid == NULL || + schema->attributes_by_linkID == NULL) { + goto failed; + } + + for (i=0, a=schema->attributes; a; i++, a=a->next) { + schema->attributes_by_lDAPDisplayName[i] = a; + schema->attributes_by_attributeID_id[i] = a; + schema->attributes_by_attributeID_oid[i] = a; + schema->attributes_by_linkID[i] = a; + } + + /* sort the arrays */ + qsort(schema->attributes_by_lDAPDisplayName, schema->num_attributes, + sizeof(struct dsdb_attribute *), QSORT_CAST dsdb_compare_attribute_by_lDAPDisplayName); + qsort(schema->attributes_by_attributeID_id, schema->num_attributes, + sizeof(struct dsdb_attribute *), QSORT_CAST dsdb_compare_attribute_by_attributeID_id); + qsort(schema->attributes_by_attributeID_oid, schema->num_attributes, + sizeof(struct dsdb_attribute *), QSORT_CAST dsdb_compare_attribute_by_attributeID_oid); + qsort(schema->attributes_by_linkID, schema->num_attributes, + sizeof(struct dsdb_attribute *), QSORT_CAST dsdb_compare_attribute_by_linkID); + + return LDB_SUCCESS; + +failed: + schema->classes_by_lDAPDisplayName = NULL; + schema->classes_by_governsID_id = NULL; + schema->classes_by_governsID_oid = NULL; + schema->classes_by_cn = NULL; + schema->attributes_by_lDAPDisplayName = NULL; + schema->attributes_by_attributeID_id = NULL; + schema->attributes_by_attributeID_oid = NULL; + schema->attributes_by_linkID = NULL; + ldb_oom(ldb); + return LDB_ERR_OPERATIONS_ERROR; +} + +int dsdb_setup_schema_inversion(struct ldb_context *ldb, struct dsdb_schema *schema) +{ + /* Walk the list of schema classes */ + + /* For each subClassOf, add us to subclasses of the parent */ + + /* collect these subclasses into a recursive list of total subclasses, preserving order */ + + /* For each subclass under 'top', write the index from it's + * order as an integer in the dsdb_class (for sorting + * objectClass lists efficiently) */ + + /* Walk the list of scheam classes */ + + /* Create a 'total possible superiors' on each class */ + return LDB_SUCCESS; +} /** * Attach the schema to an opaque pointer on the ldb, so ldb modules @@ -177,6 +336,13 @@ int dsdb_set_schema(struct ldb_context *ldb, struct dsdb_schema *schema) { int ret; + ret = dsdb_setup_sorted_accessors(ldb, schema); + if (ret != LDB_SUCCESS) { + return ret; + } + + schema_fill_constructed(schema); + ret = ldb_set_opaque(ldb, "dsdb_schema", schema); if (ret != LDB_SUCCESS) { return ret; @@ -207,6 +373,7 @@ int dsdb_set_global_schema(struct ldb_context *ldb) if (!global_schema) { return LDB_SUCCESS; } + ret = ldb_set_opaque(ldb, "dsdb_schema", global_schema); if (ret != LDB_SUCCESS) { return ret; @@ -277,7 +444,7 @@ void dsdb_make_schema_global(struct ldb_context *ldb) * schema itself to the directory. */ -WERROR dsdb_attach_schema_from_ldif_file(struct ldb_context *ldb, const char *pf, const char *df) +WERROR dsdb_attach_schema_from_ldif(struct ldb_context *ldb, const char *pf, const char *df) { struct ldb_ldif *ldif; struct ldb_message *msg; @@ -367,7 +534,7 @@ WERROR dsdb_attach_schema_from_ldif_file(struct ldb_context *ldb, const char *pf goto nomem; } - status = dsdb_attribute_from_ldb(schema, msg, sa, sa); + status = dsdb_attribute_from_ldb(ldb, schema, msg, sa, sa); if (!W_ERROR_IS_OK(status)) { goto failed; } diff --git a/source4/dsdb/schema/schema_syntax.c b/source4/dsdb/schema/schema_syntax.c index 27c9a6c4a4..4fd6501cc8 100644 --- a/source4/dsdb/schema/schema_syntax.c +++ b/source4/dsdb/schema/schema_syntax.c @@ -1227,7 +1227,7 @@ static WERROR dsdb_syntax_PRESENTATION_ADDRESS_ldb_to_drsuapi(struct ldb_context static const struct dsdb_syntax dsdb_syntaxes[] = { { .name = "Boolean", - .ldap_oid = "1.3.6.1.4.1.1466.115.121.1.7", + .ldap_oid = LDB_SYNTAX_BOOLEAN, .oMSyntax = 1, .attributeSyntax_oid = "2.5.5.8", .drsuapi_to_ldb = dsdb_syntax_BOOL_drsuapi_to_ldb, @@ -1289,7 +1289,8 @@ static const struct dsdb_syntax dsdb_syntaxes[] = { .ldb_to_drsuapi = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi, .equality = "numericStringMatch", .substring = "numericStringSubstringsMatch", - .comment = "Numeric String" + .comment = "Numeric String", + .ldb_syntax = LDB_SYNTAX_DIRECTORY_STRING, },{ .name = "String(Printable)", .ldap_oid = "1.3.6.1.4.1.1466.115.121.1.44", @@ -1297,6 +1298,7 @@ static const struct dsdb_syntax dsdb_syntaxes[] = { .attributeSyntax_oid = "2.5.5.5", .drsuapi_to_ldb = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb, .ldb_to_drsuapi = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi, + .ldb_syntax = LDB_SYNTAX_OCTET_STRING, },{ .name = "String(Teletex)", .ldap_oid = "1.2.840.113556.1.4.905", @@ -1316,7 +1318,8 @@ static const struct dsdb_syntax dsdb_syntaxes[] = { .drsuapi_to_ldb = dsdb_syntax_DATA_BLOB_drsuapi_to_ldb, .ldb_to_drsuapi = dsdb_syntax_DATA_BLOB_ldb_to_drsuapi, .equality = "caseExactIA5Match", - .comment = "Printable String" + .comment = "Printable String", + .ldb_syntax = LDB_SYNTAX_OCTET_STRING, },{ .name = "String(UTC-Time)", .ldap_oid = "1.3.6.1.4.1.1466.115.121.1.53", @@ -1423,7 +1426,8 @@ static const struct dsdb_syntax dsdb_syntaxes[] = { .attributeSyntax_oid = "2.5.5.13", .drsuapi_to_ldb = dsdb_syntax_PRESENTATION_ADDRESS_drsuapi_to_ldb, .ldb_to_drsuapi = dsdb_syntax_PRESENTATION_ADDRESS_ldb_to_drsuapi, - .comment = "Presentation Address" + .comment = "Presentation Address", + .ldb_syntax = LDB_SYNTAX_DIRECTORY_STRING, },{ /* not used in w2k3 schema */ .name = "Object(Access-Point)", @@ -1433,6 +1437,7 @@ static const struct dsdb_syntax dsdb_syntaxes[] = { .attributeSyntax_oid = "2.5.5.14", .drsuapi_to_ldb = dsdb_syntax_FOOBAR_drsuapi_to_ldb, .ldb_to_drsuapi = dsdb_syntax_FOOBAR_ldb_to_drsuapi, + .ldb_syntax = LDB_SYNTAX_DIRECTORY_STRING, },{ /* not used in w2k3 schema */ .name = "Object(DN-String)", |