Implement gss_authorize_localname, as discussed on the kitten list,
authorGreg Hudson <ghudson@mit.edu>
Sun, 10 Apr 2011 15:42:11 +0000 (15:42 +0000)
committerGreg Hudson <ghudson@mit.edu>
Sun, 10 Apr 2011 15:42:11 +0000 (15:42 +0000)
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
src/lib/gssapi/krb5/gssapi_krb5.c
src/lib/gssapi/libgssapi_krb5.exports
src/lib/gssapi/mechglue/Makefile.in
src/lib/gssapi/mechglue/g_authorize_localname.c [moved from src/lib/gssapi/mechglue/g_userok.c with 50% similarity]
src/lib/gssapi/mechglue/g_initialize.c
src/lib/gssapi/mechglue/mglueP.h

index 5350dd32ce699f47cf97a420f9489bffc3984afb..c61955e881089b2ae732df9353ec2540a3cb994e 100644 (file)
@@ -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(
index a503744e52dde7c8d9c566e381282bae2dd7593e..bc02a0716aaacea7a7341901c38f0eb09e14eae6 100644 (file)
@@ -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,
index 4b767da1459adaab283fe1f9b23a9ce20fd54886..2f85a7189c506baf7cd16d15050c34a38037e882 100644 (file)
@@ -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
index 069080f9a3f130c9ff8ebcccc871232f07f4a8ea..63302f0ee08b1a402098dfb0b615c62667eedba3 100644 (file)
@@ -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 \
similarity index 50%
rename from src/lib/gssapi/mechglue/g_userok.c
rename to src/lib/gssapi/mechglue/g_authorize_localname.c
index 318c7ccd09e53602f0fd72e4c3ec3dd369250434..eec42f739c76fcf6347479d7cb3d7b5a442db7a0 100644 (file)
 #include <gssapi/gssapi.h>
 
 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);
+}
index 60f82fd4bff1c369357d6cda97e0e6fd6aeb1fe9..c1e732fe0355292fb5ab3a9f7b03eb980846aea0 100644 (file)
@@ -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);
index fc7013e053808867b44c6f5979b1027076033a21..426b70c952e2a19ed52962cbde093662e0b2628f 100644 (file)
@@ -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 */