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