~ubuntu-branches/ubuntu/maverick/bind9/maverick

« back to all changes in this revision

Viewing changes to contrib/dlz/drivers/dlz_ldap_driver.c

  • Committer: Bazaar Package Importer
  • Author(s): LaMont Jones, LaMont Jones, Internet Software Consortium, Inc, localization folks
  • Date: 2008-08-02 14:20:20 UTC
  • mfrom: (1.2.1 upstream) (6.1.24 intrepid)
  • Revision ID: james.westby@ubuntu.com-20080802142020-l1hon9jy8lbbjxmg
[LaMont Jones]

* default to using resolvconf if it is installed
* fix sonames and dependencies.  Closes: #149259, #492418
* Do not build-depend libcap2-dev on non-linux.  Closes: #493392
* drop unused query-loc manpage.  Closes: #492564
* lwresd: Deliver /etc/bind directory.  Closes: #490027
* fix query-source comment in default install

[Internet Software Consortium, Inc]

* 9.5.0-P2.  Closes: #492949

[localization folks]

* l10n: Spanish debconf translation.  Closes: #492425 (Ignacio Mondino)
* l10n: Swedish debconf templates.  Closes: #491369 (Martin Ågren)
* l10n: Japanese debconf translations.  Closes: #492048 (Hideki Yamane
  (Debian-JP))
* l10n: Finnish translation.  Closes: #490630 (Esko Arajärvi)
* l10n: Italian debconf translations.  Closes: #492587 (Alessandro Vietta)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 2002 Stichting NLnet, Netherlands, stichting@nlnet.nl.
 
3
 *
 
4
 * Permission to use, copy, modify, and distribute this software for any
 
5
 * purpose with or without fee is hereby granted, provided that the
 
6
 * above copyright notice and this permission notice appear in all
 
7
 * copies.
 
8
 *
 
9
 * THE SOFTWARE IS PROVIDED "AS IS" AND STICHTING NLNET
 
10
 * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
 
11
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
 
12
 * STICHTING NLNET BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
 
13
 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
 
14
 * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
 
15
 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE
 
16
 * USE OR PERFORMANCE OF THIS SOFTWARE.
 
17
 *
 
18
 * The development of Dynamically Loadable Zones (DLZ) for Bind 9 was
 
19
 * conceived and contributed by Rob Butler.
 
20
 *
 
21
 * Permission to use, copy, modify, and distribute this software for any
 
22
 * purpose with or without fee is hereby granted, provided that the
 
23
 * above copyright notice and this permission notice appear in all
 
24
 * copies.
 
25
 *
 
26
 * THE SOFTWARE IS PROVIDED "AS IS" AND ROB BUTLER
 
27
 * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
 
28
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
 
29
 * ROB BUTLER BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
 
30
 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
 
31
 * OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
 
32
 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE
 
33
 * USE OR PERFORMANCE OF THIS SOFTWARE.
 
34
 */
 
35
 
 
36
/*
 
37
 * Copyright (C) 1999-2001  Internet Software Consortium.
 
38
 *
 
39
 * Permission to use, copy, modify, and distribute this software for any
 
40
 * purpose with or without fee is hereby granted, provided that the above
 
41
 * copyright notice and this permission notice appear in all copies.
 
42
 *
 
43
 * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
 
44
 * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
 
45
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
 
46
 * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
 
47
 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
 
48
 * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
 
49
 * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
 
50
 * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 
51
 */
 
52
 
 
53
#ifdef DLZ_LDAP
 
54
 
 
55
#include <config.h>
 
56
#include <stdio.h>
 
57
#include <string.h>
 
58
#include <stdlib.h>
 
59
 
 
60
#include <dns/log.h>
 
61
#include <dns/sdlz.h>
 
62
#include <dns/result.h>
 
63
 
 
64
#include <isc/mem.h>
 
65
#include <isc/platform.h>
 
66
#include <isc/print.h>
 
67
#include <isc/result.h>
 
68
#include <isc/string.h>
 
69
#include <isc/util.h>
 
70
 
 
71
#include <named/globals.h>
 
72
 
 
73
#include <dlz/sdlz_helper.h>
 
74
#include <dlz/dlz_ldap_driver.h>
 
75
 
 
76
/*
 
77
 * Need older API functions from ldap.h.
 
78
 */
 
79
#define LDAP_DEPRECATED 1
 
80
 
 
81
#include <ldap.h>
 
82
 
 
83
#define SIMPLE "simple"
 
84
#define KRB41 "krb41"
 
85
#define KRB42 "krb42"
 
86
#define V2 "v2"
 
87
#define V3 "v3"
 
88
 
 
89
static dns_sdlzimplementation_t *dlz_ldap = NULL;
 
90
 
 
91
#define dbc_search_limit 30
 
92
#define ALLNODES 1
 
93
#define ALLOWXFR 2
 
94
#define AUTHORITY 3
 
95
#define FINDZONE 4
 
96
#define LOOKUP 5
 
97
 
 
98
/*%
 
99
 * Structure to hold everthing needed by this "instance" of the LDAP
 
100
 * driver remember, the driver code is only loaded once, but may have
 
101
 * many separate instances.
 
102
 */
 
103
 
 
104
typedef struct {
 
105
 
 
106
#ifdef ISC_PLATFORM_USETHREADS
 
107
        db_list_t    *db; /*%< handle to a list of DB */
 
108
#else
 
109
        dbinstance_t *db; /*%< handle to db */
 
110
#endif
 
111
        int method;     /*%< security authentication method */
 
112
        char *user;     /*%< who is authenticating */
 
113
        char *cred;     /*%< password for simple authentication method */
 
114
        int protocol;   /*%< LDAP communication protocol version */
 
115
        char *hosts;    /*%< LDAP server hosts */
 
116
 
 
117
} ldap_instance_t;
 
118
 
 
119
/* forward references */
 
120
 
 
121
static isc_result_t
 
122
dlz_ldap_findzone(void *driverarg, void *dbdata, const char *name);
 
123
 
 
124
static void
 
125
dlz_ldap_destroy(void *driverarg, void *dbdata);
 
126
 
 
127
/*
 
128
 * Private methods
 
129
 */
 
130
 
 
131
/*% checks that the LDAP URL parameters make sense */
 
132
 
 
133
static isc_result_t
 
134
dlz_ldap_checkURL(char *URL, int attrCnt, const char *msg) {
 
135
 
 
136
        isc_result_t result = ISC_R_SUCCESS;
 
137
        int ldap_result;
 
138
        LDAPURLDesc *ldap_url = NULL;
 
139
 
 
140
        if (!ldap_is_ldap_url(URL)) {
 
141
                isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
 
142
                              DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
 
143
                              "%s query is not a valid LDAP URL", msg);
 
144
                result = ISC_R_FAILURE;
 
145
                goto cleanup;
 
146
        }
 
147
 
 
148
        ldap_result = ldap_url_parse(URL, &ldap_url);
 
