{
struct ldb_context *ldb;
unsigned int i, lowest;
- struct class_list *unsorted = NULL, *sorted = NULL, *current = NULL, *poss_parent = NULL, *new_parent = NULL, *current_lowest = NULL;
+ struct class_list *unsorted = NULL, *sorted = NULL, *current = NULL,
+ *poss_parent = NULL, *new_parent = NULL,
+ *current_lowest = NULL, *current_lowest_struct = NULL;
ldb = ldb_module_get_ctx(module);
current->objectclass = dsdb_class_by_lDAPDisplayName(schema, "top");
DLIST_ADD_END(sorted, current, struct class_list *);
+ /* If we don't have a schema yet, then just merge the lists again */
+ if (!schema) {
+ DLIST_CONCATENATE(sorted, unsorted, struct class_list *);
+ *sorted_out = sorted;
+ return LDB_SUCCESS;
+ }
/* For each object: find parent chain */
- for (current = unsorted; schema && current; current = current->next) {
+ for (current = unsorted; current != NULL; current = current->next) {
for (poss_parent = unsorted; poss_parent; poss_parent = poss_parent->next) {
if (ldb_attr_cmp(poss_parent->objectclass->lDAPDisplayName, current->objectclass->subClassOf) == 0) {
break;
DLIST_ADD_END(unsorted, new_parent, struct class_list *);
}
- do
- {
+ /* For each object: order by hierarchy */
+ while (unsorted != NULL) {
lowest = UINT_MAX;
- current_lowest = NULL;
- for (current = unsorted; schema && current; current = current->next) {
- if(current->objectclass->subClass_order < lowest) {
- current_lowest = current;
+ current_lowest = current_lowest_struct = NULL;
+ for (current = unsorted; current != NULL; current = current->next) {
+ if (current->objectclass->subClass_order <= lowest) {
+ /*
+ * According to MS-ADTS 3.1.1.1.4 structural
+ * and 88 object classes are always listed after
+ * the other class types in a subclass hierarchy
+ */
+ if (current->objectclass->objectClassCategory > 1) {
+ current_lowest = current;
+ } else {
+ current_lowest_struct = current;
+ }
lowest = current->objectclass->subClass_order;
}
}
+ if (current_lowest == NULL) {
+ current_lowest = current_lowest_struct;
+ }
- if(current_lowest != NULL) {
+ if (current_lowest != NULL) {
DLIST_REMOVE(unsorted,current_lowest);
DLIST_ADD_END(sorted,current_lowest, struct class_list *);
}
- } while(unsorted);
-
-
- if (!unsorted) {
- *sorted_out = sorted;
- return LDB_SUCCESS;
- }
-
- if (!schema) {
- /* If we don't have schema yet, then just merge the lists again */
- DLIST_CONCATENATE(sorted, unsorted, struct class_list *);
- *sorted_out = sorted;
- return LDB_SUCCESS;
}
- /* This shouldn't happen, and would break MMC, perhaps there
- * was no 'top', a conflict in the objectClasses or some other
- * schema error?
- */
- ldb_asprintf_errstring(ldb, "objectclass %s is not a valid objectClass in objectClass chain", unsorted->objectclass->lDAPDisplayName);
- return LDB_ERR_OBJECT_CLASS_VIOLATION;
+ *sorted_out = sorted;
+ return LDB_SUCCESS;
}
/*
/* Make sure its valid to add an object of this type */
objectclass = get_last_structural_class(ac->schema,
- objectclass_element, ac->req);
+ objectclass_element,
+ true);
if(objectclass == NULL) {
ldb_asprintf_errstring(ldb,
"Failed to find a structural class for %s",
/* Get the new top-most structural object class */
objectclass = get_last_structural_class(ac->schema, oc_el_entry,
- ac->req);
+ false);
if (objectclass == NULL) {
ldb_set_errstring(ldb,
"objectclass: cannot delete all structural objectclasses!");
/* existing entry without a valid object class? */
return ldb_operr(ldb);
}
- objectclass = get_last_structural_class(ac->schema, oc_el_entry, ac->req);
+ objectclass = get_last_structural_class(ac->schema, oc_el_entry,
+ false);
if (objectclass == NULL) {
/* existing entry without a valid object class? */
return ldb_operr(ldb);