#include "librpc/gen_ndr/ndr_security.h"
#include "libcli/security/security.h"
#include "auth/auth.h"
+#include "param/param.h"
struct oc_context {
const struct dsdb_class *objectclass;
};
+static int objectclass_do_add(struct ldb_handle *h);
+
static struct ldb_handle *oc_init_handle(struct ldb_request *req, struct ldb_module *module)
{
struct oc_context *ac;
static DATA_BLOB *get_sd(struct ldb_module *module, TALLOC_CTX *mem_ctx,
const struct dsdb_class *objectclass)
{
- NTSTATUS status;
+ enum ndr_err_code ndr_err;
DATA_BLOB *linear_sd;
struct auth_session_info *session_info
= ldb_get_opaque(module->ldb, "sessionInfo");
return NULL;
}
- status = ndr_push_struct_blob(linear_sd, mem_ctx, sd,
- (ndr_push_flags_fn_t)ndr_push_security_descriptor);
-
- if (!NT_STATUS_IS_OK(status)) {
+ ndr_err = ndr_push_struct_blob(linear_sd, mem_ctx,
+ lp_iconv_convenience(ldb_get_opaque(module->ldb, "loadparm")),
+ sd,
+ (ndr_push_flags_fn_t)ndr_push_security_descriptor);
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
return NULL;
}
for (i=0; i < msg->num_elements; i++) {
const struct dsdb_attribute *attribute = dsdb_attribute_by_lDAPDisplayName(schema, msg->elements[i].name);
if (!attribute) {
- ldb_asprintf_errstring(ldb, "objectclass %s is not a valid objectClass in schema", msg->elements[i].name);
+ ldb_asprintf_errstring(ldb, "attribute %s is not a valid attribute in schema", msg->elements[i].name);
return LDB_ERR_UNDEFINED_ATTRIBUTE_TYPE;
}
msg->elements[i].name = attribute->lDAPDisplayName;
/* return or own handle to deal with this call */
req->handle = h;
- parent_dn = ldb_dn_get_parent(ac, ac->orig_req->op.mod.message->dn);
+ /* If there isn't a parent, just go on to the add processing */
+ if (ldb_dn_get_comp_num(ac->orig_req->op.add.message->dn) == 1) {
+ return objectclass_do_add(h);
+ }
+
+ parent_dn = ldb_dn_get_parent(ac, ac->orig_req->op.add.message->dn);
if (parent_dn == NULL) {
ldb_oom(module->ldb);
return LDB_ERR_OPERATIONS_ERROR;
}
+
ret = ldb_build_search_req(&ac->search_req, module->ldb,
ac, parent_dn, LDB_SCOPE_BASE,
"(objectClass=*)",
/* Check we have a valid parent */
if (ac->search_res == NULL) {
- if (ldb_dn_get_comp_num(ac->orig_req->op.add.message->dn) <= 1) {
- /* Allow cn=rootdse and cn=templates for now... */
- } else if (ldb_dn_compare(ldb_get_root_basedn(ac->module->ldb), ac->orig_req->op.add.message->dn) == 0) {
+ if (ldb_dn_compare(ldb_get_root_basedn(ac->module->ldb), ac->orig_req->op.add.message->dn) == 0) {
/* Allow the tree to be started */
+
+ /* but don't keep any error string, it's meaningless */
+ ldb_set_errstring(ac->module->ldb, NULL);
} else {
ldb_asprintf_errstring(ac->module->ldb, "objectclass: Cannot add %s, parent does not exist!",
ldb_dn_get_linearized(ac->orig_req->op.add.message->dn));
&msg->dn);
if (ret != LDB_SUCCESS) {
+ ldb_asprintf_errstring(ac->module->ldb, "Could not munge DN %s into normal form",
+ ldb_dn_get_linearized(ac->orig_req->op.add.message->dn));
return ret;
}
switch (objectclass_element->flags & LDB_FLAG_MOD_MASK) {
case LDB_FLAG_MOD_DELETE:
- return LDB_ERR_OBJECT_CLASS_MODS_PROHIBITED;
+ if (objectclass_element->num_values == 0) {
+ return LDB_ERR_OBJECT_CLASS_MODS_PROHIBITED;
+ }
break;
case LDB_FLAG_MOD_REPLACE:
{
if (ldb_dn_is_special(req->op.rename.newdn)) { /* do not manipulate our control entries */
return ldb_next_request(module, req);
}
+
+ /* Firstly ensure we are not trying to rename it to be a child of itself */
+ if ((ldb_dn_compare_base(req->op.rename.olddn, req->op.rename.newdn) == 0)
+ && (ldb_dn_compare(req->op.rename.olddn, req->op.rename.newdn) != 0)) {
+ ldb_asprintf_errstring(module->ldb, "Cannot rename %s to be a child of itself",
+ ldb_dn_get_linearized(req->op.rename.olddn));
+ return LDB_ERR_UNWILLING_TO_PERFORM;
+ }
h = oc_init_handle(req, module);
if (!h) {
case OC_SEARCH_ADD_PARENT:
ret = ldb_wait(ac->search_req->handle, LDB_WAIT_NONE);
- if (ret != LDB_SUCCESS) {
+ if (ret != LDB_SUCCESS && ret != LDB_ERR_NO_SUCH_OBJECT) {
handle->status = ret;
goto done;
}
- if (ac->search_req->handle->status != LDB_SUCCESS) {
+ if (ac->search_req->handle->status != LDB_SUCCESS
+ && ac->search_req->handle->status != LDB_ERR_NO_SUCH_OBJECT) {
handle->status = ac->search_req->handle->status;
goto done;
}
case OC_SEARCH_RENAME_PARENT:
ret = ldb_wait(ac->search_req->handle, LDB_WAIT_NONE);
- if (ret != LDB_SUCCESS) {
+ if (ret != LDB_SUCCESS && ret != LDB_ERR_NO_SUCH_OBJECT) {
handle->status = ret;
goto done;
}
- if (ac->search_req->handle->status != LDB_SUCCESS) {
+ if (ac->search_req->handle->status != LDB_SUCCESS && ac->search_req->handle->status != LDB_ERR_NO_SUCH_OBJECT) {
handle->status = ac->search_req->handle->status;
goto done;
}