0f9f19ccd5
- Added back Requires for perl since dhcpd-conf-to-ldap needs it (#225691) - Put copies of dhcp-options and dhcp-eval man pages in the dhcp and dhclient packages rather than having the elaborate symlink collection - Explicitly name man pages in the %files listings - Use the %{_sysconfdir} and %{_initrddir} macros (#225691) - Use macros for commands in %build and %install - Split README.ldap, draft-ietf-dhc-ldap-schema-01.txt, and dhcpd-conf-to-ldap.pl out of the LDAP patch - Split linux.dbus-example script out of the extended new option info patch - Remove unnecessary changes from the Makefile patch
1490 lines
43 KiB
Diff
1490 lines
43 KiB
Diff
--- dhcp-3.0.5/common/conflex.c.ldapconf 2007-03-04 15:32:24.000000000 -0500
|
|
+++ dhcp-3.0.5/common/conflex.c 2007-03-04 15:32:24.000000000 -0500
|
|
@@ -47,6 +47,7 @@
|
|
static enum dhcp_token read_number PROTO ((int, struct parse *));
|
|
static enum dhcp_token read_num_or_name PROTO ((int, struct parse *));
|
|
static enum dhcp_token intern PROTO ((char *, enum dhcp_token));
|
|
+static int read_function PROTO ((struct parse *));
|
|
|
|
isc_result_t new_parse (cfile, file, inbuf, buflen, name, eolp)
|
|
struct parse **cfile;
|
|
@@ -74,6 +75,10 @@
|
|
tmp -> file = file;
|
|
tmp -> eol_token = eolp;
|
|
|
|
+ if (file != -1) {
|
|
+ tmp -> read_function = read_function;;
|
|
+ }
|
|
+
|
|
tmp -> bufix = 0;
|
|
tmp -> buflen = buflen;
|
|
if (inbuf) {
|
|
@@ -113,22 +118,11 @@
|
|
int c;
|
|
|
|
if (cfile -> bufix == cfile -> buflen) {
|
|
- if (cfile -> file != -1) {
|
|
- cfile -> buflen =
|
|
- read (cfile -> file,
|
|
- cfile -> inbuf, cfile -> bufsiz);
|
|
- if (cfile -> buflen == 0) {
|
|
- c = EOF;
|
|
- cfile -> bufix = 0;
|
|
- } else if (cfile -> buflen < 0) {
|
|
- c = EOF;
|
|
- cfile -> bufix = cfile -> buflen = 0;
|
|
- } else {
|
|
- c = cfile -> inbuf [0];
|
|
- cfile -> bufix = 1;
|
|
- }
|
|
- } else
|
|
+ if (cfile -> read_function) {
|
|
+ c = cfile -> read_function (cfile);
|
|
+ } else {
|
|
c = EOF;
|
|
+ }
|
|
} else {
|
|
c = cfile -> inbuf [cfile -> bufix];
|
|
cfile -> bufix++;
|
|
@@ -1130,3 +1124,25 @@
|
|
}
|
|
return dfv;
|
|
}
|
|
+
|
|
+
|
|
+static int
|
|
+read_function (struct parse * cfile)
|
|
+{
|
|
+ int c;
|
|
+
|
|
+ cfile -> buflen = read (cfile -> file, cfile -> inbuf, cfile -> bufsiz);
|
|
+ if (cfile -> buflen == 0) {
|
|
+ c = EOF;
|
|
+ cfile -> bufix = 0;
|
|
+ } else if (cfile -> buflen < 0) {
|
|
+ c = EOF;
|
|
+ cfile -> bufix = cfile -> buflen = 0;
|
|
+ } else {
|
|
+ c = cfile -> inbuf [0];
|
|
+ cfile -> bufix = 1;
|
|
+ }
|
|
+
|
|
+ return c;
|
|
+}
|
|
+
|
|
--- dhcp-3.0.5/common/print.c.ldapconf 2007-03-04 15:32:24.000000000 -0500
|
|
+++ dhcp-3.0.5/common/print.c 2007-03-04 15:32:24.000000000 -0500
|
|
@@ -166,9 +166,9 @@
|
|
}
|
|
|
|
char *print_hw_addr (htype, hlen, data)
|
|
- int htype;
|
|
- int hlen;
|
|
- unsigned char *data;
|
|
+ const int htype;
|
|
+ const int hlen;
|
|
+ const unsigned char *data;
|
|
{
|
|
static char habuf [49];
|
|
char *s;
|
|
--- dhcp-3.0.5/includes/dhcpd.h.ldapconf 2007-03-04 15:32:24.000000000 -0500
|
|
+++ dhcp-3.0.5/includes/dhcpd.h 2007-03-04 15:32:24.000000000 -0500
|
|
@@ -79,6 +79,11 @@
|
|
#include <isc-dhcp/result.h>
|
|
#include <omapip/omapip_p.h>
|
|
|
|
+#if defined(LDAP_CONFIGURATION)
|
|
+# include <ldap.h>
|
|
+# include <sys/utsname.h> /* for uname() */
|
|
+#endif
|
|
+
|
|
#if !defined (OPTION_HASH_SIZE)
|
|
# define OPTION_HASH_SIZE 17
|
|
# define OPTION_HASH_PTWO 32 /* Next power of two above option hash. */
|
|
@@ -139,6 +144,8 @@
|
|
char *inbuf;
|
|
unsigned bufix, buflen;
|
|
unsigned bufsiz;
|
|
+
|
|
+ int (*read_function) (struct parse *);
|
|
};
|
|
|
|
/* Variable-length array of data. */
|
|
@@ -244,6 +251,27 @@
|
|
u_int8_t hbuf [17];
|
|
};
|
|
|
|
+#if defined(LDAP_CONFIGURATION)
|
|
+# define LDAP_BUFFER_SIZE 8192
|
|
+# define LDAP_METHOD_STATIC 0
|
|
+# define LDAP_METHOD_DYNAMIC 1
|
|
+
|
|
+/* This is a tree of the current configuration we are building from LDAP */
|
|
+
|
|
+struct ldap_config_stack {
|
|
+ LDAPMessage * res; /* Pointer returned from ldap_search */
|
|
+ LDAPMessage * ldent; /* Current item in LDAP that we're processing
|
|
+ in res */
|
|
+ int close_brace; /* Put a closing } after we're through with
|
|
+ this item */
|
|
+ int processed; /* We set this flag if this base item has been
|
|
+ processed. After this base item is processed,
|
|
+ we can start processing the children */
|
|
+ struct ldap_config_stack *children;
|
|
+ struct ldap_config_stack *next;
|
|
+};
|
|
+#endif
|
|
+
|
|
typedef enum {
|
|
server_startup = 0,
|
|
server_running = 1,
|
|
@@ -426,6 +454,15 @@
|
|
# define DEFAULT_PING_TIMEOUT 1
|
|
#endif
|
|
|
|
+#if defined(LDAP_CONFIGURATION)
|
|
+# define SV_LDAP_SERVER 46
|
|
+# define SV_LDAP_PORT 47
|
|
+# define SV_LDAP_USERNAME 48
|
|
+# define SV_LDAP_PASSWORD 49
|
|
+# define SV_LDAP_BASE_DN 50
|
|
+# define SV_LDAP_METHOD 51
|
|
+#endif
|
|
+
|
|
#if !defined (DEFAULT_DEFAULT_LEASE_TIME)
|
|
# define DEFAULT_DEFAULT_LEASE_TIME 43200
|
|
#endif
|
|
@@ -1526,7 +1563,7 @@
|
|
char *quotify_string (const char *, const char *, int);
|
|
char *quotify_buf (const unsigned char *, unsigned, const char *, int);
|
|
char *print_base64 (const unsigned char *, unsigned, const char *, int);
|
|
-char *print_hw_addr PROTO ((int, int, unsigned char *));
|
|
+char *print_hw_addr PROTO ((const int, const int, const unsigned char *));
|
|
void print_lease PROTO ((struct lease *));
|
|
void dump_raw PROTO ((const unsigned char *, unsigned));
|
|
void dump_packet_option (struct option_cache *, struct packet *,
|
|
@@ -2640,3 +2677,14 @@
|
|
#endif /* FAILOVER_PROTOCOL */
|
|
|
|
const char *binding_state_print (enum failover_state);
|
|
+
|
|
+/* ldap.c */
|
|
+#if defined(LDAP_CONFIGURATION)
|
|
+extern struct enumeration ldap_methods;
|
|
+isc_result_t ldap_read_config (void);
|
|
+int find_haddr_in_ldap (struct host_decl **, int, unsigned,
|
|
+ const unsigned char *, const char *, int);
|
|
+int find_subclass_in_ldap (struct class *, struct class **,
|
|
+ struct data_string *);
|
|
+#endif
|
|
+
|
|
--- dhcp-3.0.5/includes/site.h.ldapconf 2002-03-12 13:33:39.000000000 -0500
|
|
+++ dhcp-3.0.5/includes/site.h 2007-03-04 15:32:24.000000000 -0500
|
|
@@ -177,3 +177,13 @@
|
|
traces. */
|
|
|
|
#define TRACING
|
|
+
|
|
+/* Define this if you want to read your config from LDAP. Read README.ldap
|
|
+ about how to set this up */
|
|
+
|
|
+#define LDAP_CONFIGURATION
|
|
+
|
|
+#define _PATH_DHCPD_DB "/var/lib/dhcpd/dhcpd.leases"
|
|
+#define _PATH_DHCLIENT_DB "/var/lib/dhclient/dhclient.leases"
|
|
+#define _PATH_DHCPD_DB "/var/lib/dhcpd/dhcpd.leases"
|
|
+#define _PATH_DHCLIENT_DB "/var/lib/dhclient/dhclient.leases"
|
|
--- dhcp-3.0.5/server/Makefile.dist.ldapconf 2004-06-10 13:59:50.000000000 -0400
|
|
+++ dhcp-3.0.5/server/Makefile.dist 2007-03-04 15:33:01.000000000 -0500
|
|
@@ -25,9 +25,9 @@
|
|
CATMANPAGES = dhcpd.cat8 dhcpd.conf.cat5 dhcpd.leases.cat5
|
|
SEDMANPAGES = dhcpd.man8 dhcpd.conf.man5 dhcpd.leases.man5
|
|
SRCS = dhcpd.c dhcp.c bootp.c confpars.c db.c class.c failover.c \
|
|
- omapi.c mdb.c stables.c salloc.c ddns.c
|
|
+ omapi.c mdb.c stables.c salloc.c ddns.c ldap.c
|
|
OBJS = dhcpd.o dhcp.o bootp.o confpars.o db.o class.o failover.o \
|
|
- omapi.o mdb.o stables.o salloc.o ddns.o
|
|
+ omapi.o mdb.o stables.o salloc.o ddns.o ldap.o
|
|
PROG = dhcpd
|
|
MAN = dhcpd.8 dhcpd.conf.5 dhcpd.leases.5
|
|
|
|
@@ -103,6 +103,6 @@
|
|
-e "s#RUNDIR#$(VARRUN)#g" < dhcpd.leases.5 >dhcpd.leases.man5
|
|
|
|
dhcpd: $(OBJS) $(COBJ) $(DHCPLIB)
|
|
- $(CC) $(LFLAGS) -o dhcpd $(OBJS) $(DHCPLIB) $(LIBS)
|
|
+ $(CC) $(LFLAGS) -o dhcpd $(OBJS) $(DHCPLIB) $(LIBS) -lldap
|
|
|
|
# Dependencies (semi-automatically-generated)
|
|
--- dhcp-3.0.5/server/class.c.ldapconf 2004-06-10 13:59:51.000000000 -0400
|
|
+++ dhcp-3.0.5/server/class.c 2007-03-04 15:32:24.000000000 -0500
|
|
@@ -90,6 +90,7 @@
|
|
int matched = 0;
|
|
int status;
|
|
int ignorep;
|
|
+ int classfound;
|
|
|
|
for (class = collection -> classes; class; class = class -> nic) {
|
|
#if defined (DEBUG_CLASS_MATCHING)
|
|
@@ -135,9 +136,19 @@
|
|
class -> submatch, MDL));
|
|
if (status && data.len) {
|
|
nc = (struct class *)0;
|
|
- if (class_hash_lookup (&nc, class -> hash,
|
|
- (const char *)data.data,
|
|
- data.len, MDL)) {
|
|
+ classfound = class_hash_lookup (&nc,
|
|
+ class -> hash,
|
|
+ (const char *)data.data,
|
|
+ data.len, MDL);
|
|
+
|
|
+#ifdef LDAP_CONFIGURATION
|
|
+ if (!classfound &&
|
|
+ find_subclass_in_ldap (class,
|
|
+ &nc, &data))
|
|
+ classfound = 1;
|
|
+#endif
|
|
+
|
|
+ if (classfound) {
|
|
#if defined (DEBUG_CLASS_MATCHING)
|
|
log_info ("matches subclass %s.",
|
|
print_hex_1 (data.len,
|
|
--- dhcp-3.0.5/server/confpars.c.ldapconf 2007-03-04 15:32:24.000000000 -0500
|
|
+++ dhcp-3.0.5/server/confpars.c 2007-03-04 15:32:24.000000000 -0500
|
|
@@ -63,7 +63,17 @@
|
|
|
|
isc_result_t readconf ()
|
|
{
|
|
- return read_conf_file (path_dhcpd_conf, root_group, ROOT_GROUP, 0);
|
|
+ isc_result_t res;
|
|
+
|
|
+ res = read_conf_file (path_dhcpd_conf, root_group, ROOT_GROUP, 0);
|
|
+#if defined(LDAP_CONFIGURATION)
|
|
+ if (res != ISC_R_SUCCESS)
|
|
+ return (res);
|
|
+
|
|
+ return ldap_read_config ();
|
|
+#else
|
|
+ return (res);
|
|
+#endif
|
|
}
|
|
|
|
isc_result_t read_conf_file (const char *filename, struct group *group,
|
|
--- dhcp-3.0.5/server/dhcpd.c.ldapconf 2007-03-04 15:32:24.000000000 -0500
|
|
+++ dhcp-3.0.5/server/dhcpd.c 2007-03-04 15:32:24.000000000 -0500
|
|
@@ -433,6 +433,9 @@
|
|
/* Add the ddns update style enumeration prior to parsing. */
|
|
add_enumeration (&ddns_styles);
|
|
add_enumeration (&syslog_enum);
|
|
+#if defined (LDAP_CONFIGURATION)
|
|
+ add_enumeration (&ldap_methods);
|
|
+#endif
|
|
|
|
if (!group_allocate (&root_group, MDL))
|
|
log_fatal ("Can't allocate root group!");
|
|
--- /dev/null 2007-03-03 18:04:36.394738328 -0500
|
|
+++ dhcp-3.0.5/server/ldap.c 2007-03-04 15:32:24.000000000 -0500
|
|
@@ -0,0 +1,1142 @@
|
|
+/* ldap.c
|
|
+
|
|
+ Routines for reading the configuration from LDAP */
|
|
+
|
|
+/*
|
|
+ * Copyright (c) 1996-2001 Ntelos, Inc.
|
|
+ * All rights reserved.
|
|
+ *
|
|
+ * Redistribution and use in source and binary forms, with or without
|
|
+ * modification, are permitted provided that the following conditions
|
|
+ * are met:
|
|
+ *
|
|
+ * 1. Redistributions of source code must retain the above copyright
|
|
+ * notice, this list of conditions and the following disclaimer.
|
|
+ * 2. Redistributions in binary form must reproduce the above copyright
|
|
+ * notice, this list of conditions and the following disclaimer in the
|
|
+ * documentation and/or other materials provided with the distribution.
|
|
+ * 3. Neither the name of The Internet Software Consortium nor the names
|
|
+ * of its contributors may be used to endorse or promote products derived
|
|
+ * from this software without specific prior written permission.
|
|
+ *
|
|
+ * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
|
|
+ * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
|
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
|
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
+ * DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
|
|
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
|
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
|
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
+ * SUCH DAMAGE.
|
|
+ *
|
|
+ * This LDAP module was written by Brian Masney <masneyb@ntelos.net>. It's
|
|
+ * development was sponsored by Ntelos, Inc. (www.ntelos.com).
|
|
+ */
|
|
+
|
|
+#include "dhcpd.h"
|
|
+
|
|
+#if defined(LDAP_CONFIGURATION)
|
|
+
|
|
+static LDAP * ld = NULL;
|
|
+static char *ldap_server = NULL,
|
|
+ *ldap_username = NULL,
|
|
+ *ldap_password = NULL,
|
|
+ *ldap_base_dn = NULL;
|
|
+static int ldap_method = LDAP_METHOD_DYNAMIC,
|
|
+ disable_ldap = 0;
|
|
+static struct ldap_config_stack *ldap_stack = NULL;
|
|
+
|
|
+
|
|
+static void
|
|
+ldap_parse_class (struct ldap_config_stack *item, struct parse *cfile)
|
|
+{
|
|
+ struct berval **temp;
|
|
+
|
|
+ if ((temp = ldap_get_values_len (ld, item->ldent, "cn")) == NULL ||
|
|
+ temp[0]->bv_val == NULL)
|
|
+ {
|
|
+ if (temp != NULL)
|
|
+ ldap_value_free_len (temp);
|
|
+
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ strncat (cfile->inbuf, "class \"", LDAP_BUFFER_SIZE);
|
|
+ strncat (cfile->inbuf, temp[0]->bv_val, LDAP_BUFFER_SIZE);
|
|
+ strncat (cfile->inbuf, "\" {\n", LDAP_BUFFER_SIZE);
|
|
+
|
|
+ item->close_brace = 1;
|
|
+ ldap_value_free_len (temp);
|
|
+}
|
|
+
|
|
+
|
|
+static void
|
|
+ldap_parse_subclass (struct ldap_config_stack *item, struct parse *cfile)
|
|
+{
|
|
+ struct berval **temp, **classdata;
|
|
+
|
|
+ if ((temp = ldap_get_values_len (ld, item->ldent, "cn")) == NULL ||
|
|
+ temp[0]->bv_val == NULL)
|
|
+ {
|
|
+ if (temp != NULL)
|
|
+ ldap_value_free_len (temp);
|
|
+
|
|
+ return;
|
|
+ }
|
|
+
|
|
+
|
|
+ if ((classdata = ldap_get_values_len (ld, item->ldent,
|
|
+ "dhcpClassData")) == NULL ||
|
|
+ classdata[0]->bv_val == NULL)
|
|
+ {
|
|
+ if (classdata != NULL)
|
|
+ ldap_value_free_len (classdata);
|
|
+ ldap_value_free_len (temp);
|
|
+
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ strncat (cfile->inbuf, "subclass ", LDAP_BUFFER_SIZE);
|
|
+ strncat (cfile->inbuf, (*classdata)->bv_val, LDAP_BUFFER_SIZE);
|
|
+ strncat (cfile->inbuf, " ", LDAP_BUFFER_SIZE);
|
|
+ strncat (cfile->inbuf, (*temp)->bv_val, LDAP_BUFFER_SIZE);
|
|
+ strncat (cfile->inbuf, " {\n", LDAP_BUFFER_SIZE);
|
|
+
|
|
+ item->close_brace = 1;
|
|
+ ldap_value_free_len (temp);
|
|
+ ldap_value_free_len (classdata);
|
|
+}
|
|
+
|
|
+
|
|
+static void
|
|
+ldap_parse_host (struct ldap_config_stack *item, struct parse *cfile)
|
|
+{
|
|
+ struct berval **temp, **hwaddr;
|
|
+
|
|
+
|
|
+ if ((temp = ldap_get_values_len (ld, item->ldent, "cn")) == NULL ||
|
|
+ temp[0]->bv_val == NULL)
|
|
+ {
|
|
+ if (temp != NULL)
|
|
+ ldap_value_free_len (temp);
|
|
+
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ if ((hwaddr = ldap_get_values_len (ld, item->ldent,
|
|
+ "dhcpHWAddress")) == NULL ||
|
|
+ hwaddr[0]->bv_val == NULL)
|
|
+ {
|
|
+ if (hwaddr != NULL)
|
|
+ ldap_value_free_len (hwaddr);
|
|
+ ldap_value_free_len (temp);
|
|
+
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ strncat (cfile->inbuf, "host ", LDAP_BUFFER_SIZE);
|
|
+ strncat (cfile->inbuf, (*temp)->bv_val, LDAP_BUFFER_SIZE);
|
|
+ strncat (cfile->inbuf, " {\nhardware ", LDAP_BUFFER_SIZE);
|
|
+ strncat (cfile->inbuf, (*hwaddr)->bv_val, LDAP_BUFFER_SIZE);
|
|
+ strncat (cfile->inbuf, ";\n", LDAP_BUFFER_SIZE);
|
|
+
|
|
+ item->close_brace = 1;
|
|
+ ldap_value_free_len (temp);
|
|
+ ldap_value_free_len (hwaddr);
|
|
+}
|
|
+
|
|
+
|
|
+static void
|
|
+ldap_parse_shared_network (struct ldap_config_stack *item, struct parse *cfile)
|
|
+{
|
|
+ struct berval **temp;
|
|
+
|
|
+
|
|
+ if ((temp = ldap_get_values_len (ld, item->ldent, "cn")) == NULL ||
|
|
+ temp[0]->bv_val == NULL)
|
|
+ {
|
|
+ if (temp != NULL)
|
|
+ ldap_value_free_len (temp);
|
|
+
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ strncat (cfile->inbuf, "shared-network ", LDAP_BUFFER_SIZE);
|
|
+ strncat (cfile->inbuf, (*temp)->bv_val, LDAP_BUFFER_SIZE);
|
|
+ strncat (cfile->inbuf, " {\n", LDAP_BUFFER_SIZE);
|
|
+
|
|
+ item->close_brace = 1;
|
|
+ ldap_value_free_len (temp);
|
|
+}
|
|
+
|
|
+
|
|
+static void
|
|
+parse_netmask (int netmask, char *netmaskbuf)
|
|
+{
|
|
+ unsigned long nm;
|
|
+ int i;
|
|
+
|
|
+ nm = 0;
|
|
+ for (i=1; i <= netmask; i++)
|
|
+ {
|
|
+ nm |= 1 << (32 - i);
|
|
+ }
|
|
+
|
|
+ sprintf (netmaskbuf, "%d.%d.%d.%d", (int) (nm >> 24) & 0xff,
|
|
+ (int) (nm >> 16) & 0xff,
|
|
+ (int) (nm >> 8) & 0xff,
|
|
+ (int) nm & 0xff);
|
|
+}
|
|
+
|
|
+static void
|
|
+ldap_parse_subnet (struct ldap_config_stack *item, struct parse *cfile)
|
|
+{
|
|
+ struct berval **temp, **netmask;
|
|
+ char netmaskbuf[16];
|
|
+ int i;
|
|
+
|
|
+ if ((temp = ldap_get_values_len (ld, item->ldent, "cn")) == NULL ||
|
|
+ temp[0]->bv_val == NULL)
|
|
+ {
|
|
+ if (temp != NULL)
|
|
+ ldap_value_free_len (temp);
|
|
+
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ if ((netmask = ldap_get_values_len (ld, item->ldent,
|
|
+ "dhcpNetmask")) == NULL ||
|
|
+ netmask[0]->bv_val == NULL)
|
|
+ {
|
|
+ if (netmask != NULL)
|
|
+ ldap_value_free_len (netmask);
|
|
+ ldap_value_free_len (temp);
|
|
+
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ strncat (cfile->inbuf, "subnet ", LDAP_BUFFER_SIZE);
|
|
+ strncat (cfile->inbuf, temp[0]->bv_val, LDAP_BUFFER_SIZE);
|
|
+
|
|
+ strncat (cfile->inbuf, " netmask ", LDAP_BUFFER_SIZE);
|
|
+ parse_netmask (strtol (netmask[0]->bv_val, NULL, 10), netmaskbuf);
|
|
+ strncat (cfile->inbuf, netmaskbuf, LDAP_BUFFER_SIZE);
|
|
+
|
|
+ strncat (cfile->inbuf, " {\n", LDAP_BUFFER_SIZE);
|
|
+
|
|
+ ldap_value_free_len (temp);
|
|
+ ldap_value_free_len (netmask);
|
|
+
|
|
+ if ((temp = ldap_get_values_len (ld, item->ldent, "dhcpRange")) != NULL)
|
|
+ {
|
|
+ strncat (cfile->inbuf, "range", LDAP_BUFFER_SIZE);
|
|
+ for (i=0; temp[i]->bv_val != NULL; i++)
|
|
+ {
|
|
+ strncat (cfile->inbuf, " ", LDAP_BUFFER_SIZE);
|
|
+ strncat (cfile->inbuf, temp[i]->bv_val, LDAP_BUFFER_SIZE);
|
|
+ }
|
|
+ strncat (cfile->inbuf, ";\n", LDAP_BUFFER_SIZE);
|
|
+ ldap_value_free_len (temp);
|
|
+ }
|
|
+
|
|
+ item->close_brace = 1;
|
|
+}
|
|
+
|
|
+
|
|
+static void
|
|
+ldap_parse_pool (struct ldap_config_stack *item, struct parse *cfile)
|
|
+{
|
|
+ struct berval **temp;
|
|
+ int i;
|
|
+
|
|
+ strncat (cfile->inbuf, "pool {\n", LDAP_BUFFER_SIZE);
|
|
+
|
|
+ if ((temp = ldap_get_values_len (ld, item->ldent, "dhcpRange")) != NULL)
|
|
+ {
|
|
+ strncat (cfile->inbuf, "range", LDAP_BUFFER_SIZE);
|
|
+ for (i=0; temp[i]->bv_val != NULL; i++)
|
|
+ {
|
|
+ strncat (cfile->inbuf, " ", LDAP_BUFFER_SIZE);
|
|
+ strncat (cfile->inbuf, temp[i]->bv_val, LDAP_BUFFER_SIZE);
|
|
+ }
|
|
+ strncat (cfile->inbuf, ";\n", LDAP_BUFFER_SIZE);
|
|
+ ldap_value_free_len (temp);
|
|
+ }
|
|
+
|
|
+ if ((temp = ldap_get_values_len (ld, item->ldent, "dhcpPermitList")) != NULL)
|
|
+ {
|
|
+ for (i=0; temp[i]->bv_val != NULL; i++)
|
|
+ {
|
|
+ strncat (cfile->inbuf, temp[i]->bv_val, LDAP_BUFFER_SIZE);
|
|
+ strncat (cfile->inbuf, ";\n", LDAP_BUFFER_SIZE);
|
|
+ }
|
|
+ ldap_value_free_len (temp);
|
|
+ }
|
|
+
|
|
+ item->close_brace = 1;
|
|
+}
|
|
+
|
|
+
|
|
+static void
|
|
+ldap_parse_group (struct ldap_config_stack *item, struct parse *cfile)
|
|
+{
|
|
+ strncat (cfile->inbuf, "group {\n", LDAP_BUFFER_SIZE);
|
|
+ item->close_brace = 1;
|
|
+}
|
|
+
|
|
+
|
|
+static void
|
|
+parse_external_dns (LDAPMessage * ent)
|
|
+{
|
|
+ char *search[] = {"dhcpOptionsDN", "dhcpSharedNetworkDN", "dhcpSubnetDN",
|
|
+ "dhcpGroupDN", "dhcpHostDN", "dhcpClassesDN",
|
|
+ "dhcpPoolDN", NULL};
|
|
+ LDAPMessage * newres, * newent;
|
|
+ struct ldap_config_stack *ns;
|
|
+ struct berval **temp;
|
|
+ int i, ret;
|
|
+
|
|
+ for (i=0; search[i] != NULL; i++)
|
|
+ {
|
|
+ if ((ldap_method = LDAP_METHOD_DYNAMIC) &&
|
|
+ (strcmp (search[i], "dhcpHostDN") == 0))
|
|
+ continue;
|
|
+
|
|
+ if ((temp = ldap_get_values_len (ld, ent, search[i])) == NULL)
|
|
+ continue;
|
|
+
|
|
+ if ((ret = ldap_search_ext_s (ld, temp[0]->bv_val, LDAP_SCOPE_BASE,
|
|
+ "objectClass=*", NULL, 0,
|
|
+ NULL, NULL, NULL, 0,
|
|
+ &newres)) != LDAP_SUCCESS)
|
|
+ {
|
|
+ ldap_value_free_len (temp);
|
|
+ ldap_unbind_ext (ld, NULL, NULL);
|
|
+ ld = NULL;
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ ldap_value_free_len (temp);
|
|
+
|
|
+ newent = ldap_first_entry (ld, newres);
|
|
+ if (newent == NULL)
|
|
+ {
|
|
+ ldap_msgfree (newres);
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+#if defined(DEBUG_LDAP)
|
|
+ log_info ("Adding LDAP entry '%s' as child", ldap_get_dn (ld, newent));
|
|
+#endif
|
|
+
|
|
+ ns = dmalloc (sizeof (*ns), MDL);
|
|
+ ns->res = newres;
|
|
+ ns->ldent = newent;
|
|
+ ns->close_brace = 0;
|
|
+ ns->processed = 0;
|
|
+ ns->children = NULL;
|
|
+ ns->next = ldap_stack->children;
|
|
+ ldap_stack->children = ns;
|
|
+ }
|
|
+}
|
|
+
|
|
+
|
|
+static void
|
|
+ldap_generate_config_string (struct ldap_config_stack *item, struct parse *cfile)
|
|
+{
|
|
+ struct berval **objectClass, **temp;
|
|
+ int i, j, ignore, found;
|
|
+
|
|
+ if ((objectClass = ldap_get_values_len (ld, item->ldent,
|
|
+ "objectClass")) == NULL)
|
|
+ return;
|
|
+
|
|
+ ignore = 0;
|
|
+ found = 1;
|
|
+ for (i=0; objectClass[i]->bv_val != NULL; i++)
|
|
+ {
|
|
+ if (strcmp (objectClass[i]->bv_val, "dhcpSharedNetwork") == 0)
|
|
+ ldap_parse_shared_network (item, cfile);
|
|
+ else if (strcmp (objectClass[i]->bv_val, "dhcpClass") == 0)
|
|
+ ldap_parse_class (item, cfile);
|
|
+ else if (strcmp (objectClass[i]->bv_val, "dhcpSubnet") == 0)
|
|
+ ldap_parse_subnet (item, cfile);
|
|
+ else if (strcmp (objectClass[i]->bv_val, "dhcpPool") == 0)
|
|
+ ldap_parse_pool (item, cfile);
|
|
+ else if (strcmp (objectClass[i]->bv_val, "dhcpGroup") == 0)
|
|
+ ldap_parse_group (item, cfile);
|
|
+ else if (strcmp (objectClass[i]->bv_val, "dhcpHost") == 0)
|
|
+ {
|
|
+ if (ldap_method == LDAP_METHOD_STATIC)
|
|
+ ldap_parse_host (item, cfile);
|
|
+ else
|
|
+ {
|
|
+ ignore = 1;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ else if (strcmp (objectClass[i]->bv_val, "dhcpSubClass") == 0)
|
|
+ {
|
|
+ if (ldap_method == LDAP_METHOD_STATIC)
|
|
+ ldap_parse_subclass (item, cfile);
|
|
+ else
|
|
+ {
|
|
+ ignore = 1;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ else
|
|
+ found = 0;
|
|
+
|
|
+ if (found && cfile->inbuf[0] == '\0')
|
|
+ {
|
|
+ ignore = 1;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ ldap_value_free_len (objectClass);
|
|
+
|
|
+ if (ignore)
|
|
+ return;
|
|
+
|
|
+ if ((temp = ldap_get_values_len (ld, item->ldent, "dhcpOption")) != NULL)
|
|
+ {
|
|
+ for (j=0; temp[j]->bv_val != NULL; j++)
|
|
+ {
|
|
+ strncat (cfile->inbuf, "option ", LDAP_BUFFER_SIZE);
|
|
+ strncat (cfile->inbuf, temp[j]->bv_val, LDAP_BUFFER_SIZE);
|
|
+ strncat (cfile->inbuf, ";\n", LDAP_BUFFER_SIZE);
|
|
+ }
|
|
+ ldap_value_free_len (temp);
|
|
+ }
|
|
+
|
|
+ if ((temp = ldap_get_values_len (ld, item->ldent, "dhcpStatements")) != NULL)
|
|
+ {
|
|
+ for (j=0; temp[j]->bv_val != NULL; j++)
|
|
+ {
|
|
+ strncat (cfile->inbuf, temp[j]->bv_val, LDAP_BUFFER_SIZE);
|
|
+ strncat (cfile->inbuf, ";\n", LDAP_BUFFER_SIZE);
|
|
+ }
|
|
+ ldap_value_free_len (temp);
|
|
+ }
|
|
+
|
|
+ parse_external_dns (item->ldent);
|
|
+}
|
|
+
|
|
+
|
|
+static void
|
|
+free_stack_entry (struct ldap_config_stack *item)
|
|
+{
|
|
+ ldap_msgfree (item->res);
|
|
+ dfree (item, MDL);
|
|
+}
|
|
+
|
|
+
|
|
+static void
|
|
+next_ldap_entry (struct parse *cfile)
|
|
+{
|
|
+ struct ldap_config_stack *temp_stack;
|
|
+
|
|
+ if (ldap_stack->processed && ldap_stack->children != NULL)
|
|
+ {
|
|
+ temp_stack = ldap_stack->children;
|
|
+ if (temp_stack->close_brace)
|
|
+ strncat (cfile->inbuf, "}\n", LDAP_BUFFER_SIZE);
|
|
+
|
|
+ ldap_stack->children = ldap_stack->children->next;
|
|
+ free_stack_entry (temp_stack);
|
|
+
|
|
+ if (ldap_stack->processed && ldap_stack->children != NULL)
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ if (ldap_stack->close_brace)
|
|
+ {
|
|
+ strncat (cfile->inbuf, "}\n", LDAP_BUFFER_SIZE);
|
|
+ ldap_stack->close_brace = 0;
|
|
+ }
|
|
+
|
|
+ while (ldap_stack != NULL && ldap_stack->children == NULL &&
|
|
+ (ldap_stack->ldent = ldap_next_entry (ld, ldap_stack->ldent)) == NULL)
|
|
+ {
|
|
+ if (ldap_stack->close_brace)
|
|
+ {
|
|
+ strncat (cfile->inbuf, "}\n", LDAP_BUFFER_SIZE);
|
|
+ ldap_stack->close_brace = 0;
|
|
+ }
|
|
+
|
|
+ temp_stack = ldap_stack;
|
|
+ ldap_stack = ldap_stack->next;
|
|
+ free_stack_entry (temp_stack);
|
|
+ }
|
|
+
|
|
+ if (ldap_stack != NULL && ldap_stack->children == NULL &&
|
|
+ ldap_stack->close_brace)
|
|
+ {
|
|
+ strncat (cfile->inbuf, "}\n", LDAP_BUFFER_SIZE);
|
|
+ ldap_stack->close_brace = 0;
|
|
+ }
|
|
+}
|
|
+
|
|
+
|
|
+static void
|
|
+add_to_config_stack (LDAPMessage * res, LDAPMessage * ent)
|
|
+{
|
|
+ struct ldap_config_stack *ns;
|
|
+
|
|
+ ns = dmalloc (sizeof (*ns), MDL);
|
|
+ ns->res = res;
|
|
+ ns->ldent = ent;
|
|
+ ns->close_brace = 0;
|
|
+ ns->processed = 0;
|
|
+ ns->children = NULL;
|
|
+ ns->next = ldap_stack;
|
|
+ ldap_stack = ns;
|
|
+}
|
|
+
|
|
+
|
|
+static void
|
|
+ldap_start (void)
|
|
+{
|
|
+ struct option_state *options;
|
|
+ struct option_cache *oc;
|
|
+ struct data_string db;
|
|
+ int ret;
|
|
+
|
|
+ if (ld != NULL)
|
|
+ return;
|
|
+
|
|
+ if (ldap_server == NULL)
|
|
+ {
|
|
+ options = NULL;
|
|
+ option_state_allocate (&options, MDL);
|
|
+
|
|
+ execute_statements_in_scope ((struct binding_value **) NULL,
|
|
+ (struct packet *) NULL, (struct lease *) NULL,
|
|
+ (struct client_state *) NULL, (struct option_state *) NULL,
|
|
+ options, &global_scope, root_group, (struct group *) NULL);
|
|
+
|
|
+ memset (&db, 0, sizeof (db));
|
|
+ oc = lookup_option (&server_universe, options, SV_LDAP_SERVER);
|
|
+ if (oc &&
|
|
+ evaluate_option_cache (&db, (struct packet*) NULL,
|
|
+ (struct lease *) NULL, (struct client_state *) NULL,
|
|
+ options, (struct option_state *) NULL, &global_scope, oc, MDL))
|
|
+ {
|
|
+ ldap_server = dmalloc (db.len + 1, MDL);
|
|
+ if (!ldap_server)
|
|
+ log_fatal ("no memory for ldap server");
|
|
+ memcpy (ldap_server, db.data, db.len);
|
|
+ ldap_server[db.len] = 0;
|
|
+ data_string_forget (&db, MDL);
|
|
+ }
|
|
+
|
|
+ oc = lookup_option (&server_universe, options, SV_LDAP_USERNAME);
|
|
+ if (oc &&
|
|
+ evaluate_option_cache (&db, (struct packet*) NULL,
|
|
+ (struct lease *) NULL, (struct client_state *) NULL,
|
|
+ options, (struct option_state *) NULL, &global_scope, oc, MDL))
|
|
+ {
|
|
+ ldap_username = dmalloc (db.len + 1, MDL);
|
|
+ if (!ldap_username)
|
|
+ log_fatal ("no memory for ldap username");
|
|
+ memcpy (ldap_username, db.data, db.len);
|
|
+ ldap_username[db.len] = 0;
|
|
+ data_string_forget (&db, MDL);
|
|
+ }
|
|
+
|
|
+ oc = lookup_option (&server_universe, options, SV_LDAP_PASSWORD);
|
|
+ if (oc &&
|
|
+ evaluate_option_cache (&db, (struct packet*) NULL,
|
|
+ (struct lease *) NULL, (struct client_state *) NULL,
|
|
+ options, (struct option_state *) NULL, &global_scope, oc, MDL))
|
|
+ {
|
|
+ ldap_password = dmalloc (db.len + 1, MDL);
|
|
+ if (!ldap_password)
|
|
+ log_fatal ("no memory for ldap password");
|
|
+ memcpy (ldap_password, db.data, db.len);
|
|
+ ldap_password[db.len] = 0;
|
|
+ data_string_forget (&db, MDL);
|
|
+ }
|
|
+
|
|
+ oc = lookup_option (&server_universe, options, SV_LDAP_BASE_DN);
|
|
+ if (oc &&
|
|
+ evaluate_option_cache (&db, (struct packet*) NULL,
|
|
+ (struct lease *) NULL, (struct client_state *) NULL,
|
|
+ options, (struct option_state *) NULL, &global_scope, oc, MDL))
|
|
+ {
|
|
+ ldap_base_dn = dmalloc (db.len + 1, MDL);
|
|
+ if (!ldap_base_dn)
|
|
+ log_fatal ("no memory for ldap password");
|
|
+ memcpy (ldap_base_dn, db.data, db.len);
|
|
+ ldap_base_dn[db.len] = 0;
|
|
+ data_string_forget (&db, MDL);
|
|
+ }
|
|
+
|
|
+ oc = lookup_option (&server_universe, options, SV_LDAP_METHOD);
|
|
+ if (oc &&
|
|
+ evaluate_option_cache (&db, (struct packet*) NULL,
|
|
+ (struct lease *) NULL, (struct client_state *) NULL,
|
|
+ options, (struct option_state *) NULL, &global_scope, oc, MDL))
|
|
+ {
|
|
+
|
|
+ if (db.len == 1)
|
|
+ ldap_method = db.data [0];
|
|
+ else
|
|
+ log_fatal ("invalid dns update type");
|
|
+ data_string_forget (&db, MDL);
|
|
+ }
|
|
+
|
|
+ option_state_dereference (&options, MDL);
|
|
+ }
|
|
+
|
|
+ if (ldap_server == NULL || ldap_username == NULL || ldap_password == NULL ||
|
|
+ ldap_base_dn == NULL)
|
|
+ {
|
|
+ log_info ("Not searching LDAP since ldap-server, ldap-port, ldap-username, ldap-password and ldap-baes-dn were not specified in the config file");
|
|
+ disable_ldap = 1;
|
|
+ return;
|
|
+ }
|
|
+
|
|
+#if defined (DEBUG_LDAP)
|
|
+ log_info ("Connecting to LDAP server ldap://%s", ldap_server);
|
|
+#endif
|
|
+
|
|
+ char *tmpserver = NULL;
|
|
+ if ((tmpserver = malloc(strlen(ldap_server) + 8)) == NULL)
|
|
+ {
|
|
+ log_error ("Cannot init tmpldapserver string to ldap://%s", ldap_server);
|
|
+ disable_ldap = 1;
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ if (sprintf(tmpserver, "ldap://%s", ldap_server) == -1)
|
|
+ {
|
|
+ log_error ("Cannot init tmpldapserver via sprintf()");
|
|
+ disable_ldap = 1;
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ ldap_initialize (&ld, tmpserver);
|
|
+ if (ld == NULL)
|
|
+ {
|
|
+ log_error ("Cannot init ldap session to %s", ldap_server);
|
|
+ disable_ldap = 1;
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ free (tmpserver);
|
|
+
|
|
+ struct berval cred;
|
|
+ cred.bv_val = strdup(ldap_password);
|
|
+ cred.bv_len = strlen(ldap_password);
|
|
+ ret = ldap_sasl_bind_s (ld, ldap_username, LDAP_SASL_SIMPLE,
|
|
+ &cred, NULL,NULL, NULL);
|
|
+ if (ret != LDAP_SUCCESS)
|
|
+ {
|
|
+ log_error ("Error: Cannot log into ldap server %s: %s", ldap_server,
|
|
+ ldap_err2string (ret));
|
|
+ disable_ldap = 1;
|
|
+ ldap_unbind_ext (ld, NULL, NULL);
|
|
+ ld = NULL;
|
|
+ return;
|
|
+ }
|
|
+
|
|
+#if defined (DEBUG_LDAP)
|
|
+ log_info ("Successfully logged into LDAP server %s", ldap_server);
|
|
+#endif
|
|
+}
|
|
+
|
|
+
|
|
+static int
|
|
+ldap_read_function (struct parse *cfile)
|
|
+{
|
|
+ char *dn, eofstring[2] = {EOF, '\0'};
|
|
+ struct ldap_config_stack *curentry;
|
|
+ LDAPMessage * ent, * res;
|
|
+ int ret;
|
|
+
|
|
+ cfile->inbuf[0] = '\0';
|
|
+ cfile->buflen = 0;
|
|
+ while (1)
|
|
+ {
|
|
+ if (ldap_stack == NULL)
|
|
+ {
|
|
+ strncat (cfile->inbuf, eofstring, LDAP_BUFFER_SIZE);
|
|
+ cfile->buflen = strlen (cfile->inbuf);
|
|
+ cfile->bufix = 1;
|
|
+ return (cfile->inbuf[0]);
|
|
+ }
|
|
+
|
|
+ if (ldap_stack->processed && ldap_stack->children != NULL)
|
|
+ curentry = ldap_stack->children;
|
|
+ else
|
|
+ curentry = ldap_stack;
|
|
+
|
|
+ dn = ldap_get_dn (ld, curentry->ldent);
|
|
+#if defined(DEBUG_LDAP)
|
|
+ log_info ("Found LDAP entry '%s'", dn);
|
|
+#endif
|
|
+
|
|
+ ldap_generate_config_string (curentry, cfile);
|
|
+ if (strlen (cfile->inbuf) == 0)
|
|
+ {
|
|
+#if defined(DEBUG_LDAP)
|
|
+ log_info ("Skipping LDAP entry '%s'", dn);
|
|
+#endif
|
|
+ ldap_memfree (dn);
|
|
+ dn = NULL;
|
|
+ next_ldap_entry (cfile);
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ curentry->processed = 1;
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ if (ld == NULL)
|
|
+ ldap_start ();
|
|
+
|
|
+ if (ld == NULL)
|
|
+ {
|
|
+ strncat (cfile->inbuf, eofstring, LDAP_BUFFER_SIZE);
|
|
+ cfile->buflen = strlen (cfile->inbuf);
|
|
+ cfile->bufix = 1;
|
|
+ return (cfile->inbuf[0]);
|
|
+ }
|
|
+
|
|
+ if ((ret = ldap_search_ext_s (ld, dn, LDAP_SCOPE_ONELEVEL, "objectClass=*",
|
|
+ NULL, 0, NULL, NULL, NULL, 0,
|
|
+ &res)) != LDAP_SUCCESS)
|
|
+ {
|
|
+ ldap_unbind_ext (ld, NULL, NULL);
|
|
+ ld = NULL;
|
|
+
|
|
+ strncat (cfile->inbuf, eofstring, LDAP_BUFFER_SIZE);
|
|
+ cfile->buflen = strlen (cfile->inbuf);
|
|
+ cfile->bufix = 1;
|
|
+ return (cfile->inbuf[0]);
|
|
+ }
|
|
+
|
|
+ ldap_memfree (dn);
|
|
+
|
|
+ ent = ldap_first_entry (ld, res);
|
|
+ if (ent != NULL)
|
|
+ add_to_config_stack (res, ent);
|
|
+ else
|
|
+ {
|
|
+ ldap_msgfree (res);
|
|
+ next_ldap_entry (cfile);
|
|
+ }
|
|
+
|
|
+#if defined (DEBUG_LDAP)
|
|
+ log_info ("Sending config line '%s'", cfile->inbuf);
|
|
+#endif
|
|
+
|
|
+ cfile->buflen = strlen (cfile->inbuf);
|
|
+ cfile->bufix = 1;
|
|
+ return (cfile->inbuf[0]);
|
|
+}
|
|
+
|
|
+
|
|
+static char *
|
|
+ldap_get_host_name (LDAPMessage * ent)
|
|
+{
|
|
+ struct berval **name;
|
|
+ char *ret;
|
|
+
|
|
+ ret = NULL;
|
|
+ if ((name = ldap_get_values_len (ld, ent, "cn")) == NULL || name[0] == NULL)
|
|
+ {
|
|
+ if (name != NULL)
|
|
+ ldap_value_free_len (name);
|
|
+
|
|
+#if defined (DEBUG_LDAP)
|
|
+ log_info ("Cannot get cn attribute for LDAP entry %s",
|
|
+ ldap_get_dn (ld, ent));
|
|
+#endif
|
|
+ return (NULL);
|
|
+ }
|
|
+
|
|
+ ret = dmalloc (strlen (name[0]->bv_val) + 1, MDL);
|
|
+ strcpy (ret, name[0]->bv_val);
|
|
+ ldap_value_free_len (name);
|
|
+
|
|
+ return (ret);
|
|
+}
|
|
+
|
|
+
|
|
+isc_result_t
|
|
+ldap_read_config (void)
|
|
+{
|
|
+ struct berval **temp;
|
|
+ char *buffer, dn[256];
|
|
+ LDAPMessage * ldres, * ent;
|
|
+ struct parse *cfile;
|
|
+ struct utsname unme;
|
|
+ isc_result_t res;
|
|
+ int ret;
|
|
+
|
|
+
|
|
+ buffer = dmalloc (LDAP_BUFFER_SIZE, MDL);
|
|
+ cfile = (struct parse *) NULL;
|
|
+ res = new_parse (&cfile, -1, buffer, LDAP_BUFFER_SIZE, "LDAP", 0);
|
|
+ if (res != ISC_R_SUCCESS)
|
|
+ return (res);
|
|
+
|
|
+ cfile->bufix = cfile->buflen = 0;
|
|
+ cfile->read_function = ldap_read_function;
|
|
+
|
|
+ if (ld == NULL)
|
|
+ ldap_start ();
|
|
+ if (ld == NULL)
|
|
+ return (ldap_server == NULL ? ISC_R_SUCCESS : ISC_R_FAILURE);
|
|
+
|
|
+ uname (&unme);
|
|
+ snprintf (dn, sizeof (dn), "(&(objectClass=dhcpServer)(cn=%s))",
|
|
+ unme.nodename);
|
|
+
|
|
+ if ((ret = ldap_search_ext_s (ld, ldap_base_dn, LDAP_SCOPE_SUBTREE, dn, NULL,
|
|
+ 0, NULL, NULL, NULL, 0, &ldres)) != LDAP_SUCCESS)
|
|
+ {
|
|
+ ldap_unbind_ext (ld, NULL, NULL);
|
|
+ ld = NULL;
|
|
+ log_error ("Cannot search LDAP for %s: %s", dn, ldap_err2string (ret));
|
|
+ return (ISC_R_FAILURE);
|
|
+ }
|
|
+
|
|
+ if ((ent = ldap_first_entry (ld, ldres)) == NULL)
|
|
+ {
|
|
+ ldap_unbind_ext (ld, NULL, NULL);
|
|
+ ld = NULL;
|
|
+ log_error ("Error: Cannot find LDAP entry matching %s", dn);
|
|
+ return (ISC_R_FAILURE);
|
|
+ }
|
|
+
|
|
+#if defined(DEBUG_LDAP)
|
|
+ buffer = ldap_get_dn (ld, ent);
|
|
+ log_info ("Found LDAP entry '%s'", buffer);
|
|
+ ldap_memfree (buffer);
|
|
+#endif
|
|
+
|
|
+ if ((temp = ldap_get_values_len (ld, ent, "dhcpServiceDN")) == NULL ||
|
|
+ temp[0]->bv_val == NULL)
|
|
+ {
|
|
+ if (temp != NULL)
|
|
+ ldap_value_free_len (temp);
|
|
+
|
|
+ ldap_unbind_ext (ld, NULL, NULL);
|
|
+ ld = NULL;
|
|
+ log_error ("Error: Cannot find LDAP entry matching %s", dn);
|
|
+ return (ISC_R_FAILURE);
|
|
+ }
|
|
+
|
|
+ ldap_msgfree (ldres);
|
|
+
|
|
+ if ((ret = ldap_search_ext_s (ld, temp[0]->bv_val, LDAP_SCOPE_BASE,
|
|
+ "objectClass=*", NULL, 0,
|
|
+ NULL, NULL, NULL, 0, &ldres)) != LDAP_SUCCESS)
|
|
+ {
|
|
+ ldap_value_free_len (temp);
|
|
+ ldap_unbind_ext (ld, NULL, NULL);
|
|
+ ld = NULL;
|
|
+ log_error ("Cannot search LDAP for %s: %s", temp[0]->bv_val,
|
|
+ ldap_err2string (ret));
|
|
+ return (ISC_R_FAILURE);
|
|
+ }
|
|
+
|
|
+ if ((ent = ldap_first_entry (ld, ldres)) == NULL)
|
|
+ {
|
|
+ ldap_value_free_len (temp);
|
|
+ ldap_unbind_ext (ld, NULL, NULL);
|
|
+ ld = NULL;
|
|
+ log_error ("Error: Cannot find LDAP entry matching %s", temp[0]->bv_val);
|
|
+ return (ISC_R_FAILURE);
|
|
+ }
|
|
+
|
|
+ ldap_value_free_len (temp);
|
|
+
|
|
+ add_to_config_stack (ldres, ent);
|
|
+
|
|
+ res = conf_file_subparse (cfile, root_group, ROOT_GROUP);
|
|
+ end_parse (&cfile);
|
|
+
|
|
+ return (res);
|
|
+}
|
|
+
|
|
+
|
|
+/* This function will parse the dhcpOption and dhcpStatements field in the LDAP
|
|
+ entry if it exists. Right now, type will be either HOST_DECL or CLASS_DECL.
|
|
+ If we are parsing a HOST_DECL, this always returns 0. If we are parsing a
|
|
+ CLASS_DECL, this will return what the current lease limit is in LDAP. If
|
|
+ there is no lease limit specified, we return 0 */
|
|
+
|
|
+static int
|
|
+ldap_parse_options (LDAPMessage * ent, struct group *group,
|
|
+ int type, struct host_decl *host,
|
|
+ struct class **class)
|
|
+{
|
|
+ struct berval **temp;
|
|
+ char option_buffer[8192];
|
|
+ int i, declaration, lease_limit;
|
|
+ enum dhcp_token token;
|
|
+ struct parse *cfile;
|
|
+ isc_result_t res;
|
|
+ const char *val;
|
|
+
|
|
+ lease_limit = 0;
|
|
+ *option_buffer = '\0';
|
|
+ if ((temp = ldap_get_values_len (ld, ent, "dhcpStatements")) != NULL)
|
|
+ {
|
|
+ for (i=0; temp[i]->bv_val != NULL; i++)
|
|
+ {
|
|
+ if (strncasecmp ("lease limit ", temp[i]->bv_val, 12) == 0)
|
|
+ {
|
|
+ lease_limit = strtol ((temp[i]->bv_val) + 12, NULL, 10);
|
|
+ continue;
|
|
+ }
|
|
+
|
|
+ strncat (option_buffer, temp[i]->bv_val, sizeof (option_buffer) - strlen (option_buffer) - 1);
|
|
+ strncat (option_buffer, ";\n", sizeof (option_buffer) - strlen (option_buffer) - 1);
|
|
+ }
|
|
+ ldap_value_free_len (temp);
|
|
+ }
|
|
+
|
|
+ if ((temp = ldap_get_values_len (ld, ent, "dhcpOption")) != NULL)
|
|
+ {
|
|
+ for (i=0; temp[i]->bv_val != NULL; i++)
|
|
+ {
|
|
+ strncat (option_buffer, "option ", sizeof (option_buffer) - strlen (option_buffer) - 1);
|
|
+ strncat (option_buffer, temp[i]->bv_val, sizeof (option_buffer) - strlen (option_buffer) - 1);
|
|
+ strncat (option_buffer, ";\n", sizeof (option_buffer) - strlen (option_buffer) - 1);
|
|
+ }
|
|
+ ldap_value_free_len (temp);
|
|
+ }
|
|
+
|
|
+ if (*option_buffer == '\0')
|
|
+ return (lease_limit);
|
|
+
|
|
+ cfile = (struct parse *) NULL;
|
|
+ res = new_parse (&cfile, -1, option_buffer, strlen (option_buffer),
|
|
+ type == HOST_DECL ? "LDAP-HOST" : "LDAP-SUBCLASS", 0);
|
|
+ if (res != ISC_R_SUCCESS)
|
|
+ return (lease_limit);
|
|
+
|
|
+#if defined (DEBUG_LDAP)
|
|
+ log_info ("Sending the following options: '%s'", option_buffer);
|
|
+#endif
|
|
+
|
|
+ declaration = 0;
|
|
+ do {
|
|
+ token = peek_token (&val, NULL, cfile);
|
|
+ if (token == END_OF_FILE)
|
|
+ break;
|
|
+ declaration = parse_statement (cfile, group, type, host, declaration);
|
|
+ } while (1);
|
|
+
|
|
+ end_parse (&cfile);
|
|
+
|
|
+ return (lease_limit);
|
|
+}
|
|
+
|
|
+
|
|
+
|
|
+int
|
|
+find_haddr_in_ldap (struct host_decl **hp, int htype, unsigned hlen,
|
|
+ const unsigned char *haddr, const char *file, int line)
|
|
+{
|
|
+ char buf[60], *type_str;
|
|
+ LDAPMessage * res, *ent;
|
|
+ struct host_decl * host;
|
|
+ isc_result_t status;
|
|
+ int ret;
|
|
+
|
|
+ if (disable_ldap || ldap_method == LDAP_METHOD_STATIC)
|
|
+ return (0);
|
|
+
|
|
+ if (ld == NULL)
|
|
+ ldap_start ();
|
|
+ if (ld == NULL)
|
|
+ return (0);
|
|
+
|
|
+ switch (htype)
|
|
+ {
|
|
+ case HTYPE_ETHER:
|
|
+ type_str = "ethernet";
|
|
+ break;
|
|
+ case HTYPE_IEEE802:
|
|
+ type_str = "token-ring";
|
|
+ break;
|
|
+ case HTYPE_FDDI:
|
|
+ type_str = "fddi";
|
|
+ break;
|
|
+ default:
|
|
+ log_info ("Ignoring unknown type %d", htype);
|
|
+ return (0);
|
|
+ }
|
|
+
|
|
+ snprintf (buf, sizeof (buf), "dhcpHWAddress=%s %s", type_str,
|
|
+ print_hw_addr (htype, hlen, haddr));
|
|
+#if defined (DEBUG_LDAP)
|
|
+ log_info ("Searching for %s in LDAP tree %s", buf, ldap_base_dn);
|
|
+#endif
|
|
+
|
|
+ if ((ret = ldap_search_ext_s (ld, ldap_base_dn, LDAP_SCOPE_SUBTREE,
|
|
+ buf, NULL, 0, NULL, NULL, NULL, 0,
|
|
+ &res)) != LDAP_SUCCESS)
|
|
+ {
|
|
+ if (ret != LDAP_NO_SUCH_OBJECT)
|
|
+ {
|
|
+ log_error ("Cannot search for %s in LDAP tree %s: %s", buf,
|
|
+ ldap_base_dn, ldap_err2string (ret));
|
|
+ ldap_unbind_ext (ld, NULL, NULL);
|
|
+ ld = NULL;
|
|
+ }
|
|
+#if defined (DEBUG_LDAP)
|
|
+ else
|
|
+ log_info ("ldap_search_ext_s returned %s when searching for %s in %s",
|
|
+ ldap_err2string (ret), buf, ldap_base_dn);
|
|
+#endif
|
|
+
|
|
+ return (0);
|
|
+ }
|
|
+
|
|
+ if ((ent = ldap_first_entry (ld, res)) != NULL)
|
|
+ {
|
|
+#if defined (DEBUG_LDAP)
|
|
+ log_info ("Found LDAP entry %s", ldap_get_dn (ld, ent));
|
|
+#endif
|
|
+
|
|
+ host = (struct host_decl *)0;
|
|
+ status = host_allocate (&host, MDL);
|
|
+ if (status != ISC_R_SUCCESS)
|
|
+ {
|
|
+ log_fatal ("can't allocate host decl struct: %s",
|
|
+ isc_result_totext (status));
|
|
+ return (0);
|
|
+ }
|
|
+
|
|
+ host->name = ldap_get_host_name (ent);
|
|
+ if (host->name == NULL)
|
|
+ {
|
|
+ host_dereference (&host, MDL);
|
|
+ ldap_msgfree (res);
|
|
+ return (0);
|
|
+ }
|
|
+
|
|
+ if (!clone_group (&host->group, root_group, MDL))
|
|
+ {
|
|
+ log_fatal ("can't clone group for host %s", host->name);
|
|
+ host_dereference (&host, MDL);
|
|
+ return (0);
|
|
+ }
|
|
+
|
|
+ ldap_parse_options (ent, host->group, HOST_DECL, host, NULL);
|
|
+
|
|
+ *hp = host;
|
|
+ ldap_msgfree (res);
|
|
+ return (1);
|
|
+ }
|
|
+
|
|
+
|
|
+ ldap_msgfree (res);
|
|
+ return (0);
|
|
+}
|
|
+
|
|
+
|
|
+int
|
|
+find_subclass_in_ldap (struct class *class, struct class **newclass,
|
|
+ struct data_string *data)
|
|
+{
|
|
+ LDAPMessage * res, * ent;
|
|
+ int ret, lease_limit;
|
|
+ isc_result_t status;
|
|
+ char buf[1024];
|
|
+
|
|
+ if (disable_ldap || ldap_method == LDAP_METHOD_STATIC)
|
|
+ return (0);
|
|
+
|
|
+ if (ld == NULL)
|
|
+ ldap_start ();
|
|
+ if (ld == NULL)
|
|
+ return (0);
|
|
+
|
|
+ snprintf (buf, sizeof (buf), "(&(objectClass=dhcpSubClass)(cn=%s)(dhcpClassData=%s))", print_hex_1 (data->len, data->data, 60), print_hex_2 (strlen (class->name), (const u_int8_t *) class->name, 60));
|
|
+#if defined (DEBUG_LDAP)
|
|
+ log_info ("Searching LDAP for %s", buf);
|
|
+#endif
|
|
+
|
|
+ if ((ret = ldap_search_ext_s (ld, ldap_base_dn, LDAP_SCOPE_SUBTREE,
|
|
+ buf, NULL, 0, NULL, NULL, NULL, 0,
|
|
+ &res)) != LDAP_SUCCESS)
|
|
+ {
|
|
+ if (ret != LDAP_NO_SUCH_OBJECT)
|
|
+ {
|
|
+ log_error ("Cannot search for %s in LDAP tree %s: %s", buf,
|
|
+ ldap_base_dn, ldap_err2string (ret));
|
|
+ ldap_unbind_ext (ld, NULL, NULL);
|
|
+ ld = NULL;
|
|
+ }
|
|
+#if defined (DEBUG_LDAP)
|
|
+ else
|
|
+ log_info ("ldap_search_ext_s returned %s when searching for %s in %s",
|
|
+ ldap_err2string (ret), buf, ldap_base_dn);
|
|
+#endif
|
|
+
|
|
+ return (0);
|
|
+ }
|
|
+
|
|
+ if ((ent = ldap_first_entry (ld, res)) != NULL)
|
|
+ {
|
|
+#if defined (DEBUG_LDAP)
|
|
+ log_info ("Found LDAP entry %s", ldap_get_dn (ld, ent));
|
|
+#endif
|
|
+
|
|
+ status = class_allocate (newclass, MDL);
|
|
+ if (status != ISC_R_SUCCESS)
|
|
+ {
|
|
+ log_error ("Cannot allocate memory for a new class");
|
|
+ return (0);
|
|
+ }
|
|
+
|
|
+ group_reference (&(*newclass)->group, class->group, MDL);
|
|
+ class_reference (&(*newclass)->superclass, class, MDL);
|
|
+ lease_limit = ldap_parse_options (ent, (*newclass)->group,
|
|
+ CLASS_DECL, NULL, newclass);
|
|
+ if (lease_limit == 0)
|
|
+ (*newclass)->lease_limit = class->lease_limit;
|
|
+ else
|
|
+ class->lease_limit = lease_limit;
|
|
+
|
|
+ if ((*newclass)->lease_limit)
|
|
+ {
|
|
+ (*newclass)->billed_leases =
|
|
+ dmalloc ((*newclass)->lease_limit * sizeof (struct lease *), MDL);
|
|
+ if (!(*newclass)->billed_leases)
|
|
+ {
|
|
+ log_error ("no memory for billing");
|
|
+ class_dereference (newclass, MDL);
|
|
+ return (0);
|
|
+ }
|
|
+ memset ((*newclass)->billed_leases, 0,
|
|
+ ((*newclass)->lease_limit * sizeof (*newclass)->billed_leases));
|
|
+ }
|
|
+
|
|
+ data_string_copy (&(*newclass)->hash_string, data, MDL);
|
|
+
|
|
+ ldap_msgfree (res);
|
|
+ return (1);
|
|
+ }
|
|
+
|
|
+
|
|
+ ldap_msgfree (res);
|
|
+ return (0);
|
|
+}
|
|
+
|
|
+#endif
|
|
+
|
|
--- dhcp-3.0.5/server/mdb.c.ldapconf 2007-03-04 15:32:24.000000000 -0500
|
|
+++ dhcp-3.0.5/server/mdb.c 2007-03-04 15:32:24.000000000 -0500
|
|
@@ -373,6 +373,12 @@
|
|
const char *file, int line)
|
|
{
|
|
struct hardware h;
|
|
+ int ret;
|
|
+
|
|
+#if defined(LDAP_CONFIGURATION)
|
|
+ if ((ret = find_haddr_in_ldap (hp, htype, hlen, haddr, file, line)))
|
|
+ return ret;
|
|
+#endif
|
|
|
|
h.hlen = hlen + 1;
|
|
h.hbuf [0] = htype;
|
|
--- dhcp-3.0.5/server/stables.c.ldapconf 2004-06-10 13:59:58.000000000 -0400
|
|
+++ dhcp-3.0.5/server/stables.c 2007-03-04 15:32:24.000000000 -0500
|
|
@@ -483,12 +483,21 @@
|
|
{ "log-facility", "Nsyslog-facilities.", &server_universe, 44 },
|
|
{ "do-forward-updates", "f", &server_universe, 45 },
|
|
{ "ping-timeout", "T", &server_universe, 46 },
|
|
+#if defined(LDAP_CONFIGURATION)
|
|
+ { "ldap-server", "t", &server_universe, 47 },
|
|
+ { "ldap-port", "d", &server_universe, 48 },
|
|
+ { "ldap-username", "t", &server_universe, 49 },
|
|
+ { "ldap-password", "t", &server_universe, 50 },
|
|
+ { "ldap-base-dn", "t", &server_universe, 51 },
|
|
+ { "ldap-method", "Nldap-methods.", &server_universe, 52 },
|
|
+#else
|
|
{ "unknown-47", "X", &server_universe, 47 },
|
|
{ "unknown-48", "X", &server_universe, 48 },
|
|
{ "unknown-49", "X", &server_universe, 49 },
|
|
{ "unknown-50", "X", &server_universe, 50 },
|
|
{ "unknown-51", "X", &server_universe, 51 },
|
|
{ "unknown-52", "X", &server_universe, 52 },
|
|
+#endif
|
|
{ "unknown-53", "X", &server_universe, 53 },
|
|
{ "unknown-54", "X", &server_universe, 54 },
|
|
{ "unknown-55", "X", &server_universe, 55 },
|
|
@@ -694,6 +703,20 @@
|
|
{ "option-end", "e", &server_universe, 255 },
|
|
};
|
|
|
|
+#if defined(LDAP_CONFIGURATION)
|
|
+struct enumeration_value ldap_values [] = {
|
|
+ { "static", LDAP_METHOD_STATIC },
|
|
+ { "dynamic", LDAP_METHOD_DYNAMIC },
|
|
+ { (char *) 0, 0 }
|
|
+};
|
|
+
|
|
+struct enumeration ldap_methods = {
|
|
+ (struct enumeration *)0,
|
|
+ "ldap-methods",
|
|
+ ldap_values
|
|
+};
|
|
+#endif
|
|
+
|
|
struct enumeration_value ddns_styles_values [] = {
|
|
{ "none", 0 },
|
|
{ "ad-hoc", 1 },
|