From 02cf28e20b852caffdb77e008f6bb6c4c0ead532 Mon Sep 17 00:00:00 2001 From: Luke Howard Date: Sun, 27 Mar 2011 17:29:24 +1100 Subject: [PATCH] implement gss_acquire_cred_ex with password support add missing SPIs to gss_mech_switch s/acquire_cred_ex/acquire_cred_ext/g --- lib/gssapi/Makefile.am | 2 + lib/gssapi/gssapi/gssapi.h | 32 ++++ lib/gssapi/gssapi/gssapi_oid.h | 7 + lib/gssapi/gssapi_mech.h | 18 +-- lib/gssapi/krb5/acquire_cred.c | 138 ++++++++++------ lib/gssapi/krb5/external.c | 2 +- lib/gssapi/mech/gss_acquire_cred_ext.c | 151 ++++++++++++++++++ .../mech/gss_acquire_cred_with_password.c | 118 ++++++++++++++ lib/gssapi/mech/gss_add_cred.c | 2 +- lib/gssapi/mech/gss_mech_switch.c | 10 ++ lib/gssapi/mech/gss_oid.c | 6 + lib/gssapi/oid.txt | 4 + lib/gssapi/test_context.c | 25 ++- lib/gssapi/version-script.map | 4 + 14 files changed, 460 insertions(+), 59 deletions(-) create mode 100644 lib/gssapi/mech/gss_acquire_cred_ext.c create mode 100644 lib/gssapi/mech/gss_acquire_cred_with_password.c diff --git a/lib/gssapi/Makefile.am b/lib/gssapi/Makefile.am index 2929f8c3c..5f04e4a58 100644 --- a/lib/gssapi/Makefile.am +++ b/lib/gssapi/Makefile.am @@ -80,6 +80,8 @@ mechsrc = \ mech/doxygen.c \ mech/gss_accept_sec_context.c \ mech/gss_acquire_cred.c \ + mech/gss_acquire_cred_ext.c \ + mech/gss_acquire_cred_with_password.c \ mech/gss_add_cred.c \ mech/gss_add_oid_set_member.c \ mech/gss_aeap.c \ diff --git a/lib/gssapi/gssapi/gssapi.h b/lib/gssapi/gssapi/gssapi.h index 94365d9f0..1fdcc3fb6 100644 --- a/lib/gssapi/gssapi/gssapi.h +++ b/lib/gssapi/gssapi/gssapi.h @@ -459,6 +459,9 @@ extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_c_nt_export_name_oid_desc; * Finally, function prototypes for the GSS-API routines. */ +#define GSS_C_OPTION_MASK 0xffff +#define GSS_C_CRED_NO_UI 0x10000 + GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gss_acquire_cred (OM_uint32 * /*minor_status*/, const gss_name_t /*desired_name*/, @@ -470,6 +473,35 @@ GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gss_acquire_cred OM_uint32 * /*time_rec*/ ); +extern gss_OID_desc GSSAPI_LIB_VARIABLE __gss_c_cred_password_oid_desc; +#define GSS_C_CRED_PASSWORD (&__gss_c_cred_password_oid_desc) + +extern gss_OID_desc GSSAPI_LIB_VARIABLE __gss_c_cred_certificate_oid_desc; +#define GSS_C_CRED_CERTIFICATE (&__gss_c_cred_certificate_oid_desc) + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gss_acquire_cred_ext + (OM_uint32 * /*minor_status*/, + const gss_name_t /*desired_name*/, + const gss_OID /*credential_type*/, + const void * /*credential_data*/, + OM_uint32 /*time_req*/, + const gss_OID /*desired_mech*/, + gss_cred_usage_t /*cred_usage*/, + gss_cred_id_t * /*output_cred_handle*/ + ); + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gss_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*/ + ); + GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL gss_release_cred (OM_uint32 * /*minor_status*/, gss_cred_id_t * /*cred_handle*/ diff --git a/lib/gssapi/gssapi/gssapi_oid.h b/lib/gssapi/gssapi/gssapi_oid.h index e7b56dc7d..9465efc77 100644 --- a/lib/gssapi/gssapi/gssapi_oid.h +++ b/lib/gssapi/gssapi/gssapi_oid.h @@ -109,6 +109,13 @@ extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_c_ma_mech_name_oid_desc; extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_c_ma_mech_description_oid_desc; #define GSS_C_MA_MECH_DESCRIPTION (&__gss_c_ma_mech_description_oid_desc) + /* credential types */ +extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_c_cred_password_oid_desc; +#define GSS_C_CRED_PASSWORD (&__gss_c_cred_password_oid_desc) + +extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_c_cred_certificate_oid_desc; +#define GSS_C_CRED_CERTIFICATE (&__gss_c_cred_certificate_oid_desc) + /* Heimdal mechanisms - 1.2.752.43.14 */ extern GSSAPI_LIB_VARIABLE gss_OID_desc __gss_sasl_digest_md5_mechanism_oid_desc; #define GSS_SASL_DIGEST_MD5_MECHANISM (&__gss_sasl_digest_md5_mechanism_oid_desc) diff --git a/lib/gssapi/gssapi_mech.h b/lib/gssapi/gssapi_mech.h index 1431dbcee..28e2836ee 100644 --- a/lib/gssapi/gssapi_mech.h +++ b/lib/gssapi/gssapi_mech.h @@ -355,14 +355,14 @@ _gss_import_cred_t(OM_uint32 * minor_status, typedef OM_uint32 GSSAPI_CALLCONV -_gss_acquire_cred_ex_t(void * /* status */, - const gss_name_t /* desired_name */, - OM_uint32 /* flags */, - OM_uint32 /* time_req */, - gss_cred_usage_t /* cred_usage */, - void * /* identity */, - void * /* ctx */, - void (* /*complete */)(void *, OM_uint32, void *, gss_cred_id_t, OM_uint32)); +_gss_acquire_cred_ext_t(OM_uint32 * /*minor_status */, + const gss_name_t /* desired_name */, + const gss_OID /* credential_type */, + const void * /* credential_data */, + OM_uint32 /* time_req */, + const gss_OID /* desired_mech */, + gss_cred_usage_t /* cred_usage */, + gss_cred_id_t * /* output_cred_handle */); typedef void GSSAPI_CALLCONV _gss_iter_creds_t(OM_uint32 /* flags */, @@ -512,7 +512,7 @@ typedef struct gssapi_mech_interface_desc { _gss_store_cred_t *gm_store_cred; _gss_export_cred_t *gm_export_cred; _gss_import_cred_t *gm_import_cred; - _gss_acquire_cred_ex_t *gm_acquire_cred_ex; + _gss_acquire_cred_ext_t *gm_acquire_cred_ext; _gss_iter_creds_t *gm_iter_creds; _gss_destroy_cred_t *gm_destroy_cred; _gss_cred_hold_t *gm_cred_hold; diff --git a/lib/gssapi/krb5/acquire_cred.c b/lib/gssapi/krb5/acquire_cred.c index 3116f0d95..8c8817eb1 100644 --- a/lib/gssapi/krb5/acquire_cred.c +++ b/lib/gssapi/krb5/acquire_cred.c @@ -104,13 +104,13 @@ get_keytab(krb5_context context, krb5_keytab *keytab) static OM_uint32 acquire_initiator_cred (OM_uint32 * minor_status, krb5_context context, + const gss_OID credential_type, + void *credential_data, const gss_name_t desired_name, OM_uint32 time_req, - const gss_OID_set desired_mechs, + const gss_OID desired_mech, gss_cred_usage_t cred_usage, - gsskrb5_cred handle, - gss_OID_set * actual_mechs, - OM_uint32 * time_rec + gsskrb5_cred handle ) { OM_uint32 ret; @@ -133,6 +133,12 @@ static OM_uint32 acquire_initiator_cred * errors while searching. */ + if (credential_type != GSS_C_NO_OID && + !gss_oid_equal(credential_type, GSS_C_CRED_PASSWORD)) { + kret = KRB5_NOCREDS_SUPPLIED; /* XXX */ + goto end; + } + if (handle->principal) { kret = krb5_cc_cache_match (context, handle->principal, @@ -175,14 +181,29 @@ static OM_uint32 acquire_initiator_cred if (kret) goto end; } - kret = get_keytab(context, &keytab); - if (kret) - goto end; kret = krb5_get_init_creds_opt_alloc(context, &opt); if (kret) goto end; - kret = krb5_get_init_creds_keytab(context, &cred, - handle->principal, keytab, 0, NULL, opt); + if (credential_type != GSS_C_NO_OID && + gss_oid_equal(credential_type, GSS_C_CRED_PASSWORD)) { + gss_buffer_t password = (gss_buffer_t)credential_data; + + /* XXX are we requiring password to be NUL terminated? */ + + kret = krb5_get_init_creds_password(context, &cred, + handle->principal, + password->value, + NULL, NULL, 0, NULL, opt); + } else { + kret = get_keytab(context, &keytab); + if (kret) { + krb5_get_init_creds_opt_free(context, opt); + goto end; + } + kret = krb5_get_init_creds_keytab(context, &cred, + handle->principal, keytab, + 0, NULL, opt); + } krb5_get_init_creds_opt_free(context, opt); if (kret) goto end; @@ -234,19 +255,25 @@ end: static OM_uint32 acquire_acceptor_cred (OM_uint32 * minor_status, krb5_context context, + const gss_OID credential_type, + void *credential_data, const gss_name_t desired_name, OM_uint32 time_req, - const gss_OID_set desired_mechs, + const gss_OID desired_mech, gss_cred_usage_t cred_usage, - gsskrb5_cred handle, - gss_OID_set * actual_mechs, - OM_uint32 * time_rec + gsskrb5_cred handle ) { OM_uint32 ret; krb5_error_code kret; ret = GSS_S_FAILURE; + + if (credential_type != GSS_C_NO_OID) { + kret = EINVAL; + goto end; + } + kret = get_keytab(context, &handle->keytab); if (kret) goto end; @@ -300,23 +327,8 @@ OM_uint32 GSSAPI_CALLCONV _gsskrb5_acquire_cred OM_uint32 * time_rec ) { - krb5_context context; - gsskrb5_cred handle; OM_uint32 ret; - if (cred_usage != GSS_C_ACCEPT && cred_usage != GSS_C_INITIATE && cred_usage != GSS_C_BOTH) { - *minor_status = GSS_KRB5_S_G_BAD_USAGE; - return GSS_S_FAILURE; - } - - GSSAPI_KRB5_INIT(&context); - - *output_cred_handle = NULL; - if (time_rec) - *time_rec = 0; - if (actual_mechs) - *actual_mechs = GSS_C_NO_OID_SET; - if (desired_mechs) { int present = 0; @@ -330,6 +342,54 @@ OM_uint32 GSSAPI_CALLCONV _gsskrb5_acquire_cred } } + ret = _gsskrb5_acquire_cred_ext(minor_status, + desired_name, + GSS_C_NO_OID, + NULL, + time_req, + GSS_KRB5_MECHANISM, + cred_usage, + output_cred_handle); + if (ret) + return ret; + + + ret = _gsskrb5_inquire_cred(minor_status, *output_cred_handle, + NULL, time_rec, NULL, actual_mechs); + if (ret) { + OM_uint32 tmp; + _gsskrb5_release_cred(&tmp, output_cred_handle); + } + + return ret; +} + +OM_uint32 GSSAPI_CALLCONV _gsskrb5_acquire_cred_ext +(OM_uint32 * minor_status, + const gss_name_t desired_name, + const gss_OID credential_type, + void *credential_data, + OM_uint32 time_req, + const gss_OID desired_mech, + gss_cred_usage_t cred_usage, + gss_cred_id_t * output_cred_handle + ) +{ + krb5_context context; + gsskrb5_cred handle; + OM_uint32 ret; + + cred_usage &= GSS_C_OPTION_MASK; + + if (cred_usage != GSS_C_ACCEPT && cred_usage != GSS_C_INITIATE && cred_usage != GSS_C_BOTH) { + *minor_status = GSS_KRB5_S_G_BAD_USAGE; + return GSS_S_FAILURE; + } + + GSSAPI_KRB5_INIT(&context); + + *output_cred_handle = NULL; + handle = calloc(1, sizeof(*handle)); if (handle == NULL) { *minor_status = ENOMEM; @@ -339,7 +399,6 @@ OM_uint32 GSSAPI_CALLCONV _gsskrb5_acquire_cred HEIMDAL_MUTEX_init(&handle->cred_id_mutex); if (desired_name != GSS_C_NO_NAME) { - ret = _gsskrb5_canon_name(minor_status, context, 1, NULL, desired_name, &handle->principal); if (ret) { @@ -350,9 +409,9 @@ OM_uint32 GSSAPI_CALLCONV _gsskrb5_acquire_cred } if (cred_usage == GSS_C_INITIATE || cred_usage == GSS_C_BOTH) { ret = acquire_initiator_cred(minor_status, context, + credential_type, credential_data, desired_name, time_req, - desired_mechs, cred_usage, handle, - actual_mechs, time_rec); + desired_mech, cred_usage, handle); if (ret != GSS_S_COMPLETE) { HEIMDAL_MUTEX_destroy(&handle->cred_id_mutex); krb5_free_principal(context, handle->principal); @@ -362,8 +421,9 @@ OM_uint32 GSSAPI_CALLCONV _gsskrb5_acquire_cred } if (cred_usage == GSS_C_ACCEPT || cred_usage == GSS_C_BOTH) { ret = acquire_acceptor_cred(minor_status, context, + credential_type, credential_data, desired_name, time_req, - desired_mechs, cred_usage, handle, actual_mechs, time_rec); + desired_mech, cred_usage, handle); if (ret != GSS_S_COMPLETE) { HEIMDAL_MUTEX_destroy(&handle->cred_id_mutex); krb5_free_principal(context, handle->principal); @@ -375,9 +435,6 @@ OM_uint32 GSSAPI_CALLCONV _gsskrb5_acquire_cred if (ret == GSS_S_COMPLETE) ret = gss_add_oid_set_member(minor_status, GSS_KRB5_MECHANISM, &handle->mechanisms); - if (ret == GSS_S_COMPLETE) - ret = _gsskrb5_inquire_cred(minor_status, (gss_cred_id_t)handle, - NULL, time_rec, NULL, actual_mechs); if (ret != GSS_S_COMPLETE) { if (handle->mechanisms != NULL) gss_release_oid_set(NULL, &handle->mechanisms); @@ -386,17 +443,8 @@ OM_uint32 GSSAPI_CALLCONV _gsskrb5_acquire_cred free(handle); return (ret); } - *minor_status = 0; - if (time_rec) { - ret = _gsskrb5_lifetime_left(minor_status, - context, - handle->lifetime, - time_rec); - - if (ret) - return ret; - } handle->usage = cred_usage; + *minor_status = 0; *output_cred_handle = (gss_cred_id_t)handle; return (GSS_S_COMPLETE); } diff --git a/lib/gssapi/krb5/external.c b/lib/gssapi/krb5/external.c index d6f14a48f..ff0060593 100644 --- a/lib/gssapi/krb5/external.c +++ b/lib/gssapi/krb5/external.c @@ -315,7 +315,7 @@ static gssapi_mech_interface_desc krb5_mech = { _gsskrb5_store_cred, _gsskrb5_export_cred, _gsskrb5_import_cred, - NULL, + _gsskrb5_acquire_cred_ext, NULL, NULL, NULL, diff --git a/lib/gssapi/mech/gss_acquire_cred_ext.c b/lib/gssapi/mech/gss_acquire_cred_ext.c new file mode 100644 index 000000000..1fbc8b1b5 --- /dev/null +++ b/lib/gssapi/mech/gss_acquire_cred_ext.c @@ -0,0 +1,151 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * All rights reserved. + * + * Portions Copyright (c) 2011 PADL Software Pty Ltd. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: src/lib/libgssapi/gss_acquire_cred.c,v 1.1 2005/12/29 14:40:20 dfr Exp $ + */ + +#include "mech_locl.h" + +GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL +gss_acquire_cred_ext(OM_uint32 *minor_status, + const gss_name_t desired_name, + const gss_OID credential_type, + const void *credential_data, + OM_uint32 time_req, + const gss_OID desired_mech, + gss_cred_usage_t cred_usage, + gss_cred_id_t *output_cred_handle) +{ + OM_uint32 major_status; + struct _gss_name *name = (struct _gss_name *) desired_name; + gssapi_mech_interface m; + struct _gss_cred *cred; + struct _gss_mechanism_cred *mc; + gss_OID_set_desc set, *mechs; + size_t i; + + *minor_status = 0; + if (output_cred_handle == NULL) + return GSS_S_CALL_INACCESSIBLE_READ; + + _gss_load_mech(); + + if (desired_mech != GSS_C_NO_OID) { + int match = 0; + + gss_test_oid_set_member(minor_status, desired_mech, + _gss_mech_oids, &match); + if (!match) + return GSS_S_BAD_MECH; + + set.count = 1; + set.elements = desired_mech; + mechs = &set; + } else + mechs = _gss_mech_oids; + + cred = calloc(1, sizeof(*cred)); + if (cred == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + + HEIM_SLIST_INIT(&cred->gc_mc); + + for (i = 0; i < mechs->count; i++) { + struct _gss_mechanism_name *mn = NULL; + gss_name_t desired_mech_name = GSS_C_NO_NAME; + + m = __gss_get_mechanism(&mechs->elements[i]); + if (!m) + continue; + + if (desired_name != GSS_C_NO_NAME) { + major_status = _gss_find_mn(minor_status, name, + &mechs->elements[i], &mn); + if (major_status != GSS_S_COMPLETE) + continue; + + desired_mech_name = mn->gmn_name; + } + + mc = calloc(1, sizeof(struct _gss_mechanism_cred)); + if (mc == NULL) + continue; + + mc->gmc_mech = m; + mc->gmc_mech_oid = &m->gm_mech_oid; + + if (m->gm_acquire_cred_ext) { + major_status = m->gm_acquire_cred_ext(minor_status, + desired_mech_name, + credential_type, + credential_data, + time_req, + mc->gmc_mech_oid, + cred_usage, + &mc->gmc_cred); + } else if (credential_type != GSS_C_NO_OID) { + gss_OID_set_desc set2; + + set2.count = 1; + set2.elements = mc->gmc_mech_oid; + + major_status = m->gm_acquire_cred(minor_status, + desired_name, + time_req, + &set2, + cred_usage, + &mc->gmc_cred, + NULL, + NULL); + } else { + major_status = GSS_S_UNAVAILABLE; + } + + if (GSS_ERROR(major_status)) { + free(mc); + continue; + } + + HEIM_SLIST_INSERT_HEAD(&cred->gc_mc, mc, gmc_link); + } + + /* + * If we didn't manage to create a single credential, return + * an error. + */ + if (!HEIM_SLIST_FIRST(&cred->gc_mc)) { + free(cred); + *minor_status = 0; + return GSS_S_NO_CRED; + } + + *output_cred_handle = (gss_cred_id_t) cred; + *minor_status = 0; + return GSS_S_COMPLETE; +} diff --git a/lib/gssapi/mech/gss_acquire_cred_with_password.c b/lib/gssapi/mech/gss_acquire_cred_with_password.c new file mode 100644 index 000000000..94415ce04 --- /dev/null +++ b/lib/gssapi/mech/gss_acquire_cred_with_password.c @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2011, PADL Software Pty Ltd. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of PADL Software nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "mech_locl.h" + +OM_uint32 +gss_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 major_status, tmp_minor; + + if (desired_mechs == GSS_C_NO_OID_SET) { + major_status = gss_acquire_cred_ext(minor_status, + desired_name, + GSS_C_CRED_PASSWORD, + password, + time_req, + GSS_C_NO_OID, + cred_usage, + output_cred_handle); + if (GSS_ERROR(major_status)) + return major_status; + } else { + size_t i; + struct _gss_cred *new_cred; + + new_cred = calloc(1, sizeof(*new_cred)); + if (new_cred == NULL) { + *minor_status = ENOMEM; + return GSS_S_FAILURE; + } + HEIM_SLIST_INIT(&new_cred->gc_mc); + + for (i = 0; i < desired_mechs->count; i++) { + struct _gss_cred *tmp_cred = NULL; + struct _gss_mechanism_cred *mc; + + major_status = gss_acquire_cred_ext(minor_status, + desired_name, + GSS_C_CRED_PASSWORD, + password, + time_req, + &desired_mechs->elements[i], + cred_usage, + (gss_cred_id_t *)&tmp_cred); + if (GSS_ERROR(major_status)) + continue; + + mc = HEIM_SLIST_FIRST(&tmp_cred->gc_mc); + if (mc) { + HEIM_SLIST_REMOVE_HEAD(&tmp_cred->gc_mc, gmc_link); + HEIM_SLIST_INSERT_HEAD(&new_cred->gc_mc, mc, gmc_link); + } + + gss_release_cred(&tmp_minor, &tmp_cred); + } + + if (!HEIM_SLIST_FIRST(&new_cred->gc_mc)) { + free(new_cred); + *minor_status = 0; + return GSS_S_NO_CRED; + } + + *output_cred_handle = (gss_cred_id_t)new_cred; + } + + if (actual_mechs != NULL || time_rec != NULL) { + major_status = gss_inquire_cred(minor_status, + *output_cred_handle, + NULL, + time_rec, + NULL, + actual_mechs); + if (GSS_ERROR(major_status)) { + gss_release_cred(&tmp_minor, output_cred_handle); + return major_status; + } + } + + *minor_status = 0; + return GSS_S_COMPLETE; +} diff --git a/lib/gssapi/mech/gss_add_cred.c b/lib/gssapi/mech/gss_add_cred.c index 19deea5b0..a998bc60f 100644 --- a/lib/gssapi/mech/gss_add_cred.c +++ b/lib/gssapi/mech/gss_add_cred.c @@ -28,7 +28,7 @@ #include "mech_locl.h" -static struct _gss_mechanism_cred * +struct _gss_mechanism_cred * _gss_copy_cred(struct _gss_mechanism_cred *mc) { struct _gss_mechanism_cred *new_mc; diff --git a/lib/gssapi/mech/gss_mech_switch.c b/lib/gssapi/mech/gss_mech_switch.c index f7f75c13f..ef7ea5169 100644 --- a/lib/gssapi/mech/gss_mech_switch.c +++ b/lib/gssapi/mech/gss_mech_switch.c @@ -343,6 +343,16 @@ _gss_load_mech(void) OPTSYM(wrap_iov); OPTSYM(unwrap_iov); OPTSYM(wrap_iov_length); + OPTSYM(store_cred); + OPTSYM(export_cred); + OPTSYM(import_cred); + OPTSYM(acquire_cred_ext); + OPTSYM(iter_creds); + OPTSYM(destroy_cred); + OPTSYM(cred_hold); + OPTSYM(cred_unhold); + OPTSYM(cred_label_get); + OPTSYM(cred_label_set); OPTSYM(display_name_ext); OPTSYM(inquire_name); OPTSYM(get_name_attribute); diff --git a/lib/gssapi/mech/gss_oid.c b/lib/gssapi/mech/gss_oid.c index bac97cacd..0998f9a67 100644 --- a/lib/gssapi/mech/gss_oid.c +++ b/lib/gssapi/mech/gss_oid.c @@ -103,6 +103,12 @@ gss_OID_desc GSSAPI_LIB_VARIABLE __gss_c_ma_mech_name_oid_desc = { 6, "\x2a\x85\ /* GSS_C_MA_MECH_DESCRIPTION - 1.2.752.43.13.102 */ gss_OID_desc GSSAPI_LIB_VARIABLE __gss_c_ma_mech_description_oid_desc = { 6, "\x2a\x85\x70\x2b\x0d\x66" }; +/* GSS_C_CRED_PASSWORD - 1.2.752.43.13.200 */ +gss_OID_desc GSSAPI_LIB_VARIABLE __gss_c_cred_password_oid_desc = { 7, "\x2a\x85\x70\x2b\x0d\x81\x48" }; + +/* GSS_C_CRED_CERTIFICATE - 1.2.752.43.13.201 */ +gss_OID_desc GSSAPI_LIB_VARIABLE __gss_c_cred_certificate_oid_desc = { 7, "\x2a\x85\x70\x2b\x0d\x81\x49" }; + /* GSS_SASL_DIGEST_MD5_MECHANISM - 1.2.752.43.14.1 */ gss_OID_desc GSSAPI_LIB_VARIABLE __gss_sasl_digest_md5_mechanism_oid_desc = { 6, "\x2a\x85\x70\x2b\x0e\x01" }; diff --git a/lib/gssapi/oid.txt b/lib/gssapi/oid.txt index 68e067b77..9dd0addda 100644 --- a/lib/gssapi/oid.txt +++ b/lib/gssapi/oid.txt @@ -41,6 +41,10 @@ oid base GSS_C_MA_SASL_MECH_NAME 1.2.752.43.13.100 oid base GSS_C_MA_MECH_NAME 1.2.752.43.13.101 oid base GSS_C_MA_MECH_DESCRIPTION 1.2.752.43.13.102 +# /* credential types */ +oid base GSS_C_CRED_PASSWORD 1.2.752.43.13.200 +oid base GSS_C_CRED_CERTIFICATE 1.2.752.43.13.201 + #/* Heimdal mechanisms - 1.2.752.43.14 */ oid base GSS_SASL_DIGEST_MD5_MECHANISM 1.2.752.43.14.1 diff --git a/lib/gssapi/test_context.c b/lib/gssapi/test_context.c index 70c68185a..0758ab8b0 100644 --- a/lib/gssapi/test_context.c +++ b/lib/gssapi/test_context.c @@ -44,6 +44,7 @@ static char *type_string; static char *mech_string; static char *ret_mech_string; static char *client_name; +static char *client_password; static int dns_canon_flag = -1; static int mutual_auth_flag = 0; static int dce_style_flag = 0; @@ -467,6 +468,7 @@ static struct getargs args[] = { "use dns to canonicalize", NULL }, {"mutual-auth",0, arg_flag, &mutual_auth_flag,"mutual auth", NULL }, {"client-name", 0, arg_string, &client_name, "client name", NULL }, + {"client-password", 0, arg_string, &client_password, "client password", NULL }, {"limit-enctype",0, arg_string, &limit_enctype_string, "enctype", NULL }, {"dce-style",0, arg_flag, &dce_style_flag, "dce-style", NULL }, {"wrapunwrap",0, arg_flag, &wrapunwrap_flag, "wrap/unwrap", NULL }, @@ -505,6 +507,8 @@ main(int argc, char **argv) void *ctx; gss_OID nameoid, mechoid, actual_mech, actual_mech2; gss_cred_id_t client_cred = GSS_C_NO_CREDENTIAL, deleg_cred = GSS_C_NO_CREDENTIAL; + gss_OID credential_type; + gss_buffer_desc credential_data; setprogname(argv[0]); @@ -552,6 +556,13 @@ main(int argc, char **argv) if (gsskrb5_acceptor_identity) gsskrb5_register_acceptor_identity(gsskrb5_acceptor_identity); + if (client_password) { + credential_type = GSS_C_CRED_PASSWORD; + credential_data.value = client_password; + credential_data.length = strlen(client_password); + } else + credential_type = GSS_C_NO_OID; + if (client_name) { gss_buffer_desc cn; gss_name_t cname; @@ -562,12 +573,20 @@ main(int argc, char **argv) errx(1, "gss_import_name: %s", gssapi_err(maj_stat, min_stat, GSS_C_NO_OID)); - maj_stat = gss_acquire_cred(&min_stat, cname, 0, NULL, - GSS_C_INITIATE, &client_cred, NULL, NULL); + maj_stat = gss_acquire_cred_ext(&min_stat, cname, + credential_type, &credential_data, + 0, GSS_C_NO_OID, GSS_C_INITIATE, &client_cred); if (GSS_ERROR(maj_stat)) - errx(1, "gss_import_name: %s", + errx(1, "gss_acquire_cred_ex: %s", gssapi_err(maj_stat, min_stat, GSS_C_NO_OID)); gss_release_name(&min_stat, &cname); + } else if (credential_type) { + maj_stat = gss_acquire_cred_ex(&min_stat, GSS_C_NO_NAME, + credential_type, &credential_data, + 0, GSS_C_NO_OID, GSS_C_INITIATE, &client_cred); + if (GSS_ERROR(maj_stat)) + errx(1, "gss_acquire_cred_ex: %s", + gssapi_err(maj_stat, min_stat, GSS_C_NO_OID)); } if (limit_enctype_string) { diff --git a/lib/gssapi/version-script.map b/lib/gssapi/version-script.map index 759112133..82365131b 100644 --- a/lib/gssapi/version-script.map +++ b/lib/gssapi/version-script.map @@ -11,8 +11,12 @@ HEIMDAL_GSS_2.0 { __gss_c_nt_user_name_oid_desc; __gss_krb5_nt_principal_name_oid_desc; __gss_c_attr_stream_sizes_oid_desc; + __gss_c_cred_password_oid_desc; + __gss_c_cred_certificate_oid_desc; gss_accept_sec_context; gss_acquire_cred; + gss_acquire_cred_ext; + gss_acquire_cred_with_password; gss_add_buffer_set_member; gss_add_cred; gss_add_oid_set_member;