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