1/* $NetBSD: ldap.c,v 1.4 2022/04/03 01:10:59 christos Exp $ */ 2 3/* ldap.c 4 5 Routines for reading the configuration from LDAP */ 6 7/* 8 * Copyright (c) 2010-2022 by Internet Systems Consortium, Inc. ("ISC") 9 * Copyright (c) 2003-2006 Ntelos, Inc. 10 * All rights reserved. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 16 * 1. Redistributions of source code must retain the above copyright 17 * notice, this list of conditions and the following disclaimer. 18 * 2. Redistributions in binary form must reproduce the above copyright 19 * notice, this list of conditions and the following disclaimer in the 20 * documentation and/or other materials provided with the distribution. 21 * 3. Neither the name of The Internet Software Consortium nor the names 22 * of its contributors may be used to endorse or promote products derived 23 * from this software without specific prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND 26 * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 27 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 28 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 29 * DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR 30 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 31 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 32 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 33 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 34 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 35 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 36 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 37 * SUCH DAMAGE. 38 * 39 * This LDAP module was written by Brian Masney <masneyb@ntelos.net>. Its 40 * development was sponsored by Ntelos, Inc. (www.ntelos.com). 41 */ 42 43#include <sys/cdefs.h> 44__RCSID("$NetBSD: ldap.c,v 1.4 2022/04/03 01:10:59 christos Exp $"); 45 46 47#include "dhcpd.h" 48#if defined(LDAP_CONFIGURATION) 49#include <signal.h> 50#include <errno.h> 51#include <ctype.h> 52#include <netdb.h> 53#include <net/if.h> 54#if defined(HAVE_IFADDRS_H) 55#include <ifaddrs.h> 56#endif 57#include <string.h> 58 59#if defined(LDAP_CASA_AUTH) 60#include "ldap_casa.h" 61#endif 62 63#if defined(LDAP_USE_GSSAPI) 64#include <sasl/sasl.h> 65#include "ldap_krb_helper.h" 66#endif 67 68static LDAP * ld = NULL; 69static char *ldap_server = NULL, 70 *ldap_username = NULL, 71 *ldap_password = NULL, 72 *ldap_base_dn = NULL, 73 *ldap_dhcp_server_cn = NULL, 74 *ldap_debug_file = NULL; 75static int ldap_port = LDAP_PORT, 76 ldap_method = LDAP_METHOD_DYNAMIC, 77 ldap_referrals = -1, 78 ldap_debug_fd = -1, 79 ldap_enable_retry = -1, 80 ldap_init_retry = -1; 81#if defined (LDAP_USE_SSL) 82static int ldap_use_ssl = -1, /* try TLS if possible */ 83 ldap_tls_reqcert = -1, 84 ldap_tls_crlcheck = -1; 85static char *ldap_tls_ca_file = NULL, 86 *ldap_tls_ca_dir = NULL, 87 *ldap_tls_cert = NULL, 88 *ldap_tls_key = NULL, 89 *ldap_tls_ciphers = NULL, 90 *ldap_tls_randfile = NULL; 91#endif 92 93#if defined (LDAP_USE_GSSAPI) 94static char *ldap_gssapi_keytab = NULL, 95 *ldap_gssapi_principal = NULL; 96 97struct ldap_sasl_instance { 98 char *sasl_mech; 99 char *sasl_realm; 100 char *sasl_authz_id; 101 char *sasl_authc_id; 102 char *sasl_password; 103}; 104 105static struct ldap_sasl_instance *ldap_sasl_inst = NULL; 106 107static int 108_ldap_sasl_interact(LDAP *ld, unsigned flags, void *defaults, void *sin) ; 109#endif 110 111static struct ldap_config_stack *ldap_stack = NULL; 112 113typedef struct ldap_dn_node { 114 struct ldap_dn_node *next; 115 size_t refs; 116 char *dn; 117} ldap_dn_node; 118 119static ldap_dn_node *ldap_service_dn_head = NULL; 120static ldap_dn_node *ldap_service_dn_tail = NULL; 121 122static int ldap_read_function (struct parse *cfile); 123 124static struct parse * 125x_parser_init(const char *name) 126{ 127 struct parse *cfile; 128 isc_result_t res; 129 char *inbuf; 130 131 inbuf = dmalloc (LDAP_BUFFER_SIZE, MDL); 132 if (inbuf == NULL) 133 return NULL; 134 135 cfile = (struct parse *) NULL; 136 res = new_parse (&cfile, -1, inbuf, LDAP_BUFFER_SIZE, name, 0); 137 if (res != ISC_R_SUCCESS) 138 { 139 dfree(inbuf, MDL); 140 return NULL; 141 } 142 /* the buffer is still empty */ 143 cfile->bufsiz = LDAP_BUFFER_SIZE; 144 cfile->buflen = cfile->bufix = 0; 145 /* attach ldap read function */ 146 cfile->read_function = ldap_read_function; 147 return cfile; 148} 149 150static isc_result_t 151x_parser_free(struct parse **cfile) 152{ 153 if (cfile && *cfile) 154 { 155 if ((*cfile)->inbuf) 156 dfree((*cfile)->inbuf, MDL); 157 (*cfile)->inbuf = NULL; 158 (*cfile)->bufsiz = 0; 159 return end_parse(cfile); 160 } 161 return ISC_R_SUCCESS; 162} 163 164static int 165x_parser_resize(struct parse *cfile, size_t len) 166{ 167 size_t size; 168 char * temp; 169 170 /* grow by len rounded up at LDAP_BUFFER_SIZE */ 171 size = cfile->bufsiz + (len | (LDAP_BUFFER_SIZE-1)) + 1; 172 173 /* realloc would be better, but there isn't any */ 174 if ((temp = dmalloc (size, MDL)) != NULL) 175 { 176#if defined (DEBUG_LDAP) 177 log_info ("Reallocated %s buffer from %zu to %zu", 178 cfile->tlname, cfile->bufsiz, size); 179#endif 180 memcpy(temp, cfile->inbuf, cfile->bufsiz); 181 dfree(cfile->inbuf, MDL); 182 cfile->inbuf = temp; 183 cfile->bufsiz = size; 184 return 1; 185 } 186 187 /* 188 * Hmm... what is worser, consider it as fatal error and 189 * bail out completely or discard config data in hope it 190 * is "only" an option in dynamic host lookup? 191 */ 192 log_error("Unable to reallocated %s buffer from %zu to %zu", 193 cfile->tlname, cfile->bufsiz, size); 194 return 0; 195} 196 197static char * 198x_parser_strcat(struct parse *cfile, const char *str) 199{ 200 size_t cur = strlen(cfile->inbuf); 201 size_t len = strlen(str); 202 size_t cnt; 203 204 if (cur + len >= cfile->bufsiz && !x_parser_resize(cfile, len)) 205 return NULL; 206 207 cnt = cfile->bufsiz > cur ? cfile->bufsiz - cur - 1 : 0; 208 return strncat(cfile->inbuf, str, cnt); 209} 210 211static inline void 212x_parser_reset(struct parse *cfile) 213{ 214 cfile->inbuf[0] = '\0'; 215 cfile->bufix = cfile->buflen = 0; 216} 217 218static inline size_t 219x_parser_length(struct parse *cfile) 220{ 221 cfile->buflen = strlen(cfile->inbuf); 222 return cfile->buflen; 223} 224 225static char * 226x_strxform(char *dst, const char *src, size_t dst_size, 227 int (*xform)(int)) 228{ 229 if(dst && src && dst_size) 230 { 231 size_t len, pos; 232 233 len = strlen(src); 234 for(pos=0; pos < len && pos + 1 < dst_size; pos++) 235 dst[pos] = xform((int)src[pos]); 236 dst[pos] = '\0'; 237 238 return dst; 239 } 240 return NULL; 241} 242 243static int 244get_host_entry(char *fqdnname, size_t fqdnname_size, 245 char *hostaddr, size_t hostaddr_size) 246{ 247#if defined(MAXHOSTNAMELEN) 248 char hname[MAXHOSTNAMELEN+1]; 249#else 250 char hname[65]; 251#endif 252 struct hostent *hp; 253 254 if (NULL == fqdnname || 1 >= fqdnname_size) 255 return -1; 256 257 memset(hname, 0, sizeof(hname)); 258 if (gethostname(hname, sizeof(hname)-1)) 259 return -1; 260 261 if (NULL == (hp = gethostbyname(hname))) 262 return -1; 263 264 strncpy(fqdnname, hp->h_name, fqdnname_size-1); 265 fqdnname[fqdnname_size-1] = '\0'; 266 267 if (hostaddr != NULL) 268 { 269 if (hp->h_addr != NULL) 270 { 271 struct in_addr *aptr = (struct in_addr *)hp->h_addr; 272#if defined(HAVE_INET_NTOP) 273 if (hostaddr_size >= INET_ADDRSTRLEN && 274 inet_ntop(AF_INET, aptr, hostaddr, hostaddr_size) != NULL) 275 { 276 return 0; 277 } 278#else 279 char *astr = inet_ntoa(*aptr); 280 size_t alen = strlen(astr); 281 if (astr && alen > 0 && hostaddr_size > alen) 282 { 283 strncpy(hostaddr, astr, hostaddr_size-1); 284 hostaddr[hostaddr_size-1] = '\0'; 285 return 0; 286 } 287#endif 288 } 289 return -1; 290 } 291 return 0; 292} 293 294#if defined(HAVE_IFADDRS_H) 295static int 296is_iface_address(struct ifaddrs *addrs, struct in_addr *addr) 297{ 298 struct ifaddrs *ia; 299 struct sockaddr_in *sa; 300 int num = 0; 301 302 if(addrs == NULL || addr == NULL) 303 return -1; 304 305 for (ia = addrs; ia != NULL; ia = ia->ifa_next) 306 { 307 ++num; 308 if (ia->ifa_addr && (ia->ifa_flags & IFF_UP) && 309 ia->ifa_addr->sa_family == AF_INET) 310 { 311 sa = (struct sockaddr_in *)(ia->ifa_addr); 312 if (addr->s_addr == sa->sin_addr.s_addr) 313 return num; 314 } 315 } 316 return 0; 317} 318 319static int 320get_host_address(const char *hostname, char *hostaddr, size_t hostaddr_size, struct ifaddrs *addrs) 321{ 322 if (hostname && *hostname && hostaddr && hostaddr_size) 323 { 324 struct in_addr addr; 325 326#if defined(HAVE_INET_PTON) 327 if (inet_pton(AF_INET, hostname, &addr) == 1) 328#else 329 if (inet_aton(hostname, &addr) != 0) 330#endif 331 { 332 /* it is already IP address string */ 333 if(strlen(hostname) < hostaddr_size) 334 { 335 strncpy(hostaddr, hostname, hostaddr_size-1); 336 hostaddr[hostaddr_size-1] = '\0'; 337 338 if (addrs != NULL && is_iface_address (addrs, &addr) > 0) 339 return 1; 340 else 341 return 0; 342 } 343 } 344 else 345 { 346 struct hostent *hp; 347 if ((hp = gethostbyname(hostname)) != NULL && hp->h_addr != NULL) 348 { 349 struct in_addr *aptr = (struct in_addr *)hp->h_addr; 350 int mret = 0; 351 352 if (addrs != NULL) 353 { 354 char **h; 355 for (h=hp->h_addr_list; *h; h++) 356 { 357 struct in_addr *haddr = (struct in_addr *)*h; 358 if (is_iface_address (addrs, haddr) > 0) 359 { 360 aptr = haddr; 361 mret = 1; 362 } 363 } 364 } 365 366#if defined(HAVE_INET_NTOP) 367 if (hostaddr_size >= INET_ADDRSTRLEN && 368 inet_ntop(AF_INET, aptr, hostaddr, hostaddr_size) != NULL) 369 { 370 return mret; 371 } 372#else 373 char *astr = inet_ntoa(*aptr); 374 size_t alen = strlen(astr); 375 if (astr && alen > 0 && alen < hostaddr_size) 376 { 377 strncpy(hostaddr, astr, hostaddr_size-1); 378 hostaddr[hostaddr_size-1] = '\0'; 379 return mret; 380 } 381#endif 382 } 383 } 384 } 385 return -1; 386} 387#endif /* HAVE_IFADDRS_H */ 388 389static void 390ldap_parse_class (struct ldap_config_stack *item, struct parse *cfile) 391{ 392 struct berval **tempbv; 393 394 if ((tempbv = ldap_get_values_len (ld, item->ldent, "cn")) == NULL || 395 tempbv[0] == NULL) 396 { 397 if (tempbv != NULL) 398 ldap_value_free_len (tempbv); 399 400 return; 401 } 402 403 x_parser_strcat (cfile, "class \""); 404 x_parser_strcat (cfile, tempbv[0]->bv_val); 405 x_parser_strcat (cfile, "\" {\n"); 406 407 item->close_brace = 1; 408 ldap_value_free_len (tempbv); 409} 410 411static int 412is_hex_string(const char *str) 413{ 414 int colon = 1; 415 int xdigit = 0; 416 size_t i; 417 418 if (!str) 419 return 0; 420 421 if (*str == '-') 422 str++; 423 424 for (i=0; str[i]; ++i) 425 { 426 if (str[i] == ':') 427 { 428 xdigit = 0; 429 if(++colon > 1) 430 return 0; 431 } 432 else if(isxdigit((unsigned char)str[i])) 433 { 434 colon = 0; 435 if (++xdigit > 2) 436 return 0; 437 } 438 else 439 return 0; 440 } 441 return i > 0 && !colon; 442} 443 444static void 445ldap_parse_subclass (struct ldap_config_stack *item, struct parse *cfile) 446{ 447 struct berval **tempbv, **classdata; 448 char *tmp; 449 450 if ((tempbv = ldap_get_values_len (ld, item->ldent, "cn")) == NULL || 451 tempbv[0] == NULL) 452 { 453 if (tempbv != NULL) 454 ldap_value_free_len (tempbv); 455 456 return; 457 } 458 459 if ((classdata = ldap_get_values_len (ld, item->ldent, 460 "dhcpClassData")) == NULL || 461 classdata[0] == NULL) 462 { 463 if (classdata != NULL) 464 ldap_value_free_len (classdata); 465 ldap_value_free_len (tempbv); 466 467 return; 468 } 469 470 x_parser_strcat (cfile, "subclass \""); 471 x_parser_strcat (cfile, classdata[0]->bv_val); 472 if (is_hex_string(tempbv[0]->bv_val)) 473 { 474 x_parser_strcat (cfile, "\" "); 475 x_parser_strcat (cfile, tempbv[0]->bv_val); 476 x_parser_strcat (cfile, " {\n"); 477 } 478 else 479 { 480 tmp = quotify_string(tempbv[0]->bv_val, MDL); 481 x_parser_strcat (cfile, "\" \""); 482 x_parser_strcat (cfile, tmp); 483 x_parser_strcat (cfile, "\" {\n"); 484 dfree(tmp, MDL); 485 } 486 487 item->close_brace = 1; 488 ldap_value_free_len (tempbv); 489 ldap_value_free_len (classdata); 490} 491 492 493static void 494ldap_parse_host (struct ldap_config_stack *item, struct parse *cfile) 495{ 496 struct berval **tempbv, **hwaddr; 497 498 if ((tempbv = ldap_get_values_len (ld, item->ldent, "cn")) == NULL || 499 tempbv[0] == NULL) 500 { 501 if (tempbv != NULL) 502 ldap_value_free_len (tempbv); 503 504 return; 505 } 506 507 hwaddr = ldap_get_values_len (ld, item->ldent, "dhcpHWAddress"); 508 509 x_parser_strcat (cfile, "host "); 510 x_parser_strcat (cfile, tempbv[0]->bv_val); 511 x_parser_strcat (cfile, " {\n"); 512 513 if (hwaddr != NULL) 514 { 515 if (hwaddr[0] != NULL) 516 { 517 x_parser_strcat (cfile, "hardware "); 518 x_parser_strcat (cfile, hwaddr[0]->bv_val); 519 x_parser_strcat (cfile, ";\n"); 520 } 521 ldap_value_free_len (hwaddr); 522 } 523 524 item->close_brace = 1; 525 ldap_value_free_len (tempbv); 526} 527 528 529static void 530ldap_parse_shared_network (struct ldap_config_stack *item, struct parse *cfile) 531{ 532 struct berval **tempbv; 533 534 if ((tempbv = ldap_get_values_len (ld, item->ldent, "cn")) == NULL || 535 tempbv[0] == NULL) 536 { 537 if (tempbv != NULL) 538 ldap_value_free_len (tempbv); 539 540 return; 541 } 542 543 x_parser_strcat (cfile, "shared-network \""); 544 x_parser_strcat (cfile, tempbv[0]->bv_val); 545 x_parser_strcat (cfile, "\" {\n"); 546 547 item->close_brace = 1; 548 ldap_value_free_len (tempbv); 549} 550 551 552static void 553parse_netmask (int netmask, char *netmaskbuf) 554{ 555 unsigned long nm; 556 int i; 557 558 nm = 0; 559 for (i=1; i <= netmask; i++) 560 { 561 nm |= 1 << (32 - i); 562 } 563 564 sprintf (netmaskbuf, "%d.%d.%d.%d", (int) (nm >> 24) & 0xff, 565 (int) (nm >> 16) & 0xff, 566 (int) (nm >> 8) & 0xff, 567 (int) nm & 0xff); 568} 569 570 571static void 572ldap_parse_subnet (struct ldap_config_stack *item, struct parse *cfile) 573{ 574 struct berval **tempbv, **netmaskstr; 575 char netmaskbuf[sizeof("255.255.255.255")]; 576 int i; 577 578 if ((tempbv = ldap_get_values_len (ld, item->ldent, "cn")) == NULL || 579 tempbv[0] == NULL) 580 { 581 if (tempbv != NULL) 582 ldap_value_free_len (tempbv); 583 584 return; 585 } 586 587 if ((netmaskstr = ldap_get_values_len (ld, item->ldent, 588 "dhcpNetmask")) == NULL || 589 netmaskstr[0] == NULL) 590 { 591 if (netmaskstr != NULL) 592 ldap_value_free_len (netmaskstr); 593 ldap_value_free_len (tempbv); 594 595 return; 596 } 597 598 x_parser_strcat (cfile, "subnet "); 599 x_parser_strcat (cfile, tempbv[0]->bv_val); 600 601 x_parser_strcat (cfile, " netmask "); 602 parse_netmask (strtol (netmaskstr[0]->bv_val, NULL, 10), netmaskbuf); 603 x_parser_strcat (cfile, netmaskbuf); 604 605 x_parser_strcat (cfile, " {\n"); 606 607 ldap_value_free_len (tempbv); 608 ldap_value_free_len (netmaskstr); 609 610 if ((tempbv = ldap_get_values_len (ld, item->ldent, "dhcpRange")) != NULL) 611 { 612 for (i=0; tempbv[i] != NULL; i++) 613 { 614 x_parser_strcat (cfile, "range"); 615 x_parser_strcat (cfile, " "); 616 x_parser_strcat (cfile, tempbv[i]->bv_val); 617 x_parser_strcat (cfile, ";\n"); 618 } 619 ldap_value_free_len (tempbv); 620 } 621 622 item->close_brace = 1; 623} 624 625static void 626ldap_parse_subnet6 (struct ldap_config_stack *item, struct parse *cfile) 627{ 628 struct berval **tempbv; 629 int i; 630 631 if ((tempbv = ldap_get_values_len (ld, item->ldent, "cn")) == NULL || 632 tempbv[0] == NULL) 633 { 634 if (tempbv != NULL) 635 ldap_value_free_len (tempbv); 636 637 return; 638 } 639 640 x_parser_strcat (cfile, "subnet6 "); 641 x_parser_strcat (cfile, tempbv[0]->bv_val); 642 643 x_parser_strcat (cfile, " {\n"); 644 645 ldap_value_free_len (tempbv); 646 647 if ((tempbv = ldap_get_values_len (ld, item->ldent, "dhcpRange6")) != NULL) 648 { 649 for (i=0; tempbv[i] != NULL; i++) 650 { 651 x_parser_strcat (cfile, "range6"); 652 x_parser_strcat (cfile, " "); 653 x_parser_strcat (cfile, tempbv[i]->bv_val); 654 x_parser_strcat (cfile, ";\n"); 655 } 656 ldap_value_free_len (tempbv); 657 } 658 659 if ((tempbv = ldap_get_values_len (ld, item->ldent, "dhcpPermitList")) != NULL) 660 { 661 for (i=0; tempbv[i] != NULL; i++) 662 { 663 x_parser_strcat (cfile, tempbv[i]->bv_val); 664 x_parser_strcat (cfile, ";\n"); 665 } 666 ldap_value_free_len (tempbv); 667 } 668 669 item->close_brace = 1; 670} 671 672static void 673ldap_parse_pool (struct ldap_config_stack *item, struct parse *cfile) 674{ 675 struct berval **tempbv; 676 int i; 677 678 x_parser_strcat (cfile, "pool {\n"); 679 680 if ((tempbv = ldap_get_values_len (ld, item->ldent, "dhcpRange")) != NULL) 681 { 682 x_parser_strcat (cfile, "range"); 683 for (i=0; tempbv[i] != NULL; i++) 684 { 685 x_parser_strcat (cfile, " "); 686 x_parser_strcat (cfile, tempbv[i]->bv_val); 687 } 688 x_parser_strcat (cfile, ";\n"); 689 ldap_value_free_len (tempbv); 690 } 691 692 if ((tempbv = ldap_get_values_len (ld, item->ldent, "dhcpPermitList")) != NULL) 693 { 694 for (i=0; tempbv[i] != NULL; i++) 695 { 696 x_parser_strcat (cfile, tempbv[i]->bv_val); 697 x_parser_strcat (cfile, ";\n"); 698 } 699 ldap_value_free_len (tempbv); 700 } 701 702 item->close_brace = 1; 703} 704 705static void 706ldap_parse_pool6 (struct ldap_config_stack *item, struct parse *cfile) 707{ 708 struct berval **tempbv; 709 int i; 710 711 x_parser_strcat (cfile, "pool6 {\n"); 712 713 if ((tempbv = ldap_get_values_len (ld, item->ldent, "dhcpRange6")) != NULL) 714 { 715 x_parser_strcat (cfile, "range6"); 716 for (i=0; tempbv[i] != NULL; i++) 717 { 718 x_parser_strcat (cfile, " "); 719 x_parser_strcat (cfile, tempbv[i]->bv_val); 720 } 721 x_parser_strcat (cfile, ";\n"); 722 ldap_value_free_len (tempbv); 723 } 724 725 if ((tempbv = ldap_get_values_len (ld, item->ldent, "dhcpPermitList")) != NULL) 726 { 727 for (i=0; tempbv[i] != NULL; i++) 728 { 729 x_parser_strcat(cfile, tempbv[i]->bv_val); 730 x_parser_strcat (cfile, ";\n"); 731 } 732 ldap_value_free_len (tempbv); 733 } 734 735 item->close_brace = 1; 736} 737 738static void 739ldap_parse_group (struct ldap_config_stack *item, struct parse *cfile) 740{ 741 x_parser_strcat (cfile, "group {\n"); 742 item->close_brace = 1; 743} 744 745 746static void 747ldap_parse_key (struct ldap_config_stack *item, struct parse *cfile) 748{ 749 struct berval **tempbv; 750 751 if ((tempbv = ldap_get_values_len (ld, item->ldent, "cn")) != NULL) 752 { 753 x_parser_strcat (cfile, "key "); 754 x_parser_strcat (cfile, tempbv[0]->bv_val); 755 x_parser_strcat (cfile, " {\n"); 756 ldap_value_free_len (tempbv); 757 } 758 759 if ((tempbv = ldap_get_values_len (ld, item->ldent, "dhcpKeyAlgorithm")) != NULL) 760 { 761 x_parser_strcat (cfile, "algorithm "); 762 x_parser_strcat (cfile, tempbv[0]->bv_val); 763 x_parser_strcat (cfile, ";\n"); 764 ldap_value_free_len (tempbv); 765 } 766 767 if ((tempbv = ldap_get_values_len (ld, item->ldent, "dhcpKeySecret")) != NULL) 768 { 769 x_parser_strcat (cfile, "secret "); 770 x_parser_strcat (cfile, tempbv[0]->bv_val); 771 x_parser_strcat (cfile, ";\n"); 772 ldap_value_free_len (tempbv); 773 } 774 775 item->close_brace = 1; 776} 777 778 779static void 780ldap_parse_zone (struct ldap_config_stack *item, struct parse *cfile) 781{ 782 char *cnFindStart, *cnFindEnd; 783 struct berval **tempbv; 784 char *keyCn; 785 size_t len; 786 787 if ((tempbv = ldap_get_values_len (ld, item->ldent, "cn")) != NULL) 788 { 789 x_parser_strcat (cfile, "zone "); 790 x_parser_strcat (cfile, tempbv[0]->bv_val); 791 x_parser_strcat (cfile, " {\n"); 792 ldap_value_free_len (tempbv); 793 } 794 795 if ((tempbv = ldap_get_values_len (ld, item->ldent, "dhcpDnsZoneServer")) != NULL) 796 { 797 x_parser_strcat (cfile, "primary "); 798 x_parser_strcat (cfile, tempbv[0]->bv_val); 799 800 x_parser_strcat (cfile, ";\n"); 801 ldap_value_free_len (tempbv); 802 } 803 804 if ((tempbv = ldap_get_values_len (ld, item->ldent, "dhcpKeyDN")) != NULL) 805 { 806 cnFindStart = strchr(tempbv[0]->bv_val,'='); 807 if (cnFindStart != NULL) 808 cnFindEnd = strchr(++cnFindStart,','); 809 else 810 cnFindEnd = NULL; 811 812 if (cnFindEnd != NULL && cnFindEnd > cnFindStart) 813 { 814 len = cnFindEnd - cnFindStart; 815 keyCn = dmalloc (len + 1, MDL); 816 } 817 else 818 { 819 len = 0; 820 keyCn = NULL; 821 } 822 823 if (keyCn != NULL) 824 { 825 strncpy (keyCn, cnFindStart, len); 826 keyCn[len] = '\0'; 827 828 x_parser_strcat (cfile, "key "); 829 x_parser_strcat (cfile, keyCn); 830 x_parser_strcat (cfile, ";\n"); 831 832 dfree (keyCn, MDL); 833 } 834 835 ldap_value_free_len (tempbv); 836 } 837 838 item->close_brace = 1; 839} 840 841#if defined(HAVE_IFADDRS_H) 842static void 843ldap_parse_failover (struct ldap_config_stack *item, struct parse *cfile) 844{ 845 struct berval **tempbv, **peername; 846 struct ifaddrs *addrs = NULL; 847 char srvaddr[2][64] = {"\0", "\0"}; 848 int primary, split = 0, match; 849 850 if ((peername = ldap_get_values_len (ld, item->ldent, "cn")) == NULL || 851 peername[0] == NULL) 852 { 853 if (peername != NULL) 854 ldap_value_free_len (peername); 855 856 // ldap with disabled schema checks? fail to avoid syntax error. 857 log_error("Unable to find mandatory failover peering name attribute"); 858 return; 859 } 860 861 /* Get all interface addresses */ 862 getifaddrs(&addrs); 863 864 /* 865 ** when dhcpFailOverPrimaryServer or dhcpFailOverSecondaryServer 866 ** matches one of our IP address, the following valiables are set: 867 ** - primary is 1 when we are primary or 0 when we are secondary 868 ** - srvaddr[0] contains ip address of the primary 869 ** - srvaddr[1] contains ip address of the secondary 870 */ 871 primary = -1; 872 if ((tempbv = ldap_get_values_len (ld, item->ldent, "dhcpFailOverPrimaryServer")) != NULL && 873 tempbv[0] != NULL) 874 { 875 match = get_host_address (tempbv[0]->bv_val, srvaddr[0], sizeof(srvaddr[0]), addrs); 876 if (match >= 0) 877 { 878 /* we are the primary */ 879 if (match > 0) 880 primary = 1; 881 } 882 else 883 { 884 log_info("Can't resolve address of the primary failover '%s' server %s", 885 peername[0]->bv_val, tempbv[0]->bv_val); 886 ldap_value_free_len (tempbv); 887 ldap_value_free_len (peername); 888 if (addrs) 889 freeifaddrs(addrs); 890 return; 891 } 892 } 893 if (tempbv != NULL) 894 ldap_value_free_len (tempbv); 895 896 if ((tempbv = ldap_get_values_len (ld, item->ldent, "dhcpFailOverSecondaryServer")) != NULL && 897 tempbv[0] != NULL) 898 { 899 match = get_host_address (tempbv[0]->bv_val, srvaddr[1], sizeof(srvaddr[1]), addrs); 900 if (match >= 0) 901 { 902 if (match > 0) 903 { 904 if (primary == 1) 905 { 906 log_info("Both, primary and secondary failover '%s' server" 907 " attributes match our local address", peername[0]->bv_val); 908 ldap_value_free_len (tempbv); 909 ldap_value_free_len (peername); 910 if (addrs) 911 freeifaddrs(addrs); 912 return; 913 } 914 915 /* we are the secondary */ 916 primary = 0; 917 } 918 } 919 else 920 { 921 log_info("Can't resolve address of the secondary failover '%s' server %s", 922 peername[0]->bv_val, tempbv[0]->bv_val); 923 ldap_value_free_len (tempbv); 924 ldap_value_free_len (peername); 925 if (addrs) 926 freeifaddrs(addrs); 927 return; 928 } 929 } 930 if (tempbv != NULL) 931 ldap_value_free_len (tempbv); 932 933 934 if (primary == -1 || *srvaddr[0] == '\0' || *srvaddr[1] == '\0') 935 { 936 log_error("Could not decide if the server type is primary" 937 " or secondary for failover peering '%s'.", peername[0]->bv_val); 938 ldap_value_free_len (peername); 939 if (addrs) 940 freeifaddrs(addrs); 941 return; 942 } 943 944 x_parser_strcat (cfile, "failover peer \""); 945 x_parser_strcat (cfile, peername[0]->bv_val); 946 x_parser_strcat (cfile, "\" {\n"); 947 948 if (primary) 949 x_parser_strcat (cfile, "primary;\n"); 950 else 951 x_parser_strcat (cfile, "secondary;\n"); 952 953 x_parser_strcat (cfile, "address "); 954 if (primary) 955 x_parser_strcat (cfile, srvaddr[0]); 956 else 957 x_parser_strcat (cfile, srvaddr[1]); 958 x_parser_strcat (cfile, ";\n"); 959 960 x_parser_strcat (cfile, "peer address "); 961 if (primary) 962 x_parser_strcat (cfile, srvaddr[1]); 963 else 964 x_parser_strcat (cfile, srvaddr[0]); 965 x_parser_strcat (cfile, ";\n"); 966 967 if ((tempbv = ldap_get_values_len (ld, item->ldent, "dhcpFailOverPrimaryPort")) != NULL && 968 tempbv[0] != NULL) 969 { 970 if (primary) 971 x_parser_strcat (cfile, "port "); 972 else 973 x_parser_strcat (cfile, "peer port "); 974 x_parser_strcat (cfile, tempbv[0]->bv_val); 975 x_parser_strcat (cfile, ";\n"); 976 } 977 if (tempbv != NULL) 978 ldap_value_free_len (tempbv); 979 980 if ((tempbv = ldap_get_values_len (ld, item->ldent, "dhcpFailOverSecondaryPort")) != NULL && 981 tempbv[0] != NULL) 982 { 983 if (primary) 984 x_parser_strcat (cfile, "peer port "); 985 else 986 x_parser_strcat (cfile, "port "); 987 x_parser_strcat (cfile, tempbv[0]->bv_val); 988 x_parser_strcat (cfile, ";\n"); 989 } 990 if (tempbv != NULL) 991 ldap_value_free_len (tempbv); 992 993 if ((tempbv = ldap_get_values_len (ld, item->ldent, "dhcpFailOverResponseDelay")) != NULL && 994 tempbv[0] != NULL) 995 { 996 x_parser_strcat (cfile, "max-response-delay "); 997 x_parser_strcat (cfile, tempbv[0]->bv_val); 998 x_parser_strcat (cfile, ";\n"); 999 } 1000 if (tempbv != NULL) 1001 ldap_value_free_len (tempbv); 1002 1003 if ((tempbv = ldap_get_values_len (ld, item->ldent, "dhcpFailOverUnackedUpdates")) != NULL && 1004 tempbv[0] != NULL) 1005 { 1006 x_parser_strcat (cfile, "max-unacked-updates "); 1007 x_parser_strcat (cfile, tempbv[0]->bv_val); 1008 x_parser_strcat (cfile, ";\n"); 1009 } 1010 if (tempbv != NULL) 1011 ldap_value_free_len (tempbv); 1012 1013 if ((tempbv = ldap_get_values_len (ld, item->ldent, "dhcpFailOverLoadBalanceTime")) != NULL && 1014 tempbv[0] != NULL) 1015 { 1016 x_parser_strcat (cfile, "load balance max seconds "); 1017 x_parser_strcat (cfile, tempbv[0]->bv_val); 1018 x_parser_strcat (cfile, ";\n"); 1019 } 1020 if (tempbv != NULL) 1021 ldap_value_free_len (tempbv); 1022 1023 tempbv = NULL; 1024 if (primary && 1025 (tempbv = ldap_get_values_len (ld, item->ldent, "dhcpMaxClientLeadTime")) != NULL && 1026 tempbv[0] != NULL) 1027 { 1028 x_parser_strcat (cfile, "mclt "); 1029 x_parser_strcat (cfile, tempbv[0]->bv_val); 1030 x_parser_strcat (cfile, ";\n"); 1031 } 1032 if (tempbv != NULL) 1033 ldap_value_free_len (tempbv); 1034 1035 tempbv = NULL; 1036 if (primary && 1037 (tempbv = ldap_get_values_len (ld, item->ldent, "dhcpFailOverSplit")) != NULL && 1038 tempbv[0] != NULL) 1039 { 1040 x_parser_strcat (cfile, "split "); 1041 x_parser_strcat (cfile, tempbv[0]->bv_val); 1042 x_parser_strcat (cfile, ";\n"); 1043 split = 1; 1044 } 1045 if (tempbv != NULL) 1046 ldap_value_free_len (tempbv); 1047 1048 tempbv = NULL; 1049 if (primary && !split && 1050 (tempbv = ldap_get_values_len (ld, item->ldent, "dhcpFailOverHashBucketAssignment")) != NULL && 1051 tempbv[0] != NULL) 1052 { 1053 x_parser_strcat (cfile, "hba "); 1054 x_parser_strcat (cfile, tempbv[0]->bv_val); 1055 x_parser_strcat (cfile, ";\n"); 1056 } 1057 if (tempbv != NULL) 1058 ldap_value_free_len (tempbv); 1059 1060 item->close_brace = 1; 1061} 1062#endif /* HAVE_IFADDRS_H */ 1063 1064static void 1065add_to_config_stack (LDAPMessage * res, LDAPMessage * ent) 1066{ 1067 struct ldap_config_stack *ns; 1068 1069 ns = dmalloc (sizeof (*ns), MDL); 1070 if (!ns) { 1071 log_fatal ("no memory for add_to_config_stack()"); 1072 } 1073 1074 ns->res = res; 1075 ns->ldent = ent; 1076 ns->close_brace = 0; 1077 ns->processed = 0; 1078 ns->next = ldap_stack; 1079 ldap_stack = ns; 1080} 1081 1082static void 1083ldap_stop() 1084{ 1085 struct sigaction old, new; 1086 1087 if (ld == NULL) 1088 return; 1089 1090 /* 1091 ** ldap_unbind after a LDAP_SERVER_DOWN result 1092 ** causes a SIGPIPE and dhcpd gets terminated, 1093 ** since it doesn't handle it... 1094 */ 1095 1096 new.sa_flags = 0; 1097 new.sa_handler = SIG_IGN; 1098 sigemptyset (&new.sa_mask); 1099 sigaction (SIGPIPE, &new, &old); 1100 1101 ldap_unbind_ext_s (ld, NULL, NULL); 1102 ld = NULL; 1103 1104 sigaction (SIGPIPE, &old, &new); 1105} 1106 1107 1108static char * 1109_do_lookup_dhcp_string_option (struct option_state *options, int option_name) 1110{ 1111 struct option_cache *oc; 1112 struct data_string db; 1113 char *ret; 1114 1115 memset (&db, 0, sizeof (db)); 1116 oc = lookup_option (&server_universe, options, option_name); 1117 if (oc && 1118 evaluate_option_cache (&db, (struct packet*) NULL, 1119 (struct lease *) NULL, 1120 (struct client_state *) NULL, options, 1121 (struct option_state *) NULL, 1122 &global_scope, oc, MDL) && 1123 db.data != NULL && *db.data != '\0') 1124 1125 { 1126 ret = dmalloc (db.len + 1, MDL); 1127 if (ret == NULL) 1128 log_fatal ("no memory for ldap option %d value", option_name); 1129 1130 memcpy (ret, db.data, db.len); 1131 ret[db.len] = 0; 1132 data_string_forget (&db, MDL); 1133 } 1134 else 1135 ret = NULL; 1136 1137 return (ret); 1138} 1139 1140 1141static int 1142_do_lookup_dhcp_int_option (struct option_state *options, int option_name) 1143{ 1144 struct option_cache *oc; 1145 struct data_string db; 1146 int ret = 0; 1147 1148 memset (&db, 0, sizeof (db)); 1149 oc = lookup_option (&server_universe, options, option_name); 1150 if (oc && 1151 evaluate_option_cache (&db, (struct packet*) NULL, 1152 (struct lease *) NULL, 1153 (struct client_state *) NULL, options, 1154 (struct option_state *) NULL, 1155 &global_scope, oc, MDL) && 1156 db.data != NULL) 1157 { 1158 if (db.len == 4) { 1159 ret = getULong(db.data); 1160 } 1161 1162 data_string_forget (&db, MDL); 1163 } 1164 1165 return (ret); 1166} 1167 1168 1169static int 1170_do_lookup_dhcp_enum_option (struct option_state *options, int option_name) 1171{ 1172 struct option_cache *oc; 1173 struct data_string db; 1174 int ret = -1; 1175 1176 memset (&db, 0, sizeof (db)); 1177 oc = lookup_option (&server_universe, options, option_name); 1178 if (oc && 1179 evaluate_option_cache (&db, (struct packet*) NULL, 1180 (struct lease *) NULL, 1181 (struct client_state *) NULL, options, 1182 (struct option_state *) NULL, 1183 &global_scope, oc, MDL) && 1184 db.data != NULL && *db.data != '\0') 1185 { 1186 if (db.len == 1) 1187 ret = db.data [0]; 1188 else 1189 log_fatal ("invalid option name %d", option_name); 1190 1191 data_string_forget (&db, MDL); 1192 } 1193 else 1194 ret = 0; 1195 1196 return (ret); 1197} 1198 1199int 1200ldap_rebind_cb (LDAP *ld, LDAP_CONST char *url, ber_tag_t request, ber_int_t msgid, void *parms) 1201{ 1202 int ret; 1203 LDAPURLDesc *ldapurl = NULL; 1204 char *who = NULL; 1205 struct berval creds; 1206 1207 log_info("LDAP rebind to '%s'", url); 1208 if ((ret = ldap_url_parse(url, &ldapurl)) != LDAP_SUCCESS) 1209 { 1210 log_error ("Error: Can not parse ldap rebind url '%s': %s", 1211 url, ldap_err2string(ret)); 1212 return ret; 1213 } 1214 1215 1216#if defined (LDAP_USE_SSL) 1217 if (strcasecmp(ldapurl->lud_scheme, "ldaps") == 0) 1218 { 1219 int opt = LDAP_OPT_X_TLS_HARD; 1220 if ((ret = ldap_set_option (ld, LDAP_OPT_X_TLS, &opt)) != LDAP_SUCCESS) 1221 { 1222 log_error ("Error: Cannot init LDAPS session to %s:%d: %s", 1223 ldapurl->lud_host, ldapurl->lud_port, ldap_err2string (ret)); 1224 ldap_free_urldesc(ldapurl); 1225 return ret; 1226 } 1227 else 1228 { 1229 log_info ("LDAPS session successfully enabled to %s", ldap_server); 1230 } 1231 } 1232 else 1233 if (strcasecmp(ldapurl->lud_scheme, "ldap") == 0 && 1234 ldap_use_ssl != LDAP_SSL_OFF) 1235 { 1236 if ((ret = ldap_start_tls_s (ld, NULL, NULL)) != LDAP_SUCCESS) 1237 { 1238 log_error ("Error: Cannot start TLS session to %s:%d: %s", 1239 ldapurl->lud_host, ldapurl->lud_port, ldap_err2string (ret)); 1240 ldap_free_urldesc(ldapurl); 1241 return ret; 1242 } 1243 else 1244 { 1245 log_info ("TLS session successfully started to %s:%d", 1246 ldapurl->lud_host, ldapurl->lud_port); 1247 } 1248 } 1249#endif 1250 1251#if defined(LDAP_USE_GSSAPI) 1252 if (ldap_gssapi_principal != NULL) { 1253 krb5_get_tgt(ldap_gssapi_principal, ldap_gssapi_keytab); 1254 if ((ret = ldap_sasl_interactive_bind_s(ld, NULL, ldap_sasl_inst->sasl_mech, 1255 NULL, NULL, LDAP_SASL_AUTOMATIC, 1256 _ldap_sasl_interact, ldap_sasl_inst) 1257 ) != LDAP_SUCCESS) 1258 { 1259 log_error ("Error: Cannot SASL bind to ldap server %s:%d: %s", 1260 ldap_server, ldap_port, ldap_err2string (ret)); 1261 char *msg=NULL; 1262 ldap_get_option( ld, LDAP_OPT_DIAGNOSTIC_MESSAGE, (void*)&msg); 1263 log_error ("\tAdditional info: %s", msg); 1264 ldap_memfree(msg); 1265 ldap_stop(); 1266 } 1267 1268 ldap_free_urldesc(ldapurl); 1269 return ret; 1270 } 1271#endif 1272 1273 if (ldap_username != NULL && *ldap_username != '\0' && ldap_password != NULL) 1274 { 1275 who = ldap_username; 1276 creds.bv_val = strdup(ldap_password); 1277 if (creds.bv_val == NULL) 1278 log_fatal ("Error: Unable to allocate memory to duplicate ldap_password"); 1279 1280 creds.bv_len = strlen(ldap_password); 1281 1282 if ((ret = ldap_sasl_bind_s (ld, who, LDAP_SASL_SIMPLE, &creds, 1283 NULL, NULL, NULL)) != LDAP_SUCCESS) 1284 { 1285 log_error ("Error: Cannot login into ldap server %s:%d: %s", 1286 ldapurl->lud_host, ldapurl->lud_port, ldap_err2string (ret)); 1287 } 1288 1289 if (creds.bv_val) 1290 free(creds.bv_val); 1291 } 1292 1293 ldap_free_urldesc(ldapurl); 1294 return ret; 1295} 1296 1297static int 1298_do_ldap_retry(int ret, const char *server, int port) 1299{ 1300 static int inform = 1; 1301 1302 if (ldap_enable_retry > 0 && ret == LDAP_SERVER_DOWN && ldap_init_retry > 0) 1303 { 1304 if (inform || (ldap_init_retry % 10) == 0) 1305 { 1306 inform = 0; 1307 log_info ("Can't contact LDAP server %s:%d: retrying for %d sec", 1308 server, port, ldap_init_retry); 1309 } 1310 sleep(1); 1311 return ldap_init_retry--; 1312 } 1313 return 0; 1314} 1315 1316static struct berval * 1317_do_ldap_str2esc_filter_bv(const char *str, ber_len_t len, struct berval *bv_o) 1318{ 1319 struct berval bv_i; 1320 1321 if (!str || !bv_o || (ber_str2bv(str, len, 0, &bv_i) == NULL) || 1322 (ldap_bv2escaped_filter_value(&bv_i, bv_o) != 0)) 1323 return NULL; 1324 return bv_o; 1325} 1326 1327static void 1328ldap_start (void) 1329{ 1330 struct option_state *options; 1331 int ret, version; 1332 char *uri = NULL; 1333 struct berval creds; 1334#if defined(LDAP_USE_GSSAPI) 1335 char *gssapi_realm = NULL; 1336 char *gssapi_user = NULL; 1337 char *running = NULL; 1338 const char *gssapi_delim = "@"; 1339#endif 1340 1341 if (ld != NULL) 1342 return; 1343 1344 if (ldap_server == NULL) 1345 { 1346 options = NULL; 1347 option_state_allocate (&options, MDL); 1348 1349 execute_statements_in_scope (NULL, NULL, NULL, NULL, NULL, 1350 options, &global_scope, root_group, 1351 NULL, NULL); 1352 1353 ldap_server = _do_lookup_dhcp_string_option (options, SV_LDAP_SERVER); 1354 ldap_dhcp_server_cn = _do_lookup_dhcp_string_option (options, 1355 SV_LDAP_DHCP_SERVER_CN); 1356 ldap_port = _do_lookup_dhcp_int_option (options, SV_LDAP_PORT); 1357 ldap_base_dn = _do_lookup_dhcp_string_option (options, SV_LDAP_BASE_DN); 1358 ldap_method = _do_lookup_dhcp_enum_option (options, SV_LDAP_METHOD); 1359 ldap_debug_file = _do_lookup_dhcp_string_option (options, 1360 SV_LDAP_DEBUG_FILE); 1361 ldap_referrals = _do_lookup_dhcp_enum_option (options, SV_LDAP_REFERRALS); 1362 ldap_init_retry = _do_lookup_dhcp_int_option (options, SV_LDAP_INIT_RETRY); 1363 1364#if defined (LDAP_USE_SSL) 1365 ldap_use_ssl = _do_lookup_dhcp_enum_option (options, SV_LDAP_SSL); 1366 if( ldap_use_ssl != LDAP_SSL_OFF) 1367 { 1368 ldap_tls_reqcert = _do_lookup_dhcp_enum_option (options, SV_LDAP_TLS_REQCERT); 1369 ldap_tls_ca_file = _do_lookup_dhcp_string_option (options, SV_LDAP_TLS_CA_FILE); 1370 ldap_tls_ca_dir = _do_lookup_dhcp_string_option (options, SV_LDAP_TLS_CA_DIR); 1371 ldap_tls_cert = _do_lookup_dhcp_string_option (options, SV_LDAP_TLS_CERT); 1372 ldap_tls_key = _do_lookup_dhcp_string_option (options, SV_LDAP_TLS_KEY); 1373 ldap_tls_crlcheck = _do_lookup_dhcp_enum_option (options, SV_LDAP_TLS_CRLCHECK); 1374 ldap_tls_ciphers = _do_lookup_dhcp_string_option (options, SV_LDAP_TLS_CIPHERS); 1375 ldap_tls_randfile = _do_lookup_dhcp_string_option (options, SV_LDAP_TLS_RANDFILE); 1376 } 1377#endif 1378 1379#if defined (LDAP_USE_GSSAPI) 1380 ldap_gssapi_principal = _do_lookup_dhcp_string_option (options, 1381 SV_LDAP_GSSAPI_PRINCIPAL); 1382 1383 if (ldap_gssapi_principal == NULL) { 1384 log_info("ldap-gssapi-principal is not set," 1385 "GSSAPI Authentication for LDAP will not be used"); 1386 } else { 1387 ldap_gssapi_keytab = _do_lookup_dhcp_string_option (options, 1388 SV_LDAP_GSSAPI_KEYTAB); 1389 if (ldap_gssapi_keytab == NULL) { 1390 log_fatal("ldap-gssapi-keytab must be specified"); 1391 } 1392 1393 running = strdup(ldap_gssapi_principal); 1394 if (running == NULL) 1395 log_fatal("Could not allocate memory to duplicate gssapi principal"); 1396 1397 gssapi_user = strtok(running, gssapi_delim); 1398 if (!gssapi_user || strlen(gssapi_user) == 0) { 1399 log_fatal ("GSSAPI principal must specify user: user@realm"); 1400 } 1401 1402 gssapi_realm = strtok(NULL, gssapi_delim); 1403 if (!gssapi_realm || strlen(gssapi_realm) == 0) { 1404 log_fatal ("GSSAPI principal must specify realm: user@realm"); 1405 } 1406 1407 ldap_sasl_inst = malloc(sizeof(struct ldap_sasl_instance)); 1408 if (ldap_sasl_inst == NULL) 1409 log_fatal("Could not allocate memory for sasl instance! Can not run!"); 1410 1411 ldap_sasl_inst->sasl_mech = ber_strdup("GSSAPI"); 1412 if (ldap_sasl_inst->sasl_mech == NULL) 1413 log_fatal("Could not allocate memory to duplicate gssapi mechanism"); 1414 1415 ldap_sasl_inst->sasl_realm = ber_strdup(gssapi_realm); 1416 if (ldap_sasl_inst->sasl_realm == NULL) 1417 log_fatal("Could not allocate memory to duplicate gssapi realm"); 1418 1419 ldap_sasl_inst->sasl_authz_id = ber_strdup(gssapi_user); 1420 if (ldap_sasl_inst->sasl_authz_id == NULL) 1421 log_fatal("Could not allocate memory to duplicate gssapi user"); 1422 1423 ldap_sasl_inst->sasl_authc_id = NULL; 1424 ldap_sasl_inst->sasl_password = NULL; //"" before 1425 free(running); 1426 } 1427#endif 1428 1429#if defined (LDAP_CASA_AUTH) 1430 if (!load_uname_pwd_from_miCASA(&ldap_username,&ldap_password)) 1431 { 1432#if defined (DEBUG_LDAP) 1433 log_info ("Authentication credential taken from file"); 1434#endif 1435#endif 1436 1437 ldap_username = _do_lookup_dhcp_string_option (options, SV_LDAP_USERNAME); 1438 ldap_password = _do_lookup_dhcp_string_option (options, SV_LDAP_PASSWORD); 1439 1440#if defined (LDAP_CASA_AUTH) 1441 } 1442#endif 1443 1444 option_state_dereference (&options, MDL); 1445 } 1446 1447 if (ldap_server == NULL || ldap_base_dn == NULL) 1448 { 1449 log_info ("Not searching LDAP since ldap-server, ldap-port and ldap-base-dn were not specified in the config file"); 1450 ldap_method = LDAP_METHOD_STATIC; 1451 return; 1452 } 1453 1454 if (ldap_debug_file != NULL && ldap_debug_fd == -1) 1455 { 1456 if ((ldap_debug_fd = open (ldap_debug_file, O_CREAT | O_TRUNC | O_WRONLY, 1457 S_IRUSR | S_IWUSR)) < 0) 1458 log_error ("Error opening debug LDAP log file %s: %s", ldap_debug_file, 1459 strerror (errno)); 1460 } 1461 1462#if defined (DEBUG_LDAP) 1463 log_info ("Connecting to LDAP server %s:%d", ldap_server, ldap_port); 1464#endif 1465 1466#if defined (LDAP_USE_SSL) 1467 if (ldap_use_ssl == -1) 1468 { 1469 /* 1470 ** There was no "ldap-ssl" option in dhcpd.conf (also not "off"). 1471 ** Let's try, if we can use an anonymous TLS session without to 1472 ** verify the server certificate -- if not continue without TLS. 1473 */ 1474 int opt = LDAP_OPT_X_TLS_ALLOW; 1475 if ((ret = ldap_set_option (NULL, LDAP_OPT_X_TLS_REQUIRE_CERT, 1476 &opt)) != LDAP_SUCCESS) 1477 { 1478 log_error ("Warning: Cannot set LDAP TLS require cert option to 'allow': %s", 1479 ldap_err2string (ret)); 1480 } 1481 } 1482 1483 if (ldap_use_ssl != LDAP_SSL_OFF) 1484 { 1485 if (ldap_tls_reqcert != -1) 1486 { 1487 if ((ret = ldap_set_option (NULL, LDAP_OPT_X_TLS_REQUIRE_CERT, 1488 &ldap_tls_reqcert)) != LDAP_SUCCESS) 1489 { 1490 log_error ("Cannot set LDAP TLS require cert option: %s", 1491 ldap_err2string (ret)); 1492 } 1493 } 1494 1495 if( ldap_tls_ca_file != NULL) 1496 { 1497 if ((ret = ldap_set_option (NULL, LDAP_OPT_X_TLS_CACERTFILE, 1498 ldap_tls_ca_file)) != LDAP_SUCCESS) 1499 { 1500 log_error ("Cannot set LDAP TLS CA certificate file %s: %s", 1501 ldap_tls_ca_file, ldap_err2string (ret)); 1502 } 1503 } 1504 if( ldap_tls_ca_dir != NULL) 1505 { 1506 if ((ret = ldap_set_option (NULL, LDAP_OPT_X_TLS_CACERTDIR, 1507 ldap_tls_ca_dir)) != LDAP_SUCCESS) 1508 { 1509 log_error ("Cannot set LDAP TLS CA certificate dir %s: %s", 1510 ldap_tls_ca_dir, ldap_err2string (ret)); 1511 } 1512 } 1513 if( ldap_tls_cert != NULL) 1514 { 1515 if ((ret = ldap_set_option (NULL, LDAP_OPT_X_TLS_CERTFILE, 1516 ldap_tls_cert)) != LDAP_SUCCESS) 1517 { 1518 log_error ("Cannot set LDAP TLS client certificate file %s: %s", 1519 ldap_tls_cert, ldap_err2string (ret)); 1520 } 1521 } 1522 if( ldap_tls_key != NULL) 1523 { 1524 if ((ret = ldap_set_option (NULL, LDAP_OPT_X_TLS_KEYFILE, 1525 ldap_tls_key)) != LDAP_SUCCESS) 1526 { 1527 log_error ("Cannot set LDAP TLS certificate key file %s: %s", 1528 ldap_tls_key, ldap_err2string (ret)); 1529 } 1530 } 1531 if( ldap_tls_crlcheck != -1) 1532 { 1533 int opt = ldap_tls_crlcheck; 1534 if ((ret = ldap_set_option (NULL, LDAP_OPT_X_TLS_CRLCHECK, 1535 &opt)) != LDAP_SUCCESS) 1536 { 1537 log_error ("Cannot set LDAP TLS crl check option: %s", 1538 ldap_err2string (ret)); 1539 } 1540 } 1541 if( ldap_tls_ciphers != NULL) 1542 { 1543 if ((ret = ldap_set_option (NULL, LDAP_OPT_X_TLS_CIPHER_SUITE, 1544 ldap_tls_ciphers)) != LDAP_SUCCESS) 1545 { 1546 log_error ("Cannot set LDAP TLS cipher suite %s: %s", 1547 ldap_tls_ciphers, ldap_err2string (ret)); 1548 } 1549 } 1550 if( ldap_tls_randfile != NULL) 1551 { 1552 if ((ret = ldap_set_option (NULL, LDAP_OPT_X_TLS_RANDOM_FILE, 1553 ldap_tls_randfile)) != LDAP_SUCCESS) 1554 { 1555 log_error ("Cannot set LDAP TLS random file %s: %s", 1556 ldap_tls_randfile, ldap_err2string (ret)); 1557 } 1558 } 1559 } 1560#endif 1561 1562 /* enough for 'ldap://+ + hostname + ':' + port number */ 1563 uri = malloc(strlen(ldap_server) + 16); 1564 if (uri == NULL) 1565 { 1566 log_error ("Cannot build ldap init URI %s:%d", ldap_server, ldap_port); 1567 return; 1568 } 1569 1570 sprintf(uri, "ldap://%s:%d", ldap_server, ldap_port); 1571 ldap_initialize(&ld, uri); 1572 1573 if (ld == NULL) 1574 { 1575 log_error ("Cannot init ldap session to %s:%d", ldap_server, ldap_port); 1576 return; 1577 } 1578 1579 free(uri); 1580 1581 version = LDAP_VERSION3; 1582 if ((ret = ldap_set_option (ld, LDAP_OPT_PROTOCOL_VERSION, &version)) != LDAP_OPT_SUCCESS) 1583 { 1584 log_error ("Cannot set LDAP version to %d: %s", version, 1585 ldap_err2string (ret)); 1586 } 1587 1588 if (ldap_referrals != -1) 1589 { 1590 if ((ret = ldap_set_option (ld, LDAP_OPT_REFERRALS, ldap_referrals ? 1591 LDAP_OPT_ON : LDAP_OPT_OFF)) != LDAP_OPT_SUCCESS) 1592 { 1593 log_error ("Cannot %s LDAP referrals option: %s", 1594 (ldap_referrals ? "enable" : "disable"), 1595 ldap_err2string (ret)); 1596 } 1597 } 1598 1599 if ((ret = ldap_set_rebind_proc(ld, ldap_rebind_cb, NULL)) != LDAP_SUCCESS) 1600 { 1601 log_error ("Warning: Cannot set ldap rebind procedure: %s", 1602 ldap_err2string (ret)); 1603 } 1604 1605#if defined (LDAP_USE_SSL) 1606 if (ldap_use_ssl == LDAP_SSL_LDAPS || 1607 (ldap_use_ssl == LDAP_SSL_ON && ldap_port == LDAPS_PORT)) 1608 { 1609 int opt = LDAP_OPT_X_TLS_HARD; 1610 if ((ret = ldap_set_option (ld, LDAP_OPT_X_TLS, &opt)) != LDAP_SUCCESS) 1611 { 1612 log_error ("Error: Cannot init LDAPS session to %s:%d: %s", 1613 ldap_server, ldap_port, ldap_err2string (ret)); 1614 ldap_stop(); 1615 return; 1616 } 1617 else 1618 { 1619 log_info ("LDAPS session successfully enabled to %s:%d", 1620 ldap_server, ldap_port); 1621 } 1622 } 1623 else if (ldap_use_ssl != LDAP_SSL_OFF) 1624 { 1625 do 1626 { 1627 ret = ldap_start_tls_s (ld, NULL, NULL); 1628 } 1629 while(_do_ldap_retry(ret, ldap_server, ldap_port) > 0); 1630 1631 if (ret != LDAP_SUCCESS) 1632 { 1633 log_error ("Error: Cannot start TLS session to %s:%d: %s", 1634 ldap_server, ldap_port, ldap_err2string (ret)); 1635 ldap_stop(); 1636 return; 1637 } 1638 else 1639 { 1640 log_info ("TLS session successfully started to %s:%d", 1641 ldap_server, ldap_port); 1642 } 1643 } 1644#endif 1645 1646#if defined(LDAP_USE_GSSAPI) 1647 if (ldap_gssapi_principal != NULL) { 1648 krb5_get_tgt(ldap_gssapi_principal, ldap_gssapi_keytab); 1649 if ((ret = ldap_sasl_interactive_bind_s(ld, NULL, ldap_sasl_inst->sasl_mech, 1650 NULL, NULL, LDAP_SASL_AUTOMATIC, 1651 _ldap_sasl_interact, ldap_sasl_inst) 1652 ) != LDAP_SUCCESS) 1653 { 1654 log_error ("Error: Cannot SASL bind to ldap server %s:%d: %s", 1655 ldap_server, ldap_port, ldap_err2string (ret)); 1656 char *msg=NULL; 1657 ldap_get_option( ld, LDAP_OPT_DIAGNOSTIC_MESSAGE, (void*)&msg); 1658 log_error ("\tAdditional info: %s", msg); 1659 ldap_memfree(msg); 1660 ldap_stop(); 1661 return; 1662 } 1663 } else 1664#endif 1665 1666 if (ldap_username != NULL && *ldap_username != '\0' && ldap_password != NULL) 1667 { 1668 creds.bv_val = strdup(ldap_password); 1669 if (creds.bv_val == NULL) 1670 log_fatal ("Error: Unable to allocate memory to duplicate ldap_password"); 1671 1672 creds.bv_len = strlen(ldap_password); 1673 1674 do 1675 { 1676 ret = ldap_sasl_bind_s (ld, ldap_username, LDAP_SASL_SIMPLE, 1677 &creds, NULL, NULL, NULL); 1678 } 1679 while(_do_ldap_retry(ret, ldap_server, ldap_port) > 0); 1680 free(creds.bv_val); 1681 1682 if (ret != LDAP_SUCCESS) 1683 { 1684 log_error ("Error: Cannot login into ldap server %s:%d: %s", 1685 ldap_server, ldap_port, ldap_err2string (ret)); 1686 ldap_stop(); 1687 return; 1688 } 1689 } 1690 1691#if defined (DEBUG_LDAP) 1692 log_info ("Successfully logged into LDAP server %s", ldap_server); 1693#endif 1694} 1695 1696 1697static void 1698parse_external_dns (LDAPMessage * ent) 1699{ 1700 char *search[] = {"dhcpOptionsDN", "dhcpSharedNetworkDN", "dhcpSubnetDN", 1701 "dhcpGroupDN", "dhcpHostDN", "dhcpClassesDN", 1702 "dhcpPoolDN", "dhcpZoneDN", "dhcpFailOverPeerDN", NULL}; 1703 1704 /* TODO: dhcpKeyDN can't be added. It is referenced in dhcpDnsZone to 1705 retrive the key name (cn). Adding keyDN will reflect adding a key 1706 declaration inside the zone configuration. 1707 1708 dhcpSubClassesDN cant be added. It is also similar to the above. 1709 Needs schema change. 1710 */ 1711 LDAPMessage * newres, * newent; 1712 struct berval **tempbv; 1713 int i, j, ret; 1714#if defined (DEBUG_LDAP) 1715 char *dn; 1716 1717 dn = ldap_get_dn (ld, ent); 1718 if (dn != NULL) 1719 { 1720 log_info ("Parsing external DNs for '%s'", dn); 1721 ldap_memfree (dn); 1722 } 1723#endif 1724 1725 if (ld == NULL) 1726 ldap_start (); 1727 if (ld == NULL) 1728 return; 1729 1730 for (i=0; search[i] != NULL; i++) 1731 { 1732 if ((tempbv = ldap_get_values_len (ld, ent, search[i])) == NULL) 1733 continue; 1734 1735 for (j=0; tempbv[j] != NULL; j++) 1736 { 1737 if (*tempbv[j]->bv_val == '\0') 1738 continue; 1739 1740 if ((ret = ldap_search_ext_s(ld, tempbv[j]->bv_val, LDAP_SCOPE_BASE, 1741 "objectClass=*", NULL, 0, NULL, 1742 NULL, NULL, 0, &newres)) != LDAP_SUCCESS) 1743 { 1744 ldap_value_free_len (tempbv); 1745 ldap_stop(); 1746 return; 1747 } 1748 1749#if defined (DEBUG_LDAP) 1750 log_info ("Adding contents of subtree '%s' to config stack from '%s' reference", tempbv[j]->bv_val, search[i]); 1751#endif 1752 for (newent = ldap_first_entry (ld, newres); 1753 newent != NULL; 1754 newent = ldap_next_entry (ld, newent)) 1755 { 1756#if defined (DEBUG_LDAP) 1757 dn = ldap_get_dn (ld, newent); 1758 if (dn != NULL) 1759 { 1760 log_info ("Adding LDAP result set starting with '%s' to config stack", dn); 1761 ldap_memfree (dn); 1762 } 1763#endif 1764 1765 add_to_config_stack (newres, newent); 1766 /* don't free newres here */ 1767 } 1768 } 1769 1770 ldap_value_free_len (tempbv); 1771 } 1772} 1773 1774 1775static void 1776free_stack_entry (struct ldap_config_stack *item) 1777{ 1778 struct ldap_config_stack *look_ahead_pointer = item; 1779 int may_free_msg = 1; 1780 1781 while (look_ahead_pointer->next != NULL) 1782 { 1783 look_ahead_pointer = look_ahead_pointer->next; 1784 if (look_ahead_pointer->res == item->res) 1785 { 1786 may_free_msg = 0; 1787 break; 1788 } 1789 } 1790 1791 if (may_free_msg) 1792 ldap_msgfree (item->res); 1793 1794 dfree (item, MDL); 1795} 1796 1797 1798static void 1799next_ldap_entry (struct parse *cfile) 1800{ 1801 struct ldap_config_stack *temp_stack; 1802 1803 if (ldap_stack != NULL && ldap_stack->close_brace) 1804 { 1805 x_parser_strcat (cfile, "}\n"); 1806 ldap_stack->close_brace = 0; 1807 } 1808 1809 while (ldap_stack != NULL && 1810 (ldap_stack->ldent == NULL || ( ldap_stack->processed && 1811 (ldap_stack->ldent = ldap_next_entry (ld, ldap_stack->ldent)) == NULL))) 1812 { 1813 if (ldap_stack->close_brace) 1814 { 1815 x_parser_strcat (cfile, "}\n"); 1816 ldap_stack->close_brace = 0; 1817 } 1818 1819 temp_stack = ldap_stack; 1820 ldap_stack = ldap_stack->next; 1821 free_stack_entry (temp_stack); 1822 } 1823 1824 if (ldap_stack != NULL && ldap_stack->close_brace) 1825 { 1826 x_parser_strcat (cfile, "}\n"); 1827 ldap_stack->close_brace = 0; 1828 } 1829} 1830 1831 1832static char 1833check_statement_end (const char *statement) 1834{ 1835 char *ptr; 1836 1837 if (statement == NULL || *statement == '\0') 1838 return ('\0'); 1839 1840 /* 1841 ** check if it ends with "}", e.g.: 1842 ** "zone my.domain. { ... }" 1843 ** optionally followed by spaces 1844 */ 1845 ptr = strrchr (statement, '}'); 1846 if (ptr != NULL) 1847 { 1848 /* skip following white-spaces */ 1849 for (++ptr; isspace ((int)*ptr); ptr++); 1850 1851 /* check if we reached the end */ 1852 if (*ptr == '\0') 1853 return ('}'); /* yes, block end */ 1854 else 1855 return (*ptr); 1856 } 1857 1858 /* 1859 ** this should not happen, but... 1860 ** check if it ends with ";", e.g.: 1861 ** "authoritative;" 1862 ** optionally followed by spaces 1863 */ 1864 ptr = strrchr (statement, ';'); 1865 if (ptr != NULL) 1866 { 1867 /* skip following white-spaces */ 1868 for (++ptr; isspace ((int)*ptr); ptr++); 1869 1870 /* check if we reached the end */ 1871 if (*ptr == '\0') 1872 return (';'); /* ends with a ; */ 1873 else 1874 return (*ptr); 1875 } 1876 1877 return ('\0'); 1878} 1879 1880 1881static isc_result_t 1882ldap_parse_entry_options (LDAPMessage *ent, struct parse *cfile, 1883 int *lease_limit) 1884{ 1885 struct berval **tempbv; 1886 int i; 1887 1888 if (ent == NULL || cfile == NULL) 1889 return (ISC_R_FAILURE); 1890 1891 if ((tempbv = ldap_get_values_len (ld, ent, "dhcpStatements")) != NULL) 1892 { 1893 for (i=0; tempbv[i] != NULL; i++) 1894 { 1895 if (lease_limit != NULL && 1896 strncasecmp ("lease limit ", tempbv[i]->bv_val, 12) == 0) 1897 { 1898 *lease_limit = (int) strtol ((tempbv[i]->bv_val) + 12, NULL, 10); 1899 continue; 1900 } 1901 1902 x_parser_strcat (cfile, tempbv[i]->bv_val); 1903 1904 switch((int) check_statement_end (tempbv[i]->bv_val)) 1905 { 1906 case '}': 1907 case ';': 1908 x_parser_strcat (cfile, "\n"); 1909 break; 1910 default: 1911 x_parser_strcat (cfile, ";\n"); 1912 break; 1913 } 1914 } 1915 ldap_value_free_len (tempbv); 1916 } 1917 1918 if ((tempbv = ldap_get_values_len (ld, ent, "dhcpOption")) != NULL) 1919 { 1920 for (i=0; tempbv[i] != NULL; i++) 1921 { 1922 x_parser_strcat (cfile, "option "); 1923 x_parser_strcat (cfile, tempbv[i]->bv_val); 1924 switch ((int) check_statement_end (tempbv[i]->bv_val)) 1925 { 1926 case ';': 1927 x_parser_strcat (cfile, "\n"); 1928 break; 1929 default: 1930 x_parser_strcat (cfile, ";\n"); 1931 break; 1932 } 1933 } 1934 ldap_value_free_len (tempbv); 1935 } 1936 1937 return (ISC_R_SUCCESS); 1938} 1939 1940 1941static void 1942ldap_generate_config_string (struct parse *cfile) 1943{ 1944 struct berval **objectClass; 1945 char *dn; 1946 struct ldap_config_stack *entry; 1947 LDAPMessage * ent, * res, *entfirst, *resfirst; 1948 int i, ignore, found; 1949 int ret, parsedn = 1; 1950 size_t len = cfile->buflen; 1951 1952 if (ld == NULL) 1953 ldap_start (); 1954 if (ld == NULL) 1955 return; 1956 1957 entry = ldap_stack; 1958 if ((objectClass = ldap_get_values_len (ld, entry->ldent, 1959 "objectClass")) == NULL) 1960 return; 1961 1962 entry->processed = 1; 1963 ignore = 0; 1964 found = 1; 1965 for (i=0; objectClass[i] != NULL; i++) 1966 { 1967 if (strcasecmp (objectClass[i]->bv_val, "dhcpSharedNetwork") == 0) 1968 ldap_parse_shared_network (entry, cfile); 1969 else if (strcasecmp (objectClass[i]->bv_val, "dhcpClass") == 0) 1970 ldap_parse_class (entry, cfile); 1971 else if (strcasecmp (objectClass[i]->bv_val, "dhcpSubnet") == 0) 1972 ldap_parse_subnet (entry, cfile); 1973 else if (strcasecmp (objectClass[i]->bv_val, "dhcpSubnet6") == 0) 1974 ldap_parse_subnet6 (entry, cfile); 1975 else if (strcasecmp (objectClass[i]->bv_val, "dhcpPool") == 0) 1976 ldap_parse_pool (entry, cfile); 1977 else if (strcasecmp (objectClass[i]->bv_val, "dhcpPool6") == 0) 1978 ldap_parse_pool6 (entry, cfile); 1979 else if (strcasecmp (objectClass[i]->bv_val, "dhcpGroup") == 0) 1980 ldap_parse_group (entry, cfile); 1981 else if (strcasecmp (objectClass[i]->bv_val, "dhcpTSigKey") == 0) 1982 ldap_parse_key (entry, cfile); 1983 else if (strcasecmp (objectClass[i]->bv_val, "dhcpDnsZone") == 0) 1984 ldap_parse_zone (entry, cfile); 1985#if defined(HAVE_IFADDRS_H) 1986 else if (strcasecmp (objectClass[i]->bv_val, "dhcpFailOverPeer") == 0) 1987 ldap_parse_failover (entry, cfile); 1988#endif 1989 else if (strcasecmp (objectClass[i]->bv_val, "dhcpHost") == 0) 1990 { 1991 if (ldap_method == LDAP_METHOD_STATIC) 1992 ldap_parse_host (entry, cfile); 1993 else 1994 { 1995 ignore = 1; 1996 break; 1997 } 1998 } 1999 else if (strcasecmp (objectClass[i]->bv_val, "dhcpSubClass") == 0) 2000 { 2001 if (ldap_method == LDAP_METHOD_STATIC) 2002 ldap_parse_subclass (entry, cfile); 2003 else 2004 { 2005 ignore = 1; 2006 break; 2007 } 2008 } 2009 else 2010 found = 0; 2011 2012 if (found && x_parser_length(cfile) <= len) 2013 { 2014 ignore = 1; 2015 break; 2016 } 2017 } 2018 2019 ldap_value_free_len (objectClass); 2020 2021 if (ignore) 2022 { 2023 next_ldap_entry (cfile); 2024 return; 2025 } 2026 2027 ldap_parse_entry_options(entry->ldent, cfile, NULL); 2028 2029 dn = ldap_get_dn (ld, entry->ldent); 2030 if (dn == NULL) 2031 { 2032 ldap_stop(); 2033 return; 2034 } 2035#if defined(DEBUG_LDAP) 2036 log_info ("Found LDAP entry '%s'", dn); 2037#endif 2038 2039 if ((ret = ldap_search_ext_s (ld, dn, LDAP_SCOPE_ONELEVEL, 2040 "(!(|(|(objectClass=dhcpTSigKey)(objectClass=dhcpClass)) (objectClass=dhcpFailOverPeer)))", 2041 NULL, 0, NULL, NULL, 2042 NULL, 0, &res)) != LDAP_SUCCESS) 2043 { 2044 ldap_memfree (dn); 2045 2046 ldap_stop(); 2047 return; 2048 } 2049 2050 if ((ret = ldap_search_ext_s (ld, dn, LDAP_SCOPE_ONELEVEL, 2051 "(|(|(objectClass=dhcpTSigKey)(objectClass=dhcpClass)) (objectClass=dhcpFailOverPeer))", 2052 NULL, 0, NULL, NULL, 2053 NULL, 0, &resfirst)) != LDAP_SUCCESS) 2054 { 2055 ldap_memfree (dn); 2056 ldap_msgfree (res); 2057 2058 ldap_stop(); 2059 return; 2060 } 2061 2062 ldap_memfree (dn); 2063 2064 ent = ldap_first_entry(ld, res); 2065 entfirst = ldap_first_entry(ld, resfirst); 2066 2067 if (ent == NULL && entfirst == NULL) 2068 { 2069 parse_external_dns (entry->ldent); 2070 next_ldap_entry (cfile); 2071 } 2072 2073 if (ent != NULL) 2074 { 2075 add_to_config_stack (res, ent); 2076 parse_external_dns (entry->ldent); 2077 parsedn = 0; 2078 } 2079 else 2080 ldap_msgfree (res); 2081 2082 if (entfirst != NULL) 2083 { 2084 add_to_config_stack (resfirst, entfirst); 2085 if(parsedn) 2086 parse_external_dns (entry->ldent); 2087 2088 } 2089 else 2090 ldap_msgfree (resfirst); 2091} 2092 2093 2094static void 2095ldap_close_debug_fd() 2096{ 2097 if (ldap_debug_fd != -1) 2098 { 2099 close (ldap_debug_fd); 2100 ldap_debug_fd = -1; 2101 } 2102} 2103 2104 2105static void 2106ldap_write_debug (const void *buff, size_t size) 2107{ 2108 if (ldap_debug_fd != -1) 2109 { 2110 if (write (ldap_debug_fd, buff, size) < 0) 2111 { 2112 log_error ("Error writing to LDAP debug file %s: %s." 2113 " Disabling log file.", ldap_debug_file, 2114 strerror (errno)); 2115 ldap_close_debug_fd(); 2116 } 2117 } 2118} 2119 2120static int 2121ldap_read_function (struct parse *cfile) 2122{ 2123 size_t len; 2124 2125 /* append when in saved state */ 2126 if (cfile->saved_state == NULL) 2127 { 2128 cfile->inbuf[0] = '\0'; 2129 cfile->bufix = 0; 2130 cfile->buflen = 0; 2131 } 2132 len = cfile->buflen; 2133 2134 while (ldap_stack != NULL && x_parser_length(cfile) <= len) 2135 ldap_generate_config_string (cfile); 2136 2137 if (x_parser_length(cfile) <= len && ldap_stack == NULL) 2138 return (EOF); 2139 2140 if (cfile->buflen > len) 2141 ldap_write_debug (cfile->inbuf + len, cfile->buflen - len); 2142#if defined (DEBUG_LDAP) 2143 log_info ("Sending config portion '%s'", cfile->inbuf + len); 2144#endif 2145 2146 return (cfile->inbuf[cfile->bufix++]); 2147} 2148 2149 2150static char * 2151ldap_get_host_name (LDAPMessage * ent) 2152{ 2153 struct berval **name; 2154 char *ret; 2155 2156 ret = NULL; 2157 if ((name = ldap_get_values_len (ld, ent, "cn")) == NULL || name[0] == NULL) 2158 { 2159 if (name != NULL) 2160 ldap_value_free_len (name); 2161 2162#if defined (DEBUG_LDAP) 2163 ret = ldap_get_dn (ld, ent); 2164 if (ret != NULL) 2165 { 2166 log_info ("Cannot get cn attribute for LDAP entry %s", ret); 2167 ldap_memfree(ret); 2168 } 2169#endif 2170 return (NULL); 2171 } 2172 2173 ret = dmalloc (strlen (name[0]->bv_val) + 1, MDL); 2174 strcpy (ret, name[0]->bv_val); 2175 ldap_value_free_len (name); 2176 2177 return (ret); 2178} 2179 2180 2181isc_result_t 2182ldap_read_config (void) 2183{ 2184 LDAPMessage * ldres, * hostres, * ent, * hostent; 2185 char hfilter[1024], sfilter[1024], fqdn[257]; 2186 char *hostdn; 2187 ldap_dn_node *curr = NULL; 2188 struct parse *cfile; 2189 struct utsname unme; 2190 isc_result_t res; 2191 size_t length; 2192 int ret, cnt; 2193 struct berval **tempbv = NULL; 2194 struct berval bv_o[2]; 2195 2196 cfile = x_parser_init("LDAP"); 2197 if (cfile == NULL) 2198 return (ISC_R_NOMEMORY); 2199 2200 ldap_enable_retry = 1; 2201 if (ld == NULL) 2202 ldap_start (); 2203 ldap_enable_retry = 0; 2204 2205 if (ld == NULL) 2206 { 2207 x_parser_free(&cfile); 2208 return (ldap_server == NULL ? ISC_R_SUCCESS : ISC_R_FAILURE); 2209 } 2210 2211 uname (&unme); 2212 if (ldap_dhcp_server_cn != NULL) 2213 { 2214 if (_do_ldap_str2esc_filter_bv(ldap_dhcp_server_cn, 0, &bv_o[0]) == NULL) 2215 { 2216 log_error ("Cannot escape ldap filter value %s: %m", ldap_dhcp_server_cn); 2217 x_parser_free(&cfile); 2218 return (ISC_R_FAILURE); 2219 } 2220 2221 snprintf (hfilter, sizeof (hfilter), 2222 "(&(objectClass=dhcpServer)(cn=%s))", bv_o[0].bv_val); 2223 2224 ber_memfree(bv_o[0].bv_val); 2225 } 2226 else 2227 { 2228 if (_do_ldap_str2esc_filter_bv(unme.nodename, 0, &bv_o[0]) == NULL) 2229 { 2230 log_error ("Cannot escape ldap filter value %s: %m", unme.nodename); 2231 x_parser_free(&cfile); 2232 return (ISC_R_FAILURE); 2233 } 2234 2235 *fqdn ='\0'; 2236 if(0 == get_host_entry(fqdn, sizeof(fqdn), NULL, 0)) 2237 { 2238 if (_do_ldap_str2esc_filter_bv(fqdn, 0, &bv_o[1]) == NULL) 2239 { 2240 log_error ("Cannot escape ldap filter value %s: %m", fqdn); 2241 ber_memfree(bv_o[0].bv_val); 2242 x_parser_free(&cfile); 2243 return (ISC_R_FAILURE); 2244 } 2245 } 2246 2247 // If we have fqdn and it isn't the same as nodename, use it in filter 2248 // otherwise just use nodename 2249 if ((*fqdn) && (strcmp(unme.nodename, fqdn))) { 2250 snprintf (hfilter, sizeof (hfilter), 2251 "(&(objectClass=dhcpServer)(|(cn=%s)(cn=%s)))", 2252 bv_o[0].bv_val, bv_o[1].bv_val); 2253 2254 ber_memfree(bv_o[1].bv_val); 2255 } 2256 else 2257 { 2258 snprintf (hfilter, sizeof (hfilter), 2259 "(&(objectClass=dhcpServer)(cn=%s))", 2260 bv_o[0].bv_val); 2261 } 2262 2263 ber_memfree(bv_o[0].bv_val); 2264 } 2265 2266 ldap_enable_retry = 1; 2267 do 2268 { 2269 hostres = NULL; 2270 ret = ldap_search_ext_s (ld, ldap_base_dn, LDAP_SCOPE_SUBTREE, 2271 hfilter, NULL, 0, NULL, NULL, NULL, 0, 2272 &hostres); 2273 } 2274 while(_do_ldap_retry(ret, ldap_server, ldap_port) > 0); 2275 ldap_enable_retry = 0; 2276 2277 if(ret != LDAP_SUCCESS) 2278 { 2279 log_error ("Cannot find host LDAP entry %s %s", 2280 ((ldap_dhcp_server_cn == NULL)?(unme.nodename):(ldap_dhcp_server_cn)), hfilter); 2281 if(NULL != hostres) 2282 ldap_msgfree (hostres); 2283 ldap_stop(); 2284 x_parser_free(&cfile); 2285 return (ISC_R_FAILURE); 2286 } 2287 2288 if ((hostent = ldap_first_entry (ld, hostres)) == NULL) 2289 { 2290 log_error ("Error: Cannot find LDAP entry matching %s", hfilter); 2291 ldap_msgfree (hostres); 2292 ldap_stop(); 2293 x_parser_free(&cfile); 2294 return (ISC_R_FAILURE); 2295 } 2296 2297 hostdn = ldap_get_dn (ld, hostent); 2298#if defined(DEBUG_LDAP) 2299 if (hostdn != NULL) 2300 log_info ("Found dhcpServer LDAP entry '%s'", hostdn); 2301#endif 2302 2303 if (hostdn == NULL || 2304 (tempbv = ldap_get_values_len (ld, hostent, "dhcpServiceDN")) == NULL || 2305 tempbv[0] == NULL) 2306 { 2307 log_error ("Error: No dhcp service is associated with the server %s %s", 2308 (hostdn ? "dn" : "name"), (hostdn ? hostdn : 2309 (ldap_dhcp_server_cn ? ldap_dhcp_server_cn : unme.nodename))); 2310 2311 if (tempbv != NULL) 2312 ldap_value_free_len (tempbv); 2313 2314 if (hostdn) 2315 ldap_memfree (hostdn); 2316 ldap_msgfree (hostres); 2317 ldap_stop(); 2318 x_parser_free(&cfile); 2319 return (ISC_R_FAILURE); 2320 } 2321 2322#if defined(DEBUG_LDAP) 2323 log_info ("LDAP: Parsing dhcpServer options '%s' ...", hostdn); 2324#endif 2325 2326 res = ldap_parse_entry_options(hostent, cfile, NULL); 2327 if (res != ISC_R_SUCCESS) 2328 { 2329 ldap_value_free_len (tempbv); 2330 ldap_msgfree (hostres); 2331 ldap_memfree (hostdn); 2332 ldap_stop(); 2333 x_parser_free(&cfile); 2334 return res; 2335 } 2336 2337 if (x_parser_length(cfile) > 0) 2338 { 2339 ldap_write_debug(cfile->inbuf, cfile->buflen); 2340 2341 res = conf_file_subparse (cfile, root_group, ROOT_GROUP); 2342 if (res != ISC_R_SUCCESS) 2343 { 2344 log_error ("LDAP: cannot parse dhcpServer entry '%s'", hostdn); 2345 ldap_value_free_len (tempbv); 2346 ldap_msgfree (hostres); 2347 ldap_memfree (hostdn); 2348 ldap_stop(); 2349 x_parser_free(&cfile); 2350 return res; 2351 } 2352 x_parser_reset(cfile); 2353 } 2354 ldap_msgfree (hostres); 2355 2356 res = ISC_R_SUCCESS; 2357 for (cnt=0; tempbv[cnt] != NULL; cnt++) 2358 { 2359 2360 if (_do_ldap_str2esc_filter_bv(hostdn, 0, &bv_o[0]) == NULL) 2361 { 2362 log_error ("Cannot escape ldap filter value %s: %m", hostdn); 2363 res = ISC_R_FAILURE; 2364 break; 2365 } 2366 2367 snprintf(sfilter, sizeof(sfilter), "(&(objectClass=dhcpService)" 2368 "(|(|(dhcpPrimaryDN=%s)(dhcpSecondaryDN=%s))(dhcpServerDN=%s)))", 2369 bv_o[0].bv_val, bv_o[0].bv_val, bv_o[0].bv_val); 2370 2371 ber_memfree(bv_o[0].bv_val); 2372 2373 ldres = NULL; 2374 if ((ret = ldap_search_ext_s (ld, tempbv[cnt]->bv_val, LDAP_SCOPE_BASE, 2375 sfilter, NULL, 0, NULL, NULL, NULL, 2376 0, &ldres)) != LDAP_SUCCESS) 2377 { 2378 log_error ("Error searching for dhcpServiceDN '%s': %s. Please update the LDAP entry '%s'", 2379 tempbv[cnt]->bv_val, ldap_err2string (ret), hostdn); 2380 if(NULL != ldres) 2381 ldap_msgfree(ldres); 2382 res = ISC_R_FAILURE; 2383 break; 2384 } 2385 2386 if ((ent = ldap_first_entry (ld, ldres)) == NULL) 2387 { 2388 log_error ("Error: Cannot find dhcpService DN '%s' with server reference. Please update the LDAP server entry '%s'", 2389 tempbv[cnt]->bv_val, hostdn); 2390 2391 ldap_msgfree(ldres); 2392 res = ISC_R_FAILURE; 2393 break; 2394 } 2395 2396 /* 2397 ** FIXME: how to free the remembered dn's on exit? 2398 ** This should be OK if dmalloc registers the 2399 ** memory it allocated and frees it on exit.. 2400 */ 2401 2402 curr = dmalloc (sizeof (*curr), MDL); 2403 if (curr != NULL) 2404 { 2405 length = strlen (tempbv[cnt]->bv_val); 2406 curr->dn = dmalloc (length + 1, MDL); 2407 if (curr->dn == NULL) 2408 { 2409 dfree (curr, MDL); 2410 curr = NULL; 2411 } 2412 else 2413 strcpy (curr->dn, tempbv[cnt]->bv_val); 2414 } 2415 2416 if (curr != NULL) 2417 { 2418 curr->refs++; 2419 2420 /* append to service-dn list */ 2421 if (ldap_service_dn_tail != NULL) 2422 ldap_service_dn_tail->next = curr; 2423 else 2424 ldap_service_dn_head = curr; 2425 2426 ldap_service_dn_tail = curr; 2427 } 2428 else 2429 log_fatal ("no memory to remember ldap service dn"); 2430 2431#if defined (DEBUG_LDAP) 2432 log_info ("LDAP: Parsing dhcpService DN '%s' ...", tempbv[cnt]->bv_val); 2433#endif 2434 add_to_config_stack (ldres, ent); 2435 res = conf_file_subparse (cfile, root_group, ROOT_GROUP); 2436 if (res != ISC_R_SUCCESS) 2437 { 2438 log_error ("LDAP: cannot parse dhcpService entry '%s'", tempbv[cnt]->bv_val); 2439 break; 2440 } 2441 } 2442 2443 x_parser_free(&cfile); 2444 ldap_close_debug_fd(); 2445 2446 ldap_memfree (hostdn); 2447 ldap_value_free_len (tempbv); 2448 2449 if (res != ISC_R_SUCCESS) 2450 { 2451 struct ldap_config_stack *temp_stack; 2452 2453 while ((curr = ldap_service_dn_head) != NULL) 2454 { 2455 ldap_service_dn_head = curr->next; 2456 dfree (curr->dn, MDL); 2457 dfree (curr, MDL); 2458 } 2459 2460 ldap_service_dn_tail = NULL; 2461 2462 while ((temp_stack = ldap_stack) != NULL) 2463 { 2464 ldap_stack = temp_stack->next; 2465 free_stack_entry (temp_stack); 2466 } 2467 2468 ldap_stop(); 2469 } 2470 2471 /* Unbind from ldap immediately after reading config in static mode. */ 2472 if (ldap_method == LDAP_METHOD_STATIC) 2473 ldap_stop(); 2474 2475 return (res); 2476} 2477 2478 2479/* This function will parse the dhcpOption and dhcpStatements field in the LDAP 2480 entry if it exists. Right now, type will be either HOST_DECL or CLASS_DECL. 2481 If we are parsing a HOST_DECL, this always returns 0. If we are parsing a 2482 CLASS_DECL, this will return what the current lease limit is in LDAP. If 2483 there is no lease limit specified, we return 0 */ 2484 2485static int 2486ldap_parse_options (LDAPMessage * ent, struct group *group, 2487 int type, struct host_decl *host, 2488 struct class **class) 2489{ 2490 int declaration, lease_limit; 2491 enum dhcp_token token; 2492 struct parse *cfile; 2493 isc_result_t res; 2494 const char *val; 2495 2496 lease_limit = 0; 2497 cfile = x_parser_init(type == HOST_DECL ? "LDAP-HOST" : "LDAP-SUBCLASS"); 2498 if (cfile == NULL) 2499 return (lease_limit); 2500 2501 /* This block of code will try to find the parent of the host, and 2502 if it is a group object, fetch the options and apply to the host. */ 2503 if (type == HOST_DECL) 2504 { 2505 char *hostdn, *basedn, *temp1, *temp2, filter[1024]; 2506 LDAPMessage *groupdn, *entry; 2507 int ret; 2508 2509 hostdn = ldap_get_dn (ld, ent); 2510 if( hostdn != NULL) 2511 { 2512 basedn = NULL; 2513 2514 temp1 = strchr (hostdn, '='); 2515 if (temp1 != NULL) 2516 temp1 = strchr (++temp1, '='); 2517 if (temp1 != NULL) 2518 temp2 = strchr (++temp1, ','); 2519 else 2520 temp2 = NULL; 2521 2522 if (temp2 != NULL) 2523 { 2524 struct berval bv_o; 2525 2526 if (_do_ldap_str2esc_filter_bv(temp1, (temp2 - temp1), &bv_o) == NULL) 2527 { 2528 log_error ("Cannot escape ldap filter value %.*s: %m", 2529 (int)(temp2 - temp1), temp1); 2530 filter[0] = '\0'; 2531 } 2532 else 2533 { 2534 snprintf (filter, sizeof(filter), 2535 "(&(cn=%s)(objectClass=dhcpGroup))", 2536 bv_o.bv_val); 2537 2538 ber_memfree(bv_o.bv_val); 2539 } 2540 2541 basedn = strchr (temp1, ','); 2542 if (basedn != NULL) 2543 ++basedn; 2544 } 2545 2546 if (basedn != NULL && *basedn != '\0' && filter[0] != '\0') 2547 { 2548 ret = ldap_search_ext_s (ld, basedn, LDAP_SCOPE_SUBTREE, filter, 2549 NULL, 0, NULL, NULL, NULL, 0, &groupdn); 2550 if (ret == LDAP_SUCCESS) 2551 { 2552 if ((entry = ldap_first_entry (ld, groupdn)) != NULL) 2553 { 2554 res = ldap_parse_entry_options (entry, cfile, &lease_limit); 2555 if (res != ISC_R_SUCCESS) 2556 { 2557 /* reset option buffer discarding any results */ 2558 x_parser_reset(cfile); 2559 lease_limit = 0; 2560 } 2561 } 2562 ldap_msgfree( groupdn); 2563 } 2564 } 2565 ldap_memfree( hostdn); 2566 } 2567 } 2568 2569 res = ldap_parse_entry_options (ent, cfile, &lease_limit); 2570 if (res != ISC_R_SUCCESS) 2571 { 2572 x_parser_free(&cfile); 2573 return (lease_limit); 2574 } 2575 2576 if (x_parser_length(cfile) == 0) 2577 { 2578 x_parser_free(&cfile); 2579 return (lease_limit); 2580 } 2581 2582 declaration = 0; 2583 do 2584 { 2585 token = peek_token (&val, NULL, cfile); 2586 if (token == END_OF_FILE) 2587 break; 2588 declaration = parse_statement (cfile, group, type, host, declaration); 2589 } while (1); 2590 2591 x_parser_free(&cfile); 2592 2593 return (lease_limit); 2594} 2595 2596 2597 2598int 2599find_haddr_in_ldap (struct host_decl **hp, int htype, unsigned hlen, 2600 const unsigned char *haddr, const char *file, int line) 2601{ 2602 char buf[128], *type_str; 2603 LDAPMessage * res, *ent; 2604 struct host_decl * host; 2605 isc_result_t status; 2606 ldap_dn_node *curr; 2607 char up_hwaddr[20]; 2608 char lo_hwaddr[20]; 2609 int ret; 2610 struct berval bv_o[2]; 2611 2612 *hp = NULL; 2613 2614 2615 if (ldap_method == LDAP_METHOD_STATIC) 2616 return (0); 2617 2618 if (ld == NULL) 2619 ldap_start (); 2620 if (ld == NULL) 2621 return (0); 2622 2623 switch (htype) 2624 { 2625 case HTYPE_ETHER: 2626 type_str = "ethernet"; 2627 break; 2628 case HTYPE_IEEE802: 2629 type_str = "token-ring"; 2630 break; 2631 case HTYPE_FDDI: 2632 type_str = "fddi"; 2633 break; 2634 default: 2635 log_info ("Ignoring unknown type %d", htype); 2636 return (0); 2637 } 2638 2639 /* 2640 ** FIXME: It is not guaranteed, that the dhcpHWAddress attribute 2641 ** contains _exactly_ "type addr" with one space between! 2642 */ 2643 snprintf(lo_hwaddr, sizeof(lo_hwaddr), "%s", 2644 print_hw_addr (htype, hlen, haddr)); 2645 x_strxform(up_hwaddr, lo_hwaddr, sizeof(up_hwaddr), toupper); 2646 2647 if (_do_ldap_str2esc_filter_bv(lo_hwaddr, 0, &bv_o[0]) == NULL) 2648 { 2649 log_error ("Cannot escape ldap filter value %s: %m", lo_hwaddr); 2650 return (0); 2651 } 2652 if (_do_ldap_str2esc_filter_bv(up_hwaddr, 0, &bv_o[1]) == NULL) 2653 { 2654 log_error ("Cannot escape ldap filter value %s: %m", up_hwaddr); 2655 ber_memfree(bv_o[0].bv_val); 2656 return (0); 2657 } 2658 2659 snprintf (buf, sizeof (buf), 2660 "(&(objectClass=dhcpHost)(|(dhcpHWAddress=%s %s)(dhcpHWAddress=%s %s)))", 2661 type_str, bv_o[0].bv_val, type_str, bv_o[1].bv_val); 2662 2663 ber_memfree(bv_o[0].bv_val); 2664 ber_memfree(bv_o[1].bv_val); 2665 2666 res = ent = NULL; 2667 for (curr = ldap_service_dn_head; 2668 curr != NULL && *curr->dn != '\0'; 2669 curr = curr->next) 2670 { 2671#if defined (DEBUG_LDAP) 2672 log_info ("Searching for %s in LDAP tree %s", buf, curr->dn); 2673#endif 2674 ret = ldap_search_ext_s (ld, curr->dn, LDAP_SCOPE_SUBTREE, buf, NULL, 0, 2675 NULL, NULL, NULL, 0, &res); 2676 2677 if(ret == LDAP_SERVER_DOWN) 2678 { 2679 log_info ("LDAP server was down, trying to reconnect..."); 2680 2681 ldap_stop(); 2682 ldap_start(); 2683 if(ld == NULL) 2684 { 2685 log_info ("LDAP reconnect failed - try again later..."); 2686 return (0); 2687 } 2688 2689 ret = ldap_search_ext_s (ld, curr->dn, LDAP_SCOPE_SUBTREE, buf, NULL, 2690 0, NULL, NULL, NULL, 0, &res); 2691 } 2692 2693 if (ret == LDAP_SUCCESS) 2694 { 2695 ent = ldap_first_entry (ld, res); 2696#if defined (DEBUG_LDAP) 2697 if (ent == NULL) { 2698 log_info ("No host entry for %s in LDAP tree %s", 2699 buf, curr->dn); 2700 } 2701#endif 2702 while (ent != NULL) { 2703#if defined (DEBUG_LDAP) 2704 char *dn = ldap_get_dn (ld, ent); 2705 if (dn != NULL) 2706 { 2707 log_info ("Found dhcpHWAddress LDAP entry %s", dn); 2708 ldap_memfree(dn); 2709 } 2710#endif 2711 2712 host = (struct host_decl *)0; 2713 status = host_allocate (&host, MDL); 2714 if (status != ISC_R_SUCCESS) 2715 { 2716 log_fatal ("can't allocate host decl struct: %s", 2717 isc_result_totext (status)); 2718 ldap_msgfree (res); 2719 return (0); 2720 } 2721 2722 host->name = ldap_get_host_name (ent); 2723 if (host->name == NULL) 2724 { 2725 host_dereference (&host, MDL); 2726 ldap_msgfree (res); 2727 return (0); 2728 } 2729 2730 if (!clone_group (&host->group, root_group, MDL)) 2731 { 2732 log_fatal ("can't clone group for host %s", host->name); 2733 host_dereference (&host, MDL); 2734 ldap_msgfree (res); 2735 return (0); 2736 } 2737 2738 ldap_parse_options (ent, host->group, HOST_DECL, host, NULL); 2739 2740 host->n_ipaddr = *hp; 2741 *hp = host; 2742 ent = ldap_next_entry (ld, ent); 2743 } 2744 if(res) 2745 { 2746 ldap_msgfree (res); 2747 res = NULL; 2748 } 2749 return (*hp != NULL); 2750 } 2751 else 2752 { 2753 if(res) 2754 { 2755 ldap_msgfree (res); 2756 res = NULL; 2757 } 2758 2759 if (ret != LDAP_NO_SUCH_OBJECT && ret != LDAP_SUCCESS) 2760 { 2761 log_error ("Cannot search for %s in LDAP tree %s: %s", buf, 2762 curr->dn, ldap_err2string (ret)); 2763 ldap_stop(); 2764 return (0); 2765 } 2766#if defined (DEBUG_LDAP) 2767 else 2768 { 2769 log_info ("ldap_search_ext_s returned %s when searching for %s in %s", 2770 ldap_err2string (ret), buf, curr->dn); 2771 } 2772#endif 2773 } 2774 } 2775 2776 return (0); 2777} 2778 2779 2780int 2781find_subclass_in_ldap (struct class *class, struct class **newclass, 2782 struct data_string *data) 2783{ 2784 LDAPMessage * res, * ent; 2785 int ret, lease_limit; 2786 isc_result_t status; 2787 ldap_dn_node *curr; 2788 char buf[2048]; 2789 struct berval bv_class; 2790 struct berval bv_cdata; 2791 char *hex_1; 2792 2793 if (ldap_method == LDAP_METHOD_STATIC) 2794 return (0); 2795 2796 if (ld == NULL) 2797 ldap_start (); 2798 if (ld == NULL) 2799 return (0); 2800 2801 hex_1 = print_hex_1 (data->len, data->data, 1024); 2802 if (*hex_1 == '"') 2803 { 2804 /* result is a quotted not hex string: ldap escape the original string */ 2805 if (_do_ldap_str2esc_filter_bv((const char*)data->data, data->len, &bv_cdata) == NULL) 2806 { 2807 log_error ("Cannot escape ldap filter value %s: %m", hex_1); 2808 return (0); 2809 } 2810 hex_1 = NULL; 2811 } 2812 if (_do_ldap_str2esc_filter_bv(class->name, strlen (class->name), &bv_class) == NULL) 2813 { 2814 log_error ("Cannot escape ldap filter value %s: %m", class->name); 2815 if (hex_1 == NULL) 2816 ber_memfree(bv_cdata.bv_val); 2817 return (0); 2818 } 2819 2820 snprintf (buf, sizeof (buf), 2821 "(&(objectClass=dhcpSubClass)(cn=%s)(dhcpClassData=%s))", 2822 (hex_1 == NULL ? bv_cdata.bv_val : hex_1), bv_class.bv_val); 2823 2824 if (hex_1 == NULL) 2825 ber_memfree(bv_cdata.bv_val); 2826 ber_memfree(bv_class.bv_val); 2827 2828#if defined (DEBUG_LDAP) 2829 log_info ("Searching LDAP for %s", buf); 2830#endif 2831 2832 res = ent = NULL; 2833 for (curr = ldap_service_dn_head; 2834 curr != NULL && *curr->dn != '\0'; 2835 curr = curr->next) 2836 { 2837#if defined (DEBUG_LDAP) 2838 log_info ("Searching for %s in LDAP tree %s", buf, curr->dn); 2839#endif 2840 ret = ldap_search_ext_s (ld, curr->dn, LDAP_SCOPE_SUBTREE, buf, NULL, 0, 2841 NULL, NULL, NULL, 0, &res); 2842 2843 if(ret == LDAP_SERVER_DOWN) 2844 { 2845 log_info ("LDAP server was down, trying to reconnect..."); 2846 2847 ldap_stop(); 2848 ldap_start(); 2849 2850 if(ld == NULL) 2851 { 2852 log_info ("LDAP reconnect failed - try again later..."); 2853 return (0); 2854 } 2855 2856 ret = ldap_search_ext_s (ld, curr->dn, LDAP_SCOPE_SUBTREE, buf, 2857 NULL, 0, NULL, NULL, NULL, 0, &res); 2858 } 2859 2860 if (ret == LDAP_SUCCESS) 2861 { 2862 if( (ent = ldap_first_entry (ld, res)) != NULL) 2863 break; /* search OK and have entry */ 2864 2865#if defined (DEBUG_LDAP) 2866 log_info ("No subclass entry for %s in LDAP tree %s", 2867 buf, curr->dn); 2868#endif 2869 if(res) 2870 { 2871 ldap_msgfree (res); 2872 res = NULL; 2873 } 2874 } 2875 else 2876 { 2877 if(res) 2878 { 2879 ldap_msgfree (res); 2880 res = NULL; 2881 } 2882 2883 if (ret != LDAP_NO_SUCH_OBJECT && ret != LDAP_SUCCESS) 2884 { 2885 log_error ("Cannot search for %s in LDAP tree %s: %s", buf, 2886 curr->dn, ldap_err2string (ret)); 2887 ldap_stop(); 2888 return (0); 2889 } 2890#if defined (DEBUG_LDAP) 2891 else 2892 { 2893 log_info ("ldap_search_ext_s returned %s when searching for %s in %s", 2894 ldap_err2string (ret), buf, curr->dn); 2895 } 2896#endif 2897 } 2898 } 2899 2900 if (res && ent) 2901 { 2902#if defined (DEBUG_LDAP) 2903 char *dn = ldap_get_dn (ld, ent); 2904 if (dn != NULL) 2905 { 2906 log_info ("Found subclass LDAP entry %s", dn); 2907 ldap_memfree(dn); 2908 } 2909#endif 2910 2911 status = class_allocate (newclass, MDL); 2912 if (status != ISC_R_SUCCESS) 2913 { 2914 log_error ("Cannot allocate memory for a new class"); 2915 ldap_msgfree (res); 2916 return (0); 2917 } 2918 2919 group_reference (&(*newclass)->group, class->group, MDL); 2920 class_reference (&(*newclass)->superclass, class, MDL); 2921 lease_limit = ldap_parse_options (ent, (*newclass)->group, 2922 CLASS_DECL, NULL, newclass); 2923 if (lease_limit == 0) 2924 (*newclass)->lease_limit = class->lease_limit; 2925 else 2926 class->lease_limit = lease_limit; 2927 2928 if ((*newclass)->lease_limit) 2929 { 2930 (*newclass)->billed_leases = 2931 dmalloc ((*newclass)->lease_limit * sizeof (struct lease *), MDL); 2932 if (!(*newclass)->billed_leases) 2933 { 2934 log_error ("no memory for billing"); 2935 class_dereference (newclass, MDL); 2936 ldap_msgfree (res); 2937 return (0); 2938 } 2939 memset ((*newclass)->billed_leases, 0, 2940 ((*newclass)->lease_limit * sizeof (struct lease *))); 2941 } 2942 2943 data_string_copy (&(*newclass)->hash_string, data, MDL); 2944 2945 ldap_msgfree (res); 2946 return (1); 2947 } 2948 2949 if(res) ldap_msgfree (res); 2950 return (0); 2951} 2952 2953int find_client_in_ldap (struct host_decl **hp, struct packet *packet, 2954 struct option_state *state, const char *file, int line) 2955{ 2956 LDAPMessage * res, * ent; 2957 ldap_dn_node *curr; 2958 struct host_decl * host; 2959 isc_result_t status; 2960 struct data_string client_id; 2961 char buf[1024], buf1[1024]; 2962 int ret; 2963 2964 if (ldap_method == LDAP_METHOD_STATIC) 2965 return (0); 2966 2967 if (ld == NULL) 2968 ldap_start (); 2969 if (ld == NULL) 2970 return (0); 2971 2972 memset(&client_id, 0, sizeof(client_id)); 2973 if (get_client_id(packet, &client_id) != ISC_R_SUCCESS) 2974 return (0); 2975 snprintf(buf, sizeof(buf), 2976 "(&(objectClass=dhcpHost)(dhcpClientId=%s))", 2977 print_hw_addr(0, client_id.len, client_id.data)); 2978 2979 /* log_info ("Searching LDAP for %s (%s)", buf, packet->interface->shared_network->name); */ 2980 2981 res = ent = NULL; 2982 for (curr = ldap_service_dn_head; 2983 curr != NULL && *curr->dn != '\0'; 2984 curr = curr->next) 2985 { 2986 snprintf(buf1, sizeof(buf1), "cn=%s,%s", packet->interface->shared_network->name, curr->dn); 2987#if defined (DEBUG_LDAP) 2988 log_info ("Searching for %s in LDAP tree %s", buf, buf1); 2989#endif 2990 ret = ldap_search_ext_s (ld, buf1, LDAP_SCOPE_SUBTREE, buf, NULL, 0, 2991 NULL, NULL, NULL, 0, &res); 2992 2993 if(ret == LDAP_SERVER_DOWN) 2994 { 2995 log_info ("LDAP server was down, trying to reconnect..."); 2996 2997 ldap_stop(); 2998 ldap_start(); 2999 3000 if(ld == NULL) 3001 { 3002 log_info ("LDAP reconnect failed - try again later..."); 3003 return (0); 3004 } 3005 3006 ret = ldap_search_ext_s (ld, buf1, LDAP_SCOPE_SUBTREE, buf, 3007 NULL, 0, NULL, NULL, NULL, 0, &res); 3008 } 3009 3010 if (ret == LDAP_SUCCESS) 3011 { 3012 if( (ent = ldap_first_entry (ld, res)) != NULL) { 3013 log_info ("found entry in search %s", buf1); 3014 break; /* search OK and have entry */ 3015 } 3016 3017#if defined (DEBUG_LDAP) 3018 log_info ("No subclass entry for %s in LDAP tree %s", buf, curr->dn); 3019#endif 3020 if(res) 3021 { 3022 ldap_msgfree (res); 3023 res = NULL; 3024 } 3025 } 3026 else 3027 { 3028 if(res) 3029 { 3030 ldap_msgfree (res); 3031 res = NULL; 3032 } 3033 3034 if (ret != LDAP_NO_SUCH_OBJECT && ret != LDAP_SUCCESS) 3035 { 3036 log_error ("Cannot search for %s in LDAP tree %s: %s", buf, 3037 curr->dn, ldap_err2string (ret)); 3038 ldap_stop(); 3039 return (0); 3040 } 3041 else 3042 { 3043 log_info ("did not find: %s", buf); 3044 } 3045 } 3046 } 3047 3048 if (res && ent) 3049 { 3050#if defined (DEBUG_LDAP) 3051 log_info ("ldap_get_dn %s", curr->dn); 3052 char *dn = ldap_get_dn (ld, ent); 3053 if (dn != NULL) 3054 { 3055 log_info ("Found subclass LDAP entry %s", dn); 3056 ldap_memfree(dn); 3057 } else { 3058 log_info ("DN is null %s", dn); 3059 } 3060#endif 3061 3062 host = (struct host_decl *)0; 3063 status = host_allocate (&host, MDL); 3064 if (status != ISC_R_SUCCESS) 3065 { 3066 log_fatal ("can't allocate host decl struct: %s", 3067 isc_result_totext (status)); 3068 ldap_msgfree (res); 3069 return (0); 3070 } 3071 3072 host->name = ldap_get_host_name (ent); 3073 if (host->name == NULL) 3074 { 3075 host_dereference (&host, MDL); 3076 ldap_msgfree (res); 3077 return (0); 3078 } 3079 /* log_info ("Host name %s", host->name); */ 3080 3081 if (!clone_group (&host->group, root_group, MDL)) 3082 { 3083 log_fatal ("can't clone group for host %s", host->name); 3084 host_dereference (&host, MDL); 3085 ldap_msgfree (res); 3086 return (0); 3087 } 3088 3089 ldap_parse_options (ent, host->group, HOST_DECL, host, NULL); 3090 3091 *hp = host; 3092 ldap_msgfree (res); 3093 return (1); 3094 } 3095 else 3096 { 3097 log_info ("did not find clientid: %s", buf); 3098 } 3099 3100 if(res) ldap_msgfree (res); 3101 return (0); 3102 3103} 3104 3105#if defined(LDAP_USE_GSSAPI) 3106static int 3107_ldap_sasl_interact(LDAP *ld, unsigned flags, void *defaults, void *sin) 3108{ 3109 sasl_interact_t *in; 3110 struct ldap_sasl_instance *ldap_inst = defaults; 3111 int ret = LDAP_OTHER; 3112 size_t size; 3113 3114 if (ld == NULL || sin == NULL) 3115 return LDAP_PARAM_ERROR; 3116 3117 log_info("doing interactive bind"); 3118 for (in = sin; in != NULL && in->id != SASL_CB_LIST_END; in++) { 3119 switch (in->id) { 3120 case SASL_CB_USER: 3121 log_info("got request for SASL_CB_USER %s", ldap_inst->sasl_authz_id); 3122 size = strlen(ldap_inst->sasl_authz_id); 3123 in->result = ldap_inst->sasl_authz_id; 3124 in->len = size; 3125 ret = LDAP_SUCCESS; 3126 break; 3127 case SASL_CB_GETREALM: 3128 log_info("got request for SASL_CB_GETREALM %s", ldap_inst->sasl_realm); 3129 size = strlen(ldap_inst->sasl_realm); 3130 in->result = ldap_inst->sasl_realm; 3131 in->len = size; 3132 ret = LDAP_SUCCESS; 3133 break; 3134 case SASL_CB_AUTHNAME: 3135 log_info("got request for SASL_CB_AUTHNAME %s", ldap_inst->sasl_authc_id); 3136 size = strlen(ldap_inst->sasl_authc_id); 3137 in->result = ldap_inst->sasl_authc_id; 3138 in->len = size; 3139 ret = LDAP_SUCCESS; 3140 break; 3141 case SASL_CB_PASS: 3142 log_info("got request for SASL_CB_PASS %s", ldap_inst->sasl_password); 3143 size = strlen(ldap_inst->sasl_password); 3144 in->result = ldap_inst->sasl_password; 3145 in->len = size; 3146 ret = LDAP_SUCCESS; 3147 break; 3148 default: 3149 goto cleanup; 3150 } 3151 } 3152 return ret; 3153 3154cleanup: 3155 in->result = NULL; 3156 in->len = 0; 3157 return LDAP_OTHER; 3158} 3159#endif /* LDAP_USE_GSSAPI */ 3160 3161 3162#endif 3163