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