]>
Commit | Line | Data |
---|---|---|
f1f8128e | 1 | diff -urN bind-9.2.3-orig/bin/named/Makefile.in bind-9.2.3/bin/named/Makefile.in |
2 | --- bind-9.2.3-orig/bin/named/Makefile.in 2001-05-31 18:45:00.000000000 -0600 | |
3 | +++ bind-9.2.3/bin/named/Makefile.in 2003-11-16 14:52:51.000000000 -0700 | |
4 | @@ -26,10 +26,10 @@ | |
5 | # | |
6 | # Add database drivers here. | |
7 | # | |
8 | -DBDRIVER_OBJS = | |
9 | -DBDRIVER_SRCS = | |
10 | +DBDRIVER_OBJS = ldapdb.@O@ | |
11 | +DBDRIVER_SRCS = ldapdb.c | |
12 | DBDRIVER_INCLUDES = | |
13 | -DBDRIVER_LIBS = | |
14 | +DBDRIVER_LIBS = -lldap -llber -lresolv | |
15 | ||
16 | CINCLUDES = -I${srcdir}/include -I${srcdir}/unix/include \ | |
17 | ${LWRES_INCLUDES} ${DNS_INCLUDES} \ | |
18 | diff -urN bind-9.2.3-orig/bin/named/include/ldapdb.h bind-9.2.3/bin/named/include/ldapdb.h | |
19 | --- bind-9.2.3-orig/bin/named/include/ldapdb.h 1969-12-31 17:00:00.000000000 -0700 | |
20 | +++ bind-9.2.3/bin/named/include/ldapdb.h 2003-11-16 14:52:51.000000000 -0700 | |
21 | @@ -0,0 +1,6 @@ | |
22 | +#include <isc/types.h> | |
23 | + | |
24 | +isc_result_t ldapdb_init(void); | |
25 | + | |
26 | +void ldapdb_clear(void); | |
27 | + | |
28 | diff -urN bind-9.2.3-orig/bin/named/ldapdb.c bind-9.2.3/bin/named/ldapdb.c | |
29 | --- bind-9.2.3-orig/bin/named/ldapdb.c 1969-12-31 17:00:00.000000000 -0700 | |
30 | +++ bind-9.2.3/bin/named/ldapdb.c 2003-11-16 14:52:51.000000000 -0700 | |
a37d2a21 | 31 | @@ -0,0 +1,667 @@ |
f1f8128e | 32 | +/* |
a37d2a21 | 33 | + * ldapdb.c version 1.0-beta |
f1f8128e | 34 | + * |
a37d2a21 | 35 | + * Copyright (C) 2002, 2004 Stig Venaas |
f1f8128e | 36 | + * |
37 | + * Permission to use, copy, modify, and distribute this software for any | |
38 | + * purpose with or without fee is hereby granted, provided that the above | |
39 | + * copyright notice and this permission notice appear in all copies. | |
a37d2a21 | 40 | + * |
41 | + * Contributors: Jeremy C. McDermond | |
42 | + */ | |
43 | + | |
44 | +/* | |
45 | + * If you want to use TLS, uncomment the define below | |
f1f8128e | 46 | + */ |
a37d2a21 | 47 | +/* #define LDAPDB_TLS */ |
f1f8128e | 48 | + |
49 | +/* | |
50 | + * If you are using an old LDAP API uncomment the define below. Only do this | |
51 | + * if you know what you're doing or get compilation errors on ldap_memfree(). | |
a37d2a21 | 52 | + * This also forces LDAPv2. |
f1f8128e | 53 | + */ |
a37d2a21 | 54 | +/* #define LDAPDB_RFC1823API */ |
55 | + | |
56 | +/* Using LDAPv3 by default, change this if you want v2 */ | |
57 | +#ifndef LDAPDB_LDAP_VERSION | |
58 | +#define LDAPDB_LDAP_VERSION 3 | |
59 | +#endif | |
f1f8128e | 60 | + |
61 | +#include <config.h> | |
62 | + | |
63 | +#include <string.h> | |
64 | +#include <stdio.h> | |
65 | +#include <stdlib.h> | |
66 | +#include <ctype.h> | |
67 | + | |
68 | +#include <isc/mem.h> | |
69 | +#include <isc/print.h> | |
70 | +#include <isc/result.h> | |
71 | +#include <isc/util.h> | |
72 | +#include <isc/thread.h> | |
73 | + | |
74 | +#include <dns/sdb.h> | |
75 | + | |
76 | +#include <named/globals.h> | |
77 | +#include <named/log.h> | |
78 | + | |
79 | +#include <ldap.h> | |
80 | +#include "ldapdb.h" | |
81 | + | |
82 | +/* | |
83 | + * A simple database driver for LDAP | |
84 | + */ | |
85 | + | |
86 | +/* enough for name with 8 labels of max length */ | |
87 | +#define MAXNAMELEN 519 | |
88 | + | |
89 | +static dns_sdbimplementation_t *ldapdb = NULL; | |
90 | + | |
91 | +struct ldapdb_data { | |
92 | + char *hostport; | |
93 | + char *hostname; | |
94 | + int portno; | |
95 | + char *base; | |
96 | + int defaultttl; | |
97 | + char *filterall; | |
98 | + int filteralllen; | |
99 | + char *filterone; | |
100 | + int filteronelen; | |
101 | + char *filtername; | |
a37d2a21 | 102 | + char *bindname; |
103 | + char *bindpw; | |
104 | +#ifdef LDAPDB_TLS | |
105 | + int tls; | |
106 | +#endif | |
f1f8128e | 107 | +}; |
108 | + | |
109 | +/* used by ldapdb_getconn */ | |
110 | + | |
111 | +struct ldapdb_entry { | |
112 | + void *index; | |
113 | + size_t size; | |
114 | + void *data; | |
115 | + struct ldapdb_entry *next; | |
116 | +}; | |
117 | + | |
118 | +static struct ldapdb_entry *ldapdb_find(struct ldapdb_entry *stack, | |
119 | + const void *index, size_t size) { | |
120 | + while (stack != NULL) { | |
121 | + if (stack->size == size && !memcmp(stack->index, index, size)) | |
122 | + return stack; | |
123 | + stack = stack->next; | |
124 | + } | |
125 | + return NULL; | |
126 | +} | |
127 | + | |
128 | +static void ldapdb_insert(struct ldapdb_entry **stack, | |
129 | + struct ldapdb_entry *item) { | |
130 | + item->next = *stack; | |
131 | + *stack = item; | |
132 | +} | |
133 | + | |
134 | +static void ldapdb_lock(int what) { | |
135 | + static isc_mutex_t lock; | |
136 | + | |
137 | + switch (what) { | |
138 | + case 0: | |
139 | + isc_mutex_init(&lock); | |
140 | + break; | |
141 | + case 1: | |
142 | + LOCK(&lock); | |
143 | + break; | |
144 | + case -1: | |
145 | + UNLOCK(&lock); | |
146 | + break; | |
147 | + } | |
148 | +} | |
149 | + | |
150 | +/* data == NULL means cleanup */ | |
151 | +static LDAP ** | |
152 | +ldapdb_getconn(struct ldapdb_data *data) | |
153 | +{ | |
154 | + static struct ldapdb_entry *allthreadsdata = NULL; | |
155 | + struct ldapdb_entry *threaddata, *conndata; | |
156 | + unsigned long threadid; | |
157 | + | |
158 | + if (data == NULL) { | |
159 | + /* cleanup */ | |
160 | + /* lock out other threads */ | |
161 | + ldapdb_lock(1); | |
162 | + while (allthreadsdata != NULL) { | |
163 | + threaddata = allthreadsdata; | |
164 | + free(threaddata->index); | |
165 | + while (threaddata->data != NULL) { | |
166 | + conndata = threaddata->data; | |
167 | + free(conndata->index); | |
168 | + if (conndata->data != NULL) | |
169 | + ldap_unbind((LDAP *)conndata->data); | |
170 | + threaddata->data = conndata->next; | |
171 | + free(conndata); | |
172 | + } | |
173 | + allthreadsdata = threaddata->next; | |
174 | + free(threaddata); | |
175 | + } | |
176 | + ldapdb_lock(-1); | |
177 | + return (NULL); | |
178 | + } | |
179 | + | |
180 | + /* look for connection data for current thread */ | |
181 | + threadid = isc_thread_self(); | |
182 | + threaddata = ldapdb_find(allthreadsdata, &threadid, sizeof(threadid)); | |
183 | + if (threaddata == NULL) { | |
184 | + /* no data for this thread, create empty connection list */ | |
185 | + threaddata = malloc(sizeof(*threaddata)); | |
186 | + if (threaddata == NULL) | |
187 | + return (NULL); | |
188 | + threaddata->index = malloc(sizeof(threadid)); | |
189 | + if (threaddata->index == NULL) { | |
190 | + free(threaddata); | |
191 | + return (NULL); | |
192 | + } | |
193 | + *(unsigned long *)threaddata->index = threadid; | |
194 | + threaddata->size = sizeof(threadid); | |
195 | + threaddata->data = NULL; | |
196 | + | |
197 | + /* need to lock out other threads here */ | |
198 | + ldapdb_lock(1); | |
199 | + ldapdb_insert(&allthreadsdata, threaddata); | |
200 | + ldapdb_lock(-1); | |
201 | + } | |
202 | + | |
203 | + /* threaddata points at the connection list for current thread */ | |
204 | + /* look for existing connection to our server */ | |
205 | + conndata = ldapdb_find((struct ldapdb_entry *)threaddata->data, | |
206 | + data->hostport, strlen(data->hostport)); | |
207 | + if (conndata == NULL) { | |
208 | + /* no connection data structure for this server, create one */ | |
209 | + conndata = malloc(sizeof(*conndata)); | |
210 | + if (conndata == NULL) | |
211 | + return (NULL); | |
a37d2a21 | 212 | + conndata->index = data->hostport; |
f1f8128e | 213 | + conndata->size = strlen(data->hostport); |
214 | + conndata->data = NULL; | |
215 | + ldapdb_insert((struct ldapdb_entry **)&threaddata->data, | |
216 | + conndata); | |
217 | + } | |
218 | + | |
219 | + return (LDAP **)&conndata->data; | |
220 | +} | |
221 | + | |
222 | +static void | |
223 | +ldapdb_bind(struct ldapdb_data *data, LDAP **ldp) | |
224 | +{ | |
a37d2a21 | 225 | +#ifndef LDAPDB_RFC1823API |
226 | + const int ver = LDAPDB_LDAP_VERSION; | |
227 | +#endif | |
228 | + | |
f1f8128e | 229 | + if (*ldp != NULL) |
230 | + ldap_unbind(*ldp); | |
231 | + *ldp = ldap_open(data->hostname, data->portno); | |
232 | + if (*ldp == NULL) | |
233 | + return; | |
a37d2a21 | 234 | + |
235 | +#ifndef LDAPDB_RFC1823API | |
236 | + ldap_set_option(*ldp, LDAP_OPT_PROTOCOL_VERSION, &ver); | |
237 | +#endif | |
238 | + | |
239 | +#ifdef LDAPDB_TLS | |
240 | + if (data->tls) { | |
241 | + ldap_start_tls_s(*ldp, NULL, NULL); | |
242 | + } | |
243 | +#endif | |
244 | + | |
245 | + if (ldap_simple_bind_s(*ldp, data->bindname, data->bindpw) != LDAP_SUCCESS) { | |
f1f8128e | 246 | + ldap_unbind(*ldp); |
247 | + *ldp = NULL; | |
248 | + } | |
249 | +} | |
250 | + | |
251 | +static isc_result_t | |
252 | +ldapdb_search(const char *zone, const char *name, void *dbdata, void *retdata) | |
253 | +{ | |
254 | + struct ldapdb_data *data = dbdata; | |
255 | + isc_result_t result = ISC_R_NOTFOUND; | |
256 | + LDAP **ldp; | |
257 | + LDAPMessage *res, *e; | |
a37d2a21 | 258 | + char *fltr, *a, **vals = NULL, **names = NULL; |
f1f8128e | 259 | + char type[64]; |
a37d2a21 | 260 | +#ifdef LDAPDB_RFC1823API |
f1f8128e | 261 | + void *ptr; |
262 | +#else | |
263 | + BerElement *ptr; | |
264 | +#endif | |
265 | + int i, j, errno, msgid; | |
266 | + | |
267 | + ldp = ldapdb_getconn(data); | |
268 | + if (ldp == NULL) | |
269 | + return (ISC_R_FAILURE); | |
270 | + if (*ldp == NULL) { | |
271 | + ldapdb_bind(data, ldp); | |
272 | + if (*ldp == NULL) { | |
273 | + isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR, | |
274 | + "LDAP sdb zone '%s': bind failed", zone); | |
275 | + return (ISC_R_FAILURE); | |
276 | + } | |
277 | + } | |
278 | + | |
279 | + if (name == NULL) { | |
280 | + fltr = data->filterall; | |
281 | + } else { | |
282 | + if (strlen(name) > MAXNAMELEN) { | |
283 | + isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR, | |
284 | + "LDAP sdb zone '%s': name %s too long", zone, name); | |
285 | + return (ISC_R_FAILURE); | |
286 | + } | |
287 | + sprintf(data->filtername, "%s))", name); | |
288 | + fltr = data->filterone; | |
289 | + } | |
290 | + | |
291 | + msgid = ldap_search(*ldp, data->base, LDAP_SCOPE_SUBTREE, fltr, NULL, 0); | |
292 | + if (msgid == -1) { | |
293 | + ldapdb_bind(data, ldp); | |
294 | + if (*ldp != NULL) | |
295 | + msgid = ldap_search(*ldp, data->base, LDAP_SCOPE_SUBTREE, fltr, NULL, 0); | |
296 | + } | |
297 | + | |
298 | + if (*ldp == NULL || msgid == -1) { | |
299 | + isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR, | |
300 | + "LDAP sdb zone '%s': search failed, filter %s", zone, fltr); | |
301 | + return (ISC_R_FAILURE); | |
302 | + } | |
303 | + | |
304 | + /* Get the records one by one as they arrive and return them to bind */ | |
305 | + while ((errno = ldap_result(*ldp, msgid, 0, NULL, &res)) != LDAP_RES_SEARCH_RESULT ) { | |
306 | + LDAP *ld = *ldp; | |
307 | + int ttl = data->defaultttl; | |
308 | + | |
309 | + /* not supporting continuation references at present */ | |
310 | + if (errno != LDAP_RES_SEARCH_ENTRY) { | |
311 | + isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR, | |
312 | + "LDAP sdb zone '%s': ldap_result returned %d", zone, errno); | |
313 | + ldap_msgfree(res); | |
314 | + return (ISC_R_FAILURE); | |
315 | + } | |
316 | + | |
317 | + /* only one entry per result message */ | |
318 | + e = ldap_first_entry(ld, res); | |
319 | + if (e == NULL) { | |
320 | + ldap_msgfree(res); | |
321 | + isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR, | |
322 | + "LDAP sdb zone '%s': ldap_first_entry failed", zone); | |
323 | + return (ISC_R_FAILURE); | |
324 | + } | |
325 | + | |
326 | + if (name == NULL) { | |
327 | + names = ldap_get_values(ld, e, "relativeDomainName"); | |
328 | + if (names == NULL) | |
329 | + continue; | |
330 | + } | |
331 | + | |
332 | + vals = ldap_get_values(ld, e, "dNSTTL"); | |
333 | + if (vals != NULL) { | |
334 | + ttl = atoi(vals[0]); | |
335 | + ldap_value_free(vals); | |
336 | + } | |
337 | + | |
338 | + for (a = ldap_first_attribute(ld, e, &ptr); a != NULL; a = ldap_next_attribute(ld, e, ptr)) { | |
339 | + char *s; | |
340 | + | |
341 | + for (s = a; *s; s++) | |
342 | + *s = toupper(*s); | |
343 | + s = strstr(a, "RECORD"); | |
344 | + if ((s == NULL) || (s == a) || (s - a >= (signed int)sizeof(type))) { | |
a37d2a21 | 345 | +#ifndef LDAPDB_RFC1823API |
f1f8128e | 346 | + ldap_memfree(a); |
347 | +#endif | |
348 | + continue; | |
349 | + } | |
350 | + | |
351 | + strncpy(type, a, s - a); | |
352 | + type[s - a] = '\0'; | |
353 | + vals = ldap_get_values(ld, e, a); | |
354 | + if (vals != NULL) { | |
355 | + for (i = 0; vals[i] != NULL; i++) { | |
356 | + if (name != NULL) { | |
357 | + result = dns_sdb_putrr(retdata, type, ttl, vals[i]); | |
358 | + } else { | |
359 | + for (j = 0; names[j] != NULL; j++) { | |
360 | + result = dns_sdb_putnamedrr(retdata, names[j], type, ttl, vals[i]); | |
361 | + if (result != ISC_R_SUCCESS) | |
362 | + break; | |
363 | + } | |
364 | + } | |
365 | +; if (result != ISC_R_SUCCESS) { | |
366 | + isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR, | |
367 | + "LDAP sdb zone '%s': dns_sdb_put... failed for %s", zone, vals[i]); | |
368 | + ldap_value_free(vals); | |
a37d2a21 | 369 | +#ifndef LDAPDB_RFC1823API |
f1f8128e | 370 | + ldap_memfree(a); |
371 | + if (ptr != NULL) | |
372 | + ber_free(ptr, 0); | |
373 | +#endif | |
374 | + if (name == NULL) | |
375 | + ldap_value_free(names); | |
376 | + ldap_msgfree(res); | |
377 | + return (ISC_R_FAILURE); | |
378 | + } | |
379 | + } | |
380 | + ldap_value_free(vals); | |
381 | + } | |
a37d2a21 | 382 | +#ifndef LDAPDB_RFC1823API |
f1f8128e | 383 | + ldap_memfree(a); |
384 | +#endif | |
385 | + } | |
a37d2a21 | 386 | +#ifndef LDAPDB_RFC1823API |
f1f8128e | 387 | + if (ptr != NULL) |
388 | + ber_free(ptr, 0); | |
389 | +#endif | |
390 | + if (name == NULL) | |
391 | + ldap_value_free(names); | |
392 | + | |
a37d2a21 | 393 | + /* free this result */ |
f1f8128e | 394 | + ldap_msgfree(res); |
395 | + } | |
396 | + | |
a37d2a21 | 397 | + /* free final result */ |
398 | + ldap_msgfree(res); | |
f1f8128e | 399 | + return (result); |
400 | +} | |
401 | + | |
402 | + | |
403 | +/* callback routines */ | |
404 | +static isc_result_t | |
405 | +ldapdb_lookup(const char *zone, const char *name, void *dbdata, | |
406 | + dns_sdblookup_t *lookup) | |
407 | +{ | |
408 | + return ldapdb_search(zone, name, dbdata, lookup); | |
409 | +} | |
410 | + | |
411 | +static isc_result_t | |
412 | +ldapdb_allnodes(const char *zone, void *dbdata, | |
413 | + dns_sdballnodes_t *allnodes) | |
414 | +{ | |
415 | + return ldapdb_search(zone, NULL, dbdata, allnodes); | |
416 | +} | |
417 | + | |
418 | +static char * | |
419 | +unhex(char *in) | |
420 | +{ | |
421 | + static const char hexdigits[] = "0123456789abcdef"; | |
422 | + char *p, *s = in; | |
423 | + int d1, d2; | |
424 | + | |
425 | + while ((s = strchr(s, '%'))) { | |
426 | + if (!(s[1] && s[2])) | |
427 | + return NULL; | |
428 | + if ((p = strchr(hexdigits, tolower(s[1]))) == NULL) | |
429 | + return NULL; | |
430 | + d1 = p - hexdigits; | |
431 | + if ((p = strchr(hexdigits, tolower(s[2]))) == NULL) | |
432 | + return NULL; | |
433 | + d2 = p - hexdigits; | |
434 | + *s++ = d1 << 4 | d2; | |
435 | + memmove(s, s + 2, strlen(s) - 1); | |
436 | + } | |
437 | + return in; | |
438 | +} | |
439 | + | |
a37d2a21 | 440 | +/* returns 0 for ok, -1 for bad syntax, -2 for unknown critical extension */ |
441 | +static int | |
442 | +parseextensions(char *extensions, struct ldapdb_data *data) | |
443 | +{ | |
444 | + char *s, *next, *name, *value; | |
445 | + int critical; | |
446 | + | |
447 | + while (extensions != NULL) { | |
448 | + s = strchr(extensions, ','); | |
449 | + if (s != NULL) { | |
450 | + *s++ = '\0'; | |
451 | + next = s; | |
452 | + } else { | |
453 | + next = NULL; | |
454 | + } | |
455 | + | |
456 | + if (*extensions != '\0') { | |
457 | + s = strchr(extensions, '='); | |
458 | + if (s != NULL) { | |
459 | + *s++ = '\0'; | |
460 | + value = *s != '\0' ? s : NULL; | |
461 | + } else { | |
462 | + value = NULL; | |
463 | + } | |
464 | + name = extensions; | |
f1f8128e | 465 | + |
a37d2a21 | 466 | + critical = *name == '!'; |
467 | + if (critical) { | |
468 | + name++; | |
469 | + } | |
470 | + if (*name == '\0') { | |
471 | + return -1; | |
472 | + } | |
473 | + | |
474 | + if (!strcasecmp(name, "bindname")) { | |
475 | + data->bindname = value; | |
476 | + } else if (!strcasecmp(name, "x-bindpw")) { | |
477 | + data->bindpw = value; | |
478 | +#ifdef LDAPDB_TLS | |
479 | + } else if (!strcasecmp(name, "x-tls")) { | |
480 | + data->tls = value == NULL || !strcasecmp(value, "true"); | |
481 | +#endif | |
482 | + } else if (critical) { | |
483 | + return -2; | |
484 | + } | |
485 | + } | |
486 | + extensions = next; | |
487 | + } | |
488 | + return 0; | |
489 | +} | |
f1f8128e | 490 | + |
491 | +static void | |
492 | +free_data(struct ldapdb_data *data) | |
493 | +{ | |
494 | + if (data->hostport != NULL) | |
495 | + isc_mem_free(ns_g_mctx, data->hostport); | |
496 | + if (data->hostname != NULL) | |
497 | + isc_mem_free(ns_g_mctx, data->hostname); | |
498 | + if (data->filterall != NULL) | |
499 | + isc_mem_put(ns_g_mctx, data->filterall, data->filteralllen); | |
500 | + if (data->filterone != NULL) | |
501 | + isc_mem_put(ns_g_mctx, data->filterone, data->filteronelen); | |
502 | + isc_mem_put(ns_g_mctx, data, sizeof(struct ldapdb_data)); | |
503 | +} | |
504 | + | |
505 | + | |
506 | +static isc_result_t | |
507 | +ldapdb_create(const char *zone, int argc, char **argv, | |
508 | + void *driverdata, void **dbdata) | |
509 | +{ | |
510 | + struct ldapdb_data *data; | |
a37d2a21 | 511 | + char *s, *filter = NULL, *extensions = NULL; |
f1f8128e | 512 | + int defaultttl; |
513 | + | |
514 | + UNUSED(driverdata); | |
515 | + | |
516 | + /* we assume that only one thread will call create at a time */ | |
517 | + /* want to do this only once for all instances */ | |
518 | + | |
519 | + if ((argc < 2) | |
520 | + || (argv[0] != strstr( argv[0], "ldap://")) | |
521 | + || ((defaultttl = atoi(argv[1])) < 1)) | |
522 | + return (ISC_R_FAILURE); | |
523 | + data = isc_mem_get(ns_g_mctx, sizeof(struct ldapdb_data)); | |
524 | + if (data == NULL) | |
525 | + return (ISC_R_NOMEMORY); | |
526 | + | |
527 | + memset(data, 0, sizeof(struct ldapdb_data)); | |
528 | + data->hostport = isc_mem_strdup(ns_g_mctx, argv[0] + strlen("ldap://")); | |
529 | + if (data->hostport == NULL) { | |
530 | + free_data(data); | |
531 | + return (ISC_R_NOMEMORY); | |
532 | + } | |
533 | + | |
534 | + data->defaultttl = defaultttl; | |
535 | + | |
536 | + s = strchr(data->hostport, '/'); | |
537 | + if (s != NULL) { | |
538 | + *s++ = '\0'; | |
539 | + data->base = s; | |
540 | + /* attrs, scope, filter etc? */ | |
541 | + s = strchr(s, '?'); | |
542 | + if (s != NULL) { | |
543 | + *s++ = '\0'; | |
544 | + /* ignore attributes */ | |
545 | + s = strchr(s, '?'); | |
546 | + if (s != NULL) { | |
547 | + *s++ = '\0'; | |
548 | + /* ignore scope */ | |
549 | + s = strchr(s, '?'); | |
550 | + if (s != NULL) { | |
551 | + *s++ = '\0'; | |
552 | + /* filter */ | |
553 | + filter = s; | |
554 | + s = strchr(s, '?'); | |
555 | + if (s != NULL) { | |
556 | + *s++ = '\0'; | |
a37d2a21 | 557 | + /* extensions */ |
558 | + extensions = s; | |
559 | + s = strchr(s, '?'); | |
560 | + if (s != NULL) { | |
561 | + *s++ = '\0'; | |
562 | + } | |
563 | + if (*extensions == '\0') { | |
564 | + extensions = NULL; | |
565 | + } | |
f1f8128e | 566 | + } |
567 | + if (*filter == '\0') { | |
568 | + filter = NULL; | |
569 | + } | |
570 | + } | |
571 | + } | |
572 | + } | |
573 | + if (*data->base == '\0') { | |
574 | + data->base = NULL; | |
575 | + } | |
a37d2a21 | 576 | + } |
577 | + | |
578 | + /* parse extensions */ | |
579 | + if (extensions != NULL) { | |
580 | + int err; | |
f1f8128e | 581 | + |
a37d2a21 | 582 | + err = parseextensions(extensions, data); |
583 | + if (err < 0) { | |
584 | + /* err should be -1 or -2 */ | |
f1f8128e | 585 | + free_data(data); |
a37d2a21 | 586 | + if (err == -1) { |
587 | + isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR, | |
588 | + "LDAP sdb zone '%s': URL: extension syntax error", zone); | |
589 | + } else if (err == -2) { | |
590 | + isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR, | |
591 | + "LDAP sdb zone '%s': URL: unknown critical extension", zone); | |
592 | + } | |
f1f8128e | 593 | + return (ISC_R_FAILURE); |
594 | + } | |
595 | + } | |
596 | + | |
a37d2a21 | 597 | + if ((data->base != NULL && unhex(data->base) == NULL) || |
598 | + (filter != NULL && unhex(filter) == NULL) || | |
599 | + (data->bindname != NULL && unhex(data->bindname) == NULL) || | |
600 | + (data->bindpw != NULL && unhex(data->bindpw) == NULL)) { | |
601 | + free_data(data); | |
602 | + isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_SERVER, ISC_LOG_ERROR, | |
603 | + "LDAP sdb zone '%s': URL: bad hex values", zone); | |
604 | + return (ISC_R_FAILURE); | |
605 | + } | |
606 | + | |
f1f8128e | 607 | + /* compute filterall and filterone once and for all */ |
608 | + if (filter == NULL) { | |
609 | + data->filteralllen = strlen(zone) + strlen("(zoneName=)") + 1; | |
610 | + data->filteronelen = strlen(zone) + strlen("(&(zoneName=)(relativeDomainName=))") + MAXNAMELEN + 1; | |
611 | + } else { | |
612 | + data->filteralllen = strlen(filter) + strlen(zone) + strlen("(&(zoneName=))") + 1; | |
613 | + data->filteronelen = strlen(filter) + strlen(zone) + strlen("(&(zoneName=)(relativeDomainName=))") + MAXNAMELEN + 1; | |
614 | + } | |
615 | + | |
616 | + data->filterall = isc_mem_get(ns_g_mctx, data->filteralllen); | |
617 | + if (data->filterall == NULL) { | |
618 | + free_data(data); | |
619 | + return (ISC_R_NOMEMORY); | |
620 | + } | |
621 | + data->filterone = isc_mem_get(ns_g_mctx, data->filteronelen); | |
622 | + if (data->filterone == NULL) { | |
623 | + free_data(data); | |
624 | + return (ISC_R_NOMEMORY); | |
625 | + } | |
626 | + | |
627 | + if (filter == NULL) { | |
628 | + sprintf(data->filterall, "(zoneName=%s)", zone); | |
629 | + sprintf(data->filterone, "(&(zoneName=%s)(relativeDomainName=", zone); | |
630 | + } else { | |
631 | + sprintf(data->filterall, "(&%s(zoneName=%s))", filter, zone); | |
632 | + sprintf(data->filterone, "(&%s(zoneName=%s)(relativeDomainName=", filter, zone); | |
633 | + } | |
634 | + data->filtername = data->filterone + strlen(data->filterone); | |
635 | + | |
636 | + /* support URLs with literal IPv6 addresses */ | |
637 | + data->hostname = isc_mem_strdup(ns_g_mctx, data->hostport + (*data->hostport == '[' ? 1 : 0)); | |
638 | + if (data->hostname == NULL) { | |
639 | + free_data(data); | |
640 | + return (ISC_R_NOMEMORY); | |
641 | + } | |
642 | + | |
643 | + if (*data->hostport == '[' && | |
644 | + (s = strchr(data->hostname, ']')) != NULL ) | |
645 | + *s++ = '\0'; | |
646 | + else | |
647 | + s = data->hostname; | |
648 | + s = strchr(s, ':'); | |
649 | + if (s != NULL) { | |
650 | + *s++ = '\0'; | |
651 | + data->portno = atoi(s); | |
652 | + } else | |
653 | + data->portno = LDAP_PORT; | |
654 | + | |
655 | + *dbdata = data; | |
656 | + return (ISC_R_SUCCESS); | |
657 | +} | |
658 | + | |
659 | +static void | |
660 | +ldapdb_destroy(const char *zone, void *driverdata, void **dbdata) { | |
661 | + struct ldapdb_data *data = *dbdata; | |
662 | + | |
663 | + UNUSED(zone); | |
664 | + UNUSED(driverdata); | |
665 | + | |
666 | + free_data(data); | |
667 | +} | |
668 | + | |
669 | +static dns_sdbmethods_t ldapdb_methods = { | |
670 | + ldapdb_lookup, | |
671 | + NULL, /* authority */ | |
672 | + ldapdb_allnodes, | |
673 | + ldapdb_create, | |
674 | + ldapdb_destroy | |
675 | +}; | |
676 | + | |
677 | +/* Wrapper around dns_sdb_register() */ | |
678 | +isc_result_t | |
679 | +ldapdb_init(void) { | |
680 | + unsigned int flags = | |
681 | + DNS_SDBFLAG_RELATIVEOWNER | | |
682 | + DNS_SDBFLAG_RELATIVERDATA | | |
683 | + DNS_SDBFLAG_THREADSAFE; | |
684 | + | |
685 | + ldapdb_lock(0); | |
686 | + return (dns_sdb_register("ldap", &ldapdb_methods, NULL, flags, | |
687 | + ns_g_mctx, &ldapdb)); | |
688 | +} | |
689 | + | |
690 | +/* Wrapper around dns_sdb_unregister() */ | |
691 | +void | |
692 | +ldapdb_clear(void) { | |
693 | + if (ldapdb != NULL) { | |
694 | + /* clean up thread data */ | |
695 | + ldapdb_getconn(NULL); | |
696 | + dns_sdb_unregister(&ldapdb); | |
697 | + } | |
698 | +} | |
699 | diff -urN bind-9.2.3-orig/bin/named/main.c bind-9.2.3/bin/named/main.c | |
700 | --- bind-9.2.3-orig/bin/named/main.c 2003-10-09 01:32:33.000000000 -0600 | |
701 | +++ bind-9.2.3/bin/named/main.c 2003-11-16 14:52:51.000000000 -0700 | |
702 | @@ -64,6 +64,7 @@ | |
703 | * Include header files for database drivers here. | |
704 | */ | |
705 | /* #include "xxdb.h" */ | |
706 | +#include <ldapdb.h> | |
707 | ||
708 | static isc_boolean_t want_stats = ISC_FALSE; | |
709 | static char program_name[ISC_DIR_NAMEMAX] = "named"; | |
710 | @@ -544,6 +545,7 @@ | |
711 | * Add calls to register sdb drivers here. | |
712 | */ | |
713 | /* xxdb_init(); */ | |
714 | + ldapdb_init(); | |
715 | ||
716 | ns_server_create(ns_g_mctx, &ns_g_server); | |
717 | } | |
718 | @@ -558,6 +560,7 @@ | |
719 | * Add calls to unregister sdb drivers here. | |
720 | */ | |
721 | /* xxdb_clear(); */ | |
722 | + ldapdb_clear(); | |
723 | ||
724 | isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN, | |
725 | ISC_LOG_NOTICE, "exiting"); | |
726 | diff -urN bind-9.2.3-orig/doc/INSTALL.sdb-ldap bind-9.2.3/doc/INSTALL.sdb-ldap | |
727 | --- bind-9.2.3-orig/doc/INSTALL.sdb-ldap 1969-12-31 17:00:00.000000000 -0700 | |
728 | +++ bind-9.2.3/doc/INSTALL.sdb-ldap 2003-11-16 14:53:32.000000000 -0700 | |
729 | @@ -0,0 +1,59 @@ | |
730 | +This is the INSTALL file for 0.9. See | |
731 | +http://www.venaas.no/ldap/bind-sdb/ for updates or other information. | |
732 | + | |
733 | +BUILDING | |
734 | + | |
735 | +You need the source for BIND 9.1.0 or newer (for zone transfers you | |
736 | +will need at least 9.1.1rc3 due to a bug). Basically you need to follow | |
737 | +the instructions in doc/misc/sdb, if my instructions doesn't make sense, | |
738 | +please have a look at that as well. | |
739 | + | |
740 | +Copy ldapdb.c to bin/named and ldapdb.h to bin/named/include in the | |
741 | +source tree. | |
742 | + | |
743 | +Next alter bin/named/Makefile.in. Add ldapdb.@O@ to DBDRIVER_OBJS and | |
744 | +ldapdb.c to DBDRIVER_SRCS. You also need to add something like | |
745 | +-I/usr/local/include to DBDRIVER_INCLUDES and | |
746 | +-L/usr/local/lib -lldap -llber -lresolv to DBDRIVER_LIBS | |
747 | +depending on what LDAP library you have and where you installed it. | |
748 | + | |
749 | +Finally you need to edit bin/named/main.c. Below where it says | |
750 | +"#include "xxdb.h"", add the line "#include <ldapdb.h>". Below where | |
751 | +it says "xxdb_init();" add the line "ldapdb_init();", and finally | |
752 | +below where it says "xxdb_clear();", add "ldapdb_clear();". | |
753 | + | |
754 | +Now you should hopefully be able to build it. If you get an error | |
755 | +message about ldap_memfree() not being defined, you're probably | |
756 | +using an LDAP library with the interface defined in RFC 1823. To | |
757 | +build, uncomment the #define RFC1823API line near the top of ldapdb.c. | |
758 | + | |
759 | + | |
760 | +CONFIGURING | |
761 | + | |
762 | +Before you do any configuring of LDAP stuff, please try to configure | |
763 | +and start bind as usual to see if things work. | |
764 | + | |
765 | +To do anything useful, you need to store a zone in some LDAP server. | |
766 | +From this release on, you must use a schema called dNSZone. Note that | |
767 | +it relies on some attribute definitions in the Cosine schema, so that | |
768 | +must be included as well. The Cosine schema probably comes with your | |
769 | +LDAP server. You can find dNSZone and further details on how to store | |
770 | +the data in your LDAP server at | |
771 | +http://www.venaas.no/ldap/bind-sdb/ | |
772 | + | |
773 | +For an example, have a look at my venaas.com zone. Try a subtree search | |
774 | +for objectClass=* at | |
775 | +ldap ldap://129.241.20.67/dc=venaas,dc=com,o=DNS,dc=venaas,dc=no | |
776 | + | |
777 | +To use it with BIND, I've added the following to named.conf: | |
778 | +zone "venaas.com" { | |
779 | + type master; | |
780 | + database "ldap ldap://129.241.20.67/dc=venaas,dc=com,o=DNS,dc=venaas,dc=no 172800"; | |
781 | +}; | |
782 | + | |
783 | +When doing lookups BIND will do a sub-tree search below the base in the | |
784 | +URL. The number 172800 is the TTL which will be used for all entries that | |
785 | +haven't got the dNSTTL attribute. It is also possible to add an filter to | |
786 | +the URL, say ldap://host/base???(o=internal) | |
787 | + | |
788 | +Stig Venaas <venaas@uninett.no> 2002-04-17 | |
789 | diff -urN bind-9.2.3-orig/doc/README.sdb-ldap bind-9.2.3/doc/README.sdb-ldap | |
790 | --- bind-9.2.3-orig/doc/README.sdb-ldap 1969-12-31 17:00:00.000000000 -0700 | |
791 | +++ bind-9.2.3/doc/README.sdb-ldap 2003-11-16 14:53:18.000000000 -0700 | |
792 | @@ -0,0 +1,40 @@ | |
793 | +This is an attempt at an LDAP back-end for BIND 9 using the new simplified | |
794 | +database interface "sdb". This is the nineth release (0.9) and seems to | |
795 | +be pretty stable. Note that since version 0.4 a new schema is used. | |
796 | +It is not backwards compatible with versions before 0.4. | |
797 | + | |
798 | +In 0.9 the code has been cleaned up a bit and should be slightly faster | |
799 | +than previous versions. It also fixes an error with zone transfers (AXFR) | |
800 | +and entries with multiple relativeDomainName values. The problem was | |
801 | +that it would only use the first value in the result. There's no need | |
802 | +to upgrade unless you use such entries. | |
803 | + | |
804 | +0.8 uses asynchronous LDAP search which should give better performance. | |
805 | +Thanks to Ashley Burston for providing patch. Another new feature is | |
806 | +allowing filters in URLs. The syntax is as in RFC 2255. Few people will | |
807 | +need this, but if you have say an internal and external version of the | |
808 | +same zone, you could stick say o=internal and o=external into different | |
809 | +entries, and specify for instance ldap://host/base???(o=internal) | |
810 | +Some error logging has also been added. | |
811 | + | |
812 | +0.7 allows space and other characters to be used in URLs by use of %-quoting. | |
813 | +For instance space can be written as %20. It also fixes a problem with some | |
814 | +servers and/or APIs that do not preserve attribute casing. | |
815 | + | |
816 | +0.6 fixes some memory leaks present in older versions unless compiled with | |
817 | +the RFC 1823 API. | |
818 | + | |
819 | +The big changes in 0.5 are thread support and improved connection handling. | |
820 | +Multiple threads can now access the back-end simultaneously, and rather than | |
821 | +having one connection per zone, there is now one connection per thread per | |
822 | +LDAP server. This should help people with multiple CPUs and people with a | |
823 | +huge number of zones. One final change is support for literal IPv6 addresses | |
824 | +in LDAP URLs. At least OpenLDAP 2 has IPv6 support, so if you use OpenLDAP 2 | |
825 | +libraries and server, you got all you need. | |
826 | + | |
827 | +If you have bug reports, fixes, comments, questions or whatever, please | |
828 | +contact me. See also http://www.venaas.no/ldap/bind-sdb/ for information. | |
829 | + | |
830 | +See INSTALL for how to build, install and use. | |
831 | + | |
832 | +Stig Venaas <venaas@uninett.no> 2001-12-29 |