summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimo Sorce <simo@redhat.com>2012-05-31 18:49:23 -0400
committerSimo Sorce <simo@redhat.com>2012-09-14 16:26:37 -0400
commit1f7a30669362b6049bd60e0a9a04ec2ff7b55d44 (patch)
tree8227f7cc828df1c3c932ecf9087811e2f49b29ae
parentd622ae4bd3f6f156f83c4d510082d7c248a204fd (diff)
downloadgss-proxy-1f7a30669362b6049bd60e0a9a04ec2ff7b55d44.tar.gz
gss-proxy-1f7a30669362b6049bd60e0a9a04ec2ff7b55d44.tar.xz
gss-proxy-1f7a30669362b6049bd60e0a9a04ec2ff7b55d44.zip
Implement cred related mechglue wrappers
-rw-r--r--proxy/Makefile.am2
-rw-r--r--proxy/src/mechglue/gpp_acquire_cred.c326
-rw-r--r--proxy/src/mechglue/gpp_creds.c431
-rw-r--r--proxy/src/mechglue/gss_plugin.h74
4 files changed, 833 insertions, 0 deletions
diff --git a/proxy/Makefile.am b/proxy/Makefile.am
index 4274cef..c75f0c6 100644
--- a/proxy/Makefile.am
+++ b/proxy/Makefile.am
@@ -101,6 +101,8 @@ GP_RPCCLI_OBJ = \
src/client/gpm_wrap_size_limit.c \
src/client/gpm_common.c
GP_MECHGLUE_OBJ = \
+ src/mechglue/gpp_acquire_cred.c \
+ src/mechglue/gpp_creds.c \
src/mechglue/gss_plugin.c
dist_noinst_HEADERS = \
diff --git a/proxy/src/mechglue/gpp_acquire_cred.c b/proxy/src/mechglue/gpp_acquire_cred.c
new file mode 100644
index 0000000..3f29014
--- /dev/null
+++ b/proxy/src/mechglue/gpp_acquire_cred.c
@@ -0,0 +1,326 @@
+/*
+ GSS-PROXY
+
+ Copyright (C) 2012 Red Hat, Inc.
+ Copyright (C) 2012 Simo Sorce <simo.sorce@redhat.com>
+
+ Permission is hereby granted, free of charge, to any person obtaining a
+ copy of this software and associated documentation files (the "Software"),
+ to deal in the Software without restriction, including without limitation
+ the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ and/or sell copies of the Software, and to permit persons to whom the
+ Software is furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ DEALINGS IN THE SOFTWARE.
+*/
+
+
+#include "gss_plugin.h"
+
+static OM_uint32 acquire_local(OM_uint32 *minor_status,
+ struct gpp_name_handle *name,
+ OM_uint32 time_req,
+ const gss_OID_set desired_mechs,
+ gss_cred_usage_t cred_usage,
+ struct gpp_cred_handle *out_cred_handle,
+ gss_OID_set *actual_mechs,
+ OM_uint32 *time_rec)
+{
+ gss_OID_set special_mechs = GSS_C_NO_OID_SET;
+ OM_uint32 maj, min;
+
+ special_mechs = gpp_special_available_mechs(desired_mechs);
+ if (special_mechs == GSS_C_NO_OID_SET) {
+ maj = GSS_S_BAD_MECH;
+ min = 0;
+ goto done;
+ }
+
+ if (name && name->remote && !name->local) {
+ maj = gpp_name_to_local(&min, name->remote,
+ name->mech_type, &name->local);
+ if (maj) {
+ goto done;
+ }
+ }
+
+ maj = gss_acquire_cred(&min,
+ name ? name->local : NULL,
+ time_req,
+ special_mechs,
+ cred_usage,
+ &out_cred_handle->local,
+ actual_mechs,
+ time_rec);
+
+done:
+ *minor_status = min;
+ (void)gss_release_oid_set(&min, &special_mechs);
+ return maj;
+}
+
+OM_uint32 gssi_acquire_cred(OM_uint32 *minor_status,
+ const gss_name_t desired_name,
+ OM_uint32 time_req,
+ const gss_OID_set desired_mechs,
+ gss_cred_usage_t cred_usage,
+ gss_cred_id_t *output_cred_handle,
+ gss_OID_set *actual_mechs,
+ OM_uint32 *time_rec)
+{
+ enum gpp_behavior behavior;
+ struct gpp_name_handle *name;
+ struct gpp_cred_handle *out_cred_handle = NULL;
+ OM_uint32 maj, min;
+ OM_uint32 tmaj, tmin;
+
+ if (!output_cred_handle) {
+ *minor_status = gpp_map_error(EINVAL);
+ return GSS_S_FAILURE;
+ }
+
+ tmaj = GSS_S_COMPLETE;
+ tmin = 0;
+
+ out_cred_handle = calloc(1, sizeof(struct gpp_cred_handle));
+ if (!out_cred_handle) {
+ maj = GSS_S_FAILURE;
+ min = ENOMEM;
+ goto done;
+ }
+
+ name = (struct gpp_name_handle *)desired_name;
+ behavior = gpp_get_behavior();
+
+ /* See if we should try local first */
+ if (behavior == GPP_LOCAL_ONLY || behavior == GPP_LOCAL_FIRST) {
+
+ maj = acquire_local(&min, name, time_req, desired_mechs, cred_usage,
+ out_cred_handle, actual_mechs, time_rec);
+
+ if (maj != GSS_S_NO_CRED || behavior != GPP_LOCAL_FIRST) {
+ goto done;
+ }
+
+ /* not successful, save actual local error if remote fallback fails */
+ tmaj = maj;
+ tmin = min;
+ }
+
+ /* Then try with remote */
+ if (behavior == GPP_REMOTE_ONLY || behavior == GPP_REMOTE_FIRST) {
+
+ if (name && name->local && !name->remote) {
+ maj = gpp_local_to_name(&min, name->local, &name->remote);
+ if (maj) {
+ goto done;
+ }
+ }
+
+ maj = gpm_acquire_cred(&min,
+ name ? name->remote : NULL,
+ time_req,
+ desired_mechs,
+ cred_usage,
+ &out_cred_handle->remote,
+ actual_mechs,
+ time_rec);
+ if (maj == GSS_S_COMPLETE || behavior == GPP_REMOTE_ONLY) {
+ goto done;
+ }
+
+ /* So remote failed, but we can fallback to local, try that */
+ maj = acquire_local(&min, name, time_req, desired_mechs, cred_usage,
+ out_cred_handle, actual_mechs, time_rec);
+ }
+
+done:
+ if (maj != GSS_S_COMPLETE &&
+ maj != GSS_S_CONTINUE_NEEDED &&
+ tmaj != GSS_S_COMPLETE) {
+ maj = tmaj;
+ min = tmin;
+ }
+ if (maj == GSS_S_COMPLETE) {
+ *output_cred_handle = (gss_cred_id_t)out_cred_handle;
+ } else {
+ free(out_cred_handle);
+ }
+ *minor_status = gpp_map_error(min);
+ return maj;
+}
+
+OM_uint32 gssi_add_cred(OM_uint32 *minor_status,
+ const gss_cred_id_t input_cred_handle,
+ const gss_name_t desired_name,
+ const gss_OID desired_mech,
+ gss_cred_usage_t cred_usage,
+ OM_uint32 initiator_time_req,
+ OM_uint32 acceptor_time_req,
+ gss_cred_id_t *output_cred_handle,
+ gss_OID_set *actual_mechs,
+ OM_uint32 *initiator_time_rec,
+ OM_uint32 *acceptor_time_rec)
+{
+ gss_OID_set desired_mechs = GSS_C_NO_OID_SET;
+ OM_uint32 time_req, time_rec;
+ OM_uint32 maj, min;
+
+ if (!output_cred_handle) {
+ return GSS_S_CALL_INACCESSIBLE_WRITE;
+ }
+
+ if (desired_mech) {
+ maj = gss_create_empty_oid_set(&min, &desired_mechs);
+ if (maj != GSS_S_COMPLETE) {
+ *minor_status = gpp_map_error(min);
+ return maj;
+ }
+ maj = gss_add_oid_set_member(&min, desired_mech, &desired_mechs);
+ if (maj != GSS_S_COMPLETE) {
+ (void)gss_release_oid_set(&min, &desired_mechs);
+ *minor_status = gpp_map_error(min);
+ return maj;
+ }
+ }
+
+ switch (cred_usage) {
+ case GSS_C_ACCEPT:
+ time_req = acceptor_time_req;
+ break;
+ case GSS_C_INITIATE:
+ time_req = initiator_time_req;
+ break;
+ case GSS_C_BOTH:
+ if (acceptor_time_req > initiator_time_req) {
+ time_req = acceptor_time_req;
+ } else {
+ time_req = initiator_time_req;
+ }
+ break;
+ default:
+ time_req = 0;
+ }
+
+ maj = gssi_acquire_cred(minor_status,
+ desired_name,
+ time_req,
+ desired_mechs,
+ cred_usage,
+ output_cred_handle,
+ actual_mechs,
+ &time_rec);
+ if (maj == GSS_S_COMPLETE) {
+ if (acceptor_time_rec &&
+ (cred_usage == GSS_C_ACCEPT || cred_usage == GSS_C_BOTH)) {
+ *acceptor_time_rec = time_rec;
+ }
+ if (initiator_time_rec &&
+ (cred_usage == GSS_C_INITIATE || cred_usage == GSS_C_BOTH)) {
+ *initiator_time_rec = time_rec;
+ }
+ }
+
+ (void)gss_release_oid_set(&min, &desired_mechs);
+ return maj;
+}
+
+OM_uint32 gssi_acquire_cred_with_password(OM_uint32 *minor_status,
+ const gss_name_t desired_name,
+ const gss_buffer_t password,
+ OM_uint32 time_req,
+ const gss_OID_set desired_mechs,
+ gss_cred_usage_t cred_usage,
+ gss_cred_id_t *output_cred_handle,
+ gss_OID_set *actual_mechs,
+ OM_uint32 *time_rec)
+{
+ enum gpp_behavior behavior;
+ struct gpp_name_handle *name;
+ struct gpp_cred_handle *out_cred_handle;
+ gss_OID_set special_mechs;
+ OM_uint32 maj, min;
+
+ name = (struct gpp_name_handle *)desired_name;
+
+ if (!output_cred_handle) {
+ *minor_status = gpp_map_error(EINVAL);
+ return GSS_S_FAILURE;
+ }
+
+ if (desired_mechs == GSS_C_NO_OID_SET) {
+ return GSS_S_CALL_INACCESSIBLE_READ;
+ }
+
+ behavior = gpp_get_behavior();
+
+ out_cred_handle = calloc(1, sizeof(struct gpp_cred_handle));
+ if (!out_cred_handle) {
+ *minor_status = gpp_map_error(ENOMEM);
+ return GSS_S_FAILURE;
+ }
+
+ switch (behavior) {
+ case GPP_LOCAL_ONLY:
+ case GPP_LOCAL_FIRST:
+ case GPP_REMOTE_FIRST:
+
+ /* re-enter the mechglue, using the special OIDs for skipping
+ * the use of the interposer */
+ special_mechs = gpp_special_available_mechs(desired_mechs);
+ if (special_mechs == GSS_C_NO_OID_SET) {
+ return GSS_S_FAILURE;
+ }
+
+ if (name && name->remote && !name->local) {
+ maj = gpp_name_to_local(&min, name->remote,
+ name->mech_type, &name->local);
+ if (maj) {
+ goto done;
+ }
+ }
+
+ maj = gss_acquire_cred_with_password(&min,
+ name->local,
+ password,
+ time_req,
+ special_mechs,
+ cred_usage,
+ &out_cred_handle->local,
+ actual_mechs,
+ time_rec);
+ break;
+ /* fall through if we got no creds locally and we are in
+ * automatic mode */
+
+ case GPP_REMOTE_ONLY:
+
+ /* FIXME: not currently available */
+ return GSS_S_UNAVAILABLE;
+
+ break;
+
+ default:
+ maj = GSS_S_FAILURE;
+ min = EINVAL;
+ }
+
+done:
+ if (maj == GSS_S_COMPLETE) {
+ *output_cred_handle = (gss_cred_id_t)out_cred_handle;
+ } else {
+ free(out_cred_handle);
+ }
+ *minor_status = gpp_map_error(min);
+ (void)gss_release_oid_set(&min, &special_mechs);
+ return maj;
+}
diff --git a/proxy/src/mechglue/gpp_creds.c b/proxy/src/mechglue/gpp_creds.c
new file mode 100644
index 0000000..f37fd18
--- /dev/null
+++ b/proxy/src/mechglue/gpp_creds.c
@@ -0,0 +1,431 @@
+/*
+ GSS-PROXY
+
+ Copyright (C) 2012 Red Hat, Inc.
+ Copyright (C) 2012 Simo Sorce <simo.sorce@redhat.com>
+
+ Permission is hereby granted, free of charge, to any person obtaining a
+ copy of this software and associated documentation files (the "Software"),
+ to deal in the Software without restriction, including without limitation
+ the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ and/or sell copies of the Software, and to permit persons to whom the
+ Software is furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ DEALINGS IN THE SOFTWARE.
+*/
+
+#include "gss_plugin.h"
+
+static OM_uint32 get_local_def_creds(OM_uint32 *minor_status,
+ struct gpp_name_handle *name,
+ gss_cred_usage_t cred_usage,
+ struct gpp_cred_handle *cred_handle)
+{
+ gss_OID_set interposed_mechs = GSS_C_NO_OID_SET;
+ gss_OID_set special_mechs = GSS_C_NO_OID_SET;
+ OM_uint32 maj, min;
+
+ maj = GSS_S_FAILURE;
+ min = 0;
+
+ interposed_mechs = gss_mech_interposer((gss_OID)&gssproxy_mech_interposer);
+ if (interposed_mechs == GSS_C_NO_OID_SET) {
+ goto done;
+ }
+ special_mechs = gpp_special_available_mechs(interposed_mechs);
+ if (special_mechs == GSS_C_NO_OID_SET) {
+ goto done;
+ }
+
+ maj = gss_acquire_cred(&min, name ? name->local : NULL, 0, special_mechs,
+ cred_usage, &cred_handle->local, NULL, NULL);
+done:
+ *minor_status = min;
+ (void)gss_release_oid_set(&min, &special_mechs);
+ (void)gss_release_oid_set(&min, &interposed_mechs);
+ return maj;
+}
+
+OM_uint32 gppint_get_def_creds(OM_uint32 *minor_status,
+ enum gpp_behavior behavior,
+ struct gpp_name_handle *name,
+ gss_cred_usage_t cred_usage,
+ struct gpp_cred_handle **cred_handle)
+{
+ struct gpp_cred_handle *cred;
+ OM_uint32 tmaj, tmin;
+ OM_uint32 maj, min;
+
+ cred = calloc(1, sizeof(struct gpp_cred_handle));
+ if (!cred) {
+ *minor_status = 0;
+ return GSS_S_FAILURE;
+ }
+
+ tmaj = GSS_S_COMPLETE;
+ tmin = 0;
+
+ /* See if we should try local first */
+ if (behavior == GPP_LOCAL_ONLY || behavior == GPP_LOCAL_FIRST) {
+
+ maj = get_local_def_creds(&min, name, cred_usage, cred);
+ if (maj != GSS_S_NO_CRED || behavior != GPP_LOCAL_FIRST) {
+ goto done;
+ }
+
+ /* not successful, save actual local error if remote fallback fails */
+ tmaj = maj;
+ tmin = min;
+ }
+
+ /* Then try with remote */
+ if (behavior == GPP_REMOTE_ONLY || behavior == GPP_REMOTE_FIRST) {
+
+ maj = gpm_acquire_cred(&min,
+ NULL, 0, NULL, cred_usage,
+ &cred->remote, NULL, NULL);
+
+ if (maj == GSS_S_COMPLETE || behavior == GPP_REMOTE_ONLY) {
+ goto done;
+ }
+
+ /* So remote failed, but we can fallback to local, try that */
+ maj = get_local_def_creds(&min, name, cred_usage, cred);
+ }
+
+done:
+ if (maj != GSS_S_COMPLETE && tmaj != GSS_S_COMPLETE) {
+ maj = tmaj;
+ min = tmin;
+ }
+ *minor_status = min;
+ if (maj != GSS_S_COMPLETE) {
+ gssi_release_cred(&min, (gss_cred_id_t *)&cred);
+ }
+ *cred_handle = cred;
+ return maj;
+}
+
+OM_uint32 gssi_inquire_cred(OM_uint32 *minor_status,
+ gss_cred_id_t cred_handle,
+ gss_name_t *name,
+ OM_uint32 *lifetime,
+ gss_cred_usage_t *cred_usage,
+ gss_OID_set *mechanisms)
+{
+ struct gpp_cred_handle *cred = NULL;
+ struct gpp_name_handle *gpname = NULL;
+ OM_uint32 maj, min;
+
+ if (cred_handle == GSS_C_NO_CREDENTIAL) {
+ maj = gppint_get_def_creds(&min, gpp_get_behavior(), NULL,
+ GSS_C_INITIATE, &cred);
+ if (maj != GSS_S_COMPLETE) {
+ goto done;
+ }
+ } else {
+ cred = (struct gpp_cred_handle *)cred_handle;
+ }
+
+ if (name) {
+ gpname = calloc(1, sizeof(struct gpp_name_handle));
+ if (!gpname) {
+ min = ENOMEM;
+ maj = GSS_S_FAILURE;
+ goto done;
+ }
+ }
+
+ if (cred->local) {
+ maj = gss_inquire_cred(&min, cred->local,
+ gpname ? &gpname->local : NULL,
+ lifetime, cred_usage, mechanisms);
+ } else if (cred->remote) {
+ maj = gpm_inquire_cred(&min, cred->remote,
+ gpname ? &gpname->remote : NULL,
+ lifetime, cred_usage, mechanisms);
+ } else {
+ min = 0;
+ maj = GSS_S_FAILURE;
+ }
+
+done:
+ *minor_status = gpp_map_error(min);
+ if (cred_handle == GSS_C_NO_CREDENTIAL) {
+ gssi_release_cred(&min, (gss_cred_id_t*)&cred);
+ }
+ if (name && maj == GSS_S_COMPLETE) {
+ *name = (gss_name_t)gpname;
+ } else {
+ free(gpname);
+ }
+ return maj;
+}
+
+OM_uint32 gssi_inquire_cred_by_mech(OM_uint32 *minor_status,
+ gss_cred_id_t cred_handle,
+ gss_OID mech_type,
+ gss_name_t *name,
+ OM_uint32 *initiator_lifetime,
+ OM_uint32 *acceptor_lifetime,
+ gss_cred_usage_t *cred_usage)
+{
+ struct gpp_cred_handle *cred = NULL;
+ struct gpp_name_handle *gpname = NULL;
+ OM_uint32 maj, min;
+
+ if (cred_handle == GSS_C_NO_CREDENTIAL) {
+ maj = gppint_get_def_creds(&min, gpp_get_behavior(), NULL,
+ GSS_C_INITIATE, &cred);
+ if (maj != GSS_S_COMPLETE) {
+ goto done;
+ }
+ } else {
+ cred = (struct gpp_cred_handle *)cred_handle;
+ }
+
+ if (name) {
+ gpname = calloc(1, sizeof(struct gpp_name_handle));
+ if (!gpname) {
+ min = ENOMEM;
+ maj = GSS_S_FAILURE;
+ goto done;
+ }
+ }
+
+ if (cred->local) {
+ maj = gss_inquire_cred_by_mech(&min, cred->local,
+ gpp_special_mech(mech_type),
+ gpname ? &gpname->local : NULL,
+ initiator_lifetime, acceptor_lifetime,
+ cred_usage);
+ } else if (cred->remote) {
+ maj = gpm_inquire_cred_by_mech(&min, cred->remote, mech_type,
+ gpname ? &gpname->remote : NULL,
+ initiator_lifetime, acceptor_lifetime,
+ cred_usage);
+ } else {
+ min = 0;
+ maj = GSS_S_FAILURE;
+ }
+
+done:
+ *minor_status = gpp_map_error(min);
+ if (cred_handle == GSS_C_NO_CREDENTIAL) {
+ gssi_release_cred(&min, (gss_cred_id_t*)&cred);
+ }
+ if (name && maj == GSS_S_COMPLETE) {
+ *name = (gss_name_t)gpname;
+ } else {
+ free(gpname);
+ }
+ return maj;
+}
+
+OM_uint32 gssi_inquire_cred_by_oid(OM_uint32 *minor_status,
+ const gss_cred_id_t cred_handle,
+ const gss_OID desired_object,
+ gss_buffer_set_t *data_set)
+{
+ struct gpp_cred_handle *cred = NULL;
+ OM_uint32 maj, min;
+
+ *minor_status = 0;
+ if (cred_handle == GSS_C_NO_CREDENTIAL) {
+ return GSS_S_CALL_INACCESSIBLE_READ;
+ }
+ cred = (struct gpp_cred_handle *)cred_handle;
+
+ /* NOTE: For now we can do this only for local credentials,
+ * but as far as I know there is no real oid defined, at least
+ * for the krb5 mechs, so this may be a mooot point */
+ if (!cred->local) {
+ return GSS_S_UNAVAILABLE;
+ }
+
+ maj = gss_inquire_cred_by_oid(&min, cred->local, desired_object, data_set);
+
+ *minor_status = gpp_map_error(min);
+ return maj;
+}
+
+OM_uint32 gssi_set_cred_option(OM_uint32 *minor_status,
+ gss_cred_id_t cred_handle,
+ const gss_OID desired_object,
+ const gss_buffer_t value)
+{
+ struct gpp_cred_handle *cred = NULL;
+ OM_uint32 maj, min;
+
+ *minor_status = 0;
+ if (cred_handle == GSS_C_NO_CREDENTIAL) {
+ return GSS_S_CALL_INACCESSIBLE_READ;
+ }
+ cred = (struct gpp_cred_handle *)cred_handle;
+
+ /* NOTE: For now we can do this only for local credentials */
+ if (!cred->local) {
+ return GSS_S_UNAVAILABLE;
+ }
+
+ maj = gss_set_cred_option(&min, &cred->local, desired_object, value);
+
+ *minor_status = gpp_map_error(min);
+ return maj;
+}
+
+OM_uint32 gssi_store_cred(OM_uint32 *minor_status,
+ const gss_cred_id_t input_cred_handle,
+ gss_cred_usage_t input_usage,
+ const gss_OID desired_mech,
+ OM_uint32 overwrite_cred,
+ OM_uint32 default_cred,
+ gss_OID_set *elements_stored,
+ gss_cred_usage_t *cred_usage_stored)
+{
+ struct gpp_cred_handle *cred = NULL;
+ OM_uint32 maj, min;
+
+ *minor_status = 0;
+ if (input_cred_handle == GSS_C_NO_CREDENTIAL) {
+ return GSS_S_CALL_INACCESSIBLE_READ;
+ }
+ 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;
+ }
+
+ maj = gss_store_cred(&min, cred->local, input_usage,
+ gpp_special_mech(desired_mech),
+ overwrite_cred, default_cred,
+ elements_stored, cred_usage_stored);
+
+ *minor_status = gpp_map_error(min);
+ return maj;
+}
+
+OM_uint32 gssi_release_cred(OM_uint32 *minor_status,
+ gss_cred_id_t *cred_handle)
+{
+ struct gpp_cred_handle *cred;
+ OM_uint32 maj, min;
+ OM_uint32 rmaj = GSS_S_COMPLETE;
+
+ if (*cred_handle == GSS_C_NO_CREDENTIAL) {
+ *minor_status = 0;
+ return GSS_S_COMPLETE;
+ }
+
+ cred = (struct gpp_cred_handle *)*cred_handle;
+
+ if (cred->local) {
+ maj = gss_release_cred(&min, &cred->local);
+ if (maj != GSS_S_COMPLETE) {
+ rmaj = maj;
+ *minor_status = gpp_map_error(min);
+ }
+ }
+
+ if (cred->remote) {
+ maj = gpm_release_cred(&min, &cred->remote);
+ if (maj && rmaj == GSS_S_COMPLETE) {
+ rmaj = maj;
+ *minor_status = gpp_map_error(min);
+ }
+ }
+
+ *cred_handle = GSS_C_NO_CREDENTIAL;
+ return rmaj;
+}
+
+OM_uint32 gssi_export_cred(OM_uint32 *minor_status,
+ gss_cred_id_t cred_handle,
+ gss_buffer_t token)
+{
+ struct gpp_cred_handle *cred;
+
+ cred = (struct gpp_cred_handle *)cred_handle;
+ if (!cred) {
+ return GSS_S_CALL_INACCESSIBLE_READ;
+ }
+
+ /* We do not support exporting creds via the proxy.
+ * It's exclusively a local operation for now */
+ if (!cred->local) {
+ return GSS_S_CRED_UNAVAIL;
+ }
+
+ return gss_export_cred(minor_status, cred->local, token);
+}
+
+OM_uint32 gssi_import_cred(OM_uint32 *minor_status,
+ gss_buffer_t token,
+ gss_cred_id_t *cred_handle)
+{
+ return GSS_S_UNAVAILABLE;
+}
+
+OM_uint32 gssi_import_cred_by_mech(OM_uint32 *minor_status,
+ gss_OID mech_type,
+ gss_buffer_t token,
+ gss_cred_id_t *cred_handle)
+{
+ struct gpp_cred_handle *cred;
+ gss_buffer_desc wrap_token = {0};
+ gss_OID spmech;
+ OM_uint32 maj, min = 0;
+ uint32_t len;
+
+ cred = calloc(1, sizeof(struct gpp_cred_handle));
+ if (!cred) {
+ *minor_status = 0;
+ return GSS_S_FAILURE;
+ }
+
+ /* NOTE: it makes no sense to import a cred remotely atm,
+ * so we only handle the local case for now. */
+ spmech = gpp_special_mech(mech_type);
+ if (spmech == GSS_C_NO_OID) {
+ maj = GSS_S_FAILURE;
+ goto done;
+ }
+
+ wrap_token.length = sizeof(uint32_t) + spmech->length + token->length;
+ wrap_token.value = malloc(wrap_token.length);
+ if (!wrap_token.value) {
+ wrap_token.length = 0;
+ maj = GSS_S_FAILURE;
+ goto done;
+ }
+
+ len = htobe32(wrap_token.length);
+ memcpy(wrap_token.value, &len, sizeof(uint32_t));
+ memcpy(wrap_token.value + sizeof(uint32_t),
+ spmech->elements, spmech->length);
+ memcpy(wrap_token.value + sizeof(uint32_t) + spmech->length,
+ token->value, token->length);
+
+ maj = gss_import_cred(&min, &wrap_token, &cred->local);
+
+done:
+ *minor_status = gpp_map_error(min);
+ if (maj == GSS_S_COMPLETE) {
+ *cred_handle = (gss_cred_id_t)cred;
+ } else {
+ free(cred);
+ }
+ (void)gss_release_buffer(&min, &wrap_token);
+ return maj;
+}
+
diff --git a/proxy/src/mechglue/gss_plugin.h b/proxy/src/mechglue/gss_plugin.h
index 7fe5b5c..fb548e0 100644
--- a/proxy/src/mechglue/gss_plugin.h
+++ b/proxy/src/mechglue/gss_plugin.h
@@ -68,4 +68,78 @@ uint32_t gpp_name_to_local(uint32_t *minor, gssx_name *name,
uint32_t gpp_local_to_name(uint32_t *minor,
gss_name_t local_name, gssx_name **name);
+OM_uint32 gssi_acquire_cred(OM_uint32 *minor_status,
+ const gss_name_t desired_name,
+ OM_uint32 time_req,
+ const gss_OID_set desired_mechs,
+ gss_cred_usage_t cred_usage,
+ gss_cred_id_t *output_cred_handle,
+ gss_OID_set *actual_mechs,
+ OM_uint32 *time_rec);
+
+OM_uint32 gssi_add_cred(OM_uint32 *minor_status,
+ const gss_cred_id_t input_cred_handle,
+ const gss_name_t desired_name,
+ const gss_OID desired_mech,
+ gss_cred_usage_t cred_usage,
+ OM_uint32 initiator_time_req,
+ OM_uint32 acceptor_time_req,
+ gss_cred_id_t *output_cred_handle,
+ gss_OID_set *actual_mechs,
+ OM_uint32 *initiator_time_rec,
+ OM_uint32 *acceptor_time_rec);
+
+OM_uint32 gssi_acquire_cred_with_password(OM_uint32 *minor_status,
+ const gss_name_t desired_name,
+ const gss_buffer_t password,
+ OM_uint32 time_req,
+ const gss_OID_set desired_mechs,
+ gss_cred_usage_t cred_usage,
+ gss_cred_id_t *output_cred_handle,
+ gss_OID_set *actual_mechs,
+ OM_uint32 *time_rec);
+
+OM_uint32 gppint_get_def_creds(OM_uint32 *minor_status,
+ enum gpp_behavior behavior,
+ struct gpp_name_handle *name,
+ gss_cred_usage_t cred_usage,
+ struct gpp_cred_handle **cred_handle);
+
+OM_uint32 gssi_inquire_cred(OM_uint32 *minor_status,
+ gss_cred_id_t cred_handle,
+ gss_name_t *name,
+ OM_uint32 *lifetime,
+ gss_cred_usage_t *cred_usage,
+ gss_OID_set *mechanisms);
+
+OM_uint32 gssi_inquire_cred_by_mech(OM_uint32 *minor_status,
+ gss_cred_id_t cred_handle,
+ gss_OID mech_type,
+ gss_name_t *name,
+ OM_uint32 *initiator_lifetime,
+ OM_uint32 *acceptor_lifetime,
+ gss_cred_usage_t *cred_usage);
+
+OM_uint32 gssi_inquire_cred_by_oid(OM_uint32 *minor_status,
+ const gss_cred_id_t cred_handle,
+ const gss_OID desired_object,
+ gss_buffer_set_t *data_set);
+
+OM_uint32 gssi_set_cred_option(OM_uint32 *minor_status,
+ gss_cred_id_t cred_handle,
+ const gss_OID desired_object,
+ const gss_buffer_t value);
+
+OM_uint32 gssi_store_cred(OM_uint32 *minor_status,
+ const gss_cred_id_t input_cred_handle,
+ gss_cred_usage_t input_usage,
+ const gss_OID desired_mech,
+ OM_uint32 overwrite_cred,
+ OM_uint32 default_cred,
+ gss_OID_set *elements_stored,
+ gss_cred_usage_t *cred_usage_stored);
+
+OM_uint32 gssi_release_cred(OM_uint32 *minor_status,
+ gss_cred_id_t *cred_handle);
+
#endif /* _GSS_PLUGIN_H_ */