1226031Sstas/* 2226031Sstas * Copyright (c) 2011, PADL Software Pty Ltd. 3226031Sstas * All rights reserved. 4226031Sstas * 5226031Sstas * Redistribution and use in source and binary forms, with or without 6226031Sstas * modification, are permitted provided that the following conditions 7226031Sstas * are met: 8226031Sstas * 9226031Sstas * 1. Redistributions of source code must retain the above copyright 10226031Sstas * notice, this list of conditions and the following disclaimer. 11226031Sstas * 12226031Sstas * 2. Redistributions in binary form must reproduce the above copyright 13226031Sstas * notice, this list of conditions and the following disclaimer in the 14226031Sstas * documentation and/or other materials provided with the distribution. 15226031Sstas * 16226031Sstas * 3. Neither the name of PADL Software nor the names of its contributors 17226031Sstas * may be used to endorse or promote products derived from this software 18226031Sstas * without specific prior written permission. 19226031Sstas * 20226031Sstas * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND 21226031Sstas * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22226031Sstas * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23226031Sstas * ARE DISCLAIMED. IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE 24226031Sstas * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25226031Sstas * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26226031Sstas * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27226031Sstas * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28226031Sstas * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29226031Sstas * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30226031Sstas * SUCH DAMAGE. 31226031Sstas */ 32226031Sstas 33226031Sstas#include "mech_locl.h" 34226031Sstas 35226031Sstasgss_buffer_desc GSSAPI_LIB_VARIABLE __gss_c_attr_local_login_user = { 36226031Sstas sizeof("local-login-user") - 1, 37226031Sstas "local-login-user" 38226031Sstas}; 39226031Sstas 40226031Sstasstatic OM_uint32 41226031Sstasmech_authorize_localname(OM_uint32 *minor_status, 42226031Sstas const struct _gss_name *name, 43226031Sstas const struct _gss_name *user) 44226031Sstas{ 45226031Sstas OM_uint32 major_status = GSS_S_NAME_NOT_MN; 46226031Sstas struct _gss_mechanism_name *mn; 47226031Sstas 48226031Sstas HEIM_SLIST_FOREACH(mn, &name->gn_mn, gmn_link) { 49226031Sstas gssapi_mech_interface m = mn->gmn_mech; 50226031Sstas 51226031Sstas if (m->gm_authorize_localname == NULL) { 52226031Sstas major_status = GSS_S_UNAVAILABLE; 53226031Sstas continue; 54226031Sstas } 55226031Sstas 56226031Sstas major_status = m->gm_authorize_localname(minor_status, 57226031Sstas mn->gmn_name, 58226031Sstas &user->gn_value, 59226031Sstas &user->gn_type); 60226031Sstas if (major_status != GSS_S_UNAUTHORIZED) 61226031Sstas break; 62226031Sstas } 63226031Sstas 64226031Sstas return major_status; 65226031Sstas} 66226031Sstas 67226031Sstas/* 68226031Sstas * Naming extensions based local login authorization. 69226031Sstas */ 70226031Sstasstatic OM_uint32 71226031Sstasattr_authorize_localname(OM_uint32 *minor_status, 72226031Sstas const struct _gss_name *name, 73226031Sstas const struct _gss_name *user) 74226031Sstas{ 75226031Sstas OM_uint32 major_status = GSS_S_UNAVAILABLE; 76226031Sstas int more = -1; 77226031Sstas 78226031Sstas if (!gss_oid_equal(&user->gn_type, GSS_C_NT_USER_NAME)) 79226031Sstas return GSS_S_BAD_NAMETYPE; 80226031Sstas 81226031Sstas while (more != 0 && major_status != GSS_S_COMPLETE) { 82226031Sstas OM_uint32 tmpMajor, tmpMinor; 83226031Sstas gss_buffer_desc value; 84226031Sstas gss_buffer_desc display_value; 85226031Sstas int authenticated = 0, complete = 0; 86226031Sstas 87226031Sstas tmpMajor = gss_get_name_attribute(minor_status, 88226031Sstas (gss_name_t)name, 89226031Sstas GSS_C_ATTR_LOCAL_LOGIN_USER, 90226031Sstas &authenticated, 91226031Sstas &complete, 92226031Sstas &value, 93226031Sstas &display_value, 94226031Sstas &more); 95226031Sstas if (GSS_ERROR(tmpMajor)) { 96226031Sstas major_status = tmpMajor; 97226031Sstas break; 98226031Sstas } 99226031Sstas 100226031Sstas /* If attribute is present, return an authoritative error code. */ 101226031Sstas if (authenticated && 102226031Sstas value.length == user->gn_value.length && 103226031Sstas memcmp(value.value, user->gn_value.value, user->gn_value.length) == 0) 104226031Sstas major_status = GSS_S_COMPLETE; 105226031Sstas else 106226031Sstas major_status = GSS_S_UNAUTHORIZED; 107226031Sstas 108226031Sstas gss_release_buffer(&tmpMinor, &value); 109226031Sstas gss_release_buffer(&tmpMinor, &display_value); 110226031Sstas } 111226031Sstas 112226031Sstas return major_status; 113226031Sstas} 114226031Sstas 115226031SstasGSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL 116226031Sstasgss_authorize_localname(OM_uint32 *minor_status, 117226031Sstas const gss_name_t gss_name, 118226031Sstas const gss_name_t gss_user) 119226031Sstas 120226031Sstas{ 121226031Sstas OM_uint32 major_status; 122226031Sstas const struct _gss_name *name = (const struct _gss_name *) gss_name; 123226031Sstas const struct _gss_name *user = (const struct _gss_name *) gss_user; 124226031Sstas int mechAvailable = 0; 125226031Sstas 126226031Sstas *minor_status = 0; 127226031Sstas 128226031Sstas if (gss_name == GSS_C_NO_NAME || gss_user == GSS_C_NO_NAME) 129226031Sstas return GSS_S_CALL_INACCESSIBLE_READ; 130226031Sstas 131226031Sstas /* 132226031Sstas * We should check that the user name is not a mechanism name, but 133226031Sstas * as Heimdal always calls the mechanism's gss_import_name(), it's 134226031Sstas * not possible to make this check. 135226031Sstas */ 136226031Sstas#if 0 137226031Sstas if (HEIM_SLIST_FIRST(&user->gn_mn) != NULL) 138226031Sstas return GSS_S_BAD_NAME; 139226031Sstas#endif 140226031Sstas 141226031Sstas /* If mech returns yes, we return yes */ 142226031Sstas major_status = mech_authorize_localname(minor_status, name, user); 143226031Sstas if (major_status == GSS_S_COMPLETE) 144226031Sstas return GSS_S_COMPLETE; 145226031Sstas else if (major_status != GSS_S_UNAVAILABLE) 146226031Sstas mechAvailable = 1; 147226031Sstas 148226031Sstas /* If attribute exists, it is authoritative */ 149226031Sstas major_status = attr_authorize_localname(minor_status, name, user); 150226031Sstas if (major_status == GSS_S_COMPLETE || major_status == GSS_S_UNAUTHORIZED) 151226031Sstas return major_status; 152226031Sstas 153226031Sstas /* If mechanism did not implement SPI, compare the local name */ 154226031Sstas if (mechAvailable == 0) { 155226031Sstas int match = 0; 156226031Sstas 157226031Sstas major_status = gss_compare_name(minor_status, gss_name, 158226031Sstas gss_user, &match); 159226031Sstas if (major_status == GSS_S_COMPLETE && match == 0) 160226031Sstas major_status = GSS_S_UNAUTHORIZED; 161226031Sstas } 162226031Sstas 163226031Sstas return major_status; 164226031Sstas} 165226031Sstas 166226031SstasGSSAPI_LIB_FUNCTION int GSSAPI_LIB_CALL 167226031Sstasgss_userok(const gss_name_t name, 168226031Sstas const char *user) 169226031Sstas{ 170226031Sstas OM_uint32 major_status, minor_status; 171226031Sstas gss_buffer_desc userBuf; 172226031Sstas gss_name_t userName; 173226031Sstas 174226031Sstas userBuf.value = (void *)user; 175226031Sstas userBuf.length = strlen(user); 176226031Sstas 177226031Sstas major_status = gss_import_name(&minor_status, &userBuf, 178226031Sstas GSS_C_NT_USER_NAME, &userName); 179226031Sstas if (GSS_ERROR(major_status)) 180226031Sstas return 0; 181226031Sstas 182226031Sstas major_status = gss_authorize_localname(&minor_status, name, userName); 183226031Sstas 184226031Sstas gss_release_name(&minor_status, &userName); 185226031Sstas 186226031Sstas return (major_status == GSS_S_COMPLETE); 187226031Sstas} 188