149
        if (ldap_result != LDAP_SUCCESS || ldap_url == NULL) {
 
150
                isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
 
151
                              DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
 
152
                              "parsing %s query failed", msg);
 
153
                result = ISC_R_FAILURE;
 
154
                goto cleanup;
 
155
        }
 
156
 
 
157
        if (ldap_count_values(ldap_url->lud_attrs) < attrCnt) {
 
158
                isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
 
159
                              DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
 
160
                              "%s query must specify at least "
 
161
                              "%d attributes to return",
 
162
                              msg, attrCnt);
 
163
                result = ISC_R_FAILURE;
 
164
                goto cleanup;
 
165
        }
 
166
 
 
167
        if (ldap_url->lud_host != NULL) {
 
168
                isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
 
169
                              DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
 
170
                              "%s query must not specify a host", msg);
 
171
                result = ISC_R_FAILURE;
 
172
                goto cleanup;
 
173
        }
 
174
 
 
175
        if (ldap_url->lud_port != 389) {
 
176
                isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
 
177
                              DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
 
178
                              "%s query must not specify a port", msg);
 
179
                result = ISC_R_FAILURE;
 
180
                goto cleanup;
 
181
        }
 
182
 
 
183
        if (ldap_url->lud_dn == NULL || strlen (ldap_url->lud_dn) < 1) {
 
184
                isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
 
185
                              DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
 
186
                              "%s query must specify a search base", msg);
 
187
                result = ISC_R_FAILURE;
 
188
                goto cleanup;
 
189
        }
 
190
 
 
191
        if (ldap_url->lud_exts != NULL || ldap_url->lud_crit_exts != 0) {
 
192
                isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
 
193
                              DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
 
194
                              "%s uses extensions. "
 
195
                              "The driver does not support LDAP extensions.",
 
196
                              msg);
 
197
                result = ISC_R_FAILURE;
 
198
                goto cleanup;
 
199
        }
 
200
 
 
201
 cleanup:
 
202
 
 
203
        if (ldap_url != NULL)
 
204
                ldap_free_urldesc(ldap_url);
 
205
 
 
206
        return result;
 
207
}
 
208
/*% Connects / reconnects to LDAP server */
 
209
 
 
210
static isc_result_t
 
211
dlz_ldap_connect(ldap_instance_t *dbi, dbinstance_t *dbc) {
 
212
 
 
213
        isc_result_t result;
 
214
        int ldap_result;
 
215
 
 
216
        /* if we have a connection, get ride of it. */
 
217
        if (dbc->dbconn != NULL) {
 
218
                ldap_unbind_s((LDAP *) dbc->dbconn);
 
219
                dbc->dbconn = NULL;
 
220
        }
 
221
 
 
222
        /* now connect / reconnect. */
 
223
 
 
224
        /* initialize. */
 
225
        dbc->dbconn = ldap_init(dbi->hosts, LDAP_PORT);
 
226
        if (dbc->dbconn == NULL)
 
227
                return ISC_R_NOMEMORY;
 
228
 
 
229
        /* set protocol version. */
 
230
        ldap_result = ldap_set_option((LDAP *) dbc->dbconn,
 
231
                                      LDAP_OPT_PROTOCOL_VERSION,
 
232
                                      &(dbi->protocol));
 
233
        if (ldap_result != LDAP_SUCCESS) {
 
234
                result = ISC_R_NOPERM;
 
235
                goto cleanup;
 
236
        }
 
237
 
 
238
        /* "bind" to server.  i.e. send username / pass */
 
239
        ldap_result = ldap_bind_s((LDAP *) dbc->dbconn, dbi->user,
 
240
                                  dbi->cred, dbi->method);
 
241
        if (ldap_result != LDAP_SUCCESS) {
 
242
                result = ISC_R_FAILURE;
 
243
                goto cleanup;
 
244
        }
 
245
 
 
246
        return ISC_R_SUCCESS;
 
247
 
 
248
 cleanup:
 
249
 
 
250
        /* cleanup if failure. */
 
251
        if (dbc->dbconn != NULL) {
 
252
                ldap_unbind_s((LDAP *) dbc->dbconn);
 
253
                dbc->dbconn = NULL;
 
254
        }
 
255
 
 
256
        return result;
 
257
}
 
258
 
 
259
#ifdef ISC_PLATFORM_USETHREADS
 
260
 
 
261
 
 
262
/*%
 
263
 * Properly cleans up a list of database instances.
 
264
 * This function is only used when the driver is compiled for
 
265
 * multithreaded operation.
 
266
 */
 
267
static void
 
268
ldap_destroy_dblist(db_list_t *dblist)
 
269
{
 
270
 
 
271
        dbinstance_t *ndbi = NULL;
 
272
        dbinstance_t *dbi = NULL;
 
273
 
 
274
        /* get the first DBI in the list */
 
275
        ndbi = ISC_LIST_HEAD(*dblist);
 
276
 
 
277
        /* loop through the list */
 
278
        while (ndbi != NULL) {
 
279
                dbi = ndbi;
 
280
                /* get the next DBI in the list */
 
281
                ndbi = ISC_LIST_NEXT(dbi, link);
 
282
                /* release DB connection */
 
283
                if (dbi->dbconn != NULL)
 
284
                        ldap_unbind_s((LDAP *) dbi->dbconn);
 
285
                /* release all memory that comprised a DBI */
 
286
                destroy_sqldbinstance(dbi);
 
287
        }
 
288
        /* release memory for the list structure */
 
289
        isc_mem_put(ns_g_mctx, dblist, sizeof(db_list_t));
 
290
}
 
291
 
 
292
/*%
 
293
 * Loops through the list of DB instances, attempting to lock
 
294
 * on the mutex.  If successful, the DBI is reserved for use
 
295
 * and the thread can perform queries against the database.
 
296
 * If the lock fails, the next one in the list is tried.
 
297
 * looping continues until a lock is obtained, or until
 
298
 * the list has been searched dbc_search_limit times.
 
299
 * This function is only used when the driver is compiled for
 
300
 * multithreaded operation.
 
301
 */
 
302
 
 
303
static dbinstance_t *
 
304
ldap_find_avail_conn(db_list_t *dblist)
 
305
{
 
306
        dbinstance_t *dbi = NULL;
 
307
        dbinstance_t *head;
 
308
        int count = 0;
 
309
 
 
310
        /* get top of list */
 
311
        head = dbi = ISC_LIST_HEAD(*dblist);
 
312
 
 
313
        /* loop through list */
 
314
        while (count < dbc_search_limit) {
 
315
                /* try to lock on the mutex */
 
316
                if (isc_mutex_trylock(&dbi->instance_lock) == ISC_R_SUCCESS)
 
317
                        return dbi; /* success, return the DBI for use. */
 
318
 
 
319
                /* not successful, keep trying */
 
320
                dbi = ISC_LIST_NEXT(dbi, link);
 
321
 
 
322
                /* check to see if we have gone to the top of the list. */
 
323
                if (dbi == NULL) {
 
324
                        count++;
 
325
                        dbi = head;
 
326
                }
 
327
        }
 
328
        isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
 
329
                      DNS_LOGMODULE_DLZ, ISC_LOG_INFO,
 
330
                      "LDAP driver unable to find available connection "
 
331
                      "after searching %d times",
 
332
                      count);
 
