xref: /freebsd/crypto/krb5/src/lib/gssapi/mechglue/gssd_pname_to_uid.c (revision 7f2fe78b9dd5f51c821d771b63d2e096f6fd49e9)
1 /* #pragma ident	"@(#)gssd_pname_to_uid.c	1.18	04/02/23 SMI" */
2 /*
3  * Copyright (c) 2011, PADL Software Pty Ltd.
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  *
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * 3. Neither the name of PADL Software nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  */
33 /*
34  * Copyright 1996 by Sun Microsystems, Inc.
35  *
36  * Permission to use, copy, modify, distribute, and sell this software
37  * and its documentation for any purpose is hereby granted without fee,
38  * provided that the above copyright notice appears in all copies and
39  * that both that copyright notice and this permission notice appear in
40  * supporting documentation, and that the name of Sun Microsystems not be used
41  * in advertising or publicity pertaining to distribution of the software
42  * without specific, written prior permission. Sun Microsystems makes no
43  * representations about the suitability of this software for any
44  * purpose.  It is provided "as is" without express or implied warranty.
45  *
46  * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
47  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
48  * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
49  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
50  * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
51  * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
52  * PERFORMANCE OF THIS SOFTWARE.
53  */
54 
55 /*
56  *  glue routines that test the mech id either passed in to
57  *  gss_init_sec_contex() or gss_accept_sec_context() or within the glue
58  *  routine supported version of the security context and then call
59  *  the appropriate underlying mechanism library procedure.
60  *
61  */
62 
63 #include "mglueP.h"
64 
65 #ifndef NO_PASSWORD
66 #include <pwd.h>
67 #endif
68 
69 static OM_uint32
attr_localname(OM_uint32 * minor,const gss_mechanism mech,const gss_name_t mech_name,gss_buffer_t localname)70 attr_localname(OM_uint32 *minor,
71                const gss_mechanism mech,
72                const gss_name_t mech_name,
73                gss_buffer_t localname)
74 {
75     OM_uint32 major = GSS_S_UNAVAILABLE;
76     OM_uint32 tmpMinor;
77     int more = -1;
78     gss_buffer_desc value;
79     gss_buffer_desc display_value;
80     int authenticated = 0, complete = 0;
81 
82     value.value = NULL;
83     display_value.value = NULL;
84     if (mech->gss_get_name_attribute == NULL)
85         return GSS_S_UNAVAILABLE;
86 
87     major = mech->gss_get_name_attribute(minor,
88                                          mech_name,
89                                          GSS_C_ATTR_LOCAL_LOGIN_USER,
90                                          &authenticated,
91                                          &complete,
92                                          &value,
93                                          &display_value,
94                                          &more);
95     if (GSS_ERROR(major)) {
96         map_error(minor, mech);
97         goto cleanup;
98     }
99 
100     if (!authenticated)
101         major = GSS_S_UNAVAILABLE;
102     else {
103         localname->value = value.value;
104         localname->length = value.length;
105         value.value = NULL;
106     }
107 
108 cleanup:
109     if (display_value.value)
110         gss_release_buffer(&tmpMinor, &display_value);
111     if (value.value)
112         gss_release_buffer(&tmpMinor, &value);
113     return major;
114 }
115 
116 OM_uint32 KRB5_CALLCONV
gss_localname(OM_uint32 * minor,const gss_name_t pname,gss_const_OID mech_type,gss_buffer_t localname)117 gss_localname(OM_uint32 *minor,
118               const gss_name_t pname,
119               gss_const_OID mech_type,
120               gss_buffer_t localname)
121 {
122     OM_uint32 major, tmpMinor;
123     gss_mechanism mech;
124     gss_union_name_t unionName;
125     gss_name_t mechName = GSS_C_NO_NAME, mechNameP;
126     gss_OID selected_mech = GSS_C_NO_OID, public_mech;
127 
128     if (localname != GSS_C_NO_BUFFER) {
129 	localname->length = 0;
130 	localname->value = NULL;
131     }
132 
133     if (minor == NULL)
134         return GSS_S_CALL_INACCESSIBLE_WRITE;
135 
136     *minor = 0;
137 
138     if (pname == GSS_C_NO_NAME)
139         return GSS_S_CALL_INACCESSIBLE_READ;
140 
141     if (localname == NULL)
142         return GSS_S_CALL_INACCESSIBLE_WRITE;
143 
144     unionName = (gss_union_name_t)pname;
145 
146     if (mech_type != GSS_C_NO_OID) {
147         major = gssint_select_mech_type(minor, mech_type, &selected_mech);
148         if (major != GSS_S_COMPLETE)
149 	    return major;
150         mech = gssint_get_mechanism(selected_mech);
151     } else
152         mech = gssint_get_mechanism(unionName->mech_type);
153 
154     if (mech == NULL)
155 	return GSS_S_BAD_MECH;
156 
157     /* may need to create a mechanism specific name */
158     if (unionName->mech_type == GSS_C_NO_OID ||
159         (unionName->mech_type != GSS_C_NO_OID &&
160          !g_OID_equal(unionName->mech_type, &mech->mech_type))) {
161         major = gssint_import_internal_name(minor, &mech->mech_type,
162                                             unionName, &mechName);
163         if (GSS_ERROR(major))
164             return major;
165 
166         mechNameP = mechName;
167     } else
168         mechNameP = unionName->mech_name;
169 
170     major = GSS_S_UNAVAILABLE;
171 
172     if (mech->gss_localname != NULL) {
173         public_mech = gssint_get_public_oid(selected_mech);
174         major = mech->gss_localname(minor, mechNameP, public_mech, localname);
175         if (GSS_ERROR(major))
176             map_error(minor, mech);
177     }
178 
179     if (GSS_ERROR(major))
180         major = attr_localname(minor, mech, mechNameP, localname);
181 
182     if (mechName != GSS_C_NO_NAME)
183         gssint_release_internal_name(&tmpMinor, &mech->mech_type, &mechName);
184 
185     return major;
186 }
187 
188 #ifndef _WIN32
189 OM_uint32 KRB5_CALLCONV
gss_pname_to_uid(OM_uint32 * minor,const gss_name_t name,const gss_OID mech_type,uid_t * uidOut)190 gss_pname_to_uid(OM_uint32 *minor,
191                  const gss_name_t name,
192                  const gss_OID mech_type,
193                  uid_t *uidOut)
194 {
195     OM_uint32 major = GSS_S_UNAVAILABLE, tmpminor;
196 #ifndef NO_PASSWORD
197     gss_buffer_desc localname;
198     char pwbuf[BUFSIZ];
199     char *localuser = NULL;
200     struct passwd *pwd = NULL;
201     struct passwd pw;
202     int code = 0;
203 
204     localname.value = NULL;
205     major = gss_localname(minor, name, mech_type, &localname);
206     if (!GSS_ERROR(major) && localname.value) {
207         localuser = malloc(localname.length + 1);
208         if (localuser == NULL)
209             code = ENOMEM;
210         if (code == 0) {
211             memcpy(localuser, localname.value, localname.length);
212             localuser[localname.length] = '\0';
213             code = k5_getpwnam_r(localuser, &pw, pwbuf, sizeof(pwbuf), &pwd);
214         }
215         if ((code == 0) && pwd)
216             *uidOut = pwd->pw_uid;
217         else
218             major = GSS_S_FAILURE;
219     }
220     free(localuser);
221     if (localname.value)
222         gss_release_buffer(&tmpminor, &localname);
223 #endif /*NO_PASSWORD*/
224     return major;
225 }
226 #endif /*_WIN32*/
227