diff options
-rw-r--r-- | source4/dsdb/schema/schema.h | 5 | ||||
-rw-r--r-- | source4/dsdb/schema/schema_init.c | 72 | ||||
-rw-r--r-- | source4/dsdb/schema/schema_set.c | 46 |
3 files changed, 113 insertions, 10 deletions
diff --git a/source4/dsdb/schema/schema.h b/source4/dsdb/schema/schema.h index 66df1c5f75..538b858123 100644 --- a/source4/dsdb/schema/schema.h +++ b/source4/dsdb/schema/schema.h @@ -221,6 +221,11 @@ struct dsdb_schema { struct dsdb_attribute *attributes; struct dsdb_class *classes; + struct dsdb_attribute **attributes_to_remove; + uint32_t attributes_to_remove_size; + struct dsdb_class **classes_to_remove; + uint32_t classes_to_remove_size; + /* lists of classes sorted by various attributes, for faster access */ uint32_t num_classes; diff --git a/source4/dsdb/schema/schema_init.c b/source4/dsdb/schema/schema_init.c index 752d4f57dd..efbd38a4ba 100644 --- a/source4/dsdb/schema/schema_init.c +++ b/source4/dsdb/schema/schema_init.c @@ -699,9 +699,10 @@ WERROR dsdb_attribute_from_ldb(const struct dsdb_schema *schema, return WERR_OK; } -WERROR dsdb_set_attribute_from_ldb(struct ldb_context *ldb, - struct dsdb_schema *schema, - struct ldb_message *msg) +WERROR dsdb_set_attribute_from_ldb_dups(struct ldb_context *ldb, + struct dsdb_schema *schema, + struct ldb_message *msg, + bool checkdups) { WERROR status; struct dsdb_attribute *attr = talloc_zero(schema, struct dsdb_attribute); @@ -729,12 +730,44 @@ WERROR dsdb_set_attribute_from_ldb(struct ldb_context *ldb, return WERR_DS_ATT_SCHEMA_REQ_SYNTAX; } + if (checkdups) { + const struct dsdb_attribute *a2; + struct dsdb_attribute **a; + uint32_t i; + + a2 = dsdb_attribute_by_attributeID_id(schema, + attr->attributeID_id); + if (a2 == NULL) { + goto done; + } + + i = schema->attributes_to_remove_size; + a = talloc_realloc(schema, schema->attributes_to_remove, + struct dsdb_attribute *, i + 1); + if (a == NULL) { + return WERR_NOMEM; + } + /* Mark the old attribute as to be removed */ + a[i] = discard_const_p(struct dsdb_attribute, a2); + schema->attributes_to_remove = a; + schema->attributes_to_remove_size++; + } + +done: DLIST_ADD(schema->attributes, attr); return WERR_OK; } -WERROR dsdb_set_class_from_ldb(struct dsdb_schema *schema, - struct ldb_message *msg) +WERROR dsdb_set_attribute_from_ldb(struct ldb_context *ldb, + struct dsdb_schema *schema, + struct ldb_message *msg) +{ + return dsdb_set_attribute_from_ldb_dups(ldb, schema, msg, false); +} + +WERROR dsdb_set_class_from_ldb_dups(struct dsdb_schema *schema, + struct ldb_message *msg, + bool checkdups) { WERROR status; struct dsdb_class *obj = talloc_zero(schema, struct dsdb_class); @@ -792,10 +825,39 @@ WERROR dsdb_set_class_from_ldb(struct dsdb_schema *schema, GET_BOOL_LDB(msg, "isDefunct", obj, isDefunct, false); GET_BOOL_LDB(msg, "systemOnly", obj, systemOnly, false); + if (checkdups) { + const struct dsdb_class *c2; + struct dsdb_class **c; + uint32_t i; + + c2 = dsdb_class_by_governsID_id(schema, obj->governsID_id); + if (c2 == NULL) { + goto done; + } + + i = schema->classes_to_remove_size; + c = talloc_realloc(schema, schema->classes_to_remove, + struct dsdb_class *, i + 1); + if (c == NULL) { + return WERR_NOMEM; + } + /* Mark the old class to be removed */ + c[i] = discard_const_p(struct dsdb_class, c2); + schema->classes_to_remove = c; + schema->classes_to_remove_size++; + } + +done: DLIST_ADD(schema->classes, obj); return WERR_OK; } +WERROR dsdb_set_class_from_ldb(struct dsdb_schema *schema, + struct ldb_message *msg) +{ + return dsdb_set_class_from_ldb_dups(schema, msg, false); +} + #define dsdb_oom(error_string, mem_ctx) *error_string = talloc_asprintf(mem_ctx, "dsdb out of memory at %s:%d\n", __FILE__, __LINE__) /* diff --git a/source4/dsdb/schema/schema_set.c b/source4/dsdb/schema/schema_set.c index 31862a43b7..73264f9545 100644 --- a/source4/dsdb/schema/schema_set.c +++ b/source4/dsdb/schema/schema_set.c @@ -329,6 +329,18 @@ int dsdb_setup_sorted_accessors(struct ldb_context *ldb, unsigned int num_int_id; int ret; + for (i=0; i < schema->classes_to_remove_size; i++) { + DLIST_REMOVE(schema->classes, schema->classes_to_remove[i]); + TALLOC_FREE(schema->classes_to_remove[i]); + } + for (i=0; i < schema->attributes_to_remove_size; i++) { + DLIST_REMOVE(schema->attributes, schema->attributes_to_remove[i]); + TALLOC_FREE(schema->attributes_to_remove[i]); + } + + TALLOC_FREE(schema->attributes_to_remove); + TALLOC_FREE(schema->classes_to_remove); + /* free all caches */ dsdb_sorted_accessors_free(schema); @@ -669,10 +681,26 @@ int dsdb_schema_fill_extended_dn(struct ldb_context *ldb, struct dsdb_schema *sc } /** - * Add an element to the schema (attribute or class) from an LDB message + * @brief Add a new element to the schema and checks if it's a duplicate + * + * This function will add a new element to the schema and checks for existing + * duplicates. + * + * @param[in] ldb A pointer to an LDB context + * + * @param[in] schema A pointer to the dsdb_schema where the element + * will be added. + * + * @param[in] msg The ldb_message object representing the element + * to add. + * + * @param[in] checkdups A boolean to indicate if checks for duplicates + * should be done. + * + * @return A WERROR code */ -WERROR dsdb_schema_set_el_from_ldb_msg(struct ldb_context *ldb, struct dsdb_schema *schema, - struct ldb_message *msg) +WERROR dsdb_schema_set_el_from_ldb_msg_dups(struct ldb_context *ldb, struct dsdb_schema *schema, + struct ldb_message *msg, bool checkdups) { const char* tstring; time_t ts; @@ -686,15 +714,23 @@ WERROR dsdb_schema_set_el_from_ldb_msg(struct ldb_context *ldb, struct dsdb_sche } if (samdb_find_attribute(ldb, msg, "objectclass", "attributeSchema") != NULL) { - return dsdb_set_attribute_from_ldb(ldb, schema, msg); + + return dsdb_set_attribute_from_ldb_dups(ldb, schema, msg, checkdups); } else if (samdb_find_attribute(ldb, msg, "objectclass", "classSchema") != NULL) { - return dsdb_set_class_from_ldb(schema, msg); + return dsdb_set_class_from_ldb_dups(schema, msg, checkdups); } /* Don't fail on things not classes or attributes */ return WERR_OK; } +WERROR dsdb_schema_set_el_from_ldb_msg(struct ldb_context *ldb, + struct dsdb_schema *schema, + struct ldb_message *msg) +{ + return dsdb_schema_set_el_from_ldb_msg_dups(ldb, schema, msg, false); +} + /** * Rather than read a schema from the LDB itself, read it from an ldif * file. This allows schema to be loaded and used while adding the |