vfs_fruit: ignore ENAMETOOLONG in fruit_unlink_rsrc_adouble()
[Samba.git] / source4 / ldap_server / ldap_backend.c
blob4e94417c21b46482543be490d1fdb95c45301f93
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 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 notification 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 = LDB_SCOPE_BASE;
774 break;
775 case LDAP_SEARCH_SCOPE_SINGLE:
776 scope = LDB_SCOPE_ONELEVEL;
777 break;
778 case LDAP_SEARCH_SCOPE_SUB:
779 scope = LDB_SCOPE_SUBTREE;
780 break;
781 default:
782 result = LDAP_PROTOCOL_ERROR;
783 map_ldb_error(local_ctx, LDB_ERR_PROTOCOL_ERROR, NULL,
784 &errstr);
785 scope_str = "<Invalid scope>";
786 errstr = talloc_asprintf(local_ctx,
787 "%s. Invalid scope", errstr);
788 goto reply;
790 scope_str = dsdb_search_scope_as_string(scope);
792 DEBUG(10,("SearchRequest: scope: [%s]\n", scope_str));
794 if (req->num_attributes >= 1) {
795 attrs = talloc_array(local_ctx, const char *, req->num_attributes+1);
796 NT_STATUS_HAVE_NO_MEMORY(attrs);
798 for (i=0; i < req->num_attributes; i++) {
799 DEBUG(10,("SearchRequest: attrs: [%s]\n",req->attributes[i]));
800 attrs[i] = req->attributes[i];
802 attrs[i] = NULL;
805 DEBUG(5,("ldb_request %s dn=%s filter=%s\n",
806 scope_str, req->basedn, ldb_filter_from_tree(call, req->tree)));
808 callback_ctx = talloc_zero(local_ctx, struct ldapsrv_context);
809 NT_STATUS_HAVE_NO_MEMORY(callback_ctx);
810 callback_ctx->call = call;
811 callback_ctx->extended_type = extended_type;
812 callback_ctx->attributesonly = req->attributesonly;
814 ldb_ret = ldb_build_search_req_ex(&lreq, samdb, local_ctx,
815 basedn, scope,
816 req->tree, attrs,
817 call->request->controls,
818 callback_ctx,
819 ldap_server_search_callback,
820 NULL);
822 if (ldb_ret != LDB_SUCCESS) {
823 goto reply;
826 if (call->conn->global_catalog) {
827 search_control = ldb_request_get_control(lreq, LDB_CONTROL_SEARCH_OPTIONS_OID);
829 search_options = NULL;
830 if (search_control) {
831 search_options = talloc_get_type(search_control->data, struct ldb_search_options_control);
832 search_options->search_options |= LDB_SEARCH_OPTION_PHANTOM_ROOT;
833 } else {
834 search_options = talloc(lreq, struct ldb_search_options_control);
835 NT_STATUS_HAVE_NO_MEMORY(search_options);
836 search_options->search_options = LDB_SEARCH_OPTION_PHANTOM_ROOT;
837 ldb_request_add_control(lreq, LDB_CONTROL_SEARCH_OPTIONS_OID, false, search_options);
839 } else {
840 ldb_request_add_control(lreq, DSDB_CONTROL_NO_GLOBAL_CATALOG, false, NULL);
843 extended_dn_control = ldb_request_get_control(lreq, LDB_CONTROL_EXTENDED_DN_OID);
845 if (extended_dn_control) {
846 if (extended_dn_control->data) {
847 extended_dn_decoded = talloc_get_type(extended_dn_control->data, struct ldb_extended_dn_control);
848 extended_type = extended_dn_decoded->type;
849 } else {
850 extended_type = 0;
852 callback_ctx->extended_type = extended_type;
855 notification_control = ldb_request_get_control(lreq, LDB_CONTROL_NOTIFICATION_OID);
856 if (notification_control != NULL) {
857 const struct ldapsrv_call *pc = NULL;
858 size_t count = 0;
860 for (pc = call->conn->pending_calls; pc != NULL; pc = pc->next) {
861 count += 1;
864 if (count >= call->conn->limits.max_notifications) {
865 DEBUG(10,("SearchRequest: error MaxNotificationPerConn\n"));
866 result = map_ldb_error(local_ctx,
867 LDB_ERR_ADMIN_LIMIT_EXCEEDED,
868 "MaxNotificationPerConn reached",
869 &errstr);
870 goto reply;
874 * For now we need to do periodic retries on our own.
875 * As the dsdb_notification module will return after each run.
877 call->notification.busy = true;
881 const char *scheme = NULL;
882 switch (call->conn->referral_scheme) {
883 case LDAP_REFERRAL_SCHEME_LDAPS:
884 scheme = "ldaps";
885 break;
886 default:
887 scheme = "ldap";
889 ldb_ret = ldb_set_opaque(
890 samdb,
891 LDAP_REFERRAL_SCHEME_OPAQUE,
892 discard_const_p(char *, scheme));
893 if (ldb_ret != LDB_SUCCESS) {
894 goto reply;
899 time_t timeout = call->conn->limits.search_timeout;
901 if (timeout == 0
902 || (req->timelimit != 0
903 && req->timelimit < timeout))
905 timeout = req->timelimit;
907 ldb_set_timeout(samdb, lreq, timeout);
910 if (!call->conn->is_privileged) {
911 ldb_req_mark_untrusted(lreq);
914 LDB_REQ_SET_LOCATION(lreq);
916 ldb_ret = ldb_request(samdb, lreq);
918 if (ldb_ret != LDB_SUCCESS) {
919 goto reply;
922 ldb_ret = ldb_wait(lreq->handle, LDB_WAIT_ALL);
924 if (ldb_ret == LDB_SUCCESS) {
925 if (call->notification.busy) {
926 /* Move/Add it to the end */
927 DLIST_DEMOTE(call->conn->pending_calls, call);
928 call->notification.generation =
929 call->conn->service->notification.generation;
931 if (callback_ctx->count != 0) {
932 call->notification.generation += 1;
933 ldapsrv_notification_retry_setup(call->conn->service,
934 true);
937 talloc_free(local_ctx);
938 return NT_STATUS_OK;
942 reply:
945 * This looks like duplicated code - because it is - but
946 * otherwise the work in the parameters will be done
947 * regardless, this way the functions only execute when the
948 * log level is set.
950 * The basedn is re-obtained as a string to escape it
952 if ((req->timelimit == 0 || call->conn->limits.search_timeout < req->timelimit)
953 && ldb_ret == LDB_ERR_TIME_LIMIT_EXCEEDED) {
954 struct dom_sid_buf sid_buf;
955 DBG_WARNING("MaxQueryDuration(%d) timeout exceeded "
956 "in SearchRequest by %s from %s filter: [%s] "
957 "basedn: [%s] "
958 "scope: [%s]\n",
959 call->conn->limits.search_timeout,
960 dom_sid_str_buf(&call->conn->session_info->security_token->sids[0],
961 &sid_buf),
962 tsocket_address_string(call->conn->connection->remote_address,
963 call),
964 ldb_filter_from_tree(call, req->tree),
965 ldb_dn_get_extended_linearized(call, basedn, 1),
966 scope_str);
967 for (i=0; i < req->num_attributes; i++) {
968 DBG_WARNING("MaxQueryDuration timeout exceeded attrs: [%s]\n",
969 req->attributes[i]);
972 } else if (timeval_expired(&warning_time)) {
973 struct dom_sid_buf sid_buf;
974 DBG_NOTICE("Long LDAP Query: Duration was %.2fs, "
975 "MaxQueryDuration(%d)/4 == %d "
976 "in SearchRequest by %s from %s filter: [%s] "
977 "basedn: [%s] "
978 "scope: [%s] "
979 "result: %s\n",
980 timeval_elapsed(&start_time),
981 call->conn->limits.search_timeout,
982 call->conn->limits.search_timeout / 4,
983 dom_sid_str_buf(&call->conn->session_info->security_token->sids[0],
984 &sid_buf),
985 tsocket_address_string(call->conn->connection->remote_address,
986 call),
987 ldb_filter_from_tree(call, req->tree),
988 ldb_dn_get_extended_linearized(call, basedn, 1),
989 scope_str,
990 ldb_strerror(ldb_ret));
991 for (i=0; i < req->num_attributes; i++) {
992 DBG_NOTICE("Long LDAP Query attrs: [%s]\n",
993 req->attributes[i]);
995 } else {
996 struct dom_sid_buf sid_buf;
997 DBG_INFO("LDAP Query: Duration was %.2fs, "
998 "SearchRequest by %s from %s filter: [%s] "
999 "basedn: [%s] "
1000 "scope: [%s] "
1001 "result: %s\n",
1002 timeval_elapsed(&start_time),
1003 dom_sid_str_buf(&call->conn->session_info->security_token->sids[0],
1004 &sid_buf),
1005 tsocket_address_string(call->conn->connection->remote_address,
1006 call),
1007 ldb_filter_from_tree(call, req->tree),
1008 ldb_dn_get_extended_linearized(call, basedn, 1),
1009 scope_str,
1010 ldb_strerror(ldb_ret));
1013 DLIST_REMOVE(call->conn->pending_calls, call);
1014 call->notification.busy = false;
1016 done_r = ldapsrv_init_reply(call, LDAP_TAG_SearchResultDone);
1017 NT_STATUS_HAVE_NO_MEMORY(done_r);
1019 done = &done_r->msg->r.SearchResultDone;
1020 done->dn = NULL;
1021 done->referral = NULL;
1023 if (result != -1) {
1024 } else if (ldb_ret == LDB_SUCCESS) {
1025 if (callback_ctx->controls) {
1026 done_r->msg->controls = callback_ctx->controls;
1027 talloc_steal(done_r->msg, callback_ctx->controls);
1029 result = LDB_SUCCESS;
1030 } else {
1031 DEBUG(10,("SearchRequest: error\n"));
1032 result = map_ldb_error(local_ctx, ldb_ret, ldb_errstring(samdb),
1033 &errstr);
1036 done->resultcode = result;
1037 done->errormessage = (errstr?talloc_strdup(done_r, errstr):NULL);
1039 talloc_free(local_ctx);
1041 return ldapsrv_queue_reply_forced(call, done_r);
1044 static NTSTATUS ldapsrv_ModifyRequest(struct ldapsrv_call *call)
1046 struct ldap_ModifyRequest *req = &call->request->r.ModifyRequest;
1047 struct ldap_Result *modify_result;
1048 struct ldapsrv_reply *modify_reply;
1049 TALLOC_CTX *local_ctx;
1050 struct ldb_context *samdb = call->conn->ldb;
1051 struct ldb_message *msg = NULL;
1052 struct ldb_dn *dn;
1053 const char *errstr = NULL;
1054 int result = LDAP_SUCCESS;
1055 int ldb_ret;
1056 unsigned int i,j;
1057 struct ldb_result *res = NULL;
1059 DEBUG(10, ("ModifyRequest"));
1060 DEBUGADD(10, (" dn: %s\n", req->dn));
1062 local_ctx = talloc_named(call, 0, "ModifyRequest local memory context");
1063 NT_STATUS_HAVE_NO_MEMORY(local_ctx);
1065 dn = ldb_dn_new(local_ctx, samdb, req->dn);
1066 NT_STATUS_HAVE_NO_MEMORY(dn);
1068 DEBUG(10, ("ModifyRequest: dn: [%s]\n", req->dn));
1070 msg = ldb_msg_new(local_ctx);
1071 NT_STATUS_HAVE_NO_MEMORY(msg);
1073 msg->dn = dn;
1075 if (req->num_mods > 0) {
1076 msg->num_elements = req->num_mods;
1077 msg->elements = talloc_array(msg, struct ldb_message_element, req->num_mods);
1078 NT_STATUS_HAVE_NO_MEMORY(msg->elements);
1080 for (i=0; i < msg->num_elements; i++) {
1081 msg->elements[i].name = discard_const_p(char, req->mods[i].attrib.name);
1082 msg->elements[i].num_values = 0;
1083 msg->elements[i].values = NULL;
1085 switch (req->mods[i].type) {
1086 default:
1087 result = LDAP_PROTOCOL_ERROR;
1088 map_ldb_error(local_ctx,
1089 LDB_ERR_PROTOCOL_ERROR, NULL, &errstr);
1090 errstr = talloc_asprintf(local_ctx,
1091 "%s. Invalid LDAP_MODIFY_* type", errstr);
1092 goto reply;
1093 case LDAP_MODIFY_ADD:
1094 msg->elements[i].flags = LDB_FLAG_MOD_ADD;
1095 break;
1096 case LDAP_MODIFY_DELETE:
1097 msg->elements[i].flags = LDB_FLAG_MOD_DELETE;
1098 break;
1099 case LDAP_MODIFY_REPLACE:
1100 msg->elements[i].flags = LDB_FLAG_MOD_REPLACE;
1101 break;
1104 msg->elements[i].num_values = req->mods[i].attrib.num_values;
1105 if (msg->elements[i].num_values > 0) {
1106 msg->elements[i].values = talloc_array(msg->elements, struct ldb_val,
1107 msg->elements[i].num_values);
1108 NT_STATUS_HAVE_NO_MEMORY(msg->elements[i].values);
1110 for (j=0; j < msg->elements[i].num_values; j++) {
1111 msg->elements[i].values[j].length = req->mods[i].attrib.values[j].length;
1112 msg->elements[i].values[j].data = req->mods[i].attrib.values[j].data;
1118 reply:
1119 modify_reply = ldapsrv_init_reply(call, LDAP_TAG_ModifyResponse);
1120 NT_STATUS_HAVE_NO_MEMORY(modify_reply);
1122 if (result == LDAP_SUCCESS) {
1123 res = talloc_zero(local_ctx, struct ldb_result);
1124 NT_STATUS_HAVE_NO_MEMORY(res);
1125 ldb_ret = ldapsrv_mod_with_controls(call, msg, call->request->controls, res);
1126 result = map_ldb_error(local_ctx, ldb_ret, ldb_errstring(samdb),
1127 &errstr);
1130 modify_result = &modify_reply->msg->r.ModifyResponse;
1131 modify_result->dn = NULL;
1132 if ((res != NULL) && (res->refs != NULL)) {
1133 modify_result->resultcode = map_ldb_error(local_ctx,
1134 LDB_ERR_REFERRAL,
1135 NULL, &errstr);
1136 modify_result->errormessage = (errstr?talloc_strdup(modify_reply, errstr):NULL);
1137 modify_result->referral = talloc_strdup(call, *res->refs);
1138 } else {
1139 modify_result->resultcode = result;
1140 modify_result->errormessage = (errstr?talloc_strdup(modify_reply, errstr):NULL);
1141 modify_result->referral = NULL;
1143 talloc_free(local_ctx);
1145 return ldapsrv_queue_reply(call, modify_reply);
1149 static NTSTATUS ldapsrv_AddRequest(struct ldapsrv_call *call)
1151 struct ldap_AddRequest *req = &call->request->r.AddRequest;
1152 struct ldap_Result *add_result;
1153 struct ldapsrv_reply *add_reply;
1154 TALLOC_CTX *local_ctx;
1155 struct ldb_context *samdb = call->conn->ldb;
1156 struct ldb_message *msg = NULL;
1157 struct ldb_dn *dn;
1158 const char *errstr = NULL;
1159 int result = LDAP_SUCCESS;
1160 int ldb_ret;
1161 unsigned int i,j;
1162 struct ldb_result *res = NULL;
1164 DEBUG(10, ("AddRequest"));
1165 DEBUGADD(10, (" dn: %s\n", req->dn));
1167 local_ctx = talloc_named(call, 0, "AddRequest local memory context");
1168 NT_STATUS_HAVE_NO_MEMORY(local_ctx);
1170 dn = ldb_dn_new(local_ctx, samdb, req->dn);
1171 NT_STATUS_HAVE_NO_MEMORY(dn);
1173 DEBUG(10, ("AddRequest: dn: [%s]\n", req->dn));
1175 msg = talloc(local_ctx, struct ldb_message);
1176 NT_STATUS_HAVE_NO_MEMORY(msg);
1178 msg->dn = dn;
1179 msg->num_elements = 0;
1180 msg->elements = NULL;
1182 if (req->num_attributes > 0) {
1183 msg->num_elements = req->num_attributes;
1184 msg->elements = talloc_array(msg, struct ldb_message_element, msg->num_elements);
1185 NT_STATUS_HAVE_NO_MEMORY(msg->elements);
1187 for (i=0; i < msg->num_elements; i++) {
1188 msg->elements[i].name = discard_const_p(char, req->attributes[i].name);
1189 msg->elements[i].flags = 0;
1190 msg->elements[i].num_values = 0;
1191 msg->elements[i].values = NULL;
1193 if (req->attributes[i].num_values > 0) {
1194 msg->elements[i].num_values = req->attributes[i].num_values;
1195 msg->elements[i].values = talloc_array(msg->elements, struct ldb_val,
1196 msg->elements[i].num_values);
1197 NT_STATUS_HAVE_NO_MEMORY(msg->elements[i].values);
1199 for (j=0; j < msg->elements[i].num_values; j++) {
1200 msg->elements[i].values[j].length = req->attributes[i].values[j].length;
1201 msg->elements[i].values[j].data = req->attributes[i].values[j].data;
1207 add_reply = ldapsrv_init_reply(call, LDAP_TAG_AddResponse);
1208 NT_STATUS_HAVE_NO_MEMORY(add_reply);
1210 if (result == LDAP_SUCCESS) {
1211 res = talloc_zero(local_ctx, struct ldb_result);
1212 NT_STATUS_HAVE_NO_MEMORY(res);
1213 ldb_ret = ldapsrv_add_with_controls(call, msg, call->request->controls, res);
1214 result = map_ldb_error(local_ctx, ldb_ret, ldb_errstring(samdb),
1215 &errstr);
1218 add_result = &add_reply->msg->r.AddResponse;
1219 add_result->dn = NULL;
1220 if ((res != NULL) && (res->refs != NULL)) {
1221 add_result->resultcode = map_ldb_error(local_ctx,
1222 LDB_ERR_REFERRAL, NULL,
1223 &errstr);
1224 add_result->errormessage = (errstr?talloc_strdup(add_reply,errstr):NULL);
1225 add_result->referral = talloc_strdup(call, *res->refs);
1226 } else {
1227 add_result->resultcode = result;
1228 add_result->errormessage = (errstr?talloc_strdup(add_reply,errstr):NULL);
1229 add_result->referral = NULL;
1231 talloc_free(local_ctx);
1233 return ldapsrv_queue_reply(call, add_reply);
1237 static NTSTATUS ldapsrv_DelRequest(struct ldapsrv_call *call)
1239 struct ldap_DelRequest *req = &call->request->r.DelRequest;
1240 struct ldap_Result *del_result;
1241 struct ldapsrv_reply *del_reply;
1242 TALLOC_CTX *local_ctx;
1243 struct ldb_context *samdb = call->conn->ldb;
1244 struct ldb_dn *dn;
1245 const char *errstr = NULL;
1246 int result = LDAP_SUCCESS;
1247 int ldb_ret;
1248 struct ldb_result *res = NULL;
1250 DEBUG(10, ("DelRequest"));
1251 DEBUGADD(10, (" dn: %s\n", req->dn));
1253 local_ctx = talloc_named(call, 0, "DelRequest local memory context");
1254 NT_STATUS_HAVE_NO_MEMORY(local_ctx);
1256 dn = ldb_dn_new(local_ctx, samdb, req->dn);
1257 NT_STATUS_HAVE_NO_MEMORY(dn);
1259 DEBUG(10, ("DelRequest: dn: [%s]\n", req->dn));
1261 del_reply = ldapsrv_init_reply(call, LDAP_TAG_DelResponse);
1262 NT_STATUS_HAVE_NO_MEMORY(del_reply);
1264 if (result == LDAP_SUCCESS) {
1265 res = talloc_zero(local_ctx, struct ldb_result);
1266 NT_STATUS_HAVE_NO_MEMORY(res);
1267 ldb_ret = ldapsrv_del_with_controls(call, dn, call->request->controls, res);
1268 result = map_ldb_error(local_ctx, ldb_ret, ldb_errstring(samdb),
1269 &errstr);
1272 del_result = &del_reply->msg->r.DelResponse;
1273 del_result->dn = NULL;
1274 if ((res != NULL) && (res->refs != NULL)) {
1275 del_result->resultcode = map_ldb_error(local_ctx,
1276 LDB_ERR_REFERRAL, NULL,
1277 &errstr);
1278 del_result->errormessage = (errstr?talloc_strdup(del_reply,errstr):NULL);
1279 del_result->referral = talloc_strdup(call, *res->refs);
1280 } else {
1281 del_result->resultcode = result;
1282 del_result->errormessage = (errstr?talloc_strdup(del_reply,errstr):NULL);
1283 del_result->referral = NULL;
1286 talloc_free(local_ctx);
1288 return ldapsrv_queue_reply(call, del_reply);
1291 static NTSTATUS ldapsrv_ModifyDNRequest(struct ldapsrv_call *call)
1293 struct ldap_ModifyDNRequest *req = &call->request->r.ModifyDNRequest;
1294 struct ldap_Result *modifydn;
1295 struct ldapsrv_reply *modifydn_r;
1296 TALLOC_CTX *local_ctx;
1297 struct ldb_context *samdb = call->conn->ldb;
1298 struct ldb_dn *olddn, *newdn=NULL, *newrdn;
1299 struct ldb_dn *parentdn = NULL;
1300 const char *errstr = NULL;
1301 int result = LDAP_SUCCESS;
1302 int ldb_ret;
1303 struct ldb_result *res = NULL;
1305 DEBUG(10, ("ModifyDNRequest"));
1306 DEBUGADD(10, (" dn: %s", req->dn));
1307 DEBUGADD(10, (" newrdn: %s\n", req->newrdn));
1309 local_ctx = talloc_named(call, 0, "ModifyDNRequest local memory context");
1310 NT_STATUS_HAVE_NO_MEMORY(local_ctx);
1312 olddn = ldb_dn_new(local_ctx, samdb, req->dn);
1313 NT_STATUS_HAVE_NO_MEMORY(olddn);
1315 newrdn = ldb_dn_new(local_ctx, samdb, req->newrdn);
1316 NT_STATUS_HAVE_NO_MEMORY(newrdn);
1318 DEBUG(10, ("ModifyDNRequest: olddn: [%s]\n", req->dn));
1319 DEBUG(10, ("ModifyDNRequest: newrdn: [%s]\n", req->newrdn));
1321 if (ldb_dn_get_comp_num(newrdn) == 0) {
1322 result = LDAP_PROTOCOL_ERROR;
1323 map_ldb_error(local_ctx, LDB_ERR_PROTOCOL_ERROR, NULL,
1324 &errstr);
1325 goto reply;
1328 if (ldb_dn_get_comp_num(newrdn) > 1) {
1329 result = LDAP_NAMING_VIOLATION;
1330 map_ldb_error(local_ctx, LDB_ERR_NAMING_VIOLATION, NULL,
1331 &errstr);
1332 goto reply;
1335 /* we can't handle the rename if we should not remove the old dn */
1336 if (!req->deleteolddn) {
1337 result = LDAP_UNWILLING_TO_PERFORM;
1338 map_ldb_error(local_ctx, LDB_ERR_UNWILLING_TO_PERFORM, NULL,
1339 &errstr);
1340 errstr = talloc_asprintf(local_ctx,
1341 "%s. Old RDN must be deleted", errstr);
1342 goto reply;
1345 if (req->newsuperior) {
1346 DEBUG(10, ("ModifyDNRequest: newsuperior: [%s]\n", req->newsuperior));
1347 parentdn = ldb_dn_new(local_ctx, samdb, req->newsuperior);
1350 if (!parentdn) {
1351 parentdn = ldb_dn_get_parent(local_ctx, olddn);
1353 if (!parentdn) {
1354 result = LDAP_NO_SUCH_OBJECT;
1355 map_ldb_error(local_ctx, LDB_ERR_NO_SUCH_OBJECT, NULL, &errstr);
1356 goto reply;
1359 if ( ! ldb_dn_add_child(parentdn, newrdn)) {
1360 result = LDAP_OTHER;
1361 map_ldb_error(local_ctx, LDB_ERR_OTHER, NULL, &errstr);
1362 goto reply;
1364 newdn = parentdn;
1366 reply:
1367 modifydn_r = ldapsrv_init_reply(call, LDAP_TAG_ModifyDNResponse);
1368 NT_STATUS_HAVE_NO_MEMORY(modifydn_r);
1370 if (result == LDAP_SUCCESS) {
1371 res = talloc_zero(local_ctx, struct ldb_result);
1372 NT_STATUS_HAVE_NO_MEMORY(res);
1373 ldb_ret = ldapsrv_rename_with_controls(call, olddn, newdn, call->request->controls, res);
1374 result = map_ldb_error(local_ctx, ldb_ret, ldb_errstring(samdb),
1375 &errstr);
1378 modifydn = &modifydn_r->msg->r.ModifyDNResponse;
1379 modifydn->dn = NULL;
1380 if ((res != NULL) && (res->refs != NULL)) {
1381 modifydn->resultcode = map_ldb_error(local_ctx,
1382 LDB_ERR_REFERRAL, NULL,
1383 &errstr);;
1384 modifydn->errormessage = (errstr?talloc_strdup(modifydn_r,errstr):NULL);
1385 modifydn->referral = talloc_strdup(call, *res->refs);
1386 } else {
1387 modifydn->resultcode = result;
1388 modifydn->errormessage = (errstr?talloc_strdup(modifydn_r,errstr):NULL);
1389 modifydn->referral = NULL;
1392 talloc_free(local_ctx);
1394 return ldapsrv_queue_reply(call, modifydn_r);
1397 static NTSTATUS ldapsrv_CompareRequest(struct ldapsrv_call *call)
1399 struct ldap_CompareRequest *req = &call->request->r.CompareRequest;
1400 struct ldap_Result *compare;
1401 struct ldapsrv_reply *compare_r;
1402 TALLOC_CTX *local_ctx;
1403 struct ldb_context *samdb = call->conn->ldb;
1404 struct ldb_result *res = NULL;
1405 struct ldb_dn *dn;
1406 const char *attrs[1];
1407 const char *errstr = NULL;
1408 const char *filter = NULL;
1409 int result = LDAP_SUCCESS;
1410 int ldb_ret;
1412 DEBUG(10, ("CompareRequest"));
1413 DEBUGADD(10, (" dn: %s\n", req->dn));
1415 local_ctx = talloc_named(call, 0, "CompareRequest local_memory_context");
1416 NT_STATUS_HAVE_NO_MEMORY(local_ctx);
1418 dn = ldb_dn_new(local_ctx, samdb, req->dn);
1419 NT_STATUS_HAVE_NO_MEMORY(dn);
1421 DEBUG(10, ("CompareRequest: dn: [%s]\n", req->dn));
1422 filter = talloc_asprintf(local_ctx, "(%s=%*s)", req->attribute,
1423 (int)req->value.length, req->value.data);
1424 NT_STATUS_HAVE_NO_MEMORY(filter);
1426 DEBUGADD(10, ("CompareRequest: attribute: [%s]\n", filter));
1428 attrs[0] = NULL;
1430 compare_r = ldapsrv_init_reply(call, LDAP_TAG_CompareResponse);
1431 NT_STATUS_HAVE_NO_MEMORY(compare_r);
1433 if (result == LDAP_SUCCESS) {
1434 ldb_ret = ldb_search(samdb, local_ctx, &res,
1435 dn, LDB_SCOPE_BASE, attrs, "%s", filter);
1436 if (ldb_ret != LDB_SUCCESS) {
1437 result = map_ldb_error(local_ctx, ldb_ret,
1438 ldb_errstring(samdb), &errstr);
1439 DEBUG(10,("CompareRequest: error: %s\n", errstr));
1440 } else if (res->count == 0) {
1441 DEBUG(10,("CompareRequest: doesn't matched\n"));
1442 result = LDAP_COMPARE_FALSE;
1443 errstr = NULL;
1444 } else if (res->count == 1) {
1445 DEBUG(10,("CompareRequest: matched\n"));
1446 result = LDAP_COMPARE_TRUE;
1447 errstr = NULL;
1448 } else if (res->count > 1) {
1449 result = LDAP_OTHER;
1450 map_ldb_error(local_ctx, LDB_ERR_OTHER, NULL, &errstr);
1451 errstr = talloc_asprintf(local_ctx,
1452 "%s. Too many objects match!", errstr);
1453 DEBUG(10,("CompareRequest: %d results: %s\n", res->count, errstr));
1457 compare = &compare_r->msg->r.CompareResponse;
1458 compare->dn = NULL;
1459 compare->resultcode = result;
1460 compare->errormessage = (errstr?talloc_strdup(compare_r,errstr):NULL);
1461 compare->referral = NULL;
1463 talloc_free(local_ctx);
1465 return ldapsrv_queue_reply(call, compare_r);
1468 static NTSTATUS ldapsrv_AbandonRequest(struct ldapsrv_call *call)
1470 struct ldap_AbandonRequest *req = &call->request->r.AbandonRequest;
1471 struct ldapsrv_call *c = NULL;
1472 struct ldapsrv_call *n = NULL;
1474 DEBUG(10, ("AbandonRequest\n"));
1476 for (c = call->conn->pending_calls; c != NULL; c = n) {
1477 n = c->next;
1479 if (c->request->messageid != req->messageid) {
1480 continue;
1483 DLIST_REMOVE(call->conn->pending_calls, c);
1484 TALLOC_FREE(c);
1487 return NT_STATUS_OK;
1490 static NTSTATUS ldapsrv_expired(struct ldapsrv_call *call)
1492 struct ldapsrv_reply *reply = NULL;
1493 struct ldap_ExtendedResponse *r = NULL;
1495 DBG_DEBUG("Sending connection expired message\n");
1497 reply = ldapsrv_init_reply(call, LDAP_TAG_ExtendedResponse);
1498 if (reply == NULL) {
1499 return NT_STATUS_NO_MEMORY;
1503 * According to RFC4511 section 4.4.1 this has a msgid of 0
1505 reply->msg->messageid = 0;
1507 r = &reply->msg->r.ExtendedResponse;
1508 r->response.resultcode = LDB_ERR_UNAVAILABLE;
1509 r->response.errormessage = "The server has timed out this connection";
1510 r->oid = "1.3.6.1.4.1.1466.20036"; /* see rfc4511 section 4.4.1 */
1512 ldapsrv_queue_reply(call, reply);
1513 return NT_STATUS_OK;
1516 NTSTATUS ldapsrv_do_call(struct ldapsrv_call *call)
1518 unsigned int i;
1519 struct ldap_message *msg = call->request;
1520 struct ldapsrv_connection *conn = call->conn;
1521 NTSTATUS status;
1522 bool expired;
1524 expired = timeval_expired(&conn->limits.expire_time);
1525 if (expired) {
1526 status = ldapsrv_expired(call);
1527 if (!NT_STATUS_IS_OK(status)) {
1528 return status;
1530 return NT_STATUS_NETWORK_SESSION_EXPIRED;
1533 /* Check for undecoded critical extensions */
1534 for (i=0; msg->controls && msg->controls[i]; i++) {
1535 if (!msg->controls_decoded[i] &&
1536 msg->controls[i]->critical) {
1537 DEBUG(3, ("ldapsrv_do_call: Critical extension %s is not known to this server\n",
1538 msg->controls[i]->oid));
1539 return ldapsrv_unwilling(call, LDAP_UNAVAILABLE_CRITICAL_EXTENSION);
1543 if (call->conn->authz_logged == false) {
1544 bool log = true;
1547 * We do not want to log anonymous access if the query
1548 * is just for the rootDSE, or it is a startTLS or a
1549 * Bind.
1551 * A rootDSE search could also be done over
1552 * CLDAP anonymously for example, so these don't
1553 * really count.
1554 * Essentially we want to know about
1555 * access beyond that normally done prior to a
1556 * bind.
1559 switch(call->request->type) {
1560 case LDAP_TAG_BindRequest:
1561 case LDAP_TAG_UnbindRequest:
1562 case LDAP_TAG_AbandonRequest:
1563 log = false;
1564 break;
1565 case LDAP_TAG_ExtendedResponse: {
1566 struct ldap_ExtendedRequest *req = &call->request->r.ExtendedRequest;
1567 if (strcmp(req->oid, LDB_EXTENDED_START_TLS_OID) == 0) {
1568 log = false;
1570 break;
1572 case LDAP_TAG_SearchRequest: {
1573 struct ldap_SearchRequest *req = &call->request->r.SearchRequest;
1574 if (req->scope == LDAP_SEARCH_SCOPE_BASE) {
1575 if (req->basedn[0] == '\0') {
1576 log = false;
1579 break;
1581 default:
1582 break;
1585 if (log) {
1586 const char *transport_protection = AUTHZ_TRANSPORT_PROTECTION_NONE;
1587 if (call->conn->sockets.active == call->conn->sockets.tls) {
1588 transport_protection = AUTHZ_TRANSPORT_PROTECTION_TLS;
1591 log_successful_authz_event(call->conn->connection->msg_ctx,
1592 call->conn->connection->lp_ctx,
1593 call->conn->connection->remote_address,
1594 call->conn->connection->local_address,
1595 "LDAP",
1596 "no bind",
1597 transport_protection,
1598 call->conn->session_info,
1599 NULL /* client_audit_info */,
1600 NULL /* server_audit_info */);
1602 call->conn->authz_logged = true;
1606 switch(call->request->type) {
1607 case LDAP_TAG_BindRequest:
1608 return ldapsrv_BindRequest(call);
1609 case LDAP_TAG_UnbindRequest:
1610 return ldapsrv_UnbindRequest(call);
1611 case LDAP_TAG_SearchRequest:
1612 return ldapsrv_SearchRequest(call);
1613 case LDAP_TAG_ModifyRequest:
1614 status = ldapsrv_ModifyRequest(call);
1615 break;
1616 case LDAP_TAG_AddRequest:
1617 status = ldapsrv_AddRequest(call);
1618 break;
1619 case LDAP_TAG_DelRequest:
1620 status = ldapsrv_DelRequest(call);
1621 break;
1622 case LDAP_TAG_ModifyDNRequest:
1623 status = ldapsrv_ModifyDNRequest(call);
1624 break;
1625 case LDAP_TAG_CompareRequest:
1626 return ldapsrv_CompareRequest(call);
1627 case LDAP_TAG_AbandonRequest:
1628 return ldapsrv_AbandonRequest(call);
1629 case LDAP_TAG_ExtendedRequest:
1630 status = ldapsrv_ExtendedRequest(call);
1631 break;
1632 default:
1633 return ldapsrv_unwilling(call, LDAP_PROTOCOL_ERROR);
1636 if (NT_STATUS_IS_OK(status)) {
1637 ldapsrv_notification_retry_setup(call->conn->service, true);
1640 return status;