From 18026f47c3398b9bee4573b77e8bfe5bca528b1b Mon Sep 17 00:00:00 2001 From: Jiri Popelka Date: Nov 04 2014 15:54:02 +0000 Subject: and the patch ;-) --- diff --git a/dhcp-ldapgssapi.patch b/dhcp-ldapgssapi.patch new file mode 100644 index 0000000..8ada002 --- /dev/null +++ b/dhcp-ldapgssapi.patch @@ -0,0 +1,620 @@ +diff -up dhcp-4.3.1/configure.ac.ldapgssapi dhcp-4.3.1/configure.ac +--- dhcp-4.3.1/configure.ac.ldapgssapi 2014-11-04 16:08:35.017148053 +0100 ++++ dhcp-4.3.1/configure.ac 2014-11-04 16:21:09.696504777 +0100 +@@ -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 + +diff -up dhcp-4.3.1/includes/dhcpd.h.ldapgssapi dhcp-4.3.1/includes/dhcpd.h +--- dhcp-4.3.1/includes/dhcpd.h.ldapgssapi 2014-11-04 16:08:34.952148968 +0100 ++++ dhcp-4.3.1/includes/dhcpd.h 2014-11-04 16:26:14.597202025 +0100 +@@ -103,7 +103,14 @@ typedef time_t TIME; + #if defined(LDAP_CONFIGURATION) + # include + # include /* for uname() */ +-#endif ++# if defined(LDAP_USE_GSSAPI) ++# include ++# include ++# include ++# include ++# include ++# endif /* GSSAPI */ ++#endif /* LDAP CONFIGURATION */ + + #if !defined (BYTE_NAME_HASH_SIZE) + # define BYTE_NAME_HASH_SIZE 401 /* Default would be ridiculous. */ +@@ -733,6 +740,13 @@ struct lease_state { + #define SV_LOG_THRESHOLD_LOW 83 + #define SV_LOG_THRESHOLD_HIGH 84 + ++#if defined(LDAP_CONFIGURATION) ++#if defined (LDAP_USE_GSSAPI) ++# define SV_LDAP_GSSAPI_KEYTAB 85 ++# define SV_LDAP_GSSAPI_PRINCIPAL 86 ++#endif ++#endif ++ + #if !defined (DEFAULT_PING_TIMEOUT) + # define DEFAULT_PING_TIMEOUT 1 + #endif +diff -up dhcp-4.3.1/server/krb_helper.c.ldapgssapi dhcp-4.3.1/server/krb_helper.c +--- dhcp-4.3.1/server/krb_helper.c.ldapgssapi 2014-11-04 16:08:35.018148039 +0100 ++++ dhcp-4.3.1/server/krb_helper.c 2014-11-04 16:08:35.018148039 +0100 +@@ -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 , ++ * 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 ++//#include ++//#include ++//#include ++//#include ++ ++#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 ++ +diff -up dhcp-4.3.1/server/krb_helper.h.ldapgssapi dhcp-4.3.1/server/krb_helper.h +--- dhcp-4.3.1/server/krb_helper.h.ldapgssapi 2014-11-04 16:08:35.019148025 +0100 ++++ dhcp-4.3.1/server/krb_helper.h 2014-11-04 16:08:35.018148039 +0100 +@@ -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 , ++ * inspired by krb5_helper.c from bind-dyndb-ldap by Simo Sorce (Redhat) ++ */ ++ ++isc_result_t krb5_get_tgt(const char *, const char *); +diff -up dhcp-4.3.1/server/ldap.c.ldapgssapi dhcp-4.3.1/server/ldap.c +--- dhcp-4.3.1/server/ldap.c.ldapgssapi 2014-11-04 16:08:34.989148447 +0100 ++++ dhcp-4.3.1/server/ldap.c 2014-11-04 16:08:35.019148025 +0100 +@@ -39,10 +39,16 @@ + + #include "dhcpd.h" + #include +-#include ++//#include ++#define LDAP_DEBUG 1 + + #if defined(LDAP_CONFIGURATION) + ++#if defined(LDAP_USE_GSSAPI) ++#include ++#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) +diff -up dhcp-4.3.1/server/Makefile.am.ldapgssapi dhcp-4.3.1/server/Makefile.am +--- dhcp-4.3.1/server/Makefile.am.ldapgssapi 2014-11-04 16:08:35.019148025 +0100 ++++ dhcp-4.3.1/server/Makefile.am 2014-11-04 16:37:24.616639706 +0100 +@@ -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 \ +diff -up dhcp-4.3.1/server/stables.c.ldapgssapi dhcp-4.3.1/server/stables.c +--- dhcp-4.3.1/server/stables.c.ldapgssapi 2014-11-04 16:08:35.020148010 +0100 ++++ dhcp-4.3.1/server/stables.c 2014-11-04 16:42:09.109552243 +0100 +@@ -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 },