333
        return NULL;
 
334
}
 
335
 
 
336
#endif /* ISC_PLATFORM_USETHREADS */
 
337
 
 
338
static isc_result_t
 
339
ldap_process_results(LDAP *dbc, LDAPMessage *msg, char ** attrs,
 
340
                     void *ptr, isc_boolean_t allnodes)
 
341
{
 
342
        isc_result_t result = ISC_R_SUCCESS;
 
343
        int i = 0;
 
344
        int j;
 
345
        int len;
 
346
        char *attribute = NULL;
 
347
        LDAPMessage *entry;
 
348
        char *endp = NULL;
 
349
        char *host = NULL;
 
350
        char *type = NULL;
 
351
        char *data = NULL;
 
352
        char **vals = NULL;
 
353
        int ttl;
 
354
 
 
355
        /* make sure there are at least some attributes to process. */
 
356
        REQUIRE(attrs != NULL || attrs[0] != NULL);
 
357
 
 
358
        /* get the first entry to process */
 
359
        entry = ldap_first_entry(dbc, msg);
 
360
        if (entry == NULL) {
 
361
                isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
 
362
                              DNS_LOGMODULE_DLZ, ISC_LOG_INFO,
 
363
                              "LDAP no entries to process.");
 
364
                return ISC_R_FAILURE;
 
365
        }
 
366
 
 
367
        /* loop through all entries returned */
 
368
        while (entry != NULL) {
 
369
 
 
370
                /* reset for this loop */
 
371
                ttl = 0;
 
372
                len = 0;
 
373
                i = 0;
 
374
                attribute = attrs[i];
 
375
 
 
376
                /* determine how much space we need for data string */
 
377
                for (j=0; attrs[j] != NULL; j++) {
 
378
                        /* get the list of values for this attribute. */
 
379
                        vals = ldap_get_values(dbc, entry, attrs[j]);
 
380
                        /* skip empty attributes. */
 
381
                        if (vals == NULL || ldap_count_values(vals) < 1)
 
382
                                continue;
 
383
                        /*
 
384
                         * we only use the first value.  this driver
 
385
                         * does not support multi-valued attributes.
 
386
                         */
 
387
                        len = len + strlen(vals[0]) + 1;
 
388
                        /* free vals for next loop */
 
389
                        ldap_value_free(vals);
 
390
                } /* end for (j=0; attrs[j] != NULL, j++) loop */
 
391
 
 
392
                /* allocate memory for data string */
 
393
                data = isc_mem_allocate(ns_g_mctx, len + 1);
 
394
                if (data == NULL) {
 
395
                        isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
 
396
                                      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
 
397
                                      "LDAP driver unable to allocate memory "
 
398
                                      "while processing results");
 
399
                        result = ISC_R_FAILURE;
 
400
                        goto cleanup;
 
401
                }
 
402
 
 
403
                /*
 
404
                 * Make sure data is null termed at the beginning so
 
405
                 * we can check if any data was stored to it later.
 
406
                 */
 
407
                data[0] = '\0';
 
408
 
 
409
                /* reset j to re-use below */
 
410
                j = 0;
 
411
 
 
412
                /* loop through the attributes in the order specified. */
 
413
                while (attribute != NULL) {
 
414
 
 
415
                        /* get the list of values for this attribute. */
 
416
                        vals = ldap_get_values(dbc, entry, attribute);
 
417
 
 
418
                        /* skip empty attributes. */
 
419
                        if (vals == NULL || vals[0] == NULL) {
 
420
                                /* increment attibute pointer */
 
421
                                attribute = attrs[++i];
 
422
                                /* start loop over */
 
423
                                continue;
 
424
                        }
 
425
 
 
426
                        /*
 
427
                         * j initially = 0.  Increment j each time we
 
428
                         * set a field that way next loop will set
 
429
                         * next field.
 
430
                         */
 
431
                        switch(j) {
 
432
                        case 0:
 
433
                                j++;
 
434
                                /*
 
435
                                 * convert text to int, make sure it
 
436
                                 * worked right
 
437
                                 */
 
438
                                ttl = strtol(vals[0], &endp, 10);
 
439
                                if (*endp != '\0' || ttl < 0) {
 
440
                                        isc_log_write(dns_lctx,
 
441
                                                      DNS_LOGCATEGORY_DATABASE,
 
442
                                                      DNS_LOGMODULE_DLZ,
 
443
                                                      ISC_LOG_ERROR,
 
444
                                                      "LDAP driver ttl must "
 
445
                                                      "be a postive number");
 
446
                                        goto cleanup;
 
447
                                }
 
448
                                break;
 
449
                        case 1:
 
450
                                j++;
 
451
                                type = isc_mem_strdup(ns_g_mctx, vals[0]);
 
452
                                break;
 
453
                        case 2:
 
454
                                j++;
 
455
                                if (allnodes == isc_boolean_true) {
 
456
                                        host = isc_mem_strdup(ns_g_mctx,
 
457
                                                              vals[0]);
 
458
                                } else {
 
459
                                        strcpy(data, vals[0]);
 
460
                                }
 
461
                                break;
 
462
                        case 3:
 
463
                                j++;
 
464
                                if (allnodes == isc_boolean_true) {
 
465
                                        strcpy(data, vals[0]);
 
466
                                } else {
 
467
                                        strcat(data, " ");
 
468
                                        strcat(data, vals[0]);
 
469
                                }
 
470
                                break;
 
471
                        default:
 
472
                                strcat(data, " ");
 
473
                                strcat(data, vals[0]);
 
474
                                break;
 
475
                        } /* end switch(j) */
 
476
 
 
477
                        /* free values */
 
478
                        ldap_value_free(vals);
 
479
                        vals = NULL;
 
480
 
 
481
                        /* increment attibute pointer */
 
482
                        attribute = attrs[++i];
 
483
                }       /* end while (attribute != NULL) */
 
484
 
 
485
                if (type == NULL) {
 
486
                        isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
 
487
                                      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
 
488
                                      "LDAP driver unable "
 
489
                                      "to retrieve dns type");
 
490
                        result = ISC_R_FAILURE;
 
491
                        goto cleanup;
 
492
                }
 
493
                if (strlen(data) < 1) {
 
494
                        isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
 
495
                                      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
 
496
                                      "LDAP driver unable "
 
497
                                      "to retrieve dns data");
 
498
                        result = ISC_R_FAILURE;
 
499
                        goto cleanup;
 
500
                }
 
501
                if (allnodes == isc_boolean_true) {
 
502
                        if (strcasecmp(host, "~") == 0)
 
503
                                result = dns_sdlz_putnamedrr(
 
504
                                                (dns_sdlzallnodes_t *) ptr,
 
505
                                                "*", type, ttl, data);
 
506
                        else
 
507
                                result = dns_sdlz_putnamedrr(
 
508
                                                (dns_sdlzallnodes_t *) ptr,
 
509
                                                host, type, ttl, data);
 
510
                }
 
