af3980861c
- Remove unnecessary /usr/include/dhcp4client/isc_dhcp headers - Make sure restorecon is run on /var/lib/dhcpd/dhcpd.leases (#251688) - Install dhcp.schema to /etc/openldap/dhcp.schema (#330471)
1489 lines
44 KiB
Diff
1489 lines
44 KiB
Diff
diff -up dhcp-3.1.0/server/mdb.c.ldap dhcp-3.1.0/server/mdb.c
|
|
--- dhcp-3.1.0/server/mdb.c.ldap 2007-06-08 14:57:02.000000000 -0400
|
|
+++ dhcp-3.1.0/server/mdb.c 2007-10-22 16:29:48.000000000 -0400
|
|
@@ -454,6 +454,12 @@ int find_hosts_by_haddr (struct host_dec
|
|
{
|
|
struct host_decl *foo;
|
|
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;
|
|
diff -up dhcp-3.1.0/server/Makefile.dist.ldap dhcp-3.1.0/server/Makefile.dist
|
|
--- dhcp-3.1.0/server/Makefile.dist.ldap 2006-07-25 09:26:00.000000000 -0400
|
|
+++ dhcp-3.1.0/server/Makefile.dist 2007-10-22 16:29:48.000000000 -0400
|
|
@@ -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 dhcpleasequery.c
|
|
+ omapi.c mdb.c stables.c salloc.c ddns.c dhcpleasequery.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 dhcpleasequery.o
|
|
+ omapi.o mdb.o stables.o salloc.o ddns.o dhcpleasequery.o ldap.o
|
|
PROG = dhcpd
|
|
MAN = dhcpd.8 dhcpd.conf.5 dhcpd.leases.5
|
|
|
|
@@ -106,6 +106,6 @@ dhcpd.leases.man5: dhcpd.leases.5
|
|
-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)
|
|
diff -up dhcp-3.1.0/server/dhcpd.c.ldap dhcp-3.1.0/server/dhcpd.c
|
|
--- dhcp-3.1.0/server/dhcpd.c.ldap 2007-05-29 13:49:44.000000000 -0400
|
|
+++ dhcp-3.1.0/server/dhcpd.c 2007-10-22 16:29:48.000000000 -0400
|
|
@@ -440,6 +440,9 @@ int main (argc, argv, envp)
|
|
/* 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!");
|
|
diff -up /dev/null dhcp-3.1.0/server/ldap.c
|
|
--- /dev/null 2007-10-22 10:27:59.854008585 -0400
|
|
+++ dhcp-3.1.0/server/ldap.c 2007-10-22 16:29:48.000000000 -0400
|
|
@@ -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] != NULL && 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] != NULL && 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] != NULL && 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] != NULL && 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] != NULL && 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] != NULL && 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-username, ldap-password and ldap-base-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] != NULL && 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] != NULL && 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
|
|
+
|
|
diff -up dhcp-3.1.0/server/confpars.c.ldap dhcp-3.1.0/server/confpars.c
|
|
--- dhcp-3.1.0/server/confpars.c.ldap 2007-06-28 13:20:40.000000000 -0400
|
|
+++ dhcp-3.1.0/server/confpars.c 2007-10-22 16:29:48.000000000 -0400
|
|
@@ -63,7 +63,17 @@ void parse_trace_setup ()
|
|
|
|
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,
|
|
diff -up dhcp-3.1.0/server/class.c.ldap dhcp-3.1.0/server/class.c
|
|
--- dhcp-3.1.0/server/class.c.ldap 2006-06-01 16:23:17.000000000 -0400
|
|
+++ dhcp-3.1.0/server/class.c 2007-10-22 16:29:48.000000000 -0400
|
|
@@ -90,6 +90,7 @@ int check_collection (packet, lease, col
|
|
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,15 @@ int check_collection (packet, lease, col
|
|
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,
|
|
diff -up dhcp-3.1.0/server/stables.c.ldap dhcp-3.1.0/server/stables.c
|
|
--- dhcp-3.1.0/server/stables.c.ldap 2007-04-27 18:48:10.000000000 -0400
|
|
+++ dhcp-3.1.0/server/stables.c 2007-10-22 16:29:48.000000000 -0400
|
|
@@ -238,9 +238,38 @@ static struct option server_options[] =
|
|
{ "adaptive-lease-time-threshold", "B", &server_universe, 50, 1 },
|
|
{ "do-reverse-updates", "f", &server_universe, 51, 1 },
|
|
{ "fqdn-reply", "f", &server_universe, 52, 1 },
|
|
+#if defined(LDAP_CONFIGURATION)
|
|
+ { "ldap-server", "t", &server_universe, 53 },
|
|
+ { "ldap-port", "d", &server_universe, 54 },
|
|
+ { "ldap-username", "t", &server_universe, 55 },
|
|
+ { "ldap-password", "t", &server_universe, 56 },
|
|
+ { "ldap-base-dn", "t", &server_universe, 57 },
|
|
+ { "ldap-method", "Nldap-methods.", &server_universe, 58 },
|
|
+#else
|
|
+ { "unknown-53", "X", &server_universe, 53 },
|
|
+ { "unknown-54", "X", &server_universe, 54 },
|
|
+ { "unknown-55", "X", &server_universe, 55 },
|
|
+ { "unknown-56", "X", &server_universe, 56 },
|
|
+ { "unknown-57", "X", &server_universe, 57 },
|
|
+ { "unknown-58", "X", &server_universe, 58 },
|
|
+#endif
|
|
{ NULL, NULL, NULL, 0, 0 }
|
|
};
|
|
|
|
+#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 },
|
|
diff -up dhcp-3.1.0/common/print.c.ldap dhcp-3.1.0/common/print.c
|
|
--- dhcp-3.1.0/common/print.c.ldap 2007-05-29 13:49:44.000000000 -0400
|
|
+++ dhcp-3.1.0/common/print.c 2007-10-22 16:29:48.000000000 -0400
|
|
@@ -168,9 +168,9 @@ char *print_base64 (const unsigned char
|
|
}
|
|
|
|
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;
|
|
diff -up dhcp-3.1.0/common/conflex.c.ldap dhcp-3.1.0/common/conflex.c
|
|
--- dhcp-3.1.0/common/conflex.c.ldap 2007-05-29 13:49:44.000000000 -0400
|
|
+++ dhcp-3.1.0/common/conflex.c 2007-10-22 16:29:48.000000000 -0400
|
|
@@ -47,6 +47,7 @@ static enum dhcp_token read_string PROTO
|
|
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 ((unsigned 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 @@ isc_result_t new_parse (cfile, file, inb
|
|
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 @@ static int get_char (cfile)
|
|
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++;
|
|
@@ -1213,3 +1207,23 @@ static enum dhcp_token intern (atom, dfv
|
|
}
|
|
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;
|
|
+}
|
|
diff -up dhcp-3.1.0/includes/dhcpd.h.ldap dhcp-3.1.0/includes/dhcpd.h
|
|
--- dhcp-3.1.0/includes/dhcpd.h.ldap 2007-05-29 13:49:44.000000000 -0400
|
|
+++ dhcp-3.1.0/includes/dhcpd.h 2007-10-22 16:29:56.000000000 -0400
|
|
@@ -81,6 +81,11 @@ typedef struct hash_table class_hash_t;
|
|
#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 (BYTE_NAME_HASH_SIZE)
|
|
# define BYTE_NAME_HASH_SIZE 401 /* Default would be rediculous. */
|
|
#endif
|
|
@@ -251,6 +256,8 @@ struct parse {
|
|
char *inbuf;
|
|
unsigned bufix, buflen;
|
|
unsigned bufsiz;
|
|
+
|
|
+ int (*read_function) (struct parse *);
|
|
};
|
|
|
|
/* Variable-length array of data. */
|
|
@@ -362,6 +369,26 @@ struct hardware {
|
|
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,
|
|
@@ -558,6 +585,15 @@ struct lease_state {
|
|
# define DEFAULT_PING_TIMEOUT 1
|
|
#endif
|
|
|
|
+#if defined(LDAP_CONFIGURATION)
|
|
+# define SV_LDAP_SERVER 47
|
|
+# define SV_LDAP_PORT 48
|
|
+# define SV_LDAP_USERNAME 49
|
|
+# define SV_LDAP_PASSWORD 50
|
|
+# define SV_LDAP_BASE_DN 51
|
|
+# define SV_LDAP_METHOD 52
|
|
+#endif
|
|
+
|
|
#if !defined (DEFAULT_DEFAULT_LEASE_TIME)
|
|
# define DEFAULT_DEFAULT_LEASE_TIME 43200
|
|
#endif
|
|
@@ -1702,7 +1738,7 @@ extern int db_time_format;
|
|
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 *,
|
|
@@ -2812,3 +2848,13 @@ OMAPI_OBJECT_ALLOC_DECL (dhcp_failover_l
|
|
#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
|
|
diff -up dhcp-3.1.0/includes/site.h.ldap dhcp-3.1.0/includes/site.h
|
|
--- dhcp-3.1.0/includes/site.h.ldap 2006-07-31 18:19:51.000000000 -0400
|
|
+++ dhcp-3.1.0/includes/site.h 2007-10-22 16:29:48.000000000 -0400
|
|
@@ -183,3 +183,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"
|