]> git.pld-linux.org Git - packages/dhcp.git/blame - dhcp-ldap.patch
- updated
[packages/dhcp.git] / dhcp-ldap.patch
CommitLineData
e5ebac8b
AM
1diff -up dhcp-4.0.0/server/Makefile.am.ldap dhcp-4.0.0/server/Makefile.am
2--- dhcp-4.0.0/server/Makefile.am.ldap 2007-05-29 06:32:11.000000000 -1000
3+++ dhcp-4.0.0/server/Makefile.am 2008-01-22 15:09:56.000000000 -1000
4@@ -4,12 +4,10 @@ dist_sysconf_DATA = dhcpd.conf
5 sbin_PROGRAMS = dhcpd
6 dhcpd_SOURCES = dhcpd.c dhcp.c bootp.c confpars.c db.c class.c failover.c \
7 omapi.c mdb.c stables.c salloc.c ddns.c dhcpleasequery.c \
8- dhcpv6.c mdb6.c
9+ dhcpv6.c mdb6.c ldap.c ldap_casa.c
1097e9ca 10
e5ebac8b
AM
11-# libomapi.a this is here twice to handle circular library dependencies :(
12-dhcpd_LDADD = ../common/libdhcp.a ../omapip/libomapi.a ../dst/libdst.a \
13- ../dhcpctl/libdhcpctl.a ../minires/libres.a \
14- ../omapip/libomapi.a
15+dhcpd_LDADD = ../common/libdhcp.a ../omapip/libomapi.a ../minires/libres.a \
16+ ../dhcpctl/libdhcpctl.a ../dst/libdstnomd5.a -lldap
1097e9ca 17
e5ebac8b
AM
18 man_MANS = dhcpd.8 dhcpd.conf.5 dhcpd.leases.5
19 EXTRA_DIST = $(man_MANS)
20diff -up dhcp-4.0.0/server/mdb.c.ldap dhcp-4.0.0/server/mdb.c
21--- dhcp-4.0.0/server/mdb.c.ldap 2007-11-30 11:51:43.000000000 -1000
22+++ dhcp-4.0.0/server/mdb.c 2008-01-22 15:09:56.000000000 -1000
23@@ -600,6 +600,12 @@ int find_hosts_by_haddr (struct host_dec
24 const char *file, int line)
25 {
26 struct hardware h;
27+ int ret;
1097e9ca 28+
1097e9ca 29+#if defined(LDAP_CONFIGURATION)
e5ebac8b
AM
30+ if ((ret = find_haddr_in_ldap (hp, htype, hlen, haddr, file, line)))
31+ return ret;
1097e9ca 32+#endif
1097e9ca 33
e5ebac8b
AM
34 h.hlen = hlen + 1;
35 h.hbuf [0] = htype;
36diff -up /dev/null dhcp-4.0.0/server/ldap_casa.c
37--- /dev/null 2008-01-19 23:52:35.158021373 -1000
38+++ dhcp-4.0.0/server/ldap_casa.c 2008-01-22 15:09:56.000000000 -1000
39@@ -0,0 +1,138 @@
40+/* ldap_casa.c
a37573f1 41+
e5ebac8b 42+ CASA routines for DHCPD... */
a37573f1
JR
43+
44+/* Copyright (c) 2004 Internet Systems Consorium, Inc. ("ISC")
45+ * Copyright (c) 1995-2003 Internet Software Consortium.
46+ * Copyright (c) 2006 Novell, Inc.
47+
48+ * All rights reserved.
49+ * Redistribution and use in source and binary forms, with or without
50+ * modification, are permitted provided that the following conditions are met:
51+ * 1.Redistributions of source code must retain the above copyright notice,
52+ * this list of conditions and the following disclaimer.
53+ * 2.Redistributions in binary form must reproduce the above copyright notice,
54+ * this list of conditions and the following disclaimer in the documentation
55+ * and/or other materials provided with the distribution.
56+ * 3.Neither the name of ISC, ISC DHCP, nor the names of its contributors
57+ * may be used to endorse or promote products derived from this software
58+ * without specific prior written permission.
59+
60+ * THIS SOFTWARE IS PROVIDED BY INTERNET SYSTEMS CONSORTIUM AND CONTRIBUTORS
61+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
62+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
63+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ISC OR CONTRIBUTORS BE LIABLE
64+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
65+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
66+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
67+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
68+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
69+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
70+ * POSSIBILITY OF SUCH DAMAGE.
71+
72+ * This file was written by S Kalyanasundaram <skalyanasundaram@novell.com>
73+ */
74+
75+#if defined(LDAP_CASA_AUTH)
e5ebac8b
AM
76+#include "ldap_casa.h"
77+#include "dhcpd.h"
a37573f1 78+
e5ebac8b
AM
79+int
80+load_casa (void)
81+{
82+ if( !(casaIDK = dlopen(MICASA_LIB,RTLD_LAZY)))
83+ return 0;
84+ p_miCASAGetCredential = (CASA_GetCredential_T) dlsym(casaIDK, "miCASAGetCredential");
85+ p_miCASASetCredential = (CASA_SetCredential_T) dlsym(casaIDK, "miCASASetCredential");
86+ p_miCASARemoveCredential = (CASA_RemoveCredential_T) dlsym(casaIDK, "miCASARemoveCredential");
a37573f1 87+
e5ebac8b
AM
88+ if((p_miCASAGetCredential == NULL) ||
89+ (p_miCASASetCredential == NULL) ||
90+ (p_miCASARemoveCredential == NULL))
91+ {
92+ if(casaIDK)
93+ dlclose(casaIDK);
94+ casaIDK = NULL;
95+ p_miCASAGetCredential = NULL;
96+ p_miCASASetCredential = NULL;
97+ p_miCASARemoveCredential = NULL;
98+ return 0;
99+ }
100+ else
101+ return 1;
102+}
a37573f1 103+
e5ebac8b
AM
104+static void
105+release_casa(void)
106+{
107+ if(casaIDK)
108+ {
109+ dlclose(casaIDK);
110+ casaIDK = NULL;
111+ }
a37573f1 112+
e5ebac8b
AM
113+ p_miCASAGetCredential = NULL;
114+ p_miCASASetCredential = NULL;
115+ p_miCASARemoveCredential = NULL;
a37573f1 116+
e5ebac8b
AM
117+}
118+
119+int
120+load_uname_pwd_from_miCASA (char **ldap_username, char **ldap_password)
121+ {
122+ int result = 0;
123+ uint32_t credentialtype = SSCS_CRED_TYPE_SERVER_F;
124+ SSCS_BASIC_CREDENTIAL credential;
125+ SSCS_SECRET_ID_T applicationSecretId;
126+ char *tempVar = NULL;
127+
128+ const char applicationName[10] = "dhcp-ldap";
a37573f1 129+
e5ebac8b
AM
130+ if ( load_casa() )
131+ {
132+ memset(&credential, 0, sizeof(SSCS_BASIC_CREDENTIAL));
133+ memset(&applicationSecretId, 0, sizeof(SSCS_SECRET_ID_T));
a37573f1 134+
e5ebac8b
AM
135+ applicationSecretId.len = strlen(applicationName) + 1;
136+ memcpy (applicationSecretId.id, applicationName, applicationSecretId.len);
1097e9ca 137+
e5ebac8b 138+ credential.unFlags = USERNAME_TYPE_CN_F;
1097e9ca 139+
e5ebac8b
AM
140+ result = p_miCASAGetCredential (0,
141+ &applicationSecretId,NULL,&credentialtype,
142+ &credential,NULL);
1097e9ca 143+
e5ebac8b
AM
144+ if(credential.unLen)
145+ {
146+ tempVar = dmalloc (credential.unLen + 1, MDL);
147+ if (!tempVar)
148+ log_fatal ("no memory for ldap_username");
149+ memcpy(tempVar , credential.username, credential.unLen);
150+ *ldap_username = tempVar;
1097e9ca 151+
e5ebac8b
AM
152+ tempVar = dmalloc (credential.pwordLen + 1, MDL);
153+ if (!tempVar)
154+ log_fatal ("no memory for ldap_password");
155+ memcpy(tempVar, credential.password, credential.pwordLen);
156+ *ldap_password = tempVar;
1097e9ca 157+
e5ebac8b
AM
158+#if defined (DEBUG_LDAP)
159+ log_info ("Authentication credential taken from CASA");
1097e9ca 160+#endif
161+
e5ebac8b
AM
162+ release_casa();
163+ return 1;
1097e9ca 164+
e5ebac8b
AM
165+ }
166+ else
167+ {
168+ release_casa();
169+ return 0;
170+ }
171+ }
172+ else
173+ return 0; //casa libraries not loaded
174+ }
1097e9ca 175+
e5ebac8b
AM
176+#endif /* LDAP_CASA_AUTH */
177+
178diff -up dhcp-4.0.0/server/dhcpd.c.ldap dhcp-4.0.0/server/dhcpd.c
179--- dhcp-4.0.0/server/dhcpd.c.ldap 2007-11-30 11:51:43.000000000 -1000
180+++ dhcp-4.0.0/server/dhcpd.c 2008-01-22 15:09:56.000000000 -1000
181@@ -505,6 +505,14 @@ main(int argc, char **argv) {
1097e9ca 182 /* Add the ddns update style enumeration prior to parsing. */
183 add_enumeration (&ddns_styles);
184 add_enumeration (&syslog_enum);
185+#if defined (LDAP_CONFIGURATION)
186+ add_enumeration (&ldap_methods);
a37573f1
JR
187+#if defined (USE_SSL)
188+ add_enumeration (&ldap_ssl_usage_enum);
189+ add_enumeration (&ldap_tls_reqcert_enum);
190+ add_enumeration (&ldap_tls_crlcheck_enum);
191+#endif
1097e9ca 192+#endif
193
194 if (!group_allocate (&root_group, MDL))
195 log_fatal ("Can't allocate root group!");
e5ebac8b
AM
196diff -up /dev/null dhcp-4.0.0/server/ldap.c
197--- /dev/null 2008-01-19 23:52:35.158021373 -1000
198+++ dhcp-4.0.0/server/ldap.c 2008-01-22 15:09:56.000000000 -1000
199@@ -0,0 +1,2004 @@
1097e9ca 200+/* ldap.c
201+
202+ Routines for reading the configuration from LDAP */
203+
204+/*
a37573f1 205+ * Copyright (c) 2003-2006 Ntelos, Inc.
1097e9ca 206+ * All rights reserved.
207+ *
208+ * Redistribution and use in source and binary forms, with or without
209+ * modification, are permitted provided that the following conditions
210+ * are met:
211+ *
212+ * 1. Redistributions of source code must retain the above copyright
213+ * notice, this list of conditions and the following disclaimer.
214+ * 2. Redistributions in binary form must reproduce the above copyright
215+ * notice, this list of conditions and the following disclaimer in the
216+ * documentation and/or other materials provided with the distribution.
217+ * 3. Neither the name of The Internet Software Consortium nor the names
218+ * of its contributors may be used to endorse or promote products derived
219+ * from this software without specific prior written permission.
220+ *
221+ * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
222+ * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
223+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
224+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
225+ * DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
226+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
227+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
228+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
229+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
230+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
231+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
232+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
233+ * SUCH DAMAGE.
234+ *
a37573f1 235+ * This LDAP module was written by Brian Masney <masneyb@ntelos.net>. Its
1097e9ca 236+ * development was sponsored by Ntelos, Inc. (www.ntelos.com).
237+ */
238+
239+#include "dhcpd.h"
a37573f1 240+#include <signal.h>
e5ebac8b 241+#include <errno.h>
1097e9ca 242+
243+#if defined(LDAP_CONFIGURATION)
244+
a37573f1
JR
245+#if defined(LDAP_CASA_AUTH)
246+#include "ldap_casa.h"
247+#endif
248+
1097e9ca 249+static LDAP * ld = NULL;
250+static char *ldap_server = NULL,
251+ *ldap_username = NULL,
252+ *ldap_password = NULL,
253+ *ldap_base_dn = NULL,
a37573f1 254+ *ldap_dhcp_server_cn = NULL,
1097e9ca 255+ *ldap_debug_file = NULL;
3150c1ff 256+static int ldap_port = LDAP_PORT,
1097e9ca 257+ ldap_method = LDAP_METHOD_DYNAMIC,
a37573f1 258+ ldap_referrals = -1,
1097e9ca 259+ ldap_debug_fd = -1;
a37573f1
JR
260+#if defined (USE_SSL)
261+static int ldap_use_ssl = -1, /* try TLS if possible */
262+ ldap_tls_reqcert = -1,
263+ ldap_tls_crlcheck = -1;
264+static char *ldap_tls_ca_file = NULL,
265+ *ldap_tls_ca_dir = NULL,
266+ *ldap_tls_cert = NULL,
267+ *ldap_tls_key = NULL,
268+ *ldap_tls_ciphers = NULL,
269+ *ldap_tls_randfile = NULL;
270+#endif
1097e9ca 271+static struct ldap_config_stack *ldap_stack = NULL;
272+
3150c1ff 273+typedef struct ldap_dn_node {
274+ struct ldap_dn_node *next;
275+ size_t refs;
276+ char *dn;
277+} ldap_dn_node;
278+
279+static ldap_dn_node *ldap_service_dn_head = NULL;
280+static ldap_dn_node *ldap_service_dn_tail = NULL;
281+
1097e9ca 282+
a37573f1
JR
283+static char *
284+x_strncat(char *dst, const char *src, size_t dst_size)
285+{
286+ size_t len = strlen(dst);
287+ return strncat(dst, src, dst_size > len ? dst_size - len - 1: 0);
288+}
289+
1097e9ca 290+static void
291+ldap_parse_class (struct ldap_config_stack *item, struct parse *cfile)
292+{
e5ebac8b 293+ struct berval **tempbv;
1097e9ca 294+
e5ebac8b
AM
295+ if ((tempbv = ldap_get_values_len (ld, item->ldent, "cn")) == NULL ||
296+ tempbv[0] == NULL)
1097e9ca 297+ {
e5ebac8b
AM
298+ if (tempbv != NULL)
299+ ldap_value_free_len (tempbv);
1097e9ca 300+
301+ return;
302+ }
303+
a37573f1 304+ x_strncat (cfile->inbuf, "class \"", LDAP_BUFFER_SIZE);
e5ebac8b 305+ x_strncat (cfile->inbuf, tempbv[0]->bv_val, LDAP_BUFFER_SIZE);
a37573f1 306+ x_strncat (cfile->inbuf, "\" {\n", LDAP_BUFFER_SIZE);
1097e9ca 307+
308+ item->close_brace = 1;
e5ebac8b 309+ ldap_value_free_len (tempbv);
1097e9ca 310+}
311+
312+
313+static void
314+ldap_parse_subclass (struct ldap_config_stack *item, struct parse *cfile)
315+{
e5ebac8b 316+ struct berval **tempbv, **classdata;
1097e9ca 317+
e5ebac8b
AM
318+ if ((tempbv = ldap_get_values_len (ld, item->ldent, "cn")) == NULL ||
319+ tempbv[0] == NULL)
1097e9ca 320+ {
e5ebac8b
AM
321+ if (tempbv != NULL)
322+ ldap_value_free_len (tempbv);
1097e9ca 323+
324+ return;
325+ }
326+
e5ebac8b 327+ if ((classdata = ldap_get_values_len (ld, item->ldent,
1097e9ca 328+ "dhcpClassData")) == NULL ||
329+ classdata[0] == NULL)
330+ {
331+ if (classdata != NULL)
e5ebac8b
AM
332+ ldap_value_free_len (classdata);
333+ ldap_value_free_len (tempbv);
1097e9ca 334+
335+ return;
336+ }
337+
a37573f1 338+ x_strncat (cfile->inbuf, "subclass ", LDAP_BUFFER_SIZE);
e5ebac8b 339+ x_strncat (cfile->inbuf, classdata[0]->bv_val, LDAP_BUFFER_SIZE);
a37573f1 340+ x_strncat (cfile->inbuf, " ", LDAP_BUFFER_SIZE);
e5ebac8b 341+ x_strncat (cfile->inbuf, tempbv[0]->bv_val, LDAP_BUFFER_SIZE);
a37573f1 342+ x_strncat (cfile->inbuf, " {\n", LDAP_BUFFER_SIZE);
1097e9ca 343+
344+ item->close_brace = 1;
e5ebac8b
AM
345+ ldap_value_free_len (tempbv);
346+ ldap_value_free_len (classdata);
1097e9ca 347+}
348+
349+
350+static void
351+ldap_parse_host (struct ldap_config_stack *item, struct parse *cfile)
352+{
e5ebac8b 353+ struct berval **tempbv, **hwaddr;
1097e9ca 354+
e5ebac8b
AM
355+ if ((tempbv = ldap_get_values_len (ld, item->ldent, "cn")) == NULL ||
356+ tempbv[0] == NULL)
1097e9ca 357+ {
e5ebac8b
AM
358+ if (tempbv != NULL)
359+ ldap_value_free_len (tempbv);
1097e9ca 360+
361+ return;
362+ }
363+
e5ebac8b 364+ hwaddr = ldap_get_values_len (ld, item->ldent, "dhcpHWAddress");
1097e9ca 365+
a37573f1 366+ x_strncat (cfile->inbuf, "host ", LDAP_BUFFER_SIZE);
e5ebac8b 367+ x_strncat (cfile->inbuf, tempbv[0]->bv_val, LDAP_BUFFER_SIZE);
1097e9ca 368+
a37573f1
JR
369+ if (hwaddr != NULL && hwaddr[0] != NULL)
370+ {
371+ x_strncat (cfile->inbuf, " {\nhardware ", LDAP_BUFFER_SIZE);
e5ebac8b 372+ x_strncat (cfile->inbuf, hwaddr[0]->bv_val, LDAP_BUFFER_SIZE);
a37573f1 373+ x_strncat (cfile->inbuf, ";\n", LDAP_BUFFER_SIZE);
e5ebac8b 374+ ldap_value_free_len (hwaddr);
a37573f1 375+ }
1097e9ca 376+
377+ item->close_brace = 1;
e5ebac8b 378+ ldap_value_free_len (tempbv);
1097e9ca 379+}
380+
381+
382+static void
383+ldap_parse_shared_network (struct ldap_config_stack *item, struct parse *cfile)
384+{
e5ebac8b 385+ struct berval **tempbv;
1097e9ca 386+
e5ebac8b
AM
387+ if ((tempbv = ldap_get_values_len (ld, item->ldent, "cn")) == NULL ||
388+ tempbv[0] == NULL)
1097e9ca 389+ {
e5ebac8b
AM
390+ if (tempbv != NULL)
391+ ldap_value_free_len (tempbv);
1097e9ca 392+
393+ return;
394+ }
395+
a37573f1 396+ x_strncat (cfile->inbuf, "shared-network \"", LDAP_BUFFER_SIZE);
e5ebac8b 397+ x_strncat (cfile->inbuf, tempbv[0]->bv_val, LDAP_BUFFER_SIZE);
a37573f1 398+ x_strncat (cfile->inbuf, "\" {\n", LDAP_BUFFER_SIZE);
1097e9ca 399+
400+ item->close_brace = 1;
e5ebac8b 401+ ldap_value_free_len (tempbv);
1097e9ca 402+}
403+
404+
405+static void
406+parse_netmask (int netmask, char *netmaskbuf)
407+{
408+ unsigned long nm;
409+ int i;
410+
411+ nm = 0;
412+ for (i=1; i <= netmask; i++)
413+ {
414+ nm |= 1 << (32 - i);
415+ }
416+
417+ sprintf (netmaskbuf, "%d.%d.%d.%d", (int) (nm >> 24) & 0xff,
418+ (int) (nm >> 16) & 0xff,
419+ (int) (nm >> 8) & 0xff,
420+ (int) nm & 0xff);
421+}
422+
a37573f1 423+
1097e9ca 424+static void
425+ldap_parse_subnet (struct ldap_config_stack *item, struct parse *cfile)
426+{
e5ebac8b
AM
427+ struct berval **tempbv, **netmaskstr;
428+ char netmaskbuf[16];
1097e9ca 429+ int i;
430+
e5ebac8b
AM
431+ if ((tempbv = ldap_get_values_len (ld, item->ldent, "cn")) == NULL ||
432+ tempbv[0] == NULL)
1097e9ca 433+ {
e5ebac8b
AM
434+ if (tempbv != NULL)
435+ ldap_value_free_len (tempbv);
1097e9ca 436+
437+ return;
438+ }
439+
e5ebac8b 440+ if ((netmaskstr = ldap_get_values_len (ld, item->ldent,
1097e9ca 441+ "dhcpNetmask")) == NULL ||
442+ netmaskstr[0] == NULL)
443+ {
444+ if (netmaskstr != NULL)
e5ebac8b
AM
445+ ldap_value_free_len (netmaskstr);
446+ ldap_value_free_len (tempbv);
1097e9ca 447+
448+ return;
449+ }
450+
a37573f1 451+ x_strncat (cfile->inbuf, "subnet ", LDAP_BUFFER_SIZE);
e5ebac8b 452+ x_strncat (cfile->inbuf, tempbv[0]->bv_val, LDAP_BUFFER_SIZE);
1097e9ca 453+
a37573f1 454+ x_strncat (cfile->inbuf, " netmask ", LDAP_BUFFER_SIZE);
e5ebac8b 455+ parse_netmask (strtol (netmaskstr[0]->bv_val, NULL, 10), netmaskbuf);
a37573f1 456+ x_strncat (cfile->inbuf, netmaskbuf, LDAP_BUFFER_SIZE);
1097e9ca 457+
a37573f1 458+ x_strncat (cfile->inbuf, " {\n", LDAP_BUFFER_SIZE);
1097e9ca 459+
e5ebac8b
AM
460+ ldap_value_free_len (tempbv);
461+ ldap_value_free_len (netmaskstr);
1097e9ca 462+
e5ebac8b 463+ if ((tempbv = ldap_get_values_len (ld, item->ldent, "dhcpRange")) != NULL)
1097e9ca 464+ {
e5ebac8b 465+ for (i=0; tempbv[i] != NULL; i++)
1097e9ca 466+ {
a37573f1
JR
467+ x_strncat (cfile->inbuf, "range", LDAP_BUFFER_SIZE);
468+ x_strncat (cfile->inbuf, " ", LDAP_BUFFER_SIZE);
e5ebac8b 469+ x_strncat (cfile->inbuf, tempbv[i]->bv_val, LDAP_BUFFER_SIZE);
a37573f1 470+ x_strncat (cfile->inbuf, ";\n", LDAP_BUFFER_SIZE);
1097e9ca 471+ }
1097e9ca 472+ }
473+
474+ item->close_brace = 1;
475+}
476+
477+
478+static void
479+ldap_parse_pool (struct ldap_config_stack *item, struct parse *cfile)
480+{
e5ebac8b 481+ struct berval **tempbv;
1097e9ca 482+ int i;
483+
a37573f1 484+ x_strncat (cfile->inbuf, "pool {\n", LDAP_BUFFER_SIZE);
1097e9ca 485+
e5ebac8b 486+ if ((tempbv = ldap_get_values_len (ld, item->ldent, "dhcpRange")) != NULL)
1097e9ca 487+ {
a37573f1 488+ x_strncat (cfile->inbuf, "range", LDAP_BUFFER_SIZE);
e5ebac8b 489+ for (i=0; tempbv[i] != NULL; i++)
1097e9ca 490+ {
a37573f1 491+ x_strncat (cfile->inbuf, " ", LDAP_BUFFER_SIZE);
e5ebac8b 492+ x_strncat (cfile->inbuf, tempbv[i]->bv_val, LDAP_BUFFER_SIZE);
1097e9ca 493+ }
a37573f1 494+ x_strncat (cfile->inbuf, ";\n", LDAP_BUFFER_SIZE);
e5ebac8b 495+ ldap_value_free_len (tempbv);
1097e9ca 496+ }
497+
e5ebac8b 498+ if ((tempbv = ldap_get_values_len (ld, item->ldent, "dhcpPermitList")) != NULL)
1097e9ca 499+ {
e5ebac8b 500+ for (i=0; tempbv[i] != NULL; i++)
1097e9ca 501+ {
e5ebac8b 502+ x_strncat (cfile->inbuf, tempbv[i]->bv_val, LDAP_BUFFER_SIZE);
a37573f1 503+ x_strncat (cfile->inbuf, ";\n", LDAP_BUFFER_SIZE);
1097e9ca 504+ }
e5ebac8b 505+ ldap_value_free_len (tempbv);
1097e9ca 506+ }
507+
508+ item->close_brace = 1;
509+}
510+
511+
512+static void
513+ldap_parse_group (struct ldap_config_stack *item, struct parse *cfile)
514+{
a37573f1
JR
515+ x_strncat (cfile->inbuf, "group {\n", LDAP_BUFFER_SIZE);
516+ item->close_brace = 1;
517+}
518+
519+
520+static void
521+ldap_parse_key (struct ldap_config_stack *item, struct parse *cfile)
522+{
e5ebac8b 523+ struct berval **tempbv;
a37573f1 524+
e5ebac8b 525+ if ((tempbv = ldap_get_values_len (ld, item->ldent, "cn")) != NULL)
a37573f1
JR
526+ {
527+ x_strncat (cfile->inbuf, "key ", LDAP_BUFFER_SIZE);
e5ebac8b 528+ x_strncat (cfile->inbuf, tempbv[0]->bv_val, LDAP_BUFFER_SIZE);
a37573f1 529+ x_strncat (cfile->inbuf, " {\n", LDAP_BUFFER_SIZE);
e5ebac8b 530+ ldap_value_free_len (tempbv);
a37573f1
JR
531+ }
532+
e5ebac8b 533+ if ((tempbv = ldap_get_values_len (ld, item->ldent, "dhcpKeyAlgorithm")) != NULL)
a37573f1
JR
534+ {
535+ x_strncat (cfile->inbuf, "algorithm ", LDAP_BUFFER_SIZE);
e5ebac8b 536+ x_strncat (cfile->inbuf, tempbv[0]->bv_val, LDAP_BUFFER_SIZE);
a37573f1 537+ x_strncat (cfile->inbuf, ";\n", LDAP_BUFFER_SIZE);
e5ebac8b 538+ ldap_value_free_len (tempbv);
a37573f1
JR
539+ }
540+
e5ebac8b 541+ if ((tempbv = ldap_get_values_len (ld, item->ldent, "dhcpKeySecret")) != NULL)
a37573f1
JR
542+ {
543+ x_strncat (cfile->inbuf, "secret ", LDAP_BUFFER_SIZE);
e5ebac8b 544+ x_strncat (cfile->inbuf, tempbv[0]->bv_val, LDAP_BUFFER_SIZE);
a37573f1 545+ x_strncat (cfile->inbuf, ";\n", LDAP_BUFFER_SIZE);
e5ebac8b 546+ ldap_value_free_len (tempbv);
a37573f1
JR
547+ }
548+
549+ item->close_brace = 1;
550+}
551+
552+
553+static void
554+ldap_parse_zone (struct ldap_config_stack *item, struct parse *cfile)
555+{
556+ char *cnFindStart, *cnFindEnd;
e5ebac8b 557+ struct berval **tempbv;
a37573f1
JR
558+ char *keyCn;
559+ size_t len;
560+
e5ebac8b 561+ if ((tempbv = ldap_get_values_len (ld, item->ldent, "cn")) != NULL)
a37573f1
JR
562+ {
563+ x_strncat (cfile->inbuf, "zone ", LDAP_BUFFER_SIZE);
e5ebac8b 564+ x_strncat (cfile->inbuf, tempbv[0]->bv_val, LDAP_BUFFER_SIZE);
a37573f1 565+ x_strncat (cfile->inbuf, " {\n", LDAP_BUFFER_SIZE);
e5ebac8b 566+ ldap_value_free_len (tempbv);
a37573f1
JR
567+ }
568+
e5ebac8b 569+ if ((tempbv = ldap_get_values_len (ld, item->ldent, "dhcpDnsZoneServer")) != NULL)
a37573f1
JR
570+ {
571+ x_strncat (cfile->inbuf, "primary ", LDAP_BUFFER_SIZE);
e5ebac8b 572+ x_strncat (cfile->inbuf, tempbv[0]->bv_val, LDAP_BUFFER_SIZE);
a37573f1
JR
573+
574+ x_strncat (cfile->inbuf, ";\n", LDAP_BUFFER_SIZE);
e5ebac8b 575+ ldap_value_free_len (tempbv);
a37573f1
JR
576+ }
577+
e5ebac8b 578+ if ((tempbv = ldap_get_values_len (ld, item->ldent, "dhcpKeyDN")) != NULL)
a37573f1 579+ {
e5ebac8b 580+ cnFindStart = strchr(tempbv[0]->bv_val,'=');
a37573f1
JR
581+ if (cnFindStart != NULL)
582+ cnFindEnd = strchr(++cnFindStart,',');
583+ else
584+ cnFindEnd = NULL;
585+
586+ if (cnFindEnd != NULL && cnFindEnd > cnFindStart)
587+ {
588+ len = cnFindEnd - cnFindStart;
589+ keyCn = dmalloc (len + 1, MDL);
590+ }
591+ else
592+ {
593+ len = 0;
594+ keyCn = NULL;
595+ }
596+
597+ if (keyCn != NULL)
598+ {
599+ strncpy (keyCn, cnFindStart, len);
600+ keyCn[len] = '\0';
601+
602+ x_strncat (cfile->inbuf, "key ", LDAP_BUFFER_SIZE);
603+ x_strncat (cfile->inbuf, keyCn, LDAP_BUFFER_SIZE);
604+ x_strncat (cfile->inbuf, ";\n", LDAP_BUFFER_SIZE);
605+
606+ dfree (keyCn, MDL);
607+ }
608+
e5ebac8b 609+ ldap_value_free_len (tempbv);
a37573f1
JR
610+ }
611+
1097e9ca 612+ item->close_brace = 1;
613+}
614+
615+
616+static void
617+add_to_config_stack (LDAPMessage * res, LDAPMessage * ent)
618+{
619+ struct ldap_config_stack *ns;
620+
621+ ns = dmalloc (sizeof (*ns), MDL);
622+ ns->res = res;
623+ ns->ldent = ent;
624+ ns->close_brace = 0;
625+ ns->processed = 0;
626+ ns->next = ldap_stack;
627+ ldap_stack = ns;
628+}
629+
630+
631+static void
a37573f1
JR
632+ldap_stop()
633+{
634+ struct sigaction old, new;
635+
636+ if (ld == NULL)
637+ return;
638+
639+ /*
640+ ** ldap_unbind after a LDAP_SERVER_DOWN result
641+ ** causes a SIGPIPE and dhcpd gets terminated,
642+ ** since it doesn't handle it...
643+ */
644+
645+ new.sa_flags = 0;
646+ new.sa_handler = SIG_IGN;
647+ sigemptyset (&new.sa_mask);
648+ sigaction (SIGPIPE, &new, &old);
649+
e5ebac8b 650+ ldap_unbind_ext_s (ld, NULL, NULL);
a37573f1
JR
651+ ld = NULL;
652+
653+ sigaction (SIGPIPE, &old, &new);
654+}
655+
656+
657+static char *
658+_do_lookup_dhcp_string_option (struct option_state *options, int option_name)
659+{
660+ struct option_cache *oc;
661+ struct data_string db;
662+ char *ret;
663+
664+ memset (&db, 0, sizeof (db));
665+ oc = lookup_option (&server_universe, options, option_name);
666+ if (oc &&
667+ evaluate_option_cache (&db, (struct packet*) NULL,
668+ (struct lease *) NULL,
669+ (struct client_state *) NULL, options,
670+ (struct option_state *) NULL,
671+ &global_scope, oc, MDL) &&
672+ db.data != NULL && *db.data != '\0')
673+
674+ {
675+ ret = dmalloc (db.len + 1, MDL);
676+ if (ret == NULL)
677+ log_fatal ("no memory for ldap option %d value", option_name);
678+
679+ memcpy (ret, db.data, db.len);
680+ ret[db.len] = 0;
681+ data_string_forget (&db, MDL);
682+ }
683+ else
684+ ret = NULL;
685+
686+ return (ret);
687+}
688+
689+
690+static int
691+_do_lookup_dhcp_int_option (struct option_state *options, int option_name)
692+{
693+ struct option_cache *oc;
694+ struct data_string db;
695+ int ret;
696+
697+ memset (&db, 0, sizeof (db));
698+ oc = lookup_option (&server_universe, options, option_name);
699+ if (oc &&
700+ evaluate_option_cache (&db, (struct packet*) NULL,
701+ (struct lease *) NULL,
702+ (struct client_state *) NULL, options,
703+ (struct option_state *) NULL,
704+ &global_scope, oc, MDL) &&
705+ db.data != NULL && *db.data != '\0')
706+ {
e5ebac8b 707+ ret = strtol ((const char *) db.data, NULL, 10);
a37573f1
JR
708+ data_string_forget (&db, MDL);
709+ }
710+ else
711+ ret = 0;
712+
713+ return (ret);
714+}
715+
716+
717+static int
718+_do_lookup_dhcp_enum_option (struct option_state *options, int option_name)
1097e9ca 719+{
1097e9ca 720+ struct option_cache *oc;
721+ struct data_string db;
e5ebac8b 722+ int ret = -1;
a37573f1
JR
723+
724+ memset (&db, 0, sizeof (db));
725+ oc = lookup_option (&server_universe, options, option_name);
726+ if (oc &&
727+ evaluate_option_cache (&db, (struct packet*) NULL,
728+ (struct lease *) NULL,
729+ (struct client_state *) NULL, options,
730+ (struct option_state *) NULL,
731+ &global_scope, oc, MDL) &&
732+ db.data != NULL && *db.data != '\0')
733+ {
734+ if (db.len == 1)
735+ ret = db.data [0];
736+ else
737+ log_fatal ("invalid option name %d", option_name);
738+
739+ data_string_forget (&db, MDL);
740+ }
741+ else
742+ ret = 0;
743+
744+ return (ret);
745+}
746+
747+int
748+ldap_rebind_cb (LDAP *ld, LDAP_CONST char *url, ber_tag_t request, ber_int_t msgid, void *parms)
749+{
750+ int ret;
751+ LDAPURLDesc *ldapurl = NULL;
e5ebac8b
AM
752+ char *who = NULL;
753+ struct berval creds;
a37573f1
JR
754+
755+ log_info("LDAP rebind to '%s'", url);
756+ if ((ret = ldap_url_parse(url, &ldapurl)) != LDAP_SUCCESS)
757+ {
758+ log_error ("Error: Can not parse ldap rebind url '%s': %s",
759+ url, ldap_err2string(ret));
760+ return ret;
761+ }
762+
763+
764+#if defined (USE_SSL)
765+ if (strcasecmp(ldapurl->lud_scheme, "ldaps") == 0)
766+ {
767+ int opt = LDAP_OPT_X_TLS_HARD;
768+ if ((ret = ldap_set_option (ld, LDAP_OPT_X_TLS, &opt)) != LDAP_SUCCESS)
769+ {
770+ log_error ("Error: Cannot init LDAPS session to %s:%d: %s",
771+ ldapurl->lud_host, ldapurl->lud_port, ldap_err2string (ret));
772+ return ret;
773+ }
774+ else
775+ {
776+ log_info ("LDAPS session successfully enabled to %s", ldap_server);
777+ }
778+ }
779+ else
780+ if (strcasecmp(ldapurl->lud_scheme, "ldap") == 0 &&
781+ ldap_use_ssl != LDAP_SSL_OFF)
782+ {
783+ if ((ret = ldap_start_tls_s (ld, NULL, NULL)) != LDAP_SUCCESS)
784+ {
785+ log_error ("Error: Cannot start TLS session to %s:%d: %s",
786+ ldapurl->lud_host, ldapurl->lud_port, ldap_err2string (ret));
787+ return ret;
788+ }
789+ else
790+ {
791+ log_info ("TLS session successfully started to %s:%d",
792+ ldapurl->lud_host, ldapurl->lud_port);
793+ }
794+ }
795+#endif
796+
797+
798+ if (ldap_username != NULL || *ldap_username != '\0')
799+ {
800+ who = ldap_username;
e5ebac8b
AM
801+ creds.bv_val = strdup(ldap_password);
802+ creds.bv_len = strlen(ldap_password);
a37573f1
JR
803+ }
804+
e5ebac8b
AM
805+ if ((ret = ldap_sasl_bind_s (ld, who, LDAP_SASL_SIMPLE, &creds,
806+ NULL, NULL, NULL)) != LDAP_SUCCESS)
a37573f1
JR
807+ {
808+ log_error ("Error: Cannot login into ldap server %s:%d: %s",
809+ ldapurl->lud_host, ldapurl->lud_port, ldap_err2string (ret));
810+ }
811+ return ret;
812+}
813+
814+static void
815+ldap_start (void)
816+{
817+ struct option_state *options;
1097e9ca 818+ int ret, version;
e5ebac8b
AM
819+ char *uri = NULL;
820+ struct berval creds;
1097e9ca 821+
822+ if (ld != NULL)
823+ return;
824+
825+ if (ldap_server == NULL)
826+ {
827+ options = NULL;
828+ option_state_allocate (&options, MDL);
829+
830+ execute_statements_in_scope ((struct binding_value **) NULL,
831+ (struct packet *) NULL, (struct lease *) NULL,
832+ (struct client_state *) NULL, (struct option_state *) NULL,
833+ options, &global_scope, root_group, (struct group *) NULL);
834+
a37573f1
JR
835+ ldap_server = _do_lookup_dhcp_string_option (options, SV_LDAP_SERVER);
836+ ldap_dhcp_server_cn = _do_lookup_dhcp_string_option (options,
837+ SV_LDAP_DHCP_SERVER_CN);
838+ ldap_port = _do_lookup_dhcp_int_option (options, SV_LDAP_PORT);
839+ ldap_base_dn = _do_lookup_dhcp_string_option (options, SV_LDAP_BASE_DN);
840+ ldap_method = _do_lookup_dhcp_enum_option (options, SV_LDAP_METHOD);
841+ ldap_debug_file = _do_lookup_dhcp_string_option (options,
842+ SV_LDAP_DEBUG_FILE);
843+ ldap_referrals = _do_lookup_dhcp_enum_option (options, SV_LDAP_REFERRALS);
1097e9ca 844+
a37573f1
JR
845+#if defined (USE_SSL)
846+ ldap_use_ssl = _do_lookup_dhcp_enum_option (options, SV_LDAP_SSL);
847+ if( ldap_use_ssl != LDAP_SSL_OFF)
1097e9ca 848+ {
a37573f1
JR
849+ ldap_tls_reqcert = _do_lookup_dhcp_enum_option (options, SV_LDAP_TLS_REQCERT);
850+ ldap_tls_ca_file = _do_lookup_dhcp_string_option (options, SV_LDAP_TLS_CA_FILE);
851+ ldap_tls_ca_dir = _do_lookup_dhcp_string_option (options, SV_LDAP_TLS_CA_DIR);
852+ ldap_tls_cert = _do_lookup_dhcp_string_option (options, SV_LDAP_TLS_CERT);
853+ ldap_tls_key = _do_lookup_dhcp_string_option (options, SV_LDAP_TLS_KEY);
854+ ldap_tls_crlcheck = _do_lookup_dhcp_enum_option (options, SV_LDAP_TLS_CRLCHECK);
855+ ldap_tls_ciphers = _do_lookup_dhcp_string_option (options, SV_LDAP_TLS_CIPHERS);
856+ ldap_tls_randfile = _do_lookup_dhcp_string_option (options, SV_LDAP_TLS_RANDFILE);
1097e9ca 857+ }
a37573f1 858+#endif
1097e9ca 859+
a37573f1
JR
860+#if defined (LDAP_CASA_AUTH)
861+ if (!load_uname_pwd_from_miCASA(&ldap_username,&ldap_password))
1097e9ca 862+ {
a37573f1
JR
863+#if defined (DEBUG_LDAP)
864+ log_info ("Authentication credential taken from file");
865+#endif
866+#endif
1097e9ca 867+
a37573f1
JR
868+ ldap_username = _do_lookup_dhcp_string_option (options, SV_LDAP_USERNAME);
869+ ldap_password = _do_lookup_dhcp_string_option (options, SV_LDAP_PASSWORD);
1097e9ca 870+
a37573f1
JR
871+#if defined (LDAP_CASA_AUTH)
872+ }
873+#endif
1097e9ca 874+
875+ option_state_dereference (&options, MDL);
876+ }
877+
878+ if (ldap_server == NULL || ldap_base_dn == NULL)
879+ {
880+ log_info ("Not searching LDAP since ldap-server, ldap-port and ldap-base-dn were not specified in the config file");
881+ ldap_method = LDAP_METHOD_STATIC;
882+ return;
883+ }
884+
885+ if (ldap_debug_file != NULL && ldap_debug_fd == -1)
886+ {
887+ if ((ldap_debug_fd = open (ldap_debug_file, O_CREAT | O_TRUNC | O_WRONLY,
888+ S_IRUSR | S_IWUSR)) < 0)
889+ log_error ("Error opening debug LDAP log file %s: %s", ldap_debug_file,
890+ strerror (errno));
891+ }
892+
893+#if defined (DEBUG_LDAP)
894+ log_info ("Connecting to LDAP server %s:%d", ldap_server, ldap_port);
895+#endif
896+
a37573f1
JR
897+#if defined (USE_SSL)
898+ if (ldap_use_ssl == -1)
899+ {
900+ /*
901+ ** There was no "ldap-ssl" option in dhcpd.conf (also not "off").
902+ ** Let's try, if we can use an anonymous TLS session without to
903+ ** verify the server certificate -- if not continue without TLS.
904+ */
905+ int opt = LDAP_OPT_X_TLS_ALLOW;
906+ if ((ret = ldap_set_option (NULL, LDAP_OPT_X_TLS_REQUIRE_CERT,
907+ &opt)) != LDAP_SUCCESS)
908+ {
909+ log_error ("Warning: Cannot set LDAP TLS require cert option to 'allow': %s",
910+ ldap_err2string (ret));
911+ }
912+ }
913+
914+ if (ldap_use_ssl != LDAP_SSL_OFF)
915+ {
916+ if (ldap_tls_reqcert != -1)
917+ {
918+ if ((ret = ldap_set_option (NULL, LDAP_OPT_X_TLS_REQUIRE_CERT,
919+ &ldap_tls_reqcert)) != LDAP_SUCCESS)
920+ {
921+ log_error ("Cannot set LDAP TLS require cert option: %s",
922+ ldap_err2string (ret));
923+ }
924+ }
925+
926+ if( ldap_tls_ca_file != NULL)
927+ {
928+ if ((ret = ldap_set_option (NULL, LDAP_OPT_X_TLS_CACERTFILE,
929+ ldap_tls_ca_file)) != LDAP_SUCCESS)
930+ {
931+ log_error ("Cannot set LDAP TLS CA certificate file %s: %s",
932+ ldap_tls_ca_file, ldap_err2string (ret));
933+ }
934+ }
935+ if( ldap_tls_ca_dir != NULL)
936+ {
937+ if ((ret = ldap_set_option (NULL, LDAP_OPT_X_TLS_CACERTDIR,
938+ ldap_tls_ca_dir)) != LDAP_SUCCESS)
939+ {
940+ log_error ("Cannot set LDAP TLS CA certificate dir %s: %s",
941+ ldap_tls_ca_dir, ldap_err2string (ret));
942+ }
943+ }
944+ if( ldap_tls_cert != NULL)
945+ {
946+ if ((ret = ldap_set_option (NULL, LDAP_OPT_X_TLS_CERTFILE,
947+ ldap_tls_cert)) != LDAP_SUCCESS)
948+ {
949+ log_error ("Cannot set LDAP TLS client certificate file %s: %s",
950+ ldap_tls_cert, ldap_err2string (ret));
951+ }
952+ }
953+ if( ldap_tls_key != NULL)
954+ {
955+ if ((ret = ldap_set_option (NULL, LDAP_OPT_X_TLS_KEYFILE,
956+ ldap_tls_key)) != LDAP_SUCCESS)
957+ {
958+ log_error ("Cannot set LDAP TLS certificate key file %s: %s",
959+ ldap_tls_key, ldap_err2string (ret));
960+ }
961+ }
962+ if( ldap_tls_crlcheck != -1)
963+ {
964+ int opt = ldap_tls_crlcheck;
965+ if ((ret = ldap_set_option (NULL, LDAP_OPT_X_TLS_CRLCHECK,
966+ &opt)) != LDAP_SUCCESS)
967+ {
968+ log_error ("Cannot set LDAP TLS crl check option: %s",
969+ ldap_err2string (ret));
970+ }
971+ }
972+ if( ldap_tls_ciphers != NULL)
973+ {
974+ if ((ret = ldap_set_option (NULL, LDAP_OPT_X_TLS_CIPHER_SUITE,
975+ ldap_tls_ciphers)) != LDAP_SUCCESS)
976+ {
977+ log_error ("Cannot set LDAP TLS cipher suite %s: %s",
978+ ldap_tls_ciphers, ldap_err2string (ret));
979+ }
980+ }
981+ if( ldap_tls_randfile != NULL)
982+ {
983+ if ((ret = ldap_set_option (NULL, LDAP_OPT_X_TLS_RANDOM_FILE,
984+ ldap_tls_randfile)) != LDAP_SUCCESS)
985+ {
986+ log_error ("Cannot set LDAP TLS random file %s: %s",
987+ ldap_tls_randfile, ldap_err2string (ret));
988+ }
989+ }
990+ }
991+#endif
992+
e5ebac8b
AM
993+ /* enough for 'ldap://+ + hostname + ':' + port number */
994+ uri = malloc(strlen(ldap_server) + 16);
995+ if (uri == NULL)
996+ {
997+ log_error ("Cannot build ldap init URI %s:%d", ldap_server, ldap_port);
998+ return;
999+ }
1000+
1001+ sprintf("ldap://%s:%d", ldap_server, ldap_port);
1002+ ldap_initialize(&ld, uri);
1003+
1004+ if (ld == NULL)
1097e9ca 1005+ {
a37573f1 1006+ log_error ("Cannot init ldap session to %s:%d", ldap_server, ldap_port);
1097e9ca 1007+ return;
1008+ }
1009+
e5ebac8b
AM
1010+ free(uri);
1011+
1097e9ca 1012+ version = LDAP_VERSION3;
1013+ if ((ret = ldap_set_option (ld, LDAP_OPT_PROTOCOL_VERSION, &version)) != LDAP_OPT_SUCCESS)
1014+ {
1015+ log_error ("Cannot set LDAP version to %d: %s", version,
1016+ ldap_err2string (ret));
1017+ }
1018+
a37573f1
JR
1019+ if (ldap_referrals != -1)
1020+ {
1021+ if ((ret = ldap_set_option (ld, LDAP_OPT_REFERRALS, ldap_referrals ?
1022+ LDAP_OPT_ON : LDAP_OPT_OFF)) != LDAP_OPT_SUCCESS)
1023+ {
1024+ log_error ("Cannot %s LDAP referrals option: %s",
1025+ (ldap_referrals ? "enable" : "disable"),
1026+ ldap_err2string (ret));
1027+ }
1028+ }
1029+
1030+ if ((ret = ldap_set_rebind_proc(ld, ldap_rebind_cb, NULL)) != LDAP_SUCCESS)
1031+ {
1032+ log_error ("Warning: Cannot set ldap rebind procedure: %s",
1033+ ldap_err2string (ret));
1034+ }
1035+
1097e9ca 1036+#if defined (USE_SSL)
a37573f1
JR
1037+ if (ldap_use_ssl == LDAP_SSL_LDAPS ||
1038+ (ldap_use_ssl == LDAP_SSL_ON && ldap_port == LDAPS_PORT))
1039+ {
1040+ int opt = LDAP_OPT_X_TLS_HARD;
1041+ if ((ret = ldap_set_option (ld, LDAP_OPT_X_TLS, &opt)) != LDAP_SUCCESS)
1042+ {
1043+ log_error ("Error: Cannot init LDAPS session to %s:%d: %s",
1044+ ldap_server, ldap_port, ldap_err2string (ret));
1045+ ldap_stop();
1046+ return;
1047+ }
1048+ else
1049+ {
1050+ log_info ("LDAPS session successfully enabled to %s:%d",
1051+ ldap_server, ldap_port);
1052+ }
1053+ }
1054+ else if (ldap_use_ssl != LDAP_SSL_OFF)
1055+ {
1056+ if ((ret = ldap_start_tls_s (ld, NULL, NULL)) != LDAP_SUCCESS)
1057+ {
1058+ log_error ("Error: Cannot start TLS session to %s:%d: %s",
1059+ ldap_server, ldap_port, ldap_err2string (ret));
1060+ ldap_stop();
1061+ return;
1062+ }
1063+ else
1064+ {
1065+ log_info ("TLS session successfully started to %s:%d",
1066+ ldap_server, ldap_port);
1067+ }
1068+ }
1097e9ca 1069+#endif
1070+
a37573f1 1071+ if (ldap_username != NULL && *ldap_username != '\0')
1097e9ca 1072+ {
e5ebac8b
AM
1073+ creds.bv_val = strdup(ldap_password);
1074+ creds.bv_len = strlen(ldap_password);
1075+
1076+ if ((ret == ldap_sasl_bind_s (ld, ldap_username, LDAP_SASL_SIMPLE,
1077+ &creds, NULL, NULL, NULL)) != LDAP_SUCCESS)
a37573f1
JR
1078+ {
1079+ log_error ("Error: Cannot login into ldap server %s:%d: %s",
1080+ ldap_server, ldap_port, ldap_err2string (ret));
1081+ ldap_stop();
1082+ return;
1083+ }
1097e9ca 1084+ }
1085+
1086+#if defined (DEBUG_LDAP)
1087+ log_info ("Successfully logged into LDAP server %s", ldap_server);
1088+#endif
1089+}
1090+
1091+
1092+static void
1093+parse_external_dns (LDAPMessage * ent)
1094+{
1095+ char *search[] = {"dhcpOptionsDN", "dhcpSharedNetworkDN", "dhcpSubnetDN",
a37573f1 1096+ "dhcpGroupDN", "dhcpHostDN", "dhcpClassesDN",
1097e9ca 1097+ "dhcpPoolDN", NULL};
1098+ LDAPMessage * newres, * newent;
e5ebac8b 1099+ struct berval **tempbv;
3150c1ff 1100+ int i, j, ret;
1101+#if defined (DEBUG_LDAP)
1102+ char *dn;
a37573f1
JR
1103+
1104+ dn = ldap_get_dn (ld, ent);
1105+ if (dn != NULL)
1106+ {
1107+ log_info ("Parsing external DNs for '%s'", dn);
1108+ ldap_memfree (dn);
1109+ }
3150c1ff 1110+#endif
1097e9ca 1111+
1112+ if (ld == NULL)
1113+ ldap_start ();
1114+ if (ld == NULL)
1115+ return;
1116+
1117+ for (i=0; search[i] != NULL; i++)
1118+ {
e5ebac8b 1119+ if ((tempbv = ldap_get_values_len (ld, ent, search[i])) == NULL)
1097e9ca 1120+ continue;
1121+
e5ebac8b 1122+ for (j=0; tempbv[j] != NULL; j++)
1097e9ca 1123+ {
e5ebac8b 1124+ if (*tempbv[j]->bv_val == '\0')
3150c1ff 1125+ continue;
1097e9ca 1126+
e5ebac8b
AM
1127+ if ((ret = ldap_search_ext_s(ld, tempbv[j]->bv_val, LDAP_SCOPE_BASE,
1128+ "objectClass=*", NULL, 0, NULL,
1129+ NULL, NULL, 0, &newres)) != LDAP_SUCCESS)
3150c1ff 1130+ {
e5ebac8b 1131+ ldap_value_free_len (tempbv);
a37573f1 1132+ ldap_stop();
3150c1ff 1133+ return;
1134+ }
1135+
1136+#if defined (DEBUG_LDAP)
e5ebac8b 1137+ log_info ("Adding contents of subtree '%s' to config stack from '%s' reference", tempbv[j], search[i]);
3150c1ff 1138+#endif
1139+ for (newent = ldap_first_entry (ld, newres);
1140+ newent != NULL;
a37573f1 1141+ newent = ldap_next_entry (ld, newent))
3150c1ff 1142+ {
1143+#if defined (DEBUG_LDAP)
1144+ dn = ldap_get_dn (ld, newent);
1145+ if (dn != NULL)
1146+ {
a37573f1 1147+ log_info ("Adding LDAP result set starting with '%s' to config stack", dn);
3150c1ff 1148+ ldap_memfree (dn);
1149+ }
1150+#endif
1097e9ca 1151+
3150c1ff 1152+ add_to_config_stack (newres, newent);
1153+ /* don't free newres here */
1154+ }
1097e9ca 1155+ }
1156+
e5ebac8b 1157+ ldap_value_free_len (tempbv);
1097e9ca 1158+ }
1159+}
1160+
1161+
1162+static void
1163+free_stack_entry (struct ldap_config_stack *item)
1164+{
a37573f1
JR
1165+ struct ldap_config_stack *look_ahead_pointer = item;
1166+ int may_free_msg = 1;
1167+
1168+ while (look_ahead_pointer->next != NULL)
1169+ {
1170+ look_ahead_pointer = look_ahead_pointer->next;
1171+ if (look_ahead_pointer->res == item->res)
1172+ {
1173+ may_free_msg = 0;
1174+ break;
1175+ }
1176+ }
1177+
1178+ if (may_free_msg)
1179+ ldap_msgfree (item->res);
1180+
1097e9ca 1181+ dfree (item, MDL);
1182+}
1183+
1184+
1185+static void
1186+next_ldap_entry (struct parse *cfile)
1187+{
1188+ struct ldap_config_stack *temp_stack;
1189+
1190+ if (ldap_stack != NULL && ldap_stack->close_brace)
1191+ {
a37573f1 1192+ x_strncat (cfile->inbuf, "}\n", LDAP_BUFFER_SIZE);
1097e9ca 1193+ ldap_stack->close_brace = 0;
1194+ }
1195+
1196+ while (ldap_stack != NULL &&
1197+ (ldap_stack->ldent == NULL ||
1198+ (ldap_stack->ldent = ldap_next_entry (ld, ldap_stack->ldent)) == NULL))
1199+ {
1200+ if (ldap_stack->close_brace)
1201+ {
a37573f1 1202+ x_strncat (cfile->inbuf, "}\n", LDAP_BUFFER_SIZE);
1097e9ca 1203+ ldap_stack->close_brace = 0;
1204+ }
1205+
1206+ temp_stack = ldap_stack;
1207+ ldap_stack = ldap_stack->next;
1208+ free_stack_entry (temp_stack);
1209+ }
1210+
1211+ if (ldap_stack != NULL && ldap_stack->close_brace)
1212+ {
a37573f1 1213+ x_strncat (cfile->inbuf, "}\n", LDAP_BUFFER_SIZE);
1097e9ca 1214+ ldap_stack->close_brace = 0;
1215+ }
1216+}
1217+
1218+
3150c1ff 1219+static char
1220+check_statement_end (const char *statement)
1221+{
1222+ char *ptr;
1223+
1224+ if (statement == NULL || *statement == '\0')
1225+ return ('\0');
1226+
1227+ /*
1228+ ** check if it ends with "}", e.g.:
1229+ ** "zone my.domain. { ... }"
1230+ ** optionally followed by spaces
1231+ */
1232+ ptr = strrchr (statement, '}');
1233+ if (ptr != NULL)
1234+ {
1235+ /* skip following white-spaces */
1236+ for (++ptr; isspace ((int)*ptr); ptr++);
1237+
1238+ /* check if we reached the end */
1239+ if (*ptr == '\0')
1240+ return ('}'); /* yes, block end */
1241+ else
1242+ return (*ptr);
1243+ }
1244+
1245+ /*
1246+ ** this should not happen, but...
1247+ ** check if it ends with ";", e.g.:
1248+ ** "authoritative;"
1249+ ** optionally followed by spaces
1250+ */
1251+ ptr = strrchr (statement, ';');
1252+ if (ptr != NULL)
1253+ {
1254+ /* skip following white-spaces */
1255+ for (++ptr; isspace ((int)*ptr); ptr++);
1256+
1257+ /* check if we reached the end */
1258+ if (*ptr == '\0')
1259+ return (';'); /* ends with a ; */
1260+ else
1261+ return (*ptr);
1262+ }
1263+
1264+ return ('\0');
1265+}
1266+
1267+
1268+static isc_result_t
1269+ldap_parse_entry_options (LDAPMessage *ent, char *buffer, size_t size,
1270+ int *lease_limit)
1271+{
e5ebac8b 1272+ struct berval **tempbv;
3150c1ff 1273+ int i;
1274+
1275+ if (ent == NULL || buffer == NULL || size == 0)
1276+ return (ISC_R_FAILURE);
1277+
e5ebac8b 1278+ if ((tempbv = ldap_get_values_len (ld, ent, "dhcpStatements")) != NULL)
3150c1ff 1279+ {
e5ebac8b 1280+ for (i=0; tempbv[i] != NULL; i++)
3150c1ff 1281+ {
1282+ if (lease_limit != NULL &&
e5ebac8b 1283+ strncasecmp ("lease limit ", tempbv[i]->bv_val, 12) == 0)
3150c1ff 1284+ {
e5ebac8b 1285+ *lease_limit = (int) strtol ((tempbv[i]->bv_val) + 12, NULL, 10);
3150c1ff 1286+ continue;
1287+ }
1288+
e5ebac8b 1289+ x_strncat (buffer, tempbv[i]->bv_val, size);
3150c1ff 1290+
e5ebac8b 1291+ switch((int) check_statement_end (tempbv[i]->bv_val))
3150c1ff 1292+ {
1293+ case '}':
1294+ case ';':
a37573f1 1295+ x_strncat (buffer, "\n", size);
3150c1ff 1296+ break;
1297+ default:
a37573f1 1298+ x_strncat (buffer, ";\n", size);
3150c1ff 1299+ break;
1300+ }
1301+ }
e5ebac8b 1302+ ldap_value_free_len (tempbv);
3150c1ff 1303+ }
1304+
e5ebac8b 1305+ if ((tempbv = ldap_get_values_len (ld, ent, "dhcpOption")) != NULL)
3150c1ff 1306+ {
e5ebac8b 1307+ for (i=0; tempbv[i] != NULL; i++)
3150c1ff 1308+ {
a37573f1 1309+ x_strncat (buffer, "option ", size);
e5ebac8b
AM
1310+ x_strncat (buffer, tempbv[i]->bv_val, size);
1311+ switch ((int) check_statement_end (tempbv[i]->bv_val))
3150c1ff 1312+ {
1313+ case ';':
a37573f1 1314+ x_strncat (buffer, "\n", size);
3150c1ff 1315+ break;
1316+ default:
a37573f1 1317+ x_strncat (buffer, ";\n", size);
3150c1ff 1318+ break;
1319+ }
1320+ }
e5ebac8b 1321+ ldap_value_free_len (tempbv);
3150c1ff 1322+ }
1323+
1324+ return (ISC_R_SUCCESS);
1325+}
1326+
1327+
1097e9ca 1328+static void
1329+ldap_generate_config_string (struct parse *cfile)
1330+{
e5ebac8b
AM
1331+ struct berval **objectClass;
1332+ char *dn;
1097e9ca 1333+ struct ldap_config_stack *entry;
1334+ LDAPMessage * ent, * res;
e5ebac8b 1335+ int i, ignore, found;
1097e9ca 1336+ int ret;
1337+
1338+ if (ld == NULL)
1339+ ldap_start ();
1340+ if (ld == NULL)
1341+ return;
1342+
1343+ entry = ldap_stack;
e5ebac8b 1344+ if ((objectClass = ldap_get_values_len (ld, entry->ldent,
1097e9ca 1345+ "objectClass")) == NULL)
1346+ return;
1347+
1348+ ignore = 0;
1349+ found = 1;
1350+ for (i=0; objectClass[i] != NULL; i++)
1351+ {
e5ebac8b 1352+ if (strcasecmp (objectClass[i]->bv_val, "dhcpSharedNetwork") == 0)
1097e9ca 1353+ ldap_parse_shared_network (entry, cfile);
e5ebac8b 1354+ else if (strcasecmp (objectClass[i]->bv_val, "dhcpClass") == 0)
1097e9ca 1355+ ldap_parse_class (entry, cfile);
e5ebac8b 1356+ else if (strcasecmp (objectClass[i]->bv_val, "dhcpSubnet") == 0)
1097e9ca 1357+ ldap_parse_subnet (entry, cfile);
e5ebac8b 1358+ else if (strcasecmp (objectClass[i]->bv_val, "dhcpPool") == 0)
1097e9ca 1359+ ldap_parse_pool (entry, cfile);
e5ebac8b 1360+ else if (strcasecmp (objectClass[i]->bv_val, "dhcpGroup") == 0)
1097e9ca 1361+ ldap_parse_group (entry, cfile);
e5ebac8b 1362+ else if (strcasecmp (objectClass[i]->bv_val, "dhcpTSigKey") == 0)
a37573f1 1363+ ldap_parse_key (entry, cfile);
e5ebac8b 1364+ else if (strcasecmp (objectClass[i]->bv_val, "dhcpDnsZone") == 0)
a37573f1 1365+ ldap_parse_zone (entry, cfile);
e5ebac8b 1366+ else if (strcasecmp (objectClass[i]->bv_val, "dhcpHost") == 0)
1097e9ca 1367+ {
1368+ if (ldap_method == LDAP_METHOD_STATIC)
1369+ ldap_parse_host (entry, cfile);
1370+ else
1371+ {
1372+ ignore = 1;
1373+ break;
1374+ }
1375+ }
e5ebac8b 1376+ else if (strcasecmp (objectClass[i]->bv_val, "dhcpSubClass") == 0)
1097e9ca 1377+ {
1378+ if (ldap_method == LDAP_METHOD_STATIC)
1379+ ldap_parse_subclass (entry, cfile);
1380+ else
1381+ {
1382+ ignore = 1;
1383+ break;
1384+ }
1385+ }
1386+ else
1387+ found = 0;
1388+
1389+ if (found && cfile->inbuf[0] == '\0')
1390+ {
1391+ ignore = 1;
1392+ break;
1393+ }
1394+ }
1395+
e5ebac8b 1396+ ldap_value_free_len (objectClass);
1097e9ca 1397+
1398+ if (ignore)
1399+ {
1400+ next_ldap_entry (cfile);
1401+ return;
1402+ }
1403+
3150c1ff 1404+ ldap_parse_entry_options(entry->ldent, cfile->inbuf,
1405+ LDAP_BUFFER_SIZE-1, NULL);
1097e9ca 1406+
1407+ dn = ldap_get_dn (ld, entry->ldent);
1408+
1409+#if defined(DEBUG_LDAP)
3150c1ff 1410+ if (dn != NULL)
1411+ log_info ("Found LDAP entry '%s'", dn);
1097e9ca 1412+#endif
1413+
3150c1ff 1414+ if (dn == NULL ||
e5ebac8b
AM
1415+ (ret = ldap_search_ext_s (ld, dn, LDAP_SCOPE_ONELEVEL,
1416+ "objectClass=*", NULL, 0, NULL, NULL,
1417+ NULL, 0, &res)) != LDAP_SUCCESS)
1097e9ca 1418+ {
3150c1ff 1419+ if (dn)
1420+ ldap_memfree (dn);
1421+
a37573f1 1422+ ldap_stop();
1097e9ca 1423+ return;
1424+ }
1425+
1426+ ldap_memfree (dn);
1427+
1428+ if ((ent = ldap_first_entry (ld, res)) != NULL)
1429+ {
1430+ add_to_config_stack (res, ent);
1431+ parse_external_dns (entry->ldent);
1432+ }
1433+ else
1434+ {
1435+ ldap_msgfree (res);
1436+ parse_external_dns (entry->ldent);
1437+ next_ldap_entry (cfile);
1438+ }
1439+}
1440+
1441+
3150c1ff 1442+static void
1443+ldap_close_debug_fd()
1444+{
1445+ if (ldap_debug_fd != -1)
1446+ {
1447+ close (ldap_debug_fd);
1448+ ldap_debug_fd = -1;
1449+ }
1450+}
1451+
1452+
1453+static void
1454+ldap_write_debug (const void *buff, size_t size)
1455+{
1456+ if (ldap_debug_fd != -1)
1457+ {
1458+ if (write (ldap_debug_fd, buff, size) < 0)
1459+ {
1460+ log_error ("Error writing to LDAP debug file %s: %s."
1461+ " Disabling log file.", ldap_debug_file,
1462+ strerror (errno));
1463+ ldap_close_debug_fd();
1464+ }
1465+ }
1466+}
1467+
a37573f1 1468+static int
1097e9ca 1469+ldap_read_function (struct parse *cfile)
1470+{
1097e9ca 1471+ cfile->inbuf[0] = '\0';
1472+ cfile->buflen = 0;
a37573f1 1473+
1097e9ca 1474+ while (ldap_stack != NULL && *cfile->inbuf == '\0')
1475+ ldap_generate_config_string (cfile);
1476+
a37573f1
JR
1477+ if (ldap_stack == NULL && *cfile->inbuf == '\0')
1478+ return (EOF);
1479+
1480+ cfile->bufix = 1;
1097e9ca 1481+ cfile->buflen = strlen (cfile->inbuf);
3150c1ff 1482+ if (cfile->buflen > 0)
1483+ ldap_write_debug (cfile->inbuf, cfile->buflen);
1097e9ca 1484+
1485+#if defined (DEBUG_LDAP)
1486+ log_info ("Sending config line '%s'", cfile->inbuf);
1487+#endif
1488+
1097e9ca 1489+ return (cfile->inbuf[0]);
1490+}
1491+
1492+
1493+static char *
1494+ldap_get_host_name (LDAPMessage * ent)
1495+{
e5ebac8b
AM
1496+ struct berval **name;
1497+ char *ret;
1097e9ca 1498+
1499+ ret = NULL;
e5ebac8b 1500+ if ((name = ldap_get_values_len (ld, ent, "cn")) == NULL || name[0] == NULL)
1097e9ca 1501+ {
1502+ if (name != NULL)
e5ebac8b 1503+ ldap_value_free_len (name);
1097e9ca 1504+
1505+#if defined (DEBUG_LDAP)
3150c1ff 1506+ ret = ldap_get_dn (ld, ent);
1507+ if (ret != NULL)
1508+ {
1509+ log_info ("Cannot get cn attribute for LDAP entry %s", ret);
1510+ ldap_memfree(ret);
1511+ }
1097e9ca 1512+#endif
1513+ return (NULL);
1514+ }
1515+
e5ebac8b
AM
1516+ ret = dmalloc (strlen (name[0]->bv_val) + 1, MDL);
1517+ strcpy (ret, name[0]->bv_val);
1518+ ldap_value_free_len (name);
1097e9ca 1519+
1520+ return (ret);
1521+}
1522+
1523+
3150c1ff 1524+static int
1525+getfqhostname(char *fqhost, size_t size)
1526+{
1527+#if defined(MAXHOSTNAMELEN)
1528+ char hname[MAXHOSTNAMELEN];
1529+#else
1530+ char hname[65];
1531+#endif
1532+ struct hostent *hp;
1533+
1534+ if(NULL == fqhost || 1 >= size)
1535+ return -1;
1536+
1537+ memset(hname, 0, sizeof(hname));
1538+ if( gethostname(hname, sizeof(hname)-1))
1539+ return -1;
1540+
1541+ if(NULL == (hp = gethostbyname(hname)))
1542+ return -1;
1543+
1544+ strncpy(fqhost, hp->h_name, size-1);
1545+ fqhost[size-1] = '\0';
1546+ return 0;
1547+}
1548+
1549+
1097e9ca 1550+isc_result_t
1551+ldap_read_config (void)
1552+{
1553+ LDAPMessage * ldres, * hostres, * ent, * hostent;
3150c1ff 1554+ char hfilter[1024], sfilter[1024], fqdn[257];
e5ebac8b 1555+ char *buffer, *hostdn;
3150c1ff 1556+ ldap_dn_node *curr = NULL;
1097e9ca 1557+ struct parse *cfile;
1558+ struct utsname unme;
1559+ isc_result_t res;
3150c1ff 1560+ size_t length;
1561+ int ret, cnt;
e5ebac8b 1562+ struct berval **tempbv = NULL;
1097e9ca 1563+
3150c1ff 1564+ if (ld == NULL)
1565+ ldap_start ();
1566+ if (ld == NULL)
1567+ return (ldap_server == NULL ? ISC_R_SUCCESS : ISC_R_FAILURE);
1568+
1569+ buffer = dmalloc (LDAP_BUFFER_SIZE+1, MDL);
1570+ if (buffer == NULL)
1571+ return (ISC_R_FAILURE);
1097e9ca 1572+
1097e9ca 1573+ cfile = (struct parse *) NULL;
1574+ res = new_parse (&cfile, -1, buffer, LDAP_BUFFER_SIZE, "LDAP", 0);
1575+ if (res != ISC_R_SUCCESS)
1576+ return (res);
3150c1ff 1577+
1097e9ca 1578+ uname (&unme);
a37573f1
JR
1579+ if (ldap_dhcp_server_cn != NULL)
1580+ {
1581+ snprintf (hfilter, sizeof (hfilter),
1582+ "(&(objectClass=dhcpServer)(cn=%s))", ldap_dhcp_server_cn);
1583+ }
1584+ else
1585+ {
3150c1ff 1586+ if(0 == getfqhostname(fqdn, sizeof(fqdn)))
1587+ {
1588+ snprintf (hfilter, sizeof (hfilter),
1589+ "(&(objectClass=dhcpServer)(|(cn=%s)(cn=%s)))",
1590+ unme.nodename, fqdn);
1591+ }
1592+ else
1593+ {
1594+ snprintf (hfilter, sizeof (hfilter),
1595+ "(&(objectClass=dhcpServer)(cn=%s))", unme.nodename);
1596+ }
1097e9ca 1597+
a37573f1 1598+ }
3150c1ff 1599+ hostres = NULL;
e5ebac8b
AM
1600+ if ((ret = ldap_search_ext_s (ld, ldap_base_dn, LDAP_SCOPE_SUBTREE,
1601+ hfilter, NULL, 0, NULL, NULL, NULL, 0,
1602+ &hostres)) != LDAP_SUCCESS)
1097e9ca 1603+ {
3150c1ff 1604+ log_error ("Cannot find host LDAP entry %s %s",
a37573f1 1605+ ((ldap_dhcp_server_cn == NULL)?(unme.nodename):(ldap_dhcp_server_cn)), hfilter);
3150c1ff 1606+ if(NULL != hostres)
1607+ ldap_msgfree (hostres);
a37573f1 1608+ ldap_stop();
1097e9ca 1609+ return (ISC_R_FAILURE);
1610+ }
1611+
1612+ if ((hostent = ldap_first_entry (ld, hostres)) == NULL)
1613+ {
3150c1ff 1614+ log_error ("Error: Cannot find LDAP entry matching %s", hfilter);
1615+ ldap_msgfree (hostres);
a37573f1 1616+ ldap_stop();
1097e9ca 1617+ return (ISC_R_FAILURE);
1618+ }
1619+
3150c1ff 1620+ hostdn = ldap_get_dn (ld, hostent);
1097e9ca 1621+#if defined(DEBUG_LDAP)
3150c1ff 1622+ if (hostdn != NULL)
1623+ log_info ("Found dhcpServer LDAP entry '%s'", hostdn);
1097e9ca 1624+#endif
1625+
3150c1ff 1626+ if (hostdn == NULL ||
e5ebac8b
AM
1627+ (tempbv = ldap_get_values_len (ld, hostent, "dhcpServiceDN")) == NULL ||
1628+ tempbv[0] == NULL)
1097e9ca 1629+ {
3150c1ff 1630+ log_error ("Error: Cannot find LDAP entry matching %s", hfilter);
1097e9ca 1631+
e5ebac8b
AM
1632+ if (tempbv != NULL)
1633+ ldap_value_free_len (tempbv);
1097e9ca 1634+
3150c1ff 1635+ if (hostdn)
1636+ ldap_memfree (hostdn);
1637+ ldap_msgfree (hostres);
a37573f1 1638+ ldap_stop();
1097e9ca 1639+ return (ISC_R_FAILURE);
1640+ }
1641+
3150c1ff 1642+#if defined(DEBUG_LDAP)
1643+ log_info ("LDAP: Parsing dhcpServer options '%s' ...", hostdn);
1644+#endif
1645+
1646+ cfile->inbuf[0] = '\0';
1647+ ldap_parse_entry_options(hostent, cfile->inbuf, LDAP_BUFFER_SIZE, NULL);
1648+ cfile->buflen = strlen (cfile->inbuf);
1649+ if(cfile->buflen > 0)
1097e9ca 1650+ {
3150c1ff 1651+ ldap_write_debug (cfile->inbuf, cfile->buflen);
1652+
1653+ res = conf_file_subparse (cfile, root_group, ROOT_GROUP);
1654+ if (res != ISC_R_SUCCESS)
1655+ {
1656+ log_error ("LDAP: cannot parse dhcpServer entry '%s'", hostdn);
1657+ ldap_memfree (hostdn);
a37573f1 1658+ ldap_stop();
3150c1ff 1659+ return res;
1660+ }
1661+ cfile->inbuf[0] = '\0';
1097e9ca 1662+ }
3150c1ff 1663+ ldap_msgfree (hostres);
1097e9ca 1664+
3150c1ff 1665+ /*
1666+ ** attach ldap (tree) read function now
1667+ */
1668+ cfile->bufix = cfile->buflen = 0;
1669+ cfile->read_function = ldap_read_function;
1670+
1671+ res = ISC_R_SUCCESS;
e5ebac8b 1672+ for (cnt=0; tempbv[cnt] != NULL; cnt++)
1097e9ca 1673+ {
3150c1ff 1674+ snprintf(sfilter, sizeof(sfilter), "(&(objectClass=dhcpService)"
1675+ "(|(dhcpPrimaryDN=%s)(dhcpSecondaryDN=%s)))",
1676+ hostdn, hostdn);
1677+ ldres = NULL;
e5ebac8b
AM
1678+ if ((ret = ldap_search_ext_s (ld, tempbv[cnt]->bv_val, LDAP_SCOPE_BASE,
1679+ sfilter, NULL, 0, NULL, NULL, NULL,
1680+ 0, &ldres)) != LDAP_SUCCESS)
3150c1ff 1681+ {
1682+ log_error ("Error searching for dhcpServiceDN '%s': %s. Please update the LDAP entry '%s'",
e5ebac8b 1683+ tempbv[cnt]->bv_val, ldap_err2string (ret), hostdn);
3150c1ff 1684+ if(NULL != ldres)
1685+ ldap_msgfree(ldres);
1686+ res = ISC_R_FAILURE;
1687+ break;
1688+ }
1689+
1690+ if ((ent = ldap_first_entry (ld, ldres)) == NULL)
1691+ {
1692+ log_error ("Error: Cannot find dhcpService DN '%s' with primary or secondary server reference. Please update the LDAP server entry '%s'",
e5ebac8b 1693+ tempbv[cnt]->bv_val, hostdn);
3150c1ff 1694+
1695+ ldap_msgfree(ldres);
1696+ res = ISC_R_FAILURE;
1697+ break;
1698+ }
1699+
1700+ /*
1701+ ** FIXME: how to free the remembered dn's on exit?
1702+ ** This should be OK if dmalloc registers the
1703+ ** memory it allocated and frees it on exit..
1704+ */
1705+
1706+ curr = dmalloc (sizeof (*curr), MDL);
1707+ if (curr != NULL)
1708+ {
e5ebac8b 1709+ length = strlen (tempbv[cnt]->bv_val);
3150c1ff 1710+ curr->dn = dmalloc (length + 1, MDL);
1711+ if (curr->dn == NULL)
1712+ {
1713+ dfree (curr, MDL);
1714+ curr = NULL;
1715+ }
1716+ else
e5ebac8b 1717+ strcpy (curr->dn, tempbv[cnt]->bv_val);
3150c1ff 1718+ }
1719+
1720+ if (curr != NULL)
1721+ {
1722+ curr->refs++;
1723+
1724+ /* append to service-dn list */
1725+ if (ldap_service_dn_tail != NULL)
1726+ ldap_service_dn_tail->next = curr;
1727+ else
1728+ ldap_service_dn_head = curr;
1729+
1730+ ldap_service_dn_tail = curr;
1731+ }
1732+ else
1733+ log_fatal ("no memory to remember ldap service dn");
1734+
1735+#if defined (DEBUG_LDAP)
e5ebac8b 1736+ log_info ("LDAP: Parsing dhcpService DN '%s' ...", tempbv[cnt]);
3150c1ff 1737+#endif
1738+ add_to_config_stack (ldres, ent);
1739+ res = conf_file_subparse (cfile, root_group, ROOT_GROUP);
1740+ if (res != ISC_R_SUCCESS)
1741+ {
e5ebac8b 1742+ log_error ("LDAP: cannot parse dhcpService entry '%s'", tempbv[cnt]->bv_val);
3150c1ff 1743+ break;
1744+ }
1097e9ca 1745+ }
1746+
3150c1ff 1747+ end_parse (&cfile);
1748+ ldap_close_debug_fd();
1097e9ca 1749+
3150c1ff 1750+ ldap_memfree (hostdn);
e5ebac8b 1751+ ldap_value_free_len (tempbv);
1097e9ca 1752+
3150c1ff 1753+ if (res != ISC_R_SUCCESS)
1754+ {
1755+ struct ldap_config_stack *temp_stack;
1097e9ca 1756+
3150c1ff 1757+ while ((curr = ldap_service_dn_head) != NULL)
1758+ {
1759+ ldap_service_dn_head = curr->next;
1760+ dfree (curr->dn, MDL);
1761+ dfree (curr, MDL);
1762+ }
1763+
1764+ ldap_service_dn_tail = NULL;
1765+
1766+ while ((temp_stack = ldap_stack) != NULL)
1767+ {
1768+ ldap_stack = temp_stack->next;
1769+ free_stack_entry (temp_stack);
1770+ }
1771+
a37573f1 1772+ ldap_stop();
3150c1ff 1773+ }
1097e9ca 1774+
a37573f1
JR
1775+ /* Unbind from ldap immediately after reading config in static mode. */
1776+ if (ldap_method == LDAP_METHOD_STATIC)
1777+ ldap_stop();
1778+
1097e9ca 1779+ return (res);
1780+}
1781+
1782+
1783+/* This function will parse the dhcpOption and dhcpStatements field in the LDAP
1784+ entry if it exists. Right now, type will be either HOST_DECL or CLASS_DECL.
1785+ If we are parsing a HOST_DECL, this always returns 0. If we are parsing a
1786+ CLASS_DECL, this will return what the current lease limit is in LDAP. If
1787+ there is no lease limit specified, we return 0 */
1788+
1789+static int
1790+ldap_parse_options (LDAPMessage * ent, struct group *group,
1791+ int type, struct host_decl *host,
1792+ struct class **class)
1793+{
e5ebac8b 1794+ int declaration, lease_limit;
3150c1ff 1795+ char option_buffer[8192];
1097e9ca 1796+ enum dhcp_token token;
1797+ struct parse *cfile;
1798+ isc_result_t res;
1799+ const char *val;
1800+
1801+ lease_limit = 0;
1802+ *option_buffer = '\0';
a37573f1
JR
1803+
1804+ /* This block of code will try to find the parent of the host, and
1805+ if it is a group object, fetch the options and apply to the host. */
1806+ if (type == HOST_DECL)
1807+ {
1808+ char *hostdn, *basedn, *temp1, *temp2, filter[1024];
1809+ LDAPMessage *groupdn, *entry;
1810+ int ret;
1811+
1812+ hostdn = ldap_get_dn (ld, ent);
1813+ if( hostdn != NULL)
1814+ {
1815+ basedn = NULL;
1816+
1817+ temp1 = strchr (hostdn, '=');
1818+ if (temp1 != NULL)
1819+ temp1 = strchr (++temp1, '=');
1820+ if (temp1 != NULL)
1821+ temp2 = strchr (++temp1, ',');
1822+ else
1823+ temp2 = NULL;
1824+
1825+ if (temp2 != NULL)
1826+ {
1827+ snprintf (filter, sizeof(filter),
1828+ "(&(cn=%.*s)(objectClass=dhcpGroup))",
1829+ (int)(temp2 - temp1), temp1);
1830+
1831+ basedn = strchr (temp1, ',');
1832+ if (basedn != NULL)
1833+ ++basedn;
1834+ }
1835+
1836+ if (basedn != NULL && *basedn != '\0')
1837+ {
e5ebac8b
AM
1838+ ret = ldap_search_ext_s (ld, basedn, LDAP_SCOPE_SUBTREE, filter,
1839+ NULL, 0, NULL, NULL, NULL, 0, &groupdn);
a37573f1
JR
1840+ if (ret == LDAP_SUCCESS)
1841+ {
1842+ if ((entry = ldap_first_entry (ld, groupdn)) != NULL)
1843+ {
1844+ res = ldap_parse_entry_options (entry, option_buffer,
1845+ sizeof(option_buffer) - 1,
1846+ &lease_limit);
1847+ if (res != ISC_R_SUCCESS)
1848+ {
1849+ /* reset option buffer discarding any results */
1850+ *option_buffer = '\0';
1851+ lease_limit = 0;
1852+ }
1853+ }
1854+ ldap_msgfree( groupdn);
1855+ }
1856+ }
1857+ ldap_memfree( hostdn);
1858+ }
1859+ }
1860+
3150c1ff 1861+ res = ldap_parse_entry_options (ent, option_buffer, sizeof(option_buffer) - 1,
1862+ &lease_limit);
1863+ if (res != ISC_R_SUCCESS)
1864+ return (lease_limit);
1097e9ca 1865+
3150c1ff 1866+ option_buffer[sizeof(option_buffer) - 1] = '\0';
1097e9ca 1867+ if (*option_buffer == '\0')
1868+ return (lease_limit);
1869+
1870+ cfile = (struct parse *) NULL;
1871+ res = new_parse (&cfile, -1, option_buffer, strlen (option_buffer),
1872+ type == HOST_DECL ? "LDAP-HOST" : "LDAP-SUBCLASS", 0);
1873+ if (res != ISC_R_SUCCESS)
1874+ return (lease_limit);
1875+
1876+#if defined (DEBUG_LDAP)
1877+ log_info ("Sending the following options: '%s'", option_buffer);
1878+#endif
1879+
1880+ declaration = 0;
3150c1ff 1881+ do
1882+ {
1883+ token = peek_token (&val, NULL, cfile);
1884+ if (token == END_OF_FILE)
1885+ break;
1886+ declaration = parse_statement (cfile, group, type, host, declaration);
1097e9ca 1887+ } while (1);
1888+
1889+ end_parse (&cfile);
1890+
1891+ return (lease_limit);
1892+}
1893+
1894+
1895+
1896+int
1897+find_haddr_in_ldap (struct host_decl **hp, int htype, unsigned hlen,
1898+ const unsigned char *haddr, const char *file, int line)
1899+{
e5ebac8b 1900+ char buf[128], *type_str;
1097e9ca 1901+ LDAPMessage * res, *ent;
1902+ struct host_decl * host;
1903+ isc_result_t status;
3150c1ff 1904+ ldap_dn_node *curr;
1097e9ca 1905+ int ret;
1906+
1907+ if (ldap_method == LDAP_METHOD_STATIC)
1908+ return (0);
1909+
1910+ if (ld == NULL)
1911+ ldap_start ();
1912+ if (ld == NULL)
1913+ return (0);
1914+
1915+ switch (htype)
1916+ {
1917+ case HTYPE_ETHER:
1918+ type_str = "ethernet";
1919+ break;
1920+ case HTYPE_IEEE802:
1921+ type_str = "token-ring";
1922+ break;
1923+ case HTYPE_FDDI:
1924+ type_str = "fddi";
1925+ break;
1926+ default:
1927+ log_info ("Ignoring unknown type %d", htype);
1928+ return (0);
1929+ }
1930+
1931+ /*
a37573f1
JR
1932+ ** FIXME: It is not guaranteed, that the dhcpHWAddress attribute
1933+ ** contains _exactly_ "type addr" with one space between!
1097e9ca 1934+ */
1935+ snprintf (buf, sizeof (buf),
1936+ "(&(objectClass=dhcpHost)(dhcpHWAddress=%s %s))",
3150c1ff 1937+ type_str, print_hw_addr (htype, hlen, haddr));
1097e9ca 1938+
3150c1ff 1939+ res = ent = NULL;
1940+ for (curr = ldap_service_dn_head;
1941+ curr != NULL && *curr->dn != '\0';
1942+ curr = curr->next)
1943+ {
1097e9ca 1944+#if defined (DEBUG_LDAP)
3150c1ff 1945+ log_info ("Searching for %s in LDAP tree %s", buf, curr->dn);
1097e9ca 1946+#endif
e5ebac8b
AM
1947+ ret = ldap_search_ext_s (ld, curr->dn, LDAP_SCOPE_SUBTREE, buf, NULL, 0,
1948+ NULL, NULL, NULL, 0, &res);
a37573f1
JR
1949+
1950+ if(ret == LDAP_SERVER_DOWN)
1951+ {
1952+ log_info ("LDAP server was down, trying to reconnect...");
1953+
1954+ ldap_stop();
1955+ ldap_start();
1956+ if(ld == NULL)
1957+ {
1958+ log_info ("LDAP reconnect failed - try again later...");
1959+ return (0);
1960+ }
1961+
e5ebac8b
AM
1962+ ret = ldap_search_ext_s (ld, curr->dn, LDAP_SCOPE_SUBTREE, buf, NULL,
1963+ 0, NULL, NULL, NULL, 0, &res);
a37573f1
JR
1964+ }
1965+
3150c1ff 1966+ if (ret == LDAP_SUCCESS)
1097e9ca 1967+ {
3150c1ff 1968+ if( (ent = ldap_first_entry (ld, res)) != NULL)
1969+ break; /* search OK and have entry */
1970+
1097e9ca 1971+#if defined (DEBUG_LDAP)
3150c1ff 1972+ log_info ("No host entry for %s in LDAP tree %s",
1973+ buf, curr->dn);
1097e9ca 1974+#endif
3150c1ff 1975+ if(res)
1976+ {
1977+ ldap_msgfree (res);
1978+ res = NULL;
1979+ }
1980+ }
1981+ else
1982+ {
1983+ if(res)
1984+ {
1985+ ldap_msgfree (res);
1986+ res = NULL;
1987+ }
1097e9ca 1988+
3150c1ff 1989+ if (ret != LDAP_NO_SUCH_OBJECT && ret != LDAP_SUCCESS)
1990+ {
1991+ log_error ("Cannot search for %s in LDAP tree %s: %s", buf,
1992+ curr->dn, ldap_err2string (ret));
a37573f1 1993+ ldap_stop();
3150c1ff 1994+ return (0);
1995+ }
1996+#if defined (DEBUG_LDAP)
1997+ else
1998+ {
e5ebac8b 1999+ log_info ("ldap_search_ext_s returned %s when searching for %s in %s",
3150c1ff 2000+ ldap_err2string (ret), buf, curr->dn);
2001+ }
2002+#endif
2003+ }
1097e9ca 2004+ }
2005+
3150c1ff 2006+ if (res && ent)
1097e9ca 2007+ {
2008+#if defined (DEBUG_LDAP)
3150c1ff 2009+ char *dn = ldap_get_dn (ld, ent);
2010+ if (dn != NULL)
2011+ {
2012+ log_info ("Found dhcpHWAddress LDAP entry %s", dn);
2013+ ldap_memfree(dn);
2014+ }
1097e9ca 2015+#endif
3150c1ff 2016+
1097e9ca 2017+ host = (struct host_decl *)0;
2018+ status = host_allocate (&host, MDL);
2019+ if (status != ISC_R_SUCCESS)
2020+ {
2021+ log_fatal ("can't allocate host decl struct: %s",
2022+ isc_result_totext (status));
3150c1ff 2023+ ldap_msgfree (res);
1097e9ca 2024+ return (0);
2025+ }
2026+
2027+ host->name = ldap_get_host_name (ent);
2028+ if (host->name == NULL)
2029+ {
2030+ host_dereference (&host, MDL);
2031+ ldap_msgfree (res);
2032+ return (0);
2033+ }
2034+
2035+ if (!clone_group (&host->group, root_group, MDL))
2036+ {
2037+ log_fatal ("can't clone group for host %s", host->name);
2038+ host_dereference (&host, MDL);
3150c1ff 2039+ ldap_msgfree (res);
1097e9ca 2040+ return (0);
2041+ }
2042+
2043+ ldap_parse_options (ent, host->group, HOST_DECL, host, NULL);
2044+
2045+ *hp = host;
2046+ ldap_msgfree (res);
2047+ return (1);
2048+ }
2049+
2050+
3150c1ff 2051+ if(res) ldap_msgfree (res);
1097e9ca 2052+ return (0);
2053+}
2054+
2055+
2056+int
2057+find_subclass_in_ldap (struct class *class, struct class **newclass,
2058+ struct data_string *data)
2059+{
2060+ LDAPMessage * res, * ent;
e5ebac8b 2061+ int ret, lease_limit;
1097e9ca 2062+ isc_result_t status;
3150c1ff 2063+ ldap_dn_node *curr;
1097e9ca 2064+ char buf[1024];
2065+
2066+ if (ldap_method == LDAP_METHOD_STATIC)
2067+ return (0);
2068+
2069+ if (ld == NULL)
2070+ ldap_start ();
2071+ if (ld == NULL)
2072+ return (0);
2073+
a37573f1
JR
2074+ snprintf (buf, sizeof (buf),
2075+ "(&(objectClass=dhcpSubClass)(cn=%s)(dhcpClassData=%s))",
2076+ print_hex_1 (data->len, data->data, 60),
e5ebac8b 2077+ print_hex_2 (strlen (class->name), (u_int8_t *) class->name, 60));
1097e9ca 2078+#if defined (DEBUG_LDAP)
2079+ log_info ("Searching LDAP for %s", buf);
2080+#endif
2081+
3150c1ff 2082+ res = ent = NULL;
2083+ for (curr = ldap_service_dn_head;
2084+ curr != NULL && *curr->dn != '\0';
2085+ curr = curr->next)
1097e9ca 2086+ {
3150c1ff 2087+#if defined (DEBUG_LDAP)
2088+ log_info ("Searching for %s in LDAP tree %s", buf, curr->dn);
2089+#endif
e5ebac8b
AM
2090+ ret = ldap_search_ext_s (ld, curr->dn, LDAP_SCOPE_SUBTREE, buf, NULL, 0,
2091+ NULL, NULL, NULL, 0, &res);
a37573f1
JR
2092+
2093+ if(ret == LDAP_SERVER_DOWN)
2094+ {
2095+ log_info ("LDAP server was down, trying to reconnect...");
2096+
2097+ ldap_stop();
2098+ ldap_start();
2099+
2100+ if(ld == NULL)
2101+ {
2102+ log_info ("LDAP reconnect failed - try again later...");
2103+ return (0);
2104+ }
2105+
e5ebac8b
AM
2106+ ret = ldap_search_ext_s (ld, curr->dn, LDAP_SCOPE_SUBTREE, buf,
2107+ NULL, 0, NULL, NULL, NULL, 0, &res);
a37573f1
JR
2108+ }
2109+
3150c1ff 2110+ if (ret == LDAP_SUCCESS)
1097e9ca 2111+ {
3150c1ff 2112+ if( (ent = ldap_first_entry (ld, res)) != NULL)
2113+ break; /* search OK and have entry */
2114+
1097e9ca 2115+#if defined (DEBUG_LDAP)
3150c1ff 2116+ log_info ("No subclass entry for %s in LDAP tree %s",
2117+ buf, curr->dn);
1097e9ca 2118+#endif
3150c1ff 2119+ if(res)
2120+ {
2121+ ldap_msgfree (res);
2122+ res = NULL;
2123+ }
2124+ }
2125+ else
2126+ {
2127+ if(res)
2128+ {
2129+ ldap_msgfree (res);
2130+ res = NULL;
2131+ }
1097e9ca 2132+
3150c1ff 2133+ if (ret != LDAP_NO_SUCH_OBJECT && ret != LDAP_SUCCESS)
2134+ {
2135+ log_error ("Cannot search for %s in LDAP tree %s: %s", buf,
2136+ curr->dn, ldap_err2string (ret));
a37573f1 2137+ ldap_stop();
3150c1ff 2138+ return (0);
2139+ }
2140+#if defined (DEBUG_LDAP)
2141+ else
2142+ {
e5ebac8b 2143+ log_info ("ldap_search_ext_s returned %s when searching for %s in %s",
3150c1ff 2144+ ldap_err2string (ret), buf, curr->dn);
2145+ }
2146+#endif
2147+ }
1097e9ca 2148+ }
2149+
3150c1ff 2150+ if (res && ent)
1097e9ca 2151+ {
2152+#if defined (DEBUG_LDAP)
3150c1ff 2153+ char *dn = ldap_get_dn (ld, ent);
2154+ if (dn != NULL)
2155+ {
2156+ log_info ("Found subclass LDAP entry %s", dn);
2157+ ldap_memfree(dn);
2158+ }
1097e9ca 2159+#endif
3150c1ff 2160+
1097e9ca 2161+ status = class_allocate (newclass, MDL);
2162+ if (status != ISC_R_SUCCESS)
2163+ {
2164+ log_error ("Cannot allocate memory for a new class");
3150c1ff 2165+ ldap_msgfree (res);
1097e9ca 2166+ return (0);
2167+ }
2168+
2169+ group_reference (&(*newclass)->group, class->group, MDL);
2170+ class_reference (&(*newclass)->superclass, class, MDL);
2171+ lease_limit = ldap_parse_options (ent, (*newclass)->group,
2172+ CLASS_DECL, NULL, newclass);
2173+ if (lease_limit == 0)
2174+ (*newclass)->lease_limit = class->lease_limit;
2175+ else
2176+ class->lease_limit = lease_limit;
2177+
2178+ if ((*newclass)->lease_limit)
2179+ {
2180+ (*newclass)->billed_leases =
2181+ dmalloc ((*newclass)->lease_limit * sizeof (struct lease *), MDL);
2182+ if (!(*newclass)->billed_leases)
2183+ {
2184+ log_error ("no memory for billing");
2185+ class_dereference (newclass, MDL);
3150c1ff 2186+ ldap_msgfree (res);
1097e9ca 2187+ return (0);
2188+ }
2189+ memset ((*newclass)->billed_leases, 0,
2190+ ((*newclass)->lease_limit * sizeof (*newclass)->billed_leases));
2191+ }
2192+
2193+ data_string_copy (&(*newclass)->hash_string, data, MDL);
2194+
2195+ ldap_msgfree (res);
2196+ return (1);
2197+ }
2198+
3150c1ff 2199+ if(res) ldap_msgfree (res);
1097e9ca 2200+ return (0);
2201+}
2202+
2203+#endif
e5ebac8b
AM
2204diff -up dhcp-4.0.0/server/confpars.c.ldap dhcp-4.0.0/server/confpars.c
2205--- dhcp-4.0.0/server/confpars.c.ldap 2007-11-30 11:51:43.000000000 -1000
2206+++ dhcp-4.0.0/server/confpars.c 2008-01-22 15:09:56.000000000 -1000
2207@@ -60,7 +60,17 @@ void parse_trace_setup ()
2208
2209 isc_result_t readconf ()
2210 {
2211- return read_conf_file (path_dhcpd_conf, root_group, ROOT_GROUP, 0);
2212+ isc_result_t res;
a37573f1 2213+
e5ebac8b
AM
2214+ res = read_conf_file (path_dhcpd_conf, root_group, ROOT_GROUP, 0);
2215+#if defined(LDAP_CONFIGURATION)
2216+ if (res != ISC_R_SUCCESS)
2217+ return (res);
a37573f1 2218+
e5ebac8b
AM
2219+ return ldap_read_config ();
2220+#else
2221+ return (res);
a37573f1 2222+#endif
e5ebac8b
AM
2223 }
2224
2225 isc_result_t read_conf_file (const char *filename, struct group *group,
2226diff -up dhcp-4.0.0/server/class.c.ldap dhcp-4.0.0/server/class.c
2227--- dhcp-4.0.0/server/class.c.ldap 2007-09-05 07:32:10.000000000 -1000
2228+++ dhcp-4.0.0/server/class.c 2008-01-22 15:09:56.000000000 -1000
2229@@ -84,6 +84,7 @@ int check_collection (packet, lease, col
2230 int matched = 0;
2231 int status;
2232 int ignorep;
2233+ int classfound;
2234
2235 for (class = collection -> classes; class; class = class -> nic) {
2236 #if defined (DEBUG_CLASS_MATCHING)
2237@@ -129,9 +130,15 @@ int check_collection (packet, lease, col
2238 class -> submatch, MDL));
2239 if (status && data.len) {
2240 nc = (struct class *)0;
2241- if (class_hash_lookup (&nc, class -> hash,
2242- (const char *)data.data,
2243- data.len, MDL)) {
2244+ classfound = class_hash_lookup (&nc, class -> hash,
2245+ (const char *)data.data, data.len, MDL);
a37573f1 2246+
e5ebac8b
AM
2247+#ifdef LDAP_CONFIGURATION
2248+ if (!classfound && find_subclass_in_ldap (class, &nc, &data))
2249+ classfound = 1;
1097e9ca 2250+#endif
e5ebac8b
AM
2251+
2252+ if (classfound) {
2253 #if defined (DEBUG_CLASS_MATCHING)
2254 log_info ("matches subclass %s.",
2255 print_hex_1 (data.len,
2256diff -up dhcp-4.0.0/server/stables.c.ldap dhcp-4.0.0/server/stables.c
2257--- dhcp-4.0.0/server/stables.c.ldap 2007-11-20 08:34:37.000000000 -1000
2258+++ dhcp-4.0.0/server/stables.c 2008-01-22 15:09:56.000000000 -1000
2259@@ -238,9 +238,107 @@ static struct option server_options[] =
2260 { "dhcpv6-lease-file-name", "t", &server_universe, 54, 1 },
2261 { "dhcpv6-pid-file-name", "t", &server_universe, 55, 1 },
2262 { "limit-addrs-per-ia", "L", &server_universe, 56, 1 },
1097e9ca 2263+#if defined(LDAP_CONFIGURATION)
e5ebac8b
AM
2264+ { "ldap-server", "t", &server_universe, 57, 1 },
2265+ { "ldap-port", "d", &server_universe, 58, 1 },
2266+ { "ldap-username", "t", &server_universe, 59, 1 },
2267+ { "ldap-password", "t", &server_universe, 60, 1 },
2268+ { "ldap-base-dn", "t", &server_universe, 61, 1 },
2269+ { "ldap-method", "Nldap-methods.", &server_universe, 62, 1 },
2270+ { "ldap-debug-file", "t", &server_universe, 63, 1 },
2271+ { "ldap-dhcp-server-cn", "t", &server_universe, 64, 1 },
2272+ { "ldap-referrals", "f", &server_universe, 65, 1 },
a37573f1 2273+#if defined(USE_SSL)
e5ebac8b
AM
2274+ { "ldap-ssl", "Nldap-ssl-usage.", &server_universe, 66, 1 },
2275+ { "ldap-tls-reqcert", "Nldap-tls-reqcert.", &server_universe, 67, 1 },
2276+ { "ldap-tls-ca-file", "t", &server_universe, 68, 1 },
2277+ { "ldap-tls-ca-dir", "t", &server_universe, 69, 1 },
2278+ { "ldap-tls-cert", "t", &server_universe, 70, 1 },
2279+ { "ldap-tls-key", "t", &server_universe, 71, 1 },
2280+ { "ldap-tls-crlcheck", "Nldap-tls-crlcheck.", &server_universe, 72, 1 },
2281+ { "ldap-tls-ciphers", "t", &server_universe, 73, 1 },
2282+ { "ldap-tls-randfile", "t", &server_universe, 74, 1 },
2283+#else
2284+ { "unknown-66", "X", &server_universe, 66, 1 },
2285+ { "unknown-67", "X", &server_universe, 67, 1 },
2286+ { "unknown-68", "X", &server_universe, 68, 1 },
2287+ { "unknown-69", "X", &server_universe, 69, 1 },
2288+ { "unknown-70", "X", &server_universe, 70, 1 },
2289+ { "unknown-71", "X", &server_universe, 71, 1 },
2290+ { "unknown-72", "X", &server_universe, 72, 1 },
2291+ { "unknown-73", "X", &server_universe, 73, 1 },
2292+ { "unknown-74", "X", &server_universe, 74, 1 },
a37573f1 2293+#endif
e5ebac8b
AM
2294+#else
2295+ { "unknown-57", "X", &server_universe, 57, 1 },
2296+ { "unknown-58", "X", &server_universe, 58, 1 },
2297+ { "unknown-59", "X", &server_universe, 59, 1 },
2298+ { "unknown-60", "X", &server_universe, 60, 1 },
2299+ { "unknown-61", "X", &server_universe, 61, 1 },
2300+ { "unknown-62", "X", &server_universe, 62, 1 },
2301+ { "unknown-63", "X", &server_universe, 63, 1 },
2302+ { "unknown-64", "X", &server_universe, 64, 1 },
2303+ { "unknown-65", "X", &server_universe, 65, 1 },
1097e9ca 2304+#endif
e0a22902 2305 { NULL, NULL, NULL, 0, 0 }
1097e9ca 2306 };
2307
2308+#if defined(LDAP_CONFIGURATION)
2309+struct enumeration_value ldap_values [] = {
2310+ { "static", LDAP_METHOD_STATIC },
2311+ { "dynamic", LDAP_METHOD_DYNAMIC },
2312+ { (char *) 0, 0 }
2313+};
2314+
2315+struct enumeration ldap_methods = {
2316+ (struct enumeration *)0,
e5ebac8b 2317+ "ldap-methods", 1,
1097e9ca 2318+ ldap_values
2319+};
a37573f1
JR
2320+
2321+#if defined(USE_SSL)
2322+struct enumeration_value ldap_ssl_usage_values [] = {
e5ebac8b
AM
2323+ { "off", LDAP_SSL_OFF },
2324+ { "on",LDAP_SSL_ON },
2325+ { "ldaps", LDAP_SSL_LDAPS },
2326+ { "start_tls", LDAP_SSL_TLS },
a37573f1
JR
2327+ { (char *) 0, 0 }
2328+};
e5ebac8b 2329+
a37573f1
JR
2330+struct enumeration ldap_ssl_usage_enum = {
2331+ (struct enumeration *)0,
e5ebac8b 2332+ "ldap-ssl-usage", 1,
a37573f1
JR
2333+ ldap_ssl_usage_values
2334+};
2335+
2336+struct enumeration_value ldap_tls_reqcert_values [] = {
e5ebac8b
AM
2337+ { "never", LDAP_OPT_X_TLS_NEVER },
2338+ { "hard", LDAP_OPT_X_TLS_HARD },
a37573f1 2339+ { "demand", LDAP_OPT_X_TLS_DEMAND},
e5ebac8b
AM
2340+ { "allow", LDAP_OPT_X_TLS_ALLOW },
2341+ { "try", LDAP_OPT_X_TLS_TRY },
a37573f1
JR
2342+ { (char *) 0, 0 }
2343+};
2344+struct enumeration ldap_tls_reqcert_enum = {
2345+ (struct enumeration *)0,
e5ebac8b 2346+ "ldap-tls-reqcert", 1,
a37573f1
JR
2347+ ldap_tls_reqcert_values
2348+};
2349+
2350+struct enumeration_value ldap_tls_crlcheck_values [] = {
2351+ { "none", LDAP_OPT_X_TLS_CRL_NONE},
2352+ { "peer", LDAP_OPT_X_TLS_CRL_PEER},
2353+ { "all", LDAP_OPT_X_TLS_CRL_ALL },
2354+ { (char *) 0, 0 }
2355+};
2356+struct enumeration ldap_tls_crlcheck_enum = {
2357+ (struct enumeration *)0,
e5ebac8b 2358+ "ldap-tls-crlcheck", 1,
a37573f1
JR
2359+ ldap_tls_crlcheck_values
2360+};
2361+#endif
1097e9ca 2362+#endif
2363+
2364 struct enumeration_value ddns_styles_values [] = {
2365 { "none", 0 },
2366 { "ad-hoc", 1 },
e5ebac8b
AM
2367diff -up dhcp-4.0.0/dst/Makefile.am.ldap dhcp-4.0.0/dst/Makefile.am
2368--- dhcp-4.0.0/dst/Makefile.am.ldap 2007-05-29 06:32:10.000000000 -1000
2369+++ dhcp-4.0.0/dst/Makefile.am 2008-01-22 15:09:56.000000000 -1000
2370@@ -2,7 +2,12 @@ AM_CPPFLAGS = -DMINIRES_LIB -DHMAC_MD5
2371
2372 lib_LIBRARIES = libdst.a
2373
2374+noinst_LIBRARIES = libdstnomd5.a
2375+
2376 libdst_a_SOURCES = dst_support.c dst_api.c hmac_link.c md5_dgst.c \
2377 base64.c prandom.c
2378
2379+libdstnomd5_a_SOURCES = dst_support.c dst_api.c hmac_link.c \
2380+ base64.c prandom.c
2381+
2382 EXTRA_DIST = dst_internal.h md5.h md5_locl.h
2383diff -up dhcp-4.0.0/common/print.c.ldap dhcp-4.0.0/common/print.c
2384--- dhcp-4.0.0/common/print.c.ldap 2007-10-01 04:47:35.000000000 -1000
2385+++ dhcp-4.0.0/common/print.c 2008-01-22 15:09:56.000000000 -1000
2386@@ -163,9 +163,9 @@ char *print_base64 (const unsigned char
2387 }
2388
2389 char *print_hw_addr (htype, hlen, data)
2390- int htype;
2391- int hlen;
2392- unsigned char *data;
2393+ const int htype;
2394+ const int hlen;
2395+ const unsigned char *data;
2396 {
2397 static char habuf [49];
2398 char *s;
2399diff -up dhcp-4.0.0/common/conflex.c.ldap dhcp-4.0.0/common/conflex.c
2400--- dhcp-4.0.0/common/conflex.c.ldap 2007-10-31 09:13:33.000000000 -1000
2401+++ dhcp-4.0.0/common/conflex.c 2008-01-22 15:10:31.000000000 -1000
2402@@ -43,6 +43,7 @@ static enum dhcp_token read_string PROTO
2403 static enum dhcp_token read_number PROTO ((int, struct parse *));
2404 static enum dhcp_token read_num_or_name PROTO ((int, struct parse *));
2405 static enum dhcp_token intern PROTO ((char *, enum dhcp_token));
2406+static int read_function PROTO ((struct parse *));
2407
2408 isc_result_t new_parse (cfile, file, inbuf, buflen, name, eolp)
2409 struct parse **cfile;
2410@@ -76,6 +77,10 @@ isc_result_t new_parse (cfile, file, inb
2411 tmp->file = file;
2412 tmp->eol_token = eolp;
2413
2414+ if (file != -1) {
2415+ tmp -> read_function = read_function;
2416+ }
2417+
2418 if (inbuf != NULL) {
2419 tmp->inbuf = inbuf;
2420 tmp->buflen = buflen;
2421@@ -170,9 +175,13 @@ static int get_char (cfile)
2422 /* My kingdom for WITH... */
2423 int c;
2424
2425- if (cfile->bufix == cfile->buflen)
2426- c = EOF;
2427- else {
2428+ if (cfile->bufix == cfile->buflen) {
2429+ if (cfile -> read_function) {
2430+ c = cfile -> read_function (cfile);
2431+ } else {
2432+ c = EOF;
2433+ }
2434+ } else {
2435 c = cfile->inbuf [cfile->bufix];
2436 cfile->bufix++;
2437 }
2438@@ -1415,3 +1424,25 @@ intern(char *atom, enum dhcp_token dfv)
2439 }
2440 return dfv;
2441 }
2442+
2443+static int
2444+read_function (struct parse * cfile)
2445+{
2446+ int c;
2447+
2448+ ssize_t n = read (cfile -> file, cfile -> inbuf, cfile -> bufsiz);
2449+ if (n == 0) {
2450+ c = EOF;
2451+ cfile -> bufix = 0;
2452+ cfile -> buflen = 0;
2453+ } else if (n < 0) {
2454+ c = EOF;
2455+ cfile -> bufix = cfile -> buflen = 0;
2456+ } else {
2457+ c = cfile -> inbuf [0];
2458+ cfile -> bufix = 1;
2459+ cfile -> buflen = n;
2460+ }
2461+
2462+ return c;
2463+}
2464diff -up dhcp-4.0.0/includes/dhcpd.h.ldap dhcp-4.0.0/includes/dhcpd.h
2465--- dhcp-4.0.0/includes/dhcpd.h.ldap 2007-12-08 09:36:00.000000000 -1000
2466+++ dhcp-4.0.0/includes/dhcpd.h 2008-01-22 15:09:56.000000000 -1000
2467@@ -101,6 +101,11 @@ typedef time_t TIME;
2468 #include <isc-dhcp/result.h>
2469 #include <omapip/omapip_p.h>
2470
2471+#if defined(LDAP_CONFIGURATION)
2472+# include <ldap.h>
2473+# include <sys/utsname.h> /* for uname() */
2474+#endif
2475+
2476 #if !defined (BYTE_NAME_HASH_SIZE)
2477 # define BYTE_NAME_HASH_SIZE 401 /* Default would be ridiculous. */
2478 #endif
2479@@ -290,6 +295,8 @@ struct parse {
2480 size_t bufsiz;
2481
2482 struct parse *saved_state;
2483+
2484+ int (*read_function) (struct parse *);
2485 };
2486
2487 /* Variable-length array of data. */
2488@@ -421,6 +428,32 @@ struct hardware {
2489 u_int8_t hbuf [17];
2490 };
2491
2492+#if defined(LDAP_CONFIGURATION)
2493+# define LDAP_BUFFER_SIZE 8192
2494+# define LDAP_METHOD_STATIC 0
2495+# define LDAP_METHOD_DYNAMIC 1
2496+#if defined (USE_SSL)
2497+# define LDAP_SSL_OFF 0
2498+# define LDAP_SSL_ON 1
2499+# define LDAP_SSL_TLS 2
2500+# define LDAP_SSL_LDAPS 3
2501+#endif
2502+
2503+/* This is a tree of the current configuration we are building from LDAP */
2504+struct ldap_config_stack {
2505+ LDAPMessage * res; /* Pointer returned from ldap_search */
2506+ LDAPMessage * ldent; /* Current item in LDAP that we're processing.
2507+ in res */
2508+ int close_brace; /* Put a closing } after we're through with
2509+ this item */
2510+ int processed; /* We set this flag if this base item has been
2511+ processed. After this base item is processed,
2512+ we can start processing the children */
2513+ struct ldap_config_stack *children;
2514+ struct ldap_config_stack *next;
2515+};
2516+#endif
2517+
2518 typedef enum {
2519 server_startup = 0,
2520 server_running = 1,
2521@@ -626,6 +659,29 @@ struct lease_state {
2522 # define DEFAULT_PING_TIMEOUT 1
2523 #endif
2524
2525+#if defined(LDAP_CONFIGURATION)
2526+# define SV_LDAP_SERVER 47
2527+# define SV_LDAP_PORT 48
2528+# define SV_LDAP_USERNAME 49
2529+# define SV_LDAP_PASSWORD 50
2530+# define SV_LDAP_BASE_DN 51
2531+# define SV_LDAP_METHOD 52
2532+# define SV_LDAP_DEBUG_FILE 53
2533+# define SV_LDAP_DHCP_SERVER_CN 54
2534+# define SV_LDAP_REFERRALS 55
2535+#if defined (USE_SSL)
2536+# define SV_LDAP_SSL 56
2537+# define SV_LDAP_TLS_REQCERT 57
2538+# define SV_LDAP_TLS_CA_FILE 58
2539+# define SV_LDAP_TLS_CA_DIR 59
2540+# define SV_LDAP_TLS_CERT 60
2541+# define SV_LDAP_TLS_KEY 61
2542+# define SV_LDAP_TLS_CRLCHECK 62
2543+# define SV_LDAP_TLS_CIPHERS 63
2544+# define SV_LDAP_TLS_RANDFILE 64
2545+#endif
2546+#endif
2547+
2548 #if !defined (DEFAULT_DEFAULT_LEASE_TIME)
2549 # define DEFAULT_DEFAULT_LEASE_TIME 43200
2550 #endif
2551@@ -2035,7 +2091,7 @@ extern int db_time_format;
2552 char *quotify_string (const char *, const char *, int);
2553 char *quotify_buf (const unsigned char *, unsigned, const char *, int);
2554 char *print_base64 (const unsigned char *, unsigned, const char *, int);
2555-char *print_hw_addr PROTO ((int, int, unsigned char *));
2556+char *print_hw_addr PROTO ((const int, const int, const unsigned char *));
2557 void print_lease PROTO ((struct lease *));
2558 void dump_raw PROTO ((const unsigned char *, unsigned));
2559 void dump_packet_option (struct option_cache *, struct packet *,
2560@@ -3158,6 +3214,20 @@ OMAPI_OBJECT_ALLOC_DECL (dhcp_failover_l
2561
2562 const char *binding_state_print (enum failover_state);
2563
2564+/* ldap.c */
2565+#if defined(LDAP_CONFIGURATION)
2566+extern struct enumeration ldap_methods;
2567+#if defined (USE_SSL)
2568+extern struct enumeration ldap_ssl_usage_enum;
2569+extern struct enumeration ldap_tls_reqcert_enum;
2570+extern struct enumeration ldap_tls_crlcheck_enum;
2571+#endif
2572+isc_result_t ldap_read_config (void);
2573+int find_haddr_in_ldap (struct host_decl **, int, unsigned,
2574+ const unsigned char *, const char *, int);
2575+int find_subclass_in_ldap (struct class *, struct class **,
2576+ struct data_string *);
2577+#endif
2578
2579 /* mdb6.c */
2580 HASH_FUNCTIONS_DECL(ia_na, unsigned char *, struct ia_na, ia_na_hash_t);
2581diff -up dhcp-4.0.0/includes/site.h.ldap dhcp-4.0.0/includes/site.h
2582--- dhcp-4.0.0/includes/site.h.ldap 2006-07-31 12:19:51.000000000 -1000
2583+++ dhcp-4.0.0/includes/site.h 2008-01-22 15:09:56.000000000 -1000
2584@@ -183,3 +183,13 @@
2585 traces. */
2586
2587 #define TRACING
2588+
2589+/* Define this if you want to read your config from LDAP. Read README.ldap
2590+ about how to set this up */
2591+
2592+#define LDAP_CONFIGURATION
2593+
2594+/* Define this if you want to enable LDAP over a SSL connection. You will need
2595+ to add -lcrypto -lssl to the LIBS= line of server/Makefile */
2596+
2597+#define USE_SSL
2598diff -up /dev/null dhcp-4.0.0/includes/ldap_casa.h
2599--- /dev/null 2008-01-19 23:52:35.158021373 -1000
2600+++ dhcp-4.0.0/includes/ldap_casa.h 2008-01-22 15:09:56.000000000 -1000
2601@@ -0,0 +1,83 @@
2602+/* ldap_casa.h
2603+
2604+ Definition for CASA modules... */
2605+
2606+/* Copyright (c) 2004 Internet Systems Consorium, Inc. ("ISC")
2607+ * Copyright (c) 1995-2003 Internet Software Consortium.
2608+ * Copyright (c) 2006 Novell, Inc.
2609+
2610+ * All rights reserved.
2611+ * Redistribution and use in source and binary forms, with or without
2612+ * modification, are permitted provided that the following conditions are met:
2613+ * 1.Redistributions of source code must retain the above copyright notice,
2614+ * this list of conditions and the following disclaimer.
2615+ * 2.Redistributions in binary form must reproduce the above copyright notice,
2616+ * this list of conditions and the following disclaimer in the documentation
2617+ * and/or other materials provided with the distribution.
2618+ * 3.Neither the name of ISC, ISC DHCP, nor the names of its contributors
2619+ * may be used to endorse or promote products derived from this software
2620+ * without specific prior written permission.
2621+
2622+ * THIS SOFTWARE IS PROVIDED BY INTERNET SYSTEMS CONSORTIUM AND CONTRIBUTORS
2623+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
2624+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
2625+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ISC OR CONTRIBUTORS BE LIABLE
2626+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2627+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
2628+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2629+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
2630+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
2631+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2632+ * POSSIBILITY OF SUCH DAMAGE.
2633+
2634+ * This file was written by S Kalyanasundaram <skalyanasundaram@novell.com>
2635+ */
2636+
2637+#if defined(LDAP_CASA_AUTH)
2638+#ifndef __LDAP_CASA_H__
2639+#define __LDAP_CASA_H__
2640+
2641+#include <micasa_mgmd.h>
2642+#include <dlfcn.h>
2643+#include <string.h>
2644+
2645+#define MICASA_LIB "libmicasa.so.1"
2646+
2647+SSCS_TYPEDEF_LIBCALL(int, CASA_GetCredential_T)
2648+(
2649+ uint32_t ssFlags,
2650+ SSCS_SECRET_ID_T *appSecretID,
2651+ SSCS_SECRET_ID_T *sharedSecretID,
2652+ uint32_t *credentialType,
2653+ void *credential,
2654+ SSCS_EXT_T *ext
2655+);
2656+SSCS_TYPEDEF_LIBCALL(int, CASA_SetCredential_T)
2657+(
2658+ uint32_t ssFlags,
2659+ SSCS_SECRET_ID_T *appSecretID,
2660+ SSCS_SECRET_ID_T *sharedSecretID,
2661+ uint32_t credentialType,
2662+ void *credential,
2663+ SSCS_EXT_T *ext
2664+);
2665+
2666+SSCS_TYPEDEF_LIBCALL(int, CASA_RemoveCredential_T)
2667+(
2668+ uint32_t ssFlags,
2669+ SSCS_SECRET_ID_T *appSecretID,
2670+ SSCS_SECRET_ID_T *sharedSecretID,
2671+ SSCS_EXT_T *ext
2672+);
2673+static CASA_GetCredential_T p_miCASAGetCredential = NULL;
2674+static CASA_SetCredential_T p_miCASASetCredential = NULL;
2675+static CASA_RemoveCredential_T p_miCASARemoveCredential = NULL;
2676+static void *casaIDK = NULL;
2677+
2678+int load_casa(void);
2679+static void release_casa(void);
2680+int load_uname_pwd_from_miCASA(char **, char **);
2681+
2682+#endif /* __LDAP_CASA_H__ */
2683+#endif /* LDAP_CASA_AUTH */
2684+
This page took 0.573935 seconds and 4 git commands to generate.