From: David Hankins Date: Wed, 24 Mar 2010 21:49:03 +0000 (+0000) Subject: - "The LDAP Patch" that has been circulating for some time, written by X-Git-Tag: v4_2_0b1~3^2~5 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=33692791d72335f879cb8c36ed963659dd2f153e;p=thirdparty%2Fdhcp.git - "The LDAP Patch" that has been circulating for some time, written by Brian Masney and S.Kalyanasundraram and maintained for application to the DHCP-4 sources by David Cantrell has been included. Please be advised that these sources were contributed, and do not yet meet the high standards we place on production sources we include by default. As a result, the LDAP features are only included by using a compile-time option which defaults off, and if you enable it you do so under your own recognizance. We will be improving this software over time. [ISC-Bugs #17741] --- diff --git a/Makefile.am b/Makefile.am index 698740142..928d926c4 100644 --- a/Makefile.am +++ b/Makefile.am @@ -10,7 +10,8 @@ EXTRA_DIST = RELNOTES LICENSE \ contrib/3.0b1-lease-convert contrib/dhclient-tz-exithook.sh \ contrib/dhcp.spec contrib/sethostname.sh contrib/solaris.init \ contrib/ms2isc/Registry.pm contrib/ms2isc/ms2isc.pl \ - contrib/ms2isc/readme.txt \ + contrib/ms2isc/readme.txt contrib/ldap/dhcpd-conf-to-ldap \ + contrib/ldap/dhcp.schema contrib/ldap/README.ldap \ doc/IANA-arp-parameters doc/Makefile doc/References.html \ doc/References.txt doc/References.xml doc/api+protocol \ doc/ja_JP.eucJP/dhclient-script.8 doc/ja_JP.eucJP/dhclient.8 \ diff --git a/RELNOTES b/RELNOTES index 03e1f9f4b..addae6b02 100644 --- a/RELNOTES +++ b/RELNOTES @@ -49,6 +49,16 @@ work on other platforms. Please report any problems and suggested fixes to library that names be absolute instead of relative and prevents DHCP from crashing. Bug ticket 21054. +- "The LDAP Patch" that has been circulating for some time, written by + Brian Masney and S.Kalyanasundraram and maintained for application to + the DHCP-4 sources by David Cantrell has been included. Please be + advised that these sources were contributed, and do not yet meet the + high standards we place on production sources we include by default. + As a result, the LDAP features are only included by using a compile-time + option which defaults off, and if you enable it you do so under your + own recognizance. We will be improving this software over time. + [ISC-Bugs #17741] + Changes since 4.2.0a1 - When using 'ignore client-updates;', the FQDN returned to the client diff --git a/common/conflex.c b/common/conflex.c index 77a40be31..4ef573595 100644 --- a/common/conflex.c +++ b/common/conflex.c @@ -177,9 +177,16 @@ static int get_char (cfile) /* My kingdom for WITH... */ int c; - if (cfile->bufix == cfile->buflen) + if (cfile->bufix == cfile->buflen) { +#if !defined(LDAP_CONFIGURATION) c = EOF; - else { +#else /* defined(LDAP_CONFIGURATION) */ + if (cfile->read_function != NULL) + c = cfile->read_function(cfile); + else + c = EOF; +#endif + } else { c = cfile->inbuf [cfile->bufix]; cfile->bufix++; } @@ -1502,3 +1509,4 @@ intern(char *atom, enum dhcp_token dfv) { } return dfv; } + diff --git a/common/print.c b/common/print.c index f4dda1369..dc74395da 100644 --- a/common/print.c +++ b/common/print.c @@ -163,9 +163,9 @@ char *print_base64 (const unsigned char *buf, unsigned len, } 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 --git a/configure.ac b/configure.ac index 707137f45..ff832aa6f 100644 --- a/configure.ac +++ b/configure.ac @@ -501,6 +501,34 @@ no) ;; esac +# OpenLDAP support. +AC_ARG_WITH(ldap, + AC_HELP_STRING([--with-ldap], + [enable OpenLDAP support in dhcpd (default is no)]), + [ldap=$withval], + [ldap=no]) + +# OpenLDAP with SSL support. +AC_ARG_WITH(ldapcrypto, + AC_HELP_STRING([--with-ldapcrypto], + [enable OpenLDAP crypto support in dhcpd (default is no)]), + [ldapcrypto=$withval], + [ldapcrypto=no]) + +# OpenLDAP support is disabled by default, if enabled then SSL support is an +# extra optional that is also disabled by default. Enabling LDAP SSL support +# implies enabling LDAP support. +if test x$ldap = xyes || test x$ldapcrypto = xyes ; then + AC_SEARCH_LIBS(ldap_initialize, [ldap], , + AC_MSG_FAILURE([*** Cannot find ldap_initialize with -lldap - do you need to install an OpenLDAP2 Devel package?])) + + if test x$ldapcrypto = xyes ; then + AC_SUBST(LDAP_CFLAGS, ["-DLDAP_CONFIGURATION -DLDAP_USE_SSL"]) + else + AC_SUBST(LDAP_CFLAGS, ["-DLDAP_CONFIGURATION"]) + fi +fi + # Append selected warning levels to CFLAGS before substitution (but after # AC_TRY_COMPILE & etc). CFLAGS="$CFLAGS $STD_CWARNINGS" diff --git a/includes/dhcpd.h b/includes/dhcpd.h index 4ceb22bae..28df6c86f 100644 --- a/includes/dhcpd.h +++ b/includes/dhcpd.h @@ -104,6 +104,11 @@ typedef time_t TIME; #include +#if defined(LDAP_CONFIGURATION) +# include +# include /* for uname() */ +#endif + #if !defined (BYTE_NAME_HASH_SIZE) # define BYTE_NAME_HASH_SIZE 401 /* Default would be ridiculous. */ #endif @@ -293,6 +298,16 @@ struct parse { size_t bufsiz; struct parse *saved_state; + +#if defined(LDAP_CONFIGURATION) + /* + * LDAP configuration uses a call-back to iteratively read config + * off of the LDAP repository. + * XXX: The token stream can not be rewound reliably, so this must + * be addressed for DHCPv6 support. + */ + int (*read_function)(struct parse *); +#endif }; /* Variable-length array of data. */ @@ -424,6 +439,32 @@ 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 +#if defined (LDAP_USE_SSL) +# define LDAP_SSL_OFF 0 +# define LDAP_SSL_ON 1 +# define LDAP_SSL_TLS 2 +# define LDAP_SSL_LDAPS 3 +#endif + +/* 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, @@ -671,6 +712,29 @@ struct lease_state { # define DEFAULT_MIN_ACK_DELAY_USECS 10000 /* 1/100 second */ #endif +#if defined(LDAP_CONFIGURATION) +# define SV_LDAP_SERVER 60 +# define SV_LDAP_PORT 61 +# define SV_LDAP_USERNAME 62 +# define SV_LDAP_PASSWORD 63 +# define SV_LDAP_BASE_DN 64 +# define SV_LDAP_METHOD 65 +# define SV_LDAP_DEBUG_FILE 66 +# define SV_LDAP_DHCP_SERVER_CN 67 +# define SV_LDAP_REFERRALS 68 +#if defined (LDAP_USE_SSL) +# define SV_LDAP_SSL 69 +# define SV_LDAP_TLS_REQCERT 70 +# define SV_LDAP_TLS_CA_FILE 71 +# define SV_LDAP_TLS_CA_DIR 72 +# define SV_LDAP_TLS_CERT 73 +# define SV_LDAP_TLS_KEY 74 +# define SV_LDAP_TLS_CRLCHECK 75 +# define SV_LDAP_TLS_CIPHERS 76 +# define SV_LDAP_TLS_RANDFILE 77 +#endif +#endif + #if !defined (DEFAULT_DEFAULT_LEASE_TIME) # define DEFAULT_DEFAULT_LEASE_TIME 43200 #endif @@ -2220,7 +2284,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 *, @@ -3349,6 +3413,20 @@ OMAPI_OBJECT_ALLOC_DECL (dhcp_failover_link, dhcp_failover_link_t, const char *binding_state_print (enum failover_state); +/* ldap.c */ +#if defined(LDAP_CONFIGURATION) +extern struct enumeration ldap_methods; +#if defined (LDAP_USE_SSL) +extern struct enumeration ldap_ssl_usage_enum; +extern struct enumeration ldap_tls_reqcert_enum; +extern struct enumeration ldap_tls_crlcheck_enum; +#endif +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 /* mdb6.c */ HASH_FUNCTIONS_DECL(ia, unsigned char *, struct ia_xx, ia_hash_t) diff --git a/server/Makefile.am b/server/Makefile.am index 09af72588..cdfaf471f 100644 --- a/server/Makefile.am +++ b/server/Makefile.am @@ -4,12 +4,12 @@ dist_sysconf_DATA = dhcpd.conf sbin_PROGRAMS = dhcpd dhcpd_SOURCES = 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 \ - dhcpv6.c mdb6.c + dhcpv6.c mdb6.c ldap.c ldap_casa.c -# libomapi.a this is here twice to handle circular library dependencies :( +dhcpd_CFLAGS = $(LDAP_CFLAGS) dhcpd_LDADD = ../common/libdhcp.a ../omapip/libomapi.a \ - ../dhcpctl/libdhcpctl.a ../omapip/libomapi.a \ - ../bind/lib/libdns.a ../bind/lib/libisc.a + ../dhcpctl/libdhcpctl.a ../bind/lib/libdns.a \ + ../bind/lib/libisc.a man_MANS = dhcpd.8 dhcpd.conf.5 dhcpd.leases.5 EXTRA_DIST = $(man_MANS) diff --git a/server/class.c b/server/class.c index 8aaa08941..2f92255ee 100644 --- a/server/class.c +++ b/server/class.c @@ -84,6 +84,7 @@ int check_collection (packet, lease, collection) int matched = 0; int status; int ignorep; + int classfound; for (class = collection -> classes; class; class = class -> nic) { #if defined (DEBUG_CLASS_MATCHING) @@ -129,9 +130,15 @@ int check_collection (packet, lease, collection) 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 --git a/server/confpars.c b/server/confpars.c index 27a692be0..475db64ac 100644 --- a/server/confpars.c +++ b/server/confpars.c @@ -61,7 +61,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 --git a/server/dhcpd.c b/server/dhcpd.c index 399e65b0b..f29e431bb 100644 --- a/server/dhcpd.c +++ b/server/dhcpd.c @@ -600,6 +600,14 @@ main(int argc, char **argv) { /* 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); +#if defined (LDAP_USE_SSL) + add_enumeration (&ldap_ssl_usage_enum); + add_enumeration (&ldap_tls_reqcert_enum); + add_enumeration (&ldap_tls_crlcheck_enum); +#endif +#endif if (!group_allocate (&root_group, MDL)) log_fatal ("Can't allocate root group!"); diff --git a/server/mdb.c b/server/mdb.c index 5815659c3..adcfe0639 100644 --- a/server/mdb.c +++ b/server/mdb.c @@ -600,6 +600,12 @@ int find_hosts_by_haddr (struct host_decl **hp, int htype, const char *file, int line) { struct hardware h; +#if defined(LDAP_CONFIGURATION) + int ret; + + if ((ret = find_haddr_in_ldap (hp, htype, hlen, haddr, file, line))) + return ret; +#endif h.hlen = hlen + 1; h.hbuf [0] = htype; diff --git a/server/stables.c b/server/stables.c index cd5700747..829452774 100644 --- a/server/stables.c +++ b/server/stables.c @@ -244,9 +244,87 @@ static struct option server_options[] = { { "delayed-ack", "S", &server_universe, 58, 1 }, { "max-ack-delay", "L", &server_universe, 59, 1 }, #endif +#if defined(LDAP_CONFIGURATION) + { "ldap-server", "t", &server_universe, 60, 1 }, + { "ldap-port", "d", &server_universe, 61, 1 }, + { "ldap-username", "t", &server_universe, 62, 1 }, + { "ldap-password", "t", &server_universe, 63, 1 }, + { "ldap-base-dn", "t", &server_universe, 64, 1 }, + { "ldap-method", "Nldap-methods.", &server_universe, 65, 1 }, + { "ldap-debug-file", "t", &server_universe, 66, 1 }, + { "ldap-dhcp-server-cn", "t", &server_universe, 67, 1 }, + { "ldap-referrals", "f", &server_universe, 68, 1 }, +#if defined(LDAP_USE_SSL) + { "ldap-ssl", "Nldap-ssl-usage.", &server_universe, 69, 1 }, + { "ldap-tls-reqcert", "Nldap-tls-reqcert.", &server_universe, 70, 1 }, + { "ldap-tls-ca-file", "t", &server_universe, 71, 1 }, + { "ldap-tls-ca-dir", "t", &server_universe, 72, 1 }, + { "ldap-tls-cert", "t", &server_universe, 73, 1 }, + { "ldap-tls-key", "t", &server_universe, 74, 1 }, + { "ldap-tls-crlcheck", "Nldap-tls-crlcheck.", &server_universe, 75, 1 }, + { "ldap-tls-ciphers", "t", &server_universe, 76, 1 }, + { "ldap-tls-randfile", "t", &server_universe, 77, 1 }, +#endif /* LDAP_USE_SSL */ +#endif /* LDAP_CONFIGURATION */ { 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", 1, + ldap_values +}; + +#if defined(LDAP_USE_SSL) +struct enumeration_value ldap_ssl_usage_values [] = { + { "off", LDAP_SSL_OFF }, + { "on",LDAP_SSL_ON }, + { "ldaps", LDAP_SSL_LDAPS }, + { "start_tls", LDAP_SSL_TLS }, + { (char *) 0, 0 } +}; + +struct enumeration ldap_ssl_usage_enum = { + (struct enumeration *)0, + "ldap-ssl-usage", 1, + ldap_ssl_usage_values +}; + +struct enumeration_value ldap_tls_reqcert_values [] = { + { "never", LDAP_OPT_X_TLS_NEVER }, + { "hard", LDAP_OPT_X_TLS_HARD }, + { "demand", LDAP_OPT_X_TLS_DEMAND}, + { "allow", LDAP_OPT_X_TLS_ALLOW }, + { "try", LDAP_OPT_X_TLS_TRY }, + { (char *) 0, 0 } +}; +struct enumeration ldap_tls_reqcert_enum = { + (struct enumeration *)0, + "ldap-tls-reqcert", 1, + ldap_tls_reqcert_values +}; + +struct enumeration_value ldap_tls_crlcheck_values [] = { + { "none", LDAP_OPT_X_TLS_CRL_NONE}, + { "peer", LDAP_OPT_X_TLS_CRL_PEER}, + { "all", LDAP_OPT_X_TLS_CRL_ALL }, + { (char *) 0, 0 } +}; +struct enumeration ldap_tls_crlcheck_enum = { + (struct enumeration *)0, + "ldap-tls-crlcheck", 1, + ldap_tls_crlcheck_values +}; +#endif +#endif + struct enumeration_value ddns_styles_values [] = { { "none", 0 }, { "ad-hoc", 1 },