8e053818e556bdce9c57f96c0500d5ebd2ab08e3
[metze/samba/wip.git] / source4 / lib / ldb / ldb_ldap / ldb_ldap.c
1 /* 
2    ldb database library
3
4    Copyright (C) Andrew Tridgell  2004
5    Copyright (C) Simo Sorce       2006
6
7      ** NOTE! The following LGPL license applies to the ldb
8      ** library. This does NOT imply that all of Samba is released
9      ** under the LGPL
10    
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.
15
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.
20
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/>.
23 */
24
25 /*
26  *  Name: ldb_ldap
27  *
28  *  Component: ldb ldap backend
29  *
30  *  Description: core files for LDAP backend
31  *
32  *  Author: Andrew Tridgell
33  *
34  *  Modifications:
35  *
36  *  - description: make the module use asyncronous calls
37  *    date: Feb 2006
38  *    author: Simo Sorce
39  */
40
41 #include "ldb_includes.h"
42
43 #define LDAP_DEPRECATED 1
44 #include <ldap.h>
45
46 struct lldb_private {
47         LDAP *ldap;
48 };
49
50 struct lldb_context {
51         struct ldb_module *module;
52         struct ldb_request *req;
53
54         struct lldb_private *lldb;
55
56         struct ldb_control **controls;
57         int msgid;
58 };
59
60 static int lldb_ldap_to_ldb(int err) {
61         /* Ldap errors and ldb errors are defined to the same values */
62         return err;
63 }
64
65 /*
66   convert a ldb_message structure to a list of LDAPMod structures
67   ready for ldap_add() or ldap_modify()
68 */
69 static LDAPMod **lldb_msg_to_mods(void *mem_ctx, const struct ldb_message *msg, int use_flags)
70 {
71         LDAPMod **mods;
72         unsigned int i, j;
73         int num_mods = 0;
74
75         /* allocate maximum number of elements needed */
76         mods = talloc_array(mem_ctx, LDAPMod *, msg->num_elements+1);
77         if (!mods) {
78                 errno = ENOMEM;
79                 return NULL;
80         }
81         mods[0] = NULL;
82
83         for (i=0;i<msg->num_elements;i++) {
84                 const struct ldb_message_element *el = &msg->elements[i];
85
86                 mods[num_mods] = talloc(mods, LDAPMod);
87                 if (!mods[num_mods]) {
88                         goto failed;
89                 }
90                 mods[num_mods+1] = NULL;
91                 mods[num_mods]->mod_op = LDAP_MOD_BVALUES;
92                 if (use_flags) {
93                         switch (el->flags & LDB_FLAG_MOD_MASK) {
94                         case LDB_FLAG_MOD_ADD:
95                                 mods[num_mods]->mod_op |= LDAP_MOD_ADD;
96                                 break;
97                         case LDB_FLAG_MOD_DELETE:
98                                 mods[num_mods]->mod_op |= LDAP_MOD_DELETE;
99                                 break;
100                         case LDB_FLAG_MOD_REPLACE:
101                                 mods[num_mods]->mod_op |= LDAP_MOD_REPLACE;
102                                 break;
103                         }
104                 }
105                 mods[num_mods]->mod_type = discard_const_p(char, el->name);
106                 mods[num_mods]->mod_vals.modv_bvals = talloc_array(mods[num_mods], 
107                                                                    struct berval *,
108                                                                    1+el->num_values);
109                 if (!mods[num_mods]->mod_vals.modv_bvals) {
110                         goto failed;
111                 }
112
113                 for (j=0;j<el->num_values;j++) {
114                         mods[num_mods]->mod_vals.modv_bvals[j] = talloc(mods[num_mods]->mod_vals.modv_bvals,
115                                                                         struct berval);
116                         if (!mods[num_mods]->mod_vals.modv_bvals[j]) {
117                                 goto failed;
118                         }
119                         mods[num_mods]->mod_vals.modv_bvals[j]->bv_val = el->values[j].data;
120                         mods[num_mods]->mod_vals.modv_bvals[j]->bv_len = el->values[j].length;
121                 }
122                 mods[num_mods]->mod_vals.modv_bvals[j] = NULL;
123                 num_mods++;
124         }
125
126         return mods;
127
128 failed:
129         talloc_free(mods);
130         return NULL;
131 }
132
133 /*
134   add a single set of ldap message values to a ldb_message
135 */
136 static int lldb_add_msg_attr(struct ldb_context *ldb,
137                              struct ldb_message *msg, 
138                              const char *attr, struct berval **bval)
139 {
140         int count, i;
141         struct ldb_message_element *el;
142
143         count = ldap_count_values_len(bval);
144
145         if (count <= 0) {
146                 return -1;
147         }
148
149         el = talloc_realloc(msg, msg->elements, struct ldb_message_element, 
150                               msg->num_elements + 1);
151         if (!el) {
152                 errno = ENOMEM;
153                 return -1;
154         }
155
156         msg->elements = el;
157
158         el = &msg->elements[msg->num_elements];
159
160         el->name = talloc_strdup(msg->elements, attr);
161         if (!el->name) {
162                 errno = ENOMEM;
163                 return -1;
164         }
165         el->flags = 0;
166
167         el->num_values = 0;
168         el->values = talloc_array(msg->elements, struct ldb_val, count);
169         if (!el->values) {
170                 errno = ENOMEM;
171                 return -1;
172         }
173
174         for (i=0;i<count;i++) {
175                 /* we have to ensure this is null terminated so that
176                    ldb_msg_find_attr_as_string() can work */
177                 el->values[i].data = talloc_size(el->values, bval[i]->bv_len+1);
178                 if (!el->values[i].data) {
179                         errno = ENOMEM;
180                         return -1;
181                 }
182                 memcpy(el->values[i].data, bval[i]->bv_val, bval[i]->bv_len);
183                 el->values[i].data[bval[i]->bv_len] = 0;
184                 el->values[i].length = bval[i]->bv_len;
185                 el->num_values++;
186         }
187
188         msg->num_elements++;
189
190         return 0;
191 }
192
193 /*
194   search for matching records
195 */
196 static int lldb_search(struct lldb_context *lldb_ac)
197 {
198         struct lldb_private *lldb = lldb_ac->lldb;
199         struct ldb_module *module = lldb_ac->module;
200         struct ldb_request *req = lldb_ac->req;
201         struct timeval tv;
202         int ldap_scope;
203         char *search_base;
204         char *expression;
205         int ret;
206
207         if (!req->callback || !req->context) {
208                 ldb_set_errstring(module->ldb, "Async interface called with NULL callback function or NULL context");
209                 return LDB_ERR_OPERATIONS_ERROR;
210         }
211
212         if (req->op.search.tree == NULL) {
213                 ldb_set_errstring(module->ldb, "Invalid expression parse tree");
214                 return LDB_ERR_OPERATIONS_ERROR;
215         }
216
217         if (req->controls != NULL) {
218                 ldb_debug(module->ldb, LDB_DEBUG_WARNING, "Controls are not yet supported by ldb_ldap backend!\n");
219         }
220
221         req->handle->state = LDB_ASYNC_PENDING;
222
223         search_base = ldb_dn_alloc_linearized(lldb_ac, req->op.search.base);
224         if (req->op.search.base == NULL) {
225                 search_base = talloc_strdup(lldb_ac, "");
226         }
227         if (search_base == NULL) {
228                 return LDB_ERR_OPERATIONS_ERROR;
229         }
230
231         expression = ldb_filter_from_tree(lldb_ac, req->op.search.tree);
232         if (expression == NULL) {
233                 return LDB_ERR_OPERATIONS_ERROR;
234         }
235
236         switch (req->op.search.scope) {
237         case LDB_SCOPE_BASE:
238                 ldap_scope = LDAP_SCOPE_BASE;
239                 break;
240         case LDB_SCOPE_ONELEVEL:
241                 ldap_scope = LDAP_SCOPE_ONELEVEL;
242                 break;
243         default:
244                 ldap_scope = LDAP_SCOPE_SUBTREE;
245                 break;
246         }
247
248         tv.tv_sec = req->timeout;
249         tv.tv_usec = 0;
250
251         ret = ldap_search_ext(lldb->ldap, search_base, ldap_scope, 
252                             expression, 
253                             discard_const_p(char *, req->op.search.attrs), 
254                             0,
255                             NULL,
256                             NULL,
257                             &tv,
258                             LDAP_NO_LIMIT,
259                             &lldb_ac->msgid);
260
261         if (ret != LDAP_SUCCESS) {
262                 ldb_set_errstring(module->ldb, ldap_err2string(ret));
263         }
264
265         return lldb_ldap_to_ldb(ret);
266 }
267
268 /*
269   add a record
270 */
271 static int lldb_add(struct lldb_context *lldb_ac)
272 {
273         struct lldb_private *lldb = lldb_ac->lldb;
274         struct ldb_module *module = lldb_ac->module;
275         struct ldb_request *req = lldb_ac->req;
276         LDAPMod **mods;
277         char *dn;
278         int ret;
279
280         req->handle->state = LDB_ASYNC_PENDING;
281
282         mods = lldb_msg_to_mods(lldb_ac, req->op.add.message, 0);
283         if (mods == NULL) {
284                 return LDB_ERR_OPERATIONS_ERROR;
285         }
286
287         dn = ldb_dn_alloc_linearized(lldb_ac, req->op.add.message->dn);
288         if (dn == NULL) {
289                 return LDB_ERR_OPERATIONS_ERROR;
290         }
291
292         ret = ldap_add_ext(lldb->ldap, dn, mods,
293                            NULL,
294                            NULL,
295                            &lldb_ac->msgid);
296
297         if (ret != LDAP_SUCCESS) {
298                 ldb_set_errstring(module->ldb, ldap_err2string(ret));
299         }
300
301         return lldb_ldap_to_ldb(ret);
302 }
303
304 /*
305   modify a record
306 */
307 static int lldb_modify(struct lldb_context *lldb_ac)
308 {
309         struct lldb_private *lldb = lldb_ac->lldb;
310         struct ldb_module *module = lldb_ac->module;
311         struct ldb_request *req = lldb_ac->req;
312         LDAPMod **mods;
313         char *dn;
314         int ret;
315
316         req->handle->state = LDB_ASYNC_PENDING;
317
318         mods = lldb_msg_to_mods(lldb_ac, req->op.mod.message, 1);
319         if (mods == NULL) {
320                 return LDB_ERR_OPERATIONS_ERROR;
321         }
322
323         dn = ldb_dn_alloc_linearized(lldb_ac, req->op.mod.message->dn);
324         if (dn == NULL) {
325                 return LDB_ERR_OPERATIONS_ERROR;
326         }
327
328         ret = ldap_modify_ext(lldb->ldap, dn, mods,
329                               NULL,
330                               NULL,
331                               &lldb_ac->msgid);
332
333         if (ret != LDAP_SUCCESS) {
334                 ldb_set_errstring(module->ldb, ldap_err2string(ret));
335         }
336
337         return lldb_ldap_to_ldb(ret);
338 }
339
340 /*
341   delete a record
342 */
343 static int lldb_delete(struct lldb_context *lldb_ac)
344 {
345         struct lldb_private *lldb = lldb_ac->lldb;
346         struct ldb_module *module = lldb_ac->module;
347         struct ldb_request *req = lldb_ac->req;
348         char *dnstr;
349         int ret;
350
351         req->handle->state = LDB_ASYNC_PENDING;
352
353         dnstr = ldb_dn_alloc_linearized(lldb_ac, req->op.del.dn);
354
355         ret = ldap_delete_ext(lldb->ldap, dnstr,
356                               NULL,
357                               NULL,
358                               &lldb_ac->msgid);
359
360         if (ret != LDAP_SUCCESS) {
361                 ldb_set_errstring(module->ldb, ldap_err2string(ret));
362         }
363
364         return lldb_ldap_to_ldb(ret);
365 }
366
367 /*
368   rename a record
369 */
370 static int lldb_rename(struct lldb_context *lldb_ac)
371 {
372         struct lldb_private *lldb = lldb_ac->lldb;
373         struct ldb_module *module = lldb_ac->module;
374         struct ldb_request *req = lldb_ac->req;
375         char *old_dn;
376         char *newrdn;
377         char *parentdn;
378         int ret;
379
380         req->handle->state = LDB_ASYNC_PENDING;
381
382         old_dn = ldb_dn_alloc_linearized(lldb_ac, req->op.rename.olddn);
383         if (old_dn == NULL) {
384                 return LDB_ERR_OPERATIONS_ERROR;
385         }
386
387         newrdn = talloc_asprintf(lldb_ac, "%s=%s",
388                                  ldb_dn_get_rdn_name(req->op.rename.newdn),
389                                  ldb_dn_escape_value(lldb, *(ldb_dn_get_rdn_val(req->op.rename.newdn))));
390         if (!newrdn) {
391                 return LDB_ERR_OPERATIONS_ERROR;
392         }
393
394         parentdn = ldb_dn_alloc_linearized(lldb_ac, ldb_dn_get_parent(lldb_ac, req->op.rename.newdn));
395         if (!parentdn) {
396                 return LDB_ERR_OPERATIONS_ERROR;
397         }
398
399         ret = ldap_rename(lldb->ldap, old_dn, newrdn, parentdn,
400                           1, NULL, NULL,
401                           &lldb_ac->msgid);
402
403         if (ret != LDAP_SUCCESS) {
404                 ldb_set_errstring(module->ldb, ldap_err2string(ret));
405         }
406
407         return lldb_ldap_to_ldb(ret);
408 }
409
410 static int lldb_start_trans(struct ldb_module *module)
411 {
412         /* TODO implement a local transaction mechanism here */
413
414         return LDB_SUCCESS;
415 }
416
417 static int lldb_end_trans(struct ldb_module *module)
418 {
419         /* TODO implement a local transaction mechanism here */
420
421         return LDB_SUCCESS;
422 }
423
424 static int lldb_del_trans(struct ldb_module *module)
425 {
426         /* TODO implement a local transaction mechanism here */
427
428         return LDB_SUCCESS;
429 }
430
431 void lldb_request_done(struct ldb_request *req,
432                         struct ldb_control **ctrls, int error)
433 {
434         struct ldb_reply *ares;
435
436         ares = talloc_zero(req, struct ldb_reply);
437         if (!ares) {
438                 ldb_oom(req->handle->ldb);
439                 req->callback(req, NULL);
440                 return;
441         }
442         ares->type = LDB_REPLY_DONE;
443         ares->controls = talloc_steal(ares, ctrls);
444         ares->error = error;
445
446         req->callback(req, ares);
447 }
448
449 /* return false if the request is still in progress
450  * return true if the request is completed
451  */
452 static bool lldb_parse_result(struct lldb_context *ac, LDAPMessage *result)
453 {
454         struct lldb_private *lldb = ac->lldb;
455         LDAPControl **serverctrlsp = NULL;
456         char **referralsp = NULL;
457         char *matcheddnp = NULL;
458         char *errmsgp = NULL;
459         LDAPMessage *msg;
460         int type;
461         struct ldb_message *ldbmsg;
462         char *referral;
463         bool callback_failed;
464         bool request_done;
465         bool lret;
466         int ret;
467         int i;
468
469         type = ldap_msgtype(result);
470         callback_failed = false;
471         request_done = false;
472
473         switch (type) {
474         case LDAP_RES_SEARCH_ENTRY:
475
476                 msg = ldap_first_entry(lldb->ldap, result);
477                 if (msg != NULL) {
478                         BerElement *berptr = NULL;
479                         char *attr, *dn;
480
481                         ldbmsg = ldb_msg_new(ac);
482                         if (!ldbmsg) {
483                                 ret = LDB_ERR_OPERATIONS_ERROR;
484                                 break;
485                         }
486
487                         dn = ldap_get_dn(lldb->ldap, msg);
488                         if (!dn) {
489                                 talloc_free(ldbmsg);
490                                 ret = LDB_ERR_OPERATIONS_ERROR;
491                                 break;
492                         }
493                         ldbmsg->dn = ldb_dn_new(ldbmsg, ac->module->ldb, dn);
494                         if ( ! ldb_dn_validate(ldbmsg->dn)) {
495                                 talloc_free(ldbmsg);
496                                 ret = LDB_ERR_OPERATIONS_ERROR;
497                                 break;
498                         }
499                         ldap_memfree(dn);
500
501                         ldbmsg->num_elements = 0;
502                         ldbmsg->elements = NULL;
503
504                         /* loop over all attributes */
505                         for (attr=ldap_first_attribute(lldb->ldap, msg, &berptr);
506                              attr;
507                              attr=ldap_next_attribute(lldb->ldap, msg, berptr)) {
508                                 struct berval **bval;
509                                 bval = ldap_get_values_len(lldb->ldap, msg, attr);
510
511                                 if (bval) {
512                                         lldb_add_msg_attr(ac->module->ldb, ldbmsg, attr, bval);
513                                         ldap_value_free_len(bval);
514                                 }
515                         }
516                         if (berptr) ber_free(berptr, 0);
517
518                         ret = ldb_module_send_entry(ac->req, ldbmsg, NULL /* controls not yet supported */);
519                         if (ret != LDB_SUCCESS) {
520
521                                 callback_failed = true;
522                         }
523                 } else {
524                         ret = LDB_ERR_OPERATIONS_ERROR;
525                 }
526                 break;
527
528         case LDAP_RES_SEARCH_REFERENCE:
529
530                 if (ldap_parse_result(lldb->ldap, result, &ret,
531                                         &matcheddnp, &errmsgp,
532                                         &referralsp, &serverctrlsp, 0) != LDAP_SUCCESS) {
533                         ret = LDB_ERR_OPERATIONS_ERROR;
534                 }
535                 if (ret != LDB_SUCCESS) {
536                         break;
537                 }
538                 if (referralsp == NULL) {
539                         ret = LDB_ERR_PROTOCOL_ERROR;
540                         break;
541                 }
542
543                 for (i = 0; referralsp[i]; i++) {
544                         referral = talloc_strdup(ac, referralsp[i]);
545
546                         ret = ldb_module_send_referral(ac->req, referral);
547                         if (ret != LDB_SUCCESS) {
548                                 callback_failed = true;
549                                 break;
550                         }
551                 }
552                 break;
553
554         case LDAP_RES_SEARCH_RESULT:
555         case LDAP_RES_MODIFY:
556         case LDAP_RES_ADD:
557         case LDAP_RES_DELETE:
558         case LDAP_RES_MODDN:
559
560                 if (ldap_parse_result(lldb->ldap, result, &ret,
561                                         &matcheddnp, &errmsgp,
562                                         &referralsp, &serverctrlsp, 0) != LDAP_SUCCESS) {
563                         ret = LDB_ERR_OPERATIONS_ERROR;
564                 }
565                 if (ret != LDB_SUCCESS) {
566                         break;
567                 }
568
569                 if (serverctrlsp != NULL) {
570                         /* FIXME: transform the LDAPControl list into an ldb_control one */
571                         ac->controls = NULL;
572                 }
573
574                 request_done = true;
575                 break;
576
577         default:
578                 ret = LDB_ERR_PROTOCOL_ERROR;
579                 break;
580         }
581
582         if (ret != LDB_SUCCESS) {
583
584                 /* if the callback failed the caller will have freed the
585                  * request. Just return and don't try to use it */
586                 if (callback_failed) {
587
588                         /* tell lldb_wait to remove the request from the
589                          *  queue */
590                         lret = true;
591                         goto free_and_return;
592                 }
593
594                 request_done = true;
595         }
596
597         if (request_done) {
598                 lldb_request_done(ac->req, ac->controls, ret);
599                 lret = true;
600                 goto free_and_return;
601         }
602
603         lret = false;
604
605 free_and_return:
606
607         if (matcheddnp) ldap_memfree(matcheddnp);
608         if (errmsgp && *errmsgp) {
609                 ldb_set_errstring(ac->module->ldb, errmsgp);
610         }
611         if (errmsgp) {
612                 ldap_memfree(errmsgp);
613         }
614         if (referralsp) ldap_value_free(referralsp);
615         if (serverctrlsp) ldap_controls_free(serverctrlsp);
616
617         ldap_msgfree(result);
618
619         return lret;
620 }
621
622 static void lldb_timeout(struct tevent_context *ev,
623                          struct tevent_timer *te,
624                          struct timeval t,
625                          void *private_data)
626 {
627         struct lldb_context *ac;
628         ac = talloc_get_type(private_data, struct lldb_context);
629
630         lldb_request_done(ac->req, NULL, LDB_ERR_TIME_LIMIT_EXCEEDED);
631 }
632
633 static void lldb_callback(struct tevent_context *ev,
634                           struct tevent_timer *te,
635                           struct timeval t,
636                           void *private_data)
637 {
638         struct lldb_context *ac;
639         struct tevent_timer *lte;
640         struct timeval tv;
641         LDAPMessage *result;
642         int lret;
643
644         ac = talloc_get_type(private_data, struct lldb_context);
645
646         if (!ac->msgid) {
647                 lldb_request_done(ac->req, NULL, LDB_ERR_OPERATIONS_ERROR);
648                 return;
649         }
650
651         tv.tv_sec = 0;
652         tv.tv_usec = 0;
653         lret = ldap_result(ac->lldb->ldap, ac->msgid, 0, &tv, &result);
654         if (lret == 0) {
655                 goto respin;
656         }
657         if (lret == -1) {
658                 lldb_request_done(ac->req, NULL, LDB_ERR_OPERATIONS_ERROR);
659                 return;
660         }
661
662         if ( ! lldb_parse_result(ac, result)) {
663                 goto respin;
664         }
665
666         return;
667
668 respin:
669         tv.tv_sec = 0;
670         tv.tv_usec = 100;
671         lte = event_add_timed(ev, ac, tv, lldb_callback, ac);
672         if (NULL == lte) {
673                 lldb_request_done(ac->req, NULL, LDB_ERR_OPERATIONS_ERROR);
674         }
675 }
676
677 static bool lldb_dn_is_special(struct ldb_request *req)
678 {
679         struct ldb_dn *dn = NULL;
680
681         switch (req->operation) {
682         case LDB_ADD:
683                 dn = req->op.add.message->dn;
684                 break;
685         case LDB_MODIFY:
686                 dn = req->op.mod.message->dn;
687                 break;
688         case LDB_DELETE:
689                 dn = req->op.del.dn;
690                 break;
691         case LDB_RENAME:
692                 dn = req->op.rename.olddn;
693                 break;
694         default:
695                 break;
696         }
697
698         if (dn && ldb_dn_is_special(dn)) {
699                 return true;
700         }
701         return false;
702 }
703
704 static void lldb_auto_done_callback(struct tevent_context *ev,
705                                     struct tevent_timer *te,
706                                     struct timeval t,
707                                     void *private_data)
708 {
709         struct lldb_context *ac;
710
711         ac = talloc_get_type(private_data, struct lldb_context);
712         lldb_request_done(ac->req, NULL, LDB_SUCCESS);
713 }
714
715 static int lldb_handle_request(struct ldb_module *module, struct ldb_request *req)
716 {
717         struct lldb_private *lldb;
718         struct lldb_context *ac;
719         struct tevent_context *ev;
720         struct tevent_timer *te;
721         struct timeval tv;
722         int ret;
723
724         lldb = talloc_get_type(module->private_data, struct lldb_private);
725
726         if (req->starttime == 0 || req->timeout == 0) {
727                 ldb_set_errstring(module->ldb, "Invalid timeout settings");
728                 return LDB_ERR_TIME_LIMIT_EXCEEDED;
729         }
730
731         ev = ldb_get_event_context(module->ldb);
732         if (NULL == ev) {
733                 return LDB_ERR_OPERATIONS_ERROR;
734         }
735
736         ac = talloc_zero(module->ldb, struct lldb_context);
737         if (ac == NULL) {
738                 ldb_set_errstring(module->ldb, "Out of Memory");
739                 return LDB_ERR_OPERATIONS_ERROR;
740         }
741
742         ac->module = module;
743         ac->req = req;
744         ac->lldb = lldb;
745         ac->msgid = 0;
746
747         if (lldb_dn_is_special(req)) {
748                 tv.tv_sec = 0;
749                 tv.tv_usec = 0;
750                 te = event_add_timed(ev, ac, tv,
751                                      lldb_auto_done_callback, ac);
752                 if (NULL == te) {
753                         return LDB_ERR_OPERATIONS_ERROR;
754                 }
755
756                 return LDB_SUCCESS;
757         }
758
759         switch (ac->req->operation) {
760         case LDB_SEARCH:
761                 ret = lldb_search(ac);
762                 break;
763         case LDB_ADD:
764                 ret = lldb_add(ac);
765                 break;
766         case LDB_MODIFY:
767                 ret = lldb_modify(ac);
768                 break;
769         case LDB_DELETE:
770                 ret = lldb_delete(ac);
771                 break;
772         case LDB_RENAME:
773                 ret = lldb_rename(ac);
774                 break;
775         default:
776                 /* no other op supported */
777                 ret = LDB_ERR_OPERATIONS_ERROR;
778                 break;
779         }
780
781         if (ret != LDB_SUCCESS) {
782                 lldb_request_done(req, NULL, ret);
783                 return ret;
784         }
785
786         tv.tv_sec = 0;
787         tv.tv_usec = 0;
788         te = event_add_timed(ev, ac, tv, lldb_callback, ac);
789         if (NULL == te) {
790                 return LDB_ERR_OPERATIONS_ERROR;
791         }
792
793
794         tv.tv_sec = req->starttime + req->timeout;
795         tv.tv_usec = 0;
796         te = event_add_timed(ev, ac, tv, lldb_timeout, ac);
797         if (NULL == te) {
798                 return LDB_ERR_OPERATIONS_ERROR;
799         }
800
801         return LDB_SUCCESS;
802 }
803
804 static const struct ldb_module_ops lldb_ops = {
805         .name              = "ldap",
806         .search            = lldb_handle_request,
807         .add               = lldb_handle_request,
808         .modify            = lldb_handle_request,
809         .del               = lldb_handle_request,
810         .rename            = lldb_handle_request,
811         .request           = lldb_handle_request,
812         .start_transaction = lldb_start_trans,
813         .end_transaction   = lldb_end_trans,
814         .del_transaction   = lldb_del_trans,
815 };
816
817
818 static int lldb_destructor(struct lldb_private *lldb)
819 {
820         ldap_unbind(lldb->ldap);
821         return 0;
822 }
823
824 /*
825   connect to the database
826 */
827 static int lldb_connect(struct ldb_context *ldb,
828                         const char *url,
829                         unsigned int flags,
830                         const char *options[],
831                         struct ldb_module **_module)
832 {
833         struct ldb_module *module;
834         struct lldb_private *lldb;
835         int version = 3;
836         int ret;
837
838         module = talloc(ldb, struct ldb_module);
839         if (module == NULL) {
840                 ldb_oom(ldb);
841                 talloc_free(lldb);
842                 return -1;
843         }
844         talloc_set_name_const(module, "ldb_ldap backend");
845         module->ldb             = ldb;
846         module->prev            = module->next = NULL;
847         module->ops             = &lldb_ops;
848
849         lldb = talloc(module, struct lldb_private);
850         if (!lldb) {
851                 ldb_oom(ldb);
852                 goto failed;
853         }
854         module->private_data    = lldb;
855         lldb->ldap              = NULL;
856
857         ret = ldap_initialize(&lldb->ldap, url);
858         if (ret != LDAP_SUCCESS) {
859                 ldb_debug(ldb, LDB_DEBUG_FATAL, "ldap_initialize failed for URL '%s' - %s\n",
860                           url, ldap_err2string(ret));
861                 goto failed;
862         }
863
864         talloc_set_destructor(lldb, lldb_destructor);
865
866         ret = ldap_set_option(lldb->ldap, LDAP_OPT_PROTOCOL_VERSION, &version);
867         if (ret != LDAP_SUCCESS) {
868                 ldb_debug(ldb, LDB_DEBUG_FATAL, "ldap_set_option failed - %s\n",
869                           ldap_err2string(ret));
870                 goto failed;
871         }
872
873         *_module = module;
874         return 0;
875
876 failed:
877         talloc_free(module);
878         return -1;
879 }
880
881 const struct ldb_backend_ops ldb_ldap_backend_ops = {
882         .name = "ldap",
883         .connect_fn = lldb_connect
884 };
885
886 const struct ldb_backend_ops ldb_ldapi_backend_ops = {
887         .name = "ldapi",
888         .connect_fn = lldb_connect
889 };
890
891 const struct ldb_backend_ops ldb_ldaps_backend_ops = {
892         .name = "ldaps",
893         .connect_fn = lldb_connect
894 };