2 ldb database library - ildap backend
4 Copyright (C) Andrew Tridgell 2005
5 Copyright (C) Simo Sorce 2008
7 ** NOTE! The following LGPL license applies to the ldb
8 ** library. This does NOT imply that all of Samba is released
11 This library is free software; you can redistribute it and/or
12 modify it under the terms of the GNU Lesser General Public
13 License as published by the Free Software Foundation; either
14 version 3 of the License, or (at your option) any later version.
16 This library is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 Lesser General Public License for more details.
21 You should have received a copy of the GNU Lesser General Public
22 License along with this library; if not, see <http://www.gnu.org/licenses/>.
28 * Component: ldb ildap backend
30 * Description: This is a ldb backend for the internal ldap
31 * client library in Samba4. By using this backend we are
32 * independent of a system ldap library
34 * Author: Andrew Tridgell
38 * - description: make the module use asyncronous calls
45 #include "ldb_module.h"
48 #include "libcli/ldap/ldap.h"
49 #include "libcli/ldap/ldap_client.h"
50 #include "auth/auth.h"
51 #include "auth/credentials/credentials.h"
54 struct ldap_connection
*ldap
;
55 struct tevent_context
*event_ctx
;
59 struct ldb_module
*module
;
60 struct ldb_request
*req
;
62 struct ildb_private
*ildb
;
63 struct ldap_request
*ireq
;
67 struct ildb_destructor_ctx
*dc
;
70 static void ildb_request_done(struct ildb_context
*ctx
,
71 struct ldb_control
**ctrls
, int error
)
73 struct ldb_context
*ldb
;
74 struct ldb_reply
*ares
;
76 ldb
= ldb_module_get_ctx(ctx
->module
);
80 if (ctx
->req
== NULL
) {
81 /* if the req has been freed already just return */
85 ares
= talloc_zero(ctx
->req
, struct ldb_reply
);
88 ctx
->req
->callback(ctx
->req
, NULL
);
91 ares
->type
= LDB_REPLY_DONE
;
92 ares
->controls
= talloc_steal(ares
, ctrls
);
95 ctx
->req
->callback(ctx
->req
, ares
);
98 static void ildb_auto_done_callback(struct tevent_context
*ev
,
99 struct tevent_timer
*te
,
103 struct ildb_context
*ac
;
105 ac
= talloc_get_type(private_data
, struct ildb_context
);
106 ildb_request_done(ac
, NULL
, LDB_SUCCESS
);
110 convert a ldb_message structure to a list of ldap_mod structures
111 ready for ildap_add() or ildap_modify()
113 static struct ldap_mod
**ildb_msg_to_mods(void *mem_ctx
, int *num_mods
,
114 const struct ldb_message
*msg
,
117 struct ldap_mod
**mods
;
121 /* allocate maximum number of elements needed */
122 mods
= talloc_array(mem_ctx
, struct ldap_mod
*, msg
->num_elements
+1);
129 for (i
= 0; i
< msg
->num_elements
; i
++) {
130 const struct ldb_message_element
*el
= &msg
->elements
[i
];
132 mods
[n
] = talloc(mods
, struct ldap_mod
);
138 mods
[n
]->attrib
= *el
;
140 switch (el
->flags
& LDB_FLAG_MOD_MASK
) {
141 case LDB_FLAG_MOD_ADD
:
142 mods
[n
]->type
= LDAP_MODIFY_ADD
;
144 case LDB_FLAG_MOD_DELETE
:
145 mods
[n
]->type
= LDAP_MODIFY_DELETE
;
147 case LDB_FLAG_MOD_REPLACE
:
148 mods
[n
]->type
= LDAP_MODIFY_REPLACE
;
165 map an ildap NTSTATUS to a ldb error code
167 static int ildb_map_error(struct ldb_module
*module
, NTSTATUS status
)
169 struct ildb_private
*ildb
;
170 struct ldb_context
*ldb
;
172 ildb
= talloc_get_type(ldb_module_get_private(module
), struct ildb_private
);
173 ldb
= ldb_module_get_ctx(module
);
175 TALLOC_CTX
*mem_ctx
= talloc_new(ildb
);
176 if (NT_STATUS_IS_OK(status
)) {
181 return LDB_ERR_OPERATIONS_ERROR
;
183 ldb_set_errstring(ldb
,
184 ldap_errstr(ildb
->ldap
, mem_ctx
, status
));
185 talloc_free(mem_ctx
);
186 if (NT_STATUS_IS_LDAP(status
)) {
187 return NT_STATUS_LDAP_CODE(status
);
189 return LDB_ERR_OPERATIONS_ERROR
;
192 static void ildb_request_timeout(struct tevent_context
*ev
, struct tevent_timer
*te
,
193 struct timeval t
, void *private_data
)
195 struct ildb_context
*ac
= talloc_get_type(private_data
, struct ildb_context
);
197 if (ac
->ireq
->state
== LDAP_REQUEST_PENDING
) {
198 DLIST_REMOVE(ac
->ireq
->conn
->pending
, ac
->ireq
);
201 ildb_request_done(ac
, NULL
, LDB_ERR_TIME_LIMIT_EXCEEDED
);
204 static void ildb_callback(struct ldap_request
*req
)
206 struct ldb_context
*ldb
;
207 struct ildb_context
*ac
;
209 struct ldap_SearchResEntry
*search
;
210 struct ldap_message
*msg
;
211 struct ldb_control
**controls
;
212 struct ldb_message
*ldbmsg
;
214 bool callback_failed
;
219 ac
= talloc_get_type(req
->async
.private_data
, struct ildb_context
);
220 ldb
= ldb_module_get_ctx(ac
->module
);
221 callback_failed
= false;
222 request_done
= false;
225 if (!NT_STATUS_IS_OK(req
->status
)) {
226 ret
= ildb_map_error(ac
->module
, req
->status
);
227 ildb_request_done(ac
, NULL
, ret
);
231 if (req
->num_replies
< 1) {
232 ret
= LDB_ERR_OPERATIONS_ERROR
;
233 ildb_request_done(ac
, NULL
, ret
);
239 case LDAP_TAG_ModifyRequest
:
240 if (req
->replies
[0]->type
!= LDAP_TAG_ModifyResponse
) {
241 ret
= LDB_ERR_PROTOCOL_ERROR
;
244 status
= ldap_check_response(ac
->ireq
->conn
, &req
->replies
[0]->r
.GeneralResult
);
245 ret
= ildb_map_error(ac
->module
, status
);
249 case LDAP_TAG_AddRequest
:
250 if (req
->replies
[0]->type
!= LDAP_TAG_AddResponse
) {
251 ret
= LDB_ERR_PROTOCOL_ERROR
;
254 status
= ldap_check_response(ac
->ireq
->conn
, &req
->replies
[0]->r
.GeneralResult
);
255 ret
= ildb_map_error(ac
->module
, status
);
259 case LDAP_TAG_DelRequest
:
260 if (req
->replies
[0]->type
!= LDAP_TAG_DelResponse
) {
261 ret
= LDB_ERR_PROTOCOL_ERROR
;
264 status
= ldap_check_response(ac
->ireq
->conn
, &req
->replies
[0]->r
.GeneralResult
);
265 ret
= ildb_map_error(ac
->module
, status
);
269 case LDAP_TAG_ModifyDNRequest
:
270 if (req
->replies
[0]->type
!= LDAP_TAG_ModifyDNResponse
) {
271 ret
= LDB_ERR_PROTOCOL_ERROR
;
274 status
= ldap_check_response(ac
->ireq
->conn
, &req
->replies
[0]->r
.GeneralResult
);
275 ret
= ildb_map_error(ac
->module
, status
);
279 case LDAP_TAG_SearchRequest
:
280 /* loop over all messages */
281 for (i
= 0; i
< req
->num_replies
; i
++) {
283 msg
= req
->replies
[i
];
286 case LDAP_TAG_SearchResultDone
:
288 status
= ldap_check_response(ac
->ireq
->conn
, &msg
->r
.GeneralResult
);
289 if (!NT_STATUS_IS_OK(status
)) {
290 ret
= ildb_map_error(ac
->module
, status
);
294 controls
= talloc_steal(ac
, msg
->controls
);
295 if (msg
->r
.SearchResultDone
.resultcode
) {
296 if (msg
->r
.SearchResultDone
.errormessage
) {
297 ldb_set_errstring(ldb
, msg
->r
.SearchResultDone
.errormessage
);
301 ret
= msg
->r
.SearchResultDone
.resultcode
;
305 case LDAP_TAG_SearchResultEntry
:
307 ldbmsg
= ldb_msg_new(ac
);
309 ret
= LDB_ERR_OPERATIONS_ERROR
;
313 search
= &(msg
->r
.SearchResultEntry
);
315 ldbmsg
->dn
= ldb_dn_new(ldbmsg
, ldb
, search
->dn
);
316 if ( ! ldb_dn_validate(ldbmsg
->dn
)) {
317 ret
= LDB_ERR_OPERATIONS_ERROR
;
320 ldbmsg
->num_elements
= search
->num_attributes
;
321 ldbmsg
->elements
= talloc_move(ldbmsg
, &search
->attributes
);
323 controls
= talloc_steal(ac
, msg
->controls
);
325 ret
= ldb_module_send_entry(ac
->req
, ldbmsg
, controls
);
326 if (ret
!= LDB_SUCCESS
) {
327 callback_failed
= true;
331 case LDAP_TAG_SearchResultReference
:
333 referral
= talloc_strdup(ac
, msg
->r
.SearchResultReference
.referral
);
335 ret
= ldb_module_send_referral(ac
->req
, referral
);
336 if (ret
!= LDB_SUCCESS
) {
337 callback_failed
= true;
342 /* TAG not handled, fail ! */
343 ret
= LDB_ERR_PROTOCOL_ERROR
;
347 if (ret
!= LDB_SUCCESS
) {
352 talloc_free(req
->replies
);
354 req
->num_replies
= 0;
359 ret
= LDB_ERR_PROTOCOL_ERROR
;
363 if (ret
!= LDB_SUCCESS
) {
365 /* if the callback failed the caller will have freed the
366 * request. Just return and don't try to use it */
367 if ( ! callback_failed
) {
373 ildb_request_done(ac
, controls
, ret
);
378 static int ildb_request_send(struct ildb_context
*ac
, struct ldap_message
*msg
)
380 struct ldb_context
*ldb
;
381 struct ldap_request
*req
;
384 return LDB_ERR_OPERATIONS_ERROR
;
387 ldb
= ldb_module_get_ctx(ac
->module
);
389 req
= ldap_request_send(ac
->ildb
->ldap
, msg
);
391 ldb_set_errstring(ldb
, "async send request failed");
392 return LDB_ERR_OPERATIONS_ERROR
;
394 ac
->ireq
= talloc_steal(ac
, req
);
396 if (!ac
->ireq
->conn
) {
397 ldb_set_errstring(ldb
, "connection to remote LDAP server dropped?");
398 return LDB_ERR_OPERATIONS_ERROR
;
401 talloc_free(req
->time_event
);
402 req
->time_event
= NULL
;
403 if (ac
->req
->timeout
) {
404 req
->time_event
= tevent_add_timer(ac
->ildb
->event_ctx
, ac
,
405 timeval_current_ofs(ac
->req
->timeout
, 0),
406 ildb_request_timeout
, ac
);
409 req
->async
.fn
= ildb_callback
;
410 req
->async
.private_data
= ac
;
416 search for matching records using an asynchronous function
418 static int ildb_search(struct ildb_context
*ac
)
420 struct ldb_context
*ldb
;
421 struct ldb_request
*req
= ac
->req
;
422 struct ldap_message
*msg
;
425 ldb
= ldb_module_get_ctx(ac
->module
);
427 if (!req
->callback
|| !req
->context
) {
428 ldb_set_errstring(ldb
, "Async interface called with NULL callback function or NULL context");
429 return LDB_ERR_OPERATIONS_ERROR
;
432 if (req
->op
.search
.tree
== NULL
) {
433 ldb_set_errstring(ldb
, "Invalid expression parse tree");
434 return LDB_ERR_OPERATIONS_ERROR
;
437 msg
= new_ldap_message(req
);
439 ldb_set_errstring(ldb
, "Out of Memory");
440 return LDB_ERR_OPERATIONS_ERROR
;
443 msg
->type
= LDAP_TAG_SearchRequest
;
445 if (req
->op
.search
.base
== NULL
) {
446 msg
->r
.SearchRequest
.basedn
= talloc_strdup(msg
, "");
448 msg
->r
.SearchRequest
.basedn
= ldb_dn_get_extended_linearized(msg
, req
->op
.search
.base
, 0);
450 if (msg
->r
.SearchRequest
.basedn
== NULL
) {
451 ldb_set_errstring(ldb
, "Unable to determine baseDN");
453 return LDB_ERR_OPERATIONS_ERROR
;
456 if (req
->op
.search
.scope
== LDB_SCOPE_DEFAULT
) {
457 msg
->r
.SearchRequest
.scope
= LDB_SCOPE_SUBTREE
;
459 msg
->r
.SearchRequest
.scope
= req
->op
.search
.scope
;
462 msg
->r
.SearchRequest
.deref
= LDAP_DEREFERENCE_NEVER
;
463 msg
->r
.SearchRequest
.timelimit
= 0;
464 msg
->r
.SearchRequest
.sizelimit
= 0;
465 msg
->r
.SearchRequest
.attributesonly
= 0;
466 msg
->r
.SearchRequest
.tree
= discard_const(req
->op
.search
.tree
);
468 for (n
= 0; req
->op
.search
.attrs
&& req
->op
.search
.attrs
[n
]; n
++) /* noop */ ;
469 msg
->r
.SearchRequest
.num_attributes
= n
;
470 msg
->r
.SearchRequest
.attributes
= discard_const(req
->op
.search
.attrs
);
471 msg
->controls
= req
->controls
;
473 return ildb_request_send(ac
, msg
);
479 static int ildb_add(struct ildb_context
*ac
)
481 struct ldb_request
*req
= ac
->req
;
482 struct ldap_message
*msg
;
483 struct ldap_mod
**mods
;
486 msg
= new_ldap_message(req
);
488 return LDB_ERR_OPERATIONS_ERROR
;
491 msg
->type
= LDAP_TAG_AddRequest
;
493 msg
->r
.AddRequest
.dn
= ldb_dn_get_extended_linearized(msg
, req
->op
.add
.message
->dn
, 0);
494 if (msg
->r
.AddRequest
.dn
== NULL
) {
496 return LDB_ERR_INVALID_DN_SYNTAX
;
499 mods
= ildb_msg_to_mods(msg
, &n
, req
->op
.add
.message
, 0);
502 return LDB_ERR_OPERATIONS_ERROR
;
505 msg
->r
.AddRequest
.num_attributes
= n
;
506 msg
->r
.AddRequest
.attributes
= talloc_array(msg
, struct ldb_message_element
, n
);
507 if (msg
->r
.AddRequest
.attributes
== NULL
) {
509 return LDB_ERR_OPERATIONS_ERROR
;
512 for (i
= 0; i
< n
; i
++) {
513 msg
->r
.AddRequest
.attributes
[i
] = mods
[i
]->attrib
;
516 return ildb_request_send(ac
, msg
);
522 static int ildb_modify(struct ildb_context
*ac
)
524 struct ldb_request
*req
= ac
->req
;
525 struct ldap_message
*msg
;
526 struct ldap_mod
**mods
;
529 msg
= new_ldap_message(req
);
531 return LDB_ERR_OPERATIONS_ERROR
;
534 msg
->type
= LDAP_TAG_ModifyRequest
;
536 msg
->r
.ModifyRequest
.dn
= ldb_dn_get_extended_linearized(msg
, req
->op
.mod
.message
->dn
, 0);
537 if (msg
->r
.ModifyRequest
.dn
== NULL
) {
539 return LDB_ERR_INVALID_DN_SYNTAX
;
542 mods
= ildb_msg_to_mods(msg
, &n
, req
->op
.mod
.message
, 1);
545 return LDB_ERR_OPERATIONS_ERROR
;
548 msg
->r
.ModifyRequest
.num_mods
= n
;
549 msg
->r
.ModifyRequest
.mods
= talloc_array(msg
, struct ldap_mod
, n
);
550 if (msg
->r
.ModifyRequest
.mods
== NULL
) {
552 return LDB_ERR_OPERATIONS_ERROR
;
555 for (i
= 0; i
< n
; i
++) {
556 msg
->r
.ModifyRequest
.mods
[i
] = *mods
[i
];
559 return ildb_request_send(ac
, msg
);
565 static int ildb_delete(struct ildb_context
*ac
)
567 struct ldb_request
*req
= ac
->req
;
568 struct ldap_message
*msg
;
570 msg
= new_ldap_message(req
);
572 return LDB_ERR_OPERATIONS_ERROR
;
575 msg
->type
= LDAP_TAG_DelRequest
;
577 msg
->r
.DelRequest
.dn
= ldb_dn_get_extended_linearized(msg
, req
->op
.del
.dn
, 0);
578 if (msg
->r
.DelRequest
.dn
== NULL
) {
580 return LDB_ERR_INVALID_DN_SYNTAX
;
583 return ildb_request_send(ac
, msg
);
589 static int ildb_rename(struct ildb_context
*ac
)
591 struct ldb_request
*req
= ac
->req
;
592 struct ldap_message
*msg
;
594 msg
= new_ldap_message(req
);
596 return LDB_ERR_OPERATIONS_ERROR
;
599 msg
->type
= LDAP_TAG_ModifyDNRequest
;
600 msg
->r
.ModifyDNRequest
.dn
= ldb_dn_get_extended_linearized(msg
, req
->op
.rename
.olddn
, 0);
601 if (msg
->r
.ModifyDNRequest
.dn
== NULL
) {
603 return LDB_ERR_INVALID_DN_SYNTAX
;
606 msg
->r
.ModifyDNRequest
.newrdn
=
607 talloc_asprintf(msg
, "%s=%s",
608 ldb_dn_get_rdn_name(req
->op
.rename
.newdn
),
609 ldb_dn_escape_value(msg
, *ldb_dn_get_rdn_val(req
->op
.rename
.newdn
)));
610 if (msg
->r
.ModifyDNRequest
.newrdn
== NULL
) {
612 return LDB_ERR_OPERATIONS_ERROR
;
615 msg
->r
.ModifyDNRequest
.newsuperior
=
616 ldb_dn_alloc_linearized(msg
, ldb_dn_get_parent(msg
, req
->op
.rename
.newdn
));
617 if (msg
->r
.ModifyDNRequest
.newsuperior
== NULL
) {
619 return LDB_ERR_INVALID_DN_SYNTAX
;
622 msg
->r
.ModifyDNRequest
.deleteolddn
= true;
624 return ildb_request_send(ac
, msg
);
627 static int ildb_start_trans(struct ldb_module
*module
)
629 /* TODO implement a local locking mechanism here */
634 static int ildb_end_trans(struct ldb_module
*module
)
636 /* TODO implement a local transaction mechanism here */
641 static int ildb_del_trans(struct ldb_module
*module
)
643 /* TODO implement a local locking mechanism here */
648 static bool ildb_dn_is_special(struct ldb_request
*req
)
650 struct ldb_dn
*dn
= NULL
;
652 switch (req
->operation
) {
654 dn
= req
->op
.add
.message
->dn
;
657 dn
= req
->op
.mod
.message
->dn
;
663 dn
= req
->op
.rename
.olddn
;
669 if (dn
&& ldb_dn_is_special(dn
)) {
675 static int ildb_handle_request(struct ldb_module
*module
, struct ldb_request
*req
)
677 struct ldb_context
*ldb
;
678 struct ildb_private
*ildb
;
679 struct ildb_context
*ac
;
680 struct tevent_timer
*te
;
683 ildb
= talloc_get_type(ldb_module_get_private(module
), struct ildb_private
);
684 ldb
= ldb_module_get_ctx(module
);
686 if (req
->starttime
== 0 || req
->timeout
== 0) {
687 ldb_set_errstring(ldb
, "Invalid timeout settings");
688 return LDB_ERR_TIME_LIMIT_EXCEEDED
;
691 ac
= talloc_zero(req
, struct ildb_context
);
693 ldb_set_errstring(ldb
, "Out of Memory");
694 return LDB_ERR_OPERATIONS_ERROR
;
701 if (ildb_dn_is_special(req
)) {
703 te
= tevent_add_timer(ac
->ildb
->event_ctx
,
705 ildb_auto_done_callback
, ac
);
707 return LDB_ERR_OPERATIONS_ERROR
;
713 switch (ac
->req
->operation
) {
715 ret
= ildb_search(ac
);
721 ret
= ildb_modify(ac
);
724 ret
= ildb_delete(ac
);
727 ret
= ildb_rename(ac
);
730 /* no other op supported */
731 ret
= LDB_ERR_OPERATIONS_ERROR
;
738 static const struct ldb_module_ops ildb_ops
= {
740 .search
= ildb_handle_request
,
741 .add
= ildb_handle_request
,
742 .modify
= ildb_handle_request
,
743 .del
= ildb_handle_request
,
744 .rename
= ildb_handle_request
,
745 /* .request = ildb_handle_request, */
746 .start_transaction
= ildb_start_trans
,
747 .end_transaction
= ildb_end_trans
,
748 .del_transaction
= ildb_del_trans
,
752 connect to the database
754 static int ildb_connect(struct ldb_context
*ldb
, const char *url
,
755 unsigned int flags
, const char *options
[],
756 struct ldb_module
**_module
)
758 struct ldb_module
*module
;
759 struct ildb_private
*ildb
;
761 struct cli_credentials
*creds
;
763 module
= ldb_module_new(ldb
, ldb
, "ldb_ildap backend", &ildb_ops
);
764 if (!module
) return -1;
766 ildb
= talloc(module
, struct ildb_private
);
771 ldb_module_set_private(module
, ildb
);
773 ildb
->event_ctx
= ldb_get_event_context(ldb
);
776 ildb
->ldap
= ldap4_new_connection(ildb
, ldb_get_opaque(ldb
, "loadparm"),
783 if (flags
& LDB_FLG_RECONNECT
) {
784 ldap_set_reconn_params(ildb
->ldap
, 10);
787 status
= ldap_connect(ildb
->ldap
, url
);
788 if (!NT_STATUS_IS_OK(status
)) {
789 ldb_debug(ldb
, LDB_DEBUG_ERROR
, "Failed to connect to ldap URL '%s' - %s\n",
790 url
, ldap_errstr(ildb
->ldap
, module
, status
));
794 /* caller can optionally setup credentials using the opaque token 'credentials' */
795 creds
= talloc_get_type(ldb_get_opaque(ldb
, "credentials"), struct cli_credentials
);
797 struct auth_session_info
*session_info
= talloc_get_type(ldb_get_opaque(ldb
, "sessionInfo"), struct auth_session_info
);
799 creds
= session_info
->credentials
;
803 if (creds
!= NULL
&& cli_credentials_authentication_requested(creds
)) {
804 const char *bind_dn
= cli_credentials_get_bind_dn(creds
);
806 const char *password
= cli_credentials_get_password(creds
);
807 status
= ldap_bind_simple(ildb
->ldap
, bind_dn
, password
);
808 if (!NT_STATUS_IS_OK(status
)) {
809 ldb_debug(ldb
, LDB_DEBUG_ERROR
, "Failed to bind - %s\n",
810 ldap_errstr(ildb
->ldap
, module
, status
));
814 status
= ldap_bind_sasl(ildb
->ldap
, creds
, ldb_get_opaque(ldb
, "loadparm"));
815 if (!NT_STATUS_IS_OK(status
)) {
816 ldb_debug(ldb
, LDB_DEBUG_ERROR
, "Failed to bind - %s\n",
817 ldap_errstr(ildb
->ldap
, module
, status
));
831 _PUBLIC_
const struct ldb_backend_ops ldb_ldap_backend_ops
= {
833 .connect_fn
= ildb_connect
836 _PUBLIC_
const struct ldb_backend_ops ldb_ldapi_backend_ops
= {
838 .connect_fn
= ildb_connect
841 _PUBLIC_
const struct ldb_backend_ops ldb_ldaps_backend_ops
= {
843 .connect_fn
= ildb_connect