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