From 8b62abaa08ba814ce45bde12d8798d3a6e58c209 Mon Sep 17 00:00:00 2001 From: Greg Hudson Date: Sun, 10 Apr 2011 15:42:11 +0000 Subject: [PATCH] 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 +- .../{g_userok.c => g_authorize_localname.c} | 191 ++++++++++-------- src/lib/gssapi/mechglue/g_initialize.c | 2 +- src/lib/gssapi/mechglue/mglueP.h | 14 +- 7 files changed, 145 insertions(+), 121 deletions(-) rename src/lib/gssapi/mechglue/{g_userok.c => g_authorize_localname.c} (50%) diff --git a/src/lib/gssapi/generic/gssapi_ext.h b/src/lib/gssapi/generic/gssapi_ext.h index 5350dd32c..c61955e88 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 a503744e5..bc02a0716 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 4b767da14..2f85a7189 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 069080f9a..63302f0ee 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_userok.c b/src/lib/gssapi/mechglue/g_authorize_localname.c similarity index 50% rename from src/lib/gssapi/mechglue/g_userok.c rename to src/lib/gssapi/mechglue/g_authorize_localname.c index 318c7ccd0..eec42f739 100644 --- a/src/lib/gssapi/mechglue/g_userok.c +++ b/src/lib/gssapi/mechglue/g_authorize_localname.c @@ -44,24 +44,25 @@ #include static OM_uint32 -mech_userok(OM_uint32 *minor, - const gss_union_name_t unionName, - const char *user, - int *user_ok) +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; - /* may need to import the name if this is not MN */ if (unionName->mech_type == GSS_C_NO_OID) - return (GSS_S_FAILURE); + return (GSS_S_NAME_NOT_MN); 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 (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); } @@ -73,38 +74,46 @@ mech_userok(OM_uint32 *minor, * 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) +attr_authorize_localname(OM_uint32 *minor, + const gss_name_t name, + const gss_union_name_t unionUser) { - OM_uint32 major = GSS_S_UNAVAILABLE; - OM_uint32 tmpMinor; - size_t userLen = strlen(user); + OM_uint32 major = GSS_S_UNAVAILABLE; /* attribute not present */ + gss_buffer_t externalName; int more = -1; - *user_ok = 0; + 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 && *user_ok == 0) { + 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; - major = gss_get_name_attribute(minor, - name, - GSS_C_ATTR_LOCAL_LOGIN_USER, - &authenticated, - &complete, - &value, - &display_value, - &more); - if (GSS_ERROR(major)) + 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 == userLen && - memcmp(value.value, user, userLen) == 0) - *user_ok = 1; + 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); @@ -117,96 +126,100 @@ attr_userok(OM_uint32 *minor, * 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) +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 imported_name; - gss_name_t canon_name; - gss_buffer_desc gss_user; + gss_name_t canonName; 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; - } + user, + unionName->mech_type, + &canonName); + if (status != GSS_S_COMPLETE) + return (status); 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 */ - } + (gss_name_t)unionName, + canonName, + &match); + if (status == GSS_S_COMPLETE && match == 0) + status = GSS_S_UNAUTHORIZED; + + (void) gss_release_name(&tmpMinor, &canonName); -out: return (status); } - OM_uint32 -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 major; gss_union_name_t unionName; + gss_union_name_t unionUser; + int mechAvailable = 0; - if (minor == NULL || user_ok == NULL) + if (minor == NULL) return (GSS_S_CALL_INACCESSIBLE_WRITE); - if (name == NULL || user == NULL) + if (name == GSS_C_NO_NAME || user == GSS_C_NO_NAME) return (GSS_S_CALL_INACCESSIBLE_READ); - *user_ok = 0; *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_userok(minor, unionName, user, user_ok); - if (major == GSS_S_COMPLETE && *user_ok) + 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 */ - 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); + 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); -} /* gss_userok */ +} + +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 60f82fd4b..c1e732fe0 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/mglueP.h b/src/lib/gssapi/mechglue/mglueP.h index fc7013e05..426b70c95 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 */ -- 2.26.2