511
                else
 
512
                        result = dns_sdlz_putrr((dns_sdlzlookup_t *) ptr,
 
513
                                                type, ttl, data);
 
514
 
 
515
                if (result != ISC_R_SUCCESS) {
 
516
                        isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
 
517
                                      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
 
518
                                      "LDAP driver failed "
 
519
                                      "while sending data to Bind.");
 
520
                        goto cleanup;
 
521
                }
 
522
 
 
523
                /* free memory for type, data and host for next loop */
 
524
                isc_mem_free(ns_g_mctx, type);
 
525
                isc_mem_free(ns_g_mctx, data);
 
526
                if (host != NULL)
 
527
                        isc_mem_free(ns_g_mctx, host);
 
528
 
 
529
                /* get the next entry to process */
 
530
                entry = ldap_next_entry(dbc, entry);
 
531
        } /* end while (entry != NULL) */
 
532
 
 
533
 cleanup:
 
534
 
 
535
        /* de-allocate memory */
 
536
        if (vals != NULL)
 
537
                ldap_value_free(vals);
 
538
        if (host != NULL)
 
539
                isc_mem_free(ns_g_mctx, host);
 
540
        if (type != NULL)
 
541
                isc_mem_free(ns_g_mctx, type);
 
542
        if (data != NULL)
 
543
                isc_mem_free(ns_g_mctx, data);
 
544
 
 
545
        return result;
 
546
}
 
547
 
 
548
/*%
 
549
 * This function is the real core of the driver.   Zone, record
 
550
 * and client strings are passed in (or NULL is passed if the
 
551
 * string is not available).  The type of query we want to run
 
552
 * is indicated by the query flag, and the dbdata object is passed
 
553
 * passed in to.  dbdata really holds either:
 
554
 *              1) a list of database instances (in multithreaded mode) OR
 
555
 *              2) a single database instance (in single threaded mode)
 
556
 * The function will construct the query and obtain an available
 
557
 * database instance (DBI).  It will then run the query and hopefully
 
558
 * obtain a result set.
 
559
 */
 
560
static isc_result_t
 
561
ldap_get_results(const char *zone, const char *record,
 
562
                 const char *client, unsigned int query,
 
563
                 void *dbdata, void *ptr)
 
564
{
 
565
        isc_result_t result;
 
566
        dbinstance_t *dbi = NULL;
 
567
        char *querystring = NULL;
 
568
        LDAPURLDesc *ldap_url = NULL;
 
569
        int ldap_result = 0;
 
570
        LDAPMessage *ldap_msg = NULL;
 
571
        int i;
 
572
        int entries;
 
573
 
 
574
        /* get db instance / connection */
 
575
#ifdef ISC_PLATFORM_USETHREADS
 
576
 
 
577
        /* find an available DBI from the list */
 
578
        dbi = ldap_find_avail_conn((db_list_t *)
 
579
                                   ((ldap_instance_t *)dbdata)->db);
 
580
 
 
581
#else /* ISC_PLATFORM_USETHREADS */
 
582
 
 
583
        /*
 
584
         * only 1 DBI - no need to lock instance lock either
 
585
         * only 1 thread in the whole process, no possible contention.
 
586
         */
 
587
        dbi =  (dbinstance_t *) ((ldap_instance_t *)dbdata)->db;
 
588
 
 
589
#endif /* ISC_PLATFORM_USETHREADS */
 
590
 
 
591
        /* if DBI is null, can't do anything else */
 
592
        if (dbi == NULL)
 
593
                return  ISC_R_FAILURE;
 
594
 
 
595
        /* set fields */
 
596
        if (zone != NULL) {
 
597
                dbi->zone = isc_mem_strdup(ns_g_mctx, zone);
 
598
                if (dbi->zone == NULL) {
 
599
                        result = ISC_R_NOMEMORY;
 
600
                        goto cleanup;
 
601
                }
 
602
        } else {
 
603
                dbi->zone = NULL;
 
604
        }
 
605
        if (record != NULL) {
 
606
                dbi->record = isc_mem_strdup(ns_g_mctx, record);
 
607
                if (dbi->record == NULL) {
 
608
                        result = ISC_R_NOMEMORY;
 
609
                        goto cleanup;
 
610
                }
 
611
        } else {
 
612
                dbi->record = NULL;
 
613
        }
 
614
        if (client != NULL) {
 
615
                dbi->client = isc_mem_strdup(ns_g_mctx, client);
 
616
                if (dbi->client == NULL) {
 
617
                        result = ISC_R_NOMEMORY;
 
618
                        goto cleanup;
 
619
                }
 
620
        } else {
 
621
                dbi->client = NULL;
 
622
        }
 
623
 
 
624
        /* what type of query are we going to run? */
 
625
        switch(query) {
 
626
        case ALLNODES:
 
627
                /*
 
628
                 * if the query was not passed in from the config file
 
629
                 * then we can't run it.  return not_implemented, so
 
630
                 * it's like the code for that operation was never
 
631
                 * built into the driver.... AHHH flexibility!!!
 
632
                 */
 
633
                if (dbi->allnodes_q == NULL) {
 
634
                        result = ISC_R_NOTIMPLEMENTED;
 
635
                        goto cleanup;
 
636
                } else {
 
637
                        querystring = build_querystring(ns_g_mctx,
 
638
                        dbi->allnodes_q);
 
639
                }
 
640
                break;
 
641
        case ALLOWXFR:
 
642
                /* same as comments as ALLNODES */
 
643
                if (dbi->allowxfr_q == NULL) {
 
644
                        result = ISC_R_NOTIMPLEMENTED;
 
645
                        goto cleanup;
 
646
                } else {
 
647
                        querystring = build_querystring(ns_g_mctx,
 
648
                        dbi->allowxfr_q);
 
649
                }
 
650
                break;
 
651
        case AUTHORITY:
 
652
                /* same as comments as ALLNODES */
 
653
                if (dbi->authority_q == NULL) {
 
654
                        result = ISC_R_NOTIMPLEMENTED;
 
655
                        goto cleanup;
 
656
                } else {
 
657
                        querystring = build_querystring(ns_g_mctx,
 
658
                        dbi->authority_q);
 
659
                }
 
660
                break;
 
661
        case FINDZONE:
 
662
                /* this is required.  It's the whole point of DLZ! */
 
663
                if (dbi->findzone_q == NULL) {
 
664
                        isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
 
665
                                      DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),
 
666
                                      "No query specified for findzone.  "
 
667
                                      "Findzone requires a query");
 
668
                        result = ISC_R_FAILURE;
 
669
                        goto cleanup;
 
670
                } else {
 
671
                        querystring = build_querystring(ns_g_mctx,
 
672
                        dbi->findzone_q);
 
673
                }
 
674
                break;
 
675
        case LOOKUP:
 
676
                /* this is required.  It's also a major point of DLZ! */
 
