xref: /minix3/crypto/external/bsd/heimdal/dist/lib/gssapi/mech/gss_pname_to_uid.c (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1 /*	$NetBSD: gss_pname_to_uid.c,v 1.1.1.1 2014/04/24 12:45:29 pettai 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
mech_pname_to_uid(OM_uint32 * minor_status,struct _gss_mechanism_name * mn,uid_t * uidp)38 mech_pname_to_uid(OM_uint32 *minor_status,
39                   struct _gss_mechanism_name *mn,
40                   uid_t *uidp)
41 {
42     OM_uint32 major_status = GSS_S_UNAVAILABLE;
43 
44     *minor_status = 0;
45 
46     if (mn->gmn_mech->gm_pname_to_uid == NULL)
47         return GSS_S_UNAVAILABLE;
48 
49     major_status = mn->gmn_mech->gm_pname_to_uid(minor_status,
50                                                  mn->gmn_name,
51                                                  mn->gmn_mech_oid,
52                                                  uidp);
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
attr_pname_to_uid(OM_uint32 * minor_status,struct _gss_mechanism_name * mn,uid_t * uidp)60 attr_pname_to_uid(OM_uint32 *minor_status,
61                   struct _gss_mechanism_name *mn,
62                   uid_t *uidp)
63 {
64 #ifdef NO_LOCALNAME
65     return GSS_S_UNAVAILABLE;
66 #else
67     OM_uint32 major_status = GSS_S_UNAVAILABLE;
68     OM_uint32 tmpMinor;
69     int more = -1;
70 
71     *minor_status = 0;
72 
73     if (mn->gmn_mech->gm_get_name_attribute == NULL)
74         return GSS_S_UNAVAILABLE;
75 
76     while (more != 0) {
77         gss_buffer_desc value;
78         gss_buffer_desc display_value;
79         int authenticated = 0, complete = 0;
80 #ifdef POSIX_GETPWNAM_R
81         char pwbuf[2048];
82         struct passwd pw, *pwd;
83 #else
84         struct passwd *pwd;
85 #endif
86         char *localname;
87 
88         major_status = mn->gmn_mech->gm_get_name_attribute(minor_status,
89                                                            mn->gmn_name,
90                                                            GSS_C_ATTR_LOCAL_LOGIN_USER,
91                                                            &authenticated,
92                                                            &complete,
93                                                            &value,
94                                                            &display_value,
95                                                            &more);
96         if (GSS_ERROR(major_status)) {
97             _gss_mg_error(mn->gmn_mech, major_status, *minor_status);
98             break;
99         }
100 
101         localname = malloc(value.length + 1);
102         if (localname == NULL) {
103             major_status = GSS_S_FAILURE;
104             *minor_status = ENOMEM;
105             break;
106         }
107 
108         memcpy(localname, value.value, value.length);
109         localname[value.length] = '\0';
110 
111 #ifdef POSIX_GETPWNAM_R
112         if (getpwnam_r(localname, &pw, pwbuf, sizeof(pwbuf), &pwd) != 0)
113             pwd = NULL;
114 #else
115         pwd = getpwnam(localname);
116 #endif
117 
118         free(localname);
119         gss_release_buffer(&tmpMinor, &value);
120         gss_release_buffer(&tmpMinor, &display_value);
121 
122         if (pwd != NULL) {
123             *uidp = pwd->pw_uid;
124             major_status = GSS_S_COMPLETE;
125             *minor_status = 0;
126             break;
127         } else
128             major_status = GSS_S_UNAVAILABLE;
129     }
130 
131     return major_status;
132 #endif /* NO_LOCALNAME */
133 }
134 
135 GSSAPI_LIB_FUNCTION OM_uint32 GSSAPI_LIB_CALL
gss_pname_to_uid(OM_uint32 * minor_status,const gss_name_t pname,const gss_OID mech_type,uid_t * uidp)136 gss_pname_to_uid(OM_uint32 *minor_status,
137                  const gss_name_t pname,
138                  const gss_OID mech_type,
139                  uid_t *uidp)
140 {
141     OM_uint32 major_status = GSS_S_UNAVAILABLE;
142     struct _gss_name *name = (struct _gss_name *) pname;
143     struct _gss_mechanism_name *mn = NULL;
144 
145     *minor_status = 0;
146 
147     if (mech_type != GSS_C_NO_OID) {
148         major_status = _gss_find_mn(minor_status, name, mech_type, &mn);
149         if (GSS_ERROR(major_status))
150             return major_status;
151 
152         major_status = mech_pname_to_uid(minor_status, mn, uidp);
153         if (major_status != GSS_S_COMPLETE)
154             major_status = attr_pname_to_uid(minor_status, mn, uidp);
155     } else {
156         HEIM_SLIST_FOREACH(mn, &name->gn_mn, gmn_link) {
157             major_status = mech_pname_to_uid(minor_status, mn, uidp);
158             if (major_status != GSS_S_COMPLETE)
159                 major_status = attr_pname_to_uid(minor_status, mn, uidp);
160             if (major_status != GSS_S_UNAVAILABLE)
161                 break;
162         }
163     }
164 
165     if (major_status != GSS_S_COMPLETE && mn != NULL)
166         _gss_mg_error(mn->gmn_mech, major_status, *minor_status);
167 
168     return major_status;
169 }
170