2 Unix SMB/CIFS implementation.
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/>.
23 #include "ldap_server/ldap_server.h"
24 #include "../lib/util/dlinklist.h"
25 #include "auth/credentials/credentials.h"
26 #include "auth/gensec/gensec.h"
27 #include "auth/common_auth.h"
28 #include "param/param.h"
29 #include "samba/service_stream.h"
30 #include "dsdb/gmsa/util.h"
31 #include "dsdb/samdb/samdb.h"
32 #include <ldb_errors.h>
33 #include <ldb_module.h>
35 #include "lib/tsocket/tsocket.h"
36 #include "libcli/ldap/ldap_proto.h"
37 #include "source4/auth/auth.h"
39 static int map_ldb_error(TALLOC_CTX
*mem_ctx
, int ldb_err
,
40 const char *add_err_string
, const char **errstring
)
44 /* Certain LDB modules need to return very special WERROR codes. Proof
45 * for them here and if they exist skip the rest of the mapping. */
46 if (add_err_string
!= NULL
) {
48 strtol(add_err_string
, &endptr
, 16);
49 if (endptr
!= add_err_string
) {
50 *errstring
= add_err_string
;
55 /* Otherwise we calculate here a generic, but appropriate WERROR. */
61 case LDB_ERR_OPERATIONS_ERROR
:
62 err
= WERR_DS_OPERATIONS_ERROR
;
64 case LDB_ERR_PROTOCOL_ERROR
:
65 err
= WERR_DS_PROTOCOL_ERROR
;
67 case LDB_ERR_TIME_LIMIT_EXCEEDED
:
68 err
= WERR_DS_TIMELIMIT_EXCEEDED
;
70 case LDB_ERR_SIZE_LIMIT_EXCEEDED
:
71 err
= WERR_DS_SIZELIMIT_EXCEEDED
;
73 case LDB_ERR_COMPARE_FALSE
:
74 err
= WERR_DS_COMPARE_FALSE
;
76 case LDB_ERR_COMPARE_TRUE
:
77 err
= WERR_DS_COMPARE_TRUE
;
79 case LDB_ERR_AUTH_METHOD_NOT_SUPPORTED
:
80 err
= WERR_DS_AUTH_METHOD_NOT_SUPPORTED
;
82 case LDB_ERR_STRONG_AUTH_REQUIRED
:
83 err
= WERR_DS_STRONG_AUTH_REQUIRED
;
85 case LDB_ERR_REFERRAL
:
86 err
= WERR_DS_REFERRAL
;
88 case LDB_ERR_ADMIN_LIMIT_EXCEEDED
:
89 err
= WERR_DS_ADMIN_LIMIT_EXCEEDED
;
91 case LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION
:
92 err
= WERR_DS_UNAVAILABLE_CRIT_EXTENSION
;
94 case LDB_ERR_CONFIDENTIALITY_REQUIRED
:
95 err
= WERR_DS_CONFIDENTIALITY_REQUIRED
;
97 case LDB_ERR_SASL_BIND_IN_PROGRESS
:
100 case LDB_ERR_NO_SUCH_ATTRIBUTE
:
101 err
= WERR_DS_NO_ATTRIBUTE_OR_VALUE
;
103 case LDB_ERR_UNDEFINED_ATTRIBUTE_TYPE
:
104 err
= WERR_DS_ATTRIBUTE_TYPE_UNDEFINED
;
106 case LDB_ERR_INAPPROPRIATE_MATCHING
:
107 err
= WERR_DS_INAPPROPRIATE_MATCHING
;
109 case LDB_ERR_CONSTRAINT_VIOLATION
:
110 err
= WERR_DS_CONSTRAINT_VIOLATION
;
112 case LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS
:
113 err
= WERR_DS_ATTRIBUTE_OR_VALUE_EXISTS
;
115 case LDB_ERR_INVALID_ATTRIBUTE_SYNTAX
:
116 err
= WERR_DS_INVALID_ATTRIBUTE_SYNTAX
;
118 case LDB_ERR_NO_SUCH_OBJECT
:
119 err
= WERR_DS_NO_SUCH_OBJECT
;
121 case LDB_ERR_ALIAS_PROBLEM
:
122 err
= WERR_DS_ALIAS_PROBLEM
;
124 case LDB_ERR_INVALID_DN_SYNTAX
:
125 err
= WERR_DS_INVALID_DN_SYNTAX
;
127 case LDB_ERR_ALIAS_DEREFERENCING_PROBLEM
:
128 err
= WERR_DS_ALIAS_DEREF_PROBLEM
;
130 case LDB_ERR_INAPPROPRIATE_AUTHENTICATION
:
131 err
= WERR_DS_INAPPROPRIATE_AUTH
;
133 case LDB_ERR_INVALID_CREDENTIALS
:
134 err
= WERR_ACCESS_DENIED
;
136 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS
:
137 err
= WERR_DS_INSUFF_ACCESS_RIGHTS
;
142 case LDB_ERR_UNAVAILABLE
:
143 err
= WERR_DS_UNAVAILABLE
;
145 case LDB_ERR_UNWILLING_TO_PERFORM
:
146 err
= WERR_DS_UNWILLING_TO_PERFORM
;
148 case LDB_ERR_LOOP_DETECT
:
149 err
= WERR_DS_LOOP_DETECT
;
151 case LDB_ERR_NAMING_VIOLATION
:
152 err
= WERR_DS_NAMING_VIOLATION
;
154 case LDB_ERR_OBJECT_CLASS_VIOLATION
:
155 err
= WERR_DS_OBJ_CLASS_VIOLATION
;
157 case LDB_ERR_NOT_ALLOWED_ON_NON_LEAF
:
158 err
= WERR_DS_CANT_ON_NON_LEAF
;
160 case LDB_ERR_NOT_ALLOWED_ON_RDN
:
161 err
= WERR_DS_CANT_ON_RDN
;
163 case LDB_ERR_ENTRY_ALREADY_EXISTS
:
164 err
= WERR_DS_OBJ_STRING_NAME_EXISTS
;
166 case LDB_ERR_OBJECT_CLASS_MODS_PROHIBITED
:
167 err
= WERR_DS_CANT_MOD_OBJ_CLASS
;
169 case LDB_ERR_AFFECTS_MULTIPLE_DSAS
:
170 err
= WERR_DS_AFFECTS_MULTIPLE_DSAS
;
173 err
= WERR_DS_GENERIC_ERROR
;
177 *errstring
= talloc_asprintf(mem_ctx
, "%08X: %s", W_ERROR_V(err
),
178 add_err_string
!= NULL
? add_err_string
: ldb_strerror(ldb_err
));
180 /* result is 1:1 for now */
185 connect to the sam database
187 int ldapsrv_backend_Init(struct ldapsrv_connection
*conn
,
190 bool using_tls
= conn
->sockets
.active
== conn
->sockets
.tls
;
191 bool using_seal
= conn
->gensec
!= NULL
&& gensec_have_feature(conn
->gensec
,
192 GENSEC_FEATURE_SEAL
);
193 struct dsdb_encrypted_connection_state
*opaque_connection_state
= NULL
;
195 int ret
= samdb_connect_url(conn
,
196 conn
->connection
->event
.ctx
,
199 conn
->global_catalog
? LDB_FLG_RDONLY
: 0,
201 conn
->connection
->remote_address
,
204 if (ret
!= LDB_SUCCESS
) {
209 * We can safely call ldb_set_opaque() on this ldb as we have
210 * set remote_address above which avoids the ldb handle cache
212 opaque_connection_state
= talloc_zero(conn
, struct dsdb_encrypted_connection_state
);
213 if (opaque_connection_state
== NULL
) {
214 return LDB_ERR_OPERATIONS_ERROR
;
216 opaque_connection_state
->using_encrypted_connection
= using_tls
|| using_seal
|| conn
->is_ldapi
;
217 ret
= ldb_set_opaque(conn
->ldb
,
218 DSDB_OPAQUE_ENCRYPTED_CONNECTION_STATE_NAME
,
219 opaque_connection_state
);
220 if (ret
!= LDB_SUCCESS
) {
221 DBG_ERR("ldb_set_opaque() failed to store our "
222 "encrypted connection state!\n");
226 if (conn
->server_credentials
) {
227 struct gensec_security
*gensec_security
= NULL
;
228 const char **sasl_mechs
= NULL
;
231 status
= samba_server_gensec_start(conn
,
232 conn
->connection
->event
.ctx
,
233 conn
->connection
->msg_ctx
,
235 conn
->server_credentials
,
238 if (!NT_STATUS_IS_OK(status
)) {
239 DBG_ERR("samba_server_gensec_start failed: %s\n",
241 return LDB_ERR_OPERATIONS_ERROR
;
244 /* ldb can have a different lifetime to conn, so we
245 need to ensure that sasl_mechs lives as long as the
247 sasl_mechs
= gensec_security_sasl_names(gensec_security
,
249 TALLOC_FREE(gensec_security
);
250 if (sasl_mechs
== NULL
) {
251 DBG_ERR("Failed to get sasl mechs!\n");
252 return LDB_ERR_OPERATIONS_ERROR
;
255 ldb_set_opaque(conn
->ldb
, "supportedSASLMechanisms", sasl_mechs
);
261 struct ldapsrv_reply
*ldapsrv_init_reply(struct ldapsrv_call
*call
, uint8_t type
)
263 struct ldapsrv_reply
*reply
;
265 reply
= talloc_zero(call
, struct ldapsrv_reply
);
269 reply
->msg
= talloc_zero(reply
, struct ldap_message
);
270 if (reply
->msg
== NULL
) {
275 reply
->msg
->messageid
= call
->request
->messageid
;
276 reply
->msg
->type
= type
;
277 reply
->msg
->controls
= NULL
;
283 * Encode a reply to an LDAP client as ASN.1, free the original memory
285 static NTSTATUS
ldapsrv_encode(TALLOC_CTX
*mem_ctx
,
286 struct ldapsrv_reply
*reply
)
288 bool bret
= ldap_encode(reply
->msg
,
289 samba_ldap_control_handlers(),
293 DBG_ERR("Failed to encode ldap reply of type %d: "
294 "ldap_encode() failed\n",
296 TALLOC_FREE(reply
->msg
);
297 return NT_STATUS_NO_MEMORY
;
300 TALLOC_FREE(reply
->msg
);
301 talloc_set_name_const(reply
->blob
.data
,
302 "Outgoing, encoded single LDAP reply");
308 * Queue a reply (encoding it also), even if it would exceed the
309 * limit. This allows the error packet with LDAP_SIZE_LIMIT_EXCEEDED
312 static NTSTATUS
ldapsrv_queue_reply_forced(struct ldapsrv_call
*call
,
313 struct ldapsrv_reply
*reply
)
315 NTSTATUS status
= ldapsrv_encode(call
, reply
);
317 if (NT_STATUS_IS_OK(status
)) {
318 DLIST_ADD_END(call
->replies
, reply
);
324 * Queue a reply (encoding it also) but check we do not send more than
325 * LDAP_SERVER_MAX_REPLY_SIZE of responses as a way to limit the
326 * amount of data a client can make us allocate.
328 NTSTATUS
ldapsrv_queue_reply(struct ldapsrv_call
*call
, struct ldapsrv_reply
*reply
)
330 NTSTATUS status
= ldapsrv_encode(call
, reply
);
332 if (!NT_STATUS_IS_OK(status
)) {
336 if (call
->reply_size
> call
->reply_size
+ reply
->blob
.length
337 || call
->reply_size
+ reply
->blob
.length
> LDAP_SERVER_MAX_REPLY_SIZE
) {
338 DBG_WARNING("Refusing to queue LDAP search response size "
339 "of more than %zu bytes\n",
340 LDAP_SERVER_MAX_REPLY_SIZE
);
341 TALLOC_FREE(reply
->blob
.data
);
342 return NT_STATUS_FILE_TOO_LARGE
;
345 call
->reply_size
+= reply
->blob
.length
;
347 DLIST_ADD_END(call
->replies
, reply
);
352 static NTSTATUS
ldapsrv_unwilling(struct ldapsrv_call
*call
, int error
)
354 struct ldapsrv_reply
*reply
;
355 struct ldap_ExtendedResponse
*r
;
357 DBG_DEBUG("type[%d] id[%d]\n", call
->request
->type
, call
->request
->messageid
);
359 reply
= ldapsrv_init_reply(call
, LDAP_TAG_ExtendedResponse
);
361 return NT_STATUS_NO_MEMORY
;
364 r
= &reply
->msg
->r
.ExtendedResponse
;
365 r
->response
.resultcode
= error
;
366 r
->response
.dn
= NULL
;
367 r
->response
.errormessage
= NULL
;
368 r
->response
.referral
= NULL
;
372 ldapsrv_queue_reply(call
, reply
);
376 static int ldapsrv_add_with_controls(struct ldapsrv_call
*call
,
377 const struct ldb_message
*message
,
378 struct ldb_control
**controls
,
379 struct ldb_result
*res
)
381 struct ldb_context
*ldb
= call
->conn
->ldb
;
382 struct ldb_request
*req
;
385 ret
= ldb_msg_sanity_check(ldb
, message
);
386 if (ret
!= LDB_SUCCESS
) {
390 ret
= ldb_build_add_req(&req
, ldb
, ldb
,
394 ldb_modify_default_callback
,
397 if (ret
!= LDB_SUCCESS
) return ret
;
399 if (call
->conn
->global_catalog
) {
400 return ldb_error(ldb
, LDB_ERR_UNWILLING_TO_PERFORM
, "modify forbidden on global catalog port");
402 ldb_request_add_control(req
, DSDB_CONTROL_NO_GLOBAL_CATALOG
, false, NULL
);
404 ret
= ldb_transaction_start(ldb
);
405 if (ret
!= LDB_SUCCESS
) {
409 if (!call
->conn
->is_privileged
) {
410 ldb_req_mark_untrusted(req
);
413 LDB_REQ_SET_LOCATION(req
);
415 ret
= ldb_request(ldb
, req
);
416 if (ret
== LDB_SUCCESS
) {
417 ret
= ldb_wait(req
->handle
, LDB_WAIT_ALL
);
420 if (ret
== LDB_SUCCESS
) {
421 ret
= ldb_transaction_commit(ldb
);
424 ldb_transaction_cancel(ldb
);
431 /* create and execute a modify request */
432 static int ldapsrv_mod_with_controls(struct ldapsrv_call
*call
,
433 const struct ldb_message
*message
,
434 struct ldb_control
**controls
,
435 struct ldb_result
*res
)
437 struct ldb_context
*ldb
= call
->conn
->ldb
;
438 struct ldb_request
*req
;
441 ret
= ldb_msg_sanity_check(ldb
, message
);
442 if (ret
!= LDB_SUCCESS
) {
446 ret
= ldb_build_mod_req(&req
, ldb
, ldb
,
450 ldb_modify_default_callback
,
453 if (ret
!= LDB_SUCCESS
) {
457 if (call
->conn
->global_catalog
) {
458 return ldb_error(ldb
, LDB_ERR_UNWILLING_TO_PERFORM
, "modify forbidden on global catalog port");
460 ldb_request_add_control(req
, DSDB_CONTROL_NO_GLOBAL_CATALOG
, false, NULL
);
462 ret
= ldb_transaction_start(ldb
);
463 if (ret
!= LDB_SUCCESS
) {
467 if (!call
->conn
->is_privileged
) {
468 ldb_req_mark_untrusted(req
);
471 LDB_REQ_SET_LOCATION(req
);
473 ret
= ldb_request(ldb
, req
);
474 if (ret
== LDB_SUCCESS
) {
475 ret
= ldb_wait(req
->handle
, LDB_WAIT_ALL
);
478 if (ret
== LDB_SUCCESS
) {
479 ret
= ldb_transaction_commit(ldb
);
482 ldb_transaction_cancel(ldb
);
489 /* create and execute a delete request */
490 static int ldapsrv_del_with_controls(struct ldapsrv_call
*call
,
492 struct ldb_control
**controls
,
493 struct ldb_result
*res
)
495 struct ldb_context
*ldb
= call
->conn
->ldb
;
496 struct ldb_request
*req
;
499 ret
= ldb_build_del_req(&req
, ldb
, ldb
,
503 ldb_modify_default_callback
,
506 if (ret
!= LDB_SUCCESS
) return ret
;
508 if (call
->conn
->global_catalog
) {
509 return ldb_error(ldb
, LDB_ERR_UNWILLING_TO_PERFORM
, "modify forbidden on global catalog port");
511 ldb_request_add_control(req
, DSDB_CONTROL_NO_GLOBAL_CATALOG
, false, NULL
);
513 ret
= ldb_transaction_start(ldb
);
514 if (ret
!= LDB_SUCCESS
) {
518 if (!call
->conn
->is_privileged
) {
519 ldb_req_mark_untrusted(req
);
522 LDB_REQ_SET_LOCATION(req
);
524 ret
= ldb_request(ldb
, req
);
525 if (ret
== LDB_SUCCESS
) {
526 ret
= ldb_wait(req
->handle
, LDB_WAIT_ALL
);
529 if (ret
== LDB_SUCCESS
) {
530 ret
= ldb_transaction_commit(ldb
);
533 ldb_transaction_cancel(ldb
);
540 static int ldapsrv_rename_with_controls(struct ldapsrv_call
*call
,
541 struct ldb_dn
*olddn
,
542 struct ldb_dn
*newdn
,
543 struct ldb_control
**controls
,
544 struct ldb_result
*res
)
546 struct ldb_context
*ldb
= call
->conn
->ldb
;
547 struct ldb_request
*req
;
550 ret
= ldb_build_rename_req(&req
, ldb
, ldb
,
555 ldb_modify_default_callback
,
558 if (ret
!= LDB_SUCCESS
) return ret
;
560 if (call
->conn
->global_catalog
) {
561 return ldb_error(ldb
, LDB_ERR_UNWILLING_TO_PERFORM
, "modify forbidden on global catalog port");
563 ldb_request_add_control(req
, DSDB_CONTROL_NO_GLOBAL_CATALOG
, false, NULL
);
565 ret
= ldb_transaction_start(ldb
);
566 if (ret
!= LDB_SUCCESS
) {
570 if (!call
->conn
->is_privileged
) {
571 ldb_req_mark_untrusted(req
);
574 LDB_REQ_SET_LOCATION(req
);
576 ret
= ldb_request(ldb
, req
);
577 if (ret
== LDB_SUCCESS
) {
578 ret
= ldb_wait(req
->handle
, LDB_WAIT_ALL
);
581 if (ret
== LDB_SUCCESS
) {
582 ret
= ldb_transaction_commit(ldb
);
585 ldb_transaction_cancel(ldb
);
594 struct ldapsrv_context
{
595 struct ldapsrv_call
*call
;
598 struct ldb_control
**controls
;
599 size_t count
; /* For notification only */
600 const struct gmsa_update
**updates
;
603 static int ldap_server_search_callback(struct ldb_request
*req
, struct ldb_reply
*ares
)
605 struct ldapsrv_context
*ctx
= talloc_get_type(req
->context
, struct ldapsrv_context
);
606 struct ldapsrv_call
*call
= ctx
->call
;
607 struct ldb_context
*ldb
= call
->conn
->ldb
;
609 struct ldapsrv_reply
*ent_r
= NULL
;
610 struct ldap_SearchResEntry
*ent
;
615 return ldb_request_done(req
, LDB_ERR_OPERATIONS_ERROR
);
617 if (ares
->error
!= LDB_SUCCESS
) {
618 return ldb_request_done(req
, ares
->error
);
621 switch (ares
->type
) {
622 case LDB_REPLY_ENTRY
:
624 struct ldb_message
*msg
= ares
->message
;
625 ent_r
= ldapsrv_init_reply(call
, LDAP_TAG_SearchResultEntry
);
633 * Put the LDAP search response data under ent_r->msg
634 * so we can free that later once encoded
636 talloc_steal(ent_r
->msg
, msg
);
638 ent
= &ent_r
->msg
->r
.SearchResultEntry
;
639 ent
->dn
= ldb_dn_get_extended_linearized(ent_r
, msg
->dn
,
641 ent
->num_attributes
= 0;
642 ent
->attributes
= NULL
;
643 if (msg
->num_elements
== 0) {
646 ent
->num_attributes
= msg
->num_elements
;
647 ent
->attributes
= talloc_array(ent_r
, struct ldb_message_element
, ent
->num_attributes
);
648 if (ent
->attributes
== NULL
) {
652 for (j
=0; j
< ent
->num_attributes
; j
++) {
653 ent
->attributes
[j
].name
= msg
->elements
[j
].name
;
654 ent
->attributes
[j
].num_values
= 0;
655 ent
->attributes
[j
].values
= NULL
;
656 if (ctx
->attributesonly
&& (msg
->elements
[j
].num_values
== 0)) {
659 ent
->attributes
[j
].num_values
= msg
->elements
[j
].num_values
;
660 ent
->attributes
[j
].values
= msg
->elements
[j
].values
;
664 const struct ldb_control
665 *ctrl
= ldb_controls_get_control(
667 DSDB_CONTROL_GMSA_UPDATE_OID
);
670 const struct gmsa_update
**updates
= NULL
;
671 const size_t len
= talloc_array_length(
674 updates
= talloc_realloc(
677 const struct gmsa_update
*,
679 if (updates
!= NULL
) {
680 updates
[len
] = talloc_steal(updates
,
682 ctx
->updates
= updates
;
688 status
= ldapsrv_queue_reply(call
, ent_r
);
689 if (NT_STATUS_EQUAL(status
, NT_STATUS_FILE_TOO_LARGE
)) {
690 ret
= ldb_request_done(req
,
691 LDB_ERR_SIZE_LIMIT_EXCEEDED
);
692 ldb_asprintf_errstring(ldb
,
693 "LDAP search response size "
694 "limited to %zu bytes\n",
695 LDAP_SERVER_MAX_REPLY_SIZE
);
696 } else if (!NT_STATUS_IS_OK(status
)) {
697 ret
= ldb_request_done(req
,
704 case LDB_REPLY_REFERRAL
:
706 struct ldap_SearchResRef
*ent_ref
;
709 * TODO: This should be handled by the notification
712 if (call
->notification
.busy
) {
717 ent_r
= ldapsrv_init_reply(call
, LDAP_TAG_SearchResultReference
);
723 * Put the LDAP referral data under ent_r->msg
724 * so we can free that later once encoded
726 talloc_steal(ent_r
->msg
, ares
->referral
);
728 ent_ref
= &ent_r
->msg
->r
.SearchResultReference
;
729 ent_ref
->referral
= ares
->referral
;
731 status
= ldapsrv_queue_reply(call
, ent_r
);
732 if (!NT_STATUS_IS_OK(status
)) {
733 ret
= LDB_ERR_OPERATIONS_ERROR
;
742 * We don't queue the reply for this one, we let that
745 ctx
->controls
= talloc_move(ctx
, &ares
->controls
);
748 return ldb_request_done(req
, LDB_SUCCESS
);
752 ret
= LDB_ERR_OPERATIONS_ERROR
;
760 static NTSTATUS
ldapsrv_SearchRequest(struct ldapsrv_call
*call
)
762 struct ldap_SearchRequest
*req
= &call
->request
->r
.SearchRequest
;
763 struct ldap_Result
*done
;
764 struct ldapsrv_reply
*done_r
;
765 TALLOC_CTX
*local_ctx
;
766 struct ldapsrv_context
*callback_ctx
= NULL
;
767 struct ldb_context
*samdb
= talloc_get_type(call
->conn
->ldb
, struct ldb_context
);
768 struct ldb_dn
*basedn
;
769 struct ldb_request
*lreq
;
770 struct ldb_control
*search_control
;
771 struct ldb_search_options_control
*search_options
;
772 struct ldb_control
*extended_dn_control
;
773 struct ldb_extended_dn_control
*extended_dn_decoded
= NULL
;
774 struct ldb_control
*notification_control
= NULL
;
775 enum ldb_scope scope
= LDB_SCOPE_DEFAULT
;
776 const char **attrs
= NULL
;
777 const char *scope_str
, *errstr
= NULL
;
781 int extended_type
= 1;
784 * Warn for searches that are longer than 1/4 of the
785 * search_timeout, being 30sec by default
787 struct timeval start_time
= timeval_current();
788 struct timeval warning_time
789 = timeval_add(&start_time
,
790 call
->conn
->limits
.search_timeout
/ 4,
793 local_ctx
= talloc_new(call
);
794 NT_STATUS_HAVE_NO_MEMORY(local_ctx
);
796 basedn
= ldb_dn_new(local_ctx
, samdb
, req
->basedn
);
797 NT_STATUS_HAVE_NO_MEMORY(basedn
);
799 switch (req
->scope
) {
800 case LDAP_SEARCH_SCOPE_BASE
:
801 scope
= LDB_SCOPE_BASE
;
803 case LDAP_SEARCH_SCOPE_SINGLE
:
804 scope
= LDB_SCOPE_ONELEVEL
;
806 case LDAP_SEARCH_SCOPE_SUB
:
807 scope
= LDB_SCOPE_SUBTREE
;
810 result
= LDAP_PROTOCOL_ERROR
;
811 map_ldb_error(local_ctx
, LDB_ERR_PROTOCOL_ERROR
, NULL
,
813 scope_str
= "<Invalid scope>";
814 errstr
= talloc_asprintf(local_ctx
,
815 "%s. Invalid scope", errstr
);
818 scope_str
= dsdb_search_scope_as_string(scope
);
820 DBG_DEBUG("scope: [%s]\n", scope_str
);
822 if (req
->num_attributes
>= 1) {
823 attrs
= talloc_array(local_ctx
, const char *, req
->num_attributes
+1);
824 NT_STATUS_HAVE_NO_MEMORY(attrs
);
826 for (i
=0; i
< req
->num_attributes
; i
++) {
827 DBG_DEBUG("attrs: [%s]\n",req
->attributes
[i
]);
828 attrs
[i
] = req
->attributes
[i
];
833 DBG_INFO("ldb_request %s dn=%s filter=%s\n",
834 scope_str
, req
->basedn
, ldb_filter_from_tree(call
, req
->tree
));
836 callback_ctx
= talloc_zero(local_ctx
, struct ldapsrv_context
);
837 NT_STATUS_HAVE_NO_MEMORY(callback_ctx
);
838 callback_ctx
->call
= call
;
839 callback_ctx
->extended_type
= extended_type
;
840 callback_ctx
->attributesonly
= req
->attributesonly
;
842 ldb_ret
= ldb_build_search_req_ex(&lreq
, samdb
, local_ctx
,
845 call
->request
->controls
,
847 ldap_server_search_callback
,
850 if (ldb_ret
!= LDB_SUCCESS
) {
854 if (call
->conn
->global_catalog
) {
855 search_control
= ldb_request_get_control(lreq
, LDB_CONTROL_SEARCH_OPTIONS_OID
);
857 search_options
= NULL
;
858 if (search_control
) {
859 search_options
= talloc_get_type(search_control
->data
, struct ldb_search_options_control
);
860 search_options
->search_options
|= LDB_SEARCH_OPTION_PHANTOM_ROOT
;
862 search_options
= talloc(lreq
, struct ldb_search_options_control
);
863 NT_STATUS_HAVE_NO_MEMORY(search_options
);
864 search_options
->search_options
= LDB_SEARCH_OPTION_PHANTOM_ROOT
;
865 ldb_request_add_control(lreq
, LDB_CONTROL_SEARCH_OPTIONS_OID
, false, search_options
);
868 ldb_request_add_control(lreq
, DSDB_CONTROL_NO_GLOBAL_CATALOG
, false, NULL
);
871 extended_dn_control
= ldb_request_get_control(lreq
, LDB_CONTROL_EXTENDED_DN_OID
);
873 if (extended_dn_control
) {
874 if (extended_dn_control
->data
) {
875 extended_dn_decoded
= talloc_get_type(extended_dn_control
->data
, struct ldb_extended_dn_control
);
876 extended_type
= extended_dn_decoded
->type
;
880 callback_ctx
->extended_type
= extended_type
;
883 notification_control
= ldb_request_get_control(lreq
, LDB_CONTROL_NOTIFICATION_OID
);
884 if (notification_control
!= NULL
) {
885 const struct ldapsrv_call
*pc
= NULL
;
888 for (pc
= call
->conn
->pending_calls
; pc
!= NULL
; pc
= pc
->next
) {
892 if (count
>= call
->conn
->limits
.max_notifications
) {
893 DBG_DEBUG("error MaxNotificationPerConn\n");
894 result
= map_ldb_error(local_ctx
,
895 LDB_ERR_ADMIN_LIMIT_EXCEEDED
,
896 "MaxNotificationPerConn reached",
902 * For now we need to do periodic retries on our own.
903 * As the dsdb_notification module will return after each run.
905 call
->notification
.busy
= true;
909 const char *scheme
= NULL
;
910 switch (call
->conn
->referral_scheme
) {
911 case LDAP_REFERRAL_SCHEME_LDAPS
:
917 ldb_ret
= ldb_set_opaque(
919 LDAP_REFERRAL_SCHEME_OPAQUE
,
920 discard_const_p(char *, scheme
));
921 if (ldb_ret
!= LDB_SUCCESS
) {
927 time_t timeout
= call
->conn
->limits
.search_timeout
;
930 || (req
->timelimit
!= 0
931 && req
->timelimit
< timeout
))
933 timeout
= req
->timelimit
;
935 ldb_set_timeout(samdb
, lreq
, timeout
);
938 if (!call
->conn
->is_privileged
) {
939 ldb_req_mark_untrusted(lreq
);
942 LDB_REQ_SET_LOCATION(lreq
);
944 ldb_ret
= ldb_request(samdb
, lreq
);
946 if (ldb_ret
!= LDB_SUCCESS
) {
950 ldb_ret
= ldb_wait(lreq
->handle
, LDB_WAIT_ALL
);
952 if (ldb_ret
== LDB_SUCCESS
) {
954 const size_t len
= talloc_array_length(callback_ctx
->updates
);
956 for (n
= 0; n
< len
; ++n
) {
959 ret
= dsdb_update_gmsa_entry_keys(
960 samdb
, local_ctx
, callback_ctx
->updates
[n
]);
962 /* Ignore the error. */
963 DBG_WARNING("Failed to update keys for Group "
964 "Managed Service Account: %s\n",
969 if (call
->notification
.busy
) {
970 /* Move/Add it to the end */
971 DLIST_DEMOTE(call
->conn
->pending_calls
, call
);
972 call
->notification
.generation
=
973 call
->conn
->service
->notification
.generation
;
975 if (callback_ctx
->count
!= 0) {
976 call
->notification
.generation
+= 1;
977 ldapsrv_notification_retry_setup(call
->conn
->service
,
981 talloc_free(local_ctx
);
989 * This looks like duplicated code - because it is - but
990 * otherwise the work in the parameters will be done
991 * regardless, this way the functions only execute when the
994 * The basedn is re-obtained as a string to escape it
996 if ((req
->timelimit
== 0 || call
->conn
->limits
.search_timeout
< req
->timelimit
)
997 && ldb_ret
== LDB_ERR_TIME_LIMIT_EXCEEDED
) {
998 struct dom_sid_buf sid_buf
;
999 DBG_WARNING("MaxQueryDuration(%d) timeout exceeded "
1000 "in SearchRequest by %s from %s filter: [%s] "
1003 call
->conn
->limits
.search_timeout
,
1004 dom_sid_str_buf(&call
->conn
->session_info
->security_token
->sids
[0],
1006 tsocket_address_string(call
->conn
->connection
->remote_address
,
1008 ldb_filter_from_tree(call
, req
->tree
),
1009 ldb_dn_get_extended_linearized(call
, basedn
, 1),
1011 for (i
=0; i
< req
->num_attributes
; i
++) {
1012 DBG_WARNING("MaxQueryDuration timeout exceeded attrs: [%s]\n",
1013 req
->attributes
[i
]);
1016 } else if (timeval_expired(&warning_time
)) {
1017 struct dom_sid_buf sid_buf
;
1018 DBG_NOTICE("Long LDAP Query: Duration was %.2fs, "
1019 "MaxQueryDuration(%d)/4 == %d "
1020 "in SearchRequest by %s from %s filter: [%s] "
1024 timeval_elapsed(&start_time
),
1025 call
->conn
->limits
.search_timeout
,
1026 call
->conn
->limits
.search_timeout
/ 4,
1027 dom_sid_str_buf(&call
->conn
->session_info
->security_token
->sids
[0],
1029 tsocket_address_string(call
->conn
->connection
->remote_address
,
1031 ldb_filter_from_tree(call
, req
->tree
),
1032 ldb_dn_get_extended_linearized(call
, basedn
, 1),
1034 ldb_strerror(ldb_ret
));
1035 for (i
=0; i
< req
->num_attributes
; i
++) {
1036 DBG_NOTICE("Long LDAP Query attrs: [%s]\n",
1037 req
->attributes
[i
]);
1040 struct dom_sid_buf sid_buf
;
1041 DBG_INFO("LDAP Query: Duration was %.2fs, "
1042 "SearchRequest by %s from %s filter: [%s] "
1046 timeval_elapsed(&start_time
),
1047 dom_sid_str_buf(&call
->conn
->session_info
->security_token
->sids
[0],
1049 tsocket_address_string(call
->conn
->connection
->remote_address
,
1051 ldb_filter_from_tree(call
, req
->tree
),
1052 ldb_dn_get_extended_linearized(call
, basedn
, 1),
1054 ldb_strerror(ldb_ret
));
1057 DLIST_REMOVE(call
->conn
->pending_calls
, call
);
1058 call
->notification
.busy
= false;
1060 done_r
= ldapsrv_init_reply(call
, LDAP_TAG_SearchResultDone
);
1061 NT_STATUS_HAVE_NO_MEMORY(done_r
);
1063 done
= &done_r
->msg
->r
.SearchResultDone
;
1065 done
->referral
= NULL
;
1068 } else if (ldb_ret
== LDB_SUCCESS
) {
1069 if (callback_ctx
->controls
) {
1070 done_r
->msg
->controls
= callback_ctx
->controls
;
1071 talloc_steal(done_r
->msg
, callback_ctx
->controls
);
1073 result
= LDB_SUCCESS
;
1075 DBG_DEBUG("error\n");
1076 result
= map_ldb_error(local_ctx
, ldb_ret
, ldb_errstring(samdb
),
1080 done
->resultcode
= result
;
1081 done
->errormessage
= (errstr
?talloc_strdup(done_r
, errstr
):NULL
);
1083 talloc_free(local_ctx
);
1085 return ldapsrv_queue_reply_forced(call
, done_r
);
1088 static NTSTATUS
ldapsrv_ModifyRequest(struct ldapsrv_call
*call
)
1090 struct ldap_ModifyRequest
*req
= &call
->request
->r
.ModifyRequest
;
1091 struct ldap_Result
*modify_result
;
1092 struct ldapsrv_reply
*modify_reply
;
1093 TALLOC_CTX
*local_ctx
;
1094 struct ldb_context
*samdb
= call
->conn
->ldb
;
1095 struct ldb_message
*msg
= NULL
;
1097 const char *errstr
= NULL
;
1098 int result
= LDAP_SUCCESS
;
1101 struct ldb_result
*res
= NULL
;
1103 DBG_DEBUG("dn: %s\n", req
->dn
);
1105 local_ctx
= talloc_named(call
, 0, "ModifyRequest local memory context");
1106 NT_STATUS_HAVE_NO_MEMORY(local_ctx
);
1108 dn
= ldb_dn_new(local_ctx
, samdb
, req
->dn
);
1109 NT_STATUS_HAVE_NO_MEMORY(dn
);
1111 DBG_DEBUG("dn: [%s]\n", req
->dn
);
1113 msg
= ldb_msg_new(local_ctx
);
1114 NT_STATUS_HAVE_NO_MEMORY(msg
);
1118 if (req
->num_mods
> 0) {
1119 msg
->num_elements
= req
->num_mods
;
1120 msg
->elements
= talloc_array(msg
, struct ldb_message_element
, req
->num_mods
);
1121 NT_STATUS_HAVE_NO_MEMORY(msg
->elements
);
1123 for (i
=0; i
< msg
->num_elements
; i
++) {
1124 msg
->elements
[i
].name
= discard_const_p(char, req
->mods
[i
].attrib
.name
);
1125 msg
->elements
[i
].num_values
= 0;
1126 msg
->elements
[i
].values
= NULL
;
1128 switch (req
->mods
[i
].type
) {
1130 result
= LDAP_PROTOCOL_ERROR
;
1131 map_ldb_error(local_ctx
,
1132 LDB_ERR_PROTOCOL_ERROR
, NULL
, &errstr
);
1133 errstr
= talloc_asprintf(local_ctx
,
1134 "%s. Invalid LDAP_MODIFY_* type", errstr
);
1136 case LDAP_MODIFY_ADD
:
1137 msg
->elements
[i
].flags
= LDB_FLAG_MOD_ADD
;
1139 case LDAP_MODIFY_DELETE
:
1140 msg
->elements
[i
].flags
= LDB_FLAG_MOD_DELETE
;
1142 case LDAP_MODIFY_REPLACE
:
1143 msg
->elements
[i
].flags
= LDB_FLAG_MOD_REPLACE
;
1147 msg
->elements
[i
].num_values
= req
->mods
[i
].attrib
.num_values
;
1148 if (msg
->elements
[i
].num_values
> 0) {
1149 msg
->elements
[i
].values
= talloc_array(msg
->elements
, struct ldb_val
,
1150 msg
->elements
[i
].num_values
);
1151 NT_STATUS_HAVE_NO_MEMORY(msg
->elements
[i
].values
);
1153 for (j
=0; j
< msg
->elements
[i
].num_values
; j
++) {
1154 msg
->elements
[i
].values
[j
].length
= req
->mods
[i
].attrib
.values
[j
].length
;
1155 msg
->elements
[i
].values
[j
].data
= req
->mods
[i
].attrib
.values
[j
].data
;
1162 modify_reply
= ldapsrv_init_reply(call
, LDAP_TAG_ModifyResponse
);
1163 NT_STATUS_HAVE_NO_MEMORY(modify_reply
);
1165 if (result
== LDAP_SUCCESS
) {
1166 res
= talloc_zero(local_ctx
, struct ldb_result
);
1167 NT_STATUS_HAVE_NO_MEMORY(res
);
1168 ldb_ret
= ldapsrv_mod_with_controls(call
, msg
, call
->request
->controls
, res
);
1169 result
= map_ldb_error(local_ctx
, ldb_ret
, ldb_errstring(samdb
),
1173 modify_result
= &modify_reply
->msg
->r
.ModifyResponse
;
1174 modify_result
->dn
= NULL
;
1175 if ((res
!= NULL
) && (res
->refs
!= NULL
)) {
1176 modify_result
->resultcode
= map_ldb_error(local_ctx
,
1179 modify_result
->errormessage
= (errstr
?talloc_strdup(modify_reply
, errstr
):NULL
);
1180 modify_result
->referral
= talloc_strdup(call
, *res
->refs
);
1182 modify_result
->resultcode
= result
;
1183 modify_result
->errormessage
= (errstr
?talloc_strdup(modify_reply
, errstr
):NULL
);
1184 modify_result
->referral
= NULL
;
1186 talloc_free(local_ctx
);
1188 return ldapsrv_queue_reply(call
, modify_reply
);
1192 static NTSTATUS
ldapsrv_AddRequest(struct ldapsrv_call
*call
)
1194 struct ldap_AddRequest
*req
= &call
->request
->r
.AddRequest
;
1195 struct ldap_Result
*add_result
;
1196 struct ldapsrv_reply
*add_reply
;
1197 TALLOC_CTX
*local_ctx
;
1198 struct ldb_context
*samdb
= call
->conn
->ldb
;
1199 struct ldb_message
*msg
= NULL
;
1201 const char *errstr
= NULL
;
1202 int result
= LDAP_SUCCESS
;
1205 struct ldb_result
*res
= NULL
;
1207 DBG_DEBUG("dn: %s\n", req
->dn
);
1209 local_ctx
= talloc_named(call
, 0, "AddRequest local memory context");
1210 NT_STATUS_HAVE_NO_MEMORY(local_ctx
);
1212 dn
= ldb_dn_new(local_ctx
, samdb
, req
->dn
);
1213 NT_STATUS_HAVE_NO_MEMORY(dn
);
1215 DBG_DEBUG("dn: [%s]\n", req
->dn
);
1217 msg
= talloc(local_ctx
, struct ldb_message
);
1218 NT_STATUS_HAVE_NO_MEMORY(msg
);
1221 msg
->num_elements
= 0;
1222 msg
->elements
= NULL
;
1224 if (req
->num_attributes
> 0) {
1225 msg
->num_elements
= req
->num_attributes
;
1226 msg
->elements
= talloc_array(msg
, struct ldb_message_element
, msg
->num_elements
);
1227 NT_STATUS_HAVE_NO_MEMORY(msg
->elements
);
1229 for (i
=0; i
< msg
->num_elements
; i
++) {
1230 msg
->elements
[i
].name
= discard_const_p(char, req
->attributes
[i
].name
);
1231 msg
->elements
[i
].flags
= 0;
1232 msg
->elements
[i
].num_values
= 0;
1233 msg
->elements
[i
].values
= NULL
;
1235 if (req
->attributes
[i
].num_values
> 0) {
1236 msg
->elements
[i
].num_values
= req
->attributes
[i
].num_values
;
1237 msg
->elements
[i
].values
= talloc_array(msg
->elements
, struct ldb_val
,
1238 msg
->elements
[i
].num_values
);
1239 NT_STATUS_HAVE_NO_MEMORY(msg
->elements
[i
].values
);
1241 for (j
=0; j
< msg
->elements
[i
].num_values
; j
++) {
1242 msg
->elements
[i
].values
[j
].length
= req
->attributes
[i
].values
[j
].length
;
1243 msg
->elements
[i
].values
[j
].data
= req
->attributes
[i
].values
[j
].data
;
1249 add_reply
= ldapsrv_init_reply(call
, LDAP_TAG_AddResponse
);
1250 NT_STATUS_HAVE_NO_MEMORY(add_reply
);
1252 if (result
== LDAP_SUCCESS
) {
1253 res
= talloc_zero(local_ctx
, struct ldb_result
);
1254 NT_STATUS_HAVE_NO_MEMORY(res
);
1255 ldb_ret
= ldapsrv_add_with_controls(call
, msg
, call
->request
->controls
, res
);
1256 result
= map_ldb_error(local_ctx
, ldb_ret
, ldb_errstring(samdb
),
1260 add_result
= &add_reply
->msg
->r
.AddResponse
;
1261 add_result
->dn
= NULL
;
1262 if ((res
!= NULL
) && (res
->refs
!= NULL
)) {
1263 add_result
->resultcode
= map_ldb_error(local_ctx
,
1264 LDB_ERR_REFERRAL
, NULL
,
1266 add_result
->errormessage
= (errstr
?talloc_strdup(add_reply
,errstr
):NULL
);
1267 add_result
->referral
= talloc_strdup(call
, *res
->refs
);
1269 add_result
->resultcode
= result
;
1270 add_result
->errormessage
= (errstr
?talloc_strdup(add_reply
,errstr
):NULL
);
1271 add_result
->referral
= NULL
;
1273 talloc_free(local_ctx
);
1275 return ldapsrv_queue_reply(call
, add_reply
);
1279 static NTSTATUS
ldapsrv_DelRequest(struct ldapsrv_call
*call
)
1281 struct ldap_DelRequest
*req
= &call
->request
->r
.DelRequest
;
1282 struct ldap_Result
*del_result
;
1283 struct ldapsrv_reply
*del_reply
;
1284 TALLOC_CTX
*local_ctx
;
1285 struct ldb_context
*samdb
= call
->conn
->ldb
;
1287 const char *errstr
= NULL
;
1288 int result
= LDAP_SUCCESS
;
1290 struct ldb_result
*res
= NULL
;
1292 DBG_DEBUG("dn: %s\n", req
->dn
);
1294 local_ctx
= talloc_named(call
, 0, "DelRequest local memory context");
1295 NT_STATUS_HAVE_NO_MEMORY(local_ctx
);
1297 dn
= ldb_dn_new(local_ctx
, samdb
, req
->dn
);
1298 NT_STATUS_HAVE_NO_MEMORY(dn
);
1300 DBG_DEBUG("dn: [%s]\n", req
->dn
);
1302 del_reply
= ldapsrv_init_reply(call
, LDAP_TAG_DelResponse
);
1303 NT_STATUS_HAVE_NO_MEMORY(del_reply
);
1305 if (result
== LDAP_SUCCESS
) {
1306 res
= talloc_zero(local_ctx
, struct ldb_result
);
1307 NT_STATUS_HAVE_NO_MEMORY(res
);
1308 ldb_ret
= ldapsrv_del_with_controls(call
, dn
, call
->request
->controls
, res
);
1309 result
= map_ldb_error(local_ctx
, ldb_ret
, ldb_errstring(samdb
),
1313 del_result
= &del_reply
->msg
->r
.DelResponse
;
1314 del_result
->dn
= NULL
;
1315 if ((res
!= NULL
) && (res
->refs
!= NULL
)) {
1316 del_result
->resultcode
= map_ldb_error(local_ctx
,
1317 LDB_ERR_REFERRAL
, NULL
,
1319 del_result
->errormessage
= (errstr
?talloc_strdup(del_reply
,errstr
):NULL
);
1320 del_result
->referral
= talloc_strdup(call
, *res
->refs
);
1322 del_result
->resultcode
= result
;
1323 del_result
->errormessage
= (errstr
?talloc_strdup(del_reply
,errstr
):NULL
);
1324 del_result
->referral
= NULL
;
1327 talloc_free(local_ctx
);
1329 return ldapsrv_queue_reply(call
, del_reply
);
1332 static NTSTATUS
ldapsrv_ModifyDNRequest(struct ldapsrv_call
*call
)
1334 struct ldap_ModifyDNRequest
*req
= &call
->request
->r
.ModifyDNRequest
;
1335 struct ldap_Result
*modifydn
;
1336 struct ldapsrv_reply
*modifydn_r
;
1337 TALLOC_CTX
*local_ctx
;
1338 struct ldb_context
*samdb
= call
->conn
->ldb
;
1339 struct ldb_dn
*olddn
, *newdn
=NULL
, *newrdn
;
1340 struct ldb_dn
*parentdn
= NULL
;
1341 const char *errstr
= NULL
;
1342 int result
= LDAP_SUCCESS
;
1344 struct ldb_result
*res
= NULL
;
1346 DBG_DEBUG("dn: %s newrdn: %s\n",
1347 req
->dn
, req
->newrdn
);
1349 local_ctx
= talloc_named(call
, 0, "ModifyDNRequest local memory context");
1350 NT_STATUS_HAVE_NO_MEMORY(local_ctx
);
1352 olddn
= ldb_dn_new(local_ctx
, samdb
, req
->dn
);
1353 NT_STATUS_HAVE_NO_MEMORY(olddn
);
1355 newrdn
= ldb_dn_new(local_ctx
, samdb
, req
->newrdn
);
1356 NT_STATUS_HAVE_NO_MEMORY(newrdn
);
1358 DBG_DEBUG("olddn: [%s] newrdn: [%s]\n",
1359 req
->dn
, req
->newrdn
);
1361 if (ldb_dn_get_comp_num(newrdn
) == 0) {
1362 result
= LDAP_PROTOCOL_ERROR
;
1363 map_ldb_error(local_ctx
, LDB_ERR_PROTOCOL_ERROR
, NULL
,
1368 if (ldb_dn_get_comp_num(newrdn
) > 1) {
1369 result
= LDAP_NAMING_VIOLATION
;
1370 map_ldb_error(local_ctx
, LDB_ERR_NAMING_VIOLATION
, NULL
,
1375 /* we can't handle the rename if we should not remove the old dn */
1376 if (!req
->deleteolddn
) {
1377 result
= LDAP_UNWILLING_TO_PERFORM
;
1378 map_ldb_error(local_ctx
, LDB_ERR_UNWILLING_TO_PERFORM
, NULL
,
1380 errstr
= talloc_asprintf(local_ctx
,
1381 "%s. Old RDN must be deleted", errstr
);
1385 if (req
->newsuperior
) {
1386 DBG_DEBUG("newsuperior: [%s]\n", req
->newsuperior
);
1387 parentdn
= ldb_dn_new(local_ctx
, samdb
, req
->newsuperior
);
1391 parentdn
= ldb_dn_get_parent(local_ctx
, olddn
);
1394 result
= LDAP_NO_SUCH_OBJECT
;
1395 map_ldb_error(local_ctx
, LDB_ERR_NO_SUCH_OBJECT
, NULL
, &errstr
);
1399 if ( ! ldb_dn_add_child(parentdn
, newrdn
)) {
1400 result
= LDAP_OTHER
;
1401 map_ldb_error(local_ctx
, LDB_ERR_OTHER
, NULL
, &errstr
);
1407 modifydn_r
= ldapsrv_init_reply(call
, LDAP_TAG_ModifyDNResponse
);
1408 NT_STATUS_HAVE_NO_MEMORY(modifydn_r
);
1410 if (result
== LDAP_SUCCESS
) {
1411 res
= talloc_zero(local_ctx
, struct ldb_result
);
1412 NT_STATUS_HAVE_NO_MEMORY(res
);
1413 ldb_ret
= ldapsrv_rename_with_controls(call
, olddn
, newdn
, call
->request
->controls
, res
);
1414 result
= map_ldb_error(local_ctx
, ldb_ret
, ldb_errstring(samdb
),
1418 modifydn
= &modifydn_r
->msg
->r
.ModifyDNResponse
;
1419 modifydn
->dn
= NULL
;
1420 if ((res
!= NULL
) && (res
->refs
!= NULL
)) {
1421 modifydn
->resultcode
= map_ldb_error(local_ctx
,
1422 LDB_ERR_REFERRAL
, NULL
,
1424 modifydn
->errormessage
= (errstr
?talloc_strdup(modifydn_r
,errstr
):NULL
);
1425 modifydn
->referral
= talloc_strdup(call
, *res
->refs
);
1427 modifydn
->resultcode
= result
;
1428 modifydn
->errormessage
= (errstr
?talloc_strdup(modifydn_r
,errstr
):NULL
);
1429 modifydn
->referral
= NULL
;
1432 talloc_free(local_ctx
);
1434 return ldapsrv_queue_reply(call
, modifydn_r
);
1437 static NTSTATUS
ldapsrv_CompareRequest(struct ldapsrv_call
*call
)
1439 struct ldap_CompareRequest
*req
= &call
->request
->r
.CompareRequest
;
1440 struct ldap_Result
*compare
;
1441 struct ldapsrv_reply
*compare_r
;
1442 TALLOC_CTX
*local_ctx
;
1443 struct ldb_context
*samdb
= call
->conn
->ldb
;
1444 struct ldb_result
*res
= NULL
;
1446 const char *attrs
[1];
1447 const char *errstr
= NULL
;
1448 const char *filter
= NULL
;
1449 int result
= LDAP_SUCCESS
;
1452 DBG_DEBUG("dn: %s\n", req
->dn
);
1454 local_ctx
= talloc_named(call
, 0, "CompareRequest local_memory_context");
1455 NT_STATUS_HAVE_NO_MEMORY(local_ctx
);
1457 dn
= ldb_dn_new(local_ctx
, samdb
, req
->dn
);
1458 NT_STATUS_HAVE_NO_MEMORY(dn
);
1460 DBG_DEBUG("dn: [%s]\n", req
->dn
);
1461 filter
= talloc_asprintf(local_ctx
, "(%s=%*s)", req
->attribute
,
1462 (int)req
->value
.length
, req
->value
.data
);
1463 NT_STATUS_HAVE_NO_MEMORY(filter
);
1465 DBG_DEBUG("attribute: [%s]\n", filter
);
1469 compare_r
= ldapsrv_init_reply(call
, LDAP_TAG_CompareResponse
);
1470 NT_STATUS_HAVE_NO_MEMORY(compare_r
);
1472 if (result
== LDAP_SUCCESS
) {
1473 ldb_ret
= ldb_search(samdb
, local_ctx
, &res
,
1474 dn
, LDB_SCOPE_BASE
, attrs
, "%s", filter
);
1475 if (ldb_ret
!= LDB_SUCCESS
) {
1476 result
= map_ldb_error(local_ctx
, ldb_ret
,
1477 ldb_errstring(samdb
), &errstr
);
1478 DBG_DEBUG("error: %s\n", errstr
);
1479 } else if (res
->count
== 0) {
1480 DBG_DEBUG("didn't match\n");
1481 result
= LDAP_COMPARE_FALSE
;
1483 } else if (res
->count
== 1) {
1484 DBG_DEBUG("matched\n");
1485 result
= LDAP_COMPARE_TRUE
;
1487 } else if (res
->count
> 1) {
1488 result
= LDAP_OTHER
;
1489 map_ldb_error(local_ctx
, LDB_ERR_OTHER
, NULL
, &errstr
);
1490 errstr
= talloc_asprintf(local_ctx
,
1491 "%s. Too many objects match!", errstr
);
1492 DBG_DEBUG("%u results: %s\n", res
->count
, errstr
);
1496 compare
= &compare_r
->msg
->r
.CompareResponse
;
1498 compare
->resultcode
= result
;
1499 compare
->errormessage
= (errstr
?talloc_strdup(compare_r
,errstr
):NULL
);
1500 compare
->referral
= NULL
;
1502 talloc_free(local_ctx
);
1504 return ldapsrv_queue_reply(call
, compare_r
);
1507 static NTSTATUS
ldapsrv_AbandonRequest(struct ldapsrv_call
*call
)
1509 struct ldap_AbandonRequest
*req
= &call
->request
->r
.AbandonRequest
;
1510 struct ldapsrv_call
*c
= NULL
;
1511 struct ldapsrv_call
*n
= NULL
;
1513 DBG_DEBUG("abandoned\n");
1515 for (c
= call
->conn
->pending_calls
; c
!= NULL
; c
= n
) {
1518 if (c
->request
->messageid
!= req
->messageid
) {
1522 DLIST_REMOVE(call
->conn
->pending_calls
, c
);
1526 return NT_STATUS_OK
;
1529 static NTSTATUS
ldapsrv_expired(struct ldapsrv_call
*call
)
1531 struct ldapsrv_reply
*reply
= NULL
;
1532 struct ldap_ExtendedResponse
*r
= NULL
;
1534 DBG_DEBUG("Sending connection expired message\n");
1536 reply
= ldapsrv_init_reply(call
, LDAP_TAG_ExtendedResponse
);
1537 if (reply
== NULL
) {
1538 return NT_STATUS_NO_MEMORY
;
1542 * According to RFC4511 section 4.4.1 this has a msgid of 0
1544 reply
->msg
->messageid
= 0;
1546 r
= &reply
->msg
->r
.ExtendedResponse
;
1547 r
->response
.resultcode
= LDB_ERR_UNAVAILABLE
;
1548 r
->response
.errormessage
= "The server has timed out this connection";
1549 r
->oid
= "1.3.6.1.4.1.1466.20036"; /* see rfc4511 section 4.4.1 */
1551 ldapsrv_queue_reply(call
, reply
);
1552 return NT_STATUS_OK
;
1555 NTSTATUS
ldapsrv_do_call(struct ldapsrv_call
*call
)
1558 struct ldap_message
*msg
= call
->request
;
1559 struct ldapsrv_connection
*conn
= call
->conn
;
1563 expired
= timeval_expired(&conn
->limits
.expire_time
);
1565 status
= ldapsrv_expired(call
);
1566 if (!NT_STATUS_IS_OK(status
)) {
1569 return NT_STATUS_NETWORK_SESSION_EXPIRED
;
1572 /* Check for undecoded critical extensions */
1573 for (i
=0; msg
->controls
&& msg
->controls
[i
]; i
++) {
1574 if (!msg
->controls_decoded
[i
] &&
1575 msg
->controls
[i
]->critical
) {
1576 DBG_NOTICE("Critical extension %s is not known to this server\n",
1577 msg
->controls
[i
]->oid
);
1578 return ldapsrv_unwilling(call
, LDAP_UNAVAILABLE_CRITICAL_EXTENSION
);
1582 if (call
->conn
->authz_logged
== false) {
1586 * We do not want to log anonymous access if the query
1587 * is just for the rootDSE, or it is a startTLS or a
1590 * A rootDSE search could also be done over
1591 * CLDAP anonymously for example, so these don't
1593 * Essentially we want to know about
1594 * access beyond that normally done prior to a
1598 switch(call
->request
->type
) {
1599 case LDAP_TAG_BindRequest
:
1600 case LDAP_TAG_UnbindRequest
:
1601 case LDAP_TAG_AbandonRequest
:
1604 case LDAP_TAG_ExtendedResponse
: {
1605 struct ldap_ExtendedRequest
*req
= &call
->request
->r
.ExtendedRequest
;
1606 if (strcmp(req
->oid
, LDB_EXTENDED_START_TLS_OID
) == 0) {
1611 case LDAP_TAG_SearchRequest
: {
1612 struct ldap_SearchRequest
*req
= &call
->request
->r
.SearchRequest
;
1613 if (req
->scope
== LDAP_SEARCH_SCOPE_BASE
) {
1614 if (req
->basedn
[0] == '\0') {
1625 const char *transport_protection
= AUTHZ_TRANSPORT_PROTECTION_NONE
;
1626 if (call
->conn
->sockets
.active
== call
->conn
->sockets
.tls
) {
1627 transport_protection
= AUTHZ_TRANSPORT_PROTECTION_TLS
;
1630 log_successful_authz_event(call
->conn
->connection
->msg_ctx
,
1631 call
->conn
->connection
->lp_ctx
,
1632 call
->conn
->connection
->remote_address
,
1633 call
->conn
->connection
->local_address
,
1636 transport_protection
,
1637 call
->conn
->session_info
,
1638 NULL
/* client_audit_info */,
1639 NULL
/* server_audit_info */);
1641 call
->conn
->authz_logged
= true;
1645 switch(call
->request
->type
) {
1646 case LDAP_TAG_BindRequest
:
1647 return ldapsrv_BindRequest(call
);
1648 case LDAP_TAG_UnbindRequest
:
1649 return ldapsrv_UnbindRequest(call
);
1650 case LDAP_TAG_SearchRequest
:
1651 return ldapsrv_SearchRequest(call
);
1652 case LDAP_TAG_ModifyRequest
:
1653 status
= ldapsrv_ModifyRequest(call
);
1655 case LDAP_TAG_AddRequest
:
1656 status
= ldapsrv_AddRequest(call
);
1658 case LDAP_TAG_DelRequest
:
1659 status
= ldapsrv_DelRequest(call
);
1661 case LDAP_TAG_ModifyDNRequest
:
1662 status
= ldapsrv_ModifyDNRequest(call
);
1664 case LDAP_TAG_CompareRequest
:
1665 return ldapsrv_CompareRequest(call
);
1666 case LDAP_TAG_AbandonRequest
:
1667 return ldapsrv_AbandonRequest(call
);
1668 case LDAP_TAG_ExtendedRequest
:
1669 status
= ldapsrv_ExtendedRequest(call
);
1672 return ldapsrv_unwilling(call
, LDAP_PROTOCOL_ERROR
);
1675 if (NT_STATUS_IS_OK(status
)) {
1676 ldapsrv_notification_retry_setup(call
->conn
->service
, true);