677
                if (dbi->lookup_q == NULL) {
 
678
                        isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
 
679
                                      DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),
 
680
                                      "No query specified for lookup.  "
 
681
                                      "Lookup requires a query");
 
682
                        result = ISC_R_FAILURE;
 
683
                        goto cleanup;
 
684
                } else {
 
685
                        querystring = build_querystring(ns_g_mctx,
 
686
                                                        dbi->lookup_q);
 
687
                }
 
688
                break;
 
689
        default:
 
690
                /*
 
691
                 * this should never happen.  If it does, the code is
 
692
                 * screwed up!
 
693
                 */
 
694
                UNEXPECTED_ERROR(__FILE__, __LINE__,
 
695
                                 "Incorrect query flag passed to "
 
696
                                 "ldap_get_results");
 
697
                result = ISC_R_UNEXPECTED;
 
698
                goto cleanup;
 
699
        }
 
700
 
 
701
        /* if the querystring is null, Bummer, outta RAM.  UPGRADE TIME!!!   */
 
702
        if (querystring  == NULL) {
 
703
                result = ISC_R_NOMEMORY;
 
704
                goto cleanup;
 
705
        }
 
706
 
 
707
        /*
 
708
         * output the full query string during debug so we can see
 
709
         * what lame error the query has.
 
710
         */
 
711
        isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
 
712
                      DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(1),
 
713
                      "\nQuery String: %s\n", querystring);
 
714
 
 
715
        /* break URL down into it's component parts, if error cleanup */
 
716
        ldap_result = ldap_url_parse(querystring, &ldap_url);
 
717
        if (ldap_result != LDAP_SUCCESS || ldap_url == NULL) {
 
718
                result = ISC_R_FAILURE;
 
719
                goto cleanup;
 
720
        }
 
721
 
 
722
        for (i=0; i < 3; i++) {
 
723
 
 
724
                /*
 
725
                 * dbi->dbconn may be null if trying to reconnect on a
 
726
                 * previous query failed.
 
727
                 */
 
728
                if (dbi->dbconn == NULL) {
 
729
                        isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
 
730
                                      DNS_LOGMODULE_DLZ, ISC_LOG_INFO,
 
731
                                      "LDAP driver attempting to re-connect");
 
732
 
 
733
                        result = dlz_ldap_connect((ldap_instance_t *) dbdata,
 
734
                                                  dbi);
 
735
                        if (result != ISC_R_SUCCESS) {
 
736
                                result = ISC_R_FAILURE;
 
737
                                continue;
 
738
                        }
 
739
                }
 
740
 
 
741
                /* perform ldap search syncronously */
 
742
                ldap_result = ldap_search_s((LDAP *) dbi->dbconn,
 
743
                                            ldap_url->lud_dn,
 
744
                                            ldap_url->lud_scope,
 
745
                                            ldap_url->lud_filter,
 
746
                                            ldap_url->lud_attrs, 0, &ldap_msg);
 
747
 
 
748
                /*
 
749
                 * check return code.  No such object is ok, just
 
750
                 * didn't find what we wanted
 
751
                 */
 
752
                switch(ldap_result) {
 
753
                case LDAP_NO_SUCH_OBJECT:
 
754
                        isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
 
755
                                      DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(1),
 
756
                                      "No object found matching "
 
757
                                      "query requirements");
 
758
                        result = ISC_R_NOTFOUND;
 
759
                        goto cleanup;
 
760
                        break;
 
761
                case LDAP_SUCCESS:      /* on success do nothing */
 
762
                        result = ISC_R_SUCCESS;
 
763
                        i = 3;
 
764
                        break;
 
765
                case LDAP_SERVER_DOWN:
 
766
                        isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
 
767
                                      DNS_LOGMODULE_DLZ, ISC_LOG_INFO,
 
768
                                      "LDAP driver attempting to re-connect");
 
769
                        result = dlz_ldap_connect((ldap_instance_t *) dbdata,
 
770
                                                  dbi);
 
771
                        if (result != ISC_R_SUCCESS)
 
772
                                result = ISC_R_FAILURE;
 
773
                        break;
 
774
                default:
 
775
                        /*
 
776
                         * other errors not ok.  Log error message and
 
777
                         * get out
 
778
                         */
 
779
                        isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
 
780
                                      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
 
781
                                      "LDAP error: %s",
 
782
                                      ldap_err2string(ldap_result));
 
783
                        result = ISC_R_FAILURE;
 
784
                        goto cleanup;
 
785
                        break;
 
786
                } /* close switch(ldap_result) */
 
787
        } /* end for (int i=0 i < 3; i++) */
 
788
 
 
789
        if (result != ISC_R_SUCCESS)
 
790
                goto cleanup;
 
791
 
 
792
        switch(query) {
 
793
        case ALLNODES:
 
794
                result = ldap_process_results((LDAP *) dbi->dbconn, ldap_msg,
 
795
                                              ldap_url->lud_attrs,
 
796
                                              ptr, isc_boolean_true);
 
797
                break;
 
798
        case AUTHORITY:
 
799
        case LOOKUP:
 
800
                result = ldap_process_results((LDAP *) dbi->dbconn, ldap_msg,
 
801
                                              ldap_url->lud_attrs,
 
802
                                              ptr, isc_boolean_false);
 
803
                break;
 
804
        case ALLOWXFR:
 
805
                entries = ldap_count_entries((LDAP *) dbi->dbconn, ldap_msg);
 
806
                if (entries == 0)
 
807
                        result = ISC_R_NOPERM;
 
808
                else if (entries > 0)
 
809
                        result = ISC_R_SUCCESS;
 
810
                else
 
811
                        result = ISC_R_FAILURE;
 
812
                break;
 
813
        case FINDZONE:
 
814
                entries = ldap_count_entries((LDAP *) dbi->dbconn, ldap_msg);
 
815
                if (entries == 0)
 
816
                        result = ISC_R_NOTFOUND;
 
817
                else if (entries > 0)
 
818
                        result = ISC_R_SUCCESS;
 
819
                else
 
820
                        result = ISC_R_FAILURE;
 
821
                break;
 
822
        default:
 
823
                /*
 
824
                 * this should never happen.  If it does, the code is
 
825
                 * screwed up!
 
826
                 */
 
827
                UNEXPECTED_ERROR(__FILE__, __LINE__,
 
828
                                 "Incorrect query flag passed to "
 
829
                                 "ldap_get_results");
 
830
                result = ISC_R_UNEXPECTED;
 
831
        }
 
832
 
 
833
 
 
834
 cleanup:
 
835
        /* it's always good to cleanup after yourself */
 
836
 
 
837
        /* if we retrieved results, free them */
 
838
        if (ldap_msg != NULL)
 
839
                ldap_msgfree(ldap_msg);
 
840
 
 
841
        if (ldap_url != NULL)
 
842
                ldap_free_urldesc(ldap_url);
 
843
 
 
844
        /* cleanup */
 
845
        if (dbi->zone != NULL)
 
846
                isc_mem_free(ns_g_mctx, dbi->zone);
 
