00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040 #include "dhcpd.h"
00041 #include <signal.h>
00042 #include <errno.h>
00043
00044 #if defined(LDAP_CONFIGURATION)
00045
00046 #if defined(LDAP_CASA_AUTH)
00047 #include "ldap_casa.h"
00048 #endif
00049
00050 static LDAP * ld = NULL;
00051 static char *ldap_server = NULL,
00052 *ldap_username = NULL,
00053 *ldap_password = NULL,
00054 *ldap_base_dn = NULL,
00055 *ldap_dhcp_server_cn = NULL,
00056 *ldap_debug_file = NULL;
00057 static int ldap_port = LDAP_PORT,
00058 ldap_method = LDAP_METHOD_DYNAMIC,
00059 ldap_referrals = -1,
00060 ldap_debug_fd = -1;
00061 #if defined (LDAP_USE_SSL)
00062 static int ldap_use_ssl = -1,
00063 ldap_tls_reqcert = -1,
00064 ldap_tls_crlcheck = -1;
00065 static char *ldap_tls_ca_file = NULL,
00066 *ldap_tls_ca_dir = NULL,
00067 *ldap_tls_cert = NULL,
00068 *ldap_tls_key = NULL,
00069 *ldap_tls_ciphers = NULL,
00070 *ldap_tls_randfile = NULL;
00071 #endif
00072 static struct ldap_config_stack *ldap_stack = NULL;
00073
00074 typedef struct ldap_dn_node {
00075 struct ldap_dn_node *next;
00076 size_t refs;
00077 char *dn;
00078 } ldap_dn_node;
00079
00080 static ldap_dn_node *ldap_service_dn_head = NULL;
00081 static ldap_dn_node *ldap_service_dn_tail = NULL;
00082
00083
00084 static char *
00085 x_strncat(char *dst, const char *src, size_t dst_size)
00086 {
00087 size_t len = strlen(dst);
00088 return strncat(dst, src, dst_size > len ? dst_size - len - 1: 0);
00089 }
00090
00091 static void
00092 ldap_parse_class (struct ldap_config_stack *item, struct parse *cfile)
00093 {
00094 struct berval **tempbv;
00095
00096 if ((tempbv = ldap_get_values_len (ld, item->ldent, "cn")) == NULL ||
00097 tempbv[0] == NULL)
00098 {
00099 if (tempbv != NULL)
00100 ldap_value_free_len (tempbv);
00101
00102 return;
00103 }
00104
00105 x_strncat (cfile->inbuf, "class \"", LDAP_BUFFER_SIZE);
00106 x_strncat (cfile->inbuf, tempbv[0]->bv_val, LDAP_BUFFER_SIZE);
00107 x_strncat (cfile->inbuf, "\" {\n", LDAP_BUFFER_SIZE);
00108
00109 item->close_brace = 1;
00110 ldap_value_free_len (tempbv);
00111 }
00112
00113
00114 static void
00115 ldap_parse_subclass (struct ldap_config_stack *item, struct parse *cfile)
00116 {
00117 struct berval **tempbv, **classdata;
00118
00119 if ((tempbv = ldap_get_values_len (ld, item->ldent, "cn")) == NULL ||
00120 tempbv[0] == NULL)
00121 {
00122 if (tempbv != NULL)
00123 ldap_value_free_len (tempbv);
00124
00125 return;
00126 }
00127
00128 if ((classdata = ldap_get_values_len (ld, item->ldent,
00129 "dhcpClassData")) == NULL ||
00130 classdata[0] == NULL)
00131 {
00132 if (classdata != NULL)
00133 ldap_value_free_len (classdata);
00134 ldap_value_free_len (tempbv);
00135
00136 return;
00137 }
00138
00139 x_strncat (cfile->inbuf, "subclass ", LDAP_BUFFER_SIZE);
00140 x_strncat (cfile->inbuf, classdata[0]->bv_val, LDAP_BUFFER_SIZE);
00141 x_strncat (cfile->inbuf, " ", LDAP_BUFFER_SIZE);
00142 x_strncat (cfile->inbuf, tempbv[0]->bv_val, LDAP_BUFFER_SIZE);
00143 x_strncat (cfile->inbuf, " {\n", LDAP_BUFFER_SIZE);
00144
00145 item->close_brace = 1;
00146 ldap_value_free_len (tempbv);
00147 ldap_value_free_len (classdata);
00148 }
00149
00150
00151 static void
00152 ldap_parse_host (struct ldap_config_stack *item, struct parse *cfile)
00153 {
00154 struct berval **tempbv, **hwaddr;
00155
00156 if ((tempbv = ldap_get_values_len (ld, item->ldent, "cn")) == NULL ||
00157 tempbv[0] == NULL)
00158 {
00159 if (tempbv != NULL)
00160 ldap_value_free_len (tempbv);
00161
00162 return;
00163 }
00164
00165 hwaddr = ldap_get_values_len (ld, item->ldent, "dhcpHWAddress");
00166
00167 x_strncat (cfile->inbuf, "host ", LDAP_BUFFER_SIZE);
00168 x_strncat (cfile->inbuf, tempbv[0]->bv_val, LDAP_BUFFER_SIZE);
00169
00170 if (hwaddr != NULL && hwaddr[0] != NULL)
00171 {
00172 x_strncat (cfile->inbuf, " {\nhardware ", LDAP_BUFFER_SIZE);
00173 x_strncat (cfile->inbuf, hwaddr[0]->bv_val, LDAP_BUFFER_SIZE);
00174 x_strncat (cfile->inbuf, ";\n", LDAP_BUFFER_SIZE);
00175 ldap_value_free_len (hwaddr);
00176 }
00177
00178 item->close_brace = 1;
00179 ldap_value_free_len (tempbv);
00180 }
00181
00182
00183 static void
00184 ldap_parse_shared_network (struct ldap_config_stack *item, struct parse *cfile)
00185 {
00186 struct berval **tempbv;
00187
00188 if ((tempbv = ldap_get_values_len (ld, item->ldent, "cn")) == NULL ||
00189 tempbv[0] == NULL)
00190 {
00191 if (tempbv != NULL)
00192 ldap_value_free_len (tempbv);
00193
00194 return;
00195 }
00196
00197 x_strncat (cfile->inbuf, "shared-network \"", LDAP_BUFFER_SIZE);
00198 x_strncat (cfile->inbuf, tempbv[0]->bv_val, LDAP_BUFFER_SIZE);
00199 x_strncat (cfile->inbuf, "\" {\n", LDAP_BUFFER_SIZE);
00200
00201 item->close_brace = 1;
00202 ldap_value_free_len (tempbv);
00203 }
00204
00205
00206 static void
00207 parse_netmask (int netmask, char *netmaskbuf)
00208 {
00209 unsigned long nm;
00210 int i;
00211
00212 nm = 0;
00213 for (i=1; i <= netmask; i++)
00214 {
00215 nm |= 1 << (32 - i);
00216 }
00217
00218 sprintf (netmaskbuf, "%d.%d.%d.%d", (int) (nm >> 24) & 0xff,
00219 (int) (nm >> 16) & 0xff,
00220 (int) (nm >> 8) & 0xff,
00221 (int) nm & 0xff);
00222 }
00223
00224
00225 static void
00226 ldap_parse_subnet (struct ldap_config_stack *item, struct parse *cfile)
00227 {
00228 struct berval **tempbv, **netmaskstr;
00229 char netmaskbuf[sizeof("255.255.255.255")];
00230 int i;
00231
00232 if ((tempbv = ldap_get_values_len (ld, item->ldent, "cn")) == NULL ||
00233 tempbv[0] == NULL)
00234 {
00235 if (tempbv != NULL)
00236 ldap_value_free_len (tempbv);
00237
00238 return;
00239 }
00240
00241 if ((netmaskstr = ldap_get_values_len (ld, item->ldent,
00242 "dhcpNetmask")) == NULL ||
00243 netmaskstr[0] == NULL)
00244 {
00245 if (netmaskstr != NULL)
00246 ldap_value_free_len (netmaskstr);
00247 ldap_value_free_len (tempbv);
00248
00249 return;
00250 }
00251
00252 x_strncat (cfile->inbuf, "subnet ", LDAP_BUFFER_SIZE);
00253 x_strncat (cfile->inbuf, tempbv[0]->bv_val, LDAP_BUFFER_SIZE);
00254
00255 x_strncat (cfile->inbuf, " netmask ", LDAP_BUFFER_SIZE);
00256 parse_netmask (strtol (netmaskstr[0]->bv_val, NULL, 10), netmaskbuf);
00257 x_strncat (cfile->inbuf, netmaskbuf, LDAP_BUFFER_SIZE);
00258
00259 x_strncat (cfile->inbuf, " {\n", LDAP_BUFFER_SIZE);
00260
00261 ldap_value_free_len (tempbv);
00262 ldap_value_free_len (netmaskstr);
00263
00264 if ((tempbv = ldap_get_values_len (ld, item->ldent, "dhcpRange")) != NULL)
00265 {
00266 for (i=0; tempbv[i] != NULL; i++)
00267 {
00268 x_strncat (cfile->inbuf, "range", LDAP_BUFFER_SIZE);
00269 x_strncat (cfile->inbuf, " ", LDAP_BUFFER_SIZE);
00270 x_strncat (cfile->inbuf, tempbv[i]->bv_val, LDAP_BUFFER_SIZE);
00271 x_strncat (cfile->inbuf, ";\n", LDAP_BUFFER_SIZE);
00272 }
00273 }
00274
00275 item->close_brace = 1;
00276 }
00277
00278
00279 static void
00280 ldap_parse_pool (struct ldap_config_stack *item, struct parse *cfile)
00281 {
00282 struct berval **tempbv;
00283 int i;
00284
00285 x_strncat (cfile->inbuf, "pool {\n", LDAP_BUFFER_SIZE);
00286
00287 if ((tempbv = ldap_get_values_len (ld, item->ldent, "dhcpRange")) != NULL)
00288 {
00289 x_strncat (cfile->inbuf, "range", LDAP_BUFFER_SIZE);
00290 for (i=0; tempbv[i] != NULL; i++)
00291 {
00292 x_strncat (cfile->inbuf, " ", LDAP_BUFFER_SIZE);
00293 x_strncat (cfile->inbuf, tempbv[i]->bv_val, LDAP_BUFFER_SIZE);
00294 }
00295 x_strncat (cfile->inbuf, ";\n", LDAP_BUFFER_SIZE);
00296 ldap_value_free_len (tempbv);
00297 }
00298
00299 if ((tempbv = ldap_get_values_len (ld, item->ldent, "dhcpPermitList")) != NULL)
00300 {
00301 for (i=0; tempbv[i] != NULL; i++)
00302 {
00303 x_strncat (cfile->inbuf, tempbv[i]->bv_val, LDAP_BUFFER_SIZE);
00304 x_strncat (cfile->inbuf, ";\n", LDAP_BUFFER_SIZE);
00305 }
00306 ldap_value_free_len (tempbv);
00307 }
00308
00309 item->close_brace = 1;
00310 }
00311
00312
00313 static void
00314 ldap_parse_group (struct ldap_config_stack *item, struct parse *cfile)
00315 {
00316 x_strncat (cfile->inbuf, "group {\n", LDAP_BUFFER_SIZE);
00317 item->close_brace = 1;
00318 }
00319
00320
00321 static void
00322 ldap_parse_key (struct ldap_config_stack *item, struct parse *cfile)
00323 {
00324 struct berval **tempbv;
00325
00326 if ((tempbv = ldap_get_values_len (ld, item->ldent, "cn")) != NULL)
00327 {
00328 x_strncat (cfile->inbuf, "key ", LDAP_BUFFER_SIZE);
00329 x_strncat (cfile->inbuf, tempbv[0]->bv_val, LDAP_BUFFER_SIZE);
00330 x_strncat (cfile->inbuf, " {\n", LDAP_BUFFER_SIZE);
00331 ldap_value_free_len (tempbv);
00332 }
00333
00334 if ((tempbv = ldap_get_values_len (ld, item->ldent, "dhcpKeyAlgorithm")) != NULL)
00335 {
00336 x_strncat (cfile->inbuf, "algorithm ", LDAP_BUFFER_SIZE);
00337 x_strncat (cfile->inbuf, tempbv[0]->bv_val, LDAP_BUFFER_SIZE);
00338 x_strncat (cfile->inbuf, ";\n", LDAP_BUFFER_SIZE);
00339 ldap_value_free_len (tempbv);
00340 }
00341
00342 if ((tempbv = ldap_get_values_len (ld, item->ldent, "dhcpKeySecret")) != NULL)
00343 {
00344 x_strncat (cfile->inbuf, "secret ", LDAP_BUFFER_SIZE);
00345 x_strncat (cfile->inbuf, tempbv[0]->bv_val, LDAP_BUFFER_SIZE);
00346 x_strncat (cfile->inbuf, ";\n", LDAP_BUFFER_SIZE);
00347 ldap_value_free_len (tempbv);
00348 }
00349
00350 item->close_brace = 1;
00351 }
00352
00353
00354 static void
00355 ldap_parse_zone (struct ldap_config_stack *item, struct parse *cfile)
00356 {
00357 char *cnFindStart, *cnFindEnd;
00358 struct berval **tempbv;
00359 char *keyCn;
00360 size_t len;
00361
00362 if ((tempbv = ldap_get_values_len (ld, item->ldent, "cn")) != NULL)
00363 {
00364 x_strncat (cfile->inbuf, "zone ", LDAP_BUFFER_SIZE);
00365 x_strncat (cfile->inbuf, tempbv[0]->bv_val, LDAP_BUFFER_SIZE);
00366 x_strncat (cfile->inbuf, " {\n", LDAP_BUFFER_SIZE);
00367 ldap_value_free_len (tempbv);
00368 }
00369
00370 if ((tempbv = ldap_get_values_len (ld, item->ldent, "dhcpDnsZoneServer")) != NULL)
00371 {
00372 x_strncat (cfile->inbuf, "primary ", LDAP_BUFFER_SIZE);
00373 x_strncat (cfile->inbuf, tempbv[0]->bv_val, LDAP_BUFFER_SIZE);
00374
00375 x_strncat (cfile->inbuf, ";\n", LDAP_BUFFER_SIZE);
00376 ldap_value_free_len (tempbv);
00377 }
00378
00379 if ((tempbv = ldap_get_values_len (ld, item->ldent, "dhcpKeyDN")) != NULL)
00380 {
00381 cnFindStart = strchr(tempbv[0]->bv_val,'=');
00382 if (cnFindStart != NULL)
00383 cnFindEnd = strchr(++cnFindStart,',');
00384 else
00385 cnFindEnd = NULL;
00386
00387 if (cnFindEnd != NULL && cnFindEnd > cnFindStart)
00388 {
00389 len = cnFindEnd - cnFindStart;
00390 keyCn = dmalloc (len + 1, MDL);
00391 }
00392 else
00393 {
00394 len = 0;
00395 keyCn = NULL;
00396 }
00397
00398 if (keyCn != NULL)
00399 {
00400 strncpy (keyCn, cnFindStart, len);
00401 keyCn[len] = '\0';
00402
00403 x_strncat (cfile->inbuf, "key ", LDAP_BUFFER_SIZE);
00404 x_strncat (cfile->inbuf, keyCn, LDAP_BUFFER_SIZE);
00405 x_strncat (cfile->inbuf, ";\n", LDAP_BUFFER_SIZE);
00406
00407 dfree (keyCn, MDL);
00408 }
00409
00410 ldap_value_free_len (tempbv);
00411 }
00412
00413 item->close_brace = 1;
00414 }
00415
00416
00417 static void
00418 add_to_config_stack (LDAPMessage * res, LDAPMessage * ent)
00419 {
00420 struct ldap_config_stack *ns;
00421
00422 ns = dmalloc (sizeof (*ns), MDL);
00423 ns->res = res;
00424 ns->ldent = ent;
00425 ns->close_brace = 0;
00426 ns->processed = 0;
00427 ns->next = ldap_stack;
00428 ldap_stack = ns;
00429 }
00430
00431
00432 static void
00433 ldap_stop()
00434 {
00435 struct sigaction old, new;
00436
00437 if (ld == NULL)
00438 return;
00439
00440
00441
00442
00443
00444
00445
00446 new.sa_flags = 0;
00447 new.sa_handler = SIG_IGN;
00448 sigemptyset (&new.sa_mask);
00449 sigaction (SIGPIPE, &new, &old);
00450
00451 ldap_unbind_ext_s (ld, NULL, NULL);
00452 ld = NULL;
00453
00454 sigaction (SIGPIPE, &old, &new);
00455 }
00456
00457
00458 static char *
00459 _do_lookup_dhcp_string_option (struct option_state *options, int option_name)
00460 {
00461 struct option_cache *oc;
00462 struct data_string db;
00463 char *ret;
00464
00465 memset (&db, 0, sizeof (db));
00466 oc = lookup_option (&server_universe, options, option_name);
00467 if (oc &&
00468 evaluate_option_cache (&db, (struct packet*) NULL,
00469 (struct lease *) NULL,
00470 (struct client_state *) NULL, options,
00471 (struct option_state *) NULL,
00472 &global_scope, oc, MDL) &&
00473 db.data != NULL && *db.data != '\0')
00474
00475 {
00476 ret = dmalloc (db.len + 1, MDL);
00477 if (ret == NULL)
00478 log_fatal ("no memory for ldap option %d value", option_name);
00479
00480 memcpy (ret, db.data, db.len);
00481 ret[db.len] = 0;
00482 data_string_forget (&db, MDL);
00483 }
00484 else
00485 ret = NULL;
00486
00487 return (ret);
00488 }
00489
00490
00491 static int
00492 _do_lookup_dhcp_int_option (struct option_state *options, int option_name)
00493 {
00494 struct option_cache *oc;
00495 struct data_string db;
00496 int ret;
00497
00498 memset (&db, 0, sizeof (db));
00499 oc = lookup_option (&server_universe, options, option_name);
00500 if (oc &&
00501 evaluate_option_cache (&db, (struct packet*) NULL,
00502 (struct lease *) NULL,
00503 (struct client_state *) NULL, options,
00504 (struct option_state *) NULL,
00505 &global_scope, oc, MDL) &&
00506 db.data != NULL && *db.data != '\0')
00507 {
00508 ret = strtol ((const char *) db.data, NULL, 10);
00509 data_string_forget (&db, MDL);
00510 }
00511 else
00512 ret = 0;
00513
00514 return (ret);
00515 }
00516
00517
00518 static int
00519 _do_lookup_dhcp_enum_option (struct option_state *options, int option_name)
00520 {
00521 struct option_cache *oc;
00522 struct data_string db;
00523 int ret = -1;
00524
00525 memset (&db, 0, sizeof (db));
00526 oc = lookup_option (&server_universe, options, option_name);
00527 if (oc &&
00528 evaluate_option_cache (&db, (struct packet*) NULL,
00529 (struct lease *) NULL,
00530 (struct client_state *) NULL, options,
00531 (struct option_state *) NULL,
00532 &global_scope, oc, MDL) &&
00533 db.data != NULL && *db.data != '\0')
00534 {
00535 if (db.len == 1)
00536 ret = db.data [0];
00537 else
00538 log_fatal ("invalid option name %d", option_name);
00539
00540 data_string_forget (&db, MDL);
00541 }
00542 else
00543 ret = 0;
00544
00545 return (ret);
00546 }
00547
00548 int
00549 ldap_rebind_cb (LDAP *ld, LDAP_CONST char *url, ber_tag_t request, ber_int_t msgid, void *parms)
00550 {
00551 int ret;
00552 LDAPURLDesc *ldapurl = NULL;
00553 char *who = NULL;
00554 struct berval creds;
00555
00556 log_info("LDAP rebind to '%s'", url);
00557 if ((ret = ldap_url_parse(url, &ldapurl)) != LDAP_SUCCESS)
00558 {
00559 log_error ("Error: Can not parse ldap rebind url '%s': %s",
00560 url, ldap_err2string(ret));
00561 return ret;
00562 }
00563
00564
00565 #if defined (LDAP_USE_SSL)
00566 if (strcasecmp(ldapurl->lud_scheme, "ldaps") == 0)
00567 {
00568 int opt = LDAP_OPT_X_TLS_HARD;
00569 if ((ret = ldap_set_option (ld, LDAP_OPT_X_TLS, &opt)) != LDAP_SUCCESS)
00570 {
00571 log_error ("Error: Cannot init LDAPS session to %s:%d: %s",
00572 ldapurl->lud_host, ldapurl->lud_port, ldap_err2string (ret));
00573 return ret;
00574 }
00575 else
00576 {
00577 log_info ("LDAPS session successfully enabled to %s", ldap_server);
00578 }
00579 }
00580 else
00581 if (strcasecmp(ldapurl->lud_scheme, "ldap") == 0 &&
00582 ldap_use_ssl != LDAP_SSL_OFF)
00583 {
00584 if ((ret = ldap_start_tls_s (ld, NULL, NULL)) != LDAP_SUCCESS)
00585 {
00586 log_error ("Error: Cannot start TLS session to %s:%d: %s",
00587 ldapurl->lud_host, ldapurl->lud_port, ldap_err2string (ret));
00588 return ret;
00589 }
00590 else
00591 {
00592 log_info ("TLS session successfully started to %s:%d",
00593 ldapurl->lud_host, ldapurl->lud_port);
00594 }
00595 }
00596 #endif
00597
00598
00599 if (ldap_username != NULL || *ldap_username != '\0')
00600 {
00601 who = ldap_username;
00602 creds.bv_val = strdup(ldap_password);
00603 creds.bv_len = strlen(ldap_password);
00604 }
00605
00606 if ((ret = ldap_sasl_bind_s (ld, who, LDAP_SASL_SIMPLE, &creds,
00607 NULL, NULL, NULL)) != LDAP_SUCCESS)
00608 {
00609 log_error ("Error: Cannot login into ldap server %s:%d: %s",
00610 ldapurl->lud_host, ldapurl->lud_port, ldap_err2string (ret));
00611 }
00612 return ret;
00613 }
00614
00615 static void
00616 ldap_start (void)
00617 {
00618 struct option_state *options;
00619 int ret, version;
00620 char *uri = NULL;
00621 struct berval creds;
00622
00623 if (ld != NULL)
00624 return;
00625
00626 if (ldap_server == NULL)
00627 {
00628 options = NULL;
00629 option_state_allocate (&options, MDL);
00630
00631 execute_statements_in_scope (NULL, NULL, NULL, NULL, NULL,
00632 options, &global_scope, root_group,
00633 NULL, NULL);
00634
00635 ldap_server = _do_lookup_dhcp_string_option (options, SV_LDAP_SERVER);
00636 ldap_dhcp_server_cn = _do_lookup_dhcp_string_option (options,
00637 SV_LDAP_DHCP_SERVER_CN);
00638 ldap_port = _do_lookup_dhcp_int_option (options, SV_LDAP_PORT);
00639 ldap_base_dn = _do_lookup_dhcp_string_option (options, SV_LDAP_BASE_DN);
00640 ldap_method = _do_lookup_dhcp_enum_option (options, SV_LDAP_METHOD);
00641 ldap_debug_file = _do_lookup_dhcp_string_option (options,
00642 SV_LDAP_DEBUG_FILE);
00643 ldap_referrals = _do_lookup_dhcp_enum_option (options, SV_LDAP_REFERRALS);
00644
00645 #if defined (LDAP_USE_SSL)
00646 ldap_use_ssl = _do_lookup_dhcp_enum_option (options, SV_LDAP_SSL);
00647 if( ldap_use_ssl != LDAP_SSL_OFF)
00648 {
00649 ldap_tls_reqcert = _do_lookup_dhcp_enum_option (options, SV_LDAP_TLS_REQCERT);
00650 ldap_tls_ca_file = _do_lookup_dhcp_string_option (options, SV_LDAP_TLS_CA_FILE);
00651 ldap_tls_ca_dir = _do_lookup_dhcp_string_option (options, SV_LDAP_TLS_CA_DIR);
00652 ldap_tls_cert = _do_lookup_dhcp_string_option (options, SV_LDAP_TLS_CERT);
00653 ldap_tls_key = _do_lookup_dhcp_string_option (options, SV_LDAP_TLS_KEY);
00654 ldap_tls_crlcheck = _do_lookup_dhcp_enum_option (options, SV_LDAP_TLS_CRLCHECK);
00655 ldap_tls_ciphers = _do_lookup_dhcp_string_option (options, SV_LDAP_TLS_CIPHERS);
00656 ldap_tls_randfile = _do_lookup_dhcp_string_option (options, SV_LDAP_TLS_RANDFILE);
00657 }
00658 #endif
00659
00660 #if defined (LDAP_CASA_AUTH)
00661 if (!load_uname_pwd_from_miCASA(&ldap_username,&ldap_password))
00662 {
00663 #if defined (DEBUG_LDAP)
00664 log_info ("Authentication credential taken from file");
00665 #endif
00666 #endif
00667
00668 ldap_username = _do_lookup_dhcp_string_option (options, SV_LDAP_USERNAME);
00669 ldap_password = _do_lookup_dhcp_string_option (options, SV_LDAP_PASSWORD);
00670
00671 #if defined (LDAP_CASA_AUTH)
00672 }
00673 #endif
00674
00675 option_state_dereference (&options, MDL);
00676 }
00677
00678 if (ldap_server == NULL || ldap_base_dn == NULL)
00679 {
00680 log_info ("Not searching LDAP since ldap-server, ldap-port and ldap-base-dn were not specified in the config file");
00681 ldap_method = LDAP_METHOD_STATIC;
00682 return;
00683 }
00684
00685 if (ldap_debug_file != NULL && ldap_debug_fd == -1)
00686 {
00687 if ((ldap_debug_fd = open (ldap_debug_file, O_CREAT | O_TRUNC | O_WRONLY | O_CLOEXEC,
00688 S_IRUSR | S_IWUSR)) < 0)
00689 log_error ("Error opening debug LDAP log file %s: %s", ldap_debug_file,
00690 strerror (errno));
00691 }
00692
00693 #if defined (DEBUG_LDAP)
00694 log_info ("Connecting to LDAP server %s:%d", ldap_server, ldap_port);
00695 #endif
00696
00697 #if defined (LDAP_USE_SSL)
00698 if (ldap_use_ssl == -1)
00699 {
00700
00701
00702
00703
00704
00705 int opt = LDAP_OPT_X_TLS_ALLOW;
00706 if ((ret = ldap_set_option (NULL, LDAP_OPT_X_TLS_REQUIRE_CERT,
00707 &opt)) != LDAP_SUCCESS)
00708 {
00709 log_error ("Warning: Cannot set LDAP TLS require cert option to 'allow': %s",
00710 ldap_err2string (ret));
00711 }
00712 }
00713
00714 if (ldap_use_ssl != LDAP_SSL_OFF)
00715 {
00716 if (ldap_tls_reqcert != -1)
00717 {
00718 if ((ret = ldap_set_option (NULL, LDAP_OPT_X_TLS_REQUIRE_CERT,
00719 &ldap_tls_reqcert)) != LDAP_SUCCESS)
00720 {
00721 log_error ("Cannot set LDAP TLS require cert option: %s",
00722 ldap_err2string (ret));
00723 }
00724 }
00725
00726 if( ldap_tls_ca_file != NULL)
00727 {
00728 if ((ret = ldap_set_option (NULL, LDAP_OPT_X_TLS_CACERTFILE,
00729 ldap_tls_ca_file)) != LDAP_SUCCESS)
00730 {
00731 log_error ("Cannot set LDAP TLS CA certificate file %s: %s",
00732 ldap_tls_ca_file, ldap_err2string (ret));
00733 }
00734 }
00735 if( ldap_tls_ca_dir != NULL)
00736 {
00737 if ((ret = ldap_set_option (NULL, LDAP_OPT_X_TLS_CACERTDIR,
00738 ldap_tls_ca_dir)) != LDAP_SUCCESS)
00739 {
00740 log_error ("Cannot set LDAP TLS CA certificate dir %s: %s",
00741 ldap_tls_ca_dir, ldap_err2string (ret));
00742 }
00743 }
00744 if( ldap_tls_cert != NULL)
00745 {
00746 if ((ret = ldap_set_option (NULL, LDAP_OPT_X_TLS_CERTFILE,
00747 ldap_tls_cert)) != LDAP_SUCCESS)
00748 {
00749 log_error ("Cannot set LDAP TLS client certificate file %s: %s",
00750 ldap_tls_cert, ldap_err2string (ret));
00751 }
00752 }
00753 if( ldap_tls_key != NULL)
00754 {
00755 if ((ret = ldap_set_option (NULL, LDAP_OPT_X_TLS_KEYFILE,
00756 ldap_tls_key)) != LDAP_SUCCESS)
00757 {
00758 log_error ("Cannot set LDAP TLS certificate key file %s: %s",
00759 ldap_tls_key, ldap_err2string (ret));
00760 }
00761 }
00762 if( ldap_tls_crlcheck != -1)
00763 {
00764 int opt = ldap_tls_crlcheck;
00765 if ((ret = ldap_set_option (NULL, LDAP_OPT_X_TLS_CRLCHECK,
00766 &opt)) != LDAP_SUCCESS)
00767 {
00768 log_error ("Cannot set LDAP TLS crl check option: %s",
00769 ldap_err2string (ret));
00770 }
00771 }
00772 if( ldap_tls_ciphers != NULL)
00773 {
00774 if ((ret = ldap_set_option (NULL, LDAP_OPT_X_TLS_CIPHER_SUITE,
00775 ldap_tls_ciphers)) != LDAP_SUCCESS)
00776 {
00777 log_error ("Cannot set LDAP TLS cipher suite %s: %s",
00778 ldap_tls_ciphers, ldap_err2string (ret));
00779 }
00780 }
00781 if( ldap_tls_randfile != NULL)
00782 {
00783 if ((ret = ldap_set_option (NULL, LDAP_OPT_X_TLS_RANDOM_FILE,
00784 ldap_tls_randfile)) != LDAP_SUCCESS)
00785 {
00786 log_error ("Cannot set LDAP TLS random file %s: %s",
00787 ldap_tls_randfile, ldap_err2string (ret));
00788 }
00789 }
00790 }
00791 #endif
00792
00793
00794 uri = malloc(strlen(ldap_server) + 16);
00795 if (uri == NULL)
00796 {
00797 log_error ("Cannot build ldap init URI %s:%d", ldap_server, ldap_port);
00798 return;
00799 }
00800
00801 sprintf(uri, "ldap://%s:%d", ldap_server, ldap_port);
00802 ldap_initialize(&ld, uri);
00803
00804 if (ld == NULL)
00805 {
00806 log_error ("Cannot init ldap session to %s:%d", ldap_server, ldap_port);
00807 return;
00808 }
00809
00810 free(uri);
00811
00812 version = LDAP_VERSION3;
00813 if ((ret = ldap_set_option (ld, LDAP_OPT_PROTOCOL_VERSION, &version)) != LDAP_OPT_SUCCESS)
00814 {
00815 log_error ("Cannot set LDAP version to %d: %s", version,
00816 ldap_err2string (ret));
00817 }
00818
00819 if (ldap_referrals != -1)
00820 {
00821 if ((ret = ldap_set_option (ld, LDAP_OPT_REFERRALS, ldap_referrals ?
00822 LDAP_OPT_ON : LDAP_OPT_OFF)) != LDAP_OPT_SUCCESS)
00823 {
00824 log_error ("Cannot %s LDAP referrals option: %s",
00825 (ldap_referrals ? "enable" : "disable"),
00826 ldap_err2string (ret));
00827 }
00828 }
00829
00830 if ((ret = ldap_set_rebind_proc(ld, ldap_rebind_cb, NULL)) != LDAP_SUCCESS)
00831 {
00832 log_error ("Warning: Cannot set ldap rebind procedure: %s",
00833 ldap_err2string (ret));
00834 }
00835
00836 #if defined (LDAP_USE_SSL)
00837 if (ldap_use_ssl == LDAP_SSL_LDAPS ||
00838 (ldap_use_ssl == LDAP_SSL_ON && ldap_port == LDAPS_PORT))
00839 {
00840 int opt = LDAP_OPT_X_TLS_HARD;
00841 if ((ret = ldap_set_option (ld, LDAP_OPT_X_TLS, &opt)) != LDAP_SUCCESS)
00842 {
00843 log_error ("Error: Cannot init LDAPS session to %s:%d: %s",
00844 ldap_server, ldap_port, ldap_err2string (ret));
00845 ldap_stop();
00846 return;
00847 }
00848 else
00849 {
00850 log_info ("LDAPS session successfully enabled to %s:%d",
00851 ldap_server, ldap_port);
00852 }
00853 }
00854 else if (ldap_use_ssl != LDAP_SSL_OFF)
00855 {
00856 if ((ret = ldap_start_tls_s (ld, NULL, NULL)) != LDAP_SUCCESS)
00857 {
00858 log_error ("Error: Cannot start TLS session to %s:%d: %s",
00859 ldap_server, ldap_port, ldap_err2string (ret));
00860 ldap_stop();
00861 return;
00862 }
00863 else
00864 {
00865 log_info ("TLS session successfully started to %s:%d",
00866 ldap_server, ldap_port);
00867 }
00868 }
00869 #endif
00870
00871 if (ldap_username != NULL && *ldap_username != '\0')
00872 {
00873 creds.bv_val = strdup(ldap_password);
00874 creds.bv_len = strlen(ldap_password);
00875
00876 if ((ret = ldap_sasl_bind_s (ld, ldap_username, LDAP_SASL_SIMPLE,
00877 &creds, NULL, NULL, NULL)) != LDAP_SUCCESS)
00878 {
00879 log_error ("Error: Cannot login into ldap server %s:%d: %s",
00880 ldap_server, ldap_port, ldap_err2string (ret));
00881 ldap_stop();
00882 return;
00883 }
00884 }
00885
00886 #if defined (DEBUG_LDAP)
00887 log_info ("Successfully logged into LDAP server %s", ldap_server);
00888 #endif
00889 }
00890
00891
00892 static void
00893 parse_external_dns (LDAPMessage * ent)
00894 {
00895 char *search[] = {"dhcpFailOverPeerDN", "dhcpOptionsDN", "dhcpSharedNetworkDN", "dhcpSubnetDN",
00896 "dhcpGroupDN", "dhcpHostDN", "dhcpClassesDN",
00897 "dhcpPoolDN", NULL};
00898 LDAPMessage * newres, * newent;
00899 struct berval **tempbv;
00900 int i, j, ret;
00901 #if defined (DEBUG_LDAP)
00902 char *dn;
00903
00904 dn = ldap_get_dn (ld, ent);
00905 if (dn != NULL)
00906 {
00907 log_info ("Parsing external DNs for '%s'", dn);
00908 ldap_memfree (dn);
00909 }
00910 #endif
00911
00912 if (ld == NULL)
00913 ldap_start ();
00914 if (ld == NULL)
00915 return;
00916
00917 for (i=0; search[i] != NULL; i++)
00918 {
00919 if ((tempbv = ldap_get_values_len (ld, ent, search[i])) == NULL)
00920 continue;
00921
00922 for (j=0; tempbv[j] != NULL; j++)
00923 {
00924 if (*tempbv[j]->bv_val == '\0')
00925 continue;
00926
00927 if ((ret = ldap_search_ext_s(ld, tempbv[j]->bv_val, LDAP_SCOPE_BASE,
00928 "objectClass=*", NULL, 0, NULL,
00929 NULL, NULL, 0, &newres)) != LDAP_SUCCESS)
00930 {
00931 ldap_value_free_len (tempbv);
00932 ldap_stop();
00933 return;
00934 }
00935
00936 #if defined (DEBUG_LDAP)
00937 log_info ("Adding contents of subtree '%s' to config stack from '%s' reference", tempbv[j], search[i]);
00938 #endif
00939 for (newent = ldap_first_entry (ld, newres);
00940 newent != NULL;
00941 newent = ldap_next_entry (ld, newent))
00942 {
00943 #if defined (DEBUG_LDAP)
00944 dn = ldap_get_dn (ld, newent);
00945 if (dn != NULL)
00946 {
00947 log_info ("Adding LDAP result set starting with '%s' to config stack", dn);
00948 ldap_memfree (dn);
00949 }
00950 #endif
00951
00952 add_to_config_stack (newres, newent);
00953
00954 }
00955 }
00956
00957 ldap_value_free_len (tempbv);
00958 }
00959 }
00960
00961
00962 static void
00963 free_stack_entry (struct ldap_config_stack *item)
00964 {
00965 struct ldap_config_stack *look_ahead_pointer = item;
00966 int may_free_msg = 1;
00967
00968 while (look_ahead_pointer->next != NULL)
00969 {
00970 look_ahead_pointer = look_ahead_pointer->next;
00971 if (look_ahead_pointer->res == item->res)
00972 {
00973 may_free_msg = 0;
00974 break;
00975 }
00976 }
00977
00978 if (may_free_msg)
00979 ldap_msgfree (item->res);
00980
00981 dfree (item, MDL);
00982 }
00983
00984
00985 static void
00986 next_ldap_entry (struct parse *cfile)
00987 {
00988 struct ldap_config_stack *temp_stack;
00989
00990 if (ldap_stack != NULL && ldap_stack->close_brace)
00991 {
00992 x_strncat (cfile->inbuf, "}\n", LDAP_BUFFER_SIZE);
00993 ldap_stack->close_brace = 0;
00994 }
00995
00996 while (ldap_stack != NULL &&
00997 (ldap_stack->ldent == NULL ||
00998 (ldap_stack->ldent = ldap_next_entry (ld, ldap_stack->ldent)) == NULL))
00999 {
01000 if (ldap_stack->close_brace)
01001 {
01002 x_strncat (cfile->inbuf, "}\n", LDAP_BUFFER_SIZE);
01003 ldap_stack->close_brace = 0;
01004 }
01005
01006 temp_stack = ldap_stack;
01007 ldap_stack = ldap_stack->next;
01008 free_stack_entry (temp_stack);
01009 }
01010
01011 if (ldap_stack != NULL && ldap_stack->close_brace)
01012 {
01013 x_strncat (cfile->inbuf, "}\n", LDAP_BUFFER_SIZE);
01014 ldap_stack->close_brace = 0;
01015 }
01016 }
01017
01018
01019 static char
01020 check_statement_end (const char *statement)
01021 {
01022 char *ptr;
01023
01024 if (statement == NULL || *statement == '\0')
01025 return ('\0');
01026
01027
01028
01029
01030
01031
01032 ptr = strrchr (statement, '}');
01033 if (ptr != NULL)
01034 {
01035
01036 for (++ptr; isspace ((int)*ptr); ptr++);
01037
01038
01039 if (*ptr == '\0')
01040 return ('}');
01041 else
01042 return (*ptr);
01043 }
01044
01045
01046
01047
01048
01049
01050
01051 ptr = strrchr (statement, ';');
01052 if (ptr != NULL)
01053 {
01054
01055 for (++ptr; isspace ((int)*ptr); ptr++);
01056
01057
01058 if (*ptr == '\0')
01059 return (';');
01060 else
01061 return (*ptr);
01062 }
01063
01064 return ('\0');
01065 }
01066
01067
01068 static isc_result_t
01069 ldap_parse_entry_options (LDAPMessage *ent, char *buffer, size_t size,
01070 int *lease_limit)
01071 {
01072 struct berval **tempbv;
01073 int i;
01074
01075 if (ent == NULL || buffer == NULL || size == 0)
01076 return (ISC_R_FAILURE);
01077
01078 if ((tempbv = ldap_get_values_len (ld, ent, "dhcpStatements")) != NULL)
01079 {
01080 for (i=0; tempbv[i] != NULL; i++)
01081 {
01082 if (lease_limit != NULL &&
01083 strncasecmp ("lease limit ", tempbv[i]->bv_val, 12) == 0)
01084 {
01085 *lease_limit = (int) strtol ((tempbv[i]->bv_val) + 12, NULL, 10);
01086 continue;
01087 }
01088
01089 x_strncat (buffer, tempbv[i]->bv_val, size);
01090
01091 switch((int) check_statement_end (tempbv[i]->bv_val))
01092 {
01093 case '}':
01094 case ';':
01095 x_strncat (buffer, "\n", size);
01096 break;
01097 default:
01098 x_strncat (buffer, ";\n", size);
01099 break;
01100 }
01101 }
01102 ldap_value_free_len (tempbv);
01103 }
01104
01105 if ((tempbv = ldap_get_values_len (ld, ent, "dhcpOption")) != NULL)
01106 {
01107 for (i=0; tempbv[i] != NULL; i++)
01108 {
01109 x_strncat (buffer, "option ", size);
01110 x_strncat (buffer, tempbv[i]->bv_val, size);
01111 switch ((int) check_statement_end (tempbv[i]->bv_val))
01112 {
01113 case ';':
01114 x_strncat (buffer, "\n", size);
01115 break;
01116 default:
01117 x_strncat (buffer, ";\n", size);
01118 break;
01119 }
01120 }
01121 ldap_value_free_len (tempbv);
01122 }
01123
01124 return (ISC_R_SUCCESS);
01125 }
01126
01127
01128 static void
01129 ldap_generate_config_string (struct parse *cfile)
01130 {
01131 struct berval **objectClass;
01132 char *dn;
01133 struct ldap_config_stack *entry;
01134 LDAPMessage * ent, * res;
01135 int i, ignore, found;
01136 int ret;
01137
01138 if (ld == NULL)
01139 ldap_start ();
01140 if (ld == NULL)
01141 return;
01142
01143 entry = ldap_stack;
01144 if ((objectClass = ldap_get_values_len (ld, entry->ldent,
01145 "objectClass")) == NULL)
01146 return;
01147
01148 ignore = 0;
01149 found = 1;
01150 for (i=0; objectClass[i] != NULL; i++)
01151 {
01152 if (strcasecmp (objectClass[i]->bv_val, "dhcpSharedNetwork") == 0)
01153 ldap_parse_shared_network (entry, cfile);
01154 else if (strcasecmp (objectClass[i]->bv_val, "dhcpClass") == 0)
01155 ldap_parse_class (entry, cfile);
01156 else if (strcasecmp (objectClass[i]->bv_val, "dhcpSubnet") == 0)
01157 ldap_parse_subnet (entry, cfile);
01158 else if (strcasecmp (objectClass[i]->bv_val, "dhcpPool") == 0)
01159 ldap_parse_pool (entry, cfile);
01160 else if (strcasecmp (objectClass[i]->bv_val, "dhcpGroup") == 0)
01161 ldap_parse_group (entry, cfile);
01162 else if (strcasecmp (objectClass[i]->bv_val, "dhcpTSigKey") == 0)
01163 ldap_parse_key (entry, cfile);
01164 else if (strcasecmp (objectClass[i]->bv_val, "dhcpDnsZone") == 0)
01165 ldap_parse_zone (entry, cfile);
01166 else if (strcasecmp (objectClass[i]->bv_val, "dhcpHost") == 0)
01167 {
01168 if (ldap_method == LDAP_METHOD_STATIC)
01169 ldap_parse_host (entry, cfile);
01170 else
01171 {
01172 ignore = 1;
01173 break;
01174 }
01175 }
01176 else if (strcasecmp (objectClass[i]->bv_val, "dhcpSubClass") == 0)
01177 {
01178 if (ldap_method == LDAP_METHOD_STATIC)
01179 ldap_parse_subclass (entry, cfile);
01180 else
01181 {
01182 ignore = 1;
01183 break;
01184 }
01185 }
01186 else
01187 found = 0;
01188
01189 if (found && cfile->inbuf[0] == '\0')
01190 {
01191 ignore = 1;
01192 break;
01193 }
01194 }
01195
01196 ldap_value_free_len (objectClass);
01197
01198 if (ignore)
01199 {
01200 next_ldap_entry (cfile);
01201 return;
01202 }
01203
01204 ldap_parse_entry_options(entry->ldent, cfile->inbuf,
01205 LDAP_BUFFER_SIZE-1, NULL);
01206
01207 dn = ldap_get_dn (ld, entry->ldent);
01208
01209 #if defined(DEBUG_LDAP)
01210 if (dn != NULL)
01211 log_info ("Found LDAP entry '%s'", dn);
01212 #endif
01213
01214 if (dn == NULL ||
01215 (ret = ldap_search_ext_s (ld, dn, LDAP_SCOPE_ONELEVEL,
01216 "objectClass=*", NULL, 0, NULL, NULL,
01217 NULL, 0, &res)) != LDAP_SUCCESS)
01218 {
01219 if (dn)
01220 ldap_memfree (dn);
01221
01222 ldap_stop();
01223 return;
01224 }
01225
01226 ldap_memfree (dn);
01227
01228 if ((ent = ldap_first_entry (ld, res)) != NULL)
01229 {
01230 add_to_config_stack (res, ent);
01231 parse_external_dns (entry->ldent);
01232 }
01233 else
01234 {
01235 ldap_msgfree (res);
01236 parse_external_dns (entry->ldent);
01237 next_ldap_entry (cfile);
01238 }
01239 }
01240
01241
01242 static void
01243 ldap_close_debug_fd()
01244 {
01245 if (ldap_debug_fd != -1)
01246 {
01247 close (ldap_debug_fd);
01248 ldap_debug_fd = -1;
01249 }
01250 }
01251
01252
01253 static void
01254 ldap_write_debug (const void *buff, size_t size)
01255 {
01256 if (ldap_debug_fd != -1)
01257 {
01258 if (write (ldap_debug_fd, buff, size) < 0)
01259 {
01260 log_error ("Error writing to LDAP debug file %s: %s."
01261 " Disabling log file.", ldap_debug_file,
01262 strerror (errno));
01263 ldap_close_debug_fd();
01264 }
01265 }
01266 }
01267
01268 static int
01269 ldap_read_function (struct parse *cfile)
01270 {
01271 cfile->inbuf[0] = '\0';
01272 cfile->buflen = 0;
01273
01274 while (ldap_stack != NULL && *cfile->inbuf == '\0')
01275 ldap_generate_config_string (cfile);
01276
01277 if (ldap_stack == NULL && *cfile->inbuf == '\0')
01278 return (EOF);
01279
01280 cfile->bufix = 1;
01281 cfile->buflen = strlen (cfile->inbuf) - 1;
01282 if (cfile->buflen > 0)
01283 ldap_write_debug (cfile->inbuf, cfile->buflen);
01284
01285 #if defined (DEBUG_LDAP)
01286 log_info ("Sending config line '%s'", cfile->inbuf);
01287 #endif
01288
01289 return (cfile->inbuf[0]);
01290 }
01291
01292
01293 static char *
01294 ldap_get_host_name (LDAPMessage * ent)
01295 {
01296 struct berval **name;
01297 char *ret;
01298
01299 ret = NULL;
01300 if ((name = ldap_get_values_len (ld, ent, "cn")) == NULL || name[0] == NULL)
01301 {
01302 if (name != NULL)
01303 ldap_value_free_len (name);
01304
01305 #if defined (DEBUG_LDAP)
01306 ret = ldap_get_dn (ld, ent);
01307 if (ret != NULL)
01308 {
01309 log_info ("Cannot get cn attribute for LDAP entry %s", ret);
01310 ldap_memfree(ret);
01311 }
01312 #endif
01313 return (NULL);
01314 }
01315
01316 ret = dmalloc (strlen (name[0]->bv_val) + 1, MDL);
01317 strcpy (ret, name[0]->bv_val);
01318 ldap_value_free_len (name);
01319
01320 return (ret);
01321 }
01322
01323
01324 static int
01325 getfqhostname(char *fqhost, size_t size)
01326 {
01327 #if defined(MAXHOSTNAMELEN)
01328 char hname[MAXHOSTNAMELEN];
01329 #else
01330 char hname[65];
01331 #endif
01332 struct hostent *hp;
01333
01334 if(NULL == fqhost || 1 >= size)
01335 return -1;
01336
01337 memset(hname, 0, sizeof(hname));
01338 if( gethostname(hname, sizeof(hname)-1))
01339 return -1;
01340
01341 if(NULL == (hp = gethostbyname(hname)))
01342 return -1;
01343
01344 strncpy(fqhost, hp->h_name, size-1);
01345 fqhost[size-1] = '\0';
01346 return 0;
01347 }
01348
01349
01350 isc_result_t
01351 ldap_read_config (void)
01352 {
01353 LDAPMessage * ldres, * hostres, * ent, * hostent;
01354 char hfilter[1024], sfilter[1024], fqdn[257];
01355 char *buffer, *hostdn;
01356 ldap_dn_node *curr = NULL;
01357 struct parse *cfile;
01358 struct utsname unme;
01359 isc_result_t res;
01360 size_t length;
01361 int ret, cnt;
01362 struct berval **tempbv = NULL;
01363
01364 if (ld == NULL)
01365 ldap_start ();
01366 if (ld == NULL)
01367 return (ldap_server == NULL ? ISC_R_SUCCESS : ISC_R_FAILURE);
01368
01369 buffer = dmalloc (LDAP_BUFFER_SIZE+1, MDL);
01370 if (buffer == NULL)
01371 return (ISC_R_FAILURE);
01372
01373 cfile = (struct parse *) NULL;
01374 res = new_parse (&cfile, -1, buffer, LDAP_BUFFER_SIZE, "LDAP", 0);
01375 if (res != ISC_R_SUCCESS)
01376 return (res);
01377
01378 uname (&unme);
01379 if (ldap_dhcp_server_cn != NULL)
01380 {
01381 snprintf (hfilter, sizeof (hfilter),
01382 "(&(objectClass=dhcpServer)(cn=%s))", ldap_dhcp_server_cn);
01383 }
01384 else
01385 {
01386 if(0 == getfqhostname(fqdn, sizeof(fqdn)))
01387 {
01388 snprintf (hfilter, sizeof (hfilter),
01389 "(&(objectClass=dhcpServer)(|(cn=%s)(cn=%s)))",
01390 unme.nodename, fqdn);
01391 }
01392 else
01393 {
01394 snprintf (hfilter, sizeof (hfilter),
01395 "(&(objectClass=dhcpServer)(cn=%s))", unme.nodename);
01396 }
01397
01398 }
01399 hostres = NULL;
01400 if ((ret = ldap_search_ext_s (ld, ldap_base_dn, LDAP_SCOPE_SUBTREE,
01401 hfilter, NULL, 0, NULL, NULL, NULL, 0,
01402 &hostres)) != LDAP_SUCCESS)
01403 {
01404 log_error ("Cannot find host LDAP entry %s %s",
01405 ((ldap_dhcp_server_cn == NULL)?(unme.nodename):(ldap_dhcp_server_cn)), hfilter);
01406 if(NULL != hostres)
01407 ldap_msgfree (hostres);
01408 ldap_stop();
01409 return (ISC_R_FAILURE);
01410 }
01411
01412 if ((hostent = ldap_first_entry (ld, hostres)) == NULL)
01413 {
01414 log_error ("Error: Cannot find LDAP entry matching %s", hfilter);
01415 ldap_msgfree (hostres);
01416 ldap_stop();
01417 return (ISC_R_FAILURE);
01418 }
01419
01420 hostdn = ldap_get_dn (ld, hostent);
01421 #if defined(DEBUG_LDAP)
01422 if (hostdn != NULL)
01423 log_info ("Found dhcpServer LDAP entry '%s'", hostdn);
01424 #endif
01425
01426 if (hostdn == NULL ||
01427 (tempbv = ldap_get_values_len (ld, hostent, "dhcpServiceDN")) == NULL ||
01428 tempbv[0] == NULL)
01429 {
01430 log_error ("Error: Cannot find LDAP entry matching %s", hfilter);
01431
01432 if (tempbv != NULL)
01433 ldap_value_free_len (tempbv);
01434
01435 if (hostdn)
01436 ldap_memfree (hostdn);
01437 ldap_msgfree (hostres);
01438 ldap_stop();
01439 return (ISC_R_FAILURE);
01440 }
01441
01442 #if defined(DEBUG_LDAP)
01443 log_info ("LDAP: Parsing dhcpServer options '%s' ...", hostdn);
01444 #endif
01445
01446 cfile->inbuf[0] = '\0';
01447 ldap_parse_entry_options(hostent, cfile->inbuf, LDAP_BUFFER_SIZE, NULL);
01448 cfile->buflen = strlen (cfile->inbuf);
01449 if(cfile->buflen > 0)
01450 {
01451 ldap_write_debug (cfile->inbuf, cfile->buflen);
01452
01453 res = conf_file_subparse (cfile, root_group, ROOT_GROUP);
01454 if (res != ISC_R_SUCCESS)
01455 {
01456 log_error ("LDAP: cannot parse dhcpServer entry '%s'", hostdn);
01457 ldap_memfree (hostdn);
01458 ldap_stop();
01459 return res;
01460 }
01461 cfile->inbuf[0] = '\0';
01462 }
01463 ldap_msgfree (hostres);
01464
01465
01466
01467
01468 cfile->bufix = cfile->buflen = 0;
01469 cfile->read_function = ldap_read_function;
01470
01471 res = ISC_R_SUCCESS;
01472 for (cnt=0; tempbv[cnt] != NULL; cnt++)
01473 {
01474 snprintf(sfilter, sizeof(sfilter), "(&(objectClass=dhcpService)"
01475 "(|(dhcpPrimaryDN=%s)(dhcpSecondaryDN=%s)))",
01476 hostdn, hostdn);
01477 ldres = NULL;
01478 if ((ret = ldap_search_ext_s (ld, tempbv[cnt]->bv_val, LDAP_SCOPE_BASE,
01479 sfilter, NULL, 0, NULL, NULL, NULL,
01480 0, &ldres)) != LDAP_SUCCESS)
01481 {
01482 log_error ("Error searching for dhcpServiceDN '%s': %s. Please update the LDAP entry '%s'",
01483 tempbv[cnt]->bv_val, ldap_err2string (ret), hostdn);
01484 if(NULL != ldres)
01485 ldap_msgfree(ldres);
01486 res = ISC_R_FAILURE;
01487 break;
01488 }
01489
01490 if ((ent = ldap_first_entry (ld, ldres)) == NULL)
01491 {
01492 log_error ("Error: Cannot find dhcpService DN '%s' with primary or secondary server reference. Please update the LDAP server entry '%s'",
01493 tempbv[cnt]->bv_val, hostdn);
01494
01495 ldap_msgfree(ldres);
01496 res = ISC_R_FAILURE;
01497 break;
01498 }
01499
01500
01501
01502
01503
01504
01505
01506 curr = dmalloc (sizeof (*curr), MDL);
01507 if (curr != NULL)
01508 {
01509 length = strlen (tempbv[cnt]->bv_val);
01510 curr->dn = dmalloc (length + 1, MDL);
01511 if (curr->dn == NULL)
01512 {
01513 dfree (curr, MDL);
01514 curr = NULL;
01515 }
01516 else
01517 strcpy (curr->dn, tempbv[cnt]->bv_val);
01518 }
01519
01520 if (curr != NULL)
01521 {
01522 curr->refs++;
01523
01524
01525 if (ldap_service_dn_tail != NULL)
01526 ldap_service_dn_tail->next = curr;
01527 else
01528 ldap_service_dn_head = curr;
01529
01530 ldap_service_dn_tail = curr;
01531 }
01532 else
01533 log_fatal ("no memory to remember ldap service dn");
01534
01535 #if defined (DEBUG_LDAP)
01536 log_info ("LDAP: Parsing dhcpService DN '%s' ...", tempbv[cnt]);
01537 #endif
01538 add_to_config_stack (ldres, ent);
01539 res = conf_file_subparse (cfile, root_group, ROOT_GROUP);
01540 if (res != ISC_R_SUCCESS)
01541 {
01542 log_error ("LDAP: cannot parse dhcpService entry '%s'", tempbv[cnt]->bv_val);
01543 break;
01544 }
01545 }
01546
01547 end_parse (&cfile);
01548 ldap_close_debug_fd();
01549
01550 ldap_memfree (hostdn);
01551 ldap_value_free_len (tempbv);
01552
01553 if (res != ISC_R_SUCCESS)
01554 {
01555 struct ldap_config_stack *temp_stack;
01556
01557 while ((curr = ldap_service_dn_head) != NULL)
01558 {
01559 ldap_service_dn_head = curr->next;
01560 dfree (curr->dn, MDL);
01561 dfree (curr, MDL);
01562 }
01563
01564 ldap_service_dn_tail = NULL;
01565
01566 while ((temp_stack = ldap_stack) != NULL)
01567 {
01568 ldap_stack = temp_stack->next;
01569 free_stack_entry (temp_stack);
01570 }
01571
01572 ldap_stop();
01573 }
01574
01575
01576 if (ldap_method == LDAP_METHOD_STATIC)
01577 ldap_stop();
01578
01579 return (res);
01580 }
01581
01582
01583
01584
01585
01586
01587
01588
01589 static int
01590 ldap_parse_options (LDAPMessage * ent, struct group *group,
01591 int type, struct host_decl *host,
01592 struct class **class)
01593 {
01594 int declaration, lease_limit;
01595 char option_buffer[8192];
01596 enum dhcp_token token;
01597 struct parse *cfile;
01598 isc_result_t res;
01599 const char *val;
01600
01601 lease_limit = 0;
01602 *option_buffer = '\0';
01603
01604
01605
01606 if (type == HOST_DECL)
01607 {
01608 char *hostdn, *basedn, *temp1, *temp2, filter[1024];
01609 LDAPMessage *groupdn, *entry;
01610 int ret;
01611
01612 hostdn = ldap_get_dn (ld, ent);
01613 if( hostdn != NULL)
01614 {
01615 basedn = NULL;
01616
01617 temp1 = strchr (hostdn, '=');
01618 if (temp1 != NULL)
01619 temp1 = strchr (++temp1, '=');
01620 if (temp1 != NULL)
01621 temp2 = strchr (++temp1, ',');
01622 else
01623 temp2 = NULL;
01624
01625 if (temp2 != NULL)
01626 {
01627 snprintf (filter, sizeof(filter),
01628 "(&(cn=%.*s)(objectClass=dhcpGroup))",
01629 (int)(temp2 - temp1), temp1);
01630
01631 basedn = strchr (temp1, ',');
01632 if (basedn != NULL)
01633 ++basedn;
01634 }
01635
01636 if (basedn != NULL && *basedn != '\0')
01637 {
01638 ret = ldap_search_ext_s (ld, basedn, LDAP_SCOPE_SUBTREE, filter,
01639 NULL, 0, NULL, NULL, NULL, 0, &groupdn);
01640 if (ret == LDAP_SUCCESS)
01641 {
01642 if ((entry = ldap_first_entry (ld, groupdn)) != NULL)
01643 {
01644 res = ldap_parse_entry_options (entry, option_buffer,
01645 sizeof(option_buffer) - 1,
01646 &lease_limit);
01647 if (res != ISC_R_SUCCESS)
01648 {
01649
01650 *option_buffer = '\0';
01651 lease_limit = 0;
01652 }
01653 }
01654 ldap_msgfree( groupdn);
01655 }
01656 }
01657 ldap_memfree( hostdn);
01658 }
01659 }
01660
01661 res = ldap_parse_entry_options (ent, option_buffer, sizeof(option_buffer) - 1,
01662 &lease_limit);
01663 if (res != ISC_R_SUCCESS)
01664 return (lease_limit);
01665
01666 option_buffer[sizeof(option_buffer) - 1] = '\0';
01667 if (*option_buffer == '\0')
01668 return (lease_limit);
01669
01670 cfile = (struct parse *) NULL;
01671 res = new_parse (&cfile, -1, option_buffer, strlen (option_buffer),
01672 type == HOST_DECL ? "LDAP-HOST" : "LDAP-SUBCLASS", 0);
01673 if (res != ISC_R_SUCCESS)
01674 return (lease_limit);
01675
01676 #if defined (DEBUG_LDAP)
01677 log_info ("Sending the following options: '%s'", option_buffer);
01678 #endif
01679
01680 declaration = 0;
01681 do
01682 {
01683 token = peek_token (&val, NULL, cfile);
01684 if (token == END_OF_FILE)
01685 break;
01686 declaration = parse_statement (cfile, group, type, host, declaration);
01687 } while (1);
01688
01689 end_parse (&cfile);
01690
01691 return (lease_limit);
01692 }
01693
01694
01695
01696 int
01697 find_haddr_in_ldap (struct host_decl **hp, int htype, unsigned hlen,
01698 const unsigned char *haddr, const char *file, int line)
01699 {
01700 char buf[128], *type_str;
01701 LDAPMessage * res, *ent;
01702 struct host_decl * host;
01703 isc_result_t status;
01704 ldap_dn_node *curr;
01705 int ret;
01706
01707 if (ldap_method == LDAP_METHOD_STATIC)
01708 return (0);
01709
01710 if (ld == NULL)
01711 ldap_start ();
01712 if (ld == NULL)
01713 return (0);
01714
01715 switch (htype)
01716 {
01717 case HTYPE_ETHER:
01718 type_str = "ethernet";
01719 break;
01720 case HTYPE_IEEE802:
01721 type_str = "token-ring";
01722 break;
01723 case HTYPE_FDDI:
01724 type_str = "fddi";
01725 break;
01726 default:
01727 log_info ("Ignoring unknown type %d", htype);
01728 return (0);
01729 }
01730
01731
01732
01733
01734
01735 snprintf (buf, sizeof (buf),
01736 "(&(objectClass=dhcpHost)(dhcpHWAddress=%s %s))",
01737 type_str, print_hw_addr (htype, hlen, haddr));
01738
01739 res = ent = NULL;
01740 for (curr = ldap_service_dn_head;
01741 curr != NULL && *curr->dn != '\0';
01742 curr = curr->next)
01743 {
01744 #if defined (DEBUG_LDAP)
01745 log_info ("Searching for %s in LDAP tree %s", buf, curr->dn);
01746 #endif
01747 ret = ldap_search_ext_s (ld, curr->dn, LDAP_SCOPE_SUBTREE, buf, NULL, 0,
01748 NULL, NULL, NULL, 0, &res);
01749
01750 if(ret == LDAP_SERVER_DOWN)
01751 {
01752 log_info ("LDAP server was down, trying to reconnect...");
01753
01754 ldap_stop();
01755 ldap_start();
01756 if(ld == NULL)
01757 {
01758 log_info ("LDAP reconnect failed - try again later...");
01759 return (0);
01760 }
01761
01762 ret = ldap_search_ext_s (ld, curr->dn, LDAP_SCOPE_SUBTREE, buf, NULL,
01763 0, NULL, NULL, NULL, 0, &res);
01764 }
01765
01766 if (ret == LDAP_SUCCESS)
01767 {
01768 if( (ent = ldap_first_entry (ld, res)) != NULL)
01769 break;
01770
01771 #if defined (DEBUG_LDAP)
01772 log_info ("No host entry for %s in LDAP tree %s",
01773 buf, curr->dn);
01774 #endif
01775 if(res)
01776 {
01777 ldap_msgfree (res);
01778 res = NULL;
01779 }
01780 }
01781 else
01782 {
01783 if(res)
01784 {
01785 ldap_msgfree (res);
01786 res = NULL;
01787 }
01788
01789 if (ret != LDAP_NO_SUCH_OBJECT && ret != LDAP_SUCCESS)
01790 {
01791 log_error ("Cannot search for %s in LDAP tree %s: %s", buf,
01792 curr->dn, ldap_err2string (ret));
01793 ldap_stop();
01794 return (0);
01795 }
01796 #if defined (DEBUG_LDAP)
01797 else
01798 {
01799 log_info ("ldap_search_ext_s returned %s when searching for %s in %s",
01800 ldap_err2string (ret), buf, curr->dn);
01801 }
01802 #endif
01803 }
01804 }
01805
01806 if (res && ent)
01807 {
01808 #if defined (DEBUG_LDAP)
01809 char *dn = ldap_get_dn (ld, ent);
01810 if (dn != NULL)
01811 {
01812 log_info ("Found dhcpHWAddress LDAP entry %s", dn);
01813 ldap_memfree(dn);
01814 }
01815 #endif
01816
01817 host = (struct host_decl *)0;
01818 status = host_allocate (&host, MDL);
01819 if (status != ISC_R_SUCCESS)
01820 {
01821 log_fatal ("can't allocate host decl struct: %s",
01822 isc_result_totext (status));
01823 ldap_msgfree (res);
01824 return (0);
01825 }
01826
01827 host->name = ldap_get_host_name (ent);
01828 if (host->name == NULL)
01829 {
01830 host_dereference (&host, MDL);
01831 ldap_msgfree (res);
01832 return (0);
01833 }
01834
01835 if (!clone_group (&host->group, root_group, MDL))
01836 {
01837 log_fatal ("can't clone group for host %s", host->name);
01838 host_dereference (&host, MDL);
01839 ldap_msgfree (res);
01840 return (0);
01841 }
01842
01843 ldap_parse_options (ent, host->group, HOST_DECL, host, NULL);
01844
01845 *hp = host;
01846 ldap_msgfree (res);
01847 return (1);
01848 }
01849
01850
01851 if(res) ldap_msgfree (res);
01852 return (0);
01853 }
01854
01855
01856 int
01857 find_subclass_in_ldap (struct class *class, struct class **newclass,
01858 struct data_string *data)
01859 {
01860 LDAPMessage * res, * ent;
01861 int ret, lease_limit;
01862 isc_result_t status;
01863 ldap_dn_node *curr;
01864 char buf[1024];
01865
01866 if (ldap_method == LDAP_METHOD_STATIC)
01867 return (0);
01868
01869 if (ld == NULL)
01870 ldap_start ();
01871 if (ld == NULL)
01872 return (0);
01873
01874 snprintf (buf, sizeof (buf),
01875 "(&(objectClass=dhcpSubClass)(cn=%s)(dhcpClassData=%s))",
01876 print_hex_1 (data->len, data->data, 60),
01877 print_hex_2 (strlen (class->name), (u_int8_t *) class->name, 60));
01878 #if defined (DEBUG_LDAP)
01879 log_info ("Searching LDAP for %s", buf);
01880 #endif
01881
01882 res = ent = NULL;
01883 for (curr = ldap_service_dn_head;
01884 curr != NULL && *curr->dn != '\0';
01885 curr = curr->next)
01886 {
01887 #if defined (DEBUG_LDAP)
01888 log_info ("Searching for %s in LDAP tree %s", buf, curr->dn);
01889 #endif
01890 ret = ldap_search_ext_s (ld, curr->dn, LDAP_SCOPE_SUBTREE, buf, NULL, 0,
01891 NULL, NULL, NULL, 0, &res);
01892
01893 if(ret == LDAP_SERVER_DOWN)
01894 {
01895 log_info ("LDAP server was down, trying to reconnect...");
01896
01897 ldap_stop();
01898 ldap_start();
01899
01900 if(ld == NULL)
01901 {
01902 log_info ("LDAP reconnect failed - try again later...");
01903 return (0);
01904 }
01905
01906 ret = ldap_search_ext_s (ld, curr->dn, LDAP_SCOPE_SUBTREE, buf,
01907 NULL, 0, NULL, NULL, NULL, 0, &res);
01908 }
01909
01910 if (ret == LDAP_SUCCESS)
01911 {
01912 if( (ent = ldap_first_entry (ld, res)) != NULL)
01913 break;
01914
01915 #if defined (DEBUG_LDAP)
01916 log_info ("No subclass entry for %s in LDAP tree %s",
01917 buf, curr->dn);
01918 #endif
01919 if(res)
01920 {
01921 ldap_msgfree (res);
01922 res = NULL;
01923 }
01924 }
01925 else
01926 {
01927 if(res)
01928 {
01929 ldap_msgfree (res);
01930 res = NULL;
01931 }
01932
01933 if (ret != LDAP_NO_SUCH_OBJECT && ret != LDAP_SUCCESS)
01934 {
01935 log_error ("Cannot search for %s in LDAP tree %s: %s", buf,
01936 curr->dn, ldap_err2string (ret));
01937 ldap_stop();
01938 return (0);
01939 }
01940 #if defined (DEBUG_LDAP)
01941 else
01942 {
01943 log_info ("ldap_search_ext_s returned %s when searching for %s in %s",
01944 ldap_err2string (ret), buf, curr->dn);
01945 }
01946 #endif
01947 }
01948 }
01949
01950 if (res && ent)
01951 {
01952 #if defined (DEBUG_LDAP)
01953 char *dn = ldap_get_dn (ld, ent);
01954 if (dn != NULL)
01955 {
01956 log_info ("Found subclass LDAP entry %s", dn);
01957 ldap_memfree(dn);
01958 }
01959 #endif
01960
01961 status = class_allocate (newclass, MDL);
01962 if (status != ISC_R_SUCCESS)
01963 {
01964 log_error ("Cannot allocate memory for a new class");
01965 ldap_msgfree (res);
01966 return (0);
01967 }
01968
01969 group_reference (&(*newclass)->group, class->group, MDL);
01970 class_reference (&(*newclass)->superclass, class, MDL);
01971 lease_limit = ldap_parse_options (ent, (*newclass)->group,
01972 CLASS_DECL, NULL, newclass);
01973 if (lease_limit == 0)
01974 (*newclass)->lease_limit = class->lease_limit;
01975 else
01976 class->lease_limit = lease_limit;
01977
01978 if ((*newclass)->lease_limit)
01979 {
01980 (*newclass)->billed_leases =
01981 dmalloc ((*newclass)->lease_limit * sizeof (struct lease *), MDL);
01982 if (!(*newclass)->billed_leases)
01983 {
01984 log_error ("no memory for billing");
01985 class_dereference (newclass, MDL);
01986 ldap_msgfree (res);
01987 return (0);
01988 }
01989 memset ((*newclass)->billed_leases, 0,
01990 ((*newclass)->lease_limit * sizeof (struct lease *)));
01991 }
01992
01993 data_string_copy (&(*newclass)->hash_string, data, MDL);
01994
01995 ldap_msgfree (res);
01996 return (1);
01997 }
01998
01999 if(res) ldap_msgfree (res);
02000 return (0);
02001 }
02002
02003 #endif