From e78371829cfa4acc57a3c08180c16ebd2f81c9eb Mon Sep 17 00:00:00 2001 From: Luke Howard Date: Sun, 20 Mar 2011 20:34:59 +1100 Subject: [PATCH] implement gss_userok/gss_pname_to_uid --- lib/gssapi/Makefile.am | 4 +- lib/gssapi/gssapi_mech.h | 18 +- lib/gssapi/mech/gss_mech_switch.c | 2 +- ..._any_name_mapping.c => gss_pname_to_uid.c} | 48 ++--- lib/gssapi/mech/gss_userok.c | 173 ++++++++++++++++++ lib/gssapi/mech/mech_switch.h | 11 -- 6 files changed, 220 insertions(+), 36 deletions(-) rename lib/gssapi/mech/{gss_release_any_name_mapping.c => gss_pname_to_uid.c} (63%) create mode 100644 lib/gssapi/mech/gss_userok.c diff --git a/lib/gssapi/Makefile.am b/lib/gssapi/Makefile.am index 525626eec..5b525d849 100644 --- a/lib/gssapi/Makefile.am +++ b/lib/gssapi/Makefile.am @@ -117,16 +117,15 @@ mechsrc = \ mech/gss_inquire_name.c \ mech/gss_inquire_names_for_mech.c \ mech/gss_krb5.c \ - mech/gss_map_name_to_any.c \ mech/gss_mech_switch.c \ mech/gss_mo.c \ mech/gss_names.c \ mech/gss_oid.c \ mech/gss_oid_equal.c \ mech/gss_oid_to_str.c \ + mech/gss_pname_to_uid.c \ mech/gss_process_context_token.c \ mech/gss_pseudo_random.c \ - mech/gss_release_any_name_mapping.c \ mech/gss_release_buffer.c \ mech/gss_release_cred.c \ mech/gss_release_name.c \ @@ -141,6 +140,7 @@ mechsrc = \ mech/gss_test_oid_set_member.c \ mech/gss_unseal.c \ mech/gss_unwrap.c \ + mech/gss_userok.c \ mech/gss_utils.c \ mech/gss_verify.c \ mech/gss_verify_mic.c \ diff --git a/lib/gssapi/gssapi_mech.h b/lib/gssapi/gssapi_mech.h index 071845e3a..241be1391 100644 --- a/lib/gssapi/gssapi_mech.h +++ b/lib/gssapi/gssapi_mech.h @@ -488,6 +488,20 @@ typedef OM_uint32 GSSAPI_CALLCONV _gss_add_cred_with_password_t ( OM_uint32 * /* acceptor_time_rec */ ); +typedef OM_uint32 GSSAPI_CALLCONV _gss_pname_to_uid_t ( + OM_uint32 *, /* minor_status */ + const gss_name_t, /* name */ + const gss_OID, /* mech_type */ + uid_t * /* uidOut */ + ); + +typedef OM_uint32 GSSAPI_CALLCONV _gss_userok_t ( + OM_uint32 *, /* minor_status */ + const gss_name_t, /* name */ + const char *, /* user */ + int * /*user_ok */ + ); + /* mechglue internal */ struct gss_mech_compat_desc_struct; @@ -558,7 +572,9 @@ typedef struct gssapi_mech_interface_desc { _gss_export_name_composite_t *gm_export_name_composite; _gss_acquire_cred_with_password_t *gm_acquire_cred_with_password; _gss_add_cred_with_password_t *gm_add_cred_with_password; - gss_mech_compat_desc_struct *gm_compat; + _gss_pname_to_uid_t *gm_pname_to_uid; + _gss_userok_t *gm_userok; + struct gss_mech_compat_desc_struct *gm_compat; } gssapi_mech_interface_desc, *gssapi_mech_interface; gssapi_mech_interface diff --git a/lib/gssapi/mech/gss_mech_switch.c b/lib/gssapi/mech/gss_mech_switch.c index 3070f3699..14ff5b4f2 100644 --- a/lib/gssapi/mech/gss_mech_switch.c +++ b/lib/gssapi/mech/gss_mech_switch.c @@ -360,7 +360,7 @@ _gss_load_mech(void) OPTSPISYM(acquire_cred_with_password); OPTSYM(add_cred_with_password); OPTSYM(pname_to_uid); - OPTSYM(user_ok); + OPTSYM(userok); mi = dlsym(so, "gss_mo_init"); if (mi != NULL) { diff --git a/lib/gssapi/mech/gss_release_any_name_mapping.c b/lib/gssapi/mech/gss_pname_to_uid.c similarity index 63% rename from lib/gssapi/mech/gss_release_any_name_mapping.c rename to lib/gssapi/mech/gss_pname_to_uid.c index 14a4dfa69..fd0ea6866 100644 --- a/lib/gssapi/mech/gss_release_any_name_mapping.c +++ b/lib/gssapi/mech/gss_pname_to_uid.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, PADL Software Pty Ltd. + * Copyright (c) 2011, PADL Software Pty Ltd. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -33,36 +33,42 @@ #include "mech_locl.h" OM_uint32 -gss_release_any_name_mapping(OM_uint32 *minor_status, - gss_name_t input_name, - gss_buffer_t type_id, - gss_any_t *input) +gss_pname_to_uid(OM_uint32 *minor_status, + const gss_name_t input_name, + const gss_OID mech_type, + uid_t *uidOut) { - OM_uint32 major_status = GSS_S_UNAVAILABLE; + OM_uint32 major_status; struct _gss_name *name = (struct _gss_name *) input_name; struct _gss_mechanism_name *mn; - - *minor_status = 0; - if (input_name == GSS_C_NO_NAME) - return GSS_S_BAD_NAME; + *uidOut = -1; + + if (mech_type != GSS_C_NO_OID) { + major_status = _gss_find_mn(minor_status, name, mech_type, &mn); + if (GSS_ERROR(major_status)) + return major_status; + + if (mn->gmn_mech->gm_pname_to_uid == NULL) + return GSS_S_UNAVAILABLE; + + return mn->gmn_mech->gm_pname_to_uid(minor_status, mn->gmn_name, + mech_type, uidOut); + } + + major_status = GSS_S_UNAVAILABLE; HEIM_SLIST_FOREACH(mn, &name->gn_mn, gmn_link) { - gssapi_mech_interface m = mn->gmn_mech; + if (mn->gmn_mech->gm_pname_to_uid == NULL) - if (!m->gm_release_any_name_mapping) continue; - major_status = m->gm_release_any_name_mapping(minor_status, - mn->gmn_name, - type_id, - input); - if (GSS_ERROR(major_status)) - _gss_mg_error(m, major_status, *minor_status); - else { - *input = (gss_any_t)0; + major_status = mn->gmn_mech->gm_pname_to_uid(minor_status, + mn->gmn_name, + mn->gmn_mech_oid, + uidOut); + if (major_status != GSS_S_UNAVAILABLE) break; - } } return major_status; diff --git a/lib/gssapi/mech/gss_userok.c b/lib/gssapi/mech/gss_userok.c new file mode 100644 index 000000000..2af4a02e4 --- /dev/null +++ b/lib/gssapi/mech/gss_userok.c @@ -0,0 +1,173 @@ +/* + * 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" + +static const char localLoginUserAttr[] = "local-login-user"; + +static OM_uint32 +mech_userok(OM_uint32 *minor_status, + gss_name_t input_name, + const char *user, + int *user_ok) +{ + const struct _gss_name *name = (const struct _gss_name *)input_name; + OM_uint32 major_status = GSS_S_UNAVAILABLE; + struct _gss_mechanism_name *mn; + + *user_ok = 0; + + HEIM_SLIST_FOREACH(mn, &name->gn_mn, gmn_link) { + gssapi_mech_interface m = mn->gmn_mech; + + if (!m->gm_userok) + continue; + + major_status = m->gm_userok(minor_status, + mn->gmn_name, + user, + user_ok); + if (GSS_ERROR(major_status) || *user_ok) + break; + } + + return major_status; +} + +/* + * Naming extensions based local login authorization. + */ +static OM_uint32 +attr_userok(OM_uint32 *minor_status, + const gss_name_t name, + const char *user, + int *user_ok) +{ + OM_uint32 major_status = GSS_S_UNAVAILABLE; + OM_uint32 tmpMinor; + size_t userLen = strlen(user); + int more = -1; + gss_buffer_desc attribute; + + *user_ok = 0; + + attribute.length = sizeof(localLoginUserAttr) - 1; + attribute.value = (void *)localLoginUserAttr; + + while (more != 0 && *user_ok == 0) { + gss_buffer_desc value; + gss_buffer_desc display_value; + int authenticated = 0, complete = 0; + + major_status = gss_get_name_attribute(minor_status, + name, + &attribute, + &authenticated, + &complete, + &value, + &display_value, + &more); + if (GSS_ERROR(major_status)) + break; + + if (authenticated && complete && + value.length == userLen && + memcmp(value.value, user, userLen) == 0) + *user_ok = 1; + + gss_release_buffer(&tmpMinor, &value); + gss_release_buffer(&tmpMinor, &display_value); + } + + return major_status; +} + +/* + * Equality based local login authorization. + */ +static OM_uint32 +compare_names_userok(OM_uint32 *minor_status, + const gss_name_t name, + const char *user, + int *user_ok) +{ + OM_uint32 major_status = GSS_S_UNAVAILABLE; + OM_uint32 tmpMinor; + gss_buffer_desc gssUser; + gss_name_t gssUserName = GSS_C_NO_NAME; + + *user_ok = 0; + + gssUser.length = strlen(user); + gssUser.value = (void *)user; + + major_status = gss_import_name(minor_status, &gssUser, + GSS_C_NT_USER_NAME, &gssUserName); + if (GSS_ERROR(major_status)) + return major_status; + + major_status = gss_compare_name(minor_status, name, + gssUserName, user_ok); + + gss_release_name(&tmpMinor, &gssUserName); + + return major_status; +} + +OM_uint32 +gss_userok(OM_uint32 *minor_status, + const gss_name_t name, + const char *user, + int *user_ok) + +{ + OM_uint32 major_status; + + *minor_status = 0; + *user_ok = 0; + + /* If mech returns yes, we return yes */ + major_status = mech_userok(minor_status, name, user, user_ok); + if (major_status == GSS_S_COMPLETE && *user_ok) + return GSS_S_COMPLETE; + + /* If attribute exists, we evaluate attribute */ + if (attr_userok(minor_status, name, user, user_ok) == GSS_S_COMPLETE) + return GSS_S_COMPLETE; + + /* If mech returns unavail, we compare the local name */ + if (major_status == GSS_S_UNAVAILABLE) + major_status = compare_names_userok(minor_status, name, + user, user_ok); + + return major_status; +} diff --git a/lib/gssapi/mech/mech_switch.h b/lib/gssapi/mech/mech_switch.h index f50b471b2..7ed3d4d4a 100644 --- a/lib/gssapi/mech/mech_switch.h +++ b/lib/gssapi/mech/mech_switch.h @@ -40,15 +40,4 @@ HEIM_SLIST_HEAD(_gss_mech_switch_list, _gss_mech_switch); extern struct _gss_mech_switch_list _gss_mechs; extern gss_OID_set _gss_mech_oids; -/* - * Initialization function for MO SPI, so they may dynamically return a - * set of mechanism objects at load time. - */ -typedef OM_uint32 GSSAPI_CALLCONV _gss_mo_init ( - OM_uint32 *minor, - gss_OID oid, - gss_mo_desc **mo, - size_t *mo_num - ); - void _gss_load_mech(void);