847
        if (dbi->record != NULL)
 
848
                isc_mem_free(ns_g_mctx, dbi->record);
 
849
        if (dbi->client != NULL)
 
850
                isc_mem_free(ns_g_mctx, dbi->client);
 
851
 
 
852
#ifdef ISC_PLATFORM_USETHREADS
 
853
 
 
854
        /* release the lock so another thread can use this dbi */
 
855
        isc_mutex_unlock(&dbi->instance_lock);
 
856
 
 
857
#endif /* ISC_PLATFORM_USETHREADS */
 
858
 
 
859
        /* release query string */
 
860
        if (querystring  != NULL)
 
861
                isc_mem_free(ns_g_mctx, querystring );
 
862
 
 
863
        /* return result */
 
864
        return result;
 
865
}
 
866
 
 
867
/*
 
868
 * DLZ methods
 
869
 */
 
870
 
 
871
static isc_result_t
 
872
dlz_ldap_allowzonexfr(void *driverarg, void *dbdata, const char *name,
 
873
                      const char *client)
 
874
{
 
875
        isc_result_t result;
 
876
 
 
877
        UNUSED(driverarg);
 
878
 
 
879
        /* check to see if we are authoritative for the zone first */
 
880
        result = dlz_ldap_findzone(driverarg, dbdata, name);
 
881
        if (result != ISC_R_SUCCESS) {
 
882
                return result;
 
883
        }
 
884
 
 
885
        /* get all the zone data */
 
886
        return ldap_get_results(name, NULL, client, ALLOWXFR, dbdata, NULL);
 
887
}
 
888
 
 
889
static isc_result_t
 
890
dlz_ldap_allnodes(const char *zone, void *driverarg, void *dbdata,
 
891
                  dns_sdlzallnodes_t *allnodes)
 
892
{
 
893
        UNUSED(driverarg);
 
894
        return ldap_get_results(zone, NULL, NULL, ALLNODES, dbdata, allnodes);
 
895
}
 
896
 
 
897
static isc_result_t
 
898
dlz_ldap_authority(const char *zone, void *driverarg, void *dbdata,
 
899
                   dns_sdlzlookup_t *lookup)
 
900
{
 
901
        UNUSED(driverarg);
 
902
        return ldap_get_results(zone, NULL, NULL, AUTHORITY, dbdata, lookup);
 
903
}
 
904
 
 
905
static isc_result_t
 
906
dlz_ldap_findzone(void *driverarg, void *dbdata, const char *name)
 
907
{
 
908
        UNUSED(driverarg);
 
909
        return ldap_get_results(name, NULL, NULL, FINDZONE, dbdata, NULL);
 
910
}
 
911
 
 
912
static isc_result_t
 
913
dlz_ldap_lookup(const char *zone, const char *name, void *driverarg,
 
914
                void *dbdata, dns_sdlzlookup_t *lookup)
 
915
{
 
916
        UNUSED(driverarg);
 
917
        if (strcmp(name, "*") == 0)
 
918
                return ldap_get_results(zone, "~", NULL,
 
919
                                        LOOKUP, dbdata, lookup);
 
920
        else
 
921
                return ldap_get_results(zone, name, NULL,
 
922
                                        LOOKUP, dbdata, lookup);
 
923
}
 
924
 
 
925
 
 
926
static isc_result_t
 
927
dlz_ldap_create(const char *dlzname, unsigned int argc, char *argv[],
 
928
                void *driverarg, void **dbdata)
 
929
{
 
930
 
 
931
        isc_result_t result;
 
932
        ldap_instance_t *ldap_inst = NULL;
 
933
        dbinstance_t *dbi = NULL;
 
934
        int protocol;
 
935
        int method;
 
936
 
 
937
#ifdef ISC_PLATFORM_USETHREADS
 
938
        /* if multi-threaded, we need a few extra variables. */
 
939
        int dbcount;
 
940
        char *endp;
 
941
/* db_list_t *dblist = NULL; */
 
942
        int i;
 
943
 
 
944
#endif /* ISC_PLATFORM_USETHREADS */
 
945
 
 
946
        UNUSED(dlzname);
 
947
        UNUSED(driverarg);
 
948
 
 
949
#ifdef ISC_PLATFORM_USETHREADS
 
950
        /* if debugging, let user know we are multithreaded. */
 
951
        isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
 
952
                      DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(1),
 
953
                      "LDAP driver running multithreaded");
 
954
#else /* ISC_PLATFORM_USETHREADS */
 
955
        /* if debugging, let user know we are single threaded. */
 
956
        isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
 
957
                      DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(1),
 
958
                      "LDAP driver running single threaded");
 
959
#endif /* ISC_PLATFORM_USETHREADS */
 
960
 
 
961
        if (argc < 9) {
 
962
                isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
 
963
                              DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
 
964
                              "LDAP driver requires at least "
 
965
                              "8 command line args.");
 
966
                return (ISC_R_FAILURE);
 
967
        }
 
968
 
 
969
        /* no more than 13 arg's should be passed to the driver */
 
970
        if (argc > 12) {
 
971
                isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
 
972
                              DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
 
973
                              "LDAP driver cannot accept more than "
 
974
                              "11 command line args.");
 
975
                return (ISC_R_FAILURE);
 
976
        }
 
977
 
 
978
        /* determine protocol version. */
 
979
        if (strncasecmp(argv[2], V2, strlen(V2)) == 0) {
 
980
                protocol = 2;
 
981
        } else if (strncasecmp(argv[2], V3, strlen(V3)) == 0) {
 
982
                protocol = 3;
 
983
        } else {
 
984
                isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
 
985
                              DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
 
986
                              "LDAP driver protocol must be either %s or %s",
 
987
                              V2, V3);
 
988
                return (ISC_R_FAILURE);
 
989
        }
 
990
 
 
991
        /* determine connection method. */
 
992
        if (strncasecmp(argv[3], SIMPLE, strlen(SIMPLE)) == 0) {
 
993
                method = LDAP_AUTH_SIMPLE;
 
994
        } else if (strncasecmp(argv[3], KRB41, strlen(KRB41)) == 0) {
 
995
                method = LDAP_AUTH_KRBV41;
 
996
        } else if (strncasecmp(argv[3], KRB42, strlen(KRB42)) == 0) {
 
997
                method = LDAP_AUTH_KRBV42;
 
998
        } else {
 
999
                isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
 
1000
                              DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
 
1001
                              "LDAP driver authentication method must be "
 
1002
                              "one of %s, %s or %s",
 
1003
                              SIMPLE, KRB41, KRB42);
 
1004
                return (ISC_R_FAILURE);
 
1005
        }
 
1006
 
 
1007
        /* multithreaded build can have multiple DB connections */
 
1008
#ifdef ISC_PLATFORM_USETHREADS
 
1009
 
 
1010
        /* check how many db connections we should create */
 
1011
        dbcount = strtol(argv[1], &endp, 10);
 
