You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
236 lines
9.3 KiB
236 lines
9.3 KiB
From 0e04be2c1398dac40c50910a59157eed0ad5a7e4 Mon Sep 17 00:00:00 2001 |
|
From: Simo Sorce <simo@redhat.com> |
|
Date: Tue, 14 Mar 2017 10:43:17 -0400 |
|
Subject: [PATCH] Allow connection to self when impersonator set |
|
|
|
If the target of a context establishment is the impersonator itself, |
|
then allow it. This kind of context establishment is used by tools like |
|
mod_auth_gssapi to be able to inspect the ticket just obtained via |
|
impersonation and it is basically a noop as the acceptor and the |
|
impersonator are the same entitiy. |
|
|
|
Signed-off-by: Simo Sorce <simo@redhat.com> |
|
Reviewed-by: Robbie Harwood <rharwood@redhat.com> |
|
Merges: #172 |
|
(cherry picked from commit eada55e831d12b42d3be3a555ff4e133bed7f594) |
|
--- |
|
proxy/src/gp_creds.c | 57 ++++++++++++++++++++++++++++++++----- |
|
proxy/src/gp_rpc_creds.h | 3 +- |
|
proxy/src/gp_rpc_init_sec_context.c | 2 +- |
|
proxy/tests/t_impersonate.py | 35 ++++++++++++++++------- |
|
4 files changed, 78 insertions(+), 19 deletions(-) |
|
|
|
diff --git a/proxy/src/gp_creds.c b/proxy/src/gp_creds.c |
|
index 95a1c48..7d89b06 100644 |
|
--- a/proxy/src/gp_creds.c |
|
+++ b/proxy/src/gp_creds.c |
|
@@ -883,7 +883,8 @@ static uint32_t get_impersonator_name(uint32_t *min, gss_cred_id_t cred, |
|
} |
|
} else if (ret_maj == GSS_S_UNAVAILABLE) { |
|
/* Not supported by krb5 library yet, fallback to raw krb5 calls */ |
|
- /* TODO: Remove once we set a required dependency on MIT 1.15+ */ |
|
+ /* TODO: Remove once we set a minimum required dependency on a |
|
+ * release that supports this call */ |
|
ret_maj = get_impersonator_fallback(&ret_min, cred, impersonator); |
|
if (ret_maj == GSS_S_FAILURE) { |
|
if (ret_min == KRB5_CC_NOTFOUND) { |
|
@@ -899,9 +900,47 @@ done: |
|
return ret_maj; |
|
} |
|
|
|
+static uint32_t check_impersonator_name(uint32_t *min, |
|
+ gss_name_t target_name, |
|
+ const char *impersonator) |
|
+{ |
|
+ gss_name_t canon_name = NULL; |
|
+ gss_buffer_desc buf; |
|
+ uint32_t ret_maj = 0; |
|
+ uint32_t ret_min = 0; |
|
+ uint32_t discard; |
|
+ bool match; |
|
+ |
|
+ ret_maj = gss_canonicalize_name(&discard, target_name, &gp_mech_krb5, |
|
+ &canon_name); |
|
+ if (ret_maj != GSS_S_COMPLETE) { |
|
+ *min = ret_min; |
|
+ return ret_maj; |
|
+ } |
|
+ |
|
+ ret_maj = gss_display_name(&discard, canon_name, &buf, NULL); |
|
+ gss_release_name(&discard, &canon_name); |
|
+ if (ret_maj != GSS_S_COMPLETE) { |
|
+ *min = ret_min; |
|
+ return ret_maj; |
|
+ } |
|
+ |
|
+ match = (strncmp(impersonator, buf.value, buf.length) == 0) && |
|
+ (strlen(impersonator) == buf.length); |
|
+ gss_release_buffer(&discard, &buf); |
|
+ |
|
+ *min = 0; |
|
+ if (match) { |
|
+ return GSS_S_COMPLETE; |
|
+ } else { |
|
+ return GSS_S_UNAUTHORIZED; |
|
+ } |
|
+} |
|
+ |
|
uint32_t gp_cred_allowed(uint32_t *min, |
|
struct gp_call_ctx *gpcall, |
|
- gss_cred_id_t cred) |
|
+ gss_cred_id_t cred, |
|
+ gss_name_t target_name) |
|
{ |
|
char *impersonator = NULL; |
|
uint32_t ret_maj = 0; |
|
@@ -924,11 +963,11 @@ uint32_t gp_cred_allowed(uint32_t *min, |
|
if (ret_maj) goto done; |
|
|
|
/* if we find an impersonator entry we bail as that is not authorized, |
|
- * if it were then gpcall->service->allow_const_deleg would have caused |
|
- * the ealier check to return GSS_S_COMPLETE already */ |
|
+ * *unless* the target is the impersonator itself! If the operation |
|
+ * were authorized then gpcall->service->allow_const_deleg would have |
|
+ * caused the ealier check to return GSS_S_COMPLETE already */ |
|
if (impersonator != NULL) { |
|
- ret_min = 0; |
|
- ret_maj = GSS_S_UNAUTHORIZED; |
|
+ ret_maj = check_impersonator_name(&ret_min, target_name, impersonator); |
|
} |
|
|
|
done: |
|
@@ -937,7 +976,11 @@ done: |
|
GPDEBUGN(2, "Unauthorized impersonator credentials detected\n"); |
|
break; |
|
case GSS_S_COMPLETE: |
|
- GPDEBUGN(2, "No impersonator credentials detected\n"); |
|
+ if (impersonator) { |
|
+ GPDEBUGN(2, "Credentials allowed for 'self'\n"); |
|
+ } else { |
|
+ GPDEBUGN(2, "No impersonator credentials detected\n"); |
|
+ } |
|
break; |
|
default: |
|
GPDEBUG("Failure while checking credentials\n"); |
|
diff --git a/proxy/src/gp_rpc_creds.h b/proxy/src/gp_rpc_creds.h |
|
index 54fe482..c116e53 100644 |
|
--- a/proxy/src/gp_rpc_creds.h |
|
+++ b/proxy/src/gp_rpc_creds.h |
|
@@ -34,7 +34,8 @@ uint32_t gp_add_krb5_creds(uint32_t *min, |
|
|
|
uint32_t gp_cred_allowed(uint32_t *min, |
|
struct gp_call_ctx *gpcall, |
|
- gss_cred_id_t cred); |
|
+ gss_cred_id_t cred, |
|
+ gss_name_t target_name); |
|
|
|
void gp_filter_flags(struct gp_call_ctx *gpcall, uint32_t *flags); |
|
|
|
diff --git a/proxy/src/gp_rpc_init_sec_context.c b/proxy/src/gp_rpc_init_sec_context.c |
|
index 767a3ff..413e2ec 100644 |
|
--- a/proxy/src/gp_rpc_init_sec_context.c |
|
+++ b/proxy/src/gp_rpc_init_sec_context.c |
|
@@ -108,7 +108,7 @@ int gp_init_sec_context(struct gp_call_ctx *gpcall, |
|
} |
|
} |
|
|
|
- ret_maj = gp_cred_allowed(&ret_min, gpcall, ich); |
|
+ ret_maj = gp_cred_allowed(&ret_min, gpcall, ich, target_name); |
|
if (ret_maj) { |
|
goto done; |
|
} |
|
diff --git a/proxy/tests/t_impersonate.py b/proxy/tests/t_impersonate.py |
|
index 3e25962..29f9a41 100755 |
|
--- a/proxy/tests/t_impersonate.py |
|
+++ b/proxy/tests/t_impersonate.py |
|
@@ -34,19 +34,20 @@ IMPERSONATE_CONF_TEMPLATE = ''' |
|
|
|
''' |
|
|
|
-def run_cmd(testdir, env, conf, name, socket, cmd, expected_failure): |
|
+def run_cmd(testdir, env, conf, name, socket, cmd, keytab, expected_failure): |
|
|
|
logfile = conf['logfile'] |
|
testenv = env.copy() |
|
testenv.update({'KRB5CCNAME': os.path.join(testdir, 't' + conf['prefix'] + |
|
'_impersonate.ccache'), |
|
- 'KRB5_KTNAME': os.path.join(testdir, PROXY_KTNAME), |
|
+ 'KRB5_KTNAME': os.path.join(testdir, keytab), |
|
'KRB5_TRACE': os.path.join(testdir, 't' + conf['prefix'] + |
|
'_impersonate.trace'), |
|
'GSS_USE_PROXY': 'yes', |
|
'GSSPROXY_SOCKET': socket, |
|
'GSSPROXY_BEHAVIOR': 'REMOTE_FIRST'}) |
|
|
|
+ print("\nTesting: [%s]" % (name,), file=logfile) |
|
print("[COMMAND]\n%s\n[ENVIRONMENT]\n%s\n" % (cmd, testenv), file=logfile) |
|
logfile.flush() |
|
|
|
@@ -74,45 +75,59 @@ def run(testdir, env, conf): |
|
rets = [] |
|
|
|
# Test all permitted |
|
+ msg = "Impersonate" |
|
socket = os.path.join(testdir, 'impersonate.socket') |
|
cmd = ["./tests/t_impersonate", USR_NAME, HOST_GSS, PROXY_GSS, |
|
path_prefix + 'impersonate.cache'] |
|
- r = run_cmd(testdir, env, conf, "Impersonate", socket, cmd, False) |
|
+ r = run_cmd(testdir, env, conf, msg, socket, cmd, PROXY_KTNAME, False) |
|
rets.append(r) |
|
|
|
- #Test fail |
|
+ #Test self fail |
|
+ msg = "Impersonate fail self" |
|
socket = os.path.join(testdir, 'impersonate-proxyonly.socket') |
|
cmd = ["./tests/t_impersonate", USR_NAME, HOST_GSS, PROXY_GSS, |
|
path_prefix + 'impersonate.cache'] |
|
- r = run_cmd(testdir, env, conf, "Impersonate fail self", socket, cmd, True) |
|
+ r = run_cmd(testdir, env, conf, msg, socket, cmd, PROXY_KTNAME, True) |
|
rets.append(r) |
|
|
|
- #Test fail |
|
+ #Test proxy fail |
|
+ msg = "Impersonate fail proxy" |
|
socket = os.path.join(testdir, 'impersonate-selfonly.socket') |
|
cmd = ["./tests/t_impersonate", USR_NAME, HOST_GSS, PROXY_GSS, |
|
path_prefix + 'impersonate.cache'] |
|
- r = run_cmd(testdir, env, conf, "Impersonate fail proxy", socket, cmd, True) |
|
+ r = run_cmd(testdir, env, conf, msg, socket, cmd, PROXY_KTNAME, True) |
|
rets.append(r) |
|
|
|
#Test s4u2self half succeed |
|
+ msg = "s4u2self delegation" |
|
socket = os.path.join(testdir, 'impersonate-selfonly.socket') |
|
cmd = ["./tests/t_impersonate", USR_NAME, HOST_GSS, PROXY_GSS, |
|
path_prefix + 'impersonate.cache', 's4u2self'] |
|
- r = run_cmd(testdir, env, conf, "s4u2self delegation", socket, cmd, False) |
|
+ r = run_cmd(testdir, env, conf, msg, socket, cmd, PROXY_KTNAME, False) |
|
+ rets.append(r) |
|
+ |
|
+ #Test proxy to self succeed |
|
+ msg = "Impersonate to self" |
|
+ socket = os.path.join(testdir, 'impersonate-selfonly.socket') |
|
+ cmd = ["./tests/t_impersonate", USR_NAME, HOST_GSS, HOST_GSS, |
|
+ path_prefix + 'impersonate.cache', 's4u2proxy'] |
|
+ r = run_cmd(testdir, env, conf, msg, socket, cmd, SVC_KTNAME, False) |
|
rets.append(r) |
|
|
|
#Test s4u2proxy half fail |
|
+ msg = "s4u2proxy fail" |
|
socket = os.path.join(testdir, 'impersonate-selfonly.socket') |
|
cmd = ["./tests/t_impersonate", USR_NAME, HOST_GSS, PROXY_GSS, |
|
path_prefix + 'impersonate.cache', 's4u2proxy'] |
|
- r = run_cmd(testdir, env, conf, "s4u2proxy fail", socket, cmd, True) |
|
+ r = run_cmd(testdir, env, conf, msg, socket, cmd, PROXY_KTNAME, True) |
|
rets.append(r) |
|
|
|
#Test s4u2proxy half succeed |
|
+ msg = "s4u2proxy" |
|
socket = os.path.join(testdir, 'impersonate-proxyonly.socket') |
|
cmd = ["./tests/t_impersonate", USR_NAME, HOST_GSS, PROXY_GSS, |
|
path_prefix + 'impersonate.cache', 's4u2proxy'] |
|
- r = run_cmd(testdir, env, conf, "s4u2proxy", socket, cmd, False) |
|
+ r = run_cmd(testdir, env, conf, msg, socket, cmd, PROXY_KTNAME, False) |
|
rets.append(r) |
|
|
|
# Reset back gssproxy conf
|
|
|