Line 0
Link Here
|
|
|
1 |
/* ldap.c |
2 |
|
3 |
Routines for reading the configuration from LDAP */ |
4 |
|
5 |
/* |
6 |
* Copyright (c) 2003-2006 Ntelos, Inc. |
7 |
* All rights reserved. |
8 |
* |
9 |
* Redistribution and use in source and binary forms, with or without |
10 |
* modification, are permitted provided that the following conditions |
11 |
* are met: |
12 |
* |
13 |
* 1. Redistributions of source code must retain the above copyright |
14 |
* notice, this list of conditions and the following disclaimer. |
15 |
* 2. Redistributions in binary form must reproduce the above copyright |
16 |
* notice, this list of conditions and the following disclaimer in the |
17 |
* documentation and/or other materials provided with the distribution. |
18 |
* 3. Neither the name of The Internet Software Consortium nor the names |
19 |
* of its contributors may be used to endorse or promote products derived |
20 |
* from this software without specific prior written permission. |
21 |
* |
22 |
* THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND |
23 |
* CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, |
24 |
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
25 |
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
26 |
* DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR |
27 |
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
28 |
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
29 |
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF |
30 |
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
31 |
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, |
32 |
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT |
33 |
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
34 |
* SUCH DAMAGE. |
35 |
* |
36 |
* This LDAP module was written by Brian Masney <masneyb@ntelos.net>. Its |
37 |
* development was sponsored by Ntelos, Inc. (www.ntelos.com). |
38 |
*/ |
39 |
|
40 |
#include "dhcpd.h" |
41 |
#include <signal.h> |
42 |
|
43 |
#if defined(LDAP_CONFIGURATION) |
44 |
|
45 |
#if defined(LDAP_CASA_AUTH) |
46 |
#include "ldap_casa.h" |
47 |
#endif |
48 |
|
49 |
static LDAP * ld = NULL; |
50 |
static char *ldap_server = NULL, |
51 |
*ldap_username = NULL, |
52 |
*ldap_password = NULL, |
53 |
*ldap_base_dn = NULL, |
54 |
*ldap_dhcp_server_cn = NULL, |
55 |
*ldap_debug_file = NULL; |
56 |
static int ldap_port = LDAP_PORT, |
57 |
ldap_method = LDAP_METHOD_DYNAMIC, |
58 |
ldap_referrals = -1, |
59 |
ldap_debug_fd = -1; |
60 |
#if defined (USE_SSL) |
61 |
static int ldap_use_ssl = -1, /* try TLS if possible */ |
62 |
ldap_tls_reqcert = -1, |
63 |
ldap_tls_crlcheck = -1; |
64 |
static char *ldap_tls_ca_file = NULL, |
65 |
*ldap_tls_ca_dir = NULL, |
66 |
*ldap_tls_cert = NULL, |
67 |
*ldap_tls_key = NULL, |
68 |
*ldap_tls_ciphers = NULL, |
69 |
*ldap_tls_randfile = NULL; |
70 |
#endif |
71 |
static struct ldap_config_stack *ldap_stack = NULL; |
72 |
|
73 |
typedef struct ldap_dn_node { |
74 |
struct ldap_dn_node *next; |
75 |
size_t refs; |
76 |
char *dn; |
77 |
} ldap_dn_node; |
78 |
|
79 |
static ldap_dn_node *ldap_service_dn_head = NULL; |
80 |
static ldap_dn_node *ldap_service_dn_tail = NULL; |
81 |
|
82 |
|
83 |
static char * |
84 |
x_strncat(char *dst, const char *src, size_t dst_size) |
85 |
{ |
86 |
size_t len = strlen(dst); |
87 |
return strncat(dst, src, dst_size > len ? dst_size - len - 1: 0); |
88 |
} |
89 |
|
90 |
static void |
91 |
ldap_parse_class (struct ldap_config_stack *item, struct parse *cfile) |
92 |
{ |
93 |
struct berval **tempbv; |
94 |
|
95 |
if ((tempbv = ldap_get_values_len (ld, item->ldent, "cn")) == NULL || |
96 |
tempbv[0] == NULL) |
97 |
{ |
98 |
if (tempbv != NULL) |
99 |
ldap_value_free_len (tempbv); |
100 |
|
101 |
return; |
102 |
} |
103 |
|
104 |
x_strncat (cfile->inbuf, "class \"", LDAP_BUFFER_SIZE); |
105 |
x_strncat (cfile->inbuf, tempbv[0]->bv_val, LDAP_BUFFER_SIZE); |
106 |
x_strncat (cfile->inbuf, "\" {\n", LDAP_BUFFER_SIZE); |
107 |
|
108 |
item->close_brace = 1; |
109 |
ldap_value_free_len (tempbv); |
110 |
} |
111 |
|
112 |
|
113 |
static void |
114 |
ldap_parse_subclass (struct ldap_config_stack *item, struct parse *cfile) |
115 |
{ |
116 |
struct berval **tempbv, **classdata; |
117 |
|
118 |
if ((tempbv = ldap_get_values_len (ld, item->ldent, "cn")) == NULL || |
119 |
tempbv[0] == NULL) |
120 |
{ |
121 |
if (tempbv != NULL) |
122 |
ldap_value_free_len (tempbv); |
123 |
|
124 |
return; |
125 |
} |
126 |
|
127 |
if ((classdata = ldap_get_values_len (ld, item->ldent, |
128 |
"dhcpClassData")) == NULL || |
129 |
classdata[0] == NULL) |
130 |
{ |
131 |
if (classdata != NULL) |
132 |
ldap_value_free_len (classdata); |
133 |
ldap_value_free_len (tempbv); |
134 |
|
135 |
return; |
136 |
} |
137 |
|
138 |
x_strncat (cfile->inbuf, "subclass ", LDAP_BUFFER_SIZE); |
139 |
x_strncat (cfile->inbuf, classdata[0]->bv_val, LDAP_BUFFER_SIZE); |
140 |
x_strncat (cfile->inbuf, " ", LDAP_BUFFER_SIZE); |
141 |
x_strncat (cfile->inbuf, tempbv[0]->bv_val, LDAP_BUFFER_SIZE); |
142 |
x_strncat (cfile->inbuf, " {\n", LDAP_BUFFER_SIZE); |
143 |
|
144 |
item->close_brace = 1; |
145 |
ldap_value_free_len (tempbv); |
146 |
ldap_value_free_len (classdata); |
147 |
} |
148 |
|
149 |
|
150 |
static void |
151 |
ldap_parse_host (struct ldap_config_stack *item, struct parse *cfile) |
152 |
{ |
153 |
struct berval **tempbv, **hwaddr; |
154 |
|
155 |
if ((tempbv = ldap_get_values_len (ld, item->ldent, "cn")) == NULL || |
156 |
tempbv[0] == NULL) |
157 |
{ |
158 |
if (tempbv != NULL) |
159 |
ldap_value_free_len (tempbv); |
160 |
|
161 |
return; |
162 |
} |
163 |
|
164 |
hwaddr = ldap_get_values_len (ld, item->ldent, "dhcpHWAddress"); |
165 |
|
166 |
x_strncat (cfile->inbuf, "host ", LDAP_BUFFER_SIZE); |
167 |
x_strncat (cfile->inbuf, tempbv[0]->bv_val, LDAP_BUFFER_SIZE); |
168 |
|
169 |
if (hwaddr != NULL && hwaddr[0] != NULL) |
170 |
{ |
171 |
x_strncat (cfile->inbuf, " {\nhardware ", LDAP_BUFFER_SIZE); |
172 |
x_strncat (cfile->inbuf, hwaddr[0]->bv_val, LDAP_BUFFER_SIZE); |
173 |
x_strncat (cfile->inbuf, ";\n", LDAP_BUFFER_SIZE); |
174 |
ldap_value_free_len (hwaddr); |
175 |
} |
176 |
|
177 |
item->close_brace = 1; |
178 |
ldap_value_free_len (tempbv); |
179 |
} |
180 |
|
181 |
|
182 |
static void |
183 |
ldap_parse_shared_network (struct ldap_config_stack *item, struct parse *cfile) |
184 |
{ |
185 |
struct berval **tempbv; |
186 |
|
187 |
if ((tempbv = ldap_get_values_len (ld, item->ldent, "cn")) == NULL || |
188 |
tempbv[0] == NULL) |
189 |
{ |
190 |
if (tempbv != NULL) |
191 |
ldap_value_free_len (tempbv); |
192 |
|
193 |
return; |
194 |
} |
195 |
|
196 |
x_strncat (cfile->inbuf, "shared-network \"", LDAP_BUFFER_SIZE); |
197 |
x_strncat (cfile->inbuf, tempbv[0]->bv_val, LDAP_BUFFER_SIZE); |
198 |
x_strncat (cfile->inbuf, "\" {\n", LDAP_BUFFER_SIZE); |
199 |
|
200 |
item->close_brace = 1; |
201 |
ldap_value_free_len (tempbv); |
202 |
} |
203 |
|
204 |
|
205 |
static void |
206 |
parse_netmask (int netmask, char *netmaskbuf) |
207 |
{ |
208 |
unsigned long nm; |
209 |
int i; |
210 |
|
211 |
nm = 0; |
212 |
for (i=1; i <= netmask; i++) |
213 |
{ |
214 |
nm |= 1 << (32 - i); |
215 |
} |
216 |
|
217 |
sprintf (netmaskbuf, "%d.%d.%d.%d", (int) (nm >> 24) & 0xff, |
218 |
(int) (nm >> 16) & 0xff, |
219 |
(int) (nm >> 8) & 0xff, |
220 |
(int) nm & 0xff); |
221 |
} |
222 |
|
223 |
|
224 |
static void |
225 |
ldap_parse_subnet (struct ldap_config_stack *item, struct parse *cfile) |
226 |
{ |
227 |
struct berval **tempbv, **netmaskstr; |
228 |
char netmaskbuf[16]; |
229 |
int i; |
230 |
|
231 |
if ((tempbv = ldap_get_values_len (ld, item->ldent, "cn")) == NULL || |
232 |
tempbv[0] == NULL) |
233 |
{ |
234 |
if (tempbv != NULL) |
235 |
ldap_value_free_len (tempbv); |
236 |
|
237 |
return; |
238 |
} |
239 |
|
240 |
if ((netmaskstr = ldap_get_values_len (ld, item->ldent, |
241 |
"dhcpNetmask")) == NULL || |
242 |
netmaskstr[0] == NULL) |
243 |
{ |
244 |
if (netmaskstr != NULL) |
245 |
ldap_value_free_len (netmaskstr); |
246 |
ldap_value_free_len (tempbv); |
247 |
|
248 |
return; |
249 |
} |
250 |
|
251 |
x_strncat (cfile->inbuf, "subnet ", LDAP_BUFFER_SIZE); |
252 |
x_strncat (cfile->inbuf, tempbv[0]->bv_val, LDAP_BUFFER_SIZE); |
253 |
|
254 |
x_strncat (cfile->inbuf, " netmask ", LDAP_BUFFER_SIZE); |
255 |
parse_netmask (strtol (netmaskstr[0]->bv_val, NULL, 10), netmaskbuf); |
256 |
x_strncat (cfile->inbuf, netmaskbuf, LDAP_BUFFER_SIZE); |
257 |
|
258 |
x_strncat (cfile->inbuf, " {\n", LDAP_BUFFER_SIZE); |
259 |
|
260 |
ldap_value_free_len (tempbv); |
261 |
ldap_value_free_len (netmaskstr); |
262 |
|
263 |
if ((tempbv = ldap_get_values_len (ld, item->ldent, "dhcpRange")) != NULL) |
264 |
{ |
265 |
for (i=0; tempbv[i] != NULL; i++) |
266 |
{ |
267 |
x_strncat (cfile->inbuf, "range", LDAP_BUFFER_SIZE); |
268 |
x_strncat (cfile->inbuf, " ", LDAP_BUFFER_SIZE); |
269 |
x_strncat (cfile->inbuf, tempbv[i]->bv_val, LDAP_BUFFER_SIZE); |
270 |
x_strncat (cfile->inbuf, ";\n", LDAP_BUFFER_SIZE); |
271 |
} |
272 |
} |
273 |
|
274 |
item->close_brace = 1; |
275 |
} |
276 |
|
277 |
|
278 |
static void |
279 |
ldap_parse_pool (struct ldap_config_stack *item, struct parse *cfile) |
280 |
{ |
281 |
struct berval **tempbv; |
282 |
int i; |
283 |
|
284 |
x_strncat (cfile->inbuf, "pool {\n", LDAP_BUFFER_SIZE); |
285 |
|
286 |
if ((tempbv = ldap_get_values_len (ld, item->ldent, "dhcpRange")) != NULL) |
287 |
{ |
288 |
for (i=0; tempbv[i] != NULL; i++) |
289 |
{ |
290 |
x_strncat (cfile->inbuf, "range", LDAP_BUFFER_SIZE); |
291 |
x_strncat (cfile->inbuf, " ", LDAP_BUFFER_SIZE); |
292 |
x_strncat (cfile->inbuf, tempbv[i]->bv_val, LDAP_BUFFER_SIZE); |
293 |
x_strncat (cfile->inbuf, ";\n", LDAP_BUFFER_SIZE); |
294 |
} |
295 |
ldap_value_free_len (tempbv); |
296 |
} |
297 |
|
298 |
if ((tempbv = ldap_get_values_len (ld, item->ldent, "dhcpPermitList")) != NULL) |
299 |
{ |
300 |
for (i=0; tempbv[i] != NULL; i++) |
301 |
{ |
302 |
x_strncat (cfile->inbuf, tempbv[i]->bv_val, LDAP_BUFFER_SIZE); |
303 |
x_strncat (cfile->inbuf, ";\n", LDAP_BUFFER_SIZE); |
304 |
} |
305 |
ldap_value_free_len (tempbv); |
306 |
} |
307 |
|
308 |
item->close_brace = 1; |
309 |
} |
310 |
|
311 |
|
312 |
static void |
313 |
ldap_parse_group (struct ldap_config_stack *item, struct parse *cfile) |
314 |
{ |
315 |
x_strncat (cfile->inbuf, "group {\n", LDAP_BUFFER_SIZE); |
316 |
item->close_brace = 1; |
317 |
} |
318 |
|
319 |
|
320 |
static void |
321 |
ldap_parse_key (struct ldap_config_stack *item, struct parse *cfile) |
322 |
{ |
323 |
struct berval **tempbv; |
324 |
|
325 |
if ((tempbv = ldap_get_values_len (ld, item->ldent, "cn")) != NULL) |
326 |
{ |
327 |
x_strncat (cfile->inbuf, "key ", LDAP_BUFFER_SIZE); |
328 |
x_strncat (cfile->inbuf, tempbv[0]->bv_val, LDAP_BUFFER_SIZE); |
329 |
x_strncat (cfile->inbuf, " {\n", LDAP_BUFFER_SIZE); |
330 |
ldap_value_free_len (tempbv); |
331 |
} |
332 |
|
333 |
if ((tempbv = ldap_get_values_len (ld, item->ldent, "dhcpKeyAlgorithm")) != NULL) |
334 |
{ |
335 |
x_strncat (cfile->inbuf, "algorithm ", LDAP_BUFFER_SIZE); |
336 |
x_strncat (cfile->inbuf, tempbv[0]->bv_val, LDAP_BUFFER_SIZE); |
337 |
x_strncat (cfile->inbuf, ";\n", LDAP_BUFFER_SIZE); |
338 |
ldap_value_free_len (tempbv); |
339 |
} |
340 |
|
341 |
if ((tempbv = ldap_get_values_len (ld, item->ldent, "dhcpKeySecret")) != NULL) |
342 |
{ |
343 |
x_strncat (cfile->inbuf, "secret ", LDAP_BUFFER_SIZE); |
344 |
x_strncat (cfile->inbuf, tempbv[0]->bv_val, LDAP_BUFFER_SIZE); |
345 |
x_strncat (cfile->inbuf, ";\n", LDAP_BUFFER_SIZE); |
346 |
ldap_value_free_len (tempbv); |
347 |
} |
348 |
|
349 |
item->close_brace = 1; |
350 |
} |
351 |
|
352 |
|
353 |
static void |
354 |
ldap_parse_zone (struct ldap_config_stack *item, struct parse *cfile) |
355 |
{ |
356 |
char *cnFindStart, *cnFindEnd; |
357 |
struct berval **tempbv; |
358 |
char *keyCn; |
359 |
size_t len; |
360 |
|
361 |
if ((tempbv = ldap_get_values_len (ld, item->ldent, "cn")) != NULL) |
362 |
{ |
363 |
x_strncat (cfile->inbuf, "zone ", LDAP_BUFFER_SIZE); |
364 |
x_strncat (cfile->inbuf, tempbv[0]->bv_val, LDAP_BUFFER_SIZE); |
365 |
x_strncat (cfile->inbuf, " {\n", LDAP_BUFFER_SIZE); |
366 |
ldap_value_free_len (tempbv); |
367 |
} |
368 |
|
369 |
if ((tempbv = ldap_get_values_len (ld, item->ldent, "dhcpDnsZoneServer")) != NULL) |
370 |
{ |
371 |
x_strncat (cfile->inbuf, "primary ", LDAP_BUFFER_SIZE); |
372 |
x_strncat (cfile->inbuf, tempbv[0]->bv_val, LDAP_BUFFER_SIZE); |
373 |
|
374 |
x_strncat (cfile->inbuf, ";\n", LDAP_BUFFER_SIZE); |
375 |
ldap_value_free_len (tempbv); |
376 |
} |
377 |
|
378 |
if ((tempbv = ldap_get_values_len (ld, item->ldent, "dhcpKeyDN")) != NULL) |
379 |
{ |
380 |
cnFindStart = strchr(tempbv[0]->bv_val,'='); |
381 |
if (cnFindStart != NULL) |
382 |
cnFindEnd = strchr(++cnFindStart,','); |
383 |
else |
384 |
cnFindEnd = NULL; |
385 |
|
386 |
if (cnFindEnd != NULL && cnFindEnd > cnFindStart) |
387 |
{ |
388 |
len = cnFindEnd - cnFindStart; |
389 |
keyCn = dmalloc (len + 1, MDL); |
390 |
} |
391 |
else |
392 |
{ |
393 |
len = 0; |
394 |
keyCn = NULL; |
395 |
} |
396 |
|
397 |
if (keyCn != NULL) |
398 |
{ |
399 |
strncpy (keyCn, cnFindStart, len); |
400 |
keyCn[len] = '\0'; |
401 |
|
402 |
x_strncat (cfile->inbuf, "key ", LDAP_BUFFER_SIZE); |
403 |
x_strncat (cfile->inbuf, keyCn, LDAP_BUFFER_SIZE); |
404 |
x_strncat (cfile->inbuf, ";\n", LDAP_BUFFER_SIZE); |
405 |
|
406 |
dfree (keyCn, MDL); |
407 |
} |
408 |
|
409 |
ldap_value_free_len (tempbv); |
410 |
} |
411 |
|
412 |
item->close_brace = 1; |
413 |
} |
414 |
|
415 |
|
416 |
static void |
417 |
add_to_config_stack (LDAPMessage * res, LDAPMessage * ent) |
418 |
{ |
419 |
struct ldap_config_stack *ns; |
420 |
|
421 |
ns = dmalloc (sizeof (*ns), MDL); |
422 |
ns->res = res; |
423 |
ns->ldent = ent; |
424 |
ns->close_brace = 0; |
425 |
ns->processed = 0; |
426 |
ns->next = ldap_stack; |
427 |
ldap_stack = ns; |
428 |
} |
429 |
|
430 |
|
431 |
static void |
432 |
ldap_stop() |
433 |
{ |
434 |
struct sigaction old, new; |
435 |
|
436 |
if (ld == NULL) |
437 |
return; |
438 |
|
439 |
/* |
440 |
** ldap_unbind after a LDAP_SERVER_DOWN result |
441 |
** causes a SIGPIPE and dhcpd gets terminated, |
442 |
** since it doesn't handle it... |
443 |
*/ |
444 |
|
445 |
new.sa_flags = 0; |
446 |
new.sa_handler = SIG_IGN; |
447 |
sigemptyset (&new.sa_mask); |
448 |
sigaction (SIGPIPE, &new, &old); |
449 |
|
450 |
ldap_unbind_ext_s (ld, NULL, NULL); |
451 |
ld = NULL; |
452 |
|
453 |
sigaction (SIGPIPE, &old, &new); |
454 |
} |
455 |
|
456 |
|
457 |
static char * |
458 |
_do_lookup_dhcp_string_option (struct option_state *options, int option_name) |
459 |
{ |
460 |
struct option_cache *oc; |
461 |
struct data_string db; |
462 |
char *ret; |
463 |
|
464 |
memset (&db, 0, sizeof (db)); |
465 |
oc = lookup_option (&server_universe, options, option_name); |
466 |
if (oc && |
467 |
evaluate_option_cache (&db, (struct packet*) NULL, |
468 |
(struct lease *) NULL, |
469 |
(struct client_state *) NULL, options, |
470 |
(struct option_state *) NULL, |
471 |
&global_scope, oc, MDL) && |
472 |
db.data != NULL && *db.data != '\0') |
473 |
|
474 |
{ |
475 |
ret = dmalloc (db.len + 1, MDL); |
476 |
if (ret == NULL) |
477 |
log_fatal ("no memory for ldap option %d value", option_name); |
478 |
|
479 |
memcpy (ret, db.data, db.len); |
480 |
ret[db.len] = 0; |
481 |
data_string_forget (&db, MDL); |
482 |
} |
483 |
else |
484 |
ret = NULL; |
485 |
|
486 |
return (ret); |
487 |
} |
488 |
|
489 |
|
490 |
static int |
491 |
_do_lookup_dhcp_int_option (struct option_state *options, int option_name) |
492 |
{ |
493 |
struct option_cache *oc; |
494 |
struct data_string db; |
495 |
int ret; |
496 |
|
497 |
memset (&db, 0, sizeof (db)); |
498 |
oc = lookup_option (&server_universe, options, option_name); |
499 |
if (oc && |
500 |
evaluate_option_cache (&db, (struct packet*) NULL, |
501 |
(struct lease *) NULL, |
502 |
(struct client_state *) NULL, options, |
503 |
(struct option_state *) NULL, |
504 |
&global_scope, oc, MDL) && |
505 |
db.data != NULL && *db.data != '\0') |
506 |
{ |
507 |
ret = strtol ((const char *) db.data, NULL, 10); |
508 |
data_string_forget (&db, MDL); |
509 |
} |
510 |
else |
511 |
ret = 0; |
512 |
|
513 |
return (ret); |
514 |
} |
515 |
|
516 |
|
517 |
static int |
518 |
_do_lookup_dhcp_enum_option (struct option_state *options, int option_name) |
519 |
{ |
520 |
struct option_cache *oc; |
521 |
struct data_string db; |
522 |
int ret = -1; |
523 |
|
524 |
memset (&db, 0, sizeof (db)); |
525 |
oc = lookup_option (&server_universe, options, option_name); |
526 |
if (oc && |
527 |
evaluate_option_cache (&db, (struct packet*) NULL, |
528 |
(struct lease *) NULL, |
529 |
(struct client_state *) NULL, options, |
530 |
(struct option_state *) NULL, |
531 |
&global_scope, oc, MDL) && |
532 |
db.data != NULL && *db.data != '\0') |
533 |
{ |
534 |
if (db.len == 1) |
535 |
ret = db.data [0]; |
536 |
else |
537 |
log_fatal ("invalid option name %d", option_name); |
538 |
|
539 |
data_string_forget (&db, MDL); |
540 |
} |
541 |
else |
542 |
ret = 0; |
543 |
|
544 |
return (ret); |
545 |
} |
546 |
|
547 |
int |
548 |
ldap_rebind_cb (LDAP *ld, LDAP_CONST char *url, ber_tag_t request, ber_int_t msgid, void *parms) |
549 |
{ |
550 |
int ret; |
551 |
LDAPURLDesc *ldapurl = NULL; |
552 |
char *who = NULL; |
553 |
struct berval creds; |
554 |
|
555 |
log_info("LDAP rebind to '%s'", url); |
556 |
if ((ret = ldap_url_parse(url, &ldapurl)) != LDAP_SUCCESS) |
557 |
{ |
558 |
log_error ("Error: Can not parse ldap rebind url '%s': %s", |
559 |
url, ldap_err2string(ret)); |
560 |
return ret; |
561 |
} |
562 |
|
563 |
|
564 |
#if defined (USE_SSL) |
565 |
if (strcasecmp(ldapurl->lud_scheme, "ldaps") == 0) |
566 |
{ |
567 |
int opt = LDAP_OPT_X_TLS_HARD; |
568 |
if ((ret = ldap_set_option (ld, LDAP_OPT_X_TLS, &opt)) != LDAP_SUCCESS) |
569 |
{ |
570 |
log_error ("Error: Cannot init LDAPS session to %s:%d: %s", |
571 |
ldapurl->lud_host, ldapurl->lud_port, ldap_err2string (ret)); |
572 |
return ret; |
573 |
} |
574 |
else |
575 |
{ |
576 |
log_info ("LDAPS session successfully enabled to %s", ldap_server); |
577 |
} |
578 |
} |
579 |
else |
580 |
if (strcasecmp(ldapurl->lud_scheme, "ldap") == 0 && |
581 |
ldap_use_ssl != LDAP_SSL_OFF) |
582 |
{ |
583 |
if ((ret = ldap_start_tls_s (ld, NULL, NULL)) != LDAP_SUCCESS) |
584 |
{ |
585 |
log_error ("Error: Cannot start TLS session to %s:%d: %s", |
586 |
ldapurl->lud_host, ldapurl->lud_port, ldap_err2string (ret)); |
587 |
return ret; |
588 |
} |
589 |
else |
590 |
{ |
591 |
log_info ("TLS session successfully started to %s:%d", |
592 |
ldapurl->lud_host, ldapurl->lud_port); |
593 |
} |
594 |
} |
595 |
#endif |
596 |
|
597 |
|
598 |
if (ldap_username != NULL || *ldap_username != '\0') |
599 |
{ |
600 |
who = ldap_username; |
601 |
creds.bv_val = strdup(ldap_password); |
602 |
creds.bv_len = strlen(ldap_password); |
603 |
} |
604 |
|
605 |
if ((ret = ldap_sasl_bind_s (ld, who, LDAP_SASL_SIMPLE, &creds, |
606 |
NULL, NULL, NULL)) != LDAP_SUCCESS) |
607 |
{ |
608 |
log_error ("Error: Cannot login into ldap server %s:%d: %s", |
609 |
ldapurl->lud_host, ldapurl->lud_port, ldap_err2string (ret)); |
610 |
} |
611 |
return ret; |
612 |
} |
613 |
|
614 |
static void |
615 |
ldap_start (void) |
616 |
{ |
617 |
struct option_state *options; |
618 |
int ret, version; |
619 |
char *uri = NULL; |
620 |
struct berval creds; |
621 |
|
622 |
if (ld != NULL) |
623 |
return; |
624 |
|
625 |
if (ldap_server == NULL) |
626 |
{ |
627 |
options = NULL; |
628 |
option_state_allocate (&options, MDL); |
629 |
|
630 |
execute_statements_in_scope ((struct binding_value **) NULL, |
631 |
(struct packet *) NULL, (struct lease *) NULL, |
632 |
(struct client_state *) NULL, (struct option_state *) NULL, |
633 |
options, &global_scope, root_group, (struct group *) NULL); |
634 |
|
635 |
ldap_server = _do_lookup_dhcp_string_option (options, SV_LDAP_SERVER); |
636 |
ldap_dhcp_server_cn = _do_lookup_dhcp_string_option (options, |
637 |
SV_LDAP_DHCP_SERVER_CN); |
638 |
ldap_port = _do_lookup_dhcp_int_option (options, SV_LDAP_PORT); |
639 |
ldap_base_dn = _do_lookup_dhcp_string_option (options, SV_LDAP_BASE_DN); |
640 |
ldap_method = _do_lookup_dhcp_enum_option (options, SV_LDAP_METHOD); |
641 |
ldap_debug_file = _do_lookup_dhcp_string_option (options, |
642 |
SV_LDAP_DEBUG_FILE); |
643 |
ldap_referrals = _do_lookup_dhcp_enum_option (options, SV_LDAP_REFERRALS); |
644 |
|
645 |
#if defined (USE_SSL) |
646 |
ldap_use_ssl = _do_lookup_dhcp_enum_option (options, SV_LDAP_SSL); |
647 |
if( ldap_use_ssl != LDAP_SSL_OFF) |
648 |
{ |
649 |
ldap_tls_reqcert = _do_lookup_dhcp_enum_option (options, SV_LDAP_TLS_REQCERT); |
650 |
ldap_tls_ca_file = _do_lookup_dhcp_string_option (options, SV_LDAP_TLS_CA_FILE); |
651 |
ldap_tls_ca_dir = _do_lookup_dhcp_string_option (options, SV_LDAP_TLS_CA_DIR); |
652 |
ldap_tls_cert = _do_lookup_dhcp_string_option (options, SV_LDAP_TLS_CERT); |
653 |
ldap_tls_key = _do_lookup_dhcp_string_option (options, SV_LDAP_TLS_KEY); |
654 |
ldap_tls_crlcheck = _do_lookup_dhcp_enum_option (options, SV_LDAP_TLS_CRLCHECK); |
655 |
ldap_tls_ciphers = _do_lookup_dhcp_string_option (options, SV_LDAP_TLS_CIPHERS); |
656 |
ldap_tls_randfile = _do_lookup_dhcp_string_option (options, SV_LDAP_TLS_RANDFILE); |
657 |
} |
658 |
#endif |
659 |
|
660 |
#if defined (LDAP_CASA_AUTH) |
661 |
if (!load_uname_pwd_from_miCASA(&ldap_username,&ldap_password)) |
662 |
{ |
663 |
#if defined (DEBUG_LDAP) |
664 |
log_info ("Authentication credential taken from file"); |
665 |
#endif |
666 |
#endif |
667 |
|
668 |
ldap_username = _do_lookup_dhcp_string_option (options, SV_LDAP_USERNAME); |
669 |
ldap_password = _do_lookup_dhcp_string_option (options, SV_LDAP_PASSWORD); |
670 |
|
671 |
#if defined (LDAP_CASA_AUTH) |
672 |
} |
673 |
#endif |
674 |
|
675 |
option_state_dereference (&options, MDL); |
676 |
} |
677 |
|
678 |
if (ldap_server == NULL || ldap_base_dn == NULL) |
679 |
{ |
680 |
log_info ("Not searching LDAP since ldap-server, ldap-port and ldap-base-dn were not specified in the config file"); |
681 |
ldap_method = LDAP_METHOD_STATIC; |
682 |
return; |
683 |
} |
684 |
|
685 |
if (ldap_debug_file != NULL && ldap_debug_fd == -1) |
686 |
{ |
687 |
if ((ldap_debug_fd = open (ldap_debug_file, O_CREAT | O_TRUNC | O_WRONLY, |
688 |
S_IRUSR | S_IWUSR)) < 0) |
689 |
log_error ("Error opening debug LDAP log file %s: %s", ldap_debug_file, |
690 |
strerror (errno)); |
691 |
} |
692 |
|
693 |
#if defined (DEBUG_LDAP) |
694 |
log_info ("Connecting to LDAP server %s:%d", ldap_server, ldap_port); |
695 |
#endif |
696 |
|
697 |
#if defined (USE_SSL) |
698 |
if (ldap_use_ssl == -1) |
699 |
{ |
700 |
/* |
701 |
** There was no "ldap-ssl" option in dhcpd.conf (also not "off"). |
702 |
** Let's try, if we can use an anonymous TLS session without to |
703 |
** verify the server certificate -- if not continue without TLS. |
704 |
*/ |
705 |
int opt = LDAP_OPT_X_TLS_ALLOW; |
706 |
if ((ret = ldap_set_option (NULL, LDAP_OPT_X_TLS_REQUIRE_CERT, |
707 |
&opt)) != LDAP_SUCCESS) |
708 |
{ |
709 |
log_error ("Warning: Cannot set LDAP TLS require cert option to 'allow': %s", |
710 |
ldap_err2string (ret)); |
711 |
} |
712 |
} |
713 |
|
714 |
if (ldap_use_ssl != LDAP_SSL_OFF) |
715 |
{ |
716 |
if (ldap_tls_reqcert != -1) |
717 |
{ |
718 |
if ((ret = ldap_set_option (NULL, LDAP_OPT_X_TLS_REQUIRE_CERT, |
719 |
&ldap_tls_reqcert)) != LDAP_SUCCESS) |
720 |
{ |
721 |
log_error ("Cannot set LDAP TLS require cert option: %s", |
722 |
ldap_err2string (ret)); |
723 |
} |
724 |
} |
725 |
|
726 |
if( ldap_tls_ca_file != NULL) |
727 |
{ |
728 |
if ((ret = ldap_set_option (NULL, LDAP_OPT_X_TLS_CACERTFILE, |
729 |
ldap_tls_ca_file)) != LDAP_SUCCESS) |
730 |
{ |
731 |
log_error ("Cannot set LDAP TLS CA certificate file %s: %s", |
732 |
ldap_tls_ca_file, ldap_err2string (ret)); |
733 |
} |
734 |
} |
735 |
if( ldap_tls_ca_dir != NULL) |
736 |
{ |
737 |
if ((ret = ldap_set_option (NULL, LDAP_OPT_X_TLS_CACERTDIR, |
738 |
ldap_tls_ca_dir)) != LDAP_SUCCESS) |
739 |
{ |
740 |
log_error ("Cannot set LDAP TLS CA certificate dir %s: %s", |
741 |
ldap_tls_ca_dir, ldap_err2string (ret)); |
742 |
} |
743 |
} |
744 |
if( ldap_tls_cert != NULL) |
745 |
{ |
746 |
if ((ret = ldap_set_option (NULL, LDAP_OPT_X_TLS_CERTFILE, |
747 |
ldap_tls_cert)) != LDAP_SUCCESS) |
748 |
{ |
749 |
log_error ("Cannot set LDAP TLS client certificate file %s: %s", |
750 |
ldap_tls_cert, ldap_err2string (ret)); |
751 |
} |
752 |
} |
753 |
if( ldap_tls_key != NULL) |
754 |
{ |
755 |
if ((ret = ldap_set_option (NULL, LDAP_OPT_X_TLS_KEYFILE, |
756 |
ldap_tls_key)) != LDAP_SUCCESS) |
757 |
{ |
758 |
log_error ("Cannot set LDAP TLS certificate key file %s: %s", |
759 |
ldap_tls_key, ldap_err2string (ret)); |
760 |
} |
761 |
} |
762 |
if( ldap_tls_crlcheck != -1) |
763 |
{ |
764 |
int opt = ldap_tls_crlcheck; |
765 |
if ((ret = ldap_set_option (NULL, LDAP_OPT_X_TLS_CRLCHECK, |
766 |
&opt)) != LDAP_SUCCESS) |
767 |
{ |
768 |
log_error ("Cannot set LDAP TLS crl check option: %s", |
769 |
ldap_err2string (ret)); |
770 |
} |
771 |
} |
772 |
if( ldap_tls_ciphers != NULL) |
773 |
{ |
774 |
if ((ret = ldap_set_option (NULL, LDAP_OPT_X_TLS_CIPHER_SUITE, |
775 |
ldap_tls_ciphers)) != LDAP_SUCCESS) |
776 |
{ |
777 |
log_error ("Cannot set LDAP TLS cipher suite %s: %s", |
778 |
ldap_tls_ciphers, ldap_err2string (ret)); |
779 |
} |
780 |
} |
781 |
if( ldap_tls_randfile != NULL) |
782 |
{ |
783 |
if ((ret = ldap_set_option (NULL, LDAP_OPT_X_TLS_RANDOM_FILE, |
784 |
ldap_tls_randfile)) != LDAP_SUCCESS) |
785 |
{ |
786 |
log_error ("Cannot set LDAP TLS random file %s: %s", |
787 |
ldap_tls_randfile, ldap_err2string (ret)); |
788 |
} |
789 |
} |
790 |
} |
791 |
#endif |
792 |
|
793 |
/* enough for 'ldap://+ + hostname + ':' + port number */ |
794 |
uri = malloc(strlen(ldap_server) + 16); |
795 |
if (uri == NULL) |
796 |
{ |
797 |
log_error ("Cannot build ldap init URI %s:%d", ldap_server, ldap_port); |
798 |
return; |
799 |
} |
800 |
|
801 |
sprintf(uri, "ldap://%s:%d", ldap_server, ldap_port); |
802 |
ldap_initialize(&ld, uri); |
803 |
|
804 |
if (ld == NULL) |
805 |
{ |
806 |
log_error ("Cannot init ldap session to %s:%d", ldap_server, ldap_port); |
807 |
return; |
808 |
} |
809 |
|
810 |
free(uri); |
811 |
|
812 |
version = LDAP_VERSION3; |
813 |
if ((ret = ldap_set_option (ld, LDAP_OPT_PROTOCOL_VERSION, &version)) != LDAP_OPT_SUCCESS) |
814 |
{ |
815 |
log_error ("Cannot set LDAP version to %d: %s", version, |
816 |
ldap_err2string (ret)); |
817 |
} |
818 |
|
819 |
if (ldap_referrals != -1) |
820 |
{ |
821 |
if ((ret = ldap_set_option (ld, LDAP_OPT_REFERRALS, ldap_referrals ? |
822 |
LDAP_OPT_ON : LDAP_OPT_OFF)) != LDAP_OPT_SUCCESS) |
823 |
{ |
824 |
log_error ("Cannot %s LDAP referrals option: %s", |
825 |
(ldap_referrals ? "enable" : "disable"), |
826 |
ldap_err2string (ret)); |
827 |
} |
828 |
} |
829 |
|
830 |
if ((ret = ldap_set_rebind_proc(ld, ldap_rebind_cb, NULL)) != LDAP_SUCCESS) |
831 |
{ |
832 |
log_error ("Warning: Cannot set ldap rebind procedure: %s", |
833 |
ldap_err2string (ret)); |
834 |
} |
835 |
|
836 |
#if defined (USE_SSL) |
837 |
if (ldap_use_ssl == LDAP_SSL_LDAPS || |
838 |
(ldap_use_ssl == LDAP_SSL_ON && ldap_port == LDAPS_PORT)) |
839 |
{ |
840 |
int opt = LDAP_OPT_X_TLS_HARD; |
841 |
if ((ret = ldap_set_option (ld, LDAP_OPT_X_TLS, &opt)) != LDAP_SUCCESS) |
842 |
{ |
843 |
log_error ("Error: Cannot init LDAPS session to %s:%d: %s", |
844 |
ldap_server, ldap_port, ldap_err2string (ret)); |
845 |
ldap_stop(); |
846 |
return; |
847 |
} |
848 |
else |
849 |
{ |
850 |
log_info ("LDAPS session successfully enabled to %s:%d", |
851 |
ldap_server, ldap_port); |
852 |
} |
853 |
} |
854 |
else if (ldap_use_ssl != LDAP_SSL_OFF) |
855 |
{ |
856 |
if ((ret = ldap_start_tls_s (ld, NULL, NULL)) != LDAP_SUCCESS) |
857 |
{ |
858 |
log_error ("Error: Cannot start TLS session to %s:%d: %s", |
859 |
ldap_server, ldap_port, ldap_err2string (ret)); |
860 |
ldap_stop(); |
861 |
return; |
862 |
} |
863 |
else |
864 |
{ |
865 |
log_info ("TLS session successfully started to %s:%d", |
866 |
ldap_server, ldap_port); |
867 |
} |
868 |
} |
869 |
#endif |
870 |
|
871 |
if (ldap_username != NULL && *ldap_username != '\0') |
872 |
{ |
873 |
creds.bv_val = strdup(ldap_password); |
874 |
creds.bv_len = strlen(ldap_password); |
875 |
|
876 |
if ((ret = ldap_sasl_bind_s (ld, ldap_username, LDAP_SASL_SIMPLE, |
877 |
&creds, NULL, NULL, NULL)) != LDAP_SUCCESS) |
878 |
{ |
879 |
log_error ("Error: Cannot login into ldap server %s:%d: %s", |
880 |
ldap_server, ldap_port, ldap_err2string (ret)); |
881 |
ldap_stop(); |
882 |
return; |
883 |
} |
884 |
} |
885 |
|
886 |
#if defined (DEBUG_LDAP) |
887 |
log_info ("Successfully logged into LDAP server %s", ldap_server); |
888 |
#endif |
889 |
} |
890 |
|
891 |
|
892 |
static void |
893 |
parse_external_dns (LDAPMessage * ent) |
894 |
{ |
895 |
char *search[] = {"dhcpOptionsDN", "dhcpSharedNetworkDN", "dhcpSubnetDN", |
896 |
"dhcpGroupDN", "dhcpHostDN", "dhcpClassesDN", |
897 |
"dhcpPoolDN", NULL}; |
898 |
LDAPMessage * newres, * newent; |
899 |
struct berval **tempbv; |
900 |
int i, j, ret; |
901 |
#if defined (DEBUG_LDAP) |
902 |
char *dn; |
903 |
|
904 |
dn = ldap_get_dn (ld, ent); |
905 |
if (dn != NULL) |
906 |
{ |
907 |
log_info ("Parsing external DNs for '%s'", dn); |
908 |
ldap_memfree (dn); |
909 |
} |
910 |
#endif |
911 |
|
912 |
if (ld == NULL) |
913 |
ldap_start (); |
914 |
if (ld == NULL) |
915 |
return; |
916 |
|
917 |
for (i=0; search[i] != NULL; i++) |
918 |
{ |
919 |
if ((tempbv = ldap_get_values_len (ld, ent, search[i])) == NULL) |
920 |
continue; |
921 |
|
922 |
for (j=0; tempbv[j] != NULL; j++) |
923 |
{ |
924 |
if (*tempbv[j]->bv_val == '\0') |
925 |
continue; |
926 |
|
927 |
if ((ret = ldap_search_ext_s(ld, tempbv[j]->bv_val, LDAP_SCOPE_BASE, |
928 |
"objectClass=*", NULL, 0, NULL, |
929 |
NULL, NULL, 0, &newres)) != LDAP_SUCCESS) |
930 |
{ |
931 |
ldap_value_free_len (tempbv); |
932 |
ldap_stop(); |
933 |
return; |
934 |
} |
935 |
|
936 |
#if defined (DEBUG_LDAP) |
937 |
log_info ("Adding contents of subtree '%s' to config stack from '%s' reference", tempbv[j], search[i]); |
938 |
#endif |
939 |
for (newent = ldap_first_entry (ld, newres); |
940 |
newent != NULL; |
941 |
newent = ldap_next_entry (ld, newent)) |
942 |
{ |
943 |
#if defined (DEBUG_LDAP) |
944 |
dn = ldap_get_dn (ld, newent); |
945 |
if (dn != NULL) |
946 |
{ |
947 |
log_info ("Adding LDAP result set starting with '%s' to config stack", dn); |
948 |
ldap_memfree (dn); |
949 |
} |
950 |
#endif |
951 |
|
952 |
add_to_config_stack (newres, newent); |
953 |
/* don't free newres here */ |
954 |
} |
955 |
} |
956 |
|
957 |
ldap_value_free_len (tempbv); |
958 |
} |
959 |
} |
960 |
|
961 |
|
962 |
static void |
963 |
free_stack_entry (struct ldap_config_stack *item) |
964 |
{ |
965 |
struct ldap_config_stack *look_ahead_pointer = item; |
966 |
int may_free_msg = 1; |
967 |
|
968 |
while (look_ahead_pointer->next != NULL) |
969 |
{ |
970 |
look_ahead_pointer = look_ahead_pointer->next; |
971 |
if (look_ahead_pointer->res == item->res) |
972 |
{ |
973 |
may_free_msg = 0; |
974 |
break; |
975 |
} |
976 |
} |
977 |
|
978 |
if (may_free_msg) |
979 |
ldap_msgfree (item->res); |
980 |
|
981 |
dfree (item, MDL); |
982 |
} |
983 |
|
984 |
|
985 |
static void |
986 |
next_ldap_entry (struct parse *cfile) |
987 |
{ |
988 |
struct ldap_config_stack *temp_stack; |
989 |
|
990 |
if (ldap_stack != NULL && ldap_stack->close_brace) |
991 |
{ |
992 |
x_strncat (cfile->inbuf, "}\n", LDAP_BUFFER_SIZE); |
993 |
ldap_stack->close_brace = 0; |
994 |
} |
995 |
|
996 |
while (ldap_stack != NULL && |
997 |
(ldap_stack->ldent == NULL || |
998 |
(ldap_stack->ldent = ldap_next_entry (ld, ldap_stack->ldent)) == NULL)) |
999 |
{ |
1000 |
if (ldap_stack->close_brace) |
1001 |
{ |
1002 |
x_strncat (cfile->inbuf, "}\n", LDAP_BUFFER_SIZE); |
1003 |
ldap_stack->close_brace = 0; |
1004 |
} |
1005 |
|
1006 |
temp_stack = ldap_stack; |
1007 |
ldap_stack = ldap_stack->next; |
1008 |
free_stack_entry (temp_stack); |
1009 |
} |
1010 |
|
1011 |
if (ldap_stack != NULL && ldap_stack->close_brace) |
1012 |
{ |
1013 |
x_strncat (cfile->inbuf, "}\n", LDAP_BUFFER_SIZE); |
1014 |
ldap_stack->close_brace = 0; |
1015 |
} |
1016 |
} |
1017 |
|
1018 |
|
1019 |
static char |
1020 |
check_statement_end (const char *statement) |
1021 |
{ |
1022 |
char *ptr; |
1023 |
|
1024 |
if (statement == NULL || *statement == '\0') |
1025 |
return ('\0'); |
1026 |
|
1027 |
/* |
1028 |
** check if it ends with "}", e.g.: |
1029 |
** "zone my.domain. { ... }" |
1030 |
** optionally followed by spaces |
1031 |
*/ |
1032 |
ptr = strrchr (statement, '}'); |
1033 |
if (ptr != NULL) |
1034 |
{ |
1035 |
/* skip following white-spaces */ |
1036 |
for (++ptr; isspace ((int)*ptr); ptr++); |
1037 |
|
1038 |
/* check if we reached the end */ |
1039 |
if (*ptr == '\0') |
1040 |
return ('}'); /* yes, block end */ |
1041 |
else |
1042 |
return (*ptr); |
1043 |
} |
1044 |
|
1045 |
/* |
1046 |
** this should not happen, but... |
1047 |
** check if it ends with ";", e.g.: |
1048 |
** "authoritative;" |
1049 |
** optionally followed by spaces |
1050 |
*/ |
1051 |
ptr = strrchr (statement, ';'); |
1052 |
if (ptr != NULL) |
1053 |
{ |
1054 |
/* skip following white-spaces */ |
1055 |
for (++ptr; isspace ((int)*ptr); ptr++); |
1056 |
|
1057 |
/* check if we reached the end */ |
1058 |
if (*ptr == '\0') |
1059 |
return (';'); /* ends with a ; */ |
1060 |
else |
1061 |
return (*ptr); |
1062 |
} |
1063 |
|
1064 |
return ('\0'); |
1065 |
} |
1066 |
|
1067 |
|
1068 |
static isc_result_t |
1069 |
ldap_parse_entry_options (LDAPMessage *ent, char *buffer, size_t size, |
1070 |
int *lease_limit) |
1071 |
{ |
1072 |
struct berval **tempbv; |
1073 |
int i; |
1074 |
|
1075 |
if (ent == NULL || buffer == NULL || size == 0) |
1076 |
return (ISC_R_FAILURE); |
1077 |
|
1078 |
if ((tempbv = ldap_get_values_len (ld, ent, "dhcpStatements")) != NULL) |
1079 |
{ |
1080 |
for (i=0; tempbv[i] != NULL; i++) |
1081 |
{ |
1082 |
if (lease_limit != NULL && |
1083 |
strncasecmp ("lease limit ", tempbv[i]->bv_val, 12) == 0) |
1084 |
{ |
1085 |
*lease_limit = (int) strtol ((tempbv[i]->bv_val) + 12, NULL, 10); |
1086 |
continue; |
1087 |
} |
1088 |
|
1089 |
x_strncat (buffer, tempbv[i]->bv_val, size); |
1090 |
|
1091 |
switch((int) check_statement_end (tempbv[i]->bv_val)) |
1092 |
{ |
1093 |
case '}': |
1094 |
case ';': |
1095 |
x_strncat (buffer, "\n", size); |
1096 |
break; |
1097 |
default: |
1098 |
x_strncat (buffer, ";\n", size); |
1099 |
break; |
1100 |
} |
1101 |
} |
1102 |
ldap_value_free_len (tempbv); |
1103 |
} |
1104 |
|
1105 |
if ((tempbv = ldap_get_values_len (ld, ent, "dhcpOption")) != NULL) |
1106 |
{ |
1107 |
for (i=0; tempbv[i] != NULL; i++) |
1108 |
{ |
1109 |
x_strncat (buffer, "option ", size); |
1110 |
x_strncat (buffer, tempbv[i]->bv_val, size); |
1111 |
switch ((int) check_statement_end (tempbv[i]->bv_val)) |
1112 |
{ |
1113 |
case ';': |
1114 |
x_strncat (buffer, "\n", size); |
1115 |
break; |
1116 |
default: |
1117 |
x_strncat (buffer, ";\n", size); |
1118 |
break; |
1119 |
} |
1120 |
} |
1121 |
ldap_value_free_len (tempbv); |
1122 |
} |
1123 |
|
1124 |
return (ISC_R_SUCCESS); |
1125 |
} |
1126 |
|
1127 |
|
1128 |
static void |
1129 |
ldap_generate_config_string (struct parse *cfile) |
1130 |
{ |
1131 |
struct berval **objectClass; |
1132 |
char *dn; |
1133 |
struct ldap_config_stack *entry; |
1134 |
LDAPMessage * ent, * res; |
1135 |
int i, ignore, found; |
1136 |
int ret; |
1137 |
|
1138 |
if (ld == NULL) |
1139 |
ldap_start (); |
1140 |
if (ld == NULL) |
1141 |
return; |
1142 |
|
1143 |
entry = ldap_stack; |
1144 |
if ((objectClass = ldap_get_values_len (ld, entry->ldent, |
1145 |
"objectClass")) == NULL) |
1146 |
return; |
1147 |
|
1148 |
ignore = 0; |
1149 |
found = 1; |
1150 |
for (i=0; objectClass[i] != NULL; i++) |
1151 |
{ |
1152 |
if (strcasecmp (objectClass[i]->bv_val, "dhcpSharedNetwork") == 0) |
1153 |
ldap_parse_shared_network (entry, cfile); |
1154 |
else if (strcasecmp (objectClass[i]->bv_val, "dhcpClass") == 0) |
1155 |
ldap_parse_class (entry, cfile); |
1156 |
else if (strcasecmp (objectClass[i]->bv_val, "dhcpSubnet") == 0) |
1157 |
ldap_parse_subnet (entry, cfile); |
1158 |
else if (strcasecmp (objectClass[i]->bv_val, "dhcpPool") == 0) |
1159 |
ldap_parse_pool (entry, cfile); |
1160 |
else if (strcasecmp (objectClass[i]->bv_val, "dhcpGroup") == 0) |
1161 |
ldap_parse_group (entry, cfile); |
1162 |
else if (strcasecmp (objectClass[i]->bv_val, "dhcpTSigKey") == 0) |
1163 |
ldap_parse_key (entry, cfile); |
1164 |
else if (strcasecmp (objectClass[i]->bv_val, "dhcpDnsZone") == 0) |
1165 |
ldap_parse_zone (entry, cfile); |
1166 |
else if (strcasecmp (objectClass[i]->bv_val, "dhcpHost") == 0) |
1167 |
{ |
1168 |
if (ldap_method == LDAP_METHOD_STATIC) |
1169 |
ldap_parse_host (entry, cfile); |
1170 |
else |
1171 |
{ |
1172 |
ignore = 1; |
1173 |
break; |
1174 |
} |
1175 |
} |
1176 |
else if (strcasecmp (objectClass[i]->bv_val, "dhcpSubClass") == 0) |
1177 |
{ |
1178 |
if (ldap_method == LDAP_METHOD_STATIC) |
1179 |
ldap_parse_subclass (entry, cfile); |
1180 |
else |
1181 |
{ |
1182 |
ignore = 1; |
1183 |
break; |
1184 |
} |
1185 |
} |
1186 |
else |
1187 |
found = 0; |
1188 |
|
1189 |
if (found && cfile->inbuf[0] == '\0') |
1190 |
{ |
1191 |
ignore = 1; |
1192 |
break; |
1193 |
} |
1194 |
} |
1195 |
|
1196 |
ldap_value_free_len (objectClass); |
1197 |
|
1198 |
if (ignore) |
1199 |
{ |
1200 |
next_ldap_entry (cfile); |
1201 |
return; |
1202 |
} |
1203 |
|
1204 |
ldap_parse_entry_options(entry->ldent, cfile->inbuf, |
1205 |
LDAP_BUFFER_SIZE-1, NULL); |
1206 |
|
1207 |
dn = ldap_get_dn (ld, entry->ldent); |
1208 |
|
1209 |
#if defined(DEBUG_LDAP) |
1210 |
if (dn != NULL) |
1211 |
log_info ("Found LDAP entry '%s'", dn); |
1212 |
#endif |
1213 |
|
1214 |
if (dn == NULL || |
1215 |
(ret = ldap_search_ext_s (ld, dn, LDAP_SCOPE_ONELEVEL, |
1216 |
"objectClass=*", NULL, 0, NULL, NULL, |
1217 |
NULL, 0, &res)) != LDAP_SUCCESS) |
1218 |
{ |
1219 |
if (dn) |
1220 |
ldap_memfree (dn); |
1221 |
|
1222 |
ldap_stop(); |
1223 |
return; |
1224 |
} |
1225 |
|
1226 |
ldap_memfree (dn); |
1227 |
|
1228 |
if ((ent = ldap_first_entry (ld, res)) != NULL) |
1229 |
{ |
1230 |
add_to_config_stack (res, ent); |
1231 |
parse_external_dns (entry->ldent); |
1232 |
} |
1233 |
else |
1234 |
{ |
1235 |
ldap_msgfree (res); |
1236 |
parse_external_dns (entry->ldent); |
1237 |
next_ldap_entry (cfile); |
1238 |
} |
1239 |
} |
1240 |
|
1241 |
|
1242 |
static void |
1243 |
ldap_close_debug_fd() |
1244 |
{ |
1245 |
if (ldap_debug_fd != -1) |
1246 |
{ |
1247 |
close (ldap_debug_fd); |
1248 |
ldap_debug_fd = -1; |
1249 |
} |
1250 |
} |
1251 |
|
1252 |
|
1253 |
static void |
1254 |
ldap_write_debug (const void *buff, size_t size) |
1255 |
{ |
1256 |
if (ldap_debug_fd != -1) |
1257 |
{ |
1258 |
if (write (ldap_debug_fd, buff, size) < 0) |
1259 |
{ |
1260 |
log_error ("Error writing to LDAP debug file %s: %s." |
1261 |
" Disabling log file.", ldap_debug_file, |
1262 |
strerror (errno)); |
1263 |
ldap_close_debug_fd(); |
1264 |
} |
1265 |
} |
1266 |
} |
1267 |
|
1268 |
static int |
1269 |
ldap_read_function (struct parse *cfile) |
1270 |
{ |
1271 |
cfile->inbuf[0] = '\0'; |
1272 |
cfile->buflen = 0; |
1273 |
|
1274 |
while (ldap_stack != NULL && *cfile->inbuf == '\0') |
1275 |
ldap_generate_config_string (cfile); |
1276 |
|
1277 |
if (ldap_stack == NULL && *cfile->inbuf == '\0') |
1278 |
return (EOF); |
1279 |
|
1280 |
cfile->bufix = 1; |
1281 |
cfile->buflen = strlen (cfile->inbuf); |
1282 |
if (cfile->buflen > 0) |
1283 |
ldap_write_debug (cfile->inbuf, cfile->buflen); |
1284 |
|
1285 |
#if defined (DEBUG_LDAP) |
1286 |
log_info ("Sending config line '%s'", cfile->inbuf); |
1287 |
#endif |
1288 |
|
1289 |
return (cfile->inbuf[0]); |
1290 |
} |
1291 |
|
1292 |
|
1293 |
static char * |
1294 |
ldap_get_host_name (LDAPMessage * ent) |
1295 |
{ |
1296 |
struct berval **name; |
1297 |
char *ret; |
1298 |
|
1299 |
ret = NULL; |
1300 |
if ((name = ldap_get_values_len (ld, ent, "cn")) == NULL || name[0] == NULL) |
1301 |
{ |
1302 |
if (name != NULL) |
1303 |
ldap_value_free_len (name); |
1304 |
|
1305 |
#if defined (DEBUG_LDAP) |
1306 |
ret = ldap_get_dn (ld, ent); |
1307 |
if (ret != NULL) |
1308 |
{ |
1309 |
log_info ("Cannot get cn attribute for LDAP entry %s", ret); |
1310 |
ldap_memfree(ret); |
1311 |
} |
1312 |
#endif |
1313 |
return (NULL); |
1314 |
} |
1315 |
|
1316 |
ret = dmalloc (strlen (name[0]->bv_val) + 1, MDL); |
1317 |
strcpy (ret, name[0]->bv_val); |
1318 |
ldap_value_free_len (name); |
1319 |
|
1320 |
return (ret); |
1321 |
} |
1322 |
|
1323 |
|
1324 |
static int |
1325 |
getfqhostname(char *fqhost, size_t size) |
1326 |
{ |
1327 |
#if defined(MAXHOSTNAMELEN) |
1328 |
char hname[MAXHOSTNAMELEN]; |
1329 |
#else |
1330 |
char hname[65]; |
1331 |
#endif |
1332 |
struct hostent *hp; |
1333 |
|
1334 |
if(NULL == fqhost || 1 >= size) |
1335 |
return -1; |
1336 |
|
1337 |
memset(hname, 0, sizeof(hname)); |
1338 |
if( gethostname(hname, sizeof(hname)-1)) |
1339 |
return -1; |
1340 |
|
1341 |
if(NULL == (hp = gethostbyname(hname))) |
1342 |
return -1; |
1343 |
|
1344 |
strncpy(fqhost, hp->h_name, size-1); |
1345 |
fqhost[size-1] = '\0'; |
1346 |
return 0; |
1347 |
} |
1348 |
|
1349 |
|
1350 |
isc_result_t |
1351 |
ldap_read_config (void) |
1352 |
{ |
1353 |
LDAPMessage * ldres, * hostres, * ent, * hostent; |
1354 |
char hfilter[1024], sfilter[1024], fqdn[257]; |
1355 |
char *buffer, *hostdn; |
1356 |
ldap_dn_node *curr = NULL; |
1357 |
struct parse *cfile; |
1358 |
struct utsname unme; |
1359 |
isc_result_t res; |
1360 |
size_t length; |
1361 |
int ret, cnt; |
1362 |
struct berval **tempbv = NULL; |
1363 |
|
1364 |
if (ld == NULL) |
1365 |
ldap_start (); |
1366 |
if (ld == NULL) |
1367 |
return (ldap_server == NULL ? ISC_R_SUCCESS : ISC_R_FAILURE); |
1368 |
|
1369 |
buffer = dmalloc (LDAP_BUFFER_SIZE+1, MDL); |
1370 |
if (buffer == NULL) |
1371 |
return (ISC_R_FAILURE); |
1372 |
|
1373 |
cfile = (struct parse *) NULL; |
1374 |
res = new_parse (&cfile, -1, buffer, LDAP_BUFFER_SIZE, "LDAP", 0); |
1375 |
if (res != ISC_R_SUCCESS) |
1376 |
return (res); |
1377 |
|
1378 |
uname (&unme); |
1379 |
if (ldap_dhcp_server_cn != NULL) |
1380 |
{ |
1381 |
snprintf (hfilter, sizeof (hfilter), |
1382 |
"(&(objectClass=dhcpServer)(cn=%s))", ldap_dhcp_server_cn); |
1383 |
} |
1384 |
else |
1385 |
{ |
1386 |
if(0 == getfqhostname(fqdn, sizeof(fqdn))) |
1387 |
{ |
1388 |
snprintf (hfilter, sizeof (hfilter), |
1389 |
"(&(objectClass=dhcpServer)(|(cn=%s)(cn=%s)))", |
1390 |
unme.nodename, fqdn); |
1391 |
} |
1392 |
else |
1393 |
{ |
1394 |
snprintf (hfilter, sizeof (hfilter), |
1395 |
"(&(objectClass=dhcpServer)(cn=%s))", unme.nodename); |
1396 |
} |
1397 |
|
1398 |
} |
1399 |
hostres = NULL; |
1400 |
if ((ret = ldap_search_ext_s (ld, ldap_base_dn, LDAP_SCOPE_SUBTREE, |
1401 |
hfilter, NULL, 0, NULL, NULL, NULL, 0, |
1402 |
&hostres)) != LDAP_SUCCESS) |
1403 |
{ |
1404 |
log_error ("Cannot find host LDAP entry %s %s", |
1405 |
((ldap_dhcp_server_cn == NULL)?(unme.nodename):(ldap_dhcp_server_cn)), hfilter); |
1406 |
if(NULL != hostres) |
1407 |
ldap_msgfree (hostres); |
1408 |
ldap_stop(); |
1409 |
return (ISC_R_FAILURE); |
1410 |
} |
1411 |
|
1412 |
if ((hostent = ldap_first_entry (ld, hostres)) == NULL) |
1413 |
{ |
1414 |
log_error ("Error: Cannot find LDAP entry matching %s", hfilter); |
1415 |
ldap_msgfree (hostres); |
1416 |
ldap_stop(); |
1417 |
return (ISC_R_FAILURE); |
1418 |
} |
1419 |
|
1420 |
hostdn = ldap_get_dn (ld, hostent); |
1421 |
#if defined(DEBUG_LDAP) |
1422 |
if (hostdn != NULL) |
1423 |
log_info ("Found dhcpServer LDAP entry '%s'", hostdn); |
1424 |
#endif |
1425 |
|
1426 |
if (hostdn == NULL || |
1427 |
(tempbv = ldap_get_values_len (ld, hostent, "dhcpServiceDN")) == NULL || |
1428 |
tempbv[0] == NULL) |
1429 |
{ |
1430 |
log_error ("Error: Cannot find LDAP entry matching %s", hfilter); |
1431 |
|
1432 |
if (tempbv != NULL) |
1433 |
ldap_value_free_len (tempbv); |
1434 |
|
1435 |
if (hostdn) |
1436 |
ldap_memfree (hostdn); |
1437 |
ldap_msgfree (hostres); |
1438 |
ldap_stop(); |
1439 |
return (ISC_R_FAILURE); |
1440 |
} |
1441 |
|
1442 |
#if defined(DEBUG_LDAP) |
1443 |
log_info ("LDAP: Parsing dhcpServer options '%s' ...", hostdn); |
1444 |
#endif |
1445 |
|
1446 |
cfile->inbuf[0] = '\0'; |
1447 |
ldap_parse_entry_options(hostent, cfile->inbuf, LDAP_BUFFER_SIZE, NULL); |
1448 |
cfile->buflen = strlen (cfile->inbuf); |
1449 |
if(cfile->buflen > 0) |
1450 |
{ |
1451 |
ldap_write_debug (cfile->inbuf, cfile->buflen); |
1452 |
|
1453 |
res = conf_file_subparse (cfile, root_group, ROOT_GROUP); |
1454 |
if (res != ISC_R_SUCCESS) |
1455 |
{ |
1456 |
log_error ("LDAP: cannot parse dhcpServer entry '%s'", hostdn); |
1457 |
ldap_memfree (hostdn); |
1458 |
ldap_stop(); |
1459 |
return res; |
1460 |
} |
1461 |
cfile->inbuf[0] = '\0'; |
1462 |
} |
1463 |
ldap_msgfree (hostres); |
1464 |
|
1465 |
/* |
1466 |
** attach ldap (tree) read function now |
1467 |
*/ |
1468 |
cfile->bufix = cfile->buflen = 0; |
1469 |
cfile->read_function = ldap_read_function; |
1470 |
|
1471 |
res = ISC_R_SUCCESS; |
1472 |
for (cnt=0; tempbv[cnt] != NULL; cnt++) |
1473 |
{ |
1474 |
snprintf(sfilter, sizeof(sfilter), "(&(objectClass=dhcpService)" |
1475 |
"(|(dhcpPrimaryDN=%s)(dhcpSecondaryDN=%s)))", |
1476 |
hostdn, hostdn); |
1477 |
ldres = NULL; |
1478 |
if ((ret = ldap_search_ext_s (ld, tempbv[cnt]->bv_val, LDAP_SCOPE_BASE, |
1479 |
sfilter, NULL, 0, NULL, NULL, NULL, |
1480 |
0, &ldres)) != LDAP_SUCCESS) |
1481 |
{ |
1482 |
log_error ("Error searching for dhcpServiceDN '%s': %s. Please update the LDAP entry '%s'", |
1483 |
tempbv[cnt]->bv_val, ldap_err2string (ret), hostdn); |
1484 |
if(NULL != ldres) |
1485 |
ldap_msgfree(ldres); |
1486 |
res = ISC_R_FAILURE; |
1487 |
break; |
1488 |
} |
1489 |
|
1490 |
if ((ent = ldap_first_entry (ld, ldres)) == NULL) |
1491 |
{ |
1492 |
log_error ("Error: Cannot find dhcpService DN '%s' with primary or secondary server reference. Please update the LDAP server entry '%s'", |
1493 |
tempbv[cnt]->bv_val, hostdn); |
1494 |
|
1495 |
ldap_msgfree(ldres); |
1496 |
res = ISC_R_FAILURE; |
1497 |
break; |
1498 |
} |
1499 |
|
1500 |
/* |
1501 |
** FIXME: how to free the remembered dn's on exit? |
1502 |
** This should be OK if dmalloc registers the |
1503 |
** memory it allocated and frees it on exit.. |
1504 |
*/ |
1505 |
|
1506 |
curr = dmalloc (sizeof (*curr), MDL); |
1507 |
if (curr != NULL) |
1508 |
{ |
1509 |
length = strlen (tempbv[cnt]->bv_val); |
1510 |
curr->dn = dmalloc (length + 1, MDL); |
1511 |
if (curr->dn == NULL) |
1512 |
{ |
1513 |
dfree (curr, MDL); |
1514 |
curr = NULL; |
1515 |
} |
1516 |
else |
1517 |
strcpy (curr->dn, tempbv[cnt]->bv_val); |
1518 |
} |
1519 |
|
1520 |
if (curr != NULL) |
1521 |
{ |
1522 |
curr->refs++; |
1523 |
|
1524 |
/* append to service-dn list */ |
1525 |
if (ldap_service_dn_tail != NULL) |
1526 |
ldap_service_dn_tail->next = curr; |
1527 |
else |
1528 |
ldap_service_dn_head = curr; |
1529 |
|
1530 |
ldap_service_dn_tail = curr; |
1531 |
} |
1532 |
else |
1533 |
log_fatal ("no memory to remember ldap service dn"); |
1534 |
|
1535 |
#if defined (DEBUG_LDAP) |
1536 |
log_info ("LDAP: Parsing dhcpService DN '%s' ...", tempbv[cnt]); |
1537 |
#endif |
1538 |
add_to_config_stack (ldres, ent); |
1539 |
res = conf_file_subparse (cfile, root_group, ROOT_GROUP); |
1540 |
if (res != ISC_R_SUCCESS) |
1541 |
{ |
1542 |
log_error ("LDAP: cannot parse dhcpService entry '%s'", tempbv[cnt]->bv_val); |
1543 |
break; |
1544 |
} |
1545 |
} |
1546 |
|
1547 |
end_parse (&cfile); |
1548 |
ldap_close_debug_fd(); |
1549 |
|
1550 |
ldap_memfree (hostdn); |
1551 |
ldap_value_free_len (tempbv); |
1552 |
|
1553 |
if (res != ISC_R_SUCCESS) |
1554 |
{ |
1555 |
struct ldap_config_stack *temp_stack; |
1556 |
|
1557 |
while ((curr = ldap_service_dn_head) != NULL) |
1558 |
{ |
1559 |
ldap_service_dn_head = curr->next; |
1560 |
dfree (curr->dn, MDL); |
1561 |
dfree (curr, MDL); |
1562 |
} |
1563 |
|
1564 |
ldap_service_dn_tail = NULL; |
1565 |
|
1566 |
while ((temp_stack = ldap_stack) != NULL) |
1567 |
{ |
1568 |
ldap_stack = temp_stack->next; |
1569 |
free_stack_entry (temp_stack); |
1570 |
} |
1571 |
|
1572 |
ldap_stop(); |
1573 |
} |
1574 |
|
1575 |
/* Unbind from ldap immediately after reading config in static mode. */ |
1576 |
if (ldap_method == LDAP_METHOD_STATIC) |
1577 |
ldap_stop(); |
1578 |
|
1579 |
return (res); |
1580 |
} |
1581 |
|
1582 |
|
1583 |
/* This function will parse the dhcpOption and dhcpStatements field in the LDAP |
1584 |
entry if it exists. Right now, type will be either HOST_DECL or CLASS_DECL. |
1585 |
If we are parsing a HOST_DECL, this always returns 0. If we are parsing a |
1586 |
CLASS_DECL, this will return what the current lease limit is in LDAP. If |
1587 |
there is no lease limit specified, we return 0 */ |
1588 |
|
1589 |
static int |
1590 |
ldap_parse_options (LDAPMessage * ent, struct group *group, |
1591 |
int type, struct host_decl *host, |
1592 |
struct class **class) |
1593 |
{ |
1594 |
int declaration, lease_limit; |
1595 |
char option_buffer[8192]; |
1596 |
enum dhcp_token token; |
1597 |
struct parse *cfile; |
1598 |
isc_result_t res; |
1599 |
const char *val; |
1600 |
|
1601 |
lease_limit = 0; |
1602 |
*option_buffer = '\0'; |
1603 |
|
1604 |
/* This block of code will try to find the parent of the host, and |
1605 |
if it is a group object, fetch the options and apply to the host. */ |
1606 |
if (type == HOST_DECL) |
1607 |
{ |
1608 |
char *hostdn, *basedn, *temp1, *temp2, filter[1024]; |
1609 |
LDAPMessage *groupdn, *entry; |
1610 |
int ret; |
1611 |
|
1612 |
hostdn = ldap_get_dn (ld, ent); |
1613 |
if( hostdn != NULL) |
1614 |
{ |
1615 |
basedn = NULL; |
1616 |
|
1617 |
temp1 = strchr (hostdn, '='); |
1618 |
if (temp1 != NULL) |
1619 |
temp1 = strchr (++temp1, '='); |
1620 |
if (temp1 != NULL) |
1621 |
temp2 = strchr (++temp1, ','); |
1622 |
else |
1623 |
temp2 = NULL; |
1624 |
|
1625 |
if (temp2 != NULL) |
1626 |
{ |
1627 |
snprintf (filter, sizeof(filter), |
1628 |
"(&(cn=%.*s)(objectClass=dhcpGroup))", |
1629 |
(int)(temp2 - temp1), temp1); |
1630 |
|
1631 |
basedn = strchr (temp1, ','); |
1632 |
if (basedn != NULL) |
1633 |
++basedn; |
1634 |
} |
1635 |
|
1636 |
if (basedn != NULL && *basedn != '\0') |
1637 |
{ |
1638 |
ret = ldap_search_ext_s (ld, basedn, LDAP_SCOPE_SUBTREE, filter, |
1639 |
NULL, 0, NULL, NULL, NULL, 0, &groupdn); |
1640 |
if (ret == LDAP_SUCCESS) |
1641 |
{ |
1642 |
if ((entry = ldap_first_entry (ld, groupdn)) != NULL) |
1643 |
{ |
1644 |
res = ldap_parse_entry_options (entry, option_buffer, |
1645 |
sizeof(option_buffer) - 1, |
1646 |
&lease_limit); |
1647 |
if (res != ISC_R_SUCCESS) |
1648 |
{ |
1649 |
/* reset option buffer discarding any results */ |
1650 |
*option_buffer = '\0'; |
1651 |
lease_limit = 0; |
1652 |
} |
1653 |
} |
1654 |
ldap_msgfree( groupdn); |
1655 |
} |
1656 |
} |
1657 |
ldap_memfree( hostdn); |
1658 |
} |
1659 |
} |
1660 |
|
1661 |
res = ldap_parse_entry_options (ent, option_buffer, sizeof(option_buffer) - 1, |
1662 |
&lease_limit); |
1663 |
if (res != ISC_R_SUCCESS) |
1664 |
return (lease_limit); |
1665 |
|
1666 |
option_buffer[sizeof(option_buffer) - 1] = '\0'; |
1667 |
if (*option_buffer == '\0') |
1668 |
return (lease_limit); |
1669 |
|
1670 |
cfile = (struct parse *) NULL; |
1671 |
res = new_parse (&cfile, -1, option_buffer, strlen (option_buffer), |
1672 |
type == HOST_DECL ? "LDAP-HOST" : "LDAP-SUBCLASS", 0); |
1673 |
if (res != ISC_R_SUCCESS) |
1674 |
return (lease_limit); |
1675 |
|
1676 |
#if defined (DEBUG_LDAP) |
1677 |
log_info ("Sending the following options: '%s'", option_buffer); |
1678 |
#endif |
1679 |
|
1680 |
declaration = 0; |
1681 |
do |
1682 |
{ |
1683 |
token = peek_token (&val, NULL, cfile); |
1684 |
if (token == END_OF_FILE) |
1685 |
break; |
1686 |
declaration = parse_statement (cfile, group, type, host, declaration); |
1687 |
} while (1); |
1688 |
|
1689 |
end_parse (&cfile); |
1690 |
|
1691 |
return (lease_limit); |
1692 |
} |
1693 |
|
1694 |
|
1695 |
|
1696 |
int |
1697 |
find_haddr_in_ldap (struct host_decl **hp, int htype, unsigned hlen, |
1698 |
const unsigned char *haddr, const char *file, int line) |
1699 |
{ |
1700 |
char buf[128], *type_str; |
1701 |
LDAPMessage * res, *ent; |
1702 |
struct host_decl * host; |
1703 |
isc_result_t status; |
1704 |
ldap_dn_node *curr; |
1705 |
int ret; |
1706 |
|
1707 |
if (ldap_method == LDAP_METHOD_STATIC) |
1708 |
return (0); |
1709 |
|
1710 |
if (ld == NULL) |
1711 |
ldap_start (); |
1712 |
if (ld == NULL) |
1713 |
return (0); |
1714 |
|
1715 |
switch (htype) |
1716 |
{ |
1717 |
case HTYPE_ETHER: |
1718 |
type_str = "ethernet"; |
1719 |
break; |
1720 |
case HTYPE_IEEE802: |
1721 |
type_str = "token-ring"; |
1722 |
break; |
1723 |
case HTYPE_FDDI: |
1724 |
type_str = "fddi"; |
1725 |
break; |
1726 |
default: |
1727 |
log_info ("Ignoring unknown type %d", htype); |
1728 |
return (0); |
1729 |
} |
1730 |
|
1731 |
/* |
1732 |
** FIXME: It is not guaranteed, that the dhcpHWAddress attribute |
1733 |
** contains _exactly_ "type addr" with one space between! |
1734 |
*/ |
1735 |
snprintf (buf, sizeof (buf), |
1736 |
"(&(objectClass=dhcpHost)(dhcpHWAddress=%s %s))", |
1737 |
type_str, print_hw_addr (htype, hlen, haddr)); |
1738 |
|
1739 |
res = ent = NULL; |
1740 |
for (curr = ldap_service_dn_head; |
1741 |
curr != NULL && *curr->dn != '\0'; |
1742 |
curr = curr->next) |
1743 |
{ |
1744 |
#if defined (DEBUG_LDAP) |
1745 |
log_info ("Searching for %s in LDAP tree %s", buf, curr->dn); |
1746 |
#endif |
1747 |
ret = ldap_search_ext_s (ld, curr->dn, LDAP_SCOPE_SUBTREE, buf, NULL, 0, |
1748 |
NULL, NULL, NULL, 0, &res); |
1749 |
|
1750 |
if(ret == LDAP_SERVER_DOWN) |
1751 |
{ |
1752 |
log_info ("LDAP server was down, trying to reconnect..."); |
1753 |
|
1754 |
ldap_stop(); |
1755 |
ldap_start(); |
1756 |
if(ld == NULL) |
1757 |
{ |
1758 |
log_info ("LDAP reconnect failed - try again later..."); |
1759 |
return (0); |
1760 |
} |
1761 |
|
1762 |
ret = ldap_search_ext_s (ld, curr->dn, LDAP_SCOPE_SUBTREE, buf, NULL, |
1763 |
0, NULL, NULL, NULL, 0, &res); |
1764 |
} |
1765 |
|
1766 |
if (ret == LDAP_SUCCESS) |
1767 |
{ |
1768 |
if( (ent = ldap_first_entry (ld, res)) != NULL) |
1769 |
break; /* search OK and have entry */ |
1770 |
|
1771 |
#if defined (DEBUG_LDAP) |
1772 |
log_info ("No host entry for %s in LDAP tree %s", |
1773 |
buf, curr->dn); |
1774 |
#endif |
1775 |
if(res) |
1776 |
{ |
1777 |
ldap_msgfree (res); |
1778 |
res = NULL; |
1779 |
} |
1780 |
} |
1781 |
else |
1782 |
{ |
1783 |
if(res) |
1784 |
{ |
1785 |
ldap_msgfree (res); |
1786 |
res = NULL; |
1787 |
} |
1788 |
|
1789 |
if (ret != LDAP_NO_SUCH_OBJECT && ret != LDAP_SUCCESS) |
1790 |
{ |
1791 |
log_error ("Cannot search for %s in LDAP tree %s: %s", buf, |
1792 |
curr->dn, ldap_err2string (ret)); |
1793 |
ldap_stop(); |
1794 |
return (0); |
1795 |
} |
1796 |
#if defined (DEBUG_LDAP) |
1797 |
else |
1798 |
{ |
1799 |
log_info ("ldap_search_ext_s returned %s when searching for %s in %s", |
1800 |
ldap_err2string (ret), buf, curr->dn); |
1801 |
} |
1802 |
#endif |
1803 |
} |
1804 |
} |
1805 |
|
1806 |
if (res && ent) |
1807 |
{ |
1808 |
#if defined (DEBUG_LDAP) |
1809 |
char *dn = ldap_get_dn (ld, ent); |
1810 |
if (dn != NULL) |
1811 |
{ |
1812 |
log_info ("Found dhcpHWAddress LDAP entry %s", dn); |
1813 |
ldap_memfree(dn); |
1814 |
} |
1815 |
#endif |
1816 |
|
1817 |
host = (struct host_decl *)0; |
1818 |
status = host_allocate (&host, MDL); |
1819 |
if (status != ISC_R_SUCCESS) |
1820 |
{ |
1821 |
log_fatal ("can't allocate host decl struct: %s", |
1822 |
isc_result_totext (status)); |
1823 |
ldap_msgfree (res); |
1824 |
return (0); |
1825 |
} |
1826 |
|
1827 |
host->name = ldap_get_host_name (ent); |
1828 |
if (host->name == NULL) |
1829 |
{ |
1830 |
host_dereference (&host, MDL); |
1831 |
ldap_msgfree (res); |
1832 |
return (0); |
1833 |
} |
1834 |
|
1835 |
if (!clone_group (&host->group, root_group, MDL)) |
1836 |
{ |
1837 |
log_fatal ("can't clone group for host %s", host->name); |
1838 |
host_dereference (&host, MDL); |
1839 |
ldap_msgfree (res); |
1840 |
return (0); |
1841 |
} |
1842 |
|
1843 |
ldap_parse_options (ent, host->group, HOST_DECL, host, NULL); |
1844 |
|
1845 |
*hp = host; |
1846 |
ldap_msgfree (res); |
1847 |
return (1); |
1848 |
} |
1849 |
|
1850 |
|
1851 |
if(res) ldap_msgfree (res); |
1852 |
return (0); |
1853 |
} |
1854 |
|
1855 |
|
1856 |
int |
1857 |
find_subclass_in_ldap (struct class *class, struct class **newclass, |
1858 |
struct data_string *data) |
1859 |
{ |
1860 |
LDAPMessage * res, * ent; |
1861 |
int ret, lease_limit; |
1862 |
isc_result_t status; |
1863 |
ldap_dn_node *curr; |
1864 |
char buf[1024]; |
1865 |
|
1866 |
if (ldap_method == LDAP_METHOD_STATIC) |
1867 |
return (0); |
1868 |
|
1869 |
if (ld == NULL) |
1870 |
ldap_start (); |
1871 |
if (ld == NULL) |
1872 |
return (0); |
1873 |
|
1874 |
snprintf (buf, sizeof (buf), |
1875 |
"(&(objectClass=dhcpSubClass)(cn=%s)(dhcpClassData=%s))", |
1876 |
print_hex_1 (data->len, data->data, 60), |
1877 |
print_hex_2 (strlen (class->name), (u_int8_t *) class->name, 60)); |
1878 |
#if defined (DEBUG_LDAP) |
1879 |
log_info ("Searching LDAP for %s", buf); |
1880 |
#endif |
1881 |
|
1882 |
res = ent = NULL; |
1883 |
for (curr = ldap_service_dn_head; |
1884 |
curr != NULL && *curr->dn != '\0'; |
1885 |
curr = curr->next) |
1886 |
{ |
1887 |
#if defined (DEBUG_LDAP) |
1888 |
log_info ("Searching for %s in LDAP tree %s", buf, curr->dn); |
1889 |
#endif |
1890 |
ret = ldap_search_ext_s (ld, curr->dn, LDAP_SCOPE_SUBTREE, buf, NULL, 0, |
1891 |
NULL, NULL, NULL, 0, &res); |
1892 |
|
1893 |
if(ret == LDAP_SERVER_DOWN) |
1894 |
{ |
1895 |
log_info ("LDAP server was down, trying to reconnect..."); |
1896 |
|
1897 |
ldap_stop(); |
1898 |
ldap_start(); |
1899 |
|
1900 |
if(ld == NULL) |
1901 |
{ |
1902 |
log_info ("LDAP reconnect failed - try again later..."); |
1903 |
return (0); |
1904 |
} |
1905 |
|
1906 |
ret = ldap_search_ext_s (ld, curr->dn, LDAP_SCOPE_SUBTREE, buf, |
1907 |
NULL, 0, NULL, NULL, NULL, 0, &res); |
1908 |
} |
1909 |
|
1910 |
if (ret == LDAP_SUCCESS) |
1911 |
{ |
1912 |
if( (ent = ldap_first_entry (ld, res)) != NULL) |
1913 |
break; /* search OK and have entry */ |
1914 |
|
1915 |
#if defined (DEBUG_LDAP) |
1916 |
log_info ("No subclass entry for %s in LDAP tree %s", |
1917 |
buf, curr->dn); |
1918 |
#endif |
1919 |
if(res) |
1920 |
{ |
1921 |
ldap_msgfree (res); |
1922 |
res = NULL; |
1923 |
} |
1924 |
} |
1925 |
else |
1926 |
{ |
1927 |
if(res) |
1928 |
{ |
1929 |
ldap_msgfree (res); |
1930 |
res = NULL; |
1931 |
} |
1932 |
|
1933 |
if (ret != LDAP_NO_SUCH_OBJECT && ret != LDAP_SUCCESS) |
1934 |
{ |
1935 |
log_error ("Cannot search for %s in LDAP tree %s: %s", buf, |
1936 |
curr->dn, ldap_err2string (ret)); |
1937 |
ldap_stop(); |
1938 |
return (0); |
1939 |
} |
1940 |
#if defined (DEBUG_LDAP) |
1941 |
else |
1942 |
{ |
1943 |
log_info ("ldap_search_ext_s returned %s when searching for %s in %s", |
1944 |
ldap_err2string (ret), buf, curr->dn); |
1945 |
} |
1946 |
#endif |
1947 |
} |
1948 |
} |
1949 |
|
1950 |
if (res && ent) |
1951 |
{ |
1952 |
#if defined (DEBUG_LDAP) |
1953 |
char *dn = ldap_get_dn (ld, ent); |
1954 |
if (dn != NULL) |
1955 |
{ |
1956 |
log_info ("Found subclass LDAP entry %s", dn); |
1957 |
ldap_memfree(dn); |
1958 |
} |
1959 |
#endif |
1960 |
|
1961 |
status = class_allocate (newclass, MDL); |
1962 |
if (status != ISC_R_SUCCESS) |
1963 |
{ |
1964 |
log_error ("Cannot allocate memory for a new class"); |
1965 |
ldap_msgfree (res); |
1966 |
return (0); |
1967 |
} |
1968 |
|
1969 |
group_reference (&(*newclass)->group, class->group, MDL); |
1970 |
class_reference (&(*newclass)->superclass, class, MDL); |
1971 |
lease_limit = ldap_parse_options (ent, (*newclass)->group, |
1972 |
CLASS_DECL, NULL, newclass); |
1973 |
if (lease_limit == 0) |
1974 |
(*newclass)->lease_limit = class->lease_limit; |
1975 |
else |
1976 |
class->lease_limit = lease_limit; |
1977 |
|
1978 |
if ((*newclass)->lease_limit) |
1979 |
{ |
1980 |
(*newclass)->billed_leases = |
1981 |
dmalloc ((*newclass)->lease_limit * sizeof (struct lease *), MDL); |
1982 |
if (!(*newclass)->billed_leases) |
1983 |
{ |
1984 |
log_error ("no memory for billing"); |
1985 |
class_dereference (newclass, MDL); |
1986 |
ldap_msgfree (res); |
1987 |
return (0); |
1988 |
} |
1989 |
memset ((*newclass)->billed_leases, 0, |
1990 |
((*newclass)->lease_limit * sizeof (*newclass)->billed_leases)); |
1991 |
} |
1992 |
|
1993 |
data_string_copy (&(*newclass)->hash_string, data, MDL); |
1994 |
|
1995 |
ldap_msgfree (res); |
1996 |
return (1); |
1997 |
} |
1998 |
|
1999 |
if(res) ldap_msgfree (res); |
2000 |
return (0); |
2001 |
} |
2002 |
|
2003 |
#endif |