s4/ldap_backend: fix a NULL dereference
[Samba.git] / source4 / ldap_server / ldap_backend.c
blob3bcd984f1498857f03f8eb3e9da58333fb07f3f3
1 /*
2 Unix SMB/CIFS implementation.
3 LDAP server
4 Copyright (C) Stefan Metzmacher 2004
5 Copyright (C) Matthias Dieter Wallnöfer 2009
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 #include "includes.h"
22 #include "ldap_server/ldap_server.h"
23 #include "../lib/util/dlinklist.h"
24 #include "auth/credentials/credentials.h"
25 #include "auth/gensec/gensec.h"
26 #include "auth/gensec/gensec_internal.h" /* TODO: remove this */
27 #include "auth/common_auth.h"
28 #include "param/param.h"
29 #include "samba/service_stream.h"
30 #include "dsdb/samdb/samdb.h"
31 #include <ldb_errors.h>
32 #include <ldb_module.h>
33 #include "ldb_wrap.h"
34 #include "lib/tsocket/tsocket.h"
35 #include "libcli/ldap/ldap_proto.h"
36 #include "source4/auth/auth.h"
38 static int map_ldb_error(TALLOC_CTX *mem_ctx, int ldb_err,
39 const char *add_err_string, const char **errstring)
41 WERROR err;
43 /* Certain LDB modules need to return very special WERROR codes. Proof
44 * for them here and if they exist skip the rest of the mapping. */
45 if (add_err_string != NULL) {
46 char *endptr;
47 strtol(add_err_string, &endptr, 16);
48 if (endptr != add_err_string) {
49 *errstring = add_err_string;
50 return ldb_err;
54 /* Otherwise we calculate here a generic, but appropriate WERROR. */
56 switch (ldb_err) {
57 case LDB_SUCCESS:
58 err = WERR_OK;
59 break;
60 case LDB_ERR_OPERATIONS_ERROR:
61 err = WERR_DS_OPERATIONS_ERROR;
62 break;
63 case LDB_ERR_PROTOCOL_ERROR:
64 err = WERR_DS_PROTOCOL_ERROR;
65 break;
66 case LDB_ERR_TIME_LIMIT_EXCEEDED:
67 err = WERR_DS_TIMELIMIT_EXCEEDED;
68 break;
69 case LDB_ERR_SIZE_LIMIT_EXCEEDED:
70 err = WERR_DS_SIZELIMIT_EXCEEDED;
71 break;
72 case LDB_ERR_COMPARE_FALSE:
73 err = WERR_DS_COMPARE_FALSE;
74 break;
75 case LDB_ERR_COMPARE_TRUE:
76 err = WERR_DS_COMPARE_TRUE;
77 break;
78 case LDB_ERR_AUTH_METHOD_NOT_SUPPORTED:
79 err = WERR_DS_AUTH_METHOD_NOT_SUPPORTED;
80 break;
81 case LDB_ERR_STRONG_AUTH_REQUIRED:
82 err = WERR_DS_STRONG_AUTH_REQUIRED;
83 break;
84 case LDB_ERR_REFERRAL:
85 err = WERR_DS_REFERRAL;
86 break;
87 case LDB_ERR_ADMIN_LIMIT_EXCEEDED:
88 err = WERR_DS_ADMIN_LIMIT_EXCEEDED;
89 break;
90 case LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION:
91 err = WERR_DS_UNAVAILABLE_CRIT_EXTENSION;
92 break;
93 case LDB_ERR_CONFIDENTIALITY_REQUIRED:
94 err = WERR_DS_CONFIDENTIALITY_REQUIRED;
95 break;
96 case LDB_ERR_SASL_BIND_IN_PROGRESS:
97 err = WERR_DS_BUSY;
98 break;
99 case LDB_ERR_NO_SUCH_ATTRIBUTE:
100 err = WERR_DS_NO_ATTRIBUTE_OR_VALUE;
101 break;
102 case LDB_ERR_UNDEFINED_ATTRIBUTE_TYPE:
103 err = WERR_DS_ATTRIBUTE_TYPE_UNDEFINED;
104 break;
105 case LDB_ERR_INAPPROPRIATE_MATCHING:
106 err = WERR_DS_INAPPROPRIATE_MATCHING;
107 break;
108 case LDB_ERR_CONSTRAINT_VIOLATION:
109 err = WERR_DS_CONSTRAINT_VIOLATION;
110 break;
111 case LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS:
112 err = WERR_DS_ATTRIBUTE_OR_VALUE_EXISTS;
113 break;
114 case LDB_ERR_INVALID_ATTRIBUTE_SYNTAX:
115 err = WERR_DS_INVALID_ATTRIBUTE_SYNTAX;
116 break;
117 case LDB_ERR_NO_SUCH_OBJECT:
118 err = WERR_DS_NO_SUCH_OBJECT;
119 break;
120 case LDB_ERR_ALIAS_PROBLEM:
121 err = WERR_DS_ALIAS_PROBLEM;
122 break;
123 case LDB_ERR_INVALID_DN_SYNTAX:
124 err = WERR_DS_INVALID_DN_SYNTAX;
125 break;
126 case LDB_ERR_ALIAS_DEREFERENCING_PROBLEM:
127 err = WERR_DS_ALIAS_DEREF_PROBLEM;
128 break;
129 case LDB_ERR_INAPPROPRIATE_AUTHENTICATION:
130 err = WERR_DS_INAPPROPRIATE_AUTH;
131 break;
132 case LDB_ERR_INVALID_CREDENTIALS:
133 err = WERR_ACCESS_DENIED;
134 break;
135 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
136 err = WERR_DS_INSUFF_ACCESS_RIGHTS;
137 break;
138 case LDB_ERR_BUSY:
139 err = WERR_DS_BUSY;
140 break;
141 case LDB_ERR_UNAVAILABLE:
142 err = WERR_DS_UNAVAILABLE;
143 break;
144 case LDB_ERR_UNWILLING_TO_PERFORM:
145 err = WERR_DS_UNWILLING_TO_PERFORM;
146 break;
147 case LDB_ERR_LOOP_DETECT:
148 err = WERR_DS_LOOP_DETECT;
149 break;
150 case LDB_ERR_NAMING_VIOLATION:
151 err = WERR_DS_NAMING_VIOLATION;
152 break;
153 case LDB_ERR_OBJECT_CLASS_VIOLATION:
154 err = WERR_DS_OBJ_CLASS_VIOLATION;
155 break;
156 case LDB_ERR_NOT_ALLOWED_ON_NON_LEAF:
157 err = WERR_DS_CANT_ON_NON_LEAF;
158 break;
159 case LDB_ERR_NOT_ALLOWED_ON_RDN:
160 err = WERR_DS_CANT_ON_RDN;
161 break;
162 case LDB_ERR_ENTRY_ALREADY_EXISTS:
163 err = WERR_DS_OBJ_STRING_NAME_EXISTS;
164 break;
165 case LDB_ERR_OBJECT_CLASS_MODS_PROHIBITED:
166 err = WERR_DS_CANT_MOD_OBJ_CLASS;
167 break;
168 case LDB_ERR_AFFECTS_MULTIPLE_DSAS:
169 err = WERR_DS_AFFECTS_MULTIPLE_DSAS;
170 break;
171 default:
172 err = WERR_DS_GENERIC_ERROR;
173 break;
176 *errstring = talloc_asprintf(mem_ctx, "%08X: %s", W_ERROR_V(err),
177 add_err_string != NULL ? add_err_string : ldb_strerror(ldb_err));
179 /* result is 1:1 for now */
180 return ldb_err;
184 connect to the sam database
186 int ldapsrv_backend_Init(struct ldapsrv_connection *conn,
187 char **errstring)
189 bool using_tls = conn->sockets.active == conn->sockets.tls;
190 bool using_seal = conn->gensec != NULL && gensec_have_feature(conn->gensec,
191 GENSEC_FEATURE_SEAL);
192 struct dsdb_encrypted_connection_state *opaque_connection_state = NULL;
194 int ret = samdb_connect_url(conn,
195 conn->connection->event.ctx,
196 conn->lp_ctx,
197 conn->session_info,
198 conn->global_catalog ? LDB_FLG_RDONLY : 0,
199 "sam.ldb",
200 conn->connection->remote_address,
201 &conn->ldb,
202 errstring);
203 if (ret != LDB_SUCCESS) {
204 return ret;
208 * We can safely call ldb_set_opaque() on this ldb as we have
209 * set remote_address above which avoids the ldb handle cache
211 opaque_connection_state = talloc_zero(conn, struct dsdb_encrypted_connection_state);
212 if (opaque_connection_state == NULL) {
213 return LDB_ERR_OPERATIONS_ERROR;
215 opaque_connection_state->using_encrypted_connection = using_tls || using_seal;
216 ret = ldb_set_opaque(conn->ldb,
217 DSDB_OPAQUE_ENCRYPTED_CONNECTION_STATE_NAME,
218 opaque_connection_state);
219 if (ret != LDB_SUCCESS) {
220 DBG_ERR("ldb_set_opaque() failed to store our "
221 "encrypted connection state!\n");
222 return ret;
225 if (conn->server_credentials) {
226 struct gensec_security *gensec_security = NULL;
227 const char **sasl_mechs = NULL;
228 NTSTATUS status;
230 status = samba_server_gensec_start(conn,
231 conn->connection->event.ctx,
232 conn->connection->msg_ctx,
233 conn->lp_ctx,
234 conn->server_credentials,
235 "ldap",
236 &gensec_security);
237 if (!NT_STATUS_IS_OK(status)) {
238 DBG_ERR("samba_server_gensec_start failed: %s\n",
239 nt_errstr(status));
240 return LDB_ERR_OPERATIONS_ERROR;
243 /* ldb can have a different lifetime to conn, so we
244 need to ensure that sasl_mechs lives as long as the
245 ldb does */
246 sasl_mechs = gensec_security_sasl_names(gensec_security,
247 conn->ldb);
248 TALLOC_FREE(gensec_security);
249 if (sasl_mechs == NULL) {
250 DBG_ERR("Failed to get sasl mechs!\n");
251 return LDB_ERR_OPERATIONS_ERROR;
254 ldb_set_opaque(conn->ldb, "supportedSASLMechanisms", sasl_mechs);
257 return LDB_SUCCESS;
260 struct ldapsrv_reply *ldapsrv_init_reply(struct ldapsrv_call *call, uint8_t type)
262 struct ldapsrv_reply *reply;
264 reply = talloc_zero(call, struct ldapsrv_reply);
265 if (!reply) {
266 return NULL;
268 reply->msg = talloc_zero(reply, struct ldap_message);
269 if (reply->msg == NULL) {
270 talloc_free(reply);
271 return NULL;
274 reply->msg->messageid = call->request->messageid;
275 reply->msg->type = type;
276 reply->msg->controls = NULL;
278 return reply;
282 * Encode a reply to an LDAP client as ASN.1, free the original memory
284 static NTSTATUS ldapsrv_encode(TALLOC_CTX *mem_ctx,
285 struct ldapsrv_reply *reply)
287 bool bret = ldap_encode(reply->msg,
288 samba_ldap_control_handlers(),
289 &reply->blob,
290 mem_ctx);
291 if (!bret) {
292 DEBUG(0,("Failed to encode ldap reply of type %d: "
293 "ldap_encode() failed\n",
294 reply->msg->type));
295 TALLOC_FREE(reply->msg);
296 return NT_STATUS_NO_MEMORY;
299 TALLOC_FREE(reply->msg);
300 talloc_set_name_const(reply->blob.data,
301 "Outgoing, encoded single LDAP reply");
303 return NT_STATUS_OK;
307 * Queue a reply (encoding it also), even if it would exceed the
308 * limit. This allows the error packet with LDAP_SIZE_LIMIT_EXCEEDED
309 * to be sent
311 static NTSTATUS ldapsrv_queue_reply_forced(struct ldapsrv_call *call,
312 struct ldapsrv_reply *reply)
314 NTSTATUS status = ldapsrv_encode(call, reply);
316 if (NT_STATUS_IS_OK(status)) {
317 DLIST_ADD_END(call->replies, reply);
319 return status;
323 * Queue a reply (encoding it also) but check we do not send more than
324 * LDAP_SERVER_MAX_REPLY_SIZE of responses as a way to limit the
325 * amount of data a client can make us allocate.
327 NTSTATUS ldapsrv_queue_reply(struct ldapsrv_call *call, struct ldapsrv_reply *reply)
329 NTSTATUS status = ldapsrv_encode(call, reply);
331 if (!NT_STATUS_IS_OK(status)) {
332 return status;
335 if (call->reply_size > call->reply_size + reply->blob.length
336 || call->reply_size + reply->blob.length > LDAP_SERVER_MAX_REPLY_SIZE) {
337 DBG_WARNING("Refusing to queue LDAP search response size "
338 "of more than %zu bytes\n",
339 LDAP_SERVER_MAX_REPLY_SIZE);
340 TALLOC_FREE(reply->blob.data);
341 return NT_STATUS_FILE_TOO_LARGE;
344 call->reply_size += reply->blob.length;
346 DLIST_ADD_END(call->replies, reply);
348 return status;
351 static NTSTATUS ldapsrv_unwilling(struct ldapsrv_call *call, int error)
353 struct ldapsrv_reply *reply;
354 struct ldap_ExtendedResponse *r;
356 DEBUG(10,("Unwilling type[%d] id[%d]\n", call->request->type, call->request->messageid));
358 reply = ldapsrv_init_reply(call, LDAP_TAG_ExtendedResponse);
359 if (!reply) {
360 return NT_STATUS_NO_MEMORY;
363 r = &reply->msg->r.ExtendedResponse;
364 r->response.resultcode = error;
365 r->response.dn = NULL;
366 r->response.errormessage = NULL;
367 r->response.referral = NULL;
368 r->oid = NULL;
369 r->value = NULL;
371 ldapsrv_queue_reply(call, reply);
372 return NT_STATUS_OK;
375 static int ldapsrv_add_with_controls(struct ldapsrv_call *call,
376 const struct ldb_message *message,
377 struct ldb_control **controls,
378 struct ldb_result *res)
380 struct ldb_context *ldb = call->conn->ldb;
381 struct ldb_request *req;
382 int ret;
384 ret = ldb_msg_sanity_check(ldb, message);
385 if (ret != LDB_SUCCESS) {
386 return ret;
389 ret = ldb_build_add_req(&req, ldb, ldb,
390 message,
391 controls,
392 res,
393 ldb_modify_default_callback,
394 NULL);
396 if (ret != LDB_SUCCESS) return ret;
398 if (call->conn->global_catalog) {
399 return ldb_error(ldb, LDB_ERR_UNWILLING_TO_PERFORM, "modify forbidden on global catalog port");
401 ldb_request_add_control(req, DSDB_CONTROL_NO_GLOBAL_CATALOG, false, NULL);
403 ret = ldb_transaction_start(ldb);
404 if (ret != LDB_SUCCESS) {
405 return ret;
408 if (!call->conn->is_privileged) {
409 ldb_req_mark_untrusted(req);
412 LDB_REQ_SET_LOCATION(req);
414 ret = ldb_request(ldb, req);
415 if (ret == LDB_SUCCESS) {
416 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
419 if (ret == LDB_SUCCESS) {
420 ret = ldb_transaction_commit(ldb);
422 else {
423 ldb_transaction_cancel(ldb);
426 talloc_free(req);
427 return ret;
430 /* create and execute a modify request */
431 static int ldapsrv_mod_with_controls(struct ldapsrv_call *call,
432 const struct ldb_message *message,
433 struct ldb_control **controls,
434 struct ldb_result *res)
436 struct ldb_context *ldb = call->conn->ldb;
437 struct ldb_request *req;
438 int ret;
440 ret = ldb_msg_sanity_check(ldb, message);
441 if (ret != LDB_SUCCESS) {
442 return ret;
445 ret = ldb_build_mod_req(&req, ldb, ldb,
446 message,
447 controls,
448 res,
449 ldb_modify_default_callback,
450 NULL);
452 if (ret != LDB_SUCCESS) {
453 return ret;
456 if (call->conn->global_catalog) {
457 return ldb_error(ldb, LDB_ERR_UNWILLING_TO_PERFORM, "modify forbidden on global catalog port");
459 ldb_request_add_control(req, DSDB_CONTROL_NO_GLOBAL_CATALOG, false, NULL);
461 ret = ldb_transaction_start(ldb);
462 if (ret != LDB_SUCCESS) {
463 return ret;
466 if (!call->conn->is_privileged) {
467 ldb_req_mark_untrusted(req);
470 LDB_REQ_SET_LOCATION(req);
472 ret = ldb_request(ldb, req);
473 if (ret == LDB_SUCCESS) {
474 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
477 if (ret == LDB_SUCCESS) {
478 ret = ldb_transaction_commit(ldb);
480 else {
481 ldb_transaction_cancel(ldb);
484 talloc_free(req);
485 return ret;
488 /* create and execute a delete request */
489 static int ldapsrv_del_with_controls(struct ldapsrv_call *call,
490 struct ldb_dn *dn,
491 struct ldb_control **controls,
492 struct ldb_result *res)
494 struct ldb_context *ldb = call->conn->ldb;
495 struct ldb_request *req;
496 int ret;
498 ret = ldb_build_del_req(&req, ldb, ldb,
500 controls,
501 res,
502 ldb_modify_default_callback,
503 NULL);
505 if (ret != LDB_SUCCESS) return ret;
507 if (call->conn->global_catalog) {
508 return ldb_error(ldb, LDB_ERR_UNWILLING_TO_PERFORM, "modify forbidden on global catalog port");
510 ldb_request_add_control(req, DSDB_CONTROL_NO_GLOBAL_CATALOG, false, NULL);
512 ret = ldb_transaction_start(ldb);
513 if (ret != LDB_SUCCESS) {
514 return ret;
517 if (!call->conn->is_privileged) {
518 ldb_req_mark_untrusted(req);
521 LDB_REQ_SET_LOCATION(req);
523 ret = ldb_request(ldb, req);
524 if (ret == LDB_SUCCESS) {
525 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
528 if (ret == LDB_SUCCESS) {
529 ret = ldb_transaction_commit(ldb);
531 else {
532 ldb_transaction_cancel(ldb);
535 talloc_free(req);
536 return ret;
539 static int ldapsrv_rename_with_controls(struct ldapsrv_call *call,
540 struct ldb_dn *olddn,
541 struct ldb_dn *newdn,
542 struct ldb_control **controls,
543 struct ldb_result *res)
545 struct ldb_context *ldb = call->conn->ldb;
546 struct ldb_request *req;
547 int ret;
549 ret = ldb_build_rename_req(&req, ldb, ldb,
550 olddn,
551 newdn,
552 controls,
553 res,
554 ldb_modify_default_callback,
555 NULL);
557 if (ret != LDB_SUCCESS) return ret;
559 if (call->conn->global_catalog) {
560 return ldb_error(ldb, LDB_ERR_UNWILLING_TO_PERFORM, "modify forbidden on global catalog port");
562 ldb_request_add_control(req, DSDB_CONTROL_NO_GLOBAL_CATALOG, false, NULL);
564 ret = ldb_transaction_start(ldb);
565 if (ret != LDB_SUCCESS) {
566 return ret;
569 if (!call->conn->is_privileged) {
570 ldb_req_mark_untrusted(req);
573 LDB_REQ_SET_LOCATION(req);
575 ret = ldb_request(ldb, req);
576 if (ret == LDB_SUCCESS) {
577 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
580 if (ret == LDB_SUCCESS) {
581 ret = ldb_transaction_commit(ldb);
583 else {
584 ldb_transaction_cancel(ldb);
587 talloc_free(req);
588 return ret;
593 struct ldapsrv_context {
594 struct ldapsrv_call *call;
595 int extended_type;
596 bool attributesonly;
597 struct ldb_control **controls;
598 size_t count; /* For notification only */
601 static int ldap_server_search_callback(struct ldb_request *req, struct ldb_reply *ares)
603 struct ldapsrv_context *ctx = talloc_get_type(req->context, struct ldapsrv_context);
604 struct ldapsrv_call *call = ctx->call;
605 struct ldb_context *ldb = call->conn->ldb;
606 unsigned int j;
607 struct ldapsrv_reply *ent_r = NULL;
608 struct ldap_SearchResEntry *ent;
609 int ret;
610 NTSTATUS status;
612 if (!ares) {
613 return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
615 if (ares->error != LDB_SUCCESS) {
616 return ldb_request_done(req, ares->error);
619 switch (ares->type) {
620 case LDB_REPLY_ENTRY:
622 struct ldb_message *msg = ares->message;
623 ent_r = ldapsrv_init_reply(call, LDAP_TAG_SearchResultEntry);
624 if (ent_r == NULL) {
625 return ldb_oom(ldb);
628 ctx->count++;
631 * Put the LDAP search response data under ent_r->msg
632 * so we can free that later once encoded
634 talloc_steal(ent_r->msg, msg);
636 ent = &ent_r->msg->r.SearchResultEntry;
637 ent->dn = ldb_dn_get_extended_linearized(ent_r, msg->dn,
638 ctx->extended_type);
639 ent->num_attributes = 0;
640 ent->attributes = NULL;
641 if (msg->num_elements == 0) {
642 goto queue_reply;
644 ent->num_attributes = msg->num_elements;
645 ent->attributes = talloc_array(ent_r, struct ldb_message_element, ent->num_attributes);
646 if (ent->attributes == NULL) {
647 return ldb_oom(ldb);
650 for (j=0; j < ent->num_attributes; j++) {
651 ent->attributes[j].name = msg->elements[j].name;
652 ent->attributes[j].num_values = 0;
653 ent->attributes[j].values = NULL;
654 if (ctx->attributesonly && (msg->elements[j].num_values == 0)) {
655 continue;
657 ent->attributes[j].num_values = msg->elements[j].num_values;
658 ent->attributes[j].values = msg->elements[j].values;
660 queue_reply:
661 status = ldapsrv_queue_reply(call, ent_r);
662 if (NT_STATUS_EQUAL(status, NT_STATUS_FILE_TOO_LARGE)) {
663 ret = ldb_request_done(req,
664 LDB_ERR_SIZE_LIMIT_EXCEEDED);
665 ldb_asprintf_errstring(ldb,
666 "LDAP search response size "
667 "limited to %zu bytes\n",
668 LDAP_SERVER_MAX_REPLY_SIZE);
669 } else if (!NT_STATUS_IS_OK(status)) {
670 ret = ldb_request_done(req,
671 ldb_operr(ldb));
672 } else {
673 ret = LDB_SUCCESS;
675 break;
677 case LDB_REPLY_REFERRAL:
679 struct ldap_SearchResRef *ent_ref;
682 * TODO: This should be handled by the notification
683 * module not here
685 if (call->notification.busy) {
686 ret = LDB_SUCCESS;
687 break;
690 ent_r = ldapsrv_init_reply(call, LDAP_TAG_SearchResultReference);
691 if (ent_r == NULL) {
692 return ldb_oom(ldb);
696 * Put the LDAP referral data under ent_r->msg
697 * so we can free that later once encoded
699 talloc_steal(ent_r->msg, ares->referral);
701 ent_ref = &ent_r->msg->r.SearchResultReference;
702 ent_ref->referral = ares->referral;
704 status = ldapsrv_queue_reply(call, ent_r);
705 if (!NT_STATUS_IS_OK(status)) {
706 ret = LDB_ERR_OPERATIONS_ERROR;
707 } else {
708 ret = LDB_SUCCESS;
710 break;
712 case LDB_REPLY_DONE:
715 * We don't queue the reply for this one, we let that
716 * happen outside
718 ctx->controls = talloc_move(ctx, &ares->controls);
720 TALLOC_FREE(ares);
721 return ldb_request_done(req, LDB_SUCCESS);
723 default:
724 /* Doesn't happen */
725 ret = LDB_ERR_OPERATIONS_ERROR;
727 TALLOC_FREE(ares);
729 return ret;
733 static NTSTATUS ldapsrv_SearchRequest(struct ldapsrv_call *call)
735 struct ldap_SearchRequest *req = &call->request->r.SearchRequest;
736 struct ldap_Result *done;
737 struct ldapsrv_reply *done_r;
738 TALLOC_CTX *local_ctx;
739 struct ldapsrv_context *callback_ctx = NULL;
740 struct ldb_context *samdb = talloc_get_type(call->conn->ldb, struct ldb_context);
741 struct ldb_dn *basedn;
742 struct ldb_request *lreq;
743 struct ldb_control *search_control;
744 struct ldb_search_options_control *search_options;
745 struct ldb_control *extended_dn_control;
746 struct ldb_extended_dn_control *extended_dn_decoded = NULL;
747 struct ldb_control *notification_control = NULL;
748 enum ldb_scope scope = LDB_SCOPE_DEFAULT;
749 const char **attrs = NULL;
750 const char *scope_str, *errstr = NULL;
751 int result = -1;
752 int ldb_ret = -1;
753 unsigned int i;
754 int extended_type = 1;
757 * Warn for searches that are longer than 1/4 of the
758 * search_timeout, being 30sec by default
760 struct timeval start_time = timeval_current();
761 struct timeval warning_time
762 = timeval_add(&start_time,
763 call->conn->limits.search_timeout / 4,
766 local_ctx = talloc_new(call);
767 NT_STATUS_HAVE_NO_MEMORY(local_ctx);
769 basedn = ldb_dn_new(local_ctx, samdb, req->basedn);
770 NT_STATUS_HAVE_NO_MEMORY(basedn);
772 switch (req->scope) {
773 case LDAP_SEARCH_SCOPE_BASE:
774 scope = LDB_SCOPE_BASE;
775 break;
776 case LDAP_SEARCH_SCOPE_SINGLE:
777 scope = LDB_SCOPE_ONELEVEL;
778 break;
779 case LDAP_SEARCH_SCOPE_SUB:
780 scope = LDB_SCOPE_SUBTREE;
781 break;
782 default:
783 result = LDAP_PROTOCOL_ERROR;
784 map_ldb_error(local_ctx, LDB_ERR_PROTOCOL_ERROR, NULL,
785 &errstr);
786 scope_str = "<Invalid scope>";
787 errstr = talloc_asprintf(local_ctx,
788 "%s. Invalid scope", errstr);
789 goto reply;
791 scope_str = dsdb_search_scope_as_string(scope);
793 DEBUG(10,("SearchRequest: scope: [%s]\n", scope_str));
795 if (req->num_attributes >= 1) {
796 attrs = talloc_array(local_ctx, const char *, req->num_attributes+1);
797 NT_STATUS_HAVE_NO_MEMORY(attrs);
799 for (i=0; i < req->num_attributes; i++) {
800 DEBUG(10,("SearchRequest: attrs: [%s]\n",req->attributes[i]));
801 attrs[i] = req->attributes[i];
803 attrs[i] = NULL;
806 DEBUG(5,("ldb_request %s dn=%s filter=%s\n",
807 scope_str, req->basedn, ldb_filter_from_tree(call, req->tree)));
809 callback_ctx = talloc_zero(local_ctx, struct ldapsrv_context);
810 NT_STATUS_HAVE_NO_MEMORY(callback_ctx);
811 callback_ctx->call = call;
812 callback_ctx->extended_type = extended_type;
813 callback_ctx->attributesonly = req->attributesonly;
815 ldb_ret = ldb_build_search_req_ex(&lreq, samdb, local_ctx,
816 basedn, scope,
817 req->tree, attrs,
818 call->request->controls,
819 callback_ctx,
820 ldap_server_search_callback,
821 NULL);
823 if (ldb_ret != LDB_SUCCESS) {
824 goto reply;
827 if (call->conn->global_catalog) {
828 search_control = ldb_request_get_control(lreq, LDB_CONTROL_SEARCH_OPTIONS_OID);
830 search_options = NULL;
831 if (search_control) {
832 search_options = talloc_get_type(search_control->data, struct ldb_search_options_control);
833 search_options->search_options |= LDB_SEARCH_OPTION_PHANTOM_ROOT;
834 } else {
835 search_options = talloc(lreq, struct ldb_search_options_control);
836 NT_STATUS_HAVE_NO_MEMORY(search_options);
837 search_options->search_options = LDB_SEARCH_OPTION_PHANTOM_ROOT;
838 ldb_request_add_control(lreq, LDB_CONTROL_SEARCH_OPTIONS_OID, false, search_options);
840 } else {
841 ldb_request_add_control(lreq, DSDB_CONTROL_NO_GLOBAL_CATALOG, false, NULL);
844 extended_dn_control = ldb_request_get_control(lreq, LDB_CONTROL_EXTENDED_DN_OID);
846 if (extended_dn_control) {
847 if (extended_dn_control->data) {
848 extended_dn_decoded = talloc_get_type(extended_dn_control->data, struct ldb_extended_dn_control);
849 extended_type = extended_dn_decoded->type;
850 } else {
851 extended_type = 0;
853 callback_ctx->extended_type = extended_type;
856 notification_control = ldb_request_get_control(lreq, LDB_CONTROL_NOTIFICATION_OID);
857 if (notification_control != NULL) {
858 const struct ldapsrv_call *pc = NULL;
859 size_t count = 0;
861 for (pc = call->conn->pending_calls; pc != NULL; pc = pc->next) {
862 count += 1;
865 if (count >= call->conn->limits.max_notifications) {
866 DEBUG(10,("SearchRequest: error MaxNotificationPerConn\n"));
867 result = map_ldb_error(local_ctx,
868 LDB_ERR_ADMIN_LIMIT_EXCEEDED,
869 "MaxNotificationPerConn reached",
870 &errstr);
871 goto reply;
875 * For now we need to do periodic retries on our own.
876 * As the dsdb_notification module will return after each run.
878 call->notification.busy = true;
882 const char *scheme = NULL;
883 switch (call->conn->referral_scheme) {
884 case LDAP_REFERRAL_SCHEME_LDAPS:
885 scheme = "ldaps";
886 break;
887 default:
888 scheme = "ldap";
890 ldb_ret = ldb_set_opaque(
891 samdb,
892 LDAP_REFERRAL_SCHEME_OPAQUE,
893 discard_const_p(char *, scheme));
894 if (ldb_ret != LDB_SUCCESS) {
895 goto reply;
900 time_t timeout = call->conn->limits.search_timeout;
902 if (timeout == 0
903 || (req->timelimit != 0
904 && req->timelimit < timeout))
906 timeout = req->timelimit;
908 ldb_set_timeout(samdb, lreq, timeout);
911 if (!call->conn->is_privileged) {
912 ldb_req_mark_untrusted(lreq);
915 LDB_REQ_SET_LOCATION(lreq);
917 ldb_ret = ldb_request(samdb, lreq);
919 if (ldb_ret != LDB_SUCCESS) {
920 goto reply;
923 ldb_ret = ldb_wait(lreq->handle, LDB_WAIT_ALL);
925 if (ldb_ret == LDB_SUCCESS) {
926 if (call->notification.busy) {
927 /* Move/Add it to the end */
928 DLIST_DEMOTE(call->conn->pending_calls, call);
929 call->notification.generation =
930 call->conn->service->notification.generation;
932 if (callback_ctx->count != 0) {
933 call->notification.generation += 1;
934 ldapsrv_notification_retry_setup(call->conn->service,
935 true);
938 talloc_free(local_ctx);
939 return NT_STATUS_OK;
943 reply:
946 * This looks like duplicated code - because it is - but
947 * otherwise the work in the parameters will be done
948 * regardless, this way the functions only execute when the
949 * log level is set.
951 * The basedn is re-obtained as a string to escape it
953 if ((req->timelimit == 0 || call->conn->limits.search_timeout < req->timelimit)
954 && ldb_ret == LDB_ERR_TIME_LIMIT_EXCEEDED) {
955 struct dom_sid_buf sid_buf;
956 DBG_WARNING("MaxQueryDuration(%d) timeout exceeded "
957 "in SearchRequest by %s from %s filter: [%s] "
958 "basedn: [%s] "
959 "scope: [%s]\n",
960 call->conn->limits.search_timeout,
961 dom_sid_str_buf(&call->conn->session_info->security_token->sids[0],
962 &sid_buf),
963 tsocket_address_string(call->conn->connection->remote_address,
964 call),
965 ldb_filter_from_tree(call, req->tree),
966 ldb_dn_get_extended_linearized(call, basedn, 1),
967 scope_str);
968 for (i=0; i < req->num_attributes; i++) {
969 DBG_WARNING("MaxQueryDuration timeout exceeded attrs: [%s]\n",
970 req->attributes[i]);
973 } else if (timeval_expired(&warning_time)) {
974 struct dom_sid_buf sid_buf;
975 DBG_NOTICE("Long LDAP Query: Duration was %.2fs, "
976 "MaxQueryDuration(%d)/4 == %d "
977 "in SearchRequest by %s from %s filter: [%s] "
978 "basedn: [%s] "
979 "scope: [%s] "
980 "result: %s\n",
981 timeval_elapsed(&start_time),
982 call->conn->limits.search_timeout,
983 call->conn->limits.search_timeout / 4,
984 dom_sid_str_buf(&call->conn->session_info->security_token->sids[0],
985 &sid_buf),
986 tsocket_address_string(call->conn->connection->remote_address,
987 call),
988 ldb_filter_from_tree(call, req->tree),
989 ldb_dn_get_extended_linearized(call, basedn, 1),
990 scope_str,
991 ldb_strerror(ldb_ret));
992 for (i=0; i < req->num_attributes; i++) {
993 DBG_NOTICE("Long LDAP Query attrs: [%s]\n",
994 req->attributes[i]);
996 } else {
997 struct dom_sid_buf sid_buf;
998 DBG_INFO("LDAP Query: Duration was %.2fs, "
999 "SearchRequest by %s from %s filter: [%s] "
1000 "basedn: [%s] "
1001 "scope: [%s] "
1002 "result: %s\n",
1003 timeval_elapsed(&start_time),
1004 dom_sid_str_buf(&call->conn->session_info->security_token->sids[0],
1005 &sid_buf),
1006 tsocket_address_string(call->conn->connection->remote_address,
1007 call),
1008 ldb_filter_from_tree(call, req->tree),
1009 ldb_dn_get_extended_linearized(call, basedn, 1),
1010 scope_str,
1011 ldb_strerror(ldb_ret));
1014 DLIST_REMOVE(call->conn->pending_calls, call);
1015 call->notification.busy = false;
1017 done_r = ldapsrv_init_reply(call, LDAP_TAG_SearchResultDone);
1018 NT_STATUS_HAVE_NO_MEMORY(done_r);
1020 done = &done_r->msg->r.SearchResultDone;
1021 done->dn = NULL;
1022 done->referral = NULL;
1024 if (result != -1) {
1025 } else if (ldb_ret == LDB_SUCCESS) {
1026 if (callback_ctx->controls) {
1027 done_r->msg->controls = callback_ctx->controls;
1028 talloc_steal(done_r->msg, callback_ctx->controls);
1030 result = LDB_SUCCESS;
1031 } else {
1032 DEBUG(10,("SearchRequest: error\n"));
1033 result = map_ldb_error(local_ctx, ldb_ret, ldb_errstring(samdb),
1034 &errstr);
1037 done->resultcode = result;
1038 done->errormessage = (errstr?talloc_strdup(done_r, errstr):NULL);
1040 talloc_free(local_ctx);
1042 return ldapsrv_queue_reply_forced(call, done_r);
1045 static NTSTATUS ldapsrv_ModifyRequest(struct ldapsrv_call *call)
1047 struct ldap_ModifyRequest *req = &call->request->r.ModifyRequest;
1048 struct ldap_Result *modify_result;
1049 struct ldapsrv_reply *modify_reply;
1050 TALLOC_CTX *local_ctx;
1051 struct ldb_context *samdb = call->conn->ldb;
1052 struct ldb_message *msg = NULL;
1053 struct ldb_dn *dn;
1054 const char *errstr = NULL;
1055 int result = LDAP_SUCCESS;
1056 int ldb_ret;
1057 unsigned int i,j;
1058 struct ldb_result *res = NULL;
1060 DEBUG(10, ("ModifyRequest"));
1061 DEBUGADD(10, (" dn: %s\n", req->dn));
1063 local_ctx = talloc_named(call, 0, "ModifyRequest local memory context");
1064 NT_STATUS_HAVE_NO_MEMORY(local_ctx);
1066 dn = ldb_dn_new(local_ctx, samdb, req->dn);
1067 NT_STATUS_HAVE_NO_MEMORY(dn);
1069 DEBUG(10, ("ModifyRequest: dn: [%s]\n", req->dn));
1071 msg = ldb_msg_new(local_ctx);
1072 NT_STATUS_HAVE_NO_MEMORY(msg);
1074 msg->dn = dn;
1076 if (req->num_mods > 0) {
1077 msg->num_elements = req->num_mods;
1078 msg->elements = talloc_array(msg, struct ldb_message_element, req->num_mods);
1079 NT_STATUS_HAVE_NO_MEMORY(msg->elements);
1081 for (i=0; i < msg->num_elements; i++) {
1082 msg->elements[i].name = discard_const_p(char, req->mods[i].attrib.name);
1083 msg->elements[i].num_values = 0;
1084 msg->elements[i].values = NULL;
1086 switch (req->mods[i].type) {
1087 default:
1088 result = LDAP_PROTOCOL_ERROR;
1089 map_ldb_error(local_ctx,
1090 LDB_ERR_PROTOCOL_ERROR, NULL, &errstr);
1091 errstr = talloc_asprintf(local_ctx,
1092 "%s. Invalid LDAP_MODIFY_* type", errstr);
1093 goto reply;
1094 case LDAP_MODIFY_ADD:
1095 msg->elements[i].flags = LDB_FLAG_MOD_ADD;
1096 break;
1097 case LDAP_MODIFY_DELETE:
1098 msg->elements[i].flags = LDB_FLAG_MOD_DELETE;
1099 break;
1100 case LDAP_MODIFY_REPLACE:
1101 msg->elements[i].flags = LDB_FLAG_MOD_REPLACE;
1102 break;
1105 msg->elements[i].num_values = req->mods[i].attrib.num_values;
1106 if (msg->elements[i].num_values > 0) {
1107 msg->elements[i].values = talloc_array(msg->elements, struct ldb_val,
1108 msg->elements[i].num_values);
1109 NT_STATUS_HAVE_NO_MEMORY(msg->elements[i].values);
1111 for (j=0; j < msg->elements[i].num_values; j++) {
1112 msg->elements[i].values[j].length = req->mods[i].attrib.values[j].length;
1113 msg->elements[i].values[j].data = req->mods[i].attrib.values[j].data;
1119 reply:
1120 modify_reply = ldapsrv_init_reply(call, LDAP_TAG_ModifyResponse);
1121 NT_STATUS_HAVE_NO_MEMORY(modify_reply);
1123 if (result == LDAP_SUCCESS) {
1124 res = talloc_zero(local_ctx, struct ldb_result);
1125 NT_STATUS_HAVE_NO_MEMORY(res);
1126 ldb_ret = ldapsrv_mod_with_controls(call, msg, call->request->controls, res);
1127 result = map_ldb_error(local_ctx, ldb_ret, ldb_errstring(samdb),
1128 &errstr);
1131 modify_result = &modify_reply->msg->r.ModifyResponse;
1132 modify_result->dn = NULL;
1133 if ((res != NULL) && (res->refs != NULL)) {
1134 modify_result->resultcode = map_ldb_error(local_ctx,
1135 LDB_ERR_REFERRAL,
1136 NULL, &errstr);
1137 modify_result->errormessage = (errstr?talloc_strdup(modify_reply, errstr):NULL);
1138 modify_result->referral = talloc_strdup(call, *res->refs);
1139 } else {
1140 modify_result->resultcode = result;
1141 modify_result->errormessage = (errstr?talloc_strdup(modify_reply, errstr):NULL);
1142 modify_result->referral = NULL;
1144 talloc_free(local_ctx);
1146 return ldapsrv_queue_reply(call, modify_reply);
1150 static NTSTATUS ldapsrv_AddRequest(struct ldapsrv_call *call)
1152 struct ldap_AddRequest *req = &call->request->r.AddRequest;
1153 struct ldap_Result *add_result;
1154 struct ldapsrv_reply *add_reply;
1155 TALLOC_CTX *local_ctx;
1156 struct ldb_context *samdb = call->conn->ldb;
1157 struct ldb_message *msg = NULL;
1158 struct ldb_dn *dn;
1159 const char *errstr = NULL;
1160 int result = LDAP_SUCCESS;
1161 int ldb_ret;
1162 unsigned int i,j;
1163 struct ldb_result *res = NULL;
1165 DEBUG(10, ("AddRequest"));
1166 DEBUGADD(10, (" dn: %s\n", req->dn));
1168 local_ctx = talloc_named(call, 0, "AddRequest local memory context");
1169 NT_STATUS_HAVE_NO_MEMORY(local_ctx);
1171 dn = ldb_dn_new(local_ctx, samdb, req->dn);
1172 NT_STATUS_HAVE_NO_MEMORY(dn);
1174 DEBUG(10, ("AddRequest: dn: [%s]\n", req->dn));
1176 msg = talloc(local_ctx, struct ldb_message);
1177 NT_STATUS_HAVE_NO_MEMORY(msg);
1179 msg->dn = dn;
1180 msg->num_elements = 0;
1181 msg->elements = NULL;
1183 if (req->num_attributes > 0) {
1184 msg->num_elements = req->num_attributes;
1185 msg->elements = talloc_array(msg, struct ldb_message_element, msg->num_elements);
1186 NT_STATUS_HAVE_NO_MEMORY(msg->elements);
1188 for (i=0; i < msg->num_elements; i++) {
1189 msg->elements[i].name = discard_const_p(char, req->attributes[i].name);
1190 msg->elements[i].flags = 0;
1191 msg->elements[i].num_values = 0;
1192 msg->elements[i].values = NULL;
1194 if (req->attributes[i].num_values > 0) {
1195 msg->elements[i].num_values = req->attributes[i].num_values;
1196 msg->elements[i].values = talloc_array(msg->elements, struct ldb_val,
1197 msg->elements[i].num_values);
1198 NT_STATUS_HAVE_NO_MEMORY(msg->elements[i].values);
1200 for (j=0; j < msg->elements[i].num_values; j++) {
1201 msg->elements[i].values[j].length = req->attributes[i].values[j].length;
1202 msg->elements[i].values[j].data = req->attributes[i].values[j].data;
1208 add_reply = ldapsrv_init_reply(call, LDAP_TAG_AddResponse);
1209 NT_STATUS_HAVE_NO_MEMORY(add_reply);
1211 if (result == LDAP_SUCCESS) {
1212 res = talloc_zero(local_ctx, struct ldb_result);
1213 NT_STATUS_HAVE_NO_MEMORY(res);
1214 ldb_ret = ldapsrv_add_with_controls(call, msg, call->request->controls, res);
1215 result = map_ldb_error(local_ctx, ldb_ret, ldb_errstring(samdb),
1216 &errstr);
1219 add_result = &add_reply->msg->r.AddResponse;
1220 add_result->dn = NULL;
1221 if ((res != NULL) && (res->refs != NULL)) {
1222 add_result->resultcode = map_ldb_error(local_ctx,
1223 LDB_ERR_REFERRAL, NULL,
1224 &errstr);
1225 add_result->errormessage = (errstr?talloc_strdup(add_reply,errstr):NULL);
1226 add_result->referral = talloc_strdup(call, *res->refs);
1227 } else {
1228 add_result->resultcode = result;
1229 add_result->errormessage = (errstr?talloc_strdup(add_reply,errstr):NULL);
1230 add_result->referral = NULL;
1232 talloc_free(local_ctx);
1234 return ldapsrv_queue_reply(call, add_reply);
1238 static NTSTATUS ldapsrv_DelRequest(struct ldapsrv_call *call)
1240 struct ldap_DelRequest *req = &call->request->r.DelRequest;
1241 struct ldap_Result *del_result;
1242 struct ldapsrv_reply *del_reply;
1243 TALLOC_CTX *local_ctx;
1244 struct ldb_context *samdb = call->conn->ldb;
1245 struct ldb_dn *dn;
1246 const char *errstr = NULL;
1247 int result = LDAP_SUCCESS;
1248 int ldb_ret;
1249 struct ldb_result *res = NULL;
1251 DEBUG(10, ("DelRequest"));
1252 DEBUGADD(10, (" dn: %s\n", req->dn));
1254 local_ctx = talloc_named(call, 0, "DelRequest local memory context");
1255 NT_STATUS_HAVE_NO_MEMORY(local_ctx);
1257 dn = ldb_dn_new(local_ctx, samdb, req->dn);
1258 NT_STATUS_HAVE_NO_MEMORY(dn);
1260 DEBUG(10, ("DelRequest: dn: [%s]\n", req->dn));
1262 del_reply = ldapsrv_init_reply(call, LDAP_TAG_DelResponse);
1263 NT_STATUS_HAVE_NO_MEMORY(del_reply);
1265 if (result == LDAP_SUCCESS) {
1266 res = talloc_zero(local_ctx, struct ldb_result);
1267 NT_STATUS_HAVE_NO_MEMORY(res);
1268 ldb_ret = ldapsrv_del_with_controls(call, dn, call->request->controls, res);
1269 result = map_ldb_error(local_ctx, ldb_ret, ldb_errstring(samdb),
1270 &errstr);
1273 del_result = &del_reply->msg->r.DelResponse;
1274 del_result->dn = NULL;
1275 if ((res != NULL) && (res->refs != NULL)) {
1276 del_result->resultcode = map_ldb_error(local_ctx,
1277 LDB_ERR_REFERRAL, NULL,
1278 &errstr);
1279 del_result->errormessage = (errstr?talloc_strdup(del_reply,errstr):NULL);
1280 del_result->referral = talloc_strdup(call, *res->refs);
1281 } else {
1282 del_result->resultcode = result;
1283 del_result->errormessage = (errstr?talloc_strdup(del_reply,errstr):NULL);
1284 del_result->referral = NULL;
1287 talloc_free(local_ctx);
1289 return ldapsrv_queue_reply(call, del_reply);
1292 static NTSTATUS ldapsrv_ModifyDNRequest(struct ldapsrv_call *call)
1294 struct ldap_ModifyDNRequest *req = &call->request->r.ModifyDNRequest;
1295 struct ldap_Result *modifydn;
1296 struct ldapsrv_reply *modifydn_r;
1297 TALLOC_CTX *local_ctx;
1298 struct ldb_context *samdb = call->conn->ldb;
1299 struct ldb_dn *olddn, *newdn=NULL, *newrdn;
1300 struct ldb_dn *parentdn = NULL;
1301 const char *errstr = NULL;
1302 int result = LDAP_SUCCESS;
1303 int ldb_ret;
1304 struct ldb_result *res = NULL;
1306 DEBUG(10, ("ModifyDNRequest"));
1307 DEBUGADD(10, (" dn: %s", req->dn));
1308 DEBUGADD(10, (" newrdn: %s\n", req->newrdn));
1310 local_ctx = talloc_named(call, 0, "ModifyDNRequest local memory context");
1311 NT_STATUS_HAVE_NO_MEMORY(local_ctx);
1313 olddn = ldb_dn_new(local_ctx, samdb, req->dn);
1314 NT_STATUS_HAVE_NO_MEMORY(olddn);
1316 newrdn = ldb_dn_new(local_ctx, samdb, req->newrdn);
1317 NT_STATUS_HAVE_NO_MEMORY(newrdn);
1319 DEBUG(10, ("ModifyDNRequest: olddn: [%s]\n", req->dn));
1320 DEBUG(10, ("ModifyDNRequest: newrdn: [%s]\n", req->newrdn));
1322 if (ldb_dn_get_comp_num(newrdn) == 0) {
1323 result = LDAP_PROTOCOL_ERROR;
1324 map_ldb_error(local_ctx, LDB_ERR_PROTOCOL_ERROR, NULL,
1325 &errstr);
1326 goto reply;
1329 if (ldb_dn_get_comp_num(newrdn) > 1) {
1330 result = LDAP_NAMING_VIOLATION;
1331 map_ldb_error(local_ctx, LDB_ERR_NAMING_VIOLATION, NULL,
1332 &errstr);
1333 goto reply;
1336 /* we can't handle the rename if we should not remove the old dn */
1337 if (!req->deleteolddn) {
1338 result = LDAP_UNWILLING_TO_PERFORM;
1339 map_ldb_error(local_ctx, LDB_ERR_UNWILLING_TO_PERFORM, NULL,
1340 &errstr);
1341 errstr = talloc_asprintf(local_ctx,
1342 "%s. Old RDN must be deleted", errstr);
1343 goto reply;
1346 if (req->newsuperior) {
1347 DEBUG(10, ("ModifyDNRequest: newsuperior: [%s]\n", req->newsuperior));
1348 parentdn = ldb_dn_new(local_ctx, samdb, req->newsuperior);
1351 if (!parentdn) {
1352 parentdn = ldb_dn_get_parent(local_ctx, olddn);
1354 if (!parentdn) {
1355 result = LDAP_NO_SUCH_OBJECT;
1356 map_ldb_error(local_ctx, LDB_ERR_NO_SUCH_OBJECT, NULL, &errstr);
1357 goto reply;
1360 if ( ! ldb_dn_add_child(parentdn, newrdn)) {
1361 result = LDAP_OTHER;
1362 map_ldb_error(local_ctx, LDB_ERR_OTHER, NULL, &errstr);
1363 goto reply;
1365 newdn = parentdn;
1367 reply:
1368 modifydn_r = ldapsrv_init_reply(call, LDAP_TAG_ModifyDNResponse);
1369 NT_STATUS_HAVE_NO_MEMORY(modifydn_r);
1371 if (result == LDAP_SUCCESS) {
1372 res = talloc_zero(local_ctx, struct ldb_result);
1373 NT_STATUS_HAVE_NO_MEMORY(res);
1374 ldb_ret = ldapsrv_rename_with_controls(call, olddn, newdn, call->request->controls, res);
1375 result = map_ldb_error(local_ctx, ldb_ret, ldb_errstring(samdb),
1376 &errstr);
1379 modifydn = &modifydn_r->msg->r.ModifyDNResponse;
1380 modifydn->dn = NULL;
1381 if ((res != NULL) && (res->refs != NULL)) {
1382 modifydn->resultcode = map_ldb_error(local_ctx,
1383 LDB_ERR_REFERRAL, NULL,
1384 &errstr);;
1385 modifydn->errormessage = (errstr?talloc_strdup(modifydn_r,errstr):NULL);
1386 modifydn->referral = talloc_strdup(call, *res->refs);
1387 } else {
1388 modifydn->resultcode = result;
1389 modifydn->errormessage = (errstr?talloc_strdup(modifydn_r,errstr):NULL);
1390 modifydn->referral = NULL;
1393 talloc_free(local_ctx);
1395 return ldapsrv_queue_reply(call, modifydn_r);
1398 static NTSTATUS ldapsrv_CompareRequest(struct ldapsrv_call *call)
1400 struct ldap_CompareRequest *req = &call->request->r.CompareRequest;
1401 struct ldap_Result *compare;
1402 struct ldapsrv_reply *compare_r;
1403 TALLOC_CTX *local_ctx;
1404 struct ldb_context *samdb = call->conn->ldb;
1405 struct ldb_result *res = NULL;
1406 struct ldb_dn *dn;
1407 const char *attrs[1];
1408 const char *errstr = NULL;
1409 const char *filter = NULL;
1410 int result = LDAP_SUCCESS;
1411 int ldb_ret;
1413 DEBUG(10, ("CompareRequest"));
1414 DEBUGADD(10, (" dn: %s\n", req->dn));
1416 local_ctx = talloc_named(call, 0, "CompareRequest local_memory_context");
1417 NT_STATUS_HAVE_NO_MEMORY(local_ctx);
1419 dn = ldb_dn_new(local_ctx, samdb, req->dn);
1420 NT_STATUS_HAVE_NO_MEMORY(dn);
1422 DEBUG(10, ("CompareRequest: dn: [%s]\n", req->dn));
1423 filter = talloc_asprintf(local_ctx, "(%s=%*s)", req->attribute,
1424 (int)req->value.length, req->value.data);
1425 NT_STATUS_HAVE_NO_MEMORY(filter);
1427 DEBUGADD(10, ("CompareRequest: attribute: [%s]\n", filter));
1429 attrs[0] = NULL;
1431 compare_r = ldapsrv_init_reply(call, LDAP_TAG_CompareResponse);
1432 NT_STATUS_HAVE_NO_MEMORY(compare_r);
1434 if (result == LDAP_SUCCESS) {
1435 ldb_ret = ldb_search(samdb, local_ctx, &res,
1436 dn, LDB_SCOPE_BASE, attrs, "%s", filter);
1437 if (ldb_ret != LDB_SUCCESS) {
1438 result = map_ldb_error(local_ctx, ldb_ret,
1439 ldb_errstring(samdb), &errstr);
1440 DEBUG(10,("CompareRequest: error: %s\n", errstr));
1441 } else if (res->count == 0) {
1442 DEBUG(10,("CompareRequest: doesn't matched\n"));
1443 result = LDAP_COMPARE_FALSE;
1444 errstr = NULL;
1445 } else if (res->count == 1) {
1446 DEBUG(10,("CompareRequest: matched\n"));
1447 result = LDAP_COMPARE_TRUE;
1448 errstr = NULL;
1449 } else if (res->count > 1) {
1450 result = LDAP_OTHER;
1451 map_ldb_error(local_ctx, LDB_ERR_OTHER, NULL, &errstr);
1452 errstr = talloc_asprintf(local_ctx,
1453 "%s. Too many objects match!", errstr);
1454 DEBUG(10,("CompareRequest: %d results: %s\n", res->count, errstr));
1458 compare = &compare_r->msg->r.CompareResponse;
1459 compare->dn = NULL;
1460 compare->resultcode = result;
1461 compare->errormessage = (errstr?talloc_strdup(compare_r,errstr):NULL);
1462 compare->referral = NULL;
1464 talloc_free(local_ctx);
1466 return ldapsrv_queue_reply(call, compare_r);
1469 static NTSTATUS ldapsrv_AbandonRequest(struct ldapsrv_call *call)
1471 struct ldap_AbandonRequest *req = &call->request->r.AbandonRequest;
1472 struct ldapsrv_call *c = NULL;
1473 struct ldapsrv_call *n = NULL;
1475 DEBUG(10, ("AbandonRequest\n"));
1477 for (c = call->conn->pending_calls; c != NULL; c = n) {
1478 n = c->next;
1480 if (c->request->messageid != req->messageid) {
1481 continue;
1484 DLIST_REMOVE(call->conn->pending_calls, c);
1485 TALLOC_FREE(c);
1488 return NT_STATUS_OK;
1491 static NTSTATUS ldapsrv_expired(struct ldapsrv_call *call)
1493 struct ldapsrv_reply *reply = NULL;
1494 struct ldap_ExtendedResponse *r = NULL;
1496 DBG_DEBUG("Sending connection expired message\n");
1498 reply = ldapsrv_init_reply(call, LDAP_TAG_ExtendedResponse);
1499 if (reply == NULL) {
1500 return NT_STATUS_NO_MEMORY;
1504 * According to RFC4511 section 4.4.1 this has a msgid of 0
1506 reply->msg->messageid = 0;
1508 r = &reply->msg->r.ExtendedResponse;
1509 r->response.resultcode = LDB_ERR_UNAVAILABLE;
1510 r->response.errormessage = "The server has timed out this connection";
1511 r->oid = "1.3.6.1.4.1.1466.20036"; /* see rfc4511 section 4.4.1 */
1513 ldapsrv_queue_reply(call, reply);
1514 return NT_STATUS_OK;
1517 NTSTATUS ldapsrv_do_call(struct ldapsrv_call *call)
1519 unsigned int i;
1520 struct ldap_message *msg = call->request;
1521 struct ldapsrv_connection *conn = call->conn;
1522 NTSTATUS status;
1523 bool expired;
1525 expired = timeval_expired(&conn->limits.expire_time);
1526 if (expired) {
1527 status = ldapsrv_expired(call);
1528 if (!NT_STATUS_IS_OK(status)) {
1529 return status;
1531 return NT_STATUS_NETWORK_SESSION_EXPIRED;
1534 /* Check for undecoded critical extensions */
1535 for (i=0; msg->controls && msg->controls[i]; i++) {
1536 if (!msg->controls_decoded[i] &&
1537 msg->controls[i]->critical) {
1538 DEBUG(3, ("ldapsrv_do_call: Critical extension %s is not known to this server\n",
1539 msg->controls[i]->oid));
1540 return ldapsrv_unwilling(call, LDAP_UNAVAILABLE_CRITICAL_EXTENSION);
1544 if (call->conn->authz_logged == false) {
1545 bool log = true;
1548 * We do not want to log anonymous access if the query
1549 * is just for the rootDSE, or it is a startTLS or a
1550 * Bind.
1552 * A rootDSE search could also be done over
1553 * CLDAP anonymously for example, so these don't
1554 * really count.
1555 * Essentially we want to know about
1556 * access beyond that normally done prior to a
1557 * bind.
1560 switch(call->request->type) {
1561 case LDAP_TAG_BindRequest:
1562 case LDAP_TAG_UnbindRequest:
1563 case LDAP_TAG_AbandonRequest:
1564 log = false;
1565 break;
1566 case LDAP_TAG_ExtendedResponse: {
1567 struct ldap_ExtendedRequest *req = &call->request->r.ExtendedRequest;
1568 if (strcmp(req->oid, LDB_EXTENDED_START_TLS_OID) == 0) {
1569 log = false;
1571 break;
1573 case LDAP_TAG_SearchRequest: {
1574 struct ldap_SearchRequest *req = &call->request->r.SearchRequest;
1575 if (req->scope == LDAP_SEARCH_SCOPE_BASE) {
1576 if (req->basedn[0] == '\0') {
1577 log = false;
1580 break;
1582 default:
1583 break;
1586 if (log) {
1587 const char *transport_protection = AUTHZ_TRANSPORT_PROTECTION_NONE;
1588 if (call->conn->sockets.active == call->conn->sockets.tls) {
1589 transport_protection = AUTHZ_TRANSPORT_PROTECTION_TLS;
1592 log_successful_authz_event(call->conn->connection->msg_ctx,
1593 call->conn->connection->lp_ctx,
1594 call->conn->connection->remote_address,
1595 call->conn->connection->local_address,
1596 "LDAP",
1597 "no bind",
1598 transport_protection,
1599 call->conn->session_info,
1600 NULL /* client_audit_info */,
1601 NULL /* server_audit_info */);
1603 call->conn->authz_logged = true;
1607 switch(call->request->type) {
1608 case LDAP_TAG_BindRequest:
1609 return ldapsrv_BindRequest(call);
1610 case LDAP_TAG_UnbindRequest:
1611 return ldapsrv_UnbindRequest(call);
1612 case LDAP_TAG_SearchRequest:
1613 return ldapsrv_SearchRequest(call);
1614 case LDAP_TAG_ModifyRequest:
1615 status = ldapsrv_ModifyRequest(call);
1616 break;
1617 case LDAP_TAG_AddRequest:
1618 status = ldapsrv_AddRequest(call);
1619 break;
1620 case LDAP_TAG_DelRequest:
1621 status = ldapsrv_DelRequest(call);
1622 break;
1623 case LDAP_TAG_ModifyDNRequest:
1624 status = ldapsrv_ModifyDNRequest(call);
1625 break;
1626 case LDAP_TAG_CompareRequest:
1627 return ldapsrv_CompareRequest(call);
1628 case LDAP_TAG_AbandonRequest:
1629 return ldapsrv_AbandonRequest(call);
1630 case LDAP_TAG_ExtendedRequest:
1631 status = ldapsrv_ExtendedRequest(call);
1632 break;
1633 default:
1634 return ldapsrv_unwilling(call, LDAP_PROTOCOL_ERROR);
1637 if (NT_STATUS_IS_OK(status)) {
1638 ldapsrv_notification_retry_setup(call->conn->service, true);
1641 return status;