1 /* $NetBSD: gss_pname_to_uid.c,v 1.4 2023/06/19 21:41:43 christos Exp $ */ 2 3 /* 4 * Copyright (c) 2011, PADL Software Pty Ltd. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * 3. Neither the name of PADL Software nor the names of its contributors 19 * may be used to endorse or promote products derived from this software 20 * without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 */ 34 35 #include "mech_locl.h" 36 37 static OM_uint32 38 mech_localname(OM_uint32 *minor_status, 39 struct _gss_mechanism_name *mn, 40 gss_buffer_t localname) 41 { 42 OM_uint32 major_status = GSS_S_UNAVAILABLE; 43 44 *minor_status = 0; 45 46 if (mn->gmn_mech->gm_localname == NULL) 47 return GSS_S_UNAVAILABLE; 48 49 major_status = mn->gmn_mech->gm_localname(minor_status, 50 mn->gmn_name, 51 mn->gmn_mech_oid, 52 localname); 53 if (GSS_ERROR(major_status)) 54 _gss_mg_error(mn->gmn_mech, major_status, *minor_status); 55 56 return major_status; 57 } 58 59 static OM_uint32 60 attr_localname(OM_uint32 *minor_status, 61 struct _gss_mechanism_name *mn, 62 gss_buffer_t localname) 63 { 64 OM_uint32 major_status = GSS_S_UNAVAILABLE; 65 OM_uint32 tmpMinor; 66 gss_buffer_desc value = GSS_C_EMPTY_BUFFER; 67 gss_buffer_desc display_value = GSS_C_EMPTY_BUFFER; 68 int authenticated = 0, complete = 0; 69 int more = -1; 70 71 *minor_status = 0; 72 73 localname->length = 0; 74 localname->value = NULL; 75 76 if (mn->gmn_mech->gm_get_name_attribute == NULL) 77 return GSS_S_UNAVAILABLE; 78 79 major_status = mn->gmn_mech->gm_get_name_attribute(minor_status, 80 mn->gmn_name, 81 GSS_C_ATTR_LOCAL_LOGIN_USER, 82 &authenticated, 83 &complete, 84 &value, 85 &display_value, 86 &more); 87 if (GSS_ERROR(major_status)) { 88 _gss_mg_error(mn->gmn_mech, major_status, *minor_status); 89 return major_status; 90 } 91 92 if (authenticated) { 93 *localname = value; 94 } else { 95 major_status = GSS_S_UNAVAILABLE; 96 gss_release_buffer(&tmpMinor, &value); 97 } 98 99 gss_release_buffer(&tmpMinor, &display_value); 100 101 return major_status; 102 } 103 104 GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL 105 gss_localname(OM_uint32 *minor_status, 106 gss_const_name_t pname, 107 const gss_OID mech_type, 108 gss_buffer_t localname) 109 { 110 OM_uint32 major_status = GSS_S_UNAVAILABLE; 111 struct _gss_name *name = (struct _gss_name *) pname; 112 struct _gss_mechanism_name *mn = NULL; 113 114 *minor_status = 0; 115 116 if (mech_type != GSS_C_NO_OID) { 117 major_status = _gss_find_mn(minor_status, name, mech_type, &mn); 118 if (GSS_ERROR(major_status)) 119 return major_status; 120 121 major_status = mech_localname(minor_status, mn, localname); 122 if (major_status != GSS_S_COMPLETE) 123 major_status = attr_localname(minor_status, mn, localname); 124 } else { 125 HEIM_SLIST_FOREACH(mn, &name->gn_mn, gmn_link) { 126 major_status = mech_localname(minor_status, mn, localname); 127 if (major_status != GSS_S_COMPLETE) 128 major_status = attr_localname(minor_status, mn, localname); 129 if (major_status != GSS_S_UNAVAILABLE) 130 break; 131 } 132 } 133 134 if (major_status != GSS_S_COMPLETE && mn != NULL) 135 _gss_mg_error(mn->gmn_mech, major_status, *minor_status); 136 137 return major_status; 138 } 139 140 141 GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL 142 gss_pname_to_uid(OM_uint32 *minor_status, 143 gss_const_name_t pname, 144 const gss_OID mech_type, 145 uid_t *uidp) 146 { 147 #ifdef NO_LOCALNAME 148 return GSS_S_UNAVAILABLE; 149 #else 150 OM_uint32 major, tmpMinor; 151 gss_buffer_desc localname = GSS_C_EMPTY_BUFFER; 152 char *szLocalname; 153 char pwbuf[2048]; 154 struct passwd pw, *pwd; 155 156 major = gss_localname(minor_status, pname, mech_type, &localname); 157 if (GSS_ERROR(major)) 158 return major; 159 if (localname.length == 0) { 160 *minor_status = KRB5_NO_LOCALNAME; 161 return GSS_S_FAILURE; 162 } 163 164 szLocalname = malloc(localname.length + 1); 165 if (szLocalname == NULL) { 166 gss_release_buffer(&tmpMinor, &localname); 167 *minor_status = ENOMEM; 168 return GSS_S_FAILURE; 169 } 170 171 memcpy(szLocalname, localname.value, localname.length); 172 szLocalname[localname.length] = '\0'; 173 174 if (rk_getpwnam_r(szLocalname, &pw, pwbuf, sizeof(pwbuf), &pwd) != 0) 175 pwd = NULL; 176 177 gss_release_buffer(&tmpMinor, &localname); 178 free(szLocalname); 179 180 *minor_status = 0; 181 182 if (pwd != NULL) { 183 *uidp = pwd->pw_uid; 184 major = GSS_S_COMPLETE; 185 } else { 186 major = GSS_S_UNAVAILABLE; 187 } 188 189 return major; 190 #endif 191 } 192