#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) {
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 = {
#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,
#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);
}
* 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);
* 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);
+}