Fix some types
[kai/samba-autobuild/.git] / source4 / dsdb / samdb / ldb_modules / objectclass.c
index e863d481a0bef629af15a44dd7689d8c053293fb..f48917c5fd7e51bc4233712f2a556e6b96912cda 100644 (file)
@@ -319,14 +319,18 @@ static int fix_dn(struct ldb_context *ldb,
        char *upper_rdn_attr;
        const struct ldb_val *rdn_val;
 
-       /* Fix up the DN to be in the standard form, taking particular care to match the parent DN */
+       /* Fix up the DN to be in the standard form, taking particular care to
+        * match the parent DN */
        *fixed_dn = ldb_dn_copy(mem_ctx, parent_dn);
+       if (*fixed_dn == NULL) {
+               return ldb_oom(ldb);
+       }
 
        /* We need the attribute name in upper case */
        upper_rdn_attr = strupper_talloc(*fixed_dn, 
                                         ldb_dn_get_rdn_name(newdn));
-       if (!upper_rdn_attr) {
-               return ldb_operr(ldb);
+       if (upper_rdn_attr == NULL) {
+               return ldb_oom(ldb);
        }
 
        /* Create a new child */
@@ -364,7 +368,6 @@ static int objectclass_add(struct ldb_module *module, struct ldb_request *req)
        struct oc_context *ac;
        struct ldb_dn *parent_dn;
        const struct ldb_val *val;
-       char *value;
        int ret;
        static const char * const parent_attrs[] = { "objectClass", NULL };
 
@@ -385,6 +388,7 @@ static int objectclass_add(struct ldb_module *module, struct ldb_request *req)
                instanceType = ldb_msg_find_attr_as_uint(req->op.add.message,
                                                         "instanceType", 0);
                if (!(instanceType & INSTANCE_TYPE_IS_NC_HEAD)) {
+                       char *referral_uri;
                        /* When we are trying to readd the root basedn then
                         * this is denied, but with an interesting mechanism:
                         * there is generated a referral with the last
@@ -394,13 +398,13 @@ static int objectclass_add(struct ldb_module *module, struct ldb_request *req)
                        if (val == NULL) {
                                return ldb_operr(ldb);
                        }
-                       value = talloc_asprintf(req, "ldap://%s/%s", val->data,
-                                               ldb_dn_get_linearized(req->op.add.message->dn));
-                       if (value == NULL) {
-                               return ldb_oom(ldb);
+                       referral_uri = talloc_asprintf(req, "ldap://%s/%s", val->data,
+                                                      ldb_dn_get_linearized(req->op.add.message->dn));
+                       if (referral_uri == NULL) {
+                               return ldb_module_oom(module);
                        }
 
-                       return ldb_module_send_referral(req, value);
+                       return ldb_module_send_referral(req, referral_uri);
                }
        }
 
@@ -417,7 +421,7 @@ static int objectclass_add(struct ldb_module *module, struct ldb_request *req)
        /* get copy of parent DN */
        parent_dn = ldb_dn_get_parent(ac, ac->req->op.add.message->dn);
        if (parent_dn == NULL) {
-               return ldb_oom(ldb);
+               return ldb_operr(ldb);
        }
 
        ret = ldb_build_search_req(&search_req, ldb,
@@ -459,7 +463,7 @@ static bool check_rodc_ntdsdsa_add(struct oc_context *ac,
 
 static int objectclass_do_add(struct oc_context *ac)
 {
-       struct ldb_context *ldb;
+       struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
        struct ldb_request *add_req;
        struct ldb_message_element *objectclass_element, *el;
        struct ldb_message *msg;
@@ -474,9 +478,10 @@ static int objectclass_do_add(struct oc_context *ac)
        bool found;
        int ret;
 
-       ldb = ldb_module_get_ctx(ac->module);
-
        msg = ldb_msg_copy_shallow(ac, ac->req->op.add.message);
+       if (msg == NULL) {
+               return ldb_module_oom(ac->module);
+       }
 
        /* Check if we have a valid parent - this check is needed since
         * we don't get a LDB_ERR_NO_SUCH_OBJECT error. */
@@ -485,8 +490,8 @@ static int objectclass_do_add(struct oc_context *ac)
 
                /* An add operation on partition DNs without "NC-add" operation
                 * isn't allowed. */
-               instanceType = ldb_msg_find_attr_as_uint(ac->req->op.add.message,
-                                                        "instanceType", 0);
+               instanceType = ldb_msg_find_attr_as_uint(msg, "instanceType",
+                                                        0);
                if (!(instanceType & INSTANCE_TYPE_IS_NC_HEAD)) {
                        ldb_asprintf_errstring(ldb, "objectclass: Cannot add %s, parent does not exist!", 
                                               ldb_dn_get_linearized(msg->dn));
@@ -509,26 +514,24 @@ static int objectclass_do_add(struct oc_context *ac)
                }
        }
 
-       mem_ctx = talloc_new(ac);
-       if (mem_ctx == NULL) {
-               return ldb_oom(ldb);
-       }
-
        if (ac->schema != NULL) {
                objectclass_element = ldb_msg_find_element(msg, "objectClass");
                if (!objectclass_element) {
                        ldb_asprintf_errstring(ldb, "objectclass: Cannot add %s, no objectclass specified!",
                                               ldb_dn_get_linearized(msg->dn));
-                       talloc_free(mem_ctx);
                        return LDB_ERR_OBJECT_CLASS_VIOLATION;
                }
                if (objectclass_element->num_values == 0) {
                        ldb_asprintf_errstring(ldb, "objectclass: Cannot add %s, at least one (structural) objectclass has to be specified!",
                                               ldb_dn_get_linearized(msg->dn));
-                       talloc_free(mem_ctx);
                        return LDB_ERR_CONSTRAINT_VIOLATION;
                }
 
+               mem_ctx = talloc_new(ac);
+               if (mem_ctx == NULL) {
+                       return ldb_module_oom(ac->module);
+               }
+
                /* Here we do now get the "objectClass" list from the
                 * database. */
                ret = objectclass_sort(ac->module, ac->schema, mem_ctx,
@@ -560,13 +563,9 @@ static int objectclass_do_add(struct oc_context *ac)
 
                /* Move from the linked list back into an ldb msg */
                for (current = sorted; current; current = current->next) {
-                       value = talloc_strdup(msg, current->objectclass->lDAPDisplayName);
-                       if (value == NULL) {
-                               talloc_free(mem_ctx);
-                               return ldb_oom(ldb);
-                       }
+                       const char *objectclass_name = current->objectclass->lDAPDisplayName;
 
-                       ret = ldb_msg_add_string(msg, "objectClass", value);
+                       ret = ldb_msg_add_string(msg, "objectClass", objectclass_name);
                        if (ret != LDB_SUCCESS) {
                                ldb_set_errstring(ldb,
                                                  "objectclass: could not re-add sorted "
@@ -583,7 +582,7 @@ static int objectclass_do_add(struct oc_context *ac)
 
                /* Make sure its valid to add an object of this type */
                objectclass = get_last_structural_class(ac->schema,
-                                                       objectclass_element);
+                                                       objectclass_element, ac->req);
                if(objectclass == NULL) {
                        ldb_asprintf_errstring(ldb,
                                               "Failed to find a structural class for %s",
@@ -617,16 +616,10 @@ static int objectclass_do_add(struct oc_context *ac)
                if (objectclass->systemOnly &&
                    !ldb_request_get_control(ac->req, LDB_CONTROL_RELAX_OID) &&
                    !check_rodc_ntdsdsa_add(ac, objectclass)) {
-                       ldb_asprintf_errstring(ldb, "objectClass %s is systemOnly, rejecting creation of %s",
-                                               objectclass->lDAPDisplayName, ldb_dn_get_linearized(msg->dn));
-                       return LDB_ERR_UNWILLING_TO_PERFORM;
-               }
-
-               if (((strcmp(objectclass->lDAPDisplayName, "secret") == 0) ||
-                    (strcmp(objectclass->lDAPDisplayName, "trustedDomain") == 0)) &&
-                    !ldb_request_get_control(ac->req, LDB_CONTROL_RELAX_OID)) {
-                       ldb_asprintf_errstring(ldb, "objectClass %s is LSA-specific, rejecting creation of %s",
-                                               objectclass->lDAPDisplayName, ldb_dn_get_linearized(msg->dn));
+                       ldb_asprintf_errstring(ldb,
+                                              "objectclass: object class '%s' is system-only, rejecting creation of '%s'!",
+                                              objectclass->lDAPDisplayName,
+                                              ldb_dn_get_linearized(msg->dn));
                        return LDB_ERR_UNWILLING_TO_PERFORM;
                }
 
@@ -676,7 +669,7 @@ static int objectclass_do_add(struct oc_context *ac)
                                                      objectclass->defaultObjectCategory);
                        }
                        if (value == NULL) {
-                               return ldb_oom(ldb);
+                               return ldb_module_oom(ac->module);
                        }
 
                        ret = ldb_msg_add_string(msg, "objectCategory", value);
@@ -829,7 +822,7 @@ static int objectclass_modify(struct ldb_module *module, struct ldb_request *req
 
        msg = ldb_msg_copy_shallow(ac, req->op.mod.message);
        if (msg == NULL) {
-               return ldb_operr(ldb);
+               return ldb_module_oom(ac->module);
        }
 
        /* For now change everything except the objectclasses */
@@ -840,6 +833,29 @@ static int objectclass_modify(struct ldb_module *module, struct ldb_request *req
                oc_changes = true;
        }
 
+       /* MS-ADTS 3.1.1.5.3.5 - on a forest level < 2003 we do allow updates
+        * only on application NCs - not on the standard DCs */
+       if (oc_changes &&
+           (dsdb_forest_functional_level(ldb) < DS_DOMAIN_FUNCTION_2003)) {
+               struct ldb_dn *nc_root;
+
+               ret = dsdb_find_nc_root(ldb, ac, req->op.mod.message->dn,
+                                       &nc_root);
+               if (ret != LDB_SUCCESS) {
+                       return ret;
+               }
+
+               if ((ldb_dn_compare(nc_root, ldb_get_default_basedn(ldb)) == 0) ||
+                   (ldb_dn_compare(nc_root, ldb_get_config_basedn(ldb)) == 0) ||
+                   (ldb_dn_compare(nc_root, ldb_get_schema_basedn(ldb)) == 0)) {
+                       ldb_set_errstring(ldb,
+                                         "objectclass: object class changes on objects under the standard name contexts not allowed!");
+                       return LDB_ERR_UNWILLING_TO_PERFORM;
+               }
+
+               talloc_free(nc_root);
+       }
+
        ret = ldb_build_mod_req(&down_req, ldb, ac,
                                msg,
                                req->controls, ac,
@@ -887,7 +903,7 @@ static int oc_modify_callback(struct ldb_request *req, struct ldb_reply *ares)
        talloc_free(ares);
 
        /* this looks up the real existing object for fetching some important
-        * informations (objectclasses) */
+        * information (objectclasses) */
        ret = ldb_build_search_req(&search_req, ldb,
                                   ac, ac->req->op.mod.message->dn,
                                   LDB_SCOPE_BASE,
@@ -942,14 +958,14 @@ static int objectclass_do_mod(struct oc_context *ac)
        /* use a new message structure */
        msg = ldb_msg_new(ac);
        if (msg == NULL) {
-               return ldb_oom(ldb);
+               return ldb_module_oom(ac->module);
        }
 
        msg->dn = ac->req->op.mod.message->dn;
 
        mem_ctx = talloc_new(ac);
        if (mem_ctx == NULL) {
-               return ldb_oom(ldb);
+               return ldb_module_oom(ac->module);
        }
 
        /* We've to walk over all "objectClass" message elements */
@@ -983,7 +999,7 @@ static int objectclass_do_mod(struct oc_context *ac)
                                                      oc_el_entry->num_values + 1);
                                if (vals == NULL) {
                                        talloc_free(mem_ctx);
-                                       return ldb_oom(ldb);
+                                       return ldb_module_oom(ac->module);
                                }
                                oc_el_entry->values = vals;
                                oc_el_entry->values[oc_el_entry->num_values] =
@@ -992,7 +1008,7 @@ static int objectclass_do_mod(struct oc_context *ac)
                        }
 
                        objectclass = get_last_structural_class(ac->schema,
-                                                               oc_el_change);
+                                                               oc_el_change, ac->req);
                        if (objectclass != NULL) {
                                ldb_asprintf_errstring(ldb,
                                                       "objectclass: cannot add a new top-most structural objectclass '%s'!",
@@ -1028,8 +1044,9 @@ static int objectclass_do_mod(struct oc_context *ac)
                case LDB_FLAG_MOD_DELETE:
                        /* get the actual top-most structural objectclass */
                        objectclass = get_last_structural_class(ac->schema,
-                                                               oc_el_entry);
+                                                               oc_el_entry, ac->req);
                        if (objectclass == NULL) {
+                               /* no structural objectclass? */
                                talloc_free(mem_ctx);
                                return ldb_operr(ldb);
                        }
@@ -1101,7 +1118,7 @@ static int objectclass_do_mod(struct oc_context *ac)
                                        LDB_FLAG_MOD_REPLACE, &oc_el_change);
                if (ret != LDB_SUCCESS) {
                        talloc_free(mem_ctx);
-                       return ldb_oom(ldb);
+                       return ret;
                }
 
                /* Move from the linked list back into an ldb msg */
@@ -1110,7 +1127,7 @@ static int objectclass_do_mod(struct oc_context *ac)
                                              current->objectclass->lDAPDisplayName);
                        if (value == NULL) {
                                talloc_free(mem_ctx);
-                               return ldb_oom(ldb);
+                               return ldb_module_oom(ac->module);
                        }
                        ret = ldb_msg_add_string(msg, "objectClass", value);
                        if (ret != LDB_SUCCESS) {
@@ -1186,7 +1203,7 @@ static int objectclass_rename(struct ldb_module *module, struct ldb_request *req
        ldb_debug(ldb, LDB_DEBUG_TRACE, "objectclass_rename\n");
 
        /* do not manipulate our control entries */
-       if (ldb_dn_is_special(req->op.rename.newdn)) {
+       if (ldb_dn_is_special(req->op.rename.olddn)) {
                return ldb_next_request(module, req);
        }
 
@@ -1203,7 +1220,7 @@ static int objectclass_rename(struct ldb_module *module, struct ldb_request *req
        }
 
        /* this looks up the parent object for fetching some important
-        * informations (objectclasses, DN normalisation...) */
+        * information (objectclasses, DN normalisation...) */
        ret = ldb_build_search_req(&search_req, ldb,
                                   ac, parent_dn, LDB_SCOPE_BASE,
                                   "(objectClass=*)",
@@ -1255,7 +1272,7 @@ static int objectclass_do_rename(struct oc_context *ac)
        ac->search_res = NULL;
 
        /* this looks up the real existing object for fetching some important
-        * informations (objectclasses) */
+        * information (objectclasses) */
        ret = ldb_build_search_req(&search_req, ldb,
                                   ac, ac->req->op.rename.olddn,
                                   LDB_SCOPE_BASE,
@@ -1304,7 +1321,7 @@ static int objectclass_do_rename2(struct oc_context *ac)
                        /* existing entry without a valid object class? */
                        return ldb_operr(ldb);
                }
-               objectclass = get_last_structural_class(ac->schema, oc_el_entry);
+               objectclass = get_last_structural_class(ac->schema, oc_el_entry, ac->req);
                if (objectclass == NULL) {
                        /* existing entry without a valid object class? */
                        return ldb_operr(ldb);
@@ -1434,7 +1451,7 @@ static int objectclass_delete(struct ldb_module *module, struct ldb_request *req
        }
 
        /* this looks up the entry object for fetching some important
-        * informations (object classes, system flags...) */
+        * information (object classes, system flags...) */
        ret = ldb_build_search_req(&search_req, ldb,
                                   ac, req->op.del.dn, LDB_SCOPE_BASE,
                                   "(objectClass=*)",