summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source4/dsdb/schema/schema.h5
-rw-r--r--source4/dsdb/schema/schema_init.c72
-rw-r--r--source4/dsdb/schema/schema_set.c46
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