4 Copyright (C) Andrew Tridgell 2004
5 Copyright (C) Simo Sorce 2006
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 ldap backend
30 * Description: core files for LDAP backend
32 * Author: Andrew Tridgell
36 * - description: make the module use asynchronous calls
42 #include "system/filesys.h"
43 #include "system/time.h"
44 #include "ldb_module.h"
45 #include "ldb_private.h"
47 #define LDAP_DEPRECATED 1
55 struct ldb_module
*module
;
56 struct ldb_request
*req
;
58 struct lldb_private
*lldb
;
60 struct ldb_control
**controls
;
64 static int lldb_ldap_to_ldb(int err
) {
65 /* Ldap errors and ldb errors are defined to the same values */
70 convert a ldb_message structure to a list of LDAPMod structures
71 ready for ldap_add() or ldap_modify()
73 static LDAPMod
**lldb_msg_to_mods(void *mem_ctx
, const struct ldb_message
*msg
, int use_flags
)
79 /* allocate maximum number of elements needed */
80 mods
= talloc_array(mem_ctx
, LDAPMod
*, msg
->num_elements
+1);
87 for (i
=0;i
<msg
->num_elements
;i
++) {
88 const struct ldb_message_element
*el
= &msg
->elements
[i
];
90 mods
[num_mods
] = talloc(mods
, LDAPMod
);
91 if (!mods
[num_mods
]) {
94 mods
[num_mods
+1] = NULL
;
95 mods
[num_mods
]->mod_op
= LDAP_MOD_BVALUES
;
97 switch (el
->flags
& LDB_FLAG_MOD_MASK
) {
98 case LDB_FLAG_MOD_ADD
:
99 mods
[num_mods
]->mod_op
|= LDAP_MOD_ADD
;
101 case LDB_FLAG_MOD_DELETE
:
102 mods
[num_mods
]->mod_op
|= LDAP_MOD_DELETE
;
104 case LDB_FLAG_MOD_REPLACE
:
105 mods
[num_mods
]->mod_op
|= LDAP_MOD_REPLACE
;
109 mods
[num_mods
]->mod_type
= discard_const_p(char, el
->name
);
110 mods
[num_mods
]->mod_vals
.modv_bvals
= talloc_array(mods
[num_mods
],
113 if (!mods
[num_mods
]->mod_vals
.modv_bvals
) {
117 for (j
=0;j
<el
->num_values
;j
++) {
118 mods
[num_mods
]->mod_vals
.modv_bvals
[j
] = talloc(mods
[num_mods
]->mod_vals
.modv_bvals
,
120 if (!mods
[num_mods
]->mod_vals
.modv_bvals
[j
]) {
123 mods
[num_mods
]->mod_vals
.modv_bvals
[j
]->bv_val
= (char *)el
->values
[j
].data
;
124 mods
[num_mods
]->mod_vals
.modv_bvals
[j
]->bv_len
= el
->values
[j
].length
;
126 mods
[num_mods
]->mod_vals
.modv_bvals
[j
] = NULL
;
138 add a single set of ldap message values to a ldb_message
140 static int lldb_add_msg_attr(struct ldb_context
*ldb
,
141 struct ldb_message
*msg
,
142 const char *attr
, struct berval
**bval
)
145 struct ldb_message_element
*el
;
147 count
= ldap_count_values_len(bval
);
153 ret
= ldb_msg_add_empty(msg
, attr
, 0, &el
);
154 if (ret
!= LDB_SUCCESS
) {
159 el
->values
= talloc_array(msg
->elements
, struct ldb_val
, count
);
165 for (i
=0;i
<count
;i
++) {
166 /* we have to ensure this is null terminated so that
167 ldb_msg_find_attr_as_string() can work */
168 el
->values
[i
].data
= talloc_size(el
->values
, bval
[i
]->bv_len
+1);
169 if (!el
->values
[i
].data
) {
173 memcpy(el
->values
[i
].data
, bval
[i
]->bv_val
, bval
[i
]->bv_len
);
174 el
->values
[i
].data
[bval
[i
]->bv_len
] = 0;
175 el
->values
[i
].length
= bval
[i
]->bv_len
;
183 search for matching records
185 static int lldb_search(struct lldb_context
*lldb_ac
)
187 struct ldb_context
*ldb
;
188 struct lldb_private
*lldb
= lldb_ac
->lldb
;
189 struct ldb_module
*module
= lldb_ac
->module
;
190 struct ldb_request
*req
= lldb_ac
->req
;
197 ldb
= ldb_module_get_ctx(module
);
199 if (!req
->callback
|| !req
->context
) {
200 ldb_set_errstring(ldb
, "Async interface called with NULL callback function or NULL context");
201 return LDB_ERR_OPERATIONS_ERROR
;
204 if (req
->op
.search
.tree
== NULL
) {
205 ldb_set_errstring(ldb
, "Invalid expression parse tree");
206 return LDB_ERR_OPERATIONS_ERROR
;
209 if (req
->controls
!= NULL
) {
210 ldb_debug(ldb
, LDB_DEBUG_WARNING
, "Controls are not yet supported by ldb_ldap backend!");
213 ldb_request_set_state(req
, LDB_ASYNC_PENDING
);
215 search_base
= ldb_dn_alloc_linearized(lldb_ac
, req
->op
.search
.base
);
216 if (req
->op
.search
.base
== NULL
) {
217 search_base
= talloc_strdup(lldb_ac
, "");
219 if (search_base
== NULL
) {
220 return LDB_ERR_OPERATIONS_ERROR
;
223 expression
= ldb_filter_from_tree(lldb_ac
, req
->op
.search
.tree
);
224 if (expression
== NULL
) {
225 return LDB_ERR_OPERATIONS_ERROR
;
228 switch (req
->op
.search
.scope
) {
230 ldap_scope
= LDAP_SCOPE_BASE
;
232 case LDB_SCOPE_ONELEVEL
:
233 ldap_scope
= LDAP_SCOPE_ONELEVEL
;
236 ldap_scope
= LDAP_SCOPE_SUBTREE
;
242 if (req
->timeout
> 0) {
243 tv
.tv_sec
= req
->timeout
;
246 ret
= ldap_search_ext(lldb
->ldap
, search_base
, ldap_scope
,
248 discard_const_p(char *, req
->op
.search
.attrs
),
256 if (ret
!= LDAP_SUCCESS
) {
257 ldb_set_errstring(ldb
, ldap_err2string(ret
));
260 return lldb_ldap_to_ldb(ret
);
266 static int lldb_add(struct lldb_context
*lldb_ac
)
268 struct ldb_context
*ldb
;
269 struct lldb_private
*lldb
= lldb_ac
->lldb
;
270 struct ldb_module
*module
= lldb_ac
->module
;
271 struct ldb_request
*req
= lldb_ac
->req
;
276 ldb
= ldb_module_get_ctx(module
);
278 ldb_request_set_state(req
, LDB_ASYNC_PENDING
);
280 mods
= lldb_msg_to_mods(lldb_ac
, req
->op
.add
.message
, 0);
282 return LDB_ERR_OPERATIONS_ERROR
;
285 dn
= ldb_dn_alloc_linearized(lldb_ac
, req
->op
.add
.message
->dn
);
287 return LDB_ERR_OPERATIONS_ERROR
;
290 ret
= ldap_add_ext(lldb
->ldap
, dn
, mods
,
295 if (ret
!= LDAP_SUCCESS
) {
296 ldb_set_errstring(ldb
, ldap_err2string(ret
));
299 return lldb_ldap_to_ldb(ret
);
305 static int lldb_modify(struct lldb_context
*lldb_ac
)
307 struct ldb_context
*ldb
;
308 struct lldb_private
*lldb
= lldb_ac
->lldb
;
309 struct ldb_module
*module
= lldb_ac
->module
;
310 struct ldb_request
*req
= lldb_ac
->req
;
315 ldb
= ldb_module_get_ctx(module
);
317 ldb_request_set_state(req
, LDB_ASYNC_PENDING
);
319 mods
= lldb_msg_to_mods(lldb_ac
, req
->op
.mod
.message
, 1);
321 return LDB_ERR_OPERATIONS_ERROR
;
324 dn
= ldb_dn_alloc_linearized(lldb_ac
, req
->op
.mod
.message
->dn
);
326 return LDB_ERR_OPERATIONS_ERROR
;
329 ret
= ldap_modify_ext(lldb
->ldap
, dn
, mods
,
334 if (ret
!= LDAP_SUCCESS
) {
335 ldb_set_errstring(ldb
, ldap_err2string(ret
));
338 return lldb_ldap_to_ldb(ret
);
344 static int lldb_delete(struct lldb_context
*lldb_ac
)
346 struct ldb_context
*ldb
;
347 struct lldb_private
*lldb
= lldb_ac
->lldb
;
348 struct ldb_module
*module
= lldb_ac
->module
;
349 struct ldb_request
*req
= lldb_ac
->req
;
353 ldb
= ldb_module_get_ctx(module
);
355 ldb_request_set_state(req
, LDB_ASYNC_PENDING
);
357 dnstr
= ldb_dn_alloc_linearized(lldb_ac
, req
->op
.del
.dn
);
359 ret
= ldap_delete_ext(lldb
->ldap
, dnstr
,
364 if (ret
!= LDAP_SUCCESS
) {
365 ldb_set_errstring(ldb
, ldap_err2string(ret
));
368 return lldb_ldap_to_ldb(ret
);
374 static int lldb_rename(struct lldb_context
*lldb_ac
)
376 struct ldb_context
*ldb
;
377 struct lldb_private
*lldb
= lldb_ac
->lldb
;
378 struct ldb_module
*module
= lldb_ac
->module
;
379 struct ldb_request
*req
= lldb_ac
->req
;
380 const char *rdn_name
;
381 const struct ldb_val
*rdn_val
;
387 ldb
= ldb_module_get_ctx(module
);
389 ldb_request_set_state(req
, LDB_ASYNC_PENDING
);
391 old_dn
= ldb_dn_alloc_linearized(lldb_ac
, req
->op
.rename
.olddn
);
392 if (old_dn
== NULL
) {
393 return LDB_ERR_OPERATIONS_ERROR
;
396 rdn_name
= ldb_dn_get_rdn_name(req
->op
.rename
.newdn
);
397 rdn_val
= ldb_dn_get_rdn_val(req
->op
.rename
.newdn
);
399 if ((rdn_name
!= NULL
) && (rdn_val
!= NULL
)) {
400 newrdn
= talloc_asprintf(lldb_ac
, "%s=%s", rdn_name
,
401 rdn_val
->length
> 0 ? ldb_dn_escape_value(lldb_ac
, *rdn_val
) : "");
403 newrdn
= talloc_strdup(lldb_ac
, "");
406 return LDB_ERR_OPERATIONS_ERROR
;
409 parentdn
= ldb_dn_alloc_linearized(lldb_ac
, ldb_dn_get_parent(lldb_ac
, req
->op
.rename
.newdn
));
411 return LDB_ERR_OPERATIONS_ERROR
;
414 ret
= ldap_rename(lldb
->ldap
, old_dn
, newrdn
, parentdn
,
418 if (ret
!= LDAP_SUCCESS
) {
419 ldb_set_errstring(ldb
, ldap_err2string(ret
));
422 return lldb_ldap_to_ldb(ret
);
425 static int lldb_start_trans(struct ldb_module
*module
)
427 /* TODO implement a local transaction mechanism here */
432 static int lldb_end_trans(struct ldb_module
*module
)
434 /* TODO implement a local transaction mechanism here */
439 static int lldb_del_trans(struct ldb_module
*module
)
441 /* TODO implement a local transaction mechanism here */
446 static void lldb_request_done(struct lldb_context
*ac
,
447 struct ldb_control
**ctrls
, int error
)
449 struct ldb_request
*req
;
450 struct ldb_reply
*ares
;
454 ares
= talloc_zero(req
, struct ldb_reply
);
456 ldb_oom(ldb_module_get_ctx(ac
->module
));
457 req
->callback(req
, NULL
);
460 ares
->type
= LDB_REPLY_DONE
;
461 ares
->controls
= talloc_steal(ares
, ctrls
);
464 req
->callback(req
, ares
);
467 /* return false if the request is still in progress
468 * return true if the request is completed
470 static bool lldb_parse_result(struct lldb_context
*ac
, LDAPMessage
*result
)
472 struct ldb_context
*ldb
;
473 struct lldb_private
*lldb
= ac
->lldb
;
474 LDAPControl
**serverctrlsp
= NULL
;
475 char **referralsp
= NULL
;
476 char *matcheddnp
= NULL
;
477 char *errmsgp
= NULL
;
480 struct ldb_message
*ldbmsg
= NULL
;
482 bool callback_failed
;
488 ldb
= ldb_module_get_ctx(ac
->module
);
490 type
= ldap_msgtype(result
);
491 callback_failed
= false;
492 request_done
= false;
495 case LDAP_RES_SEARCH_ENTRY
:
497 msg
= ldap_first_entry(lldb
->ldap
, result
);
499 BerElement
*berptr
= NULL
;
502 ldbmsg
= ldb_msg_new(ac
);
505 ret
= LDB_ERR_OPERATIONS_ERROR
;
509 dn
= ldap_get_dn(lldb
->ldap
, msg
);
513 ret
= LDB_ERR_OPERATIONS_ERROR
;
516 ldbmsg
->dn
= ldb_dn_new(ldbmsg
, ldb
, dn
);
517 if ( ! ldb_dn_validate(ldbmsg
->dn
)) {
518 ldb_asprintf_errstring(ldb
, "Invalid DN '%s' in reply", dn
);
520 ret
= LDB_ERR_OPERATIONS_ERROR
;
525 /* loop over all attributes */
526 for (attr
=ldap_first_attribute(lldb
->ldap
, msg
, &berptr
);
528 attr
=ldap_next_attribute(lldb
->ldap
, msg
, berptr
)) {
529 struct berval
**bval
;
530 bval
= ldap_get_values_len(lldb
->ldap
, msg
, attr
);
533 lldb_add_msg_attr(ldb
, ldbmsg
, attr
, bval
);
534 ldap_value_free_len(bval
);
537 if (berptr
) ber_free(berptr
, 0);
539 ret
= ldb_module_send_entry(ac
->req
, ldbmsg
, NULL
/* controls not yet supported */);
540 if (ret
!= LDB_SUCCESS
) {
541 ldb_asprintf_errstring(ldb
, "entry send failed: %s",
543 callback_failed
= true;
546 ret
= LDB_ERR_OPERATIONS_ERROR
;
550 case LDAP_RES_SEARCH_REFERENCE
:
552 ret
= ldap_parse_reference(lldb
->ldap
, result
,
553 &referralsp
, &serverctrlsp
, 0);
554 if (ret
!= LDAP_SUCCESS
) {
555 ldb_asprintf_errstring(ldb
, "ldap reference parse error: %s : %s",
556 ldap_err2string(ret
), errmsgp
);
557 ret
= LDB_ERR_OPERATIONS_ERROR
;
560 if (referralsp
== NULL
) {
561 ldb_asprintf_errstring(ldb
, "empty ldap referrals list");
562 ret
= LDB_ERR_PROTOCOL_ERROR
;
566 for (i
= 0; referralsp
[i
]; i
++) {
567 referral
= talloc_strdup(ac
, referralsp
[i
]);
569 ret
= ldb_module_send_referral(ac
->req
, referral
);
570 if (ret
!= LDB_SUCCESS
) {
571 ldb_asprintf_errstring(ldb
, "referral send failed: %s",
573 callback_failed
= true;
579 case LDAP_RES_SEARCH_RESULT
:
580 case LDAP_RES_MODIFY
:
582 case LDAP_RES_DELETE
:
585 if (ldap_parse_result(lldb
->ldap
, result
, &ret
,
586 &matcheddnp
, &errmsgp
,
587 &referralsp
, &serverctrlsp
, 0) != LDAP_SUCCESS
) {
588 ret
= LDB_ERR_OPERATIONS_ERROR
;
590 if (ret
!= LDB_SUCCESS
) {
591 ldb_asprintf_errstring(ldb
, "ldap parse error for type %d: %s : %s",
592 type
, ldap_err2string(ret
), errmsgp
);
596 if (serverctrlsp
!= NULL
) {
597 /* FIXME: transform the LDAPControl list into an ldb_control one */
605 ldb_asprintf_errstring(ldb
, "unknown ldap return type: %d", type
);
606 ret
= LDB_ERR_PROTOCOL_ERROR
;
610 if (ret
!= LDB_SUCCESS
) {
612 /* if the callback failed the caller will have freed the
613 * request. Just return and don't try to use it */
614 if (callback_failed
) {
616 /* tell lldb_wait to remove the request from the
619 goto free_and_return
;
626 lldb_request_done(ac
, ac
->controls
, ret
);
628 goto free_and_return
;
635 if (matcheddnp
) ldap_memfree(matcheddnp
);
636 if (errmsgp
&& *errmsgp
) {
637 ldb_set_errstring(ldb
, errmsgp
);
640 ldap_memfree(errmsgp
);
642 if (referralsp
) ldap_value_free(referralsp
);
643 if (serverctrlsp
) ldap_controls_free(serverctrlsp
);
645 ldap_msgfree(result
);
650 static void lldb_timeout(struct tevent_context
*ev
,
651 struct tevent_timer
*te
,
655 struct lldb_context
*ac
;
656 ac
= talloc_get_type(private_data
, struct lldb_context
);
658 lldb_request_done(ac
, NULL
, LDB_ERR_TIME_LIMIT_EXCEEDED
);
661 static void lldb_callback(struct tevent_context
*ev
,
662 struct tevent_timer
*te
,
666 struct lldb_context
*ac
;
667 struct tevent_timer
*lte
;
672 ac
= talloc_get_type(private_data
, struct lldb_context
);
675 lldb_request_done(ac
, NULL
, LDB_ERR_OPERATIONS_ERROR
);
681 lret
= ldap_result(ac
->lldb
->ldap
, ac
->msgid
, 0, &tv
, &result
);
686 lldb_request_done(ac
, NULL
, LDB_ERR_OPERATIONS_ERROR
);
690 if ( ! lldb_parse_result(ac
, result
)) {
699 lte
= tevent_add_timer(ev
, ac
, tv
, lldb_callback
, ac
);
701 lldb_request_done(ac
, NULL
, LDB_ERR_OPERATIONS_ERROR
);
705 static bool lldb_dn_is_special(struct ldb_request
*req
)
707 struct ldb_dn
*dn
= NULL
;
709 switch (req
->operation
) {
711 dn
= req
->op
.add
.message
->dn
;
714 dn
= req
->op
.mod
.message
->dn
;
720 dn
= req
->op
.rename
.olddn
;
726 if (dn
&& ldb_dn_is_special(dn
)) {
732 static void lldb_auto_done_callback(struct tevent_context
*ev
,
733 struct tevent_timer
*te
,
737 struct lldb_context
*ac
;
739 ac
= talloc_get_type(private_data
, struct lldb_context
);
740 lldb_request_done(ac
, NULL
, LDB_SUCCESS
);
743 static int lldb_handle_request(struct ldb_module
*module
, struct ldb_request
*req
)
745 struct ldb_context
*ldb
;
746 struct lldb_private
*lldb
;
747 struct lldb_context
*ac
;
748 struct tevent_context
*ev
;
749 struct tevent_timer
*te
;
753 lldb
= talloc_get_type(ldb_module_get_private(module
), struct lldb_private
);
754 ldb
= ldb_module_get_ctx(module
);
756 if (req
->starttime
== 0 || req
->timeout
== 0) {
757 ldb_set_errstring(ldb
, "Invalid timeout settings");
758 return LDB_ERR_TIME_LIMIT_EXCEEDED
;
761 ev
= ldb_get_event_context(ldb
);
763 return LDB_ERR_OPERATIONS_ERROR
;
766 ac
= talloc_zero(ldb
, struct lldb_context
);
768 ldb_set_errstring(ldb
, "Out of Memory");
769 return LDB_ERR_OPERATIONS_ERROR
;
777 if (lldb_dn_is_special(req
)) {
780 te
= tevent_add_timer(ev
, ac
, tv
,
781 lldb_auto_done_callback
, ac
);
783 return LDB_ERR_OPERATIONS_ERROR
;
789 switch (ac
->req
->operation
) {
791 ret
= lldb_search(ac
);
797 ret
= lldb_modify(ac
);
800 ret
= lldb_delete(ac
);
803 ret
= lldb_rename(ac
);
806 /* no other op supported */
807 ret
= LDB_ERR_PROTOCOL_ERROR
;
811 if (ret
!= LDB_SUCCESS
) {
812 lldb_request_done(ac
, NULL
, ret
);
818 te
= tevent_add_timer(ev
, ac
, tv
, lldb_callback
, ac
);
820 return LDB_ERR_OPERATIONS_ERROR
;
823 if (req
->timeout
> 0) {
824 tv
.tv_sec
= req
->starttime
+ req
->timeout
;
826 te
= tevent_add_timer(ev
, ac
, tv
, lldb_timeout
, ac
);
828 return LDB_ERR_OPERATIONS_ERROR
;
835 static const struct ldb_module_ops lldb_ops
= {
837 .search
= lldb_handle_request
,
838 .add
= lldb_handle_request
,
839 .modify
= lldb_handle_request
,
840 .del
= lldb_handle_request
,
841 .rename
= lldb_handle_request
,
842 .request
= lldb_handle_request
,
843 .start_transaction
= lldb_start_trans
,
844 .end_transaction
= lldb_end_trans
,
845 .del_transaction
= lldb_del_trans
,
849 static int lldb_destructor(struct lldb_private
*lldb
)
851 ldap_unbind(lldb
->ldap
);
857 optionally perform a bind
859 static int lldb_bind(struct ldb_module
*module
,
860 const char *options
[])
862 const char *bind_mechanism
;
863 struct lldb_private
*lldb
;
864 struct ldb_context
*ldb
= ldb_module_get_ctx(module
);
867 bind_mechanism
= ldb_options_find(ldb
, options
, "bindMech");
868 if (bind_mechanism
== NULL
) {
873 lldb
= talloc_get_type(ldb_module_get_private(module
), struct lldb_private
);
875 if (strcmp(bind_mechanism
, "simple") == 0) {
876 const char *bind_id
, *bind_secret
;
878 bind_id
= ldb_options_find(ldb
, options
, "bindID");
879 bind_secret
= ldb_options_find(ldb
, options
, "bindSecret");
880 if (bind_id
== NULL
|| bind_secret
== NULL
) {
881 ldb_asprintf_errstring(ldb
, "simple bind requires bindID and bindSecret");
882 return LDB_ERR_OPERATIONS_ERROR
;
885 ret
= ldap_simple_bind_s(lldb
->ldap
, bind_id
, bind_secret
);
886 if (ret
!= LDAP_SUCCESS
) {
887 ldb_asprintf_errstring(ldb
, "bind failed: %s", ldap_err2string(ret
));
893 ldb_asprintf_errstring(ldb
, "bind failed: unknown mechanism %s", bind_mechanism
);
894 return LDB_ERR_INAPPROPRIATE_AUTHENTICATION
;
898 connect to the database
900 static int lldb_connect(struct ldb_context
*ldb
,
903 const char *options
[],
904 struct ldb_module
**_module
)
906 struct ldb_module
*module
;
907 struct lldb_private
*lldb
;
911 module
= ldb_module_new(ldb
, ldb
, "ldb_ldap backend", &lldb_ops
);
912 if (!module
) return LDB_ERR_OPERATIONS_ERROR
;
914 lldb
= talloc_zero(module
, struct lldb_private
);
919 ldb_module_set_private(module
, lldb
);
921 ret
= ldap_initialize(&lldb
->ldap
, url
);
922 if (ret
!= LDAP_SUCCESS
) {
923 ldb_debug(ldb
, LDB_DEBUG_FATAL
, "ldap_initialize failed for URL '%s' - %s",
924 url
, ldap_err2string(ret
));
928 talloc_set_destructor(lldb
, lldb_destructor
);
930 ret
= ldap_set_option(lldb
->ldap
, LDAP_OPT_PROTOCOL_VERSION
, &version
);
931 if (ret
!= LDAP_SUCCESS
) {
932 ldb_debug(ldb
, LDB_DEBUG_FATAL
, "ldap_set_option failed - %s",
933 ldap_err2string(ret
));
939 ret
= lldb_bind(module
, options
);
940 if (ret
!= LDB_SUCCESS
) {
949 return LDB_ERR_OPERATIONS_ERROR
;
953 initialise the module
955 int ldb_ldap_init(const char *version
)
958 const char *names
[] = { "ldap", "ldaps", "ldapi", NULL
};
959 LDB_MODULE_CHECK_VERSION(version
);
960 for (i
=0; names
[i
]; i
++) {
961 ret
= ldb_register_backend(names
[i
], lldb_connect
, false);
962 if (ret
!= LDB_SUCCESS
) {