summaryrefslogtreecommitdiff
path: root/source4/ldap_server/ldap_backend.c
diff options
context:
space:
mode:
authorSimo Sorce <idra@samba.org>2006-01-13 00:38:35 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 13:50:57 -0500
commita7a79d2b256c97bd6ffa6e9740d14366ebc7602e (patch)
tree3b7b912a8ae86a8f0a523fad0f697d6516d30f70 /source4/ldap_server/ldap_backend.c
parent0ac6b5232d1e52bab55227fc5251b363fd97b333 (diff)
downloadsamba-a7a79d2b256c97bd6ffa6e9740d14366ebc7602e.tar.gz
samba-a7a79d2b256c97bd6ffa6e9740d14366ebc7602e.tar.bz2
samba-a7a79d2b256c97bd6ffa6e9740d14366ebc7602e.zip
r12880: Remove ldap partitions useless now and probably we
will not use it anyway as we plan to support partitions in ldb directly like with rootdse Merge ldap_simple_ldb into ldap_backend, it is not simple anymore and makes no sense to have it separated now that ldap partitions are gone Initial attempt at working to some limit to avoid DOSs for the ldap server. Simo. (This used to be commit 97bff3e049eba48019f2b0f3eb5a19e32fef2e23)
Diffstat (limited to 'source4/ldap_server/ldap_backend.c')
-rw-r--r--source4/ldap_server/ldap_backend.c590
1 files changed, 543 insertions, 47 deletions
diff --git a/source4/ldap_server/ldap_backend.c b/source4/ldap_server/ldap_backend.c
index 1e6d05a9bd..562263371b 100644
--- a/source4/ldap_server/ldap_backend.c
+++ b/source4/ldap_server/ldap_backend.c
@@ -22,7 +22,79 @@
#include "ldap_server/ldap_server.h"
#include "dlinklist.h"
#include "libcli/ldap/ldap.h"
+#include "lib/ldb/include/ldb.h"
+#include "lib/ldb/include/ldb_errors.h"
+#include "dsdb/samdb/samdb.h"
+
+#define VALID_DN_SYNTAX(dn,i) do {\
+ if (!(dn)) {\
+ return NT_STATUS_NO_MEMORY;\
+ } else if ((dn)->comp_num < (i)) {\
+ result = LDAP_INVALID_DN_SYNTAX;\
+ errstr = "Invalid DN (" #i " components needed for '" #dn "')";\
+ goto reply;\
+ }\
+} while(0)
+
+static int map_ldb_error(struct ldb_context *ldb, int err, const char **errstring)
+{
+ *errstring = ldb_errstring(ldb);
+
+ /* its 1:1 for now */
+ return err;
+}
+
+/*
+ map controls
+*/
+static int get_ldb_controls(void *mem_ctx, struct ldap_Control **controls, struct ldb_control ***lcontrols)
+{
+ struct ldb_control **lctrl;
+ int i, l;
+
+ if (controls == NULL || controls[0] == NULL) {
+ *lcontrols = NULL;
+ return LDB_SUCCESS;
+ }
+
+ l = 0;
+ lctrl = NULL;
+ *lcontrols = NULL;
+
+ for (i = 0; controls[i] != NULL; i++) {
+ lctrl = talloc_realloc(mem_ctx, lctrl, struct ldb_control *, l + 2);
+ if (lctrl == NULL) {
+ return LDB_ERR_OTHER;
+ }
+ lctrl[l] = talloc(lctrl, struct ldb_control);
+ if (lctrl[l] == NULL) {
+ return LDB_ERR_OTHER;
+ }
+ lctrl[l]->oid = controls[i]->oid;
+ lctrl[l]->critical = controls[i]->critical;
+ lctrl[l]->data = controls[i]->value;
+ l++;
+ }
+ lctrl[l] = NULL;
+ *lcontrols = lctrl;
+
+ return LDB_SUCCESS;
+}
+
+/*
+ connect to the sam database
+*/
+NTSTATUS ldapsrv_backend_Init(struct ldapsrv_connection *conn)
+{
+ conn->ldb = samdb_connect(conn, conn->session_info);
+ if (conn->ldb == NULL) {
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ }
+ ldb_set_opaque(conn->ldb, "server_credentials", conn->server_credentials);
+
+ return NT_STATUS_OK;
+}
struct ldapsrv_reply *ldapsrv_init_reply(struct ldapsrv_call *call, uint8_t type)
{
@@ -50,11 +122,6 @@ void ldapsrv_queue_reply(struct ldapsrv_call *call, struct ldapsrv_reply *reply)
DLIST_ADD_END(call->replies, reply, struct ldapsrv_reply *);
}
-struct ldapsrv_partition *ldapsrv_get_partition(struct ldapsrv_connection *conn, const char *dn, uint8_t scope)
-{
- return conn->default_partition;
-}
-
NTSTATUS ldapsrv_unwilling(struct ldapsrv_call *call, int error)
{
struct ldapsrv_reply *reply;
@@ -83,120 +150,549 @@ NTSTATUS ldapsrv_unwilling(struct ldapsrv_call *call, int error)
static NTSTATUS ldapsrv_SearchRequest(struct ldapsrv_call *call)
{
struct ldap_SearchRequest *req = &call->request->r.SearchRequest;
- struct ldapsrv_partition *part;
+ struct ldap_SearchResEntry *ent;
+ struct ldap_Result *done;
+ struct ldapsrv_reply *ent_r, *done_r;
+ void *local_ctx;
+ struct ldb_context *samdb = call->conn->ldb;
+ struct ldb_dn *basedn;
+ struct ldb_result *res = NULL;
+ struct ldb_request lreq;
+ enum ldb_scope scope = LDB_SCOPE_DEFAULT;
+ const char **attrs = NULL;
+ const char *errstr = NULL;
+ int success_limit = 1;
+ int result = LDAP_SUCCESS;
+ int ldb_ret;
+ int i, j, y;
DEBUG(10, ("SearchRequest"));
DEBUGADD(10, (" basedn: %s", req->basedn));
DEBUGADD(10, (" filter: %s\n", ldb_filter_from_tree(call, req->tree)));
- part = ldapsrv_get_partition(call->conn, req->basedn, req->scope);
+ local_ctx = talloc_named(call, 0, "sldb_Search local memory context");
+ NT_STATUS_HAVE_NO_MEMORY(local_ctx);
+
+ basedn = ldb_dn_explode(local_ctx, req->basedn);
+ VALID_DN_SYNTAX(basedn, 0);
+
+ DEBUG(10, ("SearchRequest: basedn: [%s]\n", req->basedn));
+ DEBUG(10, ("SearchRequest: filter: [%s]\n", ldb_filter_from_tree(call, req->tree)));
+
+ switch (req->scope) {
+ case LDAP_SEARCH_SCOPE_BASE:
+ DEBUG(10,("SearchRequest: scope: [BASE]\n"));
+ scope = LDB_SCOPE_BASE;
+ success_limit = 0;
+ break;
+ case LDAP_SEARCH_SCOPE_SINGLE:
+ DEBUG(10,("SearchRequest: scope: [ONE]\n"));
+ scope = LDB_SCOPE_ONELEVEL;
+ success_limit = 0;
+ break;
+ case LDAP_SEARCH_SCOPE_SUB:
+ DEBUG(10,("SearchRequest: scope: [SUB]\n"));
+ scope = LDB_SCOPE_SUBTREE;
+ success_limit = 0;
+ break;
+ }
- if (!part->ops->Search) {
- struct ldap_Result *done;
- struct ldapsrv_reply *done_r;
+ if (req->num_attributes >= 1) {
+ attrs = talloc_array(samdb, const char *, req->num_attributes+1);
+ NT_STATUS_HAVE_NO_MEMORY(attrs);
- done_r = ldapsrv_init_reply(call, LDAP_TAG_SearchResultDone);
- if (!done_r) {
- return NT_STATUS_NO_MEMORY;
+ for (i=0; i < req->num_attributes; i++) {
+ DEBUG(10,("SearchRequest: attrs: [%s]\n",req->attributes[i]));
+ attrs[i] = req->attributes[i];
}
+ attrs[i] = NULL;
+ }
+
+ DEBUG(5,("ldb_request dn=%s filter=%s\n",
+ req->basedn, ldb_filter_from_tree(call, req->tree)));
- done = &done_r->msg->r.SearchResultDone;
- done->resultcode = 53;
- done->dn = NULL;
- done->errormessage = NULL;
- done->referral = NULL;
+ ZERO_STRUCT(lreq);
+ lreq.operation = LDB_REQ_SEARCH;
+ lreq.op.search.base = basedn;
+ lreq.op.search.scope = scope;
+ lreq.op.search.tree = req->tree;
+ lreq.op.search.attrs = attrs;
- ldapsrv_queue_reply(call, done_r);
- return NT_STATUS_OK;
+ ldb_ret = get_ldb_controls(local_ctx, call->request->controls, &lreq.controls);
+
+ if (ldb_ret != LDB_SUCCESS) {
+ /* get_ldb_controls fails only on a critical internal error or when
+ * a control is defined as critical but it is not supported
+ */
+ goto reply;
}
- return part->ops->Search(part, call);
+ ldb_ret = ldb_request(samdb, &lreq);
+
+ res = talloc_steal(samdb, lreq.op.search.res);
+
+ if (ldb_ret == LDB_SUCCESS) {
+ for (i = 0; i < res->count; i++) {
+ ent_r = ldapsrv_init_reply(call, LDAP_TAG_SearchResultEntry);
+ NT_STATUS_HAVE_NO_MEMORY(ent_r);
+
+ ent = &ent_r->msg->r.SearchResultEntry;
+ ent->dn = ldb_dn_linearize(ent_r, res->msgs[i]->dn);
+ ent->num_attributes = 0;
+ ent->attributes = NULL;
+ if (res->msgs[i]->num_elements == 0) {
+ goto queue_reply;
+ }
+ ent->num_attributes = res->msgs[i]->num_elements;
+ ent->attributes = talloc_array(ent_r, struct ldb_message_element, ent->num_attributes);
+ NT_STATUS_HAVE_NO_MEMORY(ent->attributes);
+ for (j=0; j < ent->num_attributes; j++) {
+ ent->attributes[j].name = talloc_steal(ent->attributes, res->msgs[i]->elements[j].name);
+ ent->attributes[j].num_values = 0;
+ ent->attributes[j].values = NULL;
+ if (req->attributesonly && (res->msgs[i]->elements[j].num_values == 0)) {
+ continue;
+ }
+ ent->attributes[j].num_values = res->msgs[i]->elements[j].num_values;
+ ent->attributes[j].values = talloc_array(ent->attributes,
+ DATA_BLOB, ent->attributes[j].num_values);
+ NT_STATUS_HAVE_NO_MEMORY(ent->attributes[j].values);
+ for (y=0; y < ent->attributes[j].num_values; y++) {
+ ent->attributes[j].values[y].length = res->msgs[i]->elements[j].values[y].length;
+ ent->attributes[j].values[y].data = talloc_steal(ent->attributes[j].values,
+ res->msgs[i]->elements[j].values[y].data);
+ }
+ }
+queue_reply:
+ ldapsrv_queue_reply(call, ent_r);
+ }
+ }
+
+reply:
+ done_r = ldapsrv_init_reply(call, LDAP_TAG_SearchResultDone);
+ NT_STATUS_HAVE_NO_MEMORY(done_r);
+
+ done = &done_r->msg->r.SearchResultDone;
+ done->dn = NULL;
+ done->referral = NULL;
+
+ if (ldb_ret == LDB_SUCCESS) {
+ if (res->count >= success_limit) {
+ DEBUG(10,("SearchRequest: results: [%d]\n", res->count));
+ result = LDAP_SUCCESS;
+ errstr = NULL;
+ } else if (res->count == 0) {
+ DEBUG(10,("SearchRequest: no results\n"));
+ result = LDAP_NO_SUCH_OBJECT;
+ errstr = ldb_errstring(samdb);
+ }
+ if (res->controls) {
+ done_r->msg->controls = (struct ldap_Control **)(res->controls);
+ }
+ } else {
+ DEBUG(10,("SearchRequest: error\n"));
+ result = map_ldb_error(samdb, ldb_ret, &errstr);
+ }
+
+ done->resultcode = result;
+ done->errormessage = (errstr?talloc_strdup(done_r, errstr):NULL);
+
+ talloc_free(local_ctx);
+
+ ldapsrv_queue_reply(call, done_r);
+ return NT_STATUS_OK;
}
static NTSTATUS ldapsrv_ModifyRequest(struct ldapsrv_call *call)
{
struct ldap_ModifyRequest *req = &call->request->r.ModifyRequest;
- struct ldapsrv_partition *part;
+ struct ldap_Result *modify_result;
+ struct ldapsrv_reply *modify_reply;
+ void *local_ctx;
+ struct ldb_context *samdb = call->conn->ldb;
+ struct ldb_message *msg = NULL;
+ struct ldb_dn *dn;
+ const char *errstr = NULL;
+ int result = LDAP_SUCCESS;
+ int ldb_ret;
+ int i,j;
DEBUG(10, ("ModifyRequest"));
DEBUGADD(10, (" dn: %s", req->dn));
- part = ldapsrv_get_partition(call->conn, req->dn, LDAP_SEARCH_SCOPE_SUB);
+ local_ctx = talloc_named(call, 0, "ModifyRequest local memory context");
+ NT_STATUS_HAVE_NO_MEMORY(local_ctx);
+
+ dn = ldb_dn_explode(local_ctx, req->dn);
+ VALID_DN_SYNTAX(dn, 1);
+
+ DEBUG(10, ("ModifyRequest: dn: [%s]\n", req->dn));
+
+ msg = talloc(local_ctx, struct ldb_message);
+ NT_STATUS_HAVE_NO_MEMORY(msg);
+
+ msg->dn = dn;
+ msg->private_data = NULL;
+ msg->num_elements = 0;
+ msg->elements = NULL;
+
+ if (req->num_mods > 0) {
+ msg->num_elements = req->num_mods;
+ msg->elements = talloc_array(msg, struct ldb_message_element, req->num_mods);
+ NT_STATUS_HAVE_NO_MEMORY(msg->elements);
+
+ for (i=0; i < msg->num_elements; i++) {
+ msg->elements[i].name = discard_const_p(char, req->mods[i].attrib.name);
+ msg->elements[i].num_values = 0;
+ msg->elements[i].values = NULL;
+
+ switch (req->mods[i].type) {
+ default:
+ result = LDAP_PROTOCOL_ERROR;
+ errstr = "Invalid LDAP_MODIFY_* type";
+ goto reply;
+ case LDAP_MODIFY_ADD:
+ msg->elements[i].flags = LDB_FLAG_MOD_ADD;
+ break;
+ case LDAP_MODIFY_DELETE:
+ msg->elements[i].flags = LDB_FLAG_MOD_DELETE;
+ break;
+ case LDAP_MODIFY_REPLACE:
+ msg->elements[i].flags = LDB_FLAG_MOD_REPLACE;
+ break;
+ }
+
+ msg->elements[i].num_values = req->mods[i].attrib.num_values;
+ if (msg->elements[i].num_values > 0) {
+ msg->elements[i].values = talloc_array(msg, struct ldb_val, msg->elements[i].num_values);
+ NT_STATUS_HAVE_NO_MEMORY(msg->elements[i].values);
+
+ for (j=0; j < msg->elements[i].num_values; j++) {
+ if (!(req->mods[i].attrib.values[j].length > 0)) {
+ result = LDAP_OTHER;
+ errstr = "Empty attribute values are not allowed";
+ goto reply;
+ }
+ msg->elements[i].values[j].length = req->mods[i].attrib.values[j].length;
+ msg->elements[i].values[j].data = req->mods[i].attrib.values[j].data;
+ }
+ }
+ }
+ } else {
+ result = LDAP_OTHER;
+ errstr = "No mods are not allowed";
+ goto reply;
+ }
+
+reply:
+ modify_reply = ldapsrv_init_reply(call, LDAP_TAG_ModifyResponse);
+ NT_STATUS_HAVE_NO_MEMORY(modify_reply);
- if (!part->ops->Modify) {
- return ldapsrv_unwilling(call, 53);
+ if (result == LDAP_SUCCESS) {
+ ldb_ret = ldb_modify(samdb, msg);
+ result = map_ldb_error(samdb, ldb_ret, &errstr);
}
- return part->ops->Modify(part, call);
+ modify_result = &modify_reply->msg->r.AddResponse;
+ modify_result->dn = NULL;
+ modify_result->resultcode = result;
+ modify_result->errormessage = (errstr?talloc_strdup(modify_reply, errstr):NULL);
+ modify_result->referral = NULL;
+
+ talloc_free(local_ctx);
+
+ ldapsrv_queue_reply(call, modify_reply);
+ return NT_STATUS_OK;
+
}
static NTSTATUS ldapsrv_AddRequest(struct ldapsrv_call *call)
{
struct ldap_AddRequest *req = &call->request->r.AddRequest;
- struct ldapsrv_partition *part;
+ struct ldap_Result *add_result;
+ struct ldapsrv_reply *add_reply;
+ void *local_ctx;
+ struct ldb_context *samdb = call->conn->ldb;
+ struct ldb_message *msg = NULL;
+ struct ldb_dn *dn;
+ const char *errstr = NULL;
+ int result = LDAP_SUCCESS;
+ int ldb_ret;
+ int i,j;
DEBUG(10, ("AddRequest"));
DEBUGADD(10, (" dn: %s", req->dn));
- part = ldapsrv_get_partition(call->conn, req->dn, LDAP_SEARCH_SCOPE_SUB);
+ local_ctx = talloc_named(call, 0, "AddRequest local memory context");
+ NT_STATUS_HAVE_NO_MEMORY(local_ctx);
+
+ dn = ldb_dn_explode(local_ctx, req->dn);
+ VALID_DN_SYNTAX(dn,1);
+
+ DEBUG(10, ("AddRequest: dn: [%s]\n", req->dn));
+
+ msg = talloc(local_ctx, struct ldb_message);
+ NT_STATUS_HAVE_NO_MEMORY(msg);
+
+ msg->dn = dn;
+ msg->private_data = NULL;
+ msg->num_elements = 0;
+ msg->elements = NULL;
+
+ if (req->num_attributes > 0) {
+ msg->num_elements = req->num_attributes;
+ msg->elements = talloc_array(msg, struct ldb_message_element, msg->num_elements);
+ NT_STATUS_HAVE_NO_MEMORY(msg->elements);
+
+ for (i=0; i < msg->num_elements; i++) {
+ msg->elements[i].name = discard_const_p(char, req->attributes[i].name);
+ msg->elements[i].flags = 0;
+ msg->elements[i].num_values = 0;
+ msg->elements[i].values = NULL;
+
+ if (req->attributes[i].num_values > 0) {
+ msg->elements[i].num_values = req->attributes[i].num_values;
+ msg->elements[i].values = talloc_array(msg, struct ldb_val, msg->elements[i].num_values);
+ NT_STATUS_HAVE_NO_MEMORY(msg->elements[i].values);
+
+ for (j=0; j < msg->elements[i].num_values; j++) {
+ if (!(req->attributes[i].values[j].length > 0)) {
+ result = LDAP_OTHER;
+ errstr = "Empty attribute values are not allowed";
+ goto reply;
+ }
+ msg->elements[i].values[j].length = req->attributes[i].values[j].length;
+ msg->elements[i].values[j].data = req->attributes[i].values[j].data;
+ }
+ } else {
+ result = LDAP_OTHER;
+ errstr = "No attribute values are not allowed";
+ goto reply;
+ }
+ }
+ } else {
+ result = LDAP_OTHER;
+ errstr = "No attributes are not allowed";
+ goto reply;
+ }
+
+reply:
+ add_reply = ldapsrv_init_reply(call, LDAP_TAG_AddResponse);
+ NT_STATUS_HAVE_NO_MEMORY(add_reply);
- if (!part->ops->Add) {
- return ldapsrv_unwilling(call, 53);
+ if (result == LDAP_SUCCESS) {
+ ldb_ret = ldb_add(samdb, msg);
+ result = map_ldb_error(samdb, ldb_ret, &errstr);
}
- return part->ops->Add(part, call);
+ add_result = &add_reply->msg->r.AddResponse;
+ add_result->dn = NULL;
+ add_result->resultcode = result;
+ add_result->errormessage = (errstr?talloc_strdup(add_reply,errstr):NULL);
+ add_result->referral = NULL;
+
+ talloc_free(local_ctx);
+
+ ldapsrv_queue_reply(call, add_reply);
+ return NT_STATUS_OK;
+
}
static NTSTATUS ldapsrv_DelRequest(struct ldapsrv_call *call)
{
struct ldap_DelRequest *req = &call->request->r.DelRequest;
- struct ldapsrv_partition *part;
+ struct ldap_Result *del_result;
+ struct ldapsrv_reply *del_reply;
+ void *local_ctx;
+ struct ldb_context *samdb = call->conn->ldb;
+ struct ldb_dn *dn;
+ const char *errstr = NULL;
+ int result = LDAP_SUCCESS;
+ int ldb_ret;
DEBUG(10, ("DelRequest"));
DEBUGADD(10, (" dn: %s", req->dn));
- part = ldapsrv_get_partition(call->conn, req->dn, LDAP_SEARCH_SCOPE_SUB);
+ local_ctx = talloc_named(call, 0, "DelRequest local memory context");
+ NT_STATUS_HAVE_NO_MEMORY(local_ctx);
+
+ dn = ldb_dn_explode(local_ctx, req->dn);
+ VALID_DN_SYNTAX(dn,1);
+
+ DEBUG(10, ("DelRequest: dn: [%s]\n", req->dn));
- if (!part->ops->Del) {
- return ldapsrv_unwilling(call, 53);
+reply:
+ del_reply = ldapsrv_init_reply(call, LDAP_TAG_DelResponse);
+ NT_STATUS_HAVE_NO_MEMORY(del_reply);
+
+ if (result == LDAP_SUCCESS) {
+ ldb_ret = ldb_delete(samdb, dn);
+ result = map_ldb_error(samdb, ldb_ret, &errstr);
}
- return part->ops->Del(part, call);
+ del_result = &del_reply->msg->r.DelResponse;
+ del_result->dn = NULL;
+ del_result->resultcode = result;
+ del_result->errormessage = (errstr?talloc_strdup(del_reply,errstr):NULL);
+ del_result->referral = NULL;
+
+ talloc_free(local_ctx);
+
+ ldapsrv_queue_reply(call, del_reply);
+ return NT_STATUS_OK;
}
static NTSTATUS ldapsrv_ModifyDNRequest(struct ldapsrv_call *call)
{
struct ldap_ModifyDNRequest *req = &call->request->r.ModifyDNRequest;
- struct ldapsrv_partition *part;
+ struct ldap_Result *modifydn;
+ struct ldapsrv_reply *modifydn_r;
+ void *local_ctx;
+ struct ldb_context *samdb = call->conn->ldb;
+ struct ldb_dn *olddn, *newdn, *newrdn;
+ struct ldb_dn *parentdn = NULL;
+ const char *errstr = NULL;
+ int result = LDAP_SUCCESS;
+ int ldb_ret;
DEBUG(10, ("ModifyDNRequrest"));
DEBUGADD(10, (" dn: %s", req->dn));
DEBUGADD(10, (" newrdn: %s", req->newrdn));
- part = ldapsrv_get_partition(call->conn, req->dn, LDAP_SEARCH_SCOPE_SUB);
+ local_ctx = talloc_named(call, 0, "ModifyDNRequest local memory context");
+ NT_STATUS_HAVE_NO_MEMORY(local_ctx);
+
+ olddn = ldb_dn_explode(local_ctx, req->dn);
+ VALID_DN_SYNTAX(olddn, 2);
+
+ newrdn = ldb_dn_explode(local_ctx, req->newrdn);
+ VALID_DN_SYNTAX(newrdn, 1);
+
+ DEBUG(10, ("ModifyDNRequest: olddn: [%s]\n", req->dn));
+ DEBUG(10, ("ModifyDNRequest: newrdn: [%s]\n", req->newrdn));
- if (!part->ops->ModifyDN) {
- return ldapsrv_unwilling(call, 53);
+ /* we can't handle the rename if we should not remove the old dn */
+ if (!req->deleteolddn) {
+ result = LDAP_UNWILLING_TO_PERFORM;
+ errstr = "Old RDN must be deleted";
+ goto reply;
}
- return part->ops->ModifyDN(part, call);
+ if (newrdn->comp_num > 1) {
+ result = LDAP_NAMING_VIOLATION;
+ errstr = "Error new RDN invalid";
+ goto reply;
+ }
+
+ if (req->newsuperior) {
+ parentdn = ldb_dn_explode(local_ctx, req->newsuperior);
+ VALID_DN_SYNTAX(parentdn, 0);
+ DEBUG(10, ("ModifyDNRequest: newsuperior: [%s]\n", req->newsuperior));
+
+ if (parentdn->comp_num < 1) {
+ result = LDAP_AFFECTS_MULTIPLE_DSAS;
+ errstr = "Error new Superior DN invalid";
+ goto reply;
+ }
+ }
+
+ if (!parentdn) {
+ parentdn = ldb_dn_get_parent(local_ctx, olddn);
+ NT_STATUS_HAVE_NO_MEMORY(parentdn);
+ }
+
+ newdn = ldb_dn_make_child(local_ctx, ldb_dn_get_rdn(local_ctx, newrdn), parentdn);
+ NT_STATUS_HAVE_NO_MEMORY(newdn);
+
+reply:
+ modifydn_r = ldapsrv_init_reply(call, LDAP_TAG_ModifyDNResponse);
+ NT_STATUS_HAVE_NO_MEMORY(modifydn_r);
+
+ if (result == LDAP_SUCCESS) {
+ ldb_ret = ldb_rename(samdb, olddn, newdn);
+ result = map_ldb_error(samdb, ldb_ret, &errstr);
+ }
+
+ modifydn = &modifydn_r->msg->r.ModifyDNResponse;
+ modifydn->dn = NULL;
+ modifydn->resultcode = result;
+ modifydn->errormessage = (errstr?talloc_strdup(modifydn_r,errstr):NULL);
+ modifydn->referral = NULL;
+
+ talloc_free(local_ctx);
+
+ ldapsrv_queue_reply(call, modifydn_r);
+ return NT_STATUS_OK;
}
static NTSTATUS ldapsrv_CompareRequest(struct ldapsrv_call *call)
{
struct ldap_CompareRequest *req = &call->request->r.CompareRequest;
- struct ldapsrv_partition *part;
+ struct ldap_Result *compare;
+ struct ldapsrv_reply *compare_r;
+ void *local_ctx;
+ struct ldb_context *samdb = call->conn->ldb;
+ struct ldb_result *res = NULL;
+ struct ldb_dn *dn;
+ const char *attrs[1];
+ const char *errstr = NULL;
+ const char *filter = NULL;
+ int result = LDAP_SUCCESS;
+ int ldb_ret;
DEBUG(10, ("CompareRequest"));
DEBUGADD(10, (" dn: %s", req->dn));
- part = ldapsrv_get_partition(call->conn, req->dn, LDAP_SEARCH_SCOPE_SUB);
-
- if (!part->ops->Compare) {
- return ldapsrv_unwilling(call, 53);
+ local_ctx = talloc_named(call, 0, "CompareRequest local_memory_context");
+ NT_STATUS_HAVE_NO_MEMORY(local_ctx);
+
+ dn = ldb_dn_explode(local_ctx, req->dn);
+ VALID_DN_SYNTAX(dn, 1);
+
+ DEBUG(10, ("CompareRequest: dn: [%s]\n", req->dn));
+ filter = talloc_asprintf(local_ctx, "(%s=%*s)", req->attribute,
+ (int)req->value.length, req->value.data);
+ NT_STATUS_HAVE_NO_MEMORY(filter);
+
+ DEBUGADD(10, ("CompareRequest: attribute: [%s]\n", filter));
+
+ attrs[0] = NULL;
+
+reply:
+ compare_r = ldapsrv_init_reply(call, LDAP_TAG_CompareResponse);
+ NT_STATUS_HAVE_NO_MEMORY(compare_r);
+
+ if (result == LDAP_SUCCESS) {
+ ldb_ret = ldb_search(samdb, dn, LDB_SCOPE_BASE, filter, attrs, &res);
+ talloc_steal(samdb, res);
+ if (ldb_ret != LDB_SUCCESS) {
+ result = map_ldb_error(samdb, ldb_ret, &errstr);
+ DEBUG(10,("CompareRequest: error: %s\n", errstr));
+ } else if (res->count == 0) {
+ DEBUG(10,("CompareRequest: doesn't matched\n"));
+ result = LDAP_COMPARE_FALSE;
+ errstr = NULL;
+ } else if (res->count == 1) {
+ DEBUG(10,("CompareRequest: matched\n"));
+ result = LDAP_COMPARE_TRUE;
+ errstr = NULL;
+ } else if (res->count > 1) {
+ result = LDAP_OTHER;
+ errstr = "too many objects match";
+ DEBUG(10,("CompareRequest: %d results: %s\n", res->count, errstr));
+ }
}
- return part->ops->Compare(part, call);
+ compare = &compare_r->msg->r.CompareResponse;
+ compare->dn = NULL;
+ compare->resultcode = result;
+ compare->errormessage = (errstr?talloc_strdup(compare_r,errstr):NULL);
+ compare->referral = NULL;
+
+ talloc_free(local_ctx);
+
+ ldapsrv_queue_reply(call, compare_r);
+ return NT_STATUS_OK;
}
static NTSTATUS ldapsrv_AbandonRequest(struct ldapsrv_call *call)