|
|
31d59b |
From 37d1667ad0cc91f46a493281e62775cc8bbe3b5b Mon Sep 17 00:00:00 2001
|
|
|
31d59b |
From: Simo Sorce <simo@redhat.com>
|
|
|
31d59b |
Date: Tue, 14 Mar 2017 10:20:08 -0400
|
|
|
31d59b |
Subject: [PATCH] Change impersonator check code
|
|
|
31d59b |
|
|
|
31d59b |
In MIT 1.15 we now have a native way to check for an impersonator,
|
|
|
31d59b |
implement the use of that function but still keep the fallback for
|
|
|
31d59b |
earlier krb5 versions that do not support this method for now.
|
|
|
31d59b |
|
|
|
31d59b |
Signed-off-by: Simo Sorce <simo@redhat.com>
|
|
|
31d59b |
Reviewed-by: Robbie Harwood <rharwood@redhat.com>
|
|
|
31d59b |
Merges: #172
|
|
|
31d59b |
(cherry picked from commit 73b50c0b2799f0aed53337a6516b8e1a27279ebf)
|
|
|
31d59b |
---
|
|
|
68bf20 |
proxy/configure.ac | 3 +
|
|
|
68bf20 |
proxy/src/gp_creds.c | 147 ++++++++++++++++++++++++++++++++-----------
|
|
|
31d59b |
2 files changed, 112 insertions(+), 38 deletions(-)
|
|
|
31d59b |
|
|
|
31d59b |
diff --git a/proxy/configure.ac b/proxy/configure.ac
|
|
|
31d59b |
index 63c0edf..c52dbb6 100644
|
|
|
31d59b |
--- a/proxy/configure.ac
|
|
|
31d59b |
+++ b/proxy/configure.ac
|
|
|
31d59b |
@@ -131,6 +131,9 @@ AC_CHECK_LIB(gssapi_krb5, gss_export_cred,,
|
|
|
31d59b |
[AC_MSG_ERROR([GSSAPI library does not support gss_export_cred])],
|
|
|
31d59b |
[$GSSAPI_LIBS])
|
|
|
31d59b |
|
|
|
31d59b |
+AC_CHECK_DECLS([GSS_KRB5_GET_CRED_IMPERSONATOR], [], [],
|
|
|
31d59b |
+ [[#include <gssapi/gssapi_krb5.h>]])
|
|
|
31d59b |
+
|
|
|
31d59b |
AC_SUBST([KRB5_CFLAGS])
|
|
|
31d59b |
AC_SUBST([KRB5_LIBS])
|
|
|
31d59b |
AC_SUBST([GSSAPI_CFLAGS])
|
|
|
31d59b |
diff --git a/proxy/src/gp_creds.c b/proxy/src/gp_creds.c
|
|
|
31d59b |
index 171a724..95a1c48 100644
|
|
|
31d59b |
--- a/proxy/src/gp_creds.c
|
|
|
31d59b |
+++ b/proxy/src/gp_creds.c
|
|
|
31d59b |
@@ -773,9 +773,9 @@ void gp_filter_flags(struct gp_call_ctx *gpcall, uint32_t *flags)
|
|
|
31d59b |
*flags &= ~gpcall->service->filter_flags;
|
|
|
31d59b |
}
|
|
|
31d59b |
|
|
|
31d59b |
-uint32_t gp_cred_allowed(uint32_t *min,
|
|
|
31d59b |
- struct gp_call_ctx *gpcall,
|
|
|
31d59b |
- gss_cred_id_t cred)
|
|
|
31d59b |
+
|
|
|
31d59b |
+static uint32_t get_impersonator_fallback(uint32_t *min, gss_cred_id_t cred,
|
|
|
31d59b |
+ char **impersonator)
|
|
|
31d59b |
{
|
|
|
31d59b |
uint32_t ret_maj = 0;
|
|
|
31d59b |
uint32_t ret_min = 0;
|
|
|
31d59b |
@@ -785,22 +785,6 @@ uint32_t gp_cred_allowed(uint32_t *min,
|
|
|
31d59b |
krb5_data config;
|
|
|
31d59b |
int err;
|
|
|
31d59b |
|
|
|
31d59b |
- if (cred == GSS_C_NO_CREDENTIAL) {
|
|
|
31d59b |
- return GSS_S_CRED_UNAVAIL;
|
|
|
31d59b |
- }
|
|
|
31d59b |
-
|
|
|
31d59b |
- if (gpcall->service->trusted ||
|
|
|
31d59b |
- gpcall->service->impersonate ||
|
|
|
31d59b |
- gpcall->service->allow_const_deleg) {
|
|
|
31d59b |
-
|
|
|
31d59b |
- GPDEBUGN(2, "Credentials allowed by configuration\n");
|
|
|
31d59b |
- *min = 0;
|
|
|
31d59b |
- return GSS_S_COMPLETE;
|
|
|
31d59b |
- }
|
|
|
31d59b |
-
|
|
|
31d59b |
- /* FIXME: krb5 specific code, should get an oid registerd to query the
|
|
|
31d59b |
- * cred with gss_inquire_cred_by_oid() or similar instead */
|
|
|
31d59b |
-
|
|
|
31d59b |
err = krb5_init_context(&context);
|
|
|
31d59b |
if (err) {
|
|
|
31d59b |
ret_min = err;
|
|
|
31d59b |
@@ -835,21 +819,116 @@ uint32_t gp_cred_allowed(uint32_t *min,
|
|
|
31d59b |
goto done;
|
|
|
31d59b |
}
|
|
|
31d59b |
|
|
|
31d59b |
+ err = krb5_cc_get_config(context, ccache, NULL, "proxy_impersonator",
|
|
|
31d59b |
+ &config);
|
|
|
31d59b |
+ if (err == 0) {
|
|
|
31d59b |
+ *impersonator = strndup(config.data, config.length);
|
|
|
31d59b |
+ if (!*impersonator) {
|
|
|
31d59b |
+ ret_min = ENOMEM;
|
|
|
31d59b |
+ ret_maj = GSS_S_FAILURE;
|
|
|
31d59b |
+ } else {
|
|
|
31d59b |
+ ret_min = 0;
|
|
|
31d59b |
+ ret_maj = GSS_S_COMPLETE;
|
|
|
31d59b |
+ }
|
|
|
31d59b |
+ krb5_free_data_contents(context, &config);
|
|
|
31d59b |
+ } else {
|
|
|
31d59b |
+ ret_min = err;
|
|
|
31d59b |
+ ret_maj = GSS_S_FAILURE;
|
|
|
31d59b |
+ }
|
|
|
31d59b |
+
|
|
|
31d59b |
+done:
|
|
|
31d59b |
+ if (context) {
|
|
|
31d59b |
+ if (ccache) {
|
|
|
31d59b |
+ krb5_cc_destroy(context, ccache);
|
|
|
31d59b |
+ }
|
|
|
31d59b |
+ krb5_free_context(context);
|
|
|
31d59b |
+ }
|
|
|
31d59b |
+ free(memcache);
|
|
|
31d59b |
+
|
|
|
31d59b |
+ *min = ret_min;
|
|
|
31d59b |
+ return ret_maj;
|
|
|
31d59b |
+}
|
|
|
31d59b |
+
|
|
|
31d59b |
+#if !HAVE_DECL_GSS_KRB5_GET_CRED_IMPERSONATOR
|
|
|
31d59b |
+gss_OID_desc impersonator_oid = {
|
|
|
31d59b |
+ 11, discard_const("\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x0e")
|
|
|
31d59b |
+};
|
|
|
31d59b |
+const gss_OID GSS_KRB5_GET_CRED_IMPERSONATOR = &impersonator_oid;
|
|
|
31d59b |
+#endif
|
|
|
31d59b |
+
|
|
|
31d59b |
+static uint32_t get_impersonator_name(uint32_t *min, gss_cred_id_t cred,
|
|
|
31d59b |
+ char **impersonator)
|
|
|
31d59b |
+{
|
|
|
31d59b |
+ gss_buffer_set_t bufset = GSS_C_NO_BUFFER_SET;
|
|
|
31d59b |
+ uint32_t ret_maj = 0;
|
|
|
31d59b |
+ uint32_t ret_min = 0;
|
|
|
31d59b |
+ uint32_t discard;
|
|
|
31d59b |
+
|
|
|
31d59b |
+ *impersonator = NULL;
|
|
|
31d59b |
+
|
|
|
31d59b |
+ ret_maj = gss_inquire_cred_by_oid(&ret_min, cred,
|
|
|
31d59b |
+ GSS_KRB5_GET_CRED_IMPERSONATOR,
|
|
|
31d59b |
+ &bufset);
|
|
|
31d59b |
+ if (ret_maj == GSS_S_COMPLETE) {
|
|
|
31d59b |
+ if (bufset->count == 0) {
|
|
|
31d59b |
+ ret_min = ENOENT;
|
|
|
31d59b |
+ ret_maj = GSS_S_COMPLETE;
|
|
|
31d59b |
+ goto done;
|
|
|
31d59b |
+ }
|
|
|
31d59b |
+ *impersonator = strndup(bufset->elements[0].value,
|
|
|
31d59b |
+ bufset->elements[0].length);
|
|
|
31d59b |
+ if (!*impersonator) {
|
|
|
31d59b |
+ ret_min = ENOMEM;
|
|
|
31d59b |
+ ret_maj = GSS_S_FAILURE;
|
|
|
31d59b |
+ }
|
|
|
31d59b |
+ } else if (ret_maj == GSS_S_UNAVAILABLE) {
|
|
|
31d59b |
+ /* Not supported by krb5 library yet, fallback to raw krb5 calls */
|
|
|
31d59b |
+ /* TODO: Remove once we set a required dependency on MIT 1.15+ */
|
|
|
31d59b |
+ ret_maj = get_impersonator_fallback(&ret_min, cred, impersonator);
|
|
|
31d59b |
+ if (ret_maj == GSS_S_FAILURE) {
|
|
|
31d59b |
+ if (ret_min == KRB5_CC_NOTFOUND) {
|
|
|
31d59b |
+ ret_min = ENOENT;
|
|
|
31d59b |
+ ret_maj = GSS_S_COMPLETE;
|
|
|
31d59b |
+ }
|
|
|
31d59b |
+ }
|
|
|
31d59b |
+ }
|
|
|
31d59b |
+
|
|
|
31d59b |
+done:
|
|
|
31d59b |
+ (void)gss_release_buffer_set(&discard, &bufset);
|
|
|
31d59b |
+ *min = ret_min;
|
|
|
31d59b |
+ return ret_maj;
|
|
|
31d59b |
+}
|
|
|
31d59b |
+
|
|
|
31d59b |
+uint32_t gp_cred_allowed(uint32_t *min,
|
|
|
31d59b |
+ struct gp_call_ctx *gpcall,
|
|
|
31d59b |
+ gss_cred_id_t cred)
|
|
|
31d59b |
+{
|
|
|
31d59b |
+ char *impersonator = NULL;
|
|
|
31d59b |
+ uint32_t ret_maj = 0;
|
|
|
31d59b |
+ uint32_t ret_min = 0;
|
|
|
31d59b |
+
|
|
|
31d59b |
+ if (cred == GSS_C_NO_CREDENTIAL) {
|
|
|
31d59b |
+ return GSS_S_CRED_UNAVAIL;
|
|
|
31d59b |
+ }
|
|
|
31d59b |
+
|
|
|
31d59b |
+ if (gpcall->service->trusted ||
|
|
|
31d59b |
+ gpcall->service->impersonate ||
|
|
|
31d59b |
+ gpcall->service->allow_const_deleg) {
|
|
|
31d59b |
+
|
|
|
31d59b |
+ GPDEBUGN(2, "Credentials allowed by configuration\n");
|
|
|
31d59b |
+ *min = 0;
|
|
|
31d59b |
+ return GSS_S_COMPLETE;
|
|
|
31d59b |
+ }
|
|
|
31d59b |
+
|
|
|
31d59b |
+ ret_maj = get_impersonator_name(&ret_min, cred, &impersonator);
|
|
|
31d59b |
+ if (ret_maj) goto done;
|
|
|
31d59b |
+
|
|
|
31d59b |
/* if we find an impersonator entry we bail as that is not authorized,
|
|
|
31d59b |
* if it were then gpcall->service->allow_const_deleg would have caused
|
|
|
31d59b |
* the ealier check to return GSS_S_COMPLETE already */
|
|
|
31d59b |
- err = krb5_cc_get_config(context, ccache, NULL, "proxy_impersonator",
|
|
|
31d59b |
- &config);
|
|
|
31d59b |
- if (!err) {
|
|
|
31d59b |
- krb5_free_data_contents(context, &config);
|
|
|
31d59b |
+ if (impersonator != NULL) {
|
|
|
31d59b |
ret_min = 0;
|
|
|
31d59b |
ret_maj = GSS_S_UNAUTHORIZED;
|
|
|
31d59b |
- } else if (err != KRB5_CC_NOTFOUND) {
|
|
|
31d59b |
- ret_min = err;
|
|
|
31d59b |
- ret_maj = GSS_S_FAILURE;
|
|
|
31d59b |
- } else {
|
|
|
31d59b |
- ret_min = 0;
|
|
|
31d59b |
- ret_maj = GSS_S_COMPLETE;
|
|
|
31d59b |
}
|
|
|
31d59b |
|
|
|
31d59b |
done:
|
|
|
31d59b |
@@ -864,15 +943,7 @@ done:
|
|
|
31d59b |
GPDEBUG("Failure while checking credentials\n");
|
|
|
31d59b |
break;
|
|
|
31d59b |
}
|
|
|
31d59b |
- if (context) {
|
|
|
31d59b |
- /* NOTE: destroy only if we created a MEMORY ccache */
|
|
|
31d59b |
- if (ccache) {
|
|
|
31d59b |
- if (memcache) krb5_cc_destroy(context, ccache);
|
|
|
31d59b |
- else krb5_cc_close(context, ccache);
|
|
|
31d59b |
- }
|
|
|
31d59b |
- krb5_free_context(context);
|
|
|
31d59b |
- }
|
|
|
31d59b |
- free(memcache);
|
|
|
31d59b |
+ free(impersonator);
|
|
|
31d59b |
*min = ret_min;
|
|
|
31d59b |
return ret_maj;
|
|
|
31d59b |
}
|