[dhcp] and the patch ;-)

Jiří Popelka jpopelka at fedoraproject.org
Tue Nov 4 15:54:14 UTC 2014


commit 18026f47c3398b9bee4573b77e8bfe5bca528b1b
Author: Jiri Popelka <jpopelka at redhat.com>
Date:   Tue Nov 4 16:54:02 2014 +0100

    and the patch ;-)

 dhcp-ldapgssapi.patch |  620 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 620 insertions(+), 0 deletions(-)
---
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 <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. */
+@@ -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 <william at 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
++
+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 <william at 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 *);
+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 <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)
+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 },


More information about the scm-commits mailing list