2015-02-08 17:31:39 +00:00
|
|
|
diff -up dhcp-4.3.2b1/configure.ac.ldapgssapi dhcp-4.3.2b1/configure.ac
|
|
|
|
--- dhcp-4.3.2b1/configure.ac.ldapgssapi 2015-02-08 18:01:27.962621131 +0100
|
|
|
|
+++ dhcp-4.3.2b1/configure.ac 2015-02-08 18:01:27.966621074 +0100
|
2014-11-04 15:54:02 +00:00
|
|
|
@@ -671,19 +671,40 @@ AC_ARG_WITH(ldapcrypto,
|
|
|
|
[ldapcrypto=$withval],
|
|
|
|
[ldapcrypto=no])
|
|
|
|
|
|
|
|
+# Gssapi to allow LDAP to authenticate with a keytab
|
|
|
|
+AC_ARG_WITH(krb5,
|
|
|
|
+ AC_HELP_STRING([--with-krb5],
|
|
|
|
+ [enable krb5/gssapi authentication for OpenLDAP in dhcpd (default is no)]),
|
|
|
|
+ [krb5=$withval],
|
|
|
|
+ [krb5=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
|
|
|
|
+# implies enabling LDAP support. Similarly, KRB5 support implies LDAP support,
|
|
|
|
+# but doesn't include SSL. The two are not dependant.
|
|
|
|
+if test x$ldap = xyes || test x$ldapcrypto = xyes || test x$krb5 = 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?]))
|
|
|
|
AC_SEARCH_LIBS(ber_pvt_opt_on, [lber], ,
|
|
|
|
AC_MSG_FAILURE([*** Cannot find ber_pvt_opt_on with -llber - do you need to install an OpenLDAP2 Devel package?]))
|
|
|
|
-
|
|
|
|
+ if test x$krb5 = xyes ; then
|
|
|
|
+ AC_SEARCH_LIBS(krb5_init_context, [krb5], ,
|
|
|
|
+ AC_MSG_FAILURE([*** Cannot find krb5_init_context with -lkrb5 - do you need to install a Kerberos Devel package?]))
|
|
|
|
+ fi
|
|
|
|
+
|
|
|
|
+ # Can this be done better?
|
|
|
|
if test x$ldapcrypto = xyes ; then
|
|
|
|
- AC_SUBST(LDAP_CFLAGS, ["-DLDAP_CONFIGURATION -DLDAP_USE_SSL"])
|
|
|
|
+ if test x$krb5 = xyes; then
|
|
|
|
+ AC_SUBST(LDAP_CFLAGS, ["-DLDAP_CONFIGURATION -DLDAP_USE_SSL -DLDAP_USE_GSSAPI"])
|
|
|
|
+ else
|
|
|
|
+ AC_SUBST(LDAP_CFLAGS, ["-DLDAP_CONFIGURATION -DLDAP_USE_SSL"])
|
|
|
|
+ fi
|
|
|
|
else
|
|
|
|
- AC_SUBST(LDAP_CFLAGS, ["-DLDAP_CONFIGURATION"])
|
|
|
|
+ if test x$krb5 = xyes; then
|
|
|
|
+ AC_SUBST(LDAP_CFLAGS, ["-DLDAP_CONFIGURATION -DLDAP_USE_GSSAPI"])
|
|
|
|
+ else
|
|
|
|
+ AC_SUBST(LDAP_CFLAGS, ["-DLDAP_CONFIGURATION"])
|
|
|
|
+ fi
|
|
|
|
fi
|
|
|
|
fi
|
|
|
|
|
2015-02-08 17:31:39 +00:00
|
|
|
diff -up dhcp-4.3.2b1/includes/dhcpd.h.ldapgssapi dhcp-4.3.2b1/includes/dhcpd.h
|
|
|
|
--- dhcp-4.3.2b1/includes/dhcpd.h.ldapgssapi 2015-02-08 18:01:27.924621669 +0100
|
|
|
|
+++ dhcp-4.3.2b1/includes/dhcpd.h 2015-02-08 18:03:03.145273551 +0100
|
2014-11-04 15:54:02 +00:00
|
|
|
@@ -103,7 +103,14 @@ typedef time_t TIME;
|
|
|
|
#if defined(LDAP_CONFIGURATION)
|
|
|
|
# include <ldap.h>
|
|
|
|
# include <sys/utsname.h> /* for uname() */
|
|
|
|
-#endif
|
|
|
|
+# if defined(LDAP_USE_GSSAPI)
|
|
|
|
+# include <krb5.h>
|
|
|
|
+# include <string.h>
|
|
|
|
+# include <stdio.h>
|
|
|
|
+# include <time.h>
|
|
|
|
+# include <unistd.h>
|
|
|
|
+# endif /* GSSAPI */
|
|
|
|
+#endif /* LDAP CONFIGURATION */
|
|
|
|
|
|
|
|
#if !defined (BYTE_NAME_HASH_SIZE)
|
|
|
|
# define BYTE_NAME_HASH_SIZE 401 /* Default would be ridiculous. */
|
2015-02-08 17:31:39 +00:00
|
|
|
@@ -743,6 +750,13 @@ struct lease_state {
|
|
|
|
#define SV_SERVER_ID_CHECK 86
|
|
|
|
#define SV_PREFIX_LEN_MODE 87
|
2014-11-04 15:54:02 +00:00
|
|
|
|
|
|
|
+#if defined(LDAP_CONFIGURATION)
|
|
|
|
+#if defined (LDAP_USE_GSSAPI)
|
2015-02-08 17:31:39 +00:00
|
|
|
+# define SV_LDAP_GSSAPI_KEYTAB 88
|
|
|
|
+# define SV_LDAP_GSSAPI_PRINCIPAL 89
|
2014-11-04 15:54:02 +00:00
|
|
|
+#endif
|
|
|
|
+#endif
|
|
|
|
+
|
|
|
|
#if !defined (DEFAULT_PING_TIMEOUT)
|
|
|
|
# define DEFAULT_PING_TIMEOUT 1
|
|
|
|
#endif
|
2015-02-08 17:31:39 +00:00
|
|
|
diff -up dhcp-4.3.2b1/server/krb_helper.c.ldapgssapi dhcp-4.3.2b1/server/krb_helper.c
|
|
|
|
--- dhcp-4.3.2b1/server/krb_helper.c.ldapgssapi 2015-02-08 18:01:27.967621060 +0100
|
|
|
|
+++ dhcp-4.3.2b1/server/krb_helper.c 2015-02-08 18:01:27.967621060 +0100
|
2014-11-04 15:54:02 +00:00
|
|
|
@@ -0,0 +1,220 @@
|
|
|
|
+/* krb_helper.c
|
|
|
|
+
|
|
|
|
+ Helper routings for allowing LDAP to read configuration with GSSAPI/krb auth */
|
|
|
|
+
|
|
|
|
+/*
|
|
|
|
+ * Copyright (c) 2014 William B.
|
|
|
|
+ * 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 helper was written by William Brown <william@adelaide.edu.au>,
|
|
|
|
+ * inspired by krb5_helper.c from bind-dyndb-ldap by Simo Sorce (Redhat)
|
|
|
|
+ */
|
|
|
|
+
|
|
|
|
+#include "dhcpd.h"
|
|
|
|
+#include "krb_helper.h"
|
|
|
|
+
|
|
|
|
+#if defined(LDAP_USE_GSSAPI)
|
|
|
|
+
|
|
|
|
+//#include "ktinit.h"
|
|
|
|
+//#include <string.h>
|
|
|
|
+//#include <krb5.h>
|
|
|
|
+//#include <stdio.h>
|
|
|
|
+//#include <unistd.h>
|
|
|
|
+//#include <time.h>
|
|
|
|
+
|
|
|
|
+#define KRB_DEFAULT_KEYTAB "FILE:/etc/dhcp/dhcp.keytab"
|
|
|
|
+#define KRB_MIN_TIME 300
|
|
|
|
+
|
|
|
|
+#define CHECK_KRB5(ctx, err, msg, ...) \
|
|
|
|
+ do { \
|
|
|
|
+ if (err) { \
|
|
|
|
+ const char * errmsg = krb5_get_error_message(ctx, err); \
|
|
|
|
+ log_error("Err: %s -> %s\n", msg, errmsg); \
|
|
|
|
+ result = ISC_R_FAILURE; \
|
|
|
|
+ goto cleanup; \
|
|
|
|
+ } \
|
|
|
|
+ } while (0)
|
|
|
|
+
|
|
|
|
+#define CHECK(ret_code, msg) \
|
|
|
|
+ if (ret_code != 0) { \
|
|
|
|
+ log_error("Error, %i %s\n", ret_code, msg); \
|
|
|
|
+ goto cleanup; \
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+static isc_result_t
|
|
|
|
+check_credentials(krb5_context context, krb5_ccache ccache, krb5_principal service)
|
|
|
|
+{
|
|
|
|
+ char *realm = NULL;
|
|
|
|
+ krb5_creds creds;
|
|
|
|
+ krb5_creds mcreds;
|
|
|
|
+ krb5_error_code krberr;
|
|
|
|
+ krb5_timestamp now;
|
|
|
|
+ isc_result_t result = ISC_R_FAILURE;
|
|
|
|
+
|
|
|
|
+ memset(&mcreds, 0, sizeof(mcreds));
|
|
|
|
+ memset(&creds, 0, sizeof(creds));
|
|
|
|
+
|
|
|
|
+ krberr = krb5_get_default_realm(context, &realm);
|
|
|
|
+ CHECK_KRB5(context, krberr, "Failed to retrieve default realm");
|
|
|
|
+
|
|
|
|
+ krberr = krb5_build_principal(context, &mcreds.server,
|
|
|
|
+ strlen(realm), realm,
|
|
|
|
+ "krbtgt", realm, NULL);
|
|
|
|
+ CHECK_KRB5(context, krberr, "Failed to build 'krbtgt/REALM' principal");
|
|
|
|
+
|
|
|
|
+ mcreds.client = service;
|
|
|
|
+
|
|
|
|
+ krberr = krb5_cc_retrieve_cred(context, ccache, 0, &mcreds, &creds);
|
|
|
|
+
|
|
|
|
+ if (krberr) {
|
|
|
|
+ const char * errmsg = krb5_get_error_message(context, krberr);
|
|
|
|
+ log_error("Credentials are not present in cache (%s)\n", errmsg);
|
|
|
|
+ krb5_free_error_message(context, errmsg);
|
|
|
|
+ result = ISC_R_FAILURE;
|
|
|
|
+ goto cleanup;
|
|
|
|
+ }
|
|
|
|
+ CHECK_KRB5(context, krberr, "Credentials are not present in cache ");
|
|
|
|
+
|
|
|
|
+ krberr = krb5_timeofday(context, &now);
|
|
|
|
+ CHECK_KRB5(context, krberr, "Failed to get time of day");
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ if (now > (creds.times.endtime + KRB_MIN_TIME)) {
|
|
|
|
+ log_error("Credentials cache expired");
|
|
|
|
+ result = ISC_R_FAILURE;
|
|
|
|
+ goto cleanup;
|
|
|
|
+ } else {
|
|
|
|
+ char buf[255];
|
|
|
|
+ char fill = ' ';
|
|
|
|
+ krb5_timestamp_to_sfstring(creds.times.endtime, buf, 16, &fill);
|
|
|
|
+ log_info("Credentials valid til %s\n", buf);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ result = ISC_R_SUCCESS;
|
|
|
|
+
|
|
|
|
+cleanup:
|
|
|
|
+ krb5_free_cred_contents(context, &creds);
|
|
|
|
+ if (mcreds.server) krb5_free_principal(context, mcreds.server);
|
|
|
|
+ if (realm) krb5_free_default_realm(context, realm);
|
|
|
|
+ return result;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+isc_result_t
|
|
|
|
+krb5_get_tgt(const char *principal, const char *keyfile)
|
|
|
|
+{
|
|
|
|
+ isc_result_t result = ISC_R_FAILURE;
|
|
|
|
+ char *ccname = NULL;
|
|
|
|
+ krb5_context context = NULL;
|
|
|
|
+ krb5_error_code krberr;
|
|
|
|
+ krb5_ccache ccache = NULL;
|
|
|
|
+ krb5_principal kprincpw = NULL;
|
|
|
|
+ krb5_creds my_creds;
|
|
|
|
+ krb5_creds * my_creds_ptr = NULL;
|
|
|
|
+ krb5_get_init_creds_opt options;
|
|
|
|
+ krb5_keytab keytab = NULL;
|
|
|
|
+ int ret;
|
|
|
|
+
|
|
|
|
+ if (keyfile == NULL || keyfile[0] == '\0') {
|
|
|
|
+ keyfile = KRB_DEFAULT_KEYTAB;
|
|
|
|
+ log_info("Using default keytab %s\n", keyfile);
|
|
|
|
+ } else {
|
|
|
|
+ if (strncmp(keyfile, "FILE:", 5) != 0) {
|
|
|
|
+ log_error("Unknown keytab path format: Does it start with FILE:?\n");
|
|
|
|
+ return ISC_R_FAILURE;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ krberr = krb5_init_context(&context);
|
|
|
|
+ CHECK_KRB5(NULL, krberr, "Kerberos context initialization failed");
|
|
|
|
+
|
|
|
|
+ result = ISC_R_SUCCESS;
|
|
|
|
+
|
|
|
|
+ ccname = "MEMORY:dhcp_ld_krb5_cc";
|
|
|
|
+ log_info("Using ccache %s\n" , ccname);
|
|
|
|
+
|
|
|
|
+ ret = setenv("KRB5CCNAME", ccname, 1);
|
|
|
|
+ if (ret == -1) {
|
|
|
|
+ log_error("Failed to setup environment\n");
|
|
|
|
+ result = ISC_R_FAILURE;
|
|
|
|
+ goto cleanup;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ krberr = krb5_cc_resolve(context, ccname, &ccache);
|
|
|
|
+ CHECK_KRB5(context, krberr, "Couldnt resolve ccache '%s'", ccname);
|
|
|
|
+
|
|
|
|
+ krberr = krb5_parse_name(context, principal, &kprincpw);
|
|
|
|
+ CHECK_KRB5(context, krberr, "Failed to parse princ '%s'", princpal);
|
|
|
|
+
|
|
|
|
+ result = check_credentials(context, ccache, kprincpw);
|
|
|
|
+ if (result == ISC_R_SUCCESS) {
|
|
|
|
+ log_info("Found valid kerberos credentials\n");
|
|
|
|
+ goto cleanup;
|
|
|
|
+ } else {
|
|
|
|
+ log_error("No valid krb5 credentials\n");
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ krberr = krb5_kt_resolve(context, keyfile, &keytab);
|
|
|
|
+ CHECK_KRB5(context, krberr,
|
|
|
|
+ "Failed to resolve kt files '%s'\n", keyfile);
|
|
|
|
+
|
|
|
|
+ memset(&my_creds, 0, sizeof(my_creds));
|
|
|
|
+ memset(&options, 0, sizeof(options));
|
|
|
|
+
|
|
|
|
+ krb5_get_init_creds_opt_set_tkt_life(&options, KRB_MIN_TIME * 2);
|
|
|
|
+ krb5_get_init_creds_opt_set_address_list(&options, NULL);
|
|
|
|
+ krb5_get_init_creds_opt_set_forwardable(&options, 0);
|
|
|
|
+ krb5_get_init_creds_opt_set_proxiable(&options, 0);
|
|
|
|
+
|
|
|
|
+ krberr = krb5_get_init_creds_keytab(context, &my_creds, kprincpw,
|
|
|
|
+ keytab, 0, NULL, &options);
|
|
|
|
+ CHECK_KRB5(context, krberr, "Failed to get initial credentials TGT\n");
|
|
|
|
+
|
|
|
|
+ my_creds_ptr = &my_creds;
|
|
|
|
+
|
|
|
|
+ krberr = krb5_cc_initialize(context, ccache, kprincpw);
|
|
|
|
+ CHECK_KRB5(context, krberr, "Failed to init ccache\n");
|
|
|
|
+
|
|
|
|
+ krberr = krb5_cc_store_cred(context, ccache, &my_creds);
|
|
|
|
+ CHECK_KRB5(context, krberr, "Failed to store credentials\n");
|
|
|
|
+
|
|
|
|
+ result = ISC_R_SUCCESS;
|
|
|
|
+ log_info("Successfully init krb tgt %s", principal);
|
|
|
|
+
|
|
|
|
+cleanup:
|
|
|
|
+ if (ccache) krb5_cc_close(context, ccache);
|
|
|
|
+ if (keytab) krb5_kt_close(context, keytab);
|
|
|
|
+ if (kprincpw) krb5_free_principal(context, kprincpw);
|
|
|
|
+ if (my_creds_ptr) krb5_free_cred_contents(context, &my_creds);
|
|
|
|
+ if (context) krb5_free_context(context);
|
|
|
|
+ return result;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+#endif
|
|
|
|
+
|
2015-02-08 17:31:39 +00:00
|
|
|
diff -up dhcp-4.3.2b1/server/krb_helper.h.ldapgssapi dhcp-4.3.2b1/server/krb_helper.h
|
|
|
|
--- dhcp-4.3.2b1/server/krb_helper.h.ldapgssapi 2015-02-08 18:01:27.968621046 +0100
|
|
|
|
+++ dhcp-4.3.2b1/server/krb_helper.h 2015-02-08 18:01:27.967621060 +0100
|
2014-11-04 15:54:02 +00:00
|
|
|
@@ -0,0 +1,40 @@
|
|
|
|
+/* krb_helper.h
|
|
|
|
+
|
|
|
|
+ Helper routings for allowing LDAP to read configuration with GSSAPI/krb auth */
|
|
|
|
+
|
|
|
|
+/*
|
|
|
|
+ * Copyright (c) 2014 William B.
|
|
|
|
+ * 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 helper was written by William Brown <william@adelaide.edu.au>,
|
|
|
|
+ * inspired by krb5_helper.c from bind-dyndb-ldap by Simo Sorce (Redhat)
|
|
|
|
+ */
|
|
|
|
+
|
|
|
|
+isc_result_t krb5_get_tgt(const char *, const char *);
|
2015-02-08 17:31:39 +00:00
|
|
|
diff -up dhcp-4.3.2b1/server/ldap.c.ldapgssapi dhcp-4.3.2b1/server/ldap.c
|
|
|
|
--- dhcp-4.3.2b1/server/ldap.c.ldapgssapi 2015-02-08 18:01:27.955621230 +0100
|
|
|
|
+++ dhcp-4.3.2b1/server/ldap.c 2015-02-08 18:01:27.968621046 +0100
|
2014-11-04 15:54:02 +00:00
|
|
|
@@ -39,10 +39,16 @@
|
|
|
|
|
|
|
|
#include "dhcpd.h"
|
|
|
|
#include <signal.h>
|
|
|
|
-#include <errno.h>
|
|
|
|
+//#include <errno.h>
|
|
|
|
+#define LDAP_DEBUG 1
|
|
|
|
|
|
|
|
#if defined(LDAP_CONFIGURATION)
|
|
|
|
|
|
|
|
+#if defined(LDAP_USE_GSSAPI)
|
|
|
|
+#include <sasl/sasl.h>
|
|
|
|
+#include "krb_helper.h"
|
|
|
|
+#endif
|
|
|
|
+
|
|
|
|
#if defined(LDAP_CASA_AUTH)
|
|
|
|
#include "ldap_casa.h"
|
|
|
|
#endif
|
|
|
|
@@ -69,6 +75,20 @@ static char *ldap_tls_ca_file = NULL,
|
|
|
|
*ldap_tls_ciphers = NULL,
|
|
|
|
*ldap_tls_randfile = NULL;
|
|
|
|
#endif
|
|
|
|
+#if defined (LDAP_USE_GSSAPI)
|
|
|
|
+static char *ldap_gssapi_keytab = NULL,
|
|
|
|
+ *ldap_gssapi_principal = NULL;
|
|
|
|
+
|
|
|
|
+static struct ldap_sasl_instance {
|
|
|
|
+ char *sasl_mech;
|
|
|
|
+ char *sasl_realm;
|
|
|
|
+ char *sasl_authz_id;
|
|
|
|
+ char *sasl_authc_id;
|
|
|
|
+ char *sasl_password;
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+static struct ldap_sasl_instance *ldap_sasl_inst = NULL;
|
|
|
|
+#endif
|
|
|
|
static struct ldap_config_stack *ldap_stack = NULL;
|
|
|
|
|
|
|
|
typedef struct ldap_dn_node {
|
|
|
|
@@ -545,6 +565,62 @@ _do_lookup_dhcp_enum_option (struct opti
|
|
|
|
return (ret);
|
|
|
|
}
|
|
|
|
|
|
|
|
+#if defined(LDAP_USE_GSSAPI)
|
|
|
|
+static int
|
|
|
|
+_ldap_sasl_interact(LDAP *ld, unsigned flags, void *defaults, void *sin)
|
|
|
|
+{
|
|
|
|
+ sasl_interact_t *in;
|
|
|
|
+ struct ldap_sasl_instance *ldap_inst = defaults;
|
|
|
|
+ int ret = LDAP_OTHER;
|
|
|
|
+ size_t size;
|
|
|
|
+
|
|
|
|
+ if (ld == NULL || sin == NULL)
|
|
|
|
+ return LDAP_PARAM_ERROR;
|
|
|
|
+
|
|
|
|
+ log_info("doing interactive bind");
|
|
|
|
+ for (in = sin; in != NULL && in->id != SASL_CB_LIST_END; in++) {
|
|
|
|
+ switch (in->id) {
|
|
|
|
+ case SASL_CB_USER:
|
|
|
|
+ log_info("got request for SASL_CB_USER %s", ldap_inst->sasl_authz_id);
|
|
|
|
+ size = strlen(ldap_inst->sasl_authz_id);
|
|
|
|
+ in->result = ldap_inst->sasl_authz_id;
|
|
|
|
+ in->len = size;
|
|
|
|
+ ret = LDAP_SUCCESS;
|
|
|
|
+ break;
|
|
|
|
+ case SASL_CB_GETREALM:
|
|
|
|
+ log_info("got request for SASL_CB_GETREALM %s", ldap_inst->sasl_realm);
|
|
|
|
+ size = strlen(ldap_inst->sasl_realm);
|
|
|
|
+ in->result = ldap_inst->sasl_realm;
|
|
|
|
+ in->len = size;
|
|
|
|
+ ret = LDAP_SUCCESS;
|
|
|
|
+ break;
|
|
|
|
+ case SASL_CB_AUTHNAME:
|
|
|
|
+ log_info("got request for SASL_CB_AUTHNAME %s", ldap_inst->sasl_authc_id);
|
|
|
|
+ size = strlen(ldap_inst->sasl_authc_id);
|
|
|
|
+ in->result = ldap_inst->sasl_authc_id;
|
|
|
|
+ in->len = size;
|
|
|
|
+ ret = LDAP_SUCCESS;
|
|
|
|
+ break;
|
|
|
|
+ case SASL_CB_PASS:
|
|
|
|
+ log_info("got request for SASL_CB_PASS %s", ldap_inst->sasl_password);
|
|
|
|
+ size = strlen(ldap_inst->sasl_password);
|
|
|
|
+ in->result = ldap_inst->sasl_password;
|
|
|
|
+ in->len = size;
|
|
|
|
+ ret = LDAP_SUCCESS;
|
|
|
|
+ break;
|
|
|
|
+ default:
|
|
|
|
+ goto cleanup;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ return ret;
|
|
|
|
+
|
|
|
|
+cleanup:
|
|
|
|
+ in->result = NULL;
|
|
|
|
+ in->len = 0;
|
|
|
|
+ return LDAP_OTHER;
|
|
|
|
+}
|
|
|
|
+#endif
|
|
|
|
+
|
|
|
|
int
|
|
|
|
ldap_rebind_cb (LDAP *ld, LDAP_CONST char *url, ber_tag_t request, ber_int_t msgid, void *parms)
|
|
|
|
{
|
|
|
|
@@ -595,20 +671,48 @@ ldap_rebind_cb (LDAP *ld, LDAP_CONST cha
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
-
|
|
|
|
- if (ldap_username != NULL || *ldap_username != '\0')
|
|
|
|
+ if (ldap_username != NULL && *ldap_username != '\0')
|
|
|
|
{
|
|
|
|
- who = ldap_username;
|
|
|
|
+#if defined(LDAP_USE_GSSAPI)
|
|
|
|
+ if (ldap_gssapi_principal != NULL) {
|
|
|
|
+ log_error("Cannot use gssapi and username / password simultaneously");
|
|
|
|
+ ldap_stop();
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+#endif
|
|
|
|
creds.bv_val = strdup(ldap_password);
|
|
|
|
creds.bv_len = strlen(ldap_password);
|
|
|
|
- }
|
|
|
|
|
|
|
|
- if ((ret = ldap_sasl_bind_s (ld, who, LDAP_SASL_SIMPLE, &creds,
|
|
|
|
- NULL, NULL, NULL)) != LDAP_SUCCESS)
|
|
|
|
- {
|
|
|
|
- log_error ("Error: Cannot login into ldap server %s:%d: %s",
|
|
|
|
- ldapurl->lud_host, ldapurl->lud_port, ldap_err2string (ret));
|
|
|
|
+ if ((ret = ldap_sasl_bind_s (ld, ldap_username, LDAP_SASL_SIMPLE,
|
|
|
|
+ &creds, NULL, NULL, NULL)) != LDAP_SUCCESS)
|
|
|
|
+ {
|
|
|
|
+ log_error ("Error: Cannot login into ldap server %s:%d: %s",
|
|
|
|
+ ldap_server, ldap_port, ldap_err2string (ret));
|
|
|
|
+ ldap_stop();
|
|
|
|
+ return ret;
|
|
|
|
+ }
|
|
|
|
+#if defined(LDAP_USE_GSSAPI)
|
|
|
|
+ } else {
|
|
|
|
+ if (ldap_gssapi_principal != NULL) {
|
|
|
|
+ krb5_get_tgt(ldap_gssapi_principal, ldap_gssapi_keytab);
|
|
|
|
+ if ((ret = ldap_sasl_interactive_bind_s(ld, NULL, ldap_sasl_inst->sasl_mech,
|
|
|
|
+ NULL, NULL, LDAP_SASL_AUTOMATIC,
|
|
|
|
+ _ldap_sasl_interact, ldap_sasl_inst)
|
|
|
|
+ ) != LDAP_SUCCESS)
|
|
|
|
+ {
|
|
|
|
+ log_error ("Error: Cannot SASL bind to ldap server %s:%d: %s",
|
|
|
|
+ ldap_server, ldap_port, ldap_err2string (ret));
|
|
|
|
+ char *msg=NULL;
|
|
|
|
+ ldap_get_option( ld, LDAP_OPT_DIAGNOSTIC_MESSAGE, (void*)&msg);
|
|
|
|
+ log_error ("\tAdditional info: %s", msg);
|
|
|
|
+ ldap_memfree(msg);
|
|
|
|
+ ldap_stop();
|
|
|
|
+ return ret;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+#endif
|
|
|
|
}
|
|
|
|
+
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
@@ -618,6 +722,12 @@ ldap_start (void)
|
|
|
|
struct option_state *options;
|
|
|
|
int ret, version;
|
|
|
|
char *uri = NULL;
|
|
|
|
+#if defined(LDAP_USE_GSSAPI)
|
|
|
|
+ char *gssapi_realm = NULL;
|
|
|
|
+ char *gssapi_user = NULL;
|
|
|
|
+ char *running = NULL;
|
|
|
|
+ const char *gssapi_delim = "@";
|
|
|
|
+#endif
|
|
|
|
struct berval creds;
|
|
|
|
|
|
|
|
if (ld != NULL)
|
|
|
|
@@ -656,6 +766,26 @@ ldap_start (void)
|
|
|
|
ldap_tls_randfile = _do_lookup_dhcp_string_option (options, SV_LDAP_TLS_RANDFILE);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
+#if defined (LDAP_USE_GSSAPI)
|
|
|
|
+ ldap_gssapi_keytab = _do_lookup_dhcp_string_option (options, SV_LDAP_GSSAPI_KEYTAB);
|
|
|
|
+ ldap_gssapi_principal = _do_lookup_dhcp_string_option (options, SV_LDAP_GSSAPI_PRINCIPAL);
|
|
|
|
+
|
|
|
|
+ running = strdup(ldap_gssapi_principal);
|
|
|
|
+ gssapi_user = strtok(running, gssapi_delim);
|
|
|
|
+ gssapi_realm = strtok(NULL, gssapi_delim);
|
|
|
|
+ ldap_sasl_inst = malloc(sizeof(struct ldap_sasl_instance));
|
|
|
|
+ if (ldap_sasl_inst == NULL) {
|
|
|
|
+ log_error("Could not allocate memory for sasl instance! Can not run!");
|
|
|
|
+ ldap_stop();
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ ldap_sasl_inst->sasl_mech = ber_strdup("GSSAPI");
|
|
|
|
+ ldap_sasl_inst->sasl_realm = ber_strdup(gssapi_realm);
|
|
|
|
+ ldap_sasl_inst->sasl_authz_id = ber_strdup(gssapi_user);
|
|
|
|
+ ldap_sasl_inst->sasl_authc_id = NULL;
|
|
|
|
+ ldap_sasl_inst->sasl_password = NULL; //"" before
|
|
|
|
+ free(running);
|
|
|
|
+#endif
|
|
|
|
|
|
|
|
#if defined (LDAP_CASA_AUTH)
|
|
|
|
if (!load_uname_pwd_from_miCASA(&ldap_username,&ldap_password))
|
|
|
|
@@ -870,6 +1000,13 @@ ldap_start (void)
|
|
|
|
|
|
|
|
if (ldap_username != NULL && *ldap_username != '\0')
|
|
|
|
{
|
|
|
|
+#if defined(LDAP_USE_GSSAPI)
|
|
|
|
+ if (ldap_gssapi_principal != NULL) {
|
|
|
|
+ log_error("Cannot use gssapi and username / password simultaneously");
|
|
|
|
+ ldap_stop();
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+#endif
|
|
|
|
creds.bv_val = strdup(ldap_password);
|
|
|
|
creds.bv_len = strlen(ldap_password);
|
|
|
|
|
|
|
|
@@ -881,6 +1018,26 @@ ldap_start (void)
|
|
|
|
ldap_stop();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
+#if defined(LDAP_USE_GSSAPI)
|
|
|
|
+ } else {
|
|
|
|
+ if (ldap_gssapi_principal != NULL) {
|
|
|
|
+ krb5_get_tgt(ldap_gssapi_principal, ldap_gssapi_keytab);
|
|
|
|
+ if ((ret = ldap_sasl_interactive_bind_s(ld, NULL, ldap_sasl_inst->sasl_mech,
|
|
|
|
+ NULL, NULL, LDAP_SASL_AUTOMATIC,
|
|
|
|
+ _ldap_sasl_interact, ldap_sasl_inst)
|
|
|
|
+ ) != LDAP_SUCCESS)
|
|
|
|
+ {
|
|
|
|
+ log_error ("Error: Cannot SASL bind to ldap server %s:%d: %s",
|
|
|
|
+ ldap_server, ldap_port, ldap_err2string (ret));
|
|
|
|
+ char *msg=NULL;
|
|
|
|
+ ldap_get_option( ld, LDAP_OPT_DIAGNOSTIC_MESSAGE, (void*)&msg);
|
|
|
|
+ log_error ("\tAdditional info: %s", msg);
|
|
|
|
+ ldap_memfree(msg);
|
|
|
|
+ ldap_stop();
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
#if defined (DEBUG_LDAP)
|
2015-02-08 17:31:39 +00:00
|
|
|
diff -up dhcp-4.3.2b1/server/Makefile.am.ldapgssapi dhcp-4.3.2b1/server/Makefile.am
|
|
|
|
--- dhcp-4.3.2b1/server/Makefile.am.ldapgssapi 2015-02-08 18:01:27.943621400 +0100
|
|
|
|
+++ dhcp-4.3.2b1/server/Makefile.am 2015-02-08 18:01:27.968621046 +0100
|
2014-11-04 15:54:02 +00:00
|
|
|
@@ -10,7 +10,7 @@ dist_sysconf_DATA = dhcpd.conf.example
|
|
|
|
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 ldap.c ldap_casa.c probes.d trace.h
|
|
|
|
+ dhcpv6.c mdb6.c ldap.c ldap_casa.c krb_helper.c probes.d trace.h
|
|
|
|
|
|
|
|
dhcpd_CFLAGS = $(LDAP_CFLAGS)
|
|
|
|
dhcpd_LDADD = ../common/libdhcp.a ../omapip/libomapi.la ../dhcpctl/libdhcpctl.la \
|
2015-02-08 17:31:39 +00:00
|
|
|
diff -up dhcp-4.3.2b1/server/stables.c.ldapgssapi dhcp-4.3.2b1/server/stables.c
|
|
|
|
--- dhcp-4.3.2b1/server/stables.c.ldapgssapi 2015-01-29 14:52:57.000000000 +0100
|
|
|
|
+++ dhcp-4.3.2b1/server/stables.c 2015-02-08 18:01:27.969621032 +0100
|
2014-11-04 15:54:02 +00:00
|
|
|
@@ -259,6 +259,10 @@ static struct option server_options[] =
|
|
|
|
{ "ldap-tls-ciphers", "t", &server_universe, 76, 1 },
|
|
|
|
{ "ldap-tls-randfile", "t", &server_universe, 77, 1 },
|
|
|
|
#endif /* LDAP_USE_SSL */
|
|
|
|
+#if defined(LDAP_USE_GSSAPI)
|
|
|
|
+ { "ldap-gssapi-keytab", "t", &server_universe, 78, 1},
|
|
|
|
+ { "ldap-gssapi-principal", "t", &server_universe, 79, 1},
|
|
|
|
+#endif /* LDAP_USE_GSSAPI */
|
|
|
|
#endif /* LDAP_CONFIGURATION */
|
|
|
|
{ "dhcp-cache-threshold", "B", &server_universe, 78, 1 },
|
|
|
|
{ "dont-use-fsync", "f", &server_universe, 79, 1 },
|