r13786: [merge] Add registration functions for LDB modules
[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         uint32_t 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                 return ret;
400
401         return ldb_async_wait(module->ldb, handle, LDB_WAIT_ALL);
402 }
403
404 /*
405   add a record
406 */
407 static int lldb_add_async(struct ldb_module *module, const struct ldb_message *msg,
408                           void *context,
409                           int (*callback)(struct ldb_context *, void *, struct ldb_async_result *),
410                           int timeout,
411                           struct ldb_async_handle **handle)
412 {
413         struct lldb_private *lldb = talloc_get_type(module->private_data, struct lldb_private);
414         struct lldb_async_context *lldb_ac;
415         LDAPMod **mods;
416         char *dn;
417         int ret;
418
419         /* ltdb specials should not reach this point */
420         if (ldb_dn_is_special(msg->dn)) {
421                 return LDB_ERR_INVALID_DN_SYNTAX;
422         }
423
424         *handle = init_handle(lldb, module, context, callback, timeout);
425         if (*handle == NULL) {
426                 return LDB_ERR_OPERATIONS_ERROR;
427         }
428
429         lldb_ac = talloc_get_type((*handle)->private_data, struct lldb_async_context);
430
431         mods = lldb_msg_to_mods(lldb_ac, msg, 0);
432         if (mods == NULL) {
433                 talloc_free(*handle);
434                 return LDB_ERR_OPERATIONS_ERROR;
435         }
436
437         dn = ldb_dn_linearize(lldb_ac, msg->dn);
438         if (dn == NULL) {
439                 talloc_free(*handle);
440                 return LDB_ERR_OPERATIONS_ERROR;
441         }
442
443         ret = ldap_add_ext(lldb->ldap, dn, mods,
444                            NULL,
445                            NULL,
446                            &lldb_ac->msgid);
447
448         if (ret != LDAP_SUCCESS) {
449                 ldb_set_errstring(module->ldb, talloc_strdup(module, ldap_err2string(ret)));
450                 talloc_free(*handle);
451         }
452
453         return lldb_ldap_to_ldb(ret);
454 }
455
456 static int lldb_add(struct ldb_module *module, const struct ldb_message *msg)
457 {
458         struct lldb_private *lldb = talloc_get_type(module->private_data, struct lldb_private);
459         struct ldb_async_handle *handle;
460         int ret;
461
462         /* ldap does not understand ltdb specials */
463         if (ldb_dn_is_special(msg->dn)) {
464                 return LDB_SUCCESS;
465         }
466
467         ret = lldb_add_async(module, msg, NULL, NULL, lldb->timeout, &handle);
468
469         if (ret != LDB_SUCCESS)
470                 return ret;
471
472         return ldb_async_wait(module->ldb, handle, LDB_WAIT_ALL);
473 }
474
475
476 /*
477   modify a record
478 */
479 static int lldb_modify_async(struct ldb_module *module, const struct ldb_message *msg,
480                              void *context,
481                              int (*callback)(struct ldb_context *, void *, struct ldb_async_result *),
482                              int timeout,
483                              struct ldb_async_handle **handle)
484 {
485         struct lldb_private *lldb = talloc_get_type(module->private_data, struct lldb_private);
486         struct lldb_async_context *lldb_ac;
487         LDAPMod **mods;
488         char *dn;
489         int ret;
490
491         /* ltdb specials should not reach this point */
492         if (ldb_dn_is_special(msg->dn)) {
493                 return LDB_ERR_INVALID_DN_SYNTAX;
494         }
495
496         *handle = init_handle(lldb, module, context, callback, timeout);
497         if (*handle == NULL) {
498                 return LDB_ERR_OPERATIONS_ERROR;
499         }
500
501         lldb_ac = talloc_get_type((*handle)->private_data, struct lldb_async_context);
502
503         mods = lldb_msg_to_mods(lldb_ac, msg, 1);
504         if (mods == NULL) {
505                 talloc_free(*handle);
506                 return LDB_ERR_OPERATIONS_ERROR;
507         }
508
509         dn = ldb_dn_linearize(lldb_ac, msg->dn);
510         if (dn == NULL) {
511                 talloc_free(*handle);
512                 return LDB_ERR_OPERATIONS_ERROR;
513         }
514
515         ret = ldap_modify_ext(lldb->ldap, dn, mods,
516                               NULL,
517                               NULL,
518                               &lldb_ac->msgid);
519
520         if (ret != LDAP_SUCCESS) {
521                 ldb_set_errstring(module->ldb, talloc_strdup(module, ldap_err2string(ret)));
522                 talloc_free(*handle);
523         }
524
525         return lldb_ldap_to_ldb(ret);
526 }
527
528 static int lldb_modify(struct ldb_module *module, const struct ldb_message *msg)
529 {
530         struct lldb_private *lldb = talloc_get_type(module->private_data, struct lldb_private);
531         struct ldb_async_handle *handle;
532         int ret;
533
534         /* ldap does not understand ltdb specials */
535         if (ldb_dn_is_special(msg->dn)) {
536                 return LDB_SUCCESS;
537         }
538
539         ret = lldb_modify_async(module, msg, NULL, NULL, lldb->timeout, &handle);
540
541         if (ret != LDB_SUCCESS)
542                 return ret;
543
544         return ldb_async_wait(module->ldb, handle, LDB_WAIT_ALL);
545 }
546
547 /*
548   delete a record
549 */
550 static int lldb_delete_async(struct ldb_module *module, const struct ldb_dn *dn,
551                              void *context,
552                              int (*callback)(struct ldb_context *, void *, struct ldb_async_result *),
553                              int timeout,
554                              struct ldb_async_handle **handle)
555 {
556         struct lldb_private *lldb = talloc_get_type(module->private_data, struct lldb_private);
557         struct lldb_async_context *lldb_ac;
558         char *dnstr;
559         int ret;
560         
561         /* ltdb specials should not reach this point */
562         if (ldb_dn_is_special(dn)) {
563                 return LDB_ERR_INVALID_DN_SYNTAX;
564         }
565
566         *handle = init_handle(lldb, module, context, callback, timeout);
567         if (*handle == NULL) {
568                 return LDB_ERR_OPERATIONS_ERROR;
569         }
570
571         lldb_ac = talloc_get_type((*handle)->private_data, struct lldb_async_context);
572
573         dnstr = ldb_dn_linearize(lldb_ac, dn);
574
575         ret = ldap_delete_ext(lldb->ldap, dnstr,
576                               NULL,
577                               NULL,
578                               &lldb_ac->msgid);
579
580         if (ret != LDAP_SUCCESS) {
581                 ldb_set_errstring(module->ldb, talloc_strdup(module, ldap_err2string(ret)));
582                 talloc_free(*handle);
583         }
584
585         return lldb_ldap_to_ldb(ret);
586 }
587
588 static int lldb_delete(struct ldb_module *module, const struct ldb_dn *dn)
589 {
590         struct lldb_private *lldb = talloc_get_type(module->private_data, struct lldb_private);
591         struct ldb_async_handle *handle;
592         int ret;
593
594         /* ignore ltdb specials */
595         if (ldb_dn_is_special(dn)) {
596                 return LDB_SUCCESS;
597         }
598
599         ret = lldb_delete_async(module, dn, NULL, NULL, lldb->timeout, &handle);
600
601         if (ret != LDB_SUCCESS)
602                 return ret;
603
604         return ldb_async_wait(module->ldb, handle, LDB_WAIT_ALL);
605 }
606
607 /*
608   rename a record
609 */
610 static int lldb_rename_async(struct ldb_module *module,
611                              const struct ldb_dn *olddn, const struct ldb_dn *newdn,
612                              void *context,
613                              int (*callback)(struct ldb_context *, void *, struct ldb_async_result *),
614                              int timeout,
615                              struct ldb_async_handle **handle)
616 {
617         struct lldb_private *lldb = talloc_get_type(module->private_data, struct lldb_private);
618         struct lldb_async_context *lldb_ac;
619         char *old_dn;
620         char *newrdn;
621         char *parentdn;
622         int ret;
623         
624         /* ltdb specials should not reach this point */
625         if (ldb_dn_is_special(olddn) || ldb_dn_is_special(newdn)) {
626                 return LDB_ERR_INVALID_DN_SYNTAX;
627         }
628
629         *handle = init_handle(lldb, module, context, callback, timeout);
630         if (*handle == NULL) {
631                 return LDB_ERR_OPERATIONS_ERROR;
632         }
633
634         lldb_ac = talloc_get_type((*handle)->private_data, struct lldb_async_context);
635
636         old_dn = ldb_dn_linearize(lldb_ac, olddn);
637         if (old_dn == NULL) {
638                 talloc_free(*handle);
639                 return LDB_ERR_OPERATIONS_ERROR;
640         }
641
642         newrdn = talloc_asprintf(lldb_ac, "%s=%s",
643                                       newdn->components[0].name,
644                                       ldb_dn_escape_value(lldb, newdn->components[0].value));
645         if (!newrdn) {
646                 talloc_free(*handle);
647                 return LDB_ERR_OPERATIONS_ERROR;
648         }
649
650         parentdn = ldb_dn_linearize(lldb_ac, ldb_dn_get_parent(lldb_ac, newdn));
651         if (!parentdn) {
652                 talloc_free(*handle);
653                 return LDB_ERR_OPERATIONS_ERROR;
654         }
655
656         ret = ldap_rename(lldb->ldap, old_dn, newrdn, parentdn,
657                           1, NULL, NULL,
658                           &lldb_ac->msgid);
659
660         if (ret != LDAP_SUCCESS) {
661                 ldb_set_errstring(module->ldb, talloc_strdup(module, ldap_err2string(ret)));
662                 talloc_free(*handle);
663         }
664
665         return lldb_ldap_to_ldb(ret);
666 }
667
668 static int lldb_rename(struct ldb_module *module, const struct ldb_dn *olddn, const struct ldb_dn *newdn)
669 {
670         struct lldb_private *lldb = talloc_get_type(module->private_data, struct lldb_private);
671         struct ldb_async_handle *handle;
672         int ret;
673
674         /* ignore ltdb specials */
675         if (ldb_dn_is_special(olddn) || ldb_dn_is_special(newdn)) {
676                 return LDB_SUCCESS;
677         }
678
679         ret = lldb_rename_async(module, olddn, newdn, NULL, NULL, lldb->timeout, &handle);
680
681         if (ret != LDB_SUCCESS)
682                 return ret;
683
684         return ldb_async_wait(module->ldb, handle, LDB_WAIT_ALL);
685 }
686
687 static int lldb_parse_result(struct ldb_async_handle *handle, LDAPMessage *result)
688 {
689         struct lldb_async_context *ac = talloc_get_type(handle->private_data, struct lldb_async_context);
690         struct lldb_private *lldb = talloc_get_type(ac->module->private_data, struct lldb_private);
691         struct ldb_async_result *ares = NULL;
692         LDAPMessage *msg;
693         int type;
694         char *matcheddnp = NULL;
695         char *errmsgp = NULL;
696         char **referralsp = NULL;
697         LDAPControl **serverctrlsp = NULL;
698
699         type = ldap_msgtype(result);
700
701         switch (type) {
702
703         case LDAP_RES_SEARCH_ENTRY:
704                 msg = ldap_first_entry(lldb->ldap, result);
705                 if (msg != NULL) {
706                         BerElement *berptr = NULL;
707                         char *attr, *dn;
708
709                         ares = talloc_zero(ac, struct ldb_async_result);
710                         if (!ares) {
711                                 handle->status = LDB_ERR_OPERATIONS_ERROR;
712                                 goto error;
713                         }
714
715                         ares->message = ldb_msg_new(ares);
716                         if (!ares->message) {
717                                 handle->status = LDB_ERR_OPERATIONS_ERROR;
718                                 goto error;
719                         }
720
721                         dn = ldap_get_dn(lldb->ldap, msg);
722                         if (!dn) {
723                                 handle->status = LDB_ERR_OPERATIONS_ERROR;
724                                 goto error;
725                         }
726                         ares->message->dn = ldb_dn_explode_or_special(ares->message, dn);
727                         if (ares->message->dn == NULL) {
728                                 handle->status = LDB_ERR_OPERATIONS_ERROR;
729                                 goto error;
730                         }
731                         ldap_memfree(dn);
732
733                         ares->message->num_elements = 0;
734                         ares->message->elements = NULL;
735                         ares->message->private_data = NULL;
736
737                         /* loop over all attributes */
738                         for (attr=ldap_first_attribute(lldb->ldap, msg, &berptr);
739                              attr;
740                              attr=ldap_next_attribute(lldb->ldap, msg, berptr)) {
741                                 struct berval **bval;
742                                 bval = ldap_get_values_len(lldb->ldap, msg, attr);
743
744                                 if (bval) {
745                                         lldb_add_msg_attr(ac->module->ldb, ares->message, attr, bval);
746                                         ldap_value_free_len(bval);
747                                 }                                         
748                                 
749                                 ldap_memfree(attr);
750                         }
751                         if (berptr) ber_free(berptr, 0);
752
753
754                         ares->type = LDB_REPLY_ENTRY;
755                         handle->state = LDB_ASYNC_PENDING;
756                         handle->status = ac->callback(ac->module->ldb, ac->context, ares);
757
758                         ldap_msgfree(result);
759                 }
760                 break;
761
762         case LDAP_RES_SEARCH_REFERENCE:
763                 if (ldap_parse_result(lldb->ldap, result, &handle->status,
764                                         &matcheddnp, &errmsgp,
765                                         &referralsp, &serverctrlsp, 1) != LDAP_SUCCESS) {
766                         handle->status = LDB_ERR_OPERATIONS_ERROR;
767                         goto error;
768                 }
769                 if (referralsp == NULL) {
770                         handle->status = LDB_ERR_PROTOCOL_ERROR;
771                         goto error;
772                 }
773
774                 ares = talloc_zero(ac, struct ldb_async_result);
775                 if (!ares) {
776                         handle->status = LDB_ERR_OPERATIONS_ERROR;
777                         goto error;
778                 }
779
780                 ares->referral = talloc_strdup(ares, *referralsp);
781                 ares->type = LDB_REPLY_REFERRAL;
782                 handle->state = LDB_ASYNC_PENDING;
783                 handle->status = ac->callback(ac->module->ldb, ac->context, ares);
784
785                 break;
786
787         case LDAP_RES_SEARCH_RESULT:
788                 if (ldap_parse_result(lldb->ldap, result, &handle->status,
789                                         &matcheddnp, &errmsgp,
790                                         &referralsp, &serverctrlsp, 1) != LDAP_SUCCESS) {
791                         handle->status = LDB_ERR_OPERATIONS_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                 if (serverctrlsp != NULL) {
802                         /* FIXME: transform the LDAPControl list into an ldb_control one */
803                         ares->controls = NULL;
804                 }
805                 
806                 ares->type = LDB_REPLY_DONE;
807                 handle->state = LDB_ASYNC_DONE;
808                 handle->status = ac->callback(ac->module->ldb, ac->context, ares);
809
810                 break;
811
812         case LDAP_RES_MODIFY:
813         case LDAP_RES_ADD:
814         case LDAP_RES_DELETE:
815         case LDAP_RES_MODDN:
816                 if (ldap_parse_result(lldb->ldap, result, &handle->status,
817                                         &matcheddnp, &errmsgp,
818                                         &referralsp, &serverctrlsp, 1) != LDAP_SUCCESS) {
819                         handle->status = LDB_ERR_OPERATIONS_ERROR;
820                         goto error;
821                 }
822                 if (ac->callback && handle->status == LDB_SUCCESS) {
823                         ares = NULL; /* FIXME: build a corresponding ares to pass on */
824                         handle->status = ac->callback(ac->module->ldb, ac->context, ares);
825                 }
826                 handle->state = LDB_ASYNC_DONE;
827                 break;
828
829         default:
830                 handle->state = LDB_ERR_PROTOCOL_ERROR;
831         }
832
833         if (matcheddnp) ldap_memfree(matcheddnp);
834         if (errmsgp) {
835                 ldb_set_errstring(ac->module->ldb, talloc_strdup(ac->module, errmsgp));
836                 ldap_memfree(errmsgp);
837         }
838         if (referralsp) ldap_value_free(referralsp);
839         if (serverctrlsp) ldap_controls_free(serverctrlsp);
840
841         return handle->status;
842
843 error:
844         handle->state = LDB_ASYNC_DONE;
845         return handle->status;
846 }
847
848 static int lldb_async_wait(struct ldb_async_handle *handle, enum ldb_async_wait_type type)
849 {
850         struct lldb_async_context *ac = talloc_get_type(handle->private_data, struct lldb_async_context);
851         struct lldb_private *lldb = talloc_get_type(ac->module->private_data, struct lldb_private);
852         struct timeval timeout;
853         LDAPMessage *result;
854         int ret;
855
856         if (!ac->msgid) {
857                 return LDB_ERR_OPERATIONS_ERROR;
858         }
859
860         handle->status = LDB_SUCCESS;
861         handle->state = LDB_ASYNC_INIT;
862
863         switch(type) {
864         case LDB_WAIT_NONE:
865                 timeout.tv_sec = 0;
866                 timeout.tv_usec = 0;
867                 ret = ldap_result(lldb->ldap, ac->msgid, 0, &timeout, &result);
868                 if (ret == -1) {
869                         handle->status = LDB_ERR_OPERATIONS_ERROR;
870                         return handle->status;
871                 }
872                 if (ret == 0) {
873                         handle->status = LDB_SUCCESS;
874                         return handle->status;
875                 }
876                 ret = lldb_parse_result(handle, result);
877                 break;
878         case LDB_WAIT_ONCE:
879                 timeout.tv_sec = ac->timeout;
880                 timeout.tv_usec = 0;
881                 ret = ldap_result(lldb->ldap, ac->msgid, 0, &timeout, &result);
882                 if (ret == -1 || ret == 0) {
883                         handle->status = LDB_ERR_OPERATIONS_ERROR;
884                         return handle->status;
885                 }
886                 ret = lldb_parse_result(handle, result);
887                 break;
888         case LDB_WAIT_ALL:
889                 timeout.tv_sec = ac->timeout;
890                 timeout.tv_usec = 0;
891                 while (handle->status == LDB_SUCCESS && handle->state != LDB_ASYNC_DONE) {
892                         ret = ldap_result(lldb->ldap, ac->msgid, 0, &timeout, &result);
893                         if (ret == -1 || ret == 0) {
894                                 handle->status = LDB_ERR_OPERATIONS_ERROR;
895                                 return handle->status;
896                         }
897                         ret = lldb_parse_result(handle, result);
898                         if (ret != LDB_SUCCESS) {
899                                 return ret;
900                         }
901                 }
902                 break;
903         default:
904                 ret = LDB_ERR_OPERATIONS_ERROR;
905         }
906
907         return ret;
908 }
909
910 static int lldb_start_trans(struct ldb_module *module)
911 {
912         /* TODO implement a local transaction mechanism here */
913
914         return 0;
915 }
916
917 static int lldb_end_trans(struct ldb_module *module)
918 {
919         /* TODO implement a local transaction mechanism here */
920
921         return 0;
922 }
923
924 static int lldb_del_trans(struct ldb_module *module)
925 {
926         /* TODO implement a local transaction mechanism here */
927
928         return 0;
929 }
930
931 static int lldb_request(struct ldb_module *module, struct ldb_request *req)
932 {
933         switch (req->operation) {
934
935         case LDB_REQ_SEARCH:
936                 return lldb_search_bytree(module,
937                                           req->op.search.base,
938                                           req->op.search.scope, 
939                                           req->op.search.tree, 
940                                           req->op.search.attrs, 
941                                           req->controls,
942                                           &req->op.search.res);
943
944         case LDB_REQ_ADD:
945                 return lldb_add(module, req->op.add.message);
946
947         case LDB_REQ_MODIFY:
948                 return lldb_modify(module, req->op.mod.message);
949
950         case LDB_REQ_DELETE:
951                 return lldb_delete(module, req->op.del.dn);
952
953         case LDB_REQ_RENAME:
954                 return lldb_rename(module,
955                                         req->op.rename.olddn,
956                                         req->op.rename.newdn);
957
958         case LDB_ASYNC_SEARCH:
959                 return lldb_search_async(module,
960                                         req->op.search.base,
961                                         req->op.search.scope, 
962                                         req->op.search.tree, 
963                                         req->op.search.attrs,
964                                         req->controls,
965                                         req->async.context,
966                                         req->async.callback,
967                                         req->async.timeout,
968                                         &req->async.handle);
969
970         case LDB_ASYNC_ADD:
971                 return lldb_add_async(module,
972                                         req->op.add.message,
973                                         req->async.context,
974                                         req->async.callback,
975                                         req->async.timeout,
976                                         &req->async.handle);
977
978         case LDB_ASYNC_MODIFY:
979                 return lldb_modify_async(module,
980                                         req->op.mod.message,
981                                         req->async.context,
982                                         req->async.callback,
983                                         req->async.timeout,
984                                         &req->async.handle);
985
986         case LDB_ASYNC_DELETE:
987                 return lldb_delete_async(module,
988                                         req->op.del.dn,
989                                         req->async.context,
990                                         req->async.callback,
991                                         req->async.timeout,
992                                         &req->async.handle);
993
994         case LDB_ASYNC_RENAME:
995                 return lldb_rename_async(module,
996                                         req->op.rename.olddn,
997                                         req->op.rename.newdn,
998                                         req->async.context,
999                                         req->async.callback,
1000                                         req->async.timeout,
1001                                         &req->async.handle);
1002
1003         default:
1004                 return -1;
1005
1006         }
1007 }
1008
1009 static const struct ldb_module_ops lldb_ops = {
1010         .name              = "ldap",
1011         .request           = lldb_request,
1012         .start_transaction = lldb_start_trans,
1013         .end_transaction   = lldb_end_trans,
1014         .del_transaction   = lldb_del_trans,
1015 };
1016
1017
1018 static int lldb_destructor(void *p)
1019 {
1020         struct lldb_private *lldb = p;
1021         ldap_unbind(lldb->ldap);
1022         return 0;
1023 }
1024
1025 /*
1026   connect to the database
1027 */
1028 int lldb_connect(struct ldb_context *ldb,
1029                  const char *url, 
1030                  unsigned int flags, 
1031                  const char *options[])
1032 {
1033         struct lldb_private *lldb = NULL;
1034         int version = 3;
1035         int ret;
1036
1037         lldb = talloc(ldb, struct lldb_private);
1038         if (!lldb) {
1039                 ldb_oom(ldb);
1040                 goto failed;
1041         }
1042
1043         lldb->ldap = NULL;
1044         lldb->timeout = 120; /* TODO: get timeout from options ? */
1045
1046         ret = ldap_initialize(&lldb->ldap, url);
1047         if (ret != LDAP_SUCCESS) {
1048                 ldb_debug(ldb, LDB_DEBUG_FATAL, "ldap_initialize failed for URL '%s' - %s\n",
1049                           url, ldap_err2string(ret));
1050                 goto failed;
1051         }
1052
1053         talloc_set_destructor(lldb, lldb_destructor);
1054
1055         ret = ldap_set_option(lldb->ldap, LDAP_OPT_PROTOCOL_VERSION, &version);
1056         if (ret != LDAP_SUCCESS) {
1057                 ldb_debug(ldb, LDB_DEBUG_FATAL, "ldap_set_option failed - %s\n",
1058                           ldap_err2string(ret));
1059                 goto failed;
1060         }
1061
1062         ldb->modules = talloc(ldb, struct ldb_module);
1063         if (!ldb->modules) {
1064                 ldb_oom(ldb);
1065                 goto failed;
1066         }
1067         ldb->modules->ldb = ldb;
1068         ldb->modules->prev = ldb->modules->next = NULL;
1069         ldb->modules->private_data = lldb;
1070         ldb->modules->ops = &lldb_ops;
1071
1072         ldb->async_wait = &lldb_async_wait;
1073
1074         return 0;
1075
1076 failed:
1077         talloc_free(lldb);
1078         return -1;
1079 }
1080