s4:dsdb Don't allow creation of systemOnly objectclasses
[sfrench/samba-autobuild/.git] / source4 / dsdb / samdb / ldb_modules / objectclass.c
index ad14acbcf877ddc6dfc4f5ea7a947f7d30db0a47..b3d54612dde9a15ddc7fad3872dded1b6d4242d8 100644 (file)
@@ -138,7 +138,13 @@ static int objectclass_sort(struct ldb_module *module,
                if (!current->objectclass) {
                        ldb_asprintf_errstring(ldb, "objectclass %.*s is not a valid objectClass in schema", 
                                               (int)objectclass_element->values[i].length, (const char *)objectclass_element->values[i].data);
-                       return LDB_ERR_OBJECT_CLASS_VIOLATION;
+                       /* This looks weird, but windows apparently returns this for invalid objectClass values */
+                       return LDB_ERR_NO_SUCH_ATTRIBUTE;
+               } else if (current->objectclass->isDefunct) {
+                       ldb_asprintf_errstring(ldb, "objectclass %.*s marked as isDefunct objectClass in schema - not valid for new objects", 
+                                              (int)objectclass_element->values[i].length, (const char *)objectclass_element->values[i].data);
+                       /* This looks weird, but windows apparently returns this for invalid objectClass values */
+                       return LDB_ERR_NO_SUCH_ATTRIBUTE;
                }
 
                /* this is the root of the tree.  We will start
@@ -355,7 +361,8 @@ static int fix_attributes(struct ldb_context *ldb, const struct dsdb_schema *sch
                if (!attribute) {
                        if (strcasecmp(msg->elements[i].name, "clearTextPassword") != 0) {
                                ldb_asprintf_errstring(ldb, "attribute %s is not a valid attribute in schema", msg->elements[i].name);
-                               return LDB_ERR_UNDEFINED_ATTRIBUTE_TYPE;
+                               /* Apparently Windows sends exactly this behaviour */
+                               return LDB_ERR_NO_SUCH_ATTRIBUTE;
                        }
                } else {
                        msg->elements[i].name = attribute->lDAPDisplayName;
@@ -554,6 +561,12 @@ static int objectclass_do_add(struct oc_context *ac)
                                        return LDB_ERR_NAMING_VIOLATION;
                                }
 
+                               if (current->objectclass->systemOnly && !ldb_request_get_control(ac->req, LDB_CONTROL_RELAX_OID)) {
+                                       ldb_asprintf_errstring(ldb, "objectClass %s is systemOnly, rejecting creation of %s",
+                                                              current->objectclass->lDAPDisplayName, ldb_dn_get_linearized(msg->dn));
+                                       return LDB_ERR_UNWILLING_TO_PERFORM;
+                               }
+
                                if (!ldb_msg_find_element(msg, "objectCategory")) {
                                        value = talloc_strdup(msg, current->objectclass->defaultObjectCategory);
                                        if (value == NULL) {