r13996: simplify ldb_async_wait() some more
[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 2 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, write to the Free Software
23    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
24 */
25
26 /*
27  *  Name: ldb_ldap
28  *
29  *  Component: ldb ldap backend
30  *
31  *  Description: core files for LDAP backend
32  *
33  *  Author: Andrew Tridgell
34  *
35  *  Modifications:
36  *
37  *  - description: make the module use asyncronous calls
38  *    date: Feb 2006
39  *    author: Simo Sorce
40  */
41
42 #include "includes.h"
43 #include "ldb/include/includes.h"
44
45 #include <ldap.h>
46
47 struct lldb_private {
48         LDAP *ldap;
49         int timeout;
50 };
51
52 struct lldb_async_context {
53         struct ldb_module *module;
54         int msgid;
55         int timeout;
56         void *context;
57         int (*callback)(struct ldb_context *, void *, struct ldb_async_result *);
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 static struct ldb_async_handle *init_handle(struct lldb_private *lldb, struct ldb_module *module,
66                                             void *context,
67                                             int (*callback)(struct ldb_context *, void *, struct ldb_async_result *),
68                                             int timeout)
69 {
70         struct lldb_async_context *ac;
71         struct ldb_async_handle *h;
72
73         h = talloc_zero(lldb, struct ldb_async_handle);
74         if (h == NULL) {
75                 ldb_set_errstring(module->ldb, talloc_asprintf(module, "Out of Memory"));
76                 return NULL;
77         }
78
79         h->module = module;
80
81         ac = talloc(h, struct lldb_async_context);
82         if (ac == NULL) {
83                 ldb_set_errstring(module->ldb, talloc_asprintf(module, "Out of Memory"));
84                 talloc_free(h);
85                 return NULL;
86         }
87
88         h->private_data = (void *)ac;
89
90         ac->module = module;
91         ac->context = context;
92         ac->callback = callback;
93         ac->timeout = timeout;
94         ac->msgid = 0;
95
96         return h;
97 }
98 /*
99   convert a ldb_message structure to a list of LDAPMod structures
100   ready for ldap_add() or ldap_modify()
101 */
102 static LDAPMod **lldb_msg_to_mods(void *mem_ctx, const struct ldb_message *msg, int use_flags)
103 {
104         LDAPMod **mods;
105         unsigned int i, j;
106         int num_mods = 0;
107
108         /* allocate maximum number of elements needed */
109         mods = talloc_array(mem_ctx, LDAPMod *, msg->num_elements+1);
110         if (!mods) {
111                 errno = ENOMEM;
112                 return NULL;
113         }
114         mods[0] = NULL;
115
116         for (i=0;i<msg->num_elements;i++) {
117                 const struct ldb_message_element *el = &msg->elements[i];
118
119                 mods[num_mods] = talloc(mods, LDAPMod);
120                 if (!mods[num_mods]) {
121                         goto failed;
122                 }
123                 mods[num_mods+1] = NULL;
124                 mods[num_mods]->mod_op = LDAP_MOD_BVALUES;
125                 if (use_flags) {
126                         switch (el->flags & LDB_FLAG_MOD_MASK) {
127                         case LDB_FLAG_MOD_ADD:
128                                 mods[num_mods]->mod_op |= LDAP_MOD_ADD;
129                                 break;
130                         case LDB_FLAG_MOD_DELETE:
131                                 mods[num_mods]->mod_op |= LDAP_MOD_DELETE;
132                                 break;
133                         case LDB_FLAG_MOD_REPLACE:
134                                 mods[num_mods]->mod_op |= LDAP_MOD_REPLACE;
135                                 break;
136                         }
137                 }
138                 mods[num_mods]->mod_type = discard_const_p(char, el->name);
139                 mods[num_mods]->mod_vals.modv_bvals = talloc_array(mods[num_mods], 
140                                                                    struct berval *,
141                                                                    1+el->num_values);
142                 if (!mods[num_mods]->mod_vals.modv_bvals) {
143                         goto failed;
144                 }
145
146                 for (j=0;j<el->num_values;j++) {
147                         mods[num_mods]->mod_vals.modv_bvals[j] = talloc(mods[num_mods]->mod_vals.modv_bvals,
148                                                                         struct berval);
149                         if (!mods[num_mods]->mod_vals.modv_bvals[j]) {
150                                 goto failed;
151                         }
152                         mods[num_mods]->mod_vals.modv_bvals[j]->bv_val = el->values[j].data;
153                         mods[num_mods]->mod_vals.modv_bvals[j]->bv_len = el->values[j].length;
154                 }
155                 mods[num_mods]->mod_vals.modv_bvals[j] = NULL;
156                 num_mods++;
157         }
158
159         return mods;
160
161 failed:
162         talloc_free(mods);
163         return NULL;
164 }
165
166 /*
167   add a single set of ldap message values to a ldb_message
168 */
169 static int lldb_add_msg_attr(struct ldb_context *ldb,
170                              struct ldb_message *msg, 
171                              const char *attr, struct berval **bval)
172 {
173         int count, i;
174         struct ldb_message_element *el;
175
176         count = ldap_count_values_len(bval);
177
178         if (count <= 0) {
179                 return -1;
180         }
181
182         el = talloc_realloc(msg, msg->elements, struct ldb_message_element, 
183                               msg->num_elements + 1);
184         if (!el) {
185                 errno = ENOMEM;
186                 return -1;
187         }
188
189         msg->elements = el;
190
191         el = &msg->elements[msg->num_elements];
192
193         el->name = talloc_strdup(msg->elements, attr);
194         if (!el->name) {
195                 errno = ENOMEM;
196                 return -1;
197         }
198         el->flags = 0;
199
200         el->num_values = 0;
201         el->values = talloc_array(msg->elements, struct ldb_val, count);
202         if (!el->values) {
203                 errno = ENOMEM;
204                 return -1;
205         }
206
207         for (i=0;i<count;i++) {
208                 el->values[i].data = talloc_memdup(el->values, bval[i]->bv_val, bval[i]->bv_len);
209                 if (!el->values[i].data) {
210                         return -1;
211                 }
212                 el->values[i].length = bval[i]->bv_len;
213                 el->num_values++;
214         }
215
216         msg->num_elements++;
217
218         return 0;
219 }
220
221 /*
222   search for matching records
223 */
224 static int lldb_search_async(struct ldb_module *module, const struct ldb_dn *base,
225                               enum ldb_scope scope, struct ldb_parse_tree *tree,
226                               const char * const *attrs,
227                               struct ldb_control **control_req,
228                               void *context,
229                               int (*callback)(struct ldb_context *, void *, struct ldb_async_result *),
230                               int timeout,
231                               struct ldb_async_handle **handle)
232 {
233         struct lldb_private *lldb = talloc_get_type(module->private_data, struct lldb_private);
234         struct lldb_async_context *lldb_ac;
235         struct timeval tv;
236         int ldap_scope;
237         char *search_base;
238         char *expression;
239         int ret;
240
241         if (!callback || !context) {
242                 ldb_set_errstring(module->ldb, talloc_asprintf(module, "Async interface called with NULL callback function or NULL context"));
243                 return LDB_ERR_OPERATIONS_ERROR;
244         }
245
246         if (tree == NULL) {
247                 ldb_set_errstring(module->ldb, talloc_asprintf(module, "Invalid expression parse tree"));
248                 return LDB_ERR_OPERATIONS_ERROR;
249         }
250
251         if (control_req != NULL) {
252                 ldb_debug(module->ldb, LDB_DEBUG_WARNING, "Controls are not yet supported by ldb_ldap backend!\n");
253         }
254
255         *handle = init_handle(lldb, module, context, callback, timeout);
256         if (*handle == NULL) {
257                 talloc_free(*handle);
258                 return LDB_ERR_OPERATIONS_ERROR;
259         }
260
261         lldb_ac = talloc_get_type((*handle)->private_data, struct lldb_async_context);
262
263         search_base = ldb_dn_linearize(lldb_ac, base);
264         if (base == NULL) {
265                 search_base = talloc_strdup(lldb_ac, "");
266         }
267         if (search_base == NULL) {
268                 talloc_free(*handle);
269                 return LDB_ERR_OPERATIONS_ERROR;
270         }
271
272         expression = ldb_filter_from_tree(lldb_ac, tree);
273         if (expression == NULL) {
274                 talloc_free(*handle);
275                 return LDB_ERR_OPERATIONS_ERROR;
276         }
277
278         switch (scope) {
279         case LDB_SCOPE_BASE:
280                 ldap_scope = LDAP_SCOPE_BASE;
281                 break;
282         case LDB_SCOPE_ONELEVEL:
283                 ldap_scope = LDAP_SCOPE_ONELEVEL;
284                 break;
285         default:
286                 ldap_scope = LDAP_SCOPE_SUBTREE;
287                 break;
288         }
289
290         tv.tv_sec = timeout;
291         tv.tv_usec = 0;
292
293         ret = ldap_search_ext(lldb->ldap, search_base, ldap_scope, 
294                             expression, 
295                             discard_const_p(char *, attrs), 
296                             0,
297                             NULL,
298                             NULL,
299                             &tv,
300                             LDAP_NO_LIMIT,
301                             &lldb_ac->msgid);
302
303         if (ret != LDAP_SUCCESS) {
304                 ldb_set_errstring(module->ldb, talloc_strdup(module, ldap_err2string(ret)));
305                 talloc_free(*handle);
306                 *handle = NULL;
307         }
308
309         return lldb_ldap_to_ldb(ret);
310 }
311
312 static int lldb_search_sync_callback(struct ldb_context *ldb, void *context, struct ldb_async_result *ares)
313 {
314         struct ldb_result *res;
315         int n;
316         
317         if (!context) {
318                 ldb_set_errstring(ldb, talloc_asprintf(ldb, "NULL Context in callback"));
319                 return LDB_ERR_OPERATIONS_ERROR;
320         }       
321
322         res = *((struct ldb_result **)context);
323
324         if (!res || !ares) {
325                 goto error;
326         }
327
328         if (ares->type == LDB_REPLY_ENTRY) {
329                 res->msgs = talloc_realloc(res, res->msgs, struct ldb_message *, res->count + 2);
330                 if (! res->msgs) {
331                         goto error;
332                 }
333
334                 res->msgs[res->count + 1] = NULL;
335
336                 res->msgs[res->count] = talloc_steal(res->msgs, ares->message);
337                 if (! res->msgs[res->count]) {
338                         goto error;
339                 }
340
341                 res->count++;
342         }
343
344         if (ares->type == LDB_REPLY_REFERRAL) {
345                 if (res->refs) {
346                         for (n = 0; res->refs[n]; n++) /*noop*/ ;
347                 } else {
348                         n = 0;
349                 }
350
351                 res->refs = talloc_realloc(res, res->refs, char *, n + 2);
352                 if (! res->refs) {
353                         goto error;
354                 }
355
356                 res->refs[n] = talloc_steal(res->refs, ares->referral);
357                 res->refs[n + 1] = NULL;
358         }
359
360         if (ares->type == LDB_REPLY_DONE) {
361                 if (ares->controls) {
362                         res->controls = talloc_steal(res, ares->controls);
363                         if (! res->controls) {
364                                 goto error;
365                         }
366                 }
367         }
368
369         talloc_free(ares);
370         return LDB_SUCCESS;
371
372 error:
373         talloc_free(ares);
374         talloc_free(res);
375         *((struct ldb_result **)context) = NULL;
376         return LDB_ERR_OPERATIONS_ERROR;
377 }
378
379 /*
380   search for matching records using a synchronous function
381  */
382 static int lldb_search_bytree(struct ldb_module *module, const struct ldb_dn *base,
383                               enum ldb_scope scope, struct ldb_parse_tree *tree,
384                               const char * const *attrs,
385                               struct ldb_control **control_req,
386                               struct ldb_result **res)
387 {
388         struct lldb_private *lldb = talloc_get_type(module->private_data, struct lldb_private);
389         struct ldb_async_handle *handle;
390         int ret;
391
392         *res = talloc_zero(lldb, struct ldb_result);
393         if (! *res) {
394                 return LDB_ERR_OPERATIONS_ERROR;
395         }
396
397         ret = lldb_search_async(module, base, scope, tree, attrs, control_req,
398                                 res, &lldb_search_sync_callback, lldb->timeout, &handle);
399
400         if (ret == LDB_SUCCESS) {
401                 ret = ldb_async_wait(handle, LDB_WAIT_ALL);
402                 talloc_free(handle);
403         }
404
405         if (ret != LDB_SUCCESS) {
406                 talloc_free(*res);
407         }
408
409         return ret;
410 }
411
412 /*
413   add a record
414 */
415 static int lldb_add_async(struct ldb_module *module, const struct ldb_message *msg,
416                           void *context,
417                           int (*callback)(struct ldb_context *, void *, struct ldb_async_result *),
418                           int timeout,
419                           struct ldb_async_handle **handle)
420 {
421         struct lldb_private *lldb = talloc_get_type(module->private_data, struct lldb_private);
422         struct lldb_async_context *lldb_ac;
423         LDAPMod **mods;
424         char *dn;
425         int ret;
426
427         /* ltdb specials should not reach this point */
428         if (ldb_dn_is_special(msg->dn)) {
429                 return LDB_ERR_INVALID_DN_SYNTAX;
430         }
431
432         *handle = init_handle(lldb, module, context, callback, timeout);
433         if (*handle == NULL) {
434                 return LDB_ERR_OPERATIONS_ERROR;
435         }
436
437         lldb_ac = talloc_get_type((*handle)->private_data, struct lldb_async_context);
438
439         mods = lldb_msg_to_mods(lldb_ac, msg, 0);
440         if (mods == NULL) {
441                 talloc_free(*handle);
442                 return LDB_ERR_OPERATIONS_ERROR;
443         }
444
445         dn = ldb_dn_linearize(lldb_ac, msg->dn);
446         if (dn == NULL) {
447                 talloc_free(*handle);
448                 return LDB_ERR_OPERATIONS_ERROR;
449         }
450
451         ret = ldap_add_ext(lldb->ldap, dn, mods,
452                            NULL,
453                            NULL,
454                            &lldb_ac->msgid);
455
456         if (ret != LDAP_SUCCESS) {
457                 ldb_set_errstring(module->ldb, talloc_strdup(module, ldap_err2string(ret)));
458                 talloc_free(*handle);
459         }
460
461         return lldb_ldap_to_ldb(ret);
462 }
463
464 static int lldb_add(struct ldb_module *module, const struct ldb_message *msg)
465 {
466         struct lldb_private *lldb = talloc_get_type(module->private_data, struct lldb_private);
467         struct ldb_async_handle *handle;
468         int ret;
469
470         /* ldap does not understand ltdb specials */
471         if (ldb_dn_is_special(msg->dn)) {
472                 return LDB_SUCCESS;
473         }
474
475         ret = lldb_add_async(module, msg, NULL, NULL, lldb->timeout, &handle);
476
477         if (ret != LDB_SUCCESS)
478                 return ret;
479
480         ret = ldb_async_wait(handle, LDB_WAIT_ALL);
481
482         talloc_free(handle);
483         return ret;
484 }
485
486
487 /*
488   modify a record
489 */
490 static int lldb_modify_async(struct ldb_module *module, const struct ldb_message *msg,
491                              void *context,
492                              int (*callback)(struct ldb_context *, void *, struct ldb_async_result *),
493                              int timeout,
494                              struct ldb_async_handle **handle)
495 {
496         struct lldb_private *lldb = talloc_get_type(module->private_data, struct lldb_private);
497         struct lldb_async_context *lldb_ac;
498         LDAPMod **mods;
499         char *dn;
500         int ret;
501
502         /* ltdb specials should not reach this point */
503         if (ldb_dn_is_special(msg->dn)) {
504                 return LDB_ERR_INVALID_DN_SYNTAX;
505         }
506
507         *handle = init_handle(lldb, module, context, callback, timeout);
508         if (*handle == NULL) {
509                 return LDB_ERR_OPERATIONS_ERROR;
510         }
511
512         lldb_ac = talloc_get_type((*handle)->private_data, struct lldb_async_context);
513
514         mods = lldb_msg_to_mods(lldb_ac, msg, 1);
515         if (mods == NULL) {
516                 talloc_free(*handle);
517                 return LDB_ERR_OPERATIONS_ERROR;
518         }
519
520         dn = ldb_dn_linearize(lldb_ac, msg->dn);
521         if (dn == NULL) {
522                 talloc_free(*handle);
523                 return LDB_ERR_OPERATIONS_ERROR;
524         }
525
526         ret = ldap_modify_ext(lldb->ldap, dn, mods,
527                               NULL,
528                               NULL,
529                               &lldb_ac->msgid);
530
531         if (ret != LDAP_SUCCESS) {
532                 ldb_set_errstring(module->ldb, talloc_strdup(module, ldap_err2string(ret)));
533                 talloc_free(*handle);
534         }
535
536         return lldb_ldap_to_ldb(ret);
537 }
538
539 static int lldb_modify(struct ldb_module *module, const struct ldb_message *msg)
540 {
541         struct lldb_private *lldb = talloc_get_type(module->private_data, struct lldb_private);
542         struct ldb_async_handle *handle;
543         int ret;
544
545         /* ldap does not understand ltdb specials */
546         if (ldb_dn_is_special(msg->dn)) {
547                 return LDB_SUCCESS;
548         }
549
550         ret = lldb_modify_async(module, msg, NULL, NULL, lldb->timeout, &handle);
551
552         if (ret != LDB_SUCCESS)
553                 return ret;
554
555         ret = ldb_async_wait(handle, LDB_WAIT_ALL);
556
557         talloc_free(handle);
558         return ret;
559 }
560
561 /*
562   delete a record
563 */
564 static int lldb_delete_async(struct ldb_module *module, const struct ldb_dn *dn,
565                              void *context,
566                              int (*callback)(struct ldb_context *, void *, struct ldb_async_result *),
567                              int timeout,
568                              struct ldb_async_handle **handle)
569 {
570         struct lldb_private *lldb = talloc_get_type(module->private_data, struct lldb_private);
571         struct lldb_async_context *lldb_ac;
572         char *dnstr;
573         int ret;
574         
575         /* ltdb specials should not reach this point */
576         if (ldb_dn_is_special(dn)) {
577                 return LDB_ERR_INVALID_DN_SYNTAX;
578         }
579
580         *handle = init_handle(lldb, module, context, callback, timeout);
581         if (*handle == NULL) {
582                 return LDB_ERR_OPERATIONS_ERROR;
583         }
584
585         lldb_ac = talloc_get_type((*handle)->private_data, struct lldb_async_context);
586
587         dnstr = ldb_dn_linearize(lldb_ac, dn);
588
589         ret = ldap_delete_ext(lldb->ldap, dnstr,
590                               NULL,
591                               NULL,
592                               &lldb_ac->msgid);
593
594         if (ret != LDAP_SUCCESS) {
595                 ldb_set_errstring(module->ldb, talloc_strdup(module, ldap_err2string(ret)));
596                 talloc_free(*handle);
597         }
598
599         return lldb_ldap_to_ldb(ret);
600 }
601
602 static int lldb_delete(struct ldb_module *module, const struct ldb_dn *dn)
603 {
604         struct lldb_private *lldb = talloc_get_type(module->private_data, struct lldb_private);
605         struct ldb_async_handle *handle;
606         int ret;
607
608         /* ignore ltdb specials */
609         if (ldb_dn_is_special(dn)) {
610                 return LDB_SUCCESS;
611         }
612
613         ret = lldb_delete_async(module, dn, NULL, NULL, lldb->timeout, &handle);
614
615         if (ret != LDB_SUCCESS)
616                 return ret;
617
618         ret = ldb_async_wait(handle, LDB_WAIT_ALL);
619
620         talloc_free(handle);
621         return ret;
622 }
623
624 /*
625   rename a record
626 */
627 static int lldb_rename_async(struct ldb_module *module,
628                              const struct ldb_dn *olddn, const struct ldb_dn *newdn,
629                              void *context,
630                              int (*callback)(struct ldb_context *, void *, struct ldb_async_result *),
631                              int timeout,
632                              struct ldb_async_handle **handle)
633 {
634         struct lldb_private *lldb = talloc_get_type(module->private_data, struct lldb_private);
635         struct lldb_async_context *lldb_ac;
636         char *old_dn;
637         char *newrdn;
638         char *parentdn;
639         int ret;
640         
641         /* ltdb specials should not reach this point */
642         if (ldb_dn_is_special(olddn) || ldb_dn_is_special(newdn)) {
643                 return LDB_ERR_INVALID_DN_SYNTAX;
644         }
645
646         *handle = init_handle(lldb, module, context, callback, timeout);
647         if (*handle == NULL) {
648                 return LDB_ERR_OPERATIONS_ERROR;
649         }
650
651         lldb_ac = talloc_get_type((*handle)->private_data, struct lldb_async_context);
652
653         old_dn = ldb_dn_linearize(lldb_ac, olddn);
654         if (old_dn == NULL) {
655                 talloc_free(*handle);
656                 return LDB_ERR_OPERATIONS_ERROR;
657         }
658
659         newrdn = talloc_asprintf(lldb_ac, "%s=%s",
660                                       newdn->components[0].name,
661                                       ldb_dn_escape_value(lldb, newdn->components[0].value));
662         if (!newrdn) {
663                 talloc_free(*handle);
664                 return LDB_ERR_OPERATIONS_ERROR;
665         }
666
667         parentdn = ldb_dn_linearize(lldb_ac, ldb_dn_get_parent(lldb_ac, newdn));
668         if (!parentdn) {
669                 talloc_free(*handle);
670                 return LDB_ERR_OPERATIONS_ERROR;
671         }
672
673         ret = ldap_rename(lldb->ldap, old_dn, newrdn, parentdn,
674                           1, NULL, NULL,
675                           &lldb_ac->msgid);
676
677         if (ret != LDAP_SUCCESS) {
678                 ldb_set_errstring(module->ldb, talloc_strdup(module, ldap_err2string(ret)));
679                 talloc_free(*handle);
680         }
681
682         return lldb_ldap_to_ldb(ret);
683 }
684
685 static int lldb_rename(struct ldb_module *module, const struct ldb_dn *olddn, const struct ldb_dn *newdn)
686 {
687         struct lldb_private *lldb = talloc_get_type(module->private_data, struct lldb_private);
688         struct ldb_async_handle *handle;
689         int ret;
690
691         /* ignore ltdb specials */
692         if (ldb_dn_is_special(olddn) || ldb_dn_is_special(newdn)) {
693                 return LDB_SUCCESS;
694         }
695
696         ret = lldb_rename_async(module, olddn, newdn, NULL, NULL, lldb->timeout, &handle);
697
698         if (ret != LDB_SUCCESS)
699                 return ret;
700
701         ret = ldb_async_wait(handle, LDB_WAIT_ALL);
702
703         talloc_free(handle);
704         return ret;
705 }
706
707 static int lldb_parse_result(struct ldb_async_handle *handle, LDAPMessage *result)
708 {
709         struct lldb_async_context *ac = talloc_get_type(handle->private_data, struct lldb_async_context);
710         struct lldb_private *lldb = talloc_get_type(ac->module->private_data, struct lldb_private);
711         struct ldb_async_result *ares = NULL;
712         LDAPMessage *msg;
713         int type;
714         char *matcheddnp = NULL;
715         char *errmsgp = NULL;
716         char **referralsp = NULL;
717         LDAPControl **serverctrlsp = NULL;
718         int ret;
719
720         type = ldap_msgtype(result);
721
722         switch (type) {
723
724         case LDAP_RES_SEARCH_ENTRY:
725                 msg = ldap_first_entry(lldb->ldap, result);
726                 if (msg != NULL) {
727                         BerElement *berptr = NULL;
728                         char *attr, *dn;
729
730                         ares = talloc_zero(ac, struct ldb_async_result);
731                         if (!ares) {
732                                 handle->status = LDB_ERR_OPERATIONS_ERROR;
733                                 goto error;
734                         }
735
736                         ares->message = ldb_msg_new(ares);
737                         if (!ares->message) {
738                                 handle->status = LDB_ERR_OPERATIONS_ERROR;
739                                 goto error;
740                         }
741
742                         dn = ldap_get_dn(lldb->ldap, msg);
743                         if (!dn) {
744                                 handle->status = LDB_ERR_OPERATIONS_ERROR;
745                                 goto error;
746                         }
747                         ares->message->dn = ldb_dn_explode_or_special(ares->message, dn);
748                         if (ares->message->dn == NULL) {
749                                 handle->status = LDB_ERR_OPERATIONS_ERROR;
750                                 goto error;
751                         }
752                         ldap_memfree(dn);
753
754                         ares->message->num_elements = 0;
755                         ares->message->elements = NULL;
756                         ares->message->private_data = NULL;
757
758                         /* loop over all attributes */
759                         for (attr=ldap_first_attribute(lldb->ldap, msg, &berptr);
760                              attr;
761                              attr=ldap_next_attribute(lldb->ldap, msg, berptr)) {
762                                 struct berval **bval;
763                                 bval = ldap_get_values_len(lldb->ldap, msg, attr);
764
765                                 if (bval) {
766                                         lldb_add_msg_attr(ac->module->ldb, ares->message, attr, bval);
767                                         ldap_value_free_len(bval);
768                                 }                                         
769                         }
770                         if (berptr) ber_free(berptr, 0);
771
772
773                         ares->type = LDB_REPLY_ENTRY;
774                         handle->state = LDB_ASYNC_PENDING;
775                         ret = ac->callback(ac->module->ldb, ac->context, ares);
776                         if (ret != LDB_SUCCESS) {
777                                 handle->status = ret;
778                         }
779                 } else {
780                         handle->status = LDB_ERR_PROTOCOL_ERROR;
781                         handle->state = LDB_ASYNC_DONE;
782                 }
783                 break;
784
785         case LDAP_RES_SEARCH_REFERENCE:
786                 if (ldap_parse_result(lldb->ldap, result, &handle->status,
787                                         &matcheddnp, &errmsgp,
788                                         &referralsp, &serverctrlsp, 1) != LDAP_SUCCESS) {
789                         handle->status = LDB_ERR_OPERATIONS_ERROR;
790                         goto error;
791                 }
792                 if (referralsp == NULL) {
793                         handle->status = LDB_ERR_PROTOCOL_ERROR;
794                         goto error;
795                 }
796
797                 ares = talloc_zero(ac, struct ldb_async_result);
798                 if (!ares) {
799                         handle->status = LDB_ERR_OPERATIONS_ERROR;
800                         goto error;
801                 }
802
803                 ares->referral = talloc_strdup(ares, *referralsp);
804                 ares->type = LDB_REPLY_REFERRAL;
805                 handle->state = LDB_ASYNC_PENDING;
806                 ret = ac->callback(ac->module->ldb, ac->context, ares);
807                 if (ret != LDB_SUCCESS) {
808                         handle->status = ret;
809                 }
810
811                 break;
812
813         case LDAP_RES_SEARCH_RESULT:
814                 if (ldap_parse_result(lldb->ldap, result, &handle->status,
815                                         &matcheddnp, &errmsgp,
816                                         &referralsp, &serverctrlsp, 1) != LDAP_SUCCESS) {
817                         handle->status = LDB_ERR_OPERATIONS_ERROR;
818                         goto error;
819                 }
820
821                 ares = talloc_zero(ac, struct ldb_async_result);
822                 if (!ares) {
823                         handle->status = LDB_ERR_OPERATIONS_ERROR;
824                         goto error;
825                 }
826
827                 if (serverctrlsp != NULL) {
828                         /* FIXME: transform the LDAPControl list into an ldb_control one */
829                         ares->controls = NULL;
830                 }
831                 
832                 ares->type = LDB_REPLY_DONE;
833                 handle->state = LDB_ASYNC_DONE;
834                 ret = ac->callback(ac->module->ldb, ac->context, ares);
835                 if (ret != LDB_SUCCESS) {
836                         handle->status = ret;
837                 }
838
839                 break;
840
841         case LDAP_RES_MODIFY:
842         case LDAP_RES_ADD:
843         case LDAP_RES_DELETE:
844         case LDAP_RES_MODDN:
845                 if (ldap_parse_result(lldb->ldap, result, &handle->status,
846                                         &matcheddnp, &errmsgp,
847                                         &referralsp, &serverctrlsp, 1) != LDAP_SUCCESS) {
848                         handle->status = LDB_ERR_OPERATIONS_ERROR;
849                         goto error;
850                 }
851                 if (ac->callback && handle->status == LDB_SUCCESS) {
852                         ares = NULL; /* FIXME: build a corresponding ares to pass on */
853                         handle->status = ac->callback(ac->module->ldb, ac->context, ares);
854                 }
855                 handle->state = LDB_ASYNC_DONE;
856                 break;
857
858         default:
859                 handle->status = LDB_ERR_PROTOCOL_ERROR;
860                 goto error;
861         }
862
863         if (matcheddnp) ldap_memfree(matcheddnp);
864         if (errmsgp) {
865                 ldb_set_errstring(ac->module->ldb, talloc_strdup(ac->module, errmsgp));
866                 ldap_memfree(errmsgp);
867         }
868         if (referralsp) ldap_value_free(referralsp);
869         if (serverctrlsp) ldap_controls_free(serverctrlsp);
870
871         ldap_msgfree(result);
872         return handle->status;
873
874 error:
875         handle->state = LDB_ASYNC_DONE;
876         ldap_msgfree(result);
877         return handle->status;
878 }
879
880 static int lldb_async_wait(struct ldb_async_handle *handle, enum ldb_async_wait_type type)
881 {
882         struct lldb_async_context *ac = talloc_get_type(handle->private_data, struct lldb_async_context);
883         struct lldb_private *lldb = talloc_get_type(handle->module->private_data, struct lldb_private);
884         struct timeval timeout;
885         LDAPMessage *result;
886         int ret = LDB_ERR_OPERATIONS_ERROR;
887
888         if (!ac->msgid) {
889                 return LDB_ERR_OPERATIONS_ERROR;
890         }
891
892         handle->status = LDB_SUCCESS;
893         handle->state = LDB_ASYNC_INIT;
894
895         switch(type) {
896         case LDB_WAIT_NONE:
897                 timeout.tv_sec = 0;
898                 timeout.tv_usec = 0;
899                 ret = ldap_result(lldb->ldap, ac->msgid, 0, &timeout, &result);
900                 if (ret == -1) {
901                         handle->status = LDB_ERR_OPERATIONS_ERROR;
902                         return handle->status;
903                 }
904                 if (ret == 0) {
905                         handle->status = LDB_SUCCESS;
906                         return handle->status;
907                 }
908                 ret = lldb_parse_result(handle, result);
909                 break;
910         case LDB_WAIT_ONCE:
911                 timeout.tv_sec = ac->timeout;
912                 timeout.tv_usec = 0;
913                 ret = ldap_result(lldb->ldap, ac->msgid, 0, &timeout, &result);
914                 if (ret == -1 || ret == 0) {
915                         handle->status = LDB_ERR_OPERATIONS_ERROR;
916                         return handle->status;
917                 }
918                 ret = lldb_parse_result(handle, result);
919                 break;
920         case LDB_WAIT_ALL:
921                 timeout.tv_sec = ac->timeout;
922                 timeout.tv_usec = 0;
923                 while (handle->status == LDB_SUCCESS && handle->state != LDB_ASYNC_DONE) {
924                         ret = ldap_result(lldb->ldap, ac->msgid, 0, &timeout, &result);
925                         if (ret == -1 || ret == 0) {
926                                 handle->status = LDB_ERR_OPERATIONS_ERROR;
927                                 return handle->status;
928                         }
929                         ret = lldb_parse_result(handle, result);
930                         if (ret != LDB_SUCCESS) {
931                                 return ret;
932                         }
933                 }
934                 break;
935         }
936
937         return ret;
938 }
939
940 static int lldb_start_trans(struct ldb_module *module)
941 {
942         /* TODO implement a local transaction mechanism here */
943
944         return 0;
945 }
946
947 static int lldb_end_trans(struct ldb_module *module)
948 {
949         /* TODO implement a local transaction mechanism here */
950
951         return 0;
952 }
953
954 static int lldb_del_trans(struct ldb_module *module)
955 {
956         /* TODO implement a local transaction mechanism here */
957
958         return 0;
959 }
960
961 static int lldb_request(struct ldb_module *module, struct ldb_request *req)
962 {
963         switch (req->operation) {
964
965         case LDB_REQ_SEARCH:
966                 return lldb_search_bytree(module,
967                                           req->op.search.base,
968                                           req->op.search.scope, 
969                                           req->op.search.tree, 
970                                           req->op.search.attrs, 
971                                           req->controls,
972                                           &req->op.search.res);
973
974         case LDB_REQ_ADD:
975                 return lldb_add(module, req->op.add.message);
976
977         case LDB_REQ_MODIFY:
978                 return lldb_modify(module, req->op.mod.message);
979
980         case LDB_REQ_DELETE:
981                 return lldb_delete(module, req->op.del.dn);
982
983         case LDB_REQ_RENAME:
984                 return lldb_rename(module,
985                                         req->op.rename.olddn,
986                                         req->op.rename.newdn);
987
988         case LDB_ASYNC_SEARCH:
989                 return lldb_search_async(module,
990                                         req->op.search.base,
991                                         req->op.search.scope, 
992                                         req->op.search.tree, 
993                                         req->op.search.attrs,
994                                         req->controls,
995                                         req->async.context,
996                                         req->async.callback,
997                                         req->async.timeout,
998                                         &req->async.handle);
999
1000         case LDB_ASYNC_ADD:
1001                 return lldb_add_async(module,
1002                                         req->op.add.message,
1003                                         req->async.context,
1004                                         req->async.callback,
1005                                         req->async.timeout,
1006                                         &req->async.handle);
1007
1008         case LDB_ASYNC_MODIFY:
1009                 return lldb_modify_async(module,
1010                                         req->op.mod.message,
1011                                         req->async.context,
1012                                         req->async.callback,
1013                                         req->async.timeout,
1014                                         &req->async.handle);
1015
1016         case LDB_ASYNC_DELETE:
1017                 return lldb_delete_async(module,
1018                                         req->op.del.dn,
1019                                         req->async.context,
1020                                         req->async.callback,
1021                                         req->async.timeout,
1022                                         &req->async.handle);
1023
1024         case LDB_ASYNC_RENAME:
1025                 return lldb_rename_async(module,
1026                                         req->op.rename.olddn,
1027                                         req->op.rename.newdn,
1028                                         req->async.context,
1029                                         req->async.callback,
1030                                         req->async.timeout,
1031                                         &req->async.handle);
1032
1033         default:
1034                 return -1;
1035
1036         }
1037 }
1038
1039 static const struct ldb_module_ops lldb_ops = {
1040         .name              = "ldap",
1041         .request           = lldb_request,
1042         .start_transaction = lldb_start_trans,
1043         .end_transaction   = lldb_end_trans,
1044         .del_transaction   = lldb_del_trans,
1045         .async_wait        = lldb_async_wait
1046 };
1047
1048
1049 static int lldb_destructor(void *p)
1050 {
1051         struct lldb_private *lldb = p;
1052         ldap_unbind(lldb->ldap);
1053         return 0;
1054 }
1055
1056 /*
1057   connect to the database
1058 */
1059 static int lldb_connect(struct ldb_context *ldb,
1060                  const char *url, 
1061                  unsigned int flags, 
1062                  const char *options[])
1063 {
1064         struct lldb_private *lldb = NULL;
1065         int version = 3;
1066         int ret;
1067
1068         lldb = talloc(ldb, struct lldb_private);
1069         if (!lldb) {
1070                 ldb_oom(ldb);
1071                 goto failed;
1072         }
1073
1074         lldb->ldap = NULL;
1075         lldb->timeout = 120; /* TODO: get timeout from options ? */
1076
1077         ret = ldap_initialize(&lldb->ldap, url);
1078         if (ret != LDAP_SUCCESS) {
1079                 ldb_debug(ldb, LDB_DEBUG_FATAL, "ldap_initialize failed for URL '%s' - %s\n",
1080                           url, ldap_err2string(ret));
1081                 goto failed;
1082         }
1083
1084         talloc_set_destructor(lldb, lldb_destructor);
1085
1086         ret = ldap_set_option(lldb->ldap, LDAP_OPT_PROTOCOL_VERSION, &version);
1087         if (ret != LDAP_SUCCESS) {
1088                 ldb_debug(ldb, LDB_DEBUG_FATAL, "ldap_set_option failed - %s\n",
1089                           ldap_err2string(ret));
1090                 goto failed;
1091         }
1092
1093         ldb->modules = talloc(ldb, struct ldb_module);
1094         if (!ldb->modules) {
1095                 ldb_oom(ldb);
1096                 goto failed;
1097         }
1098         ldb->modules->ldb = ldb;
1099         ldb->modules->prev = ldb->modules->next = NULL;
1100         ldb->modules->private_data = lldb;
1101         ldb->modules->ops = &lldb_ops;
1102
1103         return 0;
1104
1105 failed:
1106         talloc_free(lldb);
1107         return -1;
1108 }
1109
1110 int ldb_ldap_init(void)
1111 {
1112         return ldb_register_backend("ldap", lldb_connect);
1113 }