diff --git a/lib/gssapi/Makefile.am b/lib/gssapi/Makefile.am index c74906103..a380672c6 100644 --- a/lib/gssapi/Makefile.am +++ b/lib/gssapi/Makefile.am @@ -80,7 +80,9 @@ mechsrc = \ mech/doxygen.c \ mech/gss_accept_sec_context.c \ mech/gss_acquire_cred.c \ + mech/gss_acquire_cred_with_password.c \ mech/gss_add_cred.c \ + mech/gss_add_cred_with_password.c \ mech/gss_add_oid_set_member.c \ mech/gss_aeap.c \ mech/gss_buffer_set.c \ diff --git a/lib/gssapi/gssapi/gssapi.h b/lib/gssapi/gssapi/gssapi.h index 12833ebe1..5739e91e8 100644 --- a/lib/gssapi/gssapi/gssapi.h +++ b/lib/gssapi/gssapi/gssapi.h @@ -986,6 +986,36 @@ gss_display_mech_attr(OM_uint32 * minor_status, gss_buffer_t short_desc, gss_buffer_t long_desc); +/* + * Solaris compat + */ + +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_add_cred_with_password ( + OM_uint32 * /*minor_status*/, + const gss_cred_id_t /*input_cred_handle*/, + const gss_name_t /*desired_name*/, + const gss_OID /*desired_mech*/, + const gss_buffer_t /*password*/, + 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*/ + ); /* * diff --git a/lib/gssapi/gssapi_mech.h b/lib/gssapi/gssapi_mech.h index b06e60a82..9fe195cd2 100644 --- a/lib/gssapi/gssapi_mech.h +++ b/lib/gssapi/gssapi_mech.h @@ -406,8 +406,35 @@ struct gss_mo_desc_struct { int (*set)(gss_const_OID, gss_mo_desc *, int, gss_buffer_t); }; +typedef OM_uint32 GSSAPI_CALLCONV _gss_acquire_cred_with_password_t + (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 */ + ); -#define GMI_VERSION 4 + +typedef OM_uint32 GSSAPI_CALLCONV _gss_add_cred_with_password_t ( + OM_uint32 *, /* minor_status */ + const gss_cred_id_t, /* input_cred_handle */ + const gss_name_t, /* desired_name */ + const gss_OID, /* desired_mech */ + const gss_buffer_t, /* password */ + 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 */ + ); + +#define GMI_VERSION 5 /* gm_flags */ #define GM_USE_MG_CRED 1 /* uses mech glue credentials */ @@ -467,6 +494,8 @@ typedef struct gssapi_mech_interface_desc { _gss_cred_label_set_t *gm_cred_label_set; gss_mo_desc *gm_mo; size_t gm_mo_num; + _gss_acquire_cred_with_password_t *gm_acquire_cred_with_password; + _gss_add_cred_with_password_t *gm_add_cred_with_password; } gssapi_mech_interface_desc, *gssapi_mech_interface; gssapi_mech_interface diff --git a/lib/gssapi/mech/cred.h b/lib/gssapi/mech/cred.h index adffe6893..5d6430f69 100644 --- a/lib/gssapi/mech/cred.h +++ b/lib/gssapi/mech/cred.h @@ -39,3 +39,6 @@ struct _gss_cred { struct _gss_mechanism_cred_list gc_mc; }; +struct _gss_mechanism_cred * +_gss_copy_cred(struct _gss_mechanism_cred *mc); + 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..d551abc39 --- /dev/null +++ b/lib/gssapi/mech/gss_acquire_cred_with_password.c @@ -0,0 +1,169 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * 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. + * + * 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_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; + gss_OID_set mechs = desired_mechs; + gss_OID_set_desc set; + struct _gss_name *name = (struct _gss_name *) desired_name; + gssapi_mech_interface m; + struct _gss_cred *cred; + struct _gss_mechanism_cred *mc; + OM_uint32 min_time, cred_time; + int i; + + *minor_status = 0; + if (output_cred_handle == NULL) + return GSS_S_CALL_INACCESSIBLE_READ; + if (actual_mechs) + *actual_mechs = GSS_C_NO_OID_SET; + if (time_rec) + *time_rec = 0; + + _gss_load_mech(); + + /* + * First make sure that at least one of the requested + * mechanisms is one that we support. + */ + if (mechs) { + for (i = 0; i < mechs->count; i++) { + int t; + gss_test_oid_set_member(minor_status, + &mechs->elements[i], _gss_mech_oids, &t); + if (t) + break; + } + if (i == mechs->count) { + *minor_status = 0; + return (GSS_S_BAD_MECH); + } + } + + if (actual_mechs) { + major_status = gss_create_empty_oid_set(minor_status, + actual_mechs); + if (major_status) + return (major_status); + } + + cred = malloc(sizeof(struct _gss_cred)); + if (!cred) { + if (actual_mechs) + gss_release_oid_set(minor_status, actual_mechs); + *minor_status = ENOMEM; + return (GSS_S_FAILURE); + } + HEIM_SLIST_INIT(&cred->gc_mc); + + if (mechs == GSS_C_NO_OID_SET) + mechs = _gss_mech_oids; + + set.count = 1; + min_time = GSS_C_INDEFINITE; + for (i = 0; i < mechs->count; i++) { + struct _gss_mechanism_name *mn = NULL; + + m = __gss_get_mechanism(&mechs->elements[i]); + if (!m || !m->gm_acquire_cred_with_password) + 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; + } + + mc = malloc(sizeof(struct _gss_mechanism_cred)); + if (!mc) { + continue; + } + mc->gmc_mech = m; + mc->gmc_mech_oid = &m->gm_mech_oid; + + /* + * XXX Probably need to do something with actual_mechs. + */ + set.elements = &mechs->elements[i]; + major_status = m->gm_acquire_cred_with_password(minor_status, + (desired_name != GSS_C_NO_NAME + ? mn->gmn_name : GSS_C_NO_NAME), + password, time_req, &set, cred_usage, + &mc->gmc_cred, NULL, &cred_time); + if (major_status) { + free(mc); + continue; + } + if (cred_time < min_time) + min_time = cred_time; + + if (actual_mechs) { + major_status = gss_add_oid_set_member(minor_status, + mc->gmc_mech_oid, actual_mechs); + if (major_status) { + m->gm_release_cred(minor_status, + &mc->gmc_cred); + 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); + if (actual_mechs) + gss_release_oid_set(minor_status, actual_mechs); + *minor_status = 0; + return (GSS_S_NO_CRED); + } + + if (time_rec) + *time_rec = min_time; + *output_cred_handle = (gss_cred_id_t) cred; + *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_add_cred_with_password.c b/lib/gssapi/mech/gss_add_cred_with_password.c new file mode 100644 index 000000000..a0dc9f002 --- /dev/null +++ b/lib/gssapi/mech/gss_add_cred_with_password.c @@ -0,0 +1,151 @@ +/*- + * Copyright (c) 2005 Doug Rabson + * 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. + * + * 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_add_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_add_cred_with_password(OM_uint32 *minor_status, + const gss_cred_id_t input_cred_handle, + const gss_name_t desired_name, + const gss_OID desired_mech, + const gss_buffer_t password, + 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 major_status; + gssapi_mech_interface m; + struct _gss_cred *cred = (struct _gss_cred *) input_cred_handle; + struct _gss_cred *new_cred; + gss_cred_id_t release_cred; + struct _gss_mechanism_cred *mc, *target_mc, *copy_mc; + struct _gss_mechanism_name *mn; + OM_uint32 junk; + + *minor_status = 0; + *output_cred_handle = GSS_C_NO_CREDENTIAL; + if (initiator_time_rec) + *initiator_time_rec = 0; + if (acceptor_time_rec) + *acceptor_time_rec = 0; + if (actual_mechs) + *actual_mechs = GSS_C_NO_OID_SET; + + new_cred = malloc(sizeof(struct _gss_cred)); + if (!new_cred) { + *minor_status = ENOMEM; + return (GSS_S_FAILURE); + } + HEIM_SLIST_INIT(&new_cred->gc_mc); + + /* + * We go through all the mc attached to the input_cred_handle + * and check the mechanism. If it matches, we call + * gss_add_cred for that mechanism, otherwise we copy the mc + * to new_cred. + */ + target_mc = 0; + if (cred) { + HEIM_SLIST_FOREACH(mc, &cred->gc_mc, gmc_link) { + if (gss_oid_equal(mc->gmc_mech_oid, desired_mech)) { + target_mc = mc; + } + copy_mc = _gss_copy_cred(mc); + if (!copy_mc) { + release_cred = (gss_cred_id_t)new_cred; + gss_release_cred(&junk, &release_cred); + *minor_status = ENOMEM; + return (GSS_S_FAILURE); + } + HEIM_SLIST_INSERT_HEAD(&new_cred->gc_mc, copy_mc, gmc_link); + } + } + + /* + * Figure out a suitable mn, if any. + */ + if (desired_name) { + major_status = _gss_find_mn(minor_status, + (struct _gss_name *) desired_name, + desired_mech, + &mn); + if (major_status != GSS_S_COMPLETE) { + free(new_cred); + return major_status; + } + } else { + mn = 0; + } + + m = __gss_get_mechanism(desired_mech); + if (m->gm_add_cred_with_password == NULL) { + release_cred = (gss_cred_id_t)new_cred; + gss_release_cred(&junk, &release_cred); + return (GSS_S_UNAVAILABLE); + } + + mc = malloc(sizeof(struct _gss_mechanism_cred)); + if (!mc) { + release_cred = (gss_cred_id_t)new_cred; + gss_release_cred(&junk, &release_cred); + *minor_status = ENOMEM; + return (GSS_S_FAILURE); + } + mc->gmc_mech = m; + mc->gmc_mech_oid = &m->gm_mech_oid; + + major_status = m->gm_add_cred_with_password(minor_status, + target_mc ? target_mc->gmc_cred : GSS_C_NO_CREDENTIAL, + desired_name ? mn->gmn_name : GSS_C_NO_NAME, + password, + desired_mech, + cred_usage, + initiator_time_req, + acceptor_time_req, + &mc->gmc_cred, + actual_mechs, + initiator_time_rec, + acceptor_time_rec); + + if (major_status) { + _gss_mg_error(m, major_status, *minor_status); + release_cred = (gss_cred_id_t)new_cred; + gss_release_cred(&junk, &release_cred); + free(mc); + return (major_status); + } + HEIM_SLIST_INSERT_HEAD(&new_cred->gc_mc, mc, gmc_link); + *output_cred_handle = (gss_cred_id_t) new_cred; + + return (GSS_S_COMPLETE); +} + diff --git a/lib/gssapi/mech/gss_mech_switch.c b/lib/gssapi/mech/gss_mech_switch.c index 48444a8fa..6da7411a9 100644 --- a/lib/gssapi/mech/gss_mech_switch.c +++ b/lib/gssapi/mech/gss_mech_switch.c @@ -160,7 +160,12 @@ do { \ #define OPTSYM(name) \ do { \ - m->gm_mech.gm_ ## name = dlsym(so, "gss_" #name); \ + m->gm_mech.gm_ ## name = dlsym(so, "gss_" #name); \ +} while (0) + +#define OPTSPISYM(name) \ +do { \ + m->gm_mech.gm_ ## name = dlsym(so, "gssspi_" #name); \ } while (0) /* @@ -332,11 +337,22 @@ _gss_load_mech(void) OPTSYM(inquire_cred_by_oid); OPTSYM(inquire_sec_context_by_oid); OPTSYM(set_sec_context_option); - OPTSYM(set_cred_option); + OPTSPISYM(set_cred_option); OPTSYM(pseudo_random); OPTSYM(wrap_iov); OPTSYM(unwrap_iov); OPTSYM(wrap_iov_length); + OPTSPISYM(acquire_cred_with_password); + OPTSYM(add_cred_with_password); + + /* pick up the oid sets of names */ + + if (m->gm_mech.gm_inquire_names_for_mech) + (*m->gm_mech.gm_inquire_names_for_mech)(&minor_status, + &m->gm_mech.gm_mech_oid, &m->gm_name_types); + + if (m->gm_name_types == NULL) + gss_create_empty_oid_set(&minor_status, &m->gm_name_types); HEIM_SLIST_INSERT_HEAD(&_gss_mechs, m, gm_link); continue; diff --git a/lib/gssapi/version-script.map b/lib/gssapi/version-script.map index 087b29a50..c0f6dcb62 100644 --- a/lib/gssapi/version-script.map +++ b/lib/gssapi/version-script.map @@ -13,8 +13,10 @@ HEIMDAL_GSS_2.0 { __gss_c_attr_stream_sizes_oid_desc; gss_accept_sec_context; gss_acquire_cred; + gss_acquire_cred_with_password; gss_add_buffer_set_member; gss_add_cred; + gss_add_cred_with_password; gss_add_oid_set_member; gss_canonicalize_name; gss_compare_name;