Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > 130701790bf2d95e902edf16031ff596 > files > 4

autofs-5.0.1-0.rc2.164.el5_8.src.rpm

autofs-5.0.1 - add external bind method

From: Ian Kent <raven@themaw.net>

Add sasl external bind handler.
---

 include/lookup_ldap.h         |    7 ++
 modules/Makefile              |    5 +
 modules/cyrus-sasl-extern.c   |  117 ++++++++++++++++++++++++++++++++++++++++++
 modules/cyrus-sasl.c          |   20 +++++++
 modules/lookup_ldap.c         |  117 ++++++++++++++++++++++++++++++++++++------
 samples/autofs_ldap_auth.conf |   28 +++++++++-
 6 files changed, 277 insertions(+), 17 deletions(-)
 create mode 100644 modules/cyrus-sasl-extern.c


--- autofs-5.0.1.orig/include/lookup_ldap.h
+++ autofs-5.0.1/include/lookup_ldap.h
@@ -9,6 +9,7 @@
 #include <libxml/tree.h>
 #endif
 
+#include "list.h"
 #include "dclist.h"
 
 struct ldap_schema {
@@ -75,9 +76,13 @@ struct lookup_context {
 	int          kinit_done;
 	int          kinit_successful;
 #ifdef WITH_SASL
+	/* Kerberos */
 	krb5_context krb5ctxt;
 	krb5_ccache  krb5_ccache;
 	sasl_conn_t  *sasl_conn;
+	/* SASL external */
+	char	     *extern_cert;
+	char	     *extern_key;
 #endif
 	/* keytab file name needs to be added */
 
@@ -109,6 +114,8 @@ int autofs_sasl_bind(unsigned logopt, LD
 void autofs_sasl_unbind(struct lookup_context *ctxt);
 void autofs_sasl_dispose(struct lookup_context *ctxt);
 void autofs_sasl_done(void);
+/* cyrus-sasl-extern */
+int do_sasl_extern(LDAP *ldap, struct lookup_context *ctxt);
 #endif
 
 #endif
--- autofs-5.0.1.orig/modules/Makefile
+++ autofs-5.0.1/modules/Makefile
@@ -42,7 +42,7 @@ ifeq ($(LDAP), 1)
   SRCS += lookup_ldap.c
   MODS += lookup_ldap.so
   ifeq ($(SASL), 1)
-    SASL_OBJ = cyrus-sasl.o
+    SASL_OBJ = cyrus-sasl.o cyrus-sasl-extern.o
     LDAP_FLAGS += $(SASL_FLAGS) $(XML_FLAGS) -DLDAP_THREAD_SAFE
     LIBLDAP += $(LIBSASL) $(XML_LIBS)
   endif
@@ -87,6 +87,9 @@ lookup_hesiod.so: lookup_hesiod.c
 cyrus-sasl.o: cyrus-sasl.c
 	$(CC) $(CFLAGS) $(LDAP_FLAGS) -c $<
 
+cyrus-sasl-extern.o: cyrus-sasl-extern.c
+	$(CC) $(CFLAGS) $(LDAP_FLAGS) -c $<
+
 lookup_ldap.so: lookup_ldap.c dclist.o $(SASL_OBJ)
 	$(CC) $(SOLDFLAGS) $(CFLAGS) $(LDAP_FLAGS) -o lookup_ldap.so \
 		lookup_ldap.c dclist.o $(SASL_OBJ) \
--- /dev/null
+++ autofs-5.0.1/modules/cyrus-sasl-extern.c
@@ -0,0 +1,117 @@
+/*
+ * cyrus-sasl-extern.c - Module for Cyrus sasl external authentication.
+ *
+ *   Copyright 2010 Ian Kent <raven@themaw.net>
+ *   Copyright 2010 Red Hat, Inc.
+ *   All rights reserved.
+ *
+ *   This program is free software; you can redistribute it and/or modify
+ *   it under the terms of the GNU General Public License as published by
+ *   the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA 02139,
+ *   USA; either version 2 of the License, or (at your option) any later
+ *   version.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *   GNU General Public License for more details.
+ */
+
+#include "config.h"
+
+#ifdef WITH_SASL
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sasl/sasl.h>
+#include <ldap.h>
+#include <ldap_cdefs.h>
+#include <lber_types.h>
+
+#include "lookup_ldap.h"
+
+struct values {
+	char *mech;
+	char *realm;
+	char *authcid;
+	char *authzid;
+	char *password;
+	char **resps;
+	int nresps;
+};
+
+static int interaction(unsigned flags, sasl_interact_t *interact, void *values)
+{
+	const char *val = interact->defresult;
+	struct values *vals = values;
+
+	switch(interact->id) {
+	case SASL_CB_GETREALM:
+		if (values)
+			val = vals->realm;
+		break;
+
+	case SASL_CB_AUTHNAME:
+		if (values)
+			val = vals->authcid;
+		break;
+
+	case SASL_CB_PASS:
+		if (values)
+			val = vals->password;
+		break;
+
+	case SASL_CB_USER:
+		if (values)
+			val = vals->authzid;
+		break;
+
+	case SASL_CB_NOECHOPROMPT:
+	case SASL_CB_ECHOPROMPT:
+		break;
+	}
+
+	if (val && !*val)
+		val = NULL;
+
+	if (val || interact->id == SASL_CB_USER) {
+		interact->result = (val && *val) ? val : "";
+		interact->len = strlen(interact->result);
+	}
+
+	return LDAP_SUCCESS;
+}
+
+int sasl_extern_interact(LDAP *ldap, unsigned flags, void *values, void *list)
+{
+	sasl_interact_t *interact = list;
+
+	if (!ldap)
+		return LDAP_PARAM_ERROR;
+
+	while (interact->id != SASL_CB_LIST_END) {
+		int rc = interaction(flags, interact, values);
+		if (rc)
+			return rc;
+		interact++;
+	}
+
+	return LDAP_SUCCESS;
+}
+
+int do_sasl_extern(LDAP *ldap, struct lookup_context *ctxt)
+{
+	int flags = LDAP_SASL_QUIET;
+	char *mech = ctxt->sasl_mech;
+	struct values values;
+	int rc;
+
+	memset(&values, 0, sizeof(struct values));
+	values.mech = mech;
+
+	rc = ldap_sasl_interactive_bind_s(ldap, NULL, mech, NULL, NULL,
+					  flags, sasl_extern_interact, &values);
+	return rc;
+}
+#endif
--- autofs-5.0.1.orig/modules/cyrus-sasl.c
+++ autofs-5.0.1/modules/cyrus-sasl.c
@@ -867,6 +867,26 @@ autofs_sasl_bind(unsigned logopt, LDAP *
 	if (ctxt->sasl_conn)
 		return 0;
 
+	if (ctxt->sasl_mech && !strncmp(ctxt->sasl_mech, "EXTERNAL", 8)) {
+		int result;
+
+		debug(logopt,
+		      "Attempting sasl bind with mechanism %s",
+		      ctxt->sasl_mech);
+
+		result = do_sasl_extern(ldap, ctxt);
+		if (result)
+			debug(logopt,
+			      "Failed to authenticate with mech %s",
+			      ctxt->sasl_mech);
+		else
+			debug(logopt,
+			      "sasl bind with mechanism %s succeeded",
+			      ctxt->sasl_mech);
+
+		return result;
+	}
+
 	sasl_auth_id = ctxt->user;
 	sasl_auth_secret = ctxt->secret;
 
--- autofs-5.0.1.orig/modules/lookup_ldap.c
+++ autofs-5.0.1/modules/lookup_ldap.c
@@ -42,6 +42,9 @@
 
 int lookup_version = AUTOFS_LOOKUP_VERSION;	/* Required by protocol */
 
+#define ENV_LDAPTLS_CERT	"LDAPTLS_CERT"
+#define ENV_LDAPTLS_KEY		"LDAPTLS_KEY"
+
 static struct ldap_schema common_schema[] = {
 	{"nisMap", "nisMapName", "nisObject", "cn", "nisMapEntry"},
 	{"automountMap", "ou", "automount", "cn", "automountInformation"},
@@ -51,6 +54,43 @@ static unsigned int common_schema_count 
 
 static int decode_percent_hack(const char *, char **);
 
+static char *get_set_env(unsigned logopt, const char *name, const char *val)
+{
+	char *save = NULL;
+	char *tmp;
+	int ret;
+
+	tmp = getenv(name);
+	if (tmp) {
+		save = strdup(tmp);
+		if (!save) {
+			error(logopt,
+			      "failed to alloc save string for %s", name);
+			return NULL;
+		}
+	}
+
+	ret = setenv(name, val, 1);
+	if (ret == -1) {
+		error(logopt, "failed to set config value for %s", name);
+		free(save);
+		return NULL;
+	}
+
+	return save;
+}
+
+static void restore_env(unsigned logopt, const char *name, char *val)
+{
+	int ret;
+
+	ret = setenv(name, val, 1);
+	if (ret == -1)
+		error(logopt, "failed to restore config value for %s", name);
+	free(val);
+	return;
+}
+
 static void uris_mutex_lock(struct lookup_context *ctxt)
 {
 	int status = pthread_mutex_lock(&ctxt->uris_mutex);
@@ -506,17 +546,29 @@ static int do_bind(unsigned logopt, LDAP
 
 static LDAP *do_connect(unsigned logopt, const char *uri, struct lookup_context *ctxt)
 {
+	char *env_tls_cert = NULL;
+	char *env_tls_key = NULL;
 	LDAP *ldap;
 
-	ldap = init_ldap_connection(logopt, uri, ctxt);
-	if (!ldap)
-		return NULL;
+	if (ctxt->extern_cert && ctxt->extern_key) {
+		env_tls_cert = get_set_env(logopt, ENV_LDAPTLS_CERT, ctxt->extern_cert);
+		env_tls_key = get_set_env(logopt, ENV_LDAPTLS_KEY, ctxt->extern_key);
+	}
 
-	if (!do_bind(logopt, ldap, uri, ctxt)) {
-		unbind_ldap_connection(logopt, ldap, ctxt);
-		return NULL;
+	ldap = init_ldap_connection(logopt, uri, ctxt);
+	if (ldap) {
+		if (!do_bind(logopt, ldap, uri, ctxt)) {
+			unbind_ldap_connection(logopt, ldap, ctxt);
+			ldap = NULL;
+		}
 	}
 
+	if (env_tls_cert)
+		restore_env(logopt, ENV_LDAPTLS_CERT, env_tls_cert);
+
+	if (env_tls_key)
+		restore_env(logopt, ENV_LDAPTLS_KEY, env_tls_key);
+
 	return ldap;
 }
 
@@ -750,6 +802,7 @@ int parse_ldap_config(unsigned logopt, s
 	xmlNodePtr   root = NULL;
 	char         *authrequired, *auth_conf, *authtype;
 	char         *user = NULL, *secret = NULL;
+	char         *extern_cert = NULL, *extern_key = NULL;
 	char         *client_princ = NULL, *client_cc = NULL;
 	char	     *usetls, *tlsrequired;
 
@@ -931,6 +984,32 @@ int parse_ldap_config(unsigned logopt, s
 			ret = -1;
 			goto out;
 		}
+	} else if (auth_required == LDAP_AUTH_REQUIRED &&
+		  (authtype && !strncmp(authtype, "EXTERNAL", 8))) {
+		ret = get_property(logopt, root, "external_cert",  &extern_cert);
+		ret |= get_property(logopt, root, "external_key",  &extern_key);
+		/*
+		 * For EXTERNAL auth to function we need a client certificate
+		 * and and certificate key. The ca certificate used to verify
+		 * the server certificate must also be set correctly in the
+		 * global configuration as the connection must be encrypted
+		 * and the server and client certificates must have been
+		 * verified for the EXTERNAL method to be offerred by the
+		 * server.
+		 */
+		if (ret != 0 || !extern_cert || !extern_key) {
+			error(logopt, MODPREFIX
+			      "failure getting values for authentication "
+			      "type %s", authtype);
+			free(authtype);
+			if (extern_cert)
+				free(extern_cert);
+			if (extern_key)
+				free(extern_key);
+
+			ret = -1;
+			goto out;
+		}
 	}
 
 	/*
@@ -951,6 +1030,8 @@ int parse_ldap_config(unsigned logopt, s
 	ctxt->secret = secret;
 	ctxt->client_princ = client_princ;
 	ctxt->client_cc = client_cc;
+	ctxt->extern_cert = extern_cert;
+	ctxt->extern_key = extern_key;
 
 	debug(logopt, MODPREFIX
 	      "ldap authentication configured with the following options:");
@@ -960,14 +1041,18 @@ int parse_ldap_config(unsigned logopt, s
 	      "auth_required: %u, "
 	      "sasl_mech: %s",
 	      use_tls, tls_required, auth_required, authtype);
-	debug(logopt, MODPREFIX
-	      "user: %s, "
-	      "secret: %s, "
-	      "client principal: %s "
-	      "credential cache: %s",
-	      user, secret ? "specified" : "unspecified",
-	      client_princ, client_cc);
-
+	if (authtype && !strncmp(authtype, "EXTERNAL", 8)) {
+		debug(logopt, MODPREFIX "external cert: %s", extern_cert);
+		debug(logopt, MODPREFIX "external key: %s ", extern_key);
+	} else {
+		debug(logopt, MODPREFIX
+		      "user: %s, "
+		      "secret: %s, "
+		      "client principal: %s "
+		      "credential cache: %s",
+		      user, secret ? "specified" : "unspecified",
+		      client_princ, client_cc);
+	}
 out:
 	xmlFreeDoc(doc);
 
@@ -1219,6 +1304,10 @@ static void free_context(struct lookup_c
 		defaults_free_searchdns(ctxt->sdns);
 	if (ctxt->dclist)
 		free_dclist(ctxt->dclist);
+	if (ctxt->extern_cert)
+		free(ctxt->extern_cert);
+	if (ctxt->extern_key)
+		free(ctxt->extern_key);
 	free(ctxt);
 
 	return;
--- autofs-5.0.1.orig/samples/autofs_ldap_auth.conf
+++ autofs-5.0.1/samples/autofs_ldap_auth.conf
@@ -34,13 +34,37 @@ authtype  -  This attribute can be used 
 	    automounter will attempt to authenticate to the ldap server
 	    using the list of supportedSASLmechanisms obtained from the
 	    directory server.  Explicitly setting the authtype will bypass
-	    this selection and only try the mechanism specified.  Legal
-	    values for this attribute include:
+	    this selection and only try the mechanism specified. The
+	    EXTERNAL mechanism may be used to authenticate using a client
+	    certificate and requires that authrequired set to "yes" if
+	    using SSL or usetls, tlsrequired and authrequired all set to
+	    "yes" if using TLS, in addition to authtype being set EXTERNAL.
+
+	    Legal values for this attribute include:
 	    "GSSAPI"
 	    "LOGIN"
 	    "PLAIN"
 	    "ANONYMOUS"
 	    "DIGEST-MD5"
+	    "EXTERNAL"
+
+	    If using authtype EXTERNAL two additional configuration entries
+	    are required:
+
+	    external_cert="<client certificate path>"
+
+	    This specifies the path of the file containing the client
+	    certificate.
+
+	    external_key="<client certificate key path>"
+
+	    This specifies the path of the file containing the client
+	    certificate key.
+
+	    These two configuration entries are mandatory when using the
+	    EXTERNAL method as the HOME environment variable cannot be
+	    assumed to be set or, if it is, to be set to the location we
+	    expect.
 
 user  -  This attribute holds the authentication identity used by
 	    authentication mechanisms that require it.  Legal values for