s4-dsdb: change samdb_replace() to dsdb_replace() and allow for dsdb_flags
[ira/wip.git] / source4 / dsdb / schema / schema_set.c
index ab870741cfd45ae3d4ff6a16d8b51379dc8ee743..3dace043042102e844fdf8b6fd1ca0676a35a045 100644 (file)
@@ -25,6 +25,9 @@
 #include "dsdb/samdb/samdb.h"
 #include "lib/ldb/include/ldb_module.h"
 #include "param/param.h"
+#include "librpc/ndr/libndr.h"
+#include "librpc/gen_ndr/ndr_misc.h"
+#include "lib/util/tsort.h"
 
 /*
   override the name to attribute handler function
@@ -135,7 +138,7 @@ static int dsdb_schema_set_attributes(struct ldb_context *ldb, struct dsdb_schem
                
                mod_msg = ldb_msg_diff(ldb, res->msgs[0], msg);
                if (mod_msg->num_elements > 0) {
-                       ret = samdb_replace(ldb, mem_ctx, mod_msg);
+                       ret = dsdb_replace(ldb, mod_msg, 0);
                }
        }
 
@@ -163,7 +166,7 @@ static int dsdb_schema_set_attributes(struct ldb_context *ldb, struct dsdb_schem
 
                mod_msg = ldb_msg_diff(ldb, res_idx->msgs[0], msg_idx);
                if (mod_msg->num_elements > 0) {
-                       ret = samdb_replace(ldb, mem_ctx, mod_msg);
+                       ret = dsdb_replace(ldb, mod_msg, 0);
                }
        }
        if (ret == LDB_ERR_OPERATIONS_ERROR || ret == LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS || ret == LDB_ERR_INVALID_DN_SYNTAX) {
@@ -178,13 +181,19 @@ op_error:
        return LDB_ERR_OPERATIONS_ERROR;
 }
 
+static int uint32_cmp(uint32_t c1, uint32_t c2)
+{
+       if (c1 == c2) return 0;
+       return c1 > c2 ? 1 : -1;
+}
+
 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;
+       return uint32_cmp((*c1)->governsID_id, (*c2)->governsID_id);
 }
 static int dsdb_compare_class_by_governsID_oid(struct dsdb_class **c1, struct dsdb_class **c2)
 {
@@ -201,7 +210,7 @@ static int dsdb_compare_attribute_by_lDAPDisplayName(struct dsdb_attribute **a1,
 }
 static int dsdb_compare_attribute_by_attributeID_id(struct dsdb_attribute **a1, struct dsdb_attribute **a2)
 {
-       return (*a1)->attributeID_id - (*a2)->attributeID_id;
+       return uint32_cmp((*a1)->attributeID_id, (*a2)->attributeID_id);
 }
 static int dsdb_compare_attribute_by_attributeID_oid(struct dsdb_attribute **a1, struct dsdb_attribute **a2)
 {
@@ -209,7 +218,7 @@ static int dsdb_compare_attribute_by_attributeID_oid(struct dsdb_attribute **a1,
 }
 static int dsdb_compare_attribute_by_linkID(struct dsdb_attribute **a1, struct dsdb_attribute **a2)
 {
-       return (*a1)->linkID - (*a2)->linkID;
+       return uint32_cmp((*a1)->linkID, (*a2)->linkID);
 }
 
 /*
@@ -251,14 +260,10 @@ static int dsdb_setup_sorted_accessors(struct ldb_context *ldb,
        }
 
        /* 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);
+       TYPESAFE_QSORT(schema->classes_by_lDAPDisplayName, schema->num_classes, dsdb_compare_class_by_lDAPDisplayName);
+       TYPESAFE_QSORT(schema->classes_by_governsID_id, schema->num_classes, dsdb_compare_class_by_governsID_id);
+       TYPESAFE_QSORT(schema->classes_by_governsID_oid, schema->num_classes, dsdb_compare_class_by_governsID_oid);
+       TYPESAFE_QSORT(schema->classes_by_cn, schema->num_classes, dsdb_compare_class_by_cn);
 
        /* now build the attribute accessor arrays */
        talloc_free(schema->attributes_by_lDAPDisplayName);
@@ -290,14 +295,10 @@ static int dsdb_setup_sorted_accessors(struct ldb_context *ldb,
        }
 
        /* 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);
+       TYPESAFE_QSORT(schema->attributes_by_lDAPDisplayName, schema->num_attributes, dsdb_compare_attribute_by_lDAPDisplayName);
+       TYPESAFE_QSORT(schema->attributes_by_attributeID_id, schema->num_attributes, dsdb_compare_attribute_by_attributeID_id);
+       TYPESAFE_QSORT(schema->attributes_by_attributeID_oid, schema->num_attributes, dsdb_compare_attribute_by_attributeID_oid);
+       TYPESAFE_QSORT(schema->attributes_by_linkID, schema->num_attributes, dsdb_compare_attribute_by_linkID);
 
        return LDB_SUCCESS;
 
@@ -456,6 +457,47 @@ void dsdb_make_schema_global(struct ldb_context *ldb)
        dsdb_set_global_schema(ldb);
 }
 
+/* When loading the schema from LDIF files, we don't get the extended DNs. 
+   
+   We need to set these up, so that from the moment we start the provision, the defaultObjectCategory links are set up correctly. 
+ */
+int dsdb_schema_fill_extended_dn(struct ldb_context *ldb, struct dsdb_schema *schema)
+{
+       struct dsdb_class *cur;
+       const struct dsdb_class *target_class;
+       for (cur = schema->classes; cur; cur = cur->next) {
+               const struct ldb_val *rdn;
+               struct ldb_val guid;
+               NTSTATUS status;
+               struct ldb_dn *dn = ldb_dn_new(NULL, ldb, cur->defaultObjectCategory);
+
+               if (!dn) {
+                       return LDB_ERR_INVALID_DN_SYNTAX;
+               }
+               rdn = ldb_dn_get_component_val(dn, 0);
+               if (!rdn) {
+                       talloc_free(dn);
+                       return LDB_ERR_INVALID_DN_SYNTAX;
+               }
+               target_class = dsdb_class_by_cn_ldb_val(schema, rdn);
+               if (!target_class) {
+                       talloc_free(dn);
+                       return LDB_ERR_CONSTRAINT_VIOLATION;
+               }
+               
+               status = GUID_to_ndr_blob(&target_class->objectGUID, dn, &guid);
+               if (!NT_STATUS_IS_OK(status)) {
+                       talloc_free(dn);
+                       return LDB_ERR_OPERATIONS_ERROR;
+               }
+               ldb_dn_set_extended_component(dn, "GUID", &guid);
+
+               cur->defaultObjectCategory = ldb_dn_get_extended_linearized(cur, dn, 1);
+               talloc_free(dn);
+       }
+       return LDB_SUCCESS;
+}
+
 /** 
  * Add an element to the schema (attribute or class) from an LDB message
  */
@@ -580,6 +622,12 @@ WERROR dsdb_set_schema_from_ldif(struct ldb_context *ldb, const char *pf, const
                goto failed;
        }
 
+       ret = dsdb_schema_fill_extended_dn(ldb, schema);
+       if (ret != LDB_SUCCESS) {
+               status = WERR_FOOBAR;
+               goto failed;
+       }
+
        goto done;
 
 nomem: