summaryrefslogtreecommitdiffstats
path: root/proxy/src/mechglue
diff options
context:
space:
mode:
authorSimo Sorce <simo@redhat.com>2015-11-09 17:10:56 -0500
committerRobbie Harwood <rharwood@redhat.com>2015-12-01 17:45:56 -0500
commit84fcb276d2253f34e5d50a87e42e34c1fd918a55 (patch)
treeb30a1b41811ff66c4471da2a0dd4bd1697e9f22b /proxy/src/mechglue
parent7e71db8edc9694ed75110ddd9efa373250cc0545 (diff)
Add helpers to store and retrieve encrypted creds
This will allow to (ab)use the krb5 ccache to store encrypted credentials in the user's ccache for later reuse. Signed-off-by: Simo Sorce <simo@redhat.com> Reviewed-by: Robbie Harwoood <rharwood@redhat.com>
Diffstat (limited to 'proxy/src/mechglue')
-rw-r--r--proxy/src/mechglue/gpp_creds.c139
-rw-r--r--proxy/src/mechglue/gpp_init_sec_context.c15
-rw-r--r--proxy/src/mechglue/gss_plugin.h1
3 files changed, 149 insertions, 6 deletions
diff --git a/proxy/src/mechglue/gpp_creds.c b/proxy/src/mechglue/gpp_creds.c
index dcfc896..ff1dfda 100644
--- a/proxy/src/mechglue/gpp_creds.c
+++ b/proxy/src/mechglue/gpp_creds.c
@@ -1,8 +1,125 @@
-/* Copyright (C) 2012 the GSS-PROXY contributors, see COPYING for license */
+/* Copyright (C) 2015 the GSS-PROXY contributors, see COPYING for license */
#include "gss_plugin.h"
#include <gssapi/gssapi_krb5.h>
+#define GPKRB_SRV_NAME "Encrypted/Credentials/v1@X-GSSPROXY:"
+#define GPKRB_MAX_CRED_SIZE 1024 * 512
+
+uint32_t gpp_store_remote_creds(uint32_t *min, gssx_cred *creds)
+{
+ krb5_context ctx = NULL;
+ krb5_ccache ccache = NULL;
+ krb5_creds cred;
+ krb5_error_code ret;
+ XDR xdrctx;
+ bool xdrok;
+
+ *min = 0;
+
+ if (creds == NULL) return GSS_S_CALL_INACCESSIBLE_READ;
+
+ memset(&cred, 0, sizeof(cred));
+
+ ret = krb5_init_context(&ctx);
+ if (ret) return ret;
+
+ ret = krb5_cc_default(ctx, &ccache);
+ if (ret) goto done;
+
+ ret = krb5_parse_name(ctx,
+ creds->desired_name.display_name.octet_string_val,
+ &cred.client);
+ if (ret) goto done;
+
+ ret = krb5_parse_name(ctx, GPKRB_SRV_NAME, &cred.server);
+ if (ret) goto done;
+
+ cred.ticket.data = malloc(GPKRB_MAX_CRED_SIZE);
+ xdrmem_create(&xdrctx, cred.ticket.data, GPKRB_MAX_CRED_SIZE, XDR_ENCODE);
+ xdrok = xdr_gssx_cred(&xdrctx, creds);
+ if (!xdrok) {
+ ret = ENOSPC;
+ goto done;
+ }
+ cred.ticket.length = xdr_getpos(&xdrctx);
+
+ ret = krb5_cc_store_cred(ctx, ccache, &cred);
+
+ if (ret == KRB5_FCC_NOFILE) {
+ /* If a ccache does not exit, try to create one */
+ ret = krb5_cc_initialize(ctx, ccache, cred.client);
+ if (ret) goto done;
+
+ /* and try again to store the cred */
+ ret = krb5_cc_store_cred(ctx, ccache, &cred);
+ }
+
+done:
+ if (ctx) {
+ krb5_free_cred_contents(ctx, &cred);
+ if (ccache) krb5_cc_close(ctx, ccache);
+ krb5_free_context(ctx);
+ }
+ *min = ret;
+ return ret ? GSS_S_FAILURE : GSS_S_COMPLETE;
+}
+
+static uint32_t retrieve_remote_creds(uint32_t *min, gssx_name *name,
+ gssx_cred *creds)
+{
+ krb5_context ctx = NULL;
+ krb5_ccache ccache = NULL;
+ krb5_creds cred;
+ krb5_creds icred;
+ krb5_error_code ret;
+ XDR xdrctx;
+ bool xdrok;
+
+ memset(&cred, 0, sizeof(krb5_creds));
+ memset(&icred, 0, sizeof(krb5_creds));
+
+ ret = krb5_init_context(&ctx);
+ if (ret) goto done;
+
+ ret = krb5_cc_default(ctx, &ccache);
+ if (ret) goto done;
+
+ if (name) {
+ ret = krb5_parse_name(ctx,
+ name->display_name.octet_string_val,
+ &icred.client);
+ } else {
+ ret = krb5_cc_get_principal(ctx, ccache, &icred.client);
+ }
+ if (ret) goto done;
+
+ ret = krb5_parse_name(ctx, GPKRB_SRV_NAME, &icred.server);
+ if (ret) goto done;
+
+ ret = krb5_cc_retrieve_cred(ctx, ccache, 0, &icred, &cred);
+ if (ret) goto done;
+
+ xdrmem_create(&xdrctx, cred.ticket.data, cred.ticket.length, XDR_DECODE);
+ xdrok = xdr_gssx_cred(&xdrctx, creds);
+
+ if (xdrok) {
+ ret = 0;
+ } else {
+ ret = EIO;
+ }
+
+done:
+ if (ctx) {
+ krb5_free_cred_contents(ctx, &cred);
+ krb5_free_cred_contents(ctx, &icred);
+ if (ccache) krb5_cc_close(ctx, ccache);
+ krb5_free_context(ctx);
+ }
+ *min = ret;
+ return ret ? GSS_S_FAILURE : GSS_S_COMPLETE;
+}
+
static OM_uint32 get_local_def_creds(OM_uint32 *minor_status,
struct gpp_name_handle *name,
gss_cred_usage_t cred_usage,
@@ -66,11 +183,21 @@ OM_uint32 gppint_get_def_creds(OM_uint32 *minor_status,
/* Then try with remote */
if (behavior == GPP_REMOTE_ONLY || behavior == GPP_REMOTE_FIRST) {
+ gssx_cred remote = {0};
+ gssx_cred *premote = NULL;
- maj = gpm_acquire_cred(&min, NULL,
+ /* We intentionally ignore failures as finding creds is optional */
+ maj = retrieve_remote_creds(&min, name ? name->remote : NULL, &remote);
+ if (maj == GSS_S_COMPLETE) {
+ premote = &remote;
+ }
+
+ maj = gpm_acquire_cred(&min, premote,
NULL, 0, NULL, cred_usage, false,
&cred->remote, NULL, NULL);
+ xdr_free((xdrproc_t)xdr_gssx_cred, (char *)&remote);
+
if (maj == GSS_S_COMPLETE || behavior == GPP_REMOTE_ONLY) {
goto done;
}
@@ -379,16 +506,16 @@ OM_uint32 gssi_store_cred(OM_uint32 *minor_status,
}
cred = (struct gpp_cred_handle *)input_cred_handle;
- /* NOTE: For now we can do this only for local credentials */
- if (!cred->local) {
- return GSS_S_UNAVAILABLE;
+ if (cred->remote) {
+ maj = gpp_store_remote_creds(&min, cred->remote);
+ goto done;
}
maj = gss_store_cred(&min, cred->local, input_usage,
gpp_special_mech(desired_mech),
overwrite_cred, default_cred,
elements_stored, cred_usage_stored);
-
+done:
*minor_status = gpp_map_error(min);
return maj;
}
diff --git a/proxy/src/mechglue/gpp_init_sec_context.c b/proxy/src/mechglue/gpp_init_sec_context.c
index 6cfe0e1..2327b58 100644
--- a/proxy/src/mechglue/gpp_init_sec_context.c
+++ b/proxy/src/mechglue/gpp_init_sec_context.c
@@ -151,6 +151,21 @@ OM_uint32 gssi_init_sec_context(OM_uint32 *minor_status,
}
}
+ if (!cred_handle->remote) {
+ struct gpp_cred_handle *r_creds;
+
+ maj = gppint_get_def_creds(&min,
+ GPP_REMOTE_ONLY,
+ GSS_C_NO_NAME,
+ GSS_C_INITIATE,
+ &r_creds);
+ if (maj == GSS_S_COMPLETE) {
+ /* steal result */
+ cred_handle->remote = r_creds->remote;
+ free(r_creds);
+ }
+ }
+
maj = gpm_init_sec_context(&min,
cred_handle->remote,
&ctx_handle->remote,
diff --git a/proxy/src/mechglue/gss_plugin.h b/proxy/src/mechglue/gss_plugin.h
index 6df4c6a..d7ab0b4 100644
--- a/proxy/src/mechglue/gss_plugin.h
+++ b/proxy/src/mechglue/gss_plugin.h
@@ -69,6 +69,7 @@ uint32_t gpp_name_to_local(uint32_t *minor, gssx_name *name,
gss_OID mech_type, gss_name_t *mech_name);
uint32_t gpp_local_to_name(uint32_t *minor,
gss_name_t local_name, gssx_name **name);
+
OM_uint32 gssi_internal_release_oid(OM_uint32 *minor_status, gss_OID *oid);
OM_uint32 gssi_acquire_cred(OM_uint32 *minor_status,