diff options
-rw-r--r-- | source4/dsdb/samdb/ldb_modules/objectclass.c | 26 |
1 files changed, 26 insertions, 0 deletions
diff --git a/source4/dsdb/samdb/ldb_modules/objectclass.c b/source4/dsdb/samdb/ldb_modules/objectclass.c index e5769a63dd..4cbb1897fe 100644 --- a/source4/dsdb/samdb/ldb_modules/objectclass.c +++ b/source4/dsdb/samdb/ldb_modules/objectclass.c @@ -360,6 +360,8 @@ static int objectclass_add(struct ldb_module *module, struct ldb_request *req) struct ldb_request *search_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[] = { "objectGUID", "objectClass", NULL }; @@ -372,6 +374,30 @@ static int objectclass_add(struct ldb_module *module, struct ldb_request *req) return ldb_next_request(module, req); } + /* An add operation on the root basedn has a special handling when the + * relax control isn't specified. */ + if (ldb_dn_compare(ldb_get_root_basedn(ldb), req->op.add.message->dn) == 0) { + if (ldb_request_get_control(req, + LDB_CONTROL_RELAX_OID) == NULL) { + /* 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 + * component value as hostname. */ + val = ldb_dn_get_component_val(req->op.add.message->dn, + ldb_dn_get_comp_num(req->op.add.message->dn) - 1); + if (val == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + value = talloc_asprintf(req, "ldap://%s/%s", val->data, + ldb_dn_get_linearized(req->op.add.message->dn)); + if (value == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + + return ldb_module_send_referral(req, value); + } + } + /* the objectClass must be specified on add */ if (ldb_msg_find_element(req->op.add.message, "objectClass") == NULL) { |