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