From 3effbe272147674cf92c13b387373a60f2cbbacf Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Tue, 10 Mar 2015 12:23:12 -0400 Subject: [PATCH] Improve Basic Auth based logins Set a per-thread Credentials Cache Name that will be thrown away once authentication is done. This handles both an issue with stomping on ccaches if two authentications happen in concurrent threads, as well as issues with gss_acquire_cred_with_password() reusing the ccache without actually performing an AS request. Fixes #11 --- configure.ac | 4 +++- src/mod_auth_gssapi.c | 40 ++++++++++++++++++++++++++++++++++++++++ src/mod_auth_gssapi.h | 1 + 3 files changed, 44 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 78f31a2..7be2b7e 100644 --- a/configure.ac +++ b/configure.ac @@ -53,7 +53,8 @@ PKG_CHECK_MODULES([OPENSSL], [openssl]) AC_SUBST([OPENSSL_CFLAGS]) AC_SUBST([OPENSSL_LIBS]) -AC_CHECK_HEADERS([gssapi/gssapi.h],,[AC_MSG_ERROR([Could not find GSSAPI headers])]) +AC_CHECK_HEADERS([gssapi/gssapi.h gssapi/gssapi_ext.h gssapi/gssapi_krb5.h], + ,[AC_MSG_ERROR([Could not find GSSAPI headers])]) AC_PATH_PROG(KRB5_CONFIG, krb5-config, failed) if test x$KRB5_CONFIG = xfailed; then AC_MSG_ERROR([Could not find GSSAPI development libraries]) @@ -66,6 +67,7 @@ AC_CHECK_LIB([gssapi_krb5], [gss_accept_sec_context], [], AC_CHECK_FUNCS(gss_acquire_cred_from) AC_CHECK_FUNCS(gss_store_cred_into) AC_CHECK_FUNCS(gss_acquire_cred_with_password) +AC_CHECK_FUNCS(gss_krb5_ccache_name) AC_SUBST([GSSAPI_CFLAGS]) AC_SUBST([GSSAPI_LIBS]) diff --git a/src/mod_auth_gssapi.c b/src/mod_auth_gssapi.c index aed0c3b..db87c10 100644 --- a/src/mod_auth_gssapi.c +++ b/src/mod_auth_gssapi.c @@ -183,6 +183,10 @@ static int mag_auth(request_rec *req) bool is_basic = false; gss_ctx_id_t user_ctx = GSS_C_NO_CONTEXT; gss_name_t server = GSS_C_NO_NAME; +#ifdef HAVE_GSS_KRB5_CCACHE_NAME + const char *user_ccache = NULL; + char *orig_ccache = NULL; +#endif type = ap_auth_type(req); if ((type == NULL) || (strcasecmp(type, "GSSAPI") != 0)) { @@ -284,6 +288,29 @@ static int mag_auth(request_rec *req) maj, min)); goto done; } +#ifdef HAVE_GSS_KRB5_CCACHE_NAME + /* Set a per-thread ccache in case we are using kerberos, + * it is not elegant but avoids interference between threads */ + long long unsigned int rndname; + apr_status_t rs; + rs = apr_generate_random_bytes((unsigned char *)(&rndname), + sizeof(long long unsigned int)); + if (rs != APR_SUCCESS) { + ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, req, + "Failed to generate random ccache name"); + goto done; + } + user_ccache = apr_psprintf(req->pool, "MEMORY:user_%qu", rndname); + maj = gss_krb5_ccache_name(&min, user_ccache, + (const char **)&orig_ccache); + if (GSS_ERROR(maj)) { + ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, req, + "In Basic Auth, %s", + mag_error(req, "gss_krb5_ccache_name() " + "failed", maj, min)); + goto done; + } +#endif maj = gss_acquire_cred_with_password(&min, client, &ba_pwd, GSS_C_INDEFINITE, GSS_C_NO_OID_SET, @@ -479,6 +506,19 @@ done: } } } +#ifdef HAVE_GSS_KRB5_CCACHE_NAME + if (user_ccache != NULL) { + maj = gss_krb5_ccache_name(&min, orig_ccache, NULL); + if (maj != GSS_S_COMPLETE) { + ap_log_rerror(APLOG_MARK, APLOG_ERR|APLOG_NOERRNO, 0, req, + "Failed to restore per-thread ccache, %s", + mag_error(req, "gss_krb5_ccache_name() " + "failed", maj, min)); + } + } + free(orig_ccache); + orig_ccache = NULL; +#endif gss_delete_sec_context(&min, &user_ctx, &output); gss_release_cred(&min, &user_cred); gss_release_cred(&min, &acquired_cred); diff --git a/src/mod_auth_gssapi.h b/src/mod_auth_gssapi.h index efe230d..4cf7d39 100644 --- a/src/mod_auth_gssapi.h +++ b/src/mod_auth_gssapi.h @@ -5,6 +5,7 @@ #include #include #include +#include #define APR_WANT_STRFUNC #include "apr_want.h" -- 2.1.4