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 2 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, write to the Free Software
23 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 * Component: ldb ldap backend
31 * Description: core files for LDAP backend
33 * Author: Andrew Tridgell
37 * - description: make the module use asyncronous calls
43 #include "ldb/include/includes.h"
52 struct lldb_async_context {
53 struct ldb_module *module;
57 int (*callback)(struct ldb_context *, void *, struct ldb_async_result *);
60 static int lldb_ldap_to_ldb(int err) {
61 /* Ldap errors and ldb errors are defined to the same values */
65 static struct ldb_async_handle *init_handle(struct lldb_private *lldb, struct ldb_module *module,
67 int (*callback)(struct ldb_context *, void *, struct ldb_async_result *),
70 struct lldb_async_context *ac;
71 struct ldb_async_handle *h;
73 h = talloc_zero(lldb, struct ldb_async_handle);
75 ldb_set_errstring(module->ldb, talloc_asprintf(module, "Out of Memory"));
81 ac = talloc(h, struct lldb_async_context);
83 ldb_set_errstring(module->ldb, talloc_asprintf(module, "Out of Memory"));
88 h->private_data = (void *)ac;
90 h->state = LDB_ASYNC_INIT;
91 h->status = LDB_SUCCESS;
94 ac->context = context;
95 ac->callback = callback;
96 ac->timeout = timeout;
102 convert a ldb_message structure to a list of LDAPMod structures
103 ready for ldap_add() or ldap_modify()
105 static LDAPMod **lldb_msg_to_mods(void *mem_ctx, const struct ldb_message *msg, int use_flags)
111 /* allocate maximum number of elements needed */
112 mods = talloc_array(mem_ctx, LDAPMod *, msg->num_elements+1);
119 for (i=0;i<msg->num_elements;i++) {
120 const struct ldb_message_element *el = &msg->elements[i];
122 mods[num_mods] = talloc(mods, LDAPMod);
123 if (!mods[num_mods]) {
126 mods[num_mods+1] = NULL;
127 mods[num_mods]->mod_op = LDAP_MOD_BVALUES;
129 switch (el->flags & LDB_FLAG_MOD_MASK) {
130 case LDB_FLAG_MOD_ADD:
131 mods[num_mods]->mod_op |= LDAP_MOD_ADD;
133 case LDB_FLAG_MOD_DELETE:
134 mods[num_mods]->mod_op |= LDAP_MOD_DELETE;
136 case LDB_FLAG_MOD_REPLACE:
137 mods[num_mods]->mod_op |= LDAP_MOD_REPLACE;
141 mods[num_mods]->mod_type = discard_const_p(char, el->name);
142 mods[num_mods]->mod_vals.modv_bvals = talloc_array(mods[num_mods],
145 if (!mods[num_mods]->mod_vals.modv_bvals) {
149 for (j=0;j<el->num_values;j++) {
150 mods[num_mods]->mod_vals.modv_bvals[j] = talloc(mods[num_mods]->mod_vals.modv_bvals,
152 if (!mods[num_mods]->mod_vals.modv_bvals[j]) {
155 mods[num_mods]->mod_vals.modv_bvals[j]->bv_val = el->values[j].data;
156 mods[num_mods]->mod_vals.modv_bvals[j]->bv_len = el->values[j].length;
158 mods[num_mods]->mod_vals.modv_bvals[j] = NULL;
170 add a single set of ldap message values to a ldb_message
172 static int lldb_add_msg_attr(struct ldb_context *ldb,
173 struct ldb_message *msg,
174 const char *attr, struct berval **bval)
177 struct ldb_message_element *el;
179 count = ldap_count_values_len(bval);
185 el = talloc_realloc(msg, msg->elements, struct ldb_message_element,
186 msg->num_elements + 1);
194 el = &msg->elements[msg->num_elements];
196 el->name = talloc_strdup(msg->elements, attr);
204 el->values = talloc_array(msg->elements, struct ldb_val, count);
210 for (i=0;i<count;i++) {
211 el->values[i].data = talloc_memdup(el->values, bval[i]->bv_val, bval[i]->bv_len);
212 if (!el->values[i].data) {
215 el->values[i].length = bval[i]->bv_len;
225 search for matching records
227 static int lldb_search_async(struct ldb_module *module, const struct ldb_dn *base,
228 enum ldb_scope scope, struct ldb_parse_tree *tree,
229 const char * const *attrs,
230 struct ldb_control **control_req,
232 int (*callback)(struct ldb_context *, void *, struct ldb_async_result *),
234 struct ldb_async_handle **handle)
236 struct lldb_private *lldb = talloc_get_type(module->private_data, struct lldb_private);
237 struct lldb_async_context *lldb_ac;
244 if (!callback || !context) {
245 ldb_set_errstring(module->ldb, talloc_asprintf(module, "Async interface called with NULL callback function or NULL context"));
246 return LDB_ERR_OPERATIONS_ERROR;
250 ldb_set_errstring(module->ldb, talloc_asprintf(module, "Invalid expression parse tree"));
251 return LDB_ERR_OPERATIONS_ERROR;
254 if (control_req != NULL) {
255 ldb_debug(module->ldb, LDB_DEBUG_WARNING, "Controls are not yet supported by ldb_ldap backend!\n");
258 *handle = init_handle(lldb, module, context, callback, timeout);
259 if (*handle == NULL) {
260 talloc_free(*handle);
261 return LDB_ERR_OPERATIONS_ERROR;
264 lldb_ac = talloc_get_type((*handle)->private_data, struct lldb_async_context);
266 search_base = ldb_dn_linearize(lldb_ac, base);
268 search_base = talloc_strdup(lldb_ac, "");
270 if (search_base == NULL) {
271 talloc_free(*handle);
272 return LDB_ERR_OPERATIONS_ERROR;
275 expression = ldb_filter_from_tree(lldb_ac, tree);
276 if (expression == NULL) {
277 talloc_free(*handle);
278 return LDB_ERR_OPERATIONS_ERROR;
283 ldap_scope = LDAP_SCOPE_BASE;
285 case LDB_SCOPE_ONELEVEL:
286 ldap_scope = LDAP_SCOPE_ONELEVEL;
289 ldap_scope = LDAP_SCOPE_SUBTREE;
296 ret = ldap_search_ext(lldb->ldap, search_base, ldap_scope,
298 discard_const_p(char *, attrs),
306 if (ret != LDAP_SUCCESS) {
307 ldb_set_errstring(module->ldb, talloc_strdup(module, ldap_err2string(ret)));
308 talloc_free(*handle);
312 return lldb_ldap_to_ldb(ret);
315 static int lldb_search_sync_callback(struct ldb_context *ldb, void *context, struct ldb_async_result *ares)
317 struct ldb_result *res;
321 ldb_set_errstring(ldb, talloc_asprintf(ldb, "NULL Context in callback"));
322 return LDB_ERR_OPERATIONS_ERROR;
325 res = *((struct ldb_result **)context);
331 if (ares->type == LDB_REPLY_ENTRY) {
332 res->msgs = talloc_realloc(res, res->msgs, struct ldb_message *, res->count + 2);
337 res->msgs[res->count + 1] = NULL;
339 res->msgs[res->count] = talloc_steal(res->msgs, ares->message);
340 if (! res->msgs[res->count]) {
347 if (ares->type == LDB_REPLY_REFERRAL) {
349 for (n = 0; res->refs[n]; n++) /*noop*/ ;
354 res->refs = talloc_realloc(res, res->refs, char *, n + 2);
359 res->refs[n] = talloc_steal(res->refs, ares->referral);
360 res->refs[n + 1] = NULL;
363 if (ares->type == LDB_REPLY_DONE) {
364 if (ares->controls) {
365 res->controls = talloc_steal(res, ares->controls);
366 if (! res->controls) {
378 *((struct ldb_result **)context) = NULL;
379 return LDB_ERR_OPERATIONS_ERROR;
383 search for matching records using a synchronous function
385 static int lldb_search_bytree(struct ldb_module *module, const struct ldb_dn *base,
386 enum ldb_scope scope, struct ldb_parse_tree *tree,
387 const char * const *attrs,
388 struct ldb_control **control_req,
389 struct ldb_result **res)
391 struct lldb_private *lldb = talloc_get_type(module->private_data, struct lldb_private);
392 struct ldb_async_handle *handle;
395 *res = talloc_zero(lldb, struct ldb_result);
397 return LDB_ERR_OPERATIONS_ERROR;
400 ret = lldb_search_async(module, base, scope, tree, attrs, control_req,
401 res, &lldb_search_sync_callback, lldb->timeout, &handle);
403 if (ret == LDB_SUCCESS) {
404 ret = ldb_async_wait(handle, LDB_WAIT_ALL);
408 if (ret != LDB_SUCCESS) {
418 static int lldb_add_async(struct ldb_module *module, const struct ldb_message *msg,
420 int (*callback)(struct ldb_context *, void *, struct ldb_async_result *),
422 struct ldb_async_handle **handle)
424 struct lldb_private *lldb = talloc_get_type(module->private_data, struct lldb_private);
425 struct lldb_async_context *lldb_ac;
430 /* ltdb specials should not reach this point */
431 if (ldb_dn_is_special(msg->dn)) {
432 return LDB_ERR_INVALID_DN_SYNTAX;
435 *handle = init_handle(lldb, module, context, callback, timeout);
436 if (*handle == NULL) {
437 return LDB_ERR_OPERATIONS_ERROR;
440 lldb_ac = talloc_get_type((*handle)->private_data, struct lldb_async_context);
442 mods = lldb_msg_to_mods(lldb_ac, msg, 0);
444 talloc_free(*handle);
445 return LDB_ERR_OPERATIONS_ERROR;
448 dn = ldb_dn_linearize(lldb_ac, msg->dn);
450 talloc_free(*handle);
451 return LDB_ERR_OPERATIONS_ERROR;
454 ret = ldap_add_ext(lldb->ldap, dn, mods,
459 if (ret != LDAP_SUCCESS) {
460 ldb_set_errstring(module->ldb, talloc_strdup(module, ldap_err2string(ret)));
461 talloc_free(*handle);
464 return lldb_ldap_to_ldb(ret);
467 static int lldb_add(struct ldb_module *module, const struct ldb_message *msg)
469 struct lldb_private *lldb = talloc_get_type(module->private_data, struct lldb_private);
470 struct ldb_async_handle *handle;
473 /* ldap does not understand ltdb specials */
474 if (ldb_dn_is_special(msg->dn)) {
478 ret = lldb_add_async(module, msg, NULL, NULL, lldb->timeout, &handle);
480 if (ret != LDB_SUCCESS)
483 ret = ldb_async_wait(handle, LDB_WAIT_ALL);
493 static int lldb_modify_async(struct ldb_module *module, const struct ldb_message *msg,
495 int (*callback)(struct ldb_context *, void *, struct ldb_async_result *),
497 struct ldb_async_handle **handle)
499 struct lldb_private *lldb = talloc_get_type(module->private_data, struct lldb_private);
500 struct lldb_async_context *lldb_ac;
505 /* ltdb specials should not reach this point */
506 if (ldb_dn_is_special(msg->dn)) {
507 return LDB_ERR_INVALID_DN_SYNTAX;
510 *handle = init_handle(lldb, module, context, callback, timeout);
511 if (*handle == NULL) {
512 return LDB_ERR_OPERATIONS_ERROR;
515 lldb_ac = talloc_get_type((*handle)->private_data, struct lldb_async_context);
517 mods = lldb_msg_to_mods(lldb_ac, msg, 1);
519 talloc_free(*handle);
520 return LDB_ERR_OPERATIONS_ERROR;
523 dn = ldb_dn_linearize(lldb_ac, msg->dn);
525 talloc_free(*handle);
526 return LDB_ERR_OPERATIONS_ERROR;
529 ret = ldap_modify_ext(lldb->ldap, dn, mods,
534 if (ret != LDAP_SUCCESS) {
535 ldb_set_errstring(module->ldb, talloc_strdup(module, ldap_err2string(ret)));
536 talloc_free(*handle);
539 return lldb_ldap_to_ldb(ret);
542 static int lldb_modify(struct ldb_module *module, const struct ldb_message *msg)
544 struct lldb_private *lldb = talloc_get_type(module->private_data, struct lldb_private);
545 struct ldb_async_handle *handle;
548 /* ldap does not understand ltdb specials */
549 if (ldb_dn_is_special(msg->dn)) {
553 ret = lldb_modify_async(module, msg, NULL, NULL, lldb->timeout, &handle);
555 if (ret != LDB_SUCCESS)
558 ret = ldb_async_wait(handle, LDB_WAIT_ALL);
567 static int lldb_delete_async(struct ldb_module *module, const struct ldb_dn *dn,
569 int (*callback)(struct ldb_context *, void *, struct ldb_async_result *),
571 struct ldb_async_handle **handle)
573 struct lldb_private *lldb = talloc_get_type(module->private_data, struct lldb_private);
574 struct lldb_async_context *lldb_ac;
578 /* ltdb specials should not reach this point */
579 if (ldb_dn_is_special(dn)) {
580 return LDB_ERR_INVALID_DN_SYNTAX;
583 *handle = init_handle(lldb, module, context, callback, timeout);
584 if (*handle == NULL) {
585 return LDB_ERR_OPERATIONS_ERROR;
588 lldb_ac = talloc_get_type((*handle)->private_data, struct lldb_async_context);
590 dnstr = ldb_dn_linearize(lldb_ac, dn);
592 ret = ldap_delete_ext(lldb->ldap, dnstr,
597 if (ret != LDAP_SUCCESS) {
598 ldb_set_errstring(module->ldb, talloc_strdup(module, ldap_err2string(ret)));
599 talloc_free(*handle);
602 return lldb_ldap_to_ldb(ret);
605 static int lldb_delete(struct ldb_module *module, const struct ldb_dn *dn)
607 struct lldb_private *lldb = talloc_get_type(module->private_data, struct lldb_private);
608 struct ldb_async_handle *handle;
611 /* ignore ltdb specials */
612 if (ldb_dn_is_special(dn)) {
616 ret = lldb_delete_async(module, dn, NULL, NULL, lldb->timeout, &handle);
618 if (ret != LDB_SUCCESS)
621 ret = ldb_async_wait(handle, LDB_WAIT_ALL);
630 static int lldb_rename_async(struct ldb_module *module,
631 const struct ldb_dn *olddn, const struct ldb_dn *newdn,
633 int (*callback)(struct ldb_context *, void *, struct ldb_async_result *),
635 struct ldb_async_handle **handle)
637 struct lldb_private *lldb = talloc_get_type(module->private_data, struct lldb_private);
638 struct lldb_async_context *lldb_ac;
644 /* ltdb specials should not reach this point */
645 if (ldb_dn_is_special(olddn) || ldb_dn_is_special(newdn)) {
646 return LDB_ERR_INVALID_DN_SYNTAX;
649 *handle = init_handle(lldb, module, context, callback, timeout);
650 if (*handle == NULL) {
651 return LDB_ERR_OPERATIONS_ERROR;
654 lldb_ac = talloc_get_type((*handle)->private_data, struct lldb_async_context);
656 old_dn = ldb_dn_linearize(lldb_ac, olddn);
657 if (old_dn == NULL) {
658 talloc_free(*handle);
659 return LDB_ERR_OPERATIONS_ERROR;
662 newrdn = talloc_asprintf(lldb_ac, "%s=%s",
663 newdn->components[0].name,
664 ldb_dn_escape_value(lldb, newdn->components[0].value));
666 talloc_free(*handle);
667 return LDB_ERR_OPERATIONS_ERROR;
670 parentdn = ldb_dn_linearize(lldb_ac, ldb_dn_get_parent(lldb_ac, newdn));
672 talloc_free(*handle);
673 return LDB_ERR_OPERATIONS_ERROR;
676 ret = ldap_rename(lldb->ldap, old_dn, newrdn, parentdn,
680 if (ret != LDAP_SUCCESS) {
681 ldb_set_errstring(module->ldb, talloc_strdup(module, ldap_err2string(ret)));
682 talloc_free(*handle);
685 return lldb_ldap_to_ldb(ret);
688 static int lldb_rename(struct ldb_module *module, const struct ldb_dn *olddn, const struct ldb_dn *newdn)
690 struct lldb_private *lldb = talloc_get_type(module->private_data, struct lldb_private);
691 struct ldb_async_handle *handle;
694 /* ignore ltdb specials */
695 if (ldb_dn_is_special(olddn) || ldb_dn_is_special(newdn)) {
699 ret = lldb_rename_async(module, olddn, newdn, NULL, NULL, lldb->timeout, &handle);
701 if (ret != LDB_SUCCESS)
704 ret = ldb_async_wait(handle, LDB_WAIT_ALL);
710 static int lldb_parse_result(struct ldb_async_handle *handle, LDAPMessage *result)
712 struct lldb_async_context *ac = talloc_get_type(handle->private_data, struct lldb_async_context);
713 struct lldb_private *lldb = talloc_get_type(ac->module->private_data, struct lldb_private);
714 struct ldb_async_result *ares = NULL;
717 char *matcheddnp = NULL;
718 char *errmsgp = NULL;
719 char **referralsp = NULL;
720 LDAPControl **serverctrlsp = NULL;
723 type = ldap_msgtype(result);
727 case LDAP_RES_SEARCH_ENTRY:
728 msg = ldap_first_entry(lldb->ldap, result);
730 BerElement *berptr = NULL;
733 ares = talloc_zero(ac, struct ldb_async_result);
735 handle->status = LDB_ERR_OPERATIONS_ERROR;
739 ares->message = ldb_msg_new(ares);
740 if (!ares->message) {
741 handle->status = LDB_ERR_OPERATIONS_ERROR;
745 dn = ldap_get_dn(lldb->ldap, msg);
747 handle->status = LDB_ERR_OPERATIONS_ERROR;
750 ares->message->dn = ldb_dn_explode_or_special(ares->message, dn);
751 if (ares->message->dn == NULL) {
752 handle->status = LDB_ERR_OPERATIONS_ERROR;
757 ares->message->num_elements = 0;
758 ares->message->elements = NULL;
759 ares->message->private_data = NULL;
761 /* loop over all attributes */
762 for (attr=ldap_first_attribute(lldb->ldap, msg, &berptr);
764 attr=ldap_next_attribute(lldb->ldap, msg, berptr)) {
765 struct berval **bval;
766 bval = ldap_get_values_len(lldb->ldap, msg, attr);
769 lldb_add_msg_attr(ac->module->ldb, ares->message, attr, bval);
770 ldap_value_free_len(bval);
773 if (berptr) ber_free(berptr, 0);
776 ares->type = LDB_REPLY_ENTRY;
777 handle->state = LDB_ASYNC_PENDING;
778 ret = ac->callback(ac->module->ldb, ac->context, ares);
779 if (ret != LDB_SUCCESS) {
780 handle->status = ret;
783 handle->status = LDB_ERR_PROTOCOL_ERROR;
784 handle->state = LDB_ASYNC_DONE;
788 case LDAP_RES_SEARCH_REFERENCE:
789 if (ldap_parse_result(lldb->ldap, result, &handle->status,
790 &matcheddnp, &errmsgp,
791 &referralsp, &serverctrlsp, 1) != LDAP_SUCCESS) {
792 handle->status = LDB_ERR_OPERATIONS_ERROR;
795 if (referralsp == NULL) {
796 handle->status = LDB_ERR_PROTOCOL_ERROR;
800 ares = talloc_zero(ac, struct ldb_async_result);
802 handle->status = LDB_ERR_OPERATIONS_ERROR;
806 ares->referral = talloc_strdup(ares, *referralsp);
807 ares->type = LDB_REPLY_REFERRAL;
808 handle->state = LDB_ASYNC_PENDING;
809 ret = ac->callback(ac->module->ldb, ac->context, ares);
810 if (ret != LDB_SUCCESS) {
811 handle->status = ret;
816 case LDAP_RES_SEARCH_RESULT:
817 if (ldap_parse_result(lldb->ldap, result, &handle->status,
818 &matcheddnp, &errmsgp,
819 &referralsp, &serverctrlsp, 1) != LDAP_SUCCESS) {
820 handle->status = LDB_ERR_OPERATIONS_ERROR;
824 ares = talloc_zero(ac, struct ldb_async_result);
826 handle->status = LDB_ERR_OPERATIONS_ERROR;
830 if (serverctrlsp != NULL) {
831 /* FIXME: transform the LDAPControl list into an ldb_control one */
832 ares->controls = NULL;
835 ares->type = LDB_REPLY_DONE;
836 handle->state = LDB_ASYNC_DONE;
837 ret = ac->callback(ac->module->ldb, ac->context, ares);
838 if (ret != LDB_SUCCESS) {
839 handle->status = ret;
844 case LDAP_RES_MODIFY:
846 case LDAP_RES_DELETE:
848 if (ldap_parse_result(lldb->ldap, result, &handle->status,
849 &matcheddnp, &errmsgp,
850 &referralsp, &serverctrlsp, 1) != LDAP_SUCCESS) {
851 handle->status = LDB_ERR_OPERATIONS_ERROR;
854 if (ac->callback && handle->status == LDB_SUCCESS) {
855 ares = NULL; /* FIXME: build a corresponding ares to pass on */
856 handle->status = ac->callback(ac->module->ldb, ac->context, ares);
858 handle->state = LDB_ASYNC_DONE;
862 handle->status = LDB_ERR_PROTOCOL_ERROR;
866 if (matcheddnp) ldap_memfree(matcheddnp);
868 ldb_set_errstring(ac->module->ldb, talloc_strdup(ac->module, errmsgp));
869 ldap_memfree(errmsgp);
871 if (referralsp) ldap_value_free(referralsp);
872 if (serverctrlsp) ldap_controls_free(serverctrlsp);
874 ldap_msgfree(result);
875 return handle->status;
878 handle->state = LDB_ASYNC_DONE;
879 ldap_msgfree(result);
880 return handle->status;
883 static int lldb_async_wait(struct ldb_async_handle *handle, enum ldb_async_wait_type type)
885 struct lldb_async_context *ac = talloc_get_type(handle->private_data, struct lldb_async_context);
886 struct lldb_private *lldb = talloc_get_type(handle->module->private_data, struct lldb_private);
887 struct timeval timeout;
889 int ret = LDB_ERR_OPERATIONS_ERROR;
891 if (handle->state == LDB_ASYNC_DONE) {
892 return handle->status;
895 if (!ac || !ac->msgid) {
896 return LDB_ERR_OPERATIONS_ERROR;
899 handle->status = LDB_SUCCESS;
905 ret = ldap_result(lldb->ldap, ac->msgid, 0, &timeout, &result);
907 handle->status = LDB_ERR_OPERATIONS_ERROR;
908 return handle->status;
911 handle->status = LDB_SUCCESS;
912 return handle->status;
914 ret = lldb_parse_result(handle, result);
917 timeout.tv_sec = ac->timeout;
919 ret = ldap_result(lldb->ldap, ac->msgid, 0, &timeout, &result);
920 if (ret == -1 || ret == 0) {
921 handle->status = LDB_ERR_OPERATIONS_ERROR;
922 return handle->status;
924 ret = lldb_parse_result(handle, result);
927 timeout.tv_sec = ac->timeout;
929 while (handle->status == LDB_SUCCESS && handle->state != LDB_ASYNC_DONE) {
930 ret = ldap_result(lldb->ldap, ac->msgid, 0, &timeout, &result);
931 if (ret == -1 || ret == 0) {
932 handle->status = LDB_ERR_OPERATIONS_ERROR;
933 return handle->status;
935 ret = lldb_parse_result(handle, result);
936 if (ret != LDB_SUCCESS) {
946 static int lldb_start_trans(struct ldb_module *module)
948 /* TODO implement a local transaction mechanism here */
953 static int lldb_end_trans(struct ldb_module *module)
955 /* TODO implement a local transaction mechanism here */
960 static int lldb_del_trans(struct ldb_module *module)
962 /* TODO implement a local transaction mechanism here */
967 static int lldb_request(struct ldb_module *module, struct ldb_request *req)
969 switch (req->operation) {
972 return lldb_search_bytree(module,
974 req->op.search.scope,
976 req->op.search.attrs,
978 &req->op.search.res);
981 return lldb_add(module, req->op.add.message);
984 return lldb_modify(module, req->op.mod.message);
987 return lldb_delete(module, req->op.del.dn);
990 return lldb_rename(module,
991 req->op.rename.olddn,
992 req->op.rename.newdn);
994 case LDB_ASYNC_SEARCH:
995 return lldb_search_async(module,
997 req->op.search.scope,
999 req->op.search.attrs,
1002 req->async.callback,
1004 &req->async.handle);
1007 return lldb_add_async(module,
1008 req->op.add.message,
1010 req->async.callback,
1012 &req->async.handle);
1014 case LDB_ASYNC_MODIFY:
1015 return lldb_modify_async(module,
1016 req->op.mod.message,
1018 req->async.callback,
1020 &req->async.handle);
1022 case LDB_ASYNC_DELETE:
1023 return lldb_delete_async(module,
1026 req->async.callback,
1028 &req->async.handle);
1030 case LDB_ASYNC_RENAME:
1031 return lldb_rename_async(module,
1032 req->op.rename.olddn,
1033 req->op.rename.newdn,
1035 req->async.callback,
1037 &req->async.handle);
1045 static const struct ldb_module_ops lldb_ops = {
1047 .request = lldb_request,
1048 .start_transaction = lldb_start_trans,
1049 .end_transaction = lldb_end_trans,
1050 .del_transaction = lldb_del_trans,
1051 .async_wait = lldb_async_wait
1055 static int lldb_destructor(void *p)
1057 struct lldb_private *lldb = p;
1058 ldap_unbind(lldb->ldap);
1063 connect to the database
1065 static int lldb_connect(struct ldb_context *ldb,
1068 const char *options[])
1070 struct lldb_private *lldb = NULL;
1074 lldb = talloc(ldb, struct lldb_private);
1081 lldb->timeout = 120; /* TODO: get timeout from options ? */
1083 ret = ldap_initialize(&lldb->ldap, url);
1084 if (ret != LDAP_SUCCESS) {
1085 ldb_debug(ldb, LDB_DEBUG_FATAL, "ldap_initialize failed for URL '%s' - %s\n",
1086 url, ldap_err2string(ret));
1090 talloc_set_destructor(lldb, lldb_destructor);
1092 ret = ldap_set_option(lldb->ldap, LDAP_OPT_PROTOCOL_VERSION, &version);
1093 if (ret != LDAP_SUCCESS) {
1094 ldb_debug(ldb, LDB_DEBUG_FATAL, "ldap_set_option failed - %s\n",
1095 ldap_err2string(ret));
1099 ldb->modules = talloc(ldb, struct ldb_module);
1100 if (!ldb->modules) {
1104 ldb->modules->ldb = ldb;
1105 ldb->modules->prev = ldb->modules->next = NULL;
1106 ldb->modules->private_data = lldb;
1107 ldb->modules->ops = &lldb_ops;
1116 int ldb_ldap_init(void)
1118 return ldb_register_backend("ldap", lldb_connect);