summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source4/dsdb/samdb/ldb_modules/objectclass.c429
-rw-r--r--source4/scripting/libjs/provision.js21
-rwxr-xr-xtestprogs/ejs/ldap.js44
3 files changed, 394 insertions, 100 deletions
diff --git a/source4/dsdb/samdb/ldb_modules/objectclass.c b/source4/dsdb/samdb/ldb_modules/objectclass.c
index 452896d5a3..14dbe3b313 100644
--- a/source4/dsdb/samdb/ldb_modules/objectclass.c
+++ b/source4/dsdb/samdb/ldb_modules/objectclass.c
@@ -42,7 +42,9 @@
struct oc_context {
- enum oc_step {OC_DO_REQ, OC_SEARCH_SELF, OC_DO_MOD} step;
+ enum oc_step {OC_DO_REQ, OC_SEARCH_SELF, OC_DO_MOD,
+ OC_SEARCH_ADD_PARENT, OC_DO_ADD,
+ OC_SEARCH_RENAME_PARENT, OC_DO_RENAME} step;
struct ldb_module *module;
struct ldb_request *orig_req;
@@ -52,7 +54,9 @@ struct oc_context {
struct ldb_request *search_req;
struct ldb_reply *search_res;
+ struct ldb_request *add_req;
struct ldb_request *mod_req;
+ struct ldb_request *rename_req;
};
struct class_list {
@@ -272,53 +276,186 @@ static DATA_BLOB *get_sd(struct ldb_module *module, TALLOC_CTX *mem_ctx,
}
+static int get_search_callback(struct ldb_context *ldb, void *context, struct ldb_reply *ares)
+{
+ struct oc_context *ac;
+
+ ac = talloc_get_type(context, struct oc_context);
+
+ /* we are interested only in the single reply (base search) we receive here */
+ if (ares->type == LDB_REPLY_ENTRY) {
+ if (ac->search_res != NULL) {
+ ldb_set_errstring(ldb, "Too many results");
+ talloc_free(ares);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ ac->search_res = talloc_move(ac, &ares);
+ } else {
+ talloc_free(ares);
+ }
+
+ return LDB_SUCCESS;
+}
+
+/* Fix up the DN to be in the standard form, taking particular care to match the parent DN
+
+ This should mean that if the parent is:
+ CN=Users,DC=samba,DC=example,DC=com
+ and a proposed child is
+ cn=Admins ,cn=USERS,dc=Samba,dc=example,dc=COM
+
+ The resulting DN should be:
+
+ CN=Admins,CN=Users,DC=samba,DC=example,DC=com
+
+ */
+static int fix_dn(TALLOC_CTX *mem_ctx,
+ struct ldb_dn *newdn, struct ldb_dn *parent_dn,
+ struct ldb_dn **fixed_dn)
+{
+ char *upper_rdn_attr;
+ /* 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);
+
+ /* 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_ERR_OPERATIONS_ERROR;
+ }
+
+ /* Create a new child */
+ if (ldb_dn_add_child_fmt(*fixed_dn, "X=X") == false) {
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ /* And replace it with CN=foo (we need the attribute in upper case */
+ return ldb_dn_set_component(*fixed_dn, 0, upper_rdn_attr,
+ *ldb_dn_get_rdn_val(newdn));
+}
+
static int objectclass_add(struct ldb_module *module, struct ldb_request *req)
{
- struct ldb_message_element *objectclass_element;
- const struct dsdb_schema *schema = dsdb_get_schema(module->ldb);
- struct class_list *sorted, *current;
- struct ldb_request *down_req;
- struct ldb_message *msg;
- int ret;
- TALLOC_CTX *mem_ctx;
+ static const char * const attrs[] = { NULL };
+
+ struct ldb_handle *h;
+ struct oc_context *ac;
+ struct ldb_dn *parent_dn;
+ int ret;
+
ldb_debug(module->ldb, LDB_DEBUG_TRACE, "objectclass_add\n");
- if (ldb_dn_is_special(req->op.add.message->dn)) { /* do not manipulate our control entries */
+ /* do not manipulate our control entries */
+ if (ldb_dn_is_special(req->op.add.message->dn)) {
return ldb_next_request(module, req);
}
-
- objectclass_element = ldb_msg_find_element(req->op.add.message, "objectClass");
- /* If no part of this add has an objectClass, then we don't
- * need to make any changes. cn=rootdse doesn't have an objectClass */
- if (!objectclass_element) {
+ /* Need to object to this, but cn=rootdse doesn't hae an objectClass... */
+ if (ldb_msg_find_element(req->op.add.message,
+ "objectClass") == NULL) {
return ldb_next_request(module, req);
}
- mem_ctx = talloc_new(req);
+ h = oc_init_handle(req, module);
+ if (!h) {
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+ ac = talloc_get_type(h->private_data, struct oc_context);
+
+ /* return or own handle to deal with this call */
+ req->handle = h;
+
+ parent_dn = ldb_dn_get_parent(ac->search_req, ac->orig_req->op.mod.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=*)",
+ attrs, NULL,
+ ac, get_search_callback);
+ if (ret != LDB_SUCCESS) {
+ return ret;
+ }
+
+ ldb_set_timeout_from_prev_req(ac->module->ldb, ac->orig_req, ac->search_req);
+
+ ac->step = OC_SEARCH_ADD_PARENT;
+
+ return ldb_next_request(ac->module, ac->search_req);
+}
+
+static int objectclass_do_add(struct ldb_handle *h)
+{
+ const struct dsdb_schema *schema;
+ struct oc_context *ac;
+ struct ldb_message_element *objectclass_element;
+ struct ldb_message *msg;
+ TALLOC_CTX *mem_ctx;
+ struct class_list *sorted, *current;
+ int ret;
+
+ ac = talloc_get_type(h->private_data, struct oc_context);
+ schema = dsdb_get_schema(ac->module->ldb);
+
+ mem_ctx = talloc_new(ac);
if (mem_ctx == NULL) {
return LDB_ERR_OPERATIONS_ERROR;
}
- /* prepare the first operation */
- down_req = talloc(req, struct ldb_request);
- if (down_req == NULL) {
- ldb_set_errstring(module->ldb, "Out of memory!");
+ ac->add_req = talloc(ac, struct ldb_request);
+ if (ac->add_req == NULL) {
talloc_free(mem_ctx);
return LDB_ERR_OPERATIONS_ERROR;
}
- *down_req = *req; /* copy the request */
+ *ac->add_req = *ac->orig_req;
- down_req->op.add.message = msg = ldb_msg_copy_shallow(down_req, req->op.add.message);
+ ac->add_req->op.add.message = msg = ldb_msg_copy_shallow(ac->add_req, ac->orig_req->op.add.message);
+
+ ldb_set_timeout_from_prev_req(ac->module->ldb, ac->orig_req, ac->add_req);
+
+ /* 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) {
+ /* Allow the tree to be started */
+ } 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));
+ return LDB_ERR_UNWILLING_TO_PERFORM;
+ }
+ } else {
+
+ /* Fix up the DN to be in the standard form, taking particular care to match the parent DN */
+ ret = fix_dn(msg,
+ ac->orig_req->op.add.message->dn,
+ ac->search_res->message->dn,
+ &msg->dn);
+
+ if (ret != LDB_SUCCESS) {
+ return ret;
+ }
+
+ /* TODO: Check this is a valid child to this parent,
+ * by reading the allowedChildClasses and
+ * allowedChildClasssesEffective attributes */
+
+ }
+
+ /* This is now the objectClass list from the database */
+ objectclass_element = ldb_msg_find_element(msg, "objectClass");
- if (down_req->op.add.message == NULL) {
+ if (!objectclass_element) {
+ /* Where did it go? bail now... */
talloc_free(mem_ctx);
return LDB_ERR_OPERATIONS_ERROR;
}
-
- ret = objectclass_sort(module, msg, mem_ctx, objectclass_element, &sorted);
+ ret = objectclass_sort(ac->module, msg, mem_ctx, objectclass_element, &sorted);
if (ret != LDB_SUCCESS) {
talloc_free(mem_ctx);
return ret;
@@ -339,7 +476,7 @@ static int objectclass_add(struct ldb_module *module, struct ldb_request *req)
for (current = sorted; current; current = current->next) {
ret = ldb_msg_add_string(msg, "objectClass", current->objectclass);
if (ret != LDB_SUCCESS) {
- ldb_set_errstring(module->ldb,
+ ldb_set_errstring(ac->module->ldb,
"objectclass: could not re-add sorted "
"objectclass to modify msg");
talloc_free(mem_ctx);
@@ -356,7 +493,7 @@ static int objectclass_add(struct ldb_module *module, struct ldb_request *req)
objectclass->defaultObjectCategory);
}
if (!ldb_msg_find_element(msg, "nTSecurityDescriptor")) {
- DATA_BLOB *sd = get_sd(module, mem_ctx, objectclass);
+ DATA_BLOB *sd = get_sd(ac->module, mem_ctx, objectclass);
ldb_msg_add_steal_value(msg, "nTSecurityDescriptor", sd);
}
}
@@ -364,21 +501,19 @@ static int objectclass_add(struct ldb_module *module, struct ldb_request *req)
}
talloc_free(mem_ctx);
- ret = ldb_msg_sanity_check(module->ldb, msg);
+ ret = ldb_msg_sanity_check(ac->module->ldb, msg);
if (ret != LDB_SUCCESS) {
return ret;
}
- /* go on with the call chain */
- ret = ldb_next_request(module, down_req);
+ h->state = LDB_ASYNC_INIT;
+ h->status = LDB_SUCCESS;
- /* do not free down_req as the call results may be linked to it,
- * it will be freed when the upper level request get freed */
- if (ret == LDB_SUCCESS) {
- req->handle = down_req->handle;
- }
- return ret;
+ ac->step = OC_DO_ADD;
+
+ /* perform the add */
+ return ldb_next_request(ac->module, ac->add_req);
}
static int objectclass_modify(struct ldb_module *module, struct ldb_request *req)
@@ -387,7 +522,8 @@ static int objectclass_modify(struct ldb_module *module, struct ldb_request *req
struct ldb_message *msg;
ldb_debug(module->ldb, LDB_DEBUG_TRACE, "objectclass_modify\n");
- if (ldb_dn_is_special(req->op.mod.message->dn)) { /* do not manipulate our control entries */
+ /* do not manipulate our control entries */
+ if (ldb_dn_is_special(req->op.mod.message->dn)) {
return ldb_next_request(module, req);
}
@@ -518,54 +654,24 @@ static int objectclass_modify(struct ldb_module *module, struct ldb_request *req
}
}
-static int get_self_callback(struct ldb_context *ldb, void *context, struct ldb_reply *ares)
+static int objectclass_search_self(struct ldb_handle *h)
{
- struct oc_context *ac;
-
- ac = talloc_get_type(context, struct oc_context);
-
- /* we are interested only in the single reply (base search) we receive here */
- if (ares->type == LDB_REPLY_ENTRY) {
- if (ac->search_res != NULL) {
- ldb_set_errstring(ldb, "Too many results");
- talloc_free(ares);
- return LDB_ERR_OPERATIONS_ERROR;
- }
-
- ac->search_res = talloc_move(ac, &ares);
- } else {
- talloc_free(ares);
- }
-
- return LDB_SUCCESS;
-}
-
-static int objectclass_search_self(struct ldb_handle *h) {
-
+ int ret;
struct oc_context *ac;
static const char * const attrs[] = { "objectClass", NULL };
ac = talloc_get_type(h->private_data, struct oc_context);
- /* prepare the search operation */
- ac->search_req = talloc_zero(ac, struct ldb_request);
- if (ac->search_req == NULL) {
- ldb_debug(ac->module->ldb, LDB_DEBUG_ERROR, "Out of Memory!\n");
- return LDB_ERR_OPERATIONS_ERROR;
- }
+ ret = ldb_build_search_req(&ac->search_req, ac->module->ldb,
+ ac, ac->orig_req->op.mod.message->dn, LDB_SCOPE_BASE,
+ "(objectClass=*)",
+ attrs, NULL,
+ ac, get_search_callback);
- ac->search_req->operation = LDB_SEARCH;
- ac->search_req->op.search.base = ac->orig_req->op.mod.message->dn;
- ac->search_req->op.search.scope = LDB_SCOPE_BASE;
- ac->search_req->op.search.tree = ldb_parse_tree(ac->search_req, NULL);
- if (ac->search_req->op.search.tree == NULL) {
- ldb_set_errstring(ac->module->ldb, "objectclass: Internal error producing null search");
- return LDB_ERR_OPERATIONS_ERROR;
+ if (ret != LDB_SUCCESS) {
+ return ret;
}
- ac->search_req->op.search.attrs = attrs;
- ac->search_req->controls = NULL;
- ac->search_req->context = ac;
- ac->search_req->callback = get_self_callback;
+
ldb_set_timeout_from_prev_req(ac->module->ldb, ac->orig_req, ac->search_req);
ac->step = OC_SEARCH_SELF;
@@ -613,9 +719,9 @@ static int objectclass_do_mod(struct ldb_handle *h) {
objectclass_element = ldb_msg_find_element(ac->search_res->message,
"objectClass");
if (!objectclass_element) {
- /* Where did it go? Move along now, nothing to see here */
+ /* Where did it go? bail now... */
talloc_free(mem_ctx);
- return LDB_SUCCESS;
+ return LDB_ERR_OPERATIONS_ERROR;
}
/* modify dn */
@@ -664,6 +770,98 @@ static int objectclass_do_mod(struct ldb_handle *h) {
return ldb_next_request(ac->module, ac->mod_req);
}
+static int objectclass_rename(struct ldb_module *module, struct ldb_request *req)
+{
+
+ static const char * const attrs[] = { NULL };
+
+ struct ldb_handle *h;
+ struct oc_context *ac;
+ struct ldb_dn *parent_dn;
+ int ret;
+
+ ldb_debug(module->ldb, LDB_DEBUG_TRACE, "objectclass_rename\n");
+
+ if (ldb_dn_is_special(req->op.rename.newdn)) { /* do not manipulate our control entries */
+ return ldb_next_request(module, req);
+ }
+
+ h = oc_init_handle(req, module);
+ if (!h) {
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+ ac = talloc_get_type(h->private_data, struct oc_context);
+
+ /* return or own handle to deal with this call */
+ req->handle = h;
+
+ parent_dn = ldb_dn_get_parent(ac->search_req, ac->orig_req->op.rename.newdn);
+ 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=*)",
+ attrs, NULL,
+ ac, get_search_callback);
+ if (ret != LDB_SUCCESS) {
+ return ret;
+ }
+
+ ldb_set_timeout_from_prev_req(ac->module->ldb, ac->orig_req, ac->search_req);
+
+ ac->step = OC_SEARCH_RENAME_PARENT;
+
+ return ldb_next_request(ac->module, ac->search_req);
+}
+
+static int objectclass_do_rename(struct ldb_handle *h)
+{
+ struct oc_context *ac;
+ int ret;
+
+ ac = talloc_get_type(h->private_data, struct oc_context);
+
+ ac->rename_req = talloc(ac, struct ldb_request);
+ if (ac->rename_req == NULL) {
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ *ac->rename_req = *ac->orig_req;
+
+ ldb_set_timeout_from_prev_req(ac->module->ldb, ac->orig_req, ac->rename_req);
+
+ /* Check we have a valid parent */
+ if (ac->search_res == NULL) {
+ ldb_asprintf_errstring(ac->module->ldb, "objectclass: Cannot rename %s, parent does not exist!",
+ ldb_dn_get_linearized(ac->orig_req->op.rename.newdn));
+ return LDB_ERR_UNWILLING_TO_PERFORM;
+ }
+
+ /* Fix up the DN to be in the standard form, taking particular care to match the parent DN */
+ ret = fix_dn(ac->rename_req,
+ ac->orig_req->op.rename.newdn,
+ ac->search_res->message->dn,
+ &ac->rename_req->op.rename.newdn);
+
+ if (ret != LDB_SUCCESS) {
+ return ret;
+ }
+
+ /* TODO: Check this is a valid child to this parent,
+ * by reading the allowedChildClasses and
+ * allowedChildClasssesEffective attributes */
+
+ h->state = LDB_ASYNC_INIT;
+ h->status = LDB_SUCCESS;
+
+ ac->step = OC_DO_RENAME;
+
+ /* perform the rename */
+ return ldb_next_request(ac->module, ac->rename_req);
+}
+
static int oc_wait(struct ldb_handle *handle) {
struct oc_context *ac;
int ret;
@@ -738,6 +936,80 @@ static int oc_wait(struct ldb_handle *handle) {
break;
+ case OC_SEARCH_ADD_PARENT:
+ ret = ldb_wait(ac->search_req->handle, LDB_WAIT_NONE);
+
+ if (ret != LDB_SUCCESS) {
+ handle->status = ret;
+ goto done;
+ }
+ if (ac->search_req->handle->status != LDB_SUCCESS) {
+ handle->status = ac->search_req->handle->status;
+ goto done;
+ }
+
+ if (ac->search_req->handle->state != LDB_ASYNC_DONE) {
+ return LDB_SUCCESS;
+ }
+
+ /* parent search done, go on */
+ return objectclass_do_add(handle);
+
+ case OC_DO_ADD:
+ ret = ldb_wait(ac->add_req->handle, LDB_WAIT_NONE);
+
+ if (ret != LDB_SUCCESS) {
+ handle->status = ret;
+ goto done;
+ }
+ if (ac->add_req->handle->status != LDB_SUCCESS) {
+ handle->status = ac->add_req->handle->status;
+ goto done;
+ }
+
+ if (ac->add_req->handle->state != LDB_ASYNC_DONE) {
+ return LDB_SUCCESS;
+ }
+
+ break;
+
+ case OC_SEARCH_RENAME_PARENT:
+ ret = ldb_wait(ac->search_req->handle, LDB_WAIT_NONE);
+
+ if (ret != LDB_SUCCESS) {
+ handle->status = ret;
+ goto done;
+ }
+ if (ac->search_req->handle->status != LDB_SUCCESS) {
+ handle->status = ac->search_req->handle->status;
+ goto done;
+ }
+
+ if (ac->search_req->handle->state != LDB_ASYNC_DONE) {
+ return LDB_SUCCESS;
+ }
+
+ /* parent search done, go on */
+ return objectclass_do_rename(handle);
+
+ case OC_DO_RENAME:
+ ret = ldb_wait(ac->rename_req->handle, LDB_WAIT_NONE);
+
+ if (ret != LDB_SUCCESS) {
+ handle->status = ret;
+ goto done;
+ }
+ if (ac->rename_req->handle->status != LDB_SUCCESS) {
+ handle->status = ac->rename_req->handle->status;
+ goto done;
+ }
+
+ if (ac->rename_req->handle->state != LDB_ASYNC_DONE) {
+ return LDB_SUCCESS;
+ }
+
+ break;
+
default:
ret = LDB_ERR_OPERATIONS_ERROR;
goto done;
@@ -777,6 +1049,7 @@ static const struct ldb_module_ops objectclass_ops = {
.name = "objectclass",
.add = objectclass_add,
.modify = objectclass_modify,
+ .rename = objectclass_rename,
.wait = objectclass_wait
};
diff --git a/source4/scripting/libjs/provision.js b/source4/scripting/libjs/provision.js
index ef43ed721d..5ca7be99e5 100644
--- a/source4/scripting/libjs/provision.js
+++ b/source4/scripting/libjs/provision.js
@@ -631,6 +631,16 @@ function provision(subobj, message, blank, paths, session_info, credentials, lda
message("Erasing data from partitions\n");
ldb_erase_partitions(info, samdb, ldapbackend);
+ // (hack) Reload, now we have the partitions and rootdse loaded.
+ var commit_ok = samdb.transaction_commit();
+ if (!commit_ok) {
+ info.message("samdb commit failed: " + samdb.errstring() + "\n");
+ assert(commit_ok);
+ }
+ samdb.close();
+
+ samdb = open_ldb(info, paths.samdb, false);
+
message("Adding DomainDN: " + subobj.DOMAINDN + " (permitted to fail)\n");
var add_ok = setup_add_ldif("provision_basedn.ldif", info, samdb, true);
message("Modifying DomainDN: " + subobj.DOMAINDN + "\n");
@@ -951,20 +961,21 @@ function provision_guess()
//
// Some Known ordering constraints:
// - rootdse must be first, as it makes redirects from "" -> cn=rootdse
- // - samldb must be before password_hash, because password_hash checks
- // that the objectclass is of type person (filled in by samldb)
+ // - objectclass must be before password_hash, because password_hash checks
+ // that the objectclass is of type person (filled in by the objectclass
+ // module when expanding the objectclass list)
// - partition must be last
// - each partition has its own module list then
modules_list = new Array("rootdse",
- "kludge_acl",
"paged_results",
"server_sort",
"extended_dn",
"asq",
"samldb",
- "operational",
- "objectclass",
"rdn_name",
+ "objectclass",
+ "kludge_acl",
+ "operational",
"subtree_rename",
"linked_attributes",
"show_deleted",
diff --git a/testprogs/ejs/ldap.js b/testprogs/ejs/ldap.js
index 4e6f5cb750..080b0a981c 100755
--- a/testprogs/ejs/ldap.js
+++ b/testprogs/ejs/ldap.js
@@ -32,7 +32,7 @@ function basic_tests(ldb, gc_ldb, base_dn, configuration_dn, schema_dn)
ldb.del("cn=ldaptestuser,cn=users," + base_dn);
var ok = ldb.add("
-dn: cn=ldaptestuser,cn=users," + base_dn + "
+dn: cn=ldaptestuser,cn=uSers," + base_dn + "
objectClass: user
objectClass: person
cn: LDAPtestUSER
@@ -44,7 +44,7 @@ cn: LDAPtestUSER
assert(ok.error == 0);
}
ok = ldb.add("
-dn: cn=ldaptestuser,cn=users," + base_dn + "
+dn: cn=ldaptestuser,cn=uSers," + base_dn + "
objectClass: user
objectClass: person
cn: LDAPtestUSER
@@ -117,7 +117,7 @@ servicePrincipalName: cifs/ldaptest2computer
}
ok = ldb.add("
-dn: cn=ldaptestuser2,cn=users," + base_dn + "
+dn: cn=ldaptestuser2,cn=useRs," + base_dn + "
objectClass: person
objectClass: user
cn: LDAPtestUSER2
@@ -129,7 +129,7 @@ cn: LDAPtestUSER2
assert(ok.error == 0);
}
ok = ldb.add("
-dn: cn=ldaptestuser2,cn=users," + base_dn + "
+dn: cn=ldaptestuser2,cn=useRs," + base_dn + "
objectClass: person
objectClass: user
cn: LDAPtestUSER2
@@ -142,6 +142,8 @@ cn: LDAPtestUSER2
ok = ldb.del("cn=ldaptestuser3,cn=users," + base_dn);
+ println("Testing Renames");
+
ok = ldb.rename("cn=ldaptestuser2,cn=users," + base_dn, "cn=ldaptestuser3,cn=users," + base_dn);
if (ok.error != 0) {
println("Could not rename cn=ldaptestuser2,cn=users," + base_dn + " into cn=ldaptestuser3,cn=users," + base_dn + ": " + ok.errstr);
@@ -150,7 +152,7 @@ cn: LDAPtestUSER2
// ensure we cannot add it again
ok = ldb.add("
-dn: cn=ldaptestuser3,cn=users," + base_dn + "
+dn: cn=ldaptestuser3,cn=userS," + base_dn + "
objectClass: person
objectClass: user
cn: LDAPtestUSER3
@@ -204,13 +206,15 @@ cn: LDAPtestUSER3
ok = ldb.del("cn=ldaptestuser5,cn=users," + base_dn);
+ println("Testing subtree Renames");
+
ok = ldb.add("
dn: cn=ldaptestcontainer," + base_dn + "
objectClass: container
");
ok = ldb.add("
-dn: cn=ldaptestuser4,cn=ldaptestcontainer," + base_dn + "
+dn: CN=ldaptestuser4,CN=ldaptestcontainer," + base_dn + "
objectClass: person
objectClass: user
cn: LDAPtestUSER4
@@ -222,7 +226,7 @@ cn: LDAPtestUSER4
assert(ok.error == 0);
}
ok = ldb.add("
-dn: cn=ldaptestuser4,cn=ldaptestcontainer," + base_dn + "
+dn: CN=ldaptestuser4,CN=ldaptestcontainer," + base_dn + "
objectClass: person
objectClass: user
cn: LDAPtestUSER4
@@ -233,8 +237,8 @@ cn: LDAPtestUSER4
}
}
- println("Testing ldb.rename of cn=ldaptestcontainer," + base_dn + "to cn=ldaptestcontainer2," + base_dn);
- ok = ldb.rename("cn=ldaptestcontainer," + base_dn, "cn=ldaptestcontainer2," + base_dn);
+ println("Testing ldb.rename of cn=ldaptestcontainer," + base_dn + " to cn=ldaptestcontainer2," + base_dn);
+ ok = ldb.rename("CN=ldaptestcontainer," + base_dn, "CN=ldaptestcontainer2," + base_dn);
if (ok.error != 0) {
println(ok.errstr);
assert(ok.error == 0);
@@ -248,7 +252,7 @@ cn: LDAPtestUSER4
assert(res.msgs.length == 1);
}
- assert(res.msgs[0].dn == ("cn=ldaptestuser4,cn=ldaptestcontainer2," + base_dn));
+ assert(res.msgs[0].dn == ("CN=ldaptestuser4,CN=ldaptestcontainer2," + base_dn));
println("Testing ldb.search for (&(cn=ldaptestuser4)(objectClass=user)) in renamed container");
var res = ldb.search("(&(cn=ldaptestuser4)(objectClass=user))", "cn=ldaptestcontainer2," + base_dn, ldb.SCOPE_SUBTREE);
@@ -258,8 +262,14 @@ cn: LDAPtestUSER4
assert(res.msgs.length == 1);
}
- assert(res.msgs[0].dn == ("cn=ldaptestuser4,cn=ldaptestcontainer2," + base_dn));
+ assert(res.msgs[0].dn == ("CN=ldaptestuser4,CN=ldaptestcontainer2," + base_dn));
+ println("Testing delete (should fail, not a leaf node) of renamed cn=ldaptestcontainer2," + base_dn);
+ ok = ldb.del("cn=ldaptestcontainer2," + base_dn);
+ if (ok.error != 66) { /* LDB_ERR_NOT_ALLOWED_ON_NON_LEAF */
+ println(ok.errstr);
+ assert(ok.error == 66);
+ }
println("Testing delete of subtree renamed "+res.msgs[0].dn);
ok = ldb.del(res.msgs[0].dn);
if (ok.error != 0) {
@@ -321,7 +331,7 @@ objectClass: user
assert(res.msgs.length == 1);
}
- assert(res.msgs[0].dn == ("cn=ldaptestuser,cn=users," + base_dn));
+ assert(res.msgs[0].dn == ("CN=ldaptestuser,CN=Users," + base_dn));
assert(res.msgs[0].cn == "ldaptestuser");
assert(res.msgs[0].name == "ldaptestuser");
assert(res.msgs[0].objectClass[0] == "top");
@@ -396,7 +406,7 @@ objectClass: user
assert(res.msgs.length == 1);
}
- assert(res.msgs[0].dn == ("cn=ldaptestcomputer,cn=computers," + base_dn));
+ assert(res.msgs[0].dn == ("CN=ldaptestcomputer,CN=Computers," + base_dn));
assert(res.msgs[0].cn == "ldaptestcomputer");
assert(res.msgs[0].name == "ldaptestcomputer");
assert(res.msgs[0].objectClass[0] == "top");
@@ -499,7 +509,7 @@ objectClass: user
assert(res.msgs.length == 1);
}
- assert(res.msgs[0].dn == ("cn=ldaptest2computer,cn=computers," + base_dn));
+ assert(res.msgs[0].dn == ("CN=ldaptest2computer,CN=Computers," + base_dn));
assert(res.msgs[0].cn == "ldaptest2computer");
assert(res.msgs[0].name == "ldaptest2computer");
assert(res.msgs[0].objectClass[0] == "top");
@@ -523,7 +533,7 @@ objectClass: user
assert(res.msgs.length == 1);
}
- assert(res.msgs[0].dn == ("cn=ldaptestuser2,cn=users," + base_dn));
+ assert(res.msgs[0].dn == ("CN=ldaptestuser2,CN=Users," + base_dn));
assert(res.msgs[0].cn == "ldaptestuser2");
assert(res.msgs[0].name == "ldaptestuser2");
assert(res.msgs[0].objectClass[0] == "top");
@@ -550,7 +560,7 @@ objectClass: user
assert(res.msgs.length == 1);
}
-// assert(res.msgs[0].dn == ("CN=ldaptestutf8user èùéìòà,CN=users," + base_dn));
+ assert(res.msgs[0].dn == ("CN=ldaptestutf8user èùéìòà,CN=Users," + base_dn));
assert(res.msgs[0].cn == "ldaptestutf8user èùéìòà");
assert(res.msgs[0].name == "ldaptestutf8user èùéìòà");
assert(res.msgs[0].objectClass[0] == "top");
@@ -572,7 +582,7 @@ objectClass: user
if (res.error != 0 || res.msgs.length != 1) {
println("Could not find (expect space collapse, win2k3 fails) (&(cn=ldaptestutf8user2 ÈÙÉÌÒÀ)(objectClass=user))");
} else {
-// assert(res.msgs[0].dn == ("cn=ldaptestutf8user2 èùéìòà,cn=users," + base_dn));
+ assert(res.msgs[0].dn == ("cn=ldaptestutf8user2 èùéìòà,cn=users," + base_dn));
assert(res.msgs[0].cn == "ldaptestutf8user2 èùéìòà");
}