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