~zulcss/samba/server-dailies-3.4

« back to all changes in this revision

Viewing changes to source3/lib/ldb/ldb_ldap/ldb_ldap.c

  • Committer: Chuck Short
  • Date: 2010-09-28 20:38:39 UTC
  • Revision ID: zulcss@ubuntu.com-20100928203839-pgjulytsi9ue63x1
Initial version

Show diffs side-by-side

added added

removed removed

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