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)
downloadgss-proxy-84fcb276d2253f34e5d50a87e42e34c1fd918a55.tar.gz
gss-proxy-84fcb276d2253f34e5d50a87e42e34c1fd918a55.tar.xz
gss-proxy-84fcb276d2253f34e5d50a87e42e34c1fd918a55.zip
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,