From 8b62abaa08ba814ce45bde12d8798d3a6e58c209 Mon Sep 17 00:00:00 2001 From: Greg Hudson Date: Sun, 10 Apr 2011 15:42:11 +0000 Subject: Implement gss_authorize_localname, as discussed on the kitten list, and make gss_userok a wrapper around it matching the Gnu GSS prototype. The SPI for gss_authorize_localname doesn't match the API since we have no way of representing the contents of an internal name to a mech at the moment. From r24855, r24857, r24858, r24862, r24863, r24864, r24866, r24867, and r24868 in users/lhoward/moonshot-mechglue-fixes. ticket: 6891 git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@24869 dc483132-0cff-0310-8789-dd5450dbe970 --- src/lib/gssapi/generic/gssapi_ext.h | 11 +- src/lib/gssapi/krb5/gssapi_krb5.c | 41 +++-- src/lib/gssapi/libgssapi_krb5.exports | 1 + src/lib/gssapi/mechglue/Makefile.in | 6 +- src/lib/gssapi/mechglue/g_authorize_localname.c | 225 ++++++++++++++++++++++++ src/lib/gssapi/mechglue/g_initialize.c | 2 +- src/lib/gssapi/mechglue/g_userok.c | 212 ---------------------- src/lib/gssapi/mechglue/mglueP.h | 14 +- 8 files changed, 268 insertions(+), 244 deletions(-) create mode 100644 src/lib/gssapi/mechglue/g_authorize_localname.c delete mode 100644 src/lib/gssapi/mechglue/g_userok.c (limited to 'src') diff --git a/src/lib/gssapi/generic/gssapi_ext.h b/src/lib/gssapi/generic/gssapi_ext.h index 5350dd32ce..c61955e881 100644 --- a/src/lib/gssapi/generic/gssapi_ext.h +++ b/src/lib/gssapi/generic/gssapi_ext.h @@ -41,11 +41,14 @@ gss_pname_to_uid const gss_OID mech_type, uid_t *uidOut); +int KRB5_CALLCONV +gss_userok(const gss_name_t name, + const char *username); + OM_uint32 KRB5_CALLCONV -gss_userok(OM_uint32 *minor, - const gss_name_t name, - const char *user, - int *user_ok); +gss_authorize_localname(OM_uint32 *minor, + const gss_name_t name, + const gss_name_t user); OM_uint32 KRB5_CALLCONV gss_acquire_cred_with_password( diff --git a/src/lib/gssapi/krb5/gssapi_krb5.c b/src/lib/gssapi/krb5/gssapi_krb5.c index a503744e52..bc02a0716a 100644 --- a/src/lib/gssapi/krb5/gssapi_krb5.c +++ b/src/lib/gssapi/krb5/gssapi_krb5.c @@ -797,17 +797,28 @@ krb5_gss_pname_to_uid(OM_uint32 *minor, #endif /* !NO_PASSWORD */ static OM_uint32 -krb5_gss_userok(OM_uint32 *minor, - const gss_name_t pname, - const char *local_user, - int *user_ok) +krb5_gss_authorize_localname(OM_uint32 *minor, + const gss_name_t pname, + gss_const_buffer_t local_user, + gss_const_OID name_type) { krb5_context context; krb5_error_code code; krb5_gss_name_t kname; + char *user; + int user_ok; - *minor = 0; - *user_ok = 0; + if (name_type != GSS_C_NO_OID && + !g_OID_equal(name_type, GSS_C_NT_USER_NAME)) { + return GSS_S_BAD_NAMETYPE; + } + + if (!kg_validate_name(pname)) { + *minor = (OM_uint32)G_VALIDATE_FAILED; + return GSS_S_CALL_BAD_STRUCTURE|GSS_S_BAD_NAME; + } + + kname = (krb5_gss_name_t)pname; code = krb5_gss_init_context(&context); if (code != 0) { @@ -815,19 +826,23 @@ krb5_gss_userok(OM_uint32 *minor, return GSS_S_FAILURE; } - if (!kg_validate_name(pname)) { - *minor = (OM_uint32)G_VALIDATE_FAILED; + user = k5alloc(local_user->length + 1, &code); + if (user == NULL) { + *minor = code; krb5_free_context(context); - return GSS_S_CALL_BAD_STRUCTURE|GSS_S_BAD_NAME; + return GSS_S_FAILURE; } - kname = (krb5_gss_name_t)pname; + memcpy(user, local_user->value, local_user->length); + user[local_user->length] = '\0'; - *user_ok = krb5_kuserok(context, kname->princ, local_user); + user_ok = krb5_kuserok(context, kname->princ, user); + free(user); krb5_free_context(context); - return GSS_S_COMPLETE; + *minor = 0; + return user_ok ? GSS_S_COMPLETE : GSS_S_UNAUTHORIZED; } static struct gss_config krb5_mechanism = { @@ -881,7 +896,7 @@ static struct gss_config krb5_mechanism = { #else krb5_gss_pname_to_uid, #endif - krb5_gss_userok, + krb5_gss_authorize_localname, krb5_gss_export_name, krb5_gss_duplicate_name, krb5_gss_store_cred, diff --git a/src/lib/gssapi/libgssapi_krb5.exports b/src/lib/gssapi/libgssapi_krb5.exports index 4b767da145..2f85a7189c 100644 --- a/src/lib/gssapi/libgssapi_krb5.exports +++ b/src/lib/gssapi/libgssapi_krb5.exports @@ -43,6 +43,7 @@ gss_add_buffer_set_member gss_add_cred gss_add_cred_impersonate_name gss_add_oid_set_member +gss_authorize_localname gss_canonicalize_name gss_compare_name gss_complete_auth_token diff --git a/src/lib/gssapi/mechglue/Makefile.in b/src/lib/gssapi/mechglue/Makefile.in index 069080f9a3..63302f0ee0 100644 --- a/src/lib/gssapi/mechglue/Makefile.in +++ b/src/lib/gssapi/mechglue/Makefile.in @@ -14,6 +14,7 @@ SRCS = \ $(srcdir)/g_acquire_cred.c \ $(srcdir)/g_acquire_cred_with_pw.c \ $(srcdir)/g_acquire_cred_imp_name.c \ + $(srcdir)/g_authorize_localname.c \ $(srcdir)/g_buffer_set.c \ $(srcdir)/g_canon_name.c \ $(srcdir)/g_compare_name.c \ @@ -65,7 +66,6 @@ SRCS = \ $(srcdir)/g_unseal.c \ $(srcdir)/g_unwrap_aead.c \ $(srcdir)/g_unwrap_iov.c \ - $(srcdir)/g_userok.c \ $(srcdir)/g_verify.c \ $(srcdir)/g_wrap_aead.c \ $(srcdir)/g_wrap_iov.c \ @@ -76,6 +76,7 @@ OBJS = \ $(OUTPRE)g_acquire_cred.$(OBJEXT) \ $(OUTPRE)g_acquire_cred_with_pw.$(OBJEXT) \ $(OUTPRE)g_acquire_cred_imp_name.$(OBJEXT) \ + $(OUTPRE)g_authorize_localname.$(OBJEXT) \ $(OUTPRE)g_buffer_set.$(OBJEXT) \ $(OUTPRE)g_canon_name.$(OBJEXT) \ $(OUTPRE)g_compare_name.$(OBJEXT) \ @@ -127,7 +128,6 @@ OBJS = \ $(OUTPRE)g_unseal.$(OBJEXT) \ $(OUTPRE)g_unwrap_aead.$(OBJEXT) \ $(OUTPRE)g_unwrap_iov.$(OBJEXT) \ - $(OUTPRE)g_userok.$(OBJEXT) \ $(OUTPRE)g_verify.$(OBJEXT) \ $(OUTPRE)g_wrap_aead.$(OBJEXT) \ $(OUTPRE)g_wrap_iov.$(OBJEXT) \ @@ -138,6 +138,7 @@ STLIBOBJS = \ g_acquire_cred.o \ g_acquire_cred_with_pw.o \ g_acquire_cred_imp_name.o \ + g_authorize_localname.o \ g_buffer_set.o \ g_canon_name.o \ g_compare_name.o \ @@ -189,7 +190,6 @@ STLIBOBJS = \ g_unseal.o \ g_unwrap_aead.o \ g_unwrap_iov.o \ - g_userok.o \ g_verify.o \ g_wrap_aead.o \ g_wrap_iov.o \ diff --git a/src/lib/gssapi/mechglue/g_authorize_localname.c b/src/lib/gssapi/mechglue/g_authorize_localname.c new file mode 100644 index 0000000000..eec42f739c --- /dev/null +++ b/src/lib/gssapi/mechglue/g_authorize_localname.c @@ -0,0 +1,225 @@ +/* + * 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. + */ +/* + * Copyright 2004 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. + */ + +/* #pragma ident "@(#)g_userok.c 1.1 04/03/25 SMI" */ + +#include +#include +#include +#include +#include +#include + +static OM_uint32 +mech_authorize_localname(OM_uint32 *minor, + const gss_union_name_t unionName, + const gss_union_name_t unionUser) +{ + OM_uint32 major = GSS_S_UNAVAILABLE; + gss_mechanism mech; + + if (unionName->mech_type == GSS_C_NO_OID) + return (GSS_S_NAME_NOT_MN); + + mech = gssint_get_mechanism(unionName->mech_type); + if (mech == NULL) + return (GSS_S_UNAVAILABLE); + + if (mech->gssspi_authorize_localname != NULL) { + major = mech->gssspi_authorize_localname(minor, + unionName->mech_name, + unionUser->external_name, + unionUser->name_type); + if (major != GSS_S_COMPLETE) + map_error(minor, mech); + } + + return (major); +} + +/* + * Naming extensions based local login authorization. + */ +static OM_uint32 +attr_authorize_localname(OM_uint32 *minor, + const gss_name_t name, + const gss_union_name_t unionUser) +{ + OM_uint32 major = GSS_S_UNAVAILABLE; /* attribute not present */ + gss_buffer_t externalName; + int more = -1; + + if (unionUser->name_type != GSS_C_NO_OID && + !g_OID_equal(unionUser->name_type, GSS_C_NT_USER_NAME)) + return (GSS_S_BAD_NAMETYPE); + + externalName = unionUser->external_name; + assert(externalName != GSS_C_NO_BUFFER); + + while (more != 0 && major != GSS_S_COMPLETE) { + OM_uint32 tmpMajor, tmpMinor; + gss_buffer_desc value; + gss_buffer_desc display_value; + int authenticated = 0, complete = 0; + + tmpMajor = gss_get_name_attribute(minor, + name, + GSS_C_ATTR_LOCAL_LOGIN_USER, + &authenticated, + &complete, + &value, + &display_value, + &more); + if (GSS_ERROR(tmpMajor)) { + major = tmpMajor; + break; + } + + if (authenticated && + value.length == externalName->length && + memcmp(value.value, externalName->value, externalName->length) == 0) + major = GSS_S_COMPLETE; + else + major = GSS_S_UNAUTHORIZED; + + gss_release_buffer(&tmpMinor, &value); + gss_release_buffer(&tmpMinor, &display_value); + } + + return (major); +} + +/* + * Equality based local login authorization. + */ +static OM_uint32 +compare_names_authorize_localname(OM_uint32 *minor, + const gss_union_name_t unionName, + const gss_name_t user) +{ + + OM_uint32 status, tmpMinor; + gss_name_t canonName; + int match = 0; + + status = gss_canonicalize_name(minor, + user, + unionName->mech_type, + &canonName); + if (status != GSS_S_COMPLETE) + return (status); + + status = gss_compare_name(minor, + (gss_name_t)unionName, + canonName, + &match); + if (status == GSS_S_COMPLETE && match == 0) + status = GSS_S_UNAUTHORIZED; + + (void) gss_release_name(&tmpMinor, &canonName); + + return (status); +} + +OM_uint32 +gss_authorize_localname(OM_uint32 *minor, + const gss_name_t name, + const gss_name_t user) + +{ + OM_uint32 major; + gss_union_name_t unionName; + gss_union_name_t unionUser; + int mechAvailable = 0; + + if (minor == NULL) + return (GSS_S_CALL_INACCESSIBLE_WRITE); + + if (name == GSS_C_NO_NAME || user == GSS_C_NO_NAME) + return (GSS_S_CALL_INACCESSIBLE_READ); + + *minor = 0; + + unionName = (gss_union_name_t)name; + unionUser = (gss_union_name_t)user; + + if (unionUser->mech_type != GSS_C_NO_OID) + return (GSS_S_BAD_NAME); + + /* If mech returns yes, we return yes */ + major = mech_authorize_localname(minor, unionName, unionUser); + if (major == GSS_S_COMPLETE) + return (GSS_S_COMPLETE); + else if (major != GSS_S_UNAVAILABLE) + mechAvailable = 1; + + /* If attribute exists, we evaluate attribute */ + major = attr_authorize_localname(minor, unionName, unionUser); + if (major == GSS_S_COMPLETE || major == GSS_S_UNAUTHORIZED) + return (major); + + /* If mech did not implement SPI, compare the local name */ + if (mechAvailable == 0 && + unionName->mech_type != GSS_C_NO_OID) { + major = compare_names_authorize_localname(minor, + unionName, + unionUser); + } + + return (major); +} + +int +gss_userok(const gss_name_t name, + const char *user) +{ + OM_uint32 major, minor; + gss_buffer_desc userBuf; + gss_name_t userName; + + userBuf.value = (void *)user; + userBuf.length = strlen(user); + + major = gss_import_name(&minor, &userBuf, GSS_C_NT_USER_NAME, &userName); + if (GSS_ERROR(major)) + return (0); + + major = gss_authorize_localname(&minor, name, userName); + + (void) gss_release_name(&minor, &userName); + + return (major == GSS_S_COMPLETE); +} diff --git a/src/lib/gssapi/mechglue/g_initialize.c b/src/lib/gssapi/mechglue/g_initialize.c index 60f82fd4bf..c1e732fe03 100644 --- a/src/lib/gssapi/mechglue/g_initialize.c +++ b/src/lib/gssapi/mechglue/g_initialize.c @@ -777,7 +777,7 @@ build_dynamicMech(void *dl, const gss_OID mech_type) GSS_ADD_DYNAMIC_METHOD(dl, mech, gss_internal_release_oid); GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_wrap_size_limit); GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_pname_to_uid); - GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_userok); + GSS_ADD_DYNAMIC_METHOD(dl, mech, gssspi_authorize_localname); GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_export_name); GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_duplicate_name); GSS_ADD_DYNAMIC_METHOD_NOLOOP(dl, mech, gss_store_cred); diff --git a/src/lib/gssapi/mechglue/g_userok.c b/src/lib/gssapi/mechglue/g_userok.c deleted file mode 100644 index 318c7ccd09..0000000000 --- a/src/lib/gssapi/mechglue/g_userok.c +++ /dev/null @@ -1,212 +0,0 @@ -/* - * 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. - */ -/* - * Copyright 2004 Sun Microsystems, Inc. All rights reserved. - * Use is subject to license terms. - */ - -/* #pragma ident "@(#)g_userok.c 1.1 04/03/25 SMI" */ - -#include -#include -#include -#include -#include -#include - -static OM_uint32 -mech_userok(OM_uint32 *minor, - const gss_union_name_t unionName, - const char *user, - int *user_ok) -{ - OM_uint32 major = GSS_S_UNAVAILABLE; - gss_mechanism mech; - - /* may need to import the name if this is not MN */ - if (unionName->mech_type == GSS_C_NO_OID) - return (GSS_S_FAILURE); - - mech = gssint_get_mechanism(unionName->mech_type); - if (mech == NULL) - return (GSS_S_UNAVAILABLE); - - if (mech->gss_userok) { - major = mech->gss_userok(minor, unionName->mech_name, user, user_ok); - if (major != GSS_S_COMPLETE) - map_error(minor, mech); - } - - return (major); -} - -/* - * Naming extensions based local login authorization. - */ -static OM_uint32 -attr_userok(OM_uint32 *minor, - const gss_name_t name, - const char *user, - int *user_ok) -{ - OM_uint32 major = GSS_S_UNAVAILABLE; - OM_uint32 tmpMinor; - size_t userLen = strlen(user); - int more = -1; - - *user_ok = 0; - - while (more != 0 && *user_ok == 0) { - gss_buffer_desc value; - gss_buffer_desc display_value; - int authenticated = 0, complete = 0; - - major = gss_get_name_attribute(minor, - name, - GSS_C_ATTR_LOCAL_LOGIN_USER, - &authenticated, - &complete, - &value, - &display_value, - &more); - if (GSS_ERROR(major)) - break; - - if (authenticated && - 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); -} - -/* - * Equality based local login authorization. - */ -static OM_uint32 -compare_names_userok(OM_uint32 *minor, - const gss_OID mech_type, - const gss_name_t name, - const char *user, - int *user_ok) -{ - - OM_uint32 status, tmpMinor; - gss_name_t imported_name; - gss_name_t canon_name; - gss_buffer_desc gss_user; - int match = 0; - - *user_ok = 0; - - gss_user.value = (void *)user; - if (gss_user.value == NULL || - name == GSS_C_NO_NAME || - mech_type == GSS_C_NO_OID) - return (GSS_S_BAD_NAME); - gss_user.length = strlen(gss_user.value); - - status = gss_import_name(minor, - &gss_user, - GSS_C_NT_USER_NAME, - &imported_name); - if (status != GSS_S_COMPLETE) { - goto out; - } - - status = gss_canonicalize_name(minor, - imported_name, - mech_type, - &canon_name); - if (status != GSS_S_COMPLETE) { - (void) gss_release_name(&tmpMinor, &imported_name); - goto out; - } - - status = gss_compare_name(minor, - canon_name, - name, - &match); - (void) gss_release_name(&tmpMinor, &canon_name); - (void) gss_release_name(&tmpMinor, &imported_name); - if (status == GSS_S_COMPLETE) { - if (match) - *user_ok = 1; /* remote user is a-ok */ - } - -out: - return (status); -} - - -OM_uint32 -gss_userok(OM_uint32 *minor, - const gss_name_t name, - const char *user, - int *user_ok) - -{ - OM_uint32 major; - gss_union_name_t unionName; - - if (minor == NULL || user_ok == NULL) - return (GSS_S_CALL_INACCESSIBLE_WRITE); - - if (name == NULL || user == NULL) - return (GSS_S_CALL_INACCESSIBLE_READ); - - *user_ok = 0; - *minor = 0; - - unionName = (gss_union_name_t)name; - - /* If mech returns yes, we return yes */ - major = mech_userok(minor, unionName, user, user_ok); - if (major == GSS_S_COMPLETE && *user_ok) - return (GSS_S_COMPLETE); - - /* If attribute exists, we evaluate attribute */ - if (attr_userok(minor, name, user, user_ok) == GSS_S_COMPLETE) - return (GSS_S_COMPLETE); - - /* If mech returns unavail, we compare the local name */ - if (major == GSS_S_UNAVAILABLE) { - major = compare_names_userok(minor, unionName->mech_type, - name, user, user_ok); - } - - return (major); -} /* gss_userok */ diff --git a/src/lib/gssapi/mechglue/mglueP.h b/src/lib/gssapi/mechglue/mglueP.h index fc7013e053..426b70c952 100644 --- a/src/lib/gssapi/mechglue/mglueP.h +++ b/src/lib/gssapi/mechglue/mglueP.h @@ -342,12 +342,12 @@ typedef struct gss_config { const gss_OID, /* mech_type */ uid_t * /* uid */ ); - OM_uint32 (*gss_userok) + OM_uint32 (*gssspi_authorize_localname) ( OM_uint32 *, /* minor_status */ const gss_name_t, /* pname */ - const char *, /* local user */ - int * /* user ok? */ + gss_const_buffer_t, /* local user */ + gss_const_OID /* local nametype */ /* */); OM_uint32 (*gss_export_name) ( @@ -723,14 +723,6 @@ gssint_get_mechanisms( int arrayLen /* length of passed in array */ ); -OM_uint32 -gssint_userok( - OM_uint32 *, /* minor */ - const gss_name_t, /* name */ - const char *, /* user */ - int * /* user_ok */ -); - int gssint_get_der_length( unsigned char **, /* buf */ -- cgit