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