1012
        if (*endp != '\0' || dbcount < 0) {
 
1013
                isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
 
1014
                              DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
 
1015
                              "LDAP driver database connection count "
 
1016
                              "must be positive.");
 
1017
                return (ISC_R_FAILURE);
 
1018
        }
 
1019
#endif
 
1020
 
 
1021
        /* check that LDAP URL parameters make sense */
 
1022
        switch(argc) {
 
1023
        case 12:
 
1024
                result = dlz_ldap_checkURL(argv[11], 0, "allow zone transfer");
 
1025
                if (result != ISC_R_SUCCESS)
 
1026
                        return result;
 
1027
        case 11:
 
1028
                result = dlz_ldap_checkURL(argv[10], 3, "all nodes");
 
1029
                if (result != ISC_R_SUCCESS)
 
1030
                        return result;
 
1031
        case 10:
 
1032
                if (strlen(argv[9]) > 0) {
 
1033
                        result = dlz_ldap_checkURL(argv[9], 3, "authority");
 
1034
                        if (result != ISC_R_SUCCESS)
 
1035
                                return result;
 
1036
                }
 
1037
        case 9:
 
1038
                result = dlz_ldap_checkURL(argv[8], 3, "lookup");
 
1039
                if (result != ISC_R_SUCCESS)
 
1040
                        return result;
 
1041
                result = dlz_ldap_checkURL(argv[7], 0, "find zone");
 
1042
                if (result != ISC_R_SUCCESS)
 
1043
                        return result;
 
1044
                break;
 
1045
        default:
 
1046
                /* not really needed, should shut up compiler. */
 
1047
                result = ISC_R_FAILURE;
 
1048
        }
 
1049
 
 
1050
        /* allocate memory for LDAP instance */
 
1051
        ldap_inst = isc_mem_get(ns_g_mctx, sizeof(ldap_instance_t));
 
1052
        if (ldap_inst == NULL)
 
1053
                return (ISC_R_NOMEMORY);
 
1054
        memset(ldap_inst, 0, sizeof(ldap_instance_t));
 
1055
 
 
1056
        /* store info needed to automatically re-connect. */
 
1057
        ldap_inst->protocol = protocol;
 
1058
        ldap_inst->method = method;
 
1059
        ldap_inst->hosts = isc_mem_strdup(ns_g_mctx, argv[6]);
 
1060
        if (ldap_inst->hosts == NULL) {
 
1061
                result = ISC_R_NOMEMORY;
 
1062
                goto cleanup;
 
1063
        }
 
1064
        ldap_inst->user = isc_mem_strdup(ns_g_mctx, argv[4]);
 
1065
        if (ldap_inst->user == NULL) {
 
1066
                result = ISC_R_NOMEMORY;
 
1067
                goto cleanup;
 
1068
        }
 
1069
        ldap_inst->cred = isc_mem_strdup(ns_g_mctx, argv[5]);
 
1070
        if (ldap_inst->cred == NULL) {
 
1071
                result = ISC_R_NOMEMORY;
 
1072
                goto cleanup;
 
1073
        }
 
1074
 
 
1075
#ifdef ISC_PLATFORM_USETHREADS
 
1076
        /* allocate memory for database connection list */
 
1077
        ldap_inst->db = isc_mem_get(ns_g_mctx, sizeof(db_list_t));
 
1078
        if (ldap_inst->db == NULL) {
 
1079
                result = ISC_R_NOMEMORY;
 
1080
                goto cleanup;
 
1081
        }
 
1082
 
 
1083
        /* initialize DB connection list */
 
1084
        ISC_LIST_INIT(*(ldap_inst->db));
 
1085
 
 
1086
        /*
 
1087
         * create the appropriate number of database instances (DBI)
 
1088
         * append each new DBI to the end of the list
 
1089
         */
 
1090
        for (i = 0; i < dbcount; i++) {
 
1091
 
 
1092
#endif /* ISC_PLATFORM_USETHREADS */
 
1093
 
 
1094
                /* how many queries were passed in from config file? */
 
1095
                switch(argc) {
 
1096
                case 9:
 
1097
                        result = build_sqldbinstance(ns_g_mctx, NULL, NULL,
 
1098
                                                     NULL, argv[7], argv[8],
 
1099
                                                     NULL, &dbi);
 
1100
                        break;
 
1101
                case 10:
 
1102
                        result = build_sqldbinstance(ns_g_mctx, NULL, NULL,
 
1103
                                                     argv[9], argv[7], argv[8],
 
1104
                                                     NULL, &dbi);
 
1105
                        break;
 
1106
                case 11:
 
1107
                        result = build_sqldbinstance(ns_g_mctx, argv[10], NULL,
 
1108
                                                     argv[9], argv[7], argv[8],
 
1109
                                                     NULL, &dbi);
 
1110
                        break;
 
1111
                case 12:
 
1112
                        result = build_sqldbinstance(ns_g_mctx, argv[10],
 
1113
                                                     argv[11], argv[9],
 
1114
                                                     argv[7], argv[8],
 
1115
                                                     NULL, &dbi);
 
1116
                        break;
 
1117
                default:
 
1118
                        /* not really needed, should shut up compiler. */
 
1119
                        result = ISC_R_FAILURE;
 
1120
                }
 
1121
 
 
1122
                if (result == ISC_R_SUCCESS) {
 
1123
                        isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
 
1124
                                      DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),
 
1125
                                      "LDAP driver created "
 
1126
                                      "database instance object.");
 
1127
                } else { /* unsuccessful?, log err msg and cleanup. */
 
1128
                        isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
 
1129
                                      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
 
1130
                                      "LDAP driver could not create "
 
1131
                                      "database instance object.");
 
1132
                        goto cleanup;
 
1133
                }
 
1134
 
 
1135
#ifdef ISC_PLATFORM_USETHREADS
 
1136
                /* when multithreaded, build a list of DBI's */
 
1137
                ISC_LINK_INIT(dbi, link);
 
1138
                ISC_LIST_APPEND(*(ldap_inst->db), dbi, link);
 
1139
#else
 
1140
                /*
 
1141
                 * when single threaded, hold onto the one connection
 
1142
                 * instance.
 
1143
                 */
 
1144
                ldap_inst->db = dbi;
 
1145
 
 
1146
#endif
 
1147
                /* attempt to connect */
 
1148
                result = dlz_ldap_connect(ldap_inst, dbi);
 
1149
 
 
1150
                /*
 
1151
                 * if db connection cannot be created, log err msg and
 
1152
                 * cleanup.
 
1153
                 */
 
1154
                switch(result) {
 
1155
                        /* success, do nothing */
 
1156
                case ISC_R_SUCCESS:
 
1157
                        break;
 
1158
                        /*
 
1159
                         * no memory means ldap_init could not
 
1160
                         * allocate memory
 
1161
                         */
 
1162
                case ISC_R_NOMEMORY:
 
1163
#ifdef ISC_PLATFORM_USETHREADS
 
1164
                        isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
 
1165
                                      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
 
1166
                                      "LDAP driver could not allocate memory "
 
1167
                                      "for connection number %u",
 
1168
                                      i+1);
 
