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 },