mirror of
https://github.com/samba-team/samba.git
synced 2024-12-23 17:34:34 +03:00
s4:LDB/LDAP - Re-allow renames
The main problem is that the "rdn_name" module launches on a rename request also a modification one with the "special attributes" which can't be changed directly. An introduced flag helps to bypass the restriction.
This commit is contained in:
parent
1cebf2dad1
commit
767fce6fcc
@ -750,7 +750,7 @@ static NTSTATUS ldapsrv_ModifyDNRequest(struct ldapsrv_call *call)
|
|||||||
DEBUG(10, ("ModifyDNRequest: olddn: [%s]\n", req->dn));
|
DEBUG(10, ("ModifyDNRequest: olddn: [%s]\n", req->dn));
|
||||||
DEBUG(10, ("ModifyDNRequest: newrdn: [%s]\n", req->newrdn));
|
DEBUG(10, ("ModifyDNRequest: newrdn: [%s]\n", req->newrdn));
|
||||||
|
|
||||||
if (ldb_dn_get_comp_num(req->newrdn) != 1) {
|
if (ldb_dn_get_comp_num(newrdn) != 1) {
|
||||||
result = LDAP_INVALID_DN_SYNTAX;
|
result = LDAP_INVALID_DN_SYNTAX;
|
||||||
map_ldb_error(local_ctx, LDB_ERR_INVALID_DN_SYNTAX, &errstr);
|
map_ldb_error(local_ctx, LDB_ERR_INVALID_DN_SYNTAX, &errstr);
|
||||||
goto reply;
|
goto reply;
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
Copyright (C) Andrew Bartlett 2005-2009
|
Copyright (C) Andrew Bartlett 2005-2009
|
||||||
Copyright (C) Simo Sorce 2006-2008
|
Copyright (C) Simo Sorce 2006-2008
|
||||||
|
Copyright (C) Matthias Dieter Wallnöfer 2009
|
||||||
|
|
||||||
** NOTE! The following LGPL license applies to the ldb
|
** NOTE! The following LGPL license applies to the ldb
|
||||||
** library. This does NOT imply that all of Samba is released
|
** library. This does NOT imply that all of Samba is released
|
||||||
@ -39,14 +40,33 @@
|
|||||||
#include "ldb_includes.h"
|
#include "ldb_includes.h"
|
||||||
#include "ldb_module.h"
|
#include "ldb_module.h"
|
||||||
|
|
||||||
struct rename_context {
|
struct rdn_name_private {
|
||||||
|
/* rename operation? */
|
||||||
|
bool rename;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct rename_context {
|
||||||
struct ldb_module *module;
|
struct ldb_module *module;
|
||||||
struct ldb_request *req;
|
struct ldb_request *req;
|
||||||
|
|
||||||
struct ldb_reply *ares;
|
struct ldb_reply *ares;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static int rdn_name_init(struct ldb_module *module)
|
||||||
|
{
|
||||||
|
struct rdn_name_private *rdn_name_private;
|
||||||
|
struct ldb_context *ldb = ldb_module_get_ctx(module);
|
||||||
|
|
||||||
|
rdn_name_private = talloc_zero(module, struct rdn_name_private);
|
||||||
|
if (rdn_name_private == NULL) {
|
||||||
|
ldb_oom(ldb);
|
||||||
|
return LDB_ERR_OPERATIONS_ERROR;
|
||||||
|
}
|
||||||
|
ldb_module_set_private(module, rdn_name_private);
|
||||||
|
|
||||||
|
return ldb_next_init(module);
|
||||||
|
}
|
||||||
|
|
||||||
static struct ldb_message_element *rdn_name_find_attribute(const struct ldb_message *msg, const char *name)
|
static struct ldb_message_element *rdn_name_find_attribute(const struct ldb_message *msg, const char *name)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
@ -115,6 +135,7 @@ static int rdn_name_add(struct ldb_module *module, struct ldb_request *req)
|
|||||||
|
|
||||||
msg = ldb_msg_copy_shallow(req, req->op.add.message);
|
msg = ldb_msg_copy_shallow(req, req->op.add.message);
|
||||||
if (msg == NULL) {
|
if (msg == NULL) {
|
||||||
|
talloc_free(ac);
|
||||||
return LDB_ERR_OPERATIONS_ERROR;
|
return LDB_ERR_OPERATIONS_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -179,6 +200,7 @@ static int rdn_name_add(struct ldb_module *module, struct ldb_request *req)
|
|||||||
ac, rdn_name_add_callback,
|
ac, rdn_name_add_callback,
|
||||||
req);
|
req);
|
||||||
if (ret != LDB_SUCCESS) {
|
if (ret != LDB_SUCCESS) {
|
||||||
|
talloc_free(ac);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -190,9 +212,15 @@ static int rdn_name_add(struct ldb_module *module, struct ldb_request *req)
|
|||||||
|
|
||||||
static int rdn_modify_callback(struct ldb_request *req, struct ldb_reply *ares)
|
static int rdn_modify_callback(struct ldb_request *req, struct ldb_reply *ares)
|
||||||
{
|
{
|
||||||
|
struct rdn_name_private *rdn_name_private;
|
||||||
struct rename_context *ac;
|
struct rename_context *ac;
|
||||||
|
|
||||||
ac = talloc_get_type(req->context, struct rename_context);
|
ac = talloc_get_type(req->context, struct rename_context);
|
||||||
|
rdn_name_private = talloc_get_type(ldb_module_get_private(ac->module),
|
||||||
|
struct rdn_name_private);
|
||||||
|
|
||||||
|
/* our rename is finished */
|
||||||
|
rdn_name_private->rename = false;
|
||||||
|
|
||||||
if (!ares) {
|
if (!ares) {
|
||||||
return ldb_module_done(ac->req, NULL, NULL,
|
return ldb_module_done(ac->req, NULL, NULL,
|
||||||
@ -216,8 +244,9 @@ static int rdn_modify_callback(struct ldb_request *req, struct ldb_reply *ares)
|
|||||||
|
|
||||||
static int rdn_rename_callback(struct ldb_request *req, struct ldb_reply *ares)
|
static int rdn_rename_callback(struct ldb_request *req, struct ldb_reply *ares)
|
||||||
{
|
{
|
||||||
struct ldb_context *ldb;
|
struct rdn_name_private *rdn_name_private;
|
||||||
struct rename_context *ac;
|
struct rename_context *ac;
|
||||||
|
struct ldb_context *ldb;
|
||||||
struct ldb_request *mod_req;
|
struct ldb_request *mod_req;
|
||||||
const char *rdn_name;
|
const char *rdn_name;
|
||||||
struct ldb_val rdn_val;
|
struct ldb_val rdn_val;
|
||||||
@ -226,6 +255,8 @@ static int rdn_rename_callback(struct ldb_request *req, struct ldb_reply *ares)
|
|||||||
|
|
||||||
ac = talloc_get_type(req->context, struct rename_context);
|
ac = talloc_get_type(req->context, struct rename_context);
|
||||||
ldb = ldb_module_get_ctx(ac->module);
|
ldb = ldb_module_get_ctx(ac->module);
|
||||||
|
rdn_name_private = talloc_get_type(ldb_module_get_private(ac->module),
|
||||||
|
struct rdn_name_private);
|
||||||
|
|
||||||
if (!ares) {
|
if (!ares) {
|
||||||
goto error;
|
goto error;
|
||||||
@ -271,6 +302,9 @@ static int rdn_rename_callback(struct ldb_request *req, struct ldb_reply *ares)
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* we do a rename */
|
||||||
|
rdn_name_private->rename = true;
|
||||||
|
|
||||||
ret = ldb_build_mod_req(&mod_req, ldb,
|
ret = ldb_build_mod_req(&mod_req, ldb,
|
||||||
ac, msg, NULL,
|
ac, msg, NULL,
|
||||||
ac, rdn_modify_callback,
|
ac, rdn_modify_callback,
|
||||||
@ -322,7 +356,8 @@ static int rdn_name_rename(struct ldb_module *module, struct ldb_request *req)
|
|||||||
req);
|
req);
|
||||||
|
|
||||||
if (ret != LDB_SUCCESS) {
|
if (ret != LDB_SUCCESS) {
|
||||||
return LDB_ERR_OPERATIONS_ERROR;
|
talloc_free(ac);
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* rename first, modify "name" if rename is ok */
|
/* rename first, modify "name" if rename is ok */
|
||||||
@ -331,6 +366,8 @@ static int rdn_name_rename(struct ldb_module *module, struct ldb_request *req)
|
|||||||
|
|
||||||
static int rdn_name_modify(struct ldb_module *module, struct ldb_request *req)
|
static int rdn_name_modify(struct ldb_module *module, struct ldb_request *req)
|
||||||
{
|
{
|
||||||
|
struct rdn_name_private *rdn_name_private =
|
||||||
|
talloc_get_type(ldb_module_get_private(module), struct rdn_name_private);
|
||||||
struct ldb_context *ldb;
|
struct ldb_context *ldb;
|
||||||
|
|
||||||
ldb = ldb_module_get_ctx(module);
|
ldb = ldb_module_get_ctx(module);
|
||||||
@ -341,13 +378,15 @@ static int rdn_name_modify(struct ldb_module *module, struct ldb_request *req)
|
|||||||
return ldb_next_request(module, req);
|
return ldb_next_request(module, req);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ldb_msg_find_element(req->op.mod.message, "name")) {
|
if ((!rdn_name_private->rename)
|
||||||
|
&& ldb_msg_find_element(req->op.mod.message, "name")) {
|
||||||
ldb_asprintf_errstring(ldb, "Modify of 'name' on %s not permitted, must use 'rename' operation instead",
|
ldb_asprintf_errstring(ldb, "Modify of 'name' on %s not permitted, must use 'rename' operation instead",
|
||||||
ldb_dn_get_linearized(req->op.mod.message->dn));
|
ldb_dn_get_linearized(req->op.mod.message->dn));
|
||||||
return LDB_ERR_NOT_ALLOWED_ON_RDN;
|
return LDB_ERR_NOT_ALLOWED_ON_RDN;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ldb_msg_find_element(req->op.mod.message, ldb_dn_get_rdn_name(req->op.mod.message->dn))) {
|
if ((!rdn_name_private->rename)
|
||||||
|
&& ldb_msg_find_element(req->op.mod.message, ldb_dn_get_rdn_name(req->op.mod.message->dn))) {
|
||||||
ldb_asprintf_errstring(ldb, "Modify of RDN '%s' on %s not permitted, must use 'rename' operation instead",
|
ldb_asprintf_errstring(ldb, "Modify of RDN '%s' on %s not permitted, must use 'rename' operation instead",
|
||||||
ldb_dn_get_rdn_name(req->op.mod.message->dn), ldb_dn_get_linearized(req->op.mod.message->dn));
|
ldb_dn_get_rdn_name(req->op.mod.message->dn), ldb_dn_get_linearized(req->op.mod.message->dn));
|
||||||
return LDB_ERR_NOT_ALLOWED_ON_RDN;
|
return LDB_ERR_NOT_ALLOWED_ON_RDN;
|
||||||
@ -359,7 +398,8 @@ static int rdn_name_modify(struct ldb_module *module, struct ldb_request *req)
|
|||||||
|
|
||||||
const struct ldb_module_ops ldb_rdn_name_module_ops = {
|
const struct ldb_module_ops ldb_rdn_name_module_ops = {
|
||||||
.name = "rdn_name",
|
.name = "rdn_name",
|
||||||
|
.init_context = rdn_name_init,
|
||||||
.add = rdn_name_add,
|
.add = rdn_name_add,
|
||||||
.modify = rdn_name_modify,
|
.modify = rdn_name_modify,
|
||||||
.rename = rdn_name_rename,
|
.rename = rdn_name_rename
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user