smbd: Remove references to get_Protocol()
[Samba.git] / source4 / ldap_server / ldap_backend.c
blob8db85c58fac0c8339d48f678fcc7917503b9c9e2
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!");
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 TALLOC_FREE(reply->msg);
292 if (!bret) {
293 DEBUG(0,("Failed to encode ldap reply of type %d: "
294 "ldap_encode() failed\n",
295 reply->msg->type));
296 return NT_STATUS_NO_MEMORY;
299 talloc_set_name_const(reply->blob.data,
300 "Outgoing, encoded single LDAP reply");
302 return NT_STATUS_OK;
306 * Queue a reply (encoding it also), even if it would exceed the
307 * limit. This allows the error packet with LDAP_SIZE_LIMIT_EXCEEDED
308 * to be sent
310 static NTSTATUS ldapsrv_queue_reply_forced(struct ldapsrv_call *call,
311 struct ldapsrv_reply *reply)
313 NTSTATUS status = ldapsrv_encode(call, reply);
315 if (NT_STATUS_IS_OK(status)) {
316 DLIST_ADD_END(call->replies, reply);
318 return status;
322 * Queue a reply (encoding it also) but check we do not send more than
323 * LDAP_SERVER_MAX_REPLY_SIZE of responses as a way to limit the
324 * amount of data a client can make us allocate.
326 NTSTATUS ldapsrv_queue_reply(struct ldapsrv_call *call, struct ldapsrv_reply *reply)
328 NTSTATUS status = ldapsrv_encode(call, reply);
330 if (!NT_STATUS_IS_OK(status)) {
331 return status;
334 if (call->reply_size > call->reply_size + reply->blob.length
335 || call->reply_size + reply->blob.length > LDAP_SERVER_MAX_REPLY_SIZE) {
336 DBG_WARNING("Refusing to queue LDAP search response size "
337 "of more than %zu bytes\n",
338 LDAP_SERVER_MAX_REPLY_SIZE);
339 TALLOC_FREE(reply->blob.data);
340 return NT_STATUS_FILE_TOO_LARGE;
343 call->reply_size += reply->blob.length;
345 DLIST_ADD_END(call->replies, reply);
347 return status;
350 static NTSTATUS ldapsrv_unwilling(struct ldapsrv_call *call, int error)
352 struct ldapsrv_reply *reply;
353 struct ldap_ExtendedResponse *r;
355 DEBUG(10,("Unwilling type[%d] id[%d]\n", call->request->type, call->request->messageid));
357 reply = ldapsrv_init_reply(call, LDAP_TAG_ExtendedResponse);
358 if (!reply) {
359 return NT_STATUS_NO_MEMORY;
362 r = &reply->msg->r.ExtendedResponse;
363 r->response.resultcode = error;
364 r->response.dn = NULL;
365 r->response.errormessage = NULL;
366 r->response.referral = NULL;
367 r->oid = NULL;
368 r->value = NULL;
370 ldapsrv_queue_reply(call, reply);
371 return NT_STATUS_OK;
374 static int ldapsrv_add_with_controls(struct ldapsrv_call *call,
375 const struct ldb_message *message,
376 struct ldb_control **controls,
377 struct ldb_result *res)
379 struct ldb_context *ldb = call->conn->ldb;
380 struct ldb_request *req;
381 int ret;
383 ret = ldb_msg_sanity_check(ldb, message);
384 if (ret != LDB_SUCCESS) {
385 return ret;
388 ret = ldb_build_add_req(&req, ldb, ldb,
389 message,
390 controls,
391 res,
392 ldb_modify_default_callback,
393 NULL);
395 if (ret != LDB_SUCCESS) return ret;
397 if (call->conn->global_catalog) {
398 return ldb_error(ldb, LDB_ERR_UNWILLING_TO_PERFORM, "modify forbidden on global catalog port");
400 ldb_request_add_control(req, DSDB_CONTROL_NO_GLOBAL_CATALOG, false, NULL);
402 ret = ldb_transaction_start(ldb);
403 if (ret != LDB_SUCCESS) {
404 return ret;
407 if (!call->conn->is_privileged) {
408 ldb_req_mark_untrusted(req);
411 LDB_REQ_SET_LOCATION(req);
413 ret = ldb_request(ldb, req);
414 if (ret == LDB_SUCCESS) {
415 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
418 if (ret == LDB_SUCCESS) {
419 ret = ldb_transaction_commit(ldb);
421 else {
422 ldb_transaction_cancel(ldb);
425 talloc_free(req);
426 return ret;
429 /* create and execute a modify request */
430 static int ldapsrv_mod_with_controls(struct ldapsrv_call *call,
431 const struct ldb_message *message,
432 struct ldb_control **controls,
433 struct ldb_result *res)
435 struct ldb_context *ldb = call->conn->ldb;
436 struct ldb_request *req;
437 int ret;
439 ret = ldb_msg_sanity_check(ldb, message);
440 if (ret != LDB_SUCCESS) {
441 return ret;
444 ret = ldb_build_mod_req(&req, ldb, ldb,
445 message,
446 controls,
447 res,
448 ldb_modify_default_callback,
449 NULL);
451 if (ret != LDB_SUCCESS) {
452 return ret;
455 if (call->conn->global_catalog) {
456 return ldb_error(ldb, LDB_ERR_UNWILLING_TO_PERFORM, "modify forbidden on global catalog port");
458 ldb_request_add_control(req, DSDB_CONTROL_NO_GLOBAL_CATALOG, false, NULL);
460 ret = ldb_transaction_start(ldb);
461 if (ret != LDB_SUCCESS) {
462 return ret;
465 if (!call->conn->is_privileged) {
466 ldb_req_mark_untrusted(req);
469 LDB_REQ_SET_LOCATION(req);
471 ret = ldb_request(ldb, req);
472 if (ret == LDB_SUCCESS) {
473 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
476 if (ret == LDB_SUCCESS) {
477 ret = ldb_transaction_commit(ldb);
479 else {
480 ldb_transaction_cancel(ldb);
483 talloc_free(req);
484 return ret;
487 /* create and execute a delete request */
488 static int ldapsrv_del_with_controls(struct ldapsrv_call *call,
489 struct ldb_dn *dn,
490 struct ldb_control **controls,
491 struct ldb_result *res)
493 struct ldb_context *ldb = call->conn->ldb;
494 struct ldb_request *req;
495 int ret;
497 ret = ldb_build_del_req(&req, ldb, ldb,
499 controls,
500 res,
501 ldb_modify_default_callback,
502 NULL);
504 if (ret != LDB_SUCCESS) return ret;
506 if (call->conn->global_catalog) {
507 return ldb_error(ldb, LDB_ERR_UNWILLING_TO_PERFORM, "modify forbidden on global catalog port");
509 ldb_request_add_control(req, DSDB_CONTROL_NO_GLOBAL_CATALOG, false, NULL);
511 ret = ldb_transaction_start(ldb);
512 if (ret != LDB_SUCCESS) {
513 return ret;
516 if (!call->conn->is_privileged) {
517 ldb_req_mark_untrusted(req);
520 LDB_REQ_SET_LOCATION(req);
522 ret = ldb_request(ldb, req);
523 if (ret == LDB_SUCCESS) {
524 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
527 if (ret == LDB_SUCCESS) {
528 ret = ldb_transaction_commit(ldb);
530 else {
531 ldb_transaction_cancel(ldb);
534 talloc_free(req);
535 return ret;
538 static int ldapsrv_rename_with_controls(struct ldapsrv_call *call,
539 struct ldb_dn *olddn,
540 struct ldb_dn *newdn,
541 struct ldb_control **controls,
542 struct ldb_result *res)
544 struct ldb_context *ldb = call->conn->ldb;
545 struct ldb_request *req;
546 int ret;
548 ret = ldb_build_rename_req(&req, ldb, ldb,
549 olddn,
550 newdn,
551 controls,
552 res,
553 ldb_modify_default_callback,
554 NULL);
556 if (ret != LDB_SUCCESS) return ret;
558 if (call->conn->global_catalog) {
559 return ldb_error(ldb, LDB_ERR_UNWILLING_TO_PERFORM, "modify forbidden on global catalog port");
561 ldb_request_add_control(req, DSDB_CONTROL_NO_GLOBAL_CATALOG, false, NULL);
563 ret = ldb_transaction_start(ldb);
564 if (ret != LDB_SUCCESS) {
565 return ret;
568 if (!call->conn->is_privileged) {
569 ldb_req_mark_untrusted(req);
572 LDB_REQ_SET_LOCATION(req);
574 ret = ldb_request(ldb, req);
575 if (ret == LDB_SUCCESS) {
576 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
579 if (ret == LDB_SUCCESS) {
580 ret = ldb_transaction_commit(ldb);
582 else {
583 ldb_transaction_cancel(ldb);
586 talloc_free(req);
587 return ret;
592 struct ldapsrv_context {
593 struct ldapsrv_call *call;
594 int extended_type;
595 bool attributesonly;
596 struct ldb_control **controls;
597 size_t count; /* For notificaiton only */
600 static int ldap_server_search_callback(struct ldb_request *req, struct ldb_reply *ares)
602 struct ldapsrv_context *ctx = talloc_get_type(req->context, struct ldapsrv_context);
603 struct ldapsrv_call *call = ctx->call;
604 struct ldb_context *ldb = call->conn->ldb;
605 unsigned int j;
606 struct ldapsrv_reply *ent_r = NULL;
607 struct ldap_SearchResEntry *ent;
608 int ret;
609 NTSTATUS status;
611 if (!ares) {
612 return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
614 if (ares->error != LDB_SUCCESS) {
615 return ldb_request_done(req, ares->error);
618 switch (ares->type) {
619 case LDB_REPLY_ENTRY:
621 struct ldb_message *msg = ares->message;
622 ent_r = ldapsrv_init_reply(call, LDAP_TAG_SearchResultEntry);
623 if (ent_r == NULL) {
624 return ldb_oom(ldb);
627 ctx->count++;
630 * Put the LDAP search response data under ent_r->msg
631 * so we can free that later once encoded
633 talloc_steal(ent_r->msg, msg);
635 ent = &ent_r->msg->r.SearchResultEntry;
636 ent->dn = ldb_dn_get_extended_linearized(ent_r, msg->dn,
637 ctx->extended_type);
638 ent->num_attributes = 0;
639 ent->attributes = NULL;
640 if (msg->num_elements == 0) {
641 goto queue_reply;
643 ent->num_attributes = msg->num_elements;
644 ent->attributes = talloc_array(ent_r, struct ldb_message_element, ent->num_attributes);
645 if (ent->attributes == NULL) {
646 return ldb_oom(ldb);
649 for (j=0; j < ent->num_attributes; j++) {
650 ent->attributes[j].name = msg->elements[j].name;
651 ent->attributes[j].num_values = 0;
652 ent->attributes[j].values = NULL;
653 if (ctx->attributesonly && (msg->elements[j].num_values == 0)) {
654 continue;
656 ent->attributes[j].num_values = msg->elements[j].num_values;
657 ent->attributes[j].values = msg->elements[j].values;
659 queue_reply:
660 status = ldapsrv_queue_reply(call, ent_r);
661 if (NT_STATUS_EQUAL(status, NT_STATUS_FILE_TOO_LARGE)) {
662 ret = ldb_request_done(req,
663 LDB_ERR_SIZE_LIMIT_EXCEEDED);
664 ldb_asprintf_errstring(ldb,
665 "LDAP search response size "
666 "limited to %zu bytes\n",
667 LDAP_SERVER_MAX_REPLY_SIZE);
668 } else if (!NT_STATUS_IS_OK(status)) {
669 ret = ldb_request_done(req,
670 ldb_operr(ldb));
671 } else {
672 ret = LDB_SUCCESS;
674 break;
676 case LDB_REPLY_REFERRAL:
678 struct ldap_SearchResRef *ent_ref;
681 * TODO: This should be handled by the notification
682 * module not here
684 if (call->notification.busy) {
685 ret = LDB_SUCCESS;
686 break;
689 ent_r = ldapsrv_init_reply(call, LDAP_TAG_SearchResultReference);
690 if (ent_r == NULL) {
691 return ldb_oom(ldb);
695 * Put the LDAP referral data under ent_r->msg
696 * so we can free that later once encoded
698 talloc_steal(ent_r->msg, ares->referral);
700 ent_ref = &ent_r->msg->r.SearchResultReference;
701 ent_ref->referral = ares->referral;
703 status = ldapsrv_queue_reply(call, ent_r);
704 if (!NT_STATUS_IS_OK(status)) {
705 ret = LDB_ERR_OPERATIONS_ERROR;
706 } else {
707 ret = LDB_SUCCESS;
709 break;
711 case LDB_REPLY_DONE:
714 * We don't queue the reply for this one, we let that
715 * happen outside
717 ctx->controls = talloc_move(ctx, &ares->controls);
719 TALLOC_FREE(ares);
720 return ldb_request_done(req, LDB_SUCCESS);
722 default:
723 /* Doesn't happen */
724 ret = LDB_ERR_OPERATIONS_ERROR;
726 TALLOC_FREE(ares);
728 return ret;
732 static NTSTATUS ldapsrv_SearchRequest(struct ldapsrv_call *call)
734 struct ldap_SearchRequest *req = &call->request->r.SearchRequest;
735 struct ldap_Result *done;
736 struct ldapsrv_reply *done_r;
737 TALLOC_CTX *local_ctx;
738 struct ldapsrv_context *callback_ctx = NULL;
739 struct ldb_context *samdb = talloc_get_type(call->conn->ldb, struct ldb_context);
740 struct ldb_dn *basedn;
741 struct ldb_request *lreq;
742 struct ldb_control *search_control;
743 struct ldb_search_options_control *search_options;
744 struct ldb_control *extended_dn_control;
745 struct ldb_extended_dn_control *extended_dn_decoded = NULL;
746 struct ldb_control *notification_control = NULL;
747 enum ldb_scope scope = LDB_SCOPE_DEFAULT;
748 const char **attrs = NULL;
749 const char *scope_str, *errstr = NULL;
750 int result = -1;
751 int ldb_ret = -1;
752 unsigned int i;
753 int extended_type = 1;
756 * Warn for searches that are longer than 1/4 of the
757 * search_timeout, being 30sec by default
759 struct timeval start_time = timeval_current();
760 struct timeval warning_time
761 = timeval_add(&start_time,
762 call->conn->limits.search_timeout / 4,
765 local_ctx = talloc_new(call);
766 NT_STATUS_HAVE_NO_MEMORY(local_ctx);
768 basedn = ldb_dn_new(local_ctx, samdb, req->basedn);
769 NT_STATUS_HAVE_NO_MEMORY(basedn);
771 switch (req->scope) {
772 case LDAP_SEARCH_SCOPE_BASE:
773 scope_str = "BASE";
774 scope = LDB_SCOPE_BASE;
775 break;
776 case LDAP_SEARCH_SCOPE_SINGLE:
777 scope_str = "ONE";
778 scope = LDB_SCOPE_ONELEVEL;
779 break;
780 case LDAP_SEARCH_SCOPE_SUB:
781 scope_str = "SUB";
782 scope = LDB_SCOPE_SUBTREE;
783 break;
784 default:
785 result = LDAP_PROTOCOL_ERROR;
786 map_ldb_error(local_ctx, LDB_ERR_PROTOCOL_ERROR, NULL,
787 &errstr);
788 scope_str = "<Invalid scope>";
789 errstr = talloc_asprintf(local_ctx,
790 "%s. Invalid scope", errstr);
791 goto reply;
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);
1601 call->conn->authz_logged = true;
1605 switch(call->request->type) {
1606 case LDAP_TAG_BindRequest:
1607 return ldapsrv_BindRequest(call);
1608 case LDAP_TAG_UnbindRequest:
1609 return ldapsrv_UnbindRequest(call);
1610 case LDAP_TAG_SearchRequest:
1611 return ldapsrv_SearchRequest(call);
1612 case LDAP_TAG_ModifyRequest:
1613 status = ldapsrv_ModifyRequest(call);
1614 break;
1615 case LDAP_TAG_AddRequest:
1616 status = ldapsrv_AddRequest(call);
1617 break;
1618 case LDAP_TAG_DelRequest:
1619 status = ldapsrv_DelRequest(call);
1620 break;
1621 case LDAP_TAG_ModifyDNRequest:
1622 status = ldapsrv_ModifyDNRequest(call);
1623 break;
1624 case LDAP_TAG_CompareRequest:
1625 return ldapsrv_CompareRequest(call);
1626 case LDAP_TAG_AbandonRequest:
1627 return ldapsrv_AbandonRequest(call);
1628 case LDAP_TAG_ExtendedRequest:
1629 status = ldapsrv_ExtendedRequest(call);
1630 break;
1631 default:
1632 return ldapsrv_unwilling(call, LDAP_PROTOCOL_ERROR);
1635 if (NT_STATUS_IS_OK(status)) {
1636 ldapsrv_notification_retry_setup(call->conn->service, true);
1639 return status;