1169
#else
 
1170
                        isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
 
1171
                                      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
 
1172
                                      "LDAP driver could not allocate memory "
 
1173
                                      "for connection");
 
1174
#endif
 
1175
                        goto cleanup;
 
1176
                        break;
 
1177
                        /*
 
1178
                         * no perm means ldap_set_option could not set
 
1179
                         * protocol version
 
1180
                         */
 
1181
                case ISC_R_NOPERM:
 
1182
                        isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
 
1183
                                      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
 
1184
                                      "LDAP driver could not "
 
1185
                                      "set protocol version.");
 
1186
                        result = ISC_R_FAILURE;
 
1187
                        goto cleanup;
 
1188
                        break;
 
1189
                        /* failure means couldn't connect to ldap server */
 
1190
                case ISC_R_FAILURE:
 
1191
#ifdef ISC_PLATFORM_USETHREADS
 
1192
                        isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
 
1193
                                      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
 
1194
                                      "LDAP driver could not "
 
1195
                                      "bind connection number %u to server.",
 
1196
                                      i+1);
 
1197
#else
 
1198
                        isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
 
1199
                                      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
 
1200
                                      "LDAP driver could not "
 
1201
                                      "bind connection to server.");
 
1202
#endif
 
1203
                        goto cleanup;
 
1204
                        break;
 
1205
                        /*
 
1206
                         * default should never happen.  If it does,
 
1207
                         * major errors.
 
1208
                         */
 
1209
                default:
 
1210
                        UNEXPECTED_ERROR(__FILE__, __LINE__,
 
1211
                                         "dlz_ldap_create() failed: %s",
 
1212
                                         isc_result_totext(result));
 
1213
                        result = ISC_R_UNEXPECTED;
 
1214
                        goto cleanup;
 
1215
                        break;
 
1216
                } /* end switch(result) */
 
1217
 
 
1218
 
 
1219
#ifdef ISC_PLATFORM_USETHREADS
 
1220
 
 
1221
                /* set DBI = null for next loop through. */
 
1222
                dbi = NULL;
 
1223
        }       /* end for loop */
 
1224
 
 
1225
#endif /* ISC_PLATFORM_USETHREADS */
 
1226
 
 
1227
 
 
1228
        /* set dbdata to the ldap_instance we created. */
 
1229
        *dbdata = ldap_inst;
 
1230
 
 
1231
        /* hey, we got through all of that ok, return success. */
 
1232
        return(ISC_R_SUCCESS);
 
1233
 
 
1234
 cleanup:
 
1235
 
 
1236
        dlz_ldap_destroy(NULL, ldap_inst);
 
1237
 
 
1238
        return(ISC_R_FAILURE);
 
1239
}
 
1240
 
 
1241
void
 
1242
dlz_ldap_destroy(void *driverarg, void *dbdata)
 
1243
{
 
1244
 
 
1245
        UNUSED(driverarg);
 
1246
 
 
1247
        if (dbdata != NULL) {
 
1248
 
 
1249
#ifdef ISC_PLATFORM_USETHREADS
 
1250
 
 
1251
                /* cleanup the list of DBI's */
 
1252
                ldap_destroy_dblist((db_list_t *)
 
1253
                                    ((ldap_instance_t *)dbdata)->db);
 
1254
 
 
1255
#else /* ISC_PLATFORM_USETHREADS */
 
1256
 
 
1257
                /* release connection */
 
1258
                if (((ldap_instance_t *)dbdata)->db->dbconn != NULL)
 
1259
                        ldap_unbind_s((LDAP *)
 
1260
                                      ((ldap_instance_t *)dbdata)->db->dbconn);
 
1261
 
 
1262
                /* destroy single DB instance */
 
1263
                destroy_sqldbinstance(((ldap_instance_t *)dbdata)->db);
 
1264
 
 
1265
#endif /* ISC_PLATFORM_USETHREADS */
 
1266
 
 
1267
                if (((ldap_instance_t *)dbdata)->hosts != NULL)
 
1268
                        isc_mem_free(ns_g_mctx,
 
1269
                                     ((ldap_instance_t *)dbdata)->hosts);
 
1270
 
 
1271
                if (((ldap_instance_t *)dbdata)->user != NULL)
 
1272
                        isc_mem_free(ns_g_mctx,
 
1273
                                     ((ldap_instance_t *)dbdata)->user);
 
1274
 
 
1275
                if (((ldap_instance_t *)dbdata)->cred != NULL)
 
1276
                        isc_mem_free(ns_g_mctx,
 
1277
                                     ((ldap_instance_t *)dbdata)->cred);
 
1278
 
 
1279
                isc_mem_put(ns_g_mctx, dbdata, sizeof(ldap_instance_t));
 
1280
        }
 
1281
}
 
1282
 
 
1283
static dns_sdlzmethods_t dlz_ldap_methods = {
 
1284
        dlz_ldap_create,
 
1285
        dlz_ldap_destroy,
 
1286
        dlz_ldap_findzone,
 
1287
        dlz_ldap_lookup,
 
1288
        dlz_ldap_authority,
 
1289
        dlz_ldap_allnodes,
 
1290
        dlz_ldap_allowzonexfr
 
1291
};
 
1292
 
 
1293
/*%
 
1294
 * Wrapper around dns_sdlzregister().
 
1295
 */
 
1296
isc_result_t
 
1297
dlz_ldap_init(void) {
 
1298
        isc_result_t result;
 
1299
 
 
1300
        /*
 
1301
         * Write debugging message to log
 
1302
         */
 
1303
        isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
 
1304
                      DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),
 
1305
                      "Registering DLZ ldap driver.");
 
1306
 
 
1307
        result = dns_sdlzregister("ldap", &dlz_ldap_methods, NULL,
 
1308
                                  DNS_SDLZFLAG_RELATIVEOWNER |
 
1309
                                  DNS_SDLZFLAG_RELATIVERDATA,
 
1310
                                  ns_g_mctx, &dlz_ldap);
 
1311
        if (result != ISC_R_SUCCESS) {
 
1312
                UNEXPECTED_ERROR(__FILE__, __LINE__,
 
1313
                                 "dns_sdlzregister() failed: %s",
 
1314
                                 isc_result_totext(result));
 
1315
                result = ISC_R_UNEXPECTED;
 
1316
        }
 
1317
 
 
1318
 
 
1319
        return result;
 
1320
}
 
1321
 
 
1322
/*%
 
1323
 * Wrapper around dns_sdlzunregister().
 
1324
 */
 
1325
void
 
1326
dlz_ldap_clear(void) {
 
1327
 
 
1328
        /*
 
1329
         * Write debugging message to log
 
1330
         */
 
1331
        isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
 
1332
                      DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),
 
1333
                      "Unregistering DLZ ldap driver.");
 
1334
 
 
1335
        if (dlz_ldap != NULL)
 
1336
                dns_sdlzunregister(&dlz_ldap);
 
1337
}
 
1338
 
 
1339
#endif