summaryrefslogtreecommitdiff
path: root/source4/dsdb
diff options
context:
space:
mode:
authorMatthieu Patou <mat@matws.net>2013-01-26 23:42:10 -0800
committerAndrew Bartlett <abartlet@samba.org>2013-05-23 20:26:07 +1000
commitfe85bc1fb9ab2f891a9fd46bd8e00325622d39cf (patch)
treea0e2d5cebb75470477e36ff356a727519809b055 /source4/dsdb
parentc524be17815e92ce9fcdd0565e76b026e483cc9d (diff)
downloadsamba-fe85bc1fb9ab2f891a9fd46bd8e00325622d39cf.tar.gz
samba-fe85bc1fb9ab2f891a9fd46bd8e00325622d39cf.tar.bz2
samba-fe85bc1fb9ab2f891a9fd46bd8e00325622d39cf.zip
dsdb-schema: make deduplication of class and schema possible (bug #8680)
When a class or an attribute is replicated it might already exists in the existing schema, so while replicating the new version of this object we want to get rid of the old version of the object is the current validating schema so that we don't end up having duplicates. Pair-Programmed-With: Stefan Metzmacher <metze@samba.org> Signed-off-by: Matthieu Patou <mat@matws.net> Signed-off-by: Stefan Metzmacher <metze@samba.org> Reviewed-by: Andrew Bartlett <abartlet@samba.org>
Diffstat (limited to 'source4/dsdb')
-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