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