1 /* $OpenBSD: auth_unix.c,v 1.30 2022/02/14 03:38:59 guenther Exp $ */
2
3 /*
4 * Copyright (c) 2010, Oracle America, Inc.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above
13 * copyright notice, this list of conditions and the following
14 * disclaimer in the documentation and/or other materials
15 * provided with the distribution.
16 * * Neither the name of the "Oracle America, Inc." nor the names of its
17 * contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
25 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
27 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 */
33
34 /*
35 * auth_unix.c, Implements UNIX style authentication parameters.
36 *
37 * The system is very weak. The client uses no encryption for its
38 * credentials and only sends null verifiers. The server sends backs
39 * null verifiers or optionally a verifier that suggests a new short hand
40 * for the credentials.
41 *
42 */
43
44 #include <stdio.h>
45 #include <stdlib.h>
46 #include <unistd.h>
47 #include <string.h>
48
49 #include <rpc/types.h>
50 #include <rpc/xdr.h>
51 #include <rpc/rpc.h>
52 #include <rpc/auth.h>
53 #include <rpc/auth_unix.h>
54
55 /*
56 * Unix authenticator operations vector
57 */
58 static void authunix_nextverf(struct __rpc_auth *);
59 static bool_t authunix_marshal(struct __rpc_auth *, XDR *);
60 static bool_t authunix_validate(struct __rpc_auth *, struct opaque_auth *);
61 static bool_t authunix_refresh(struct __rpc_auth *);
62 static void authunix_destroy(struct __rpc_auth *);
63
64 static const struct auth_ops auth_unix_ops = {
65 authunix_nextverf,
66 authunix_marshal,
67 authunix_validate,
68 authunix_refresh,
69 authunix_destroy
70 };
71
72 /*
73 * This struct is pointed to by the ah_private field of an auth_handle.
74 */
75 struct audata {
76 struct opaque_auth au_origcred; /* original credentials */
77 struct opaque_auth au_shcred; /* short hand cred */
78 u_long au_shfaults; /* short hand cache faults */
79 char au_marshed[MAX_AUTH_BYTES];
80 u_int au_mpos; /* xdr pos at end of marshed */
81 };
82 #define AUTH_PRIVATE(auth) ((struct audata *)auth->ah_private)
83
84 static void marshal_new_auth(AUTH *auth);
85
86
87 /*
88 * Create a unix style authenticator.
89 * Returns an auth handle with the given stuff in it.
90 */
91 AUTH *
authunix_create(char * machname,int uid,int gid,int len,int * aup_gids)92 authunix_create(char *machname, int uid, int gid, int len, int *aup_gids)
93 {
94 struct authunix_parms aup;
95 char mymem[MAX_AUTH_BYTES];
96 struct timeval now;
97 XDR xdrs;
98 AUTH *auth;
99 struct audata *au;
100
101 /*
102 * Allocate and set up auth handle
103 */
104 auth = (AUTH *)mem_alloc(sizeof(*auth));
105 #ifndef KERNEL
106 if (auth == NULL)
107 return (NULL);
108 #endif
109 au = (struct audata *)mem_alloc(sizeof(*au));
110 #ifndef KERNEL
111 if (au == NULL) {
112 free(auth);
113 return (NULL);
114 }
115 #endif
116 auth->ah_ops = &auth_unix_ops;
117 auth->ah_private = (caddr_t)au;
118 auth->ah_verf = au->au_shcred = _null_auth;
119 au->au_shfaults = 0;
120
121 /*
122 * fill in param struct from the given params
123 */
124 (void)WRAP(gettimeofday)(&now, NULL);
125 aup.aup_time = now.tv_sec;
126 aup.aup_machname = machname;
127 aup.aup_uid = uid;
128 aup.aup_gid = gid;
129 aup.aup_len = (u_int)len;
130 aup.aup_gids = aup_gids;
131
132 /*
133 * Serialize the parameters into origcred
134 */
135 xdrmem_create(&xdrs, mymem, MAX_AUTH_BYTES, XDR_ENCODE);
136 if (!xdr_authunix_parms(&xdrs, &aup))
137 goto authfail;
138 au->au_origcred.oa_length = len = XDR_GETPOS(&xdrs);
139 au->au_origcred.oa_flavor = AUTH_UNIX;
140 #ifdef KERNEL
141 au->au_origcred.oa_base = mem_alloc((u_int) len);
142 #else
143 if ((au->au_origcred.oa_base = mem_alloc((u_int) len)) == NULL)
144 goto authfail;
145 #endif
146 memcpy(au->au_origcred.oa_base, mymem, (u_int)len);
147
148 /*
149 * set auth handle to reflect new cred.
150 */
151 auth->ah_cred = au->au_origcred;
152 marshal_new_auth(auth);
153 return (auth);
154
155 authfail:
156 XDR_DESTROY(&xdrs);
157 free(au);
158 free(auth);
159 return (NULL);
160 }
161 DEF_WEAK(authunix_create);
162
163
164 /*
165 * Some servers will refuse mounts if the group list is larger
166 * than it expects (like 8). This allows the application to set
167 * the maximum size of the group list that will be sent.
168 */
169 static int maxgrplist = NGRPS;
170
171 void
set_rpc_maxgrouplist(int num)172 set_rpc_maxgrouplist(int num)
173 {
174 if (num < NGRPS)
175 maxgrplist = num;
176 }
177
178 /*
179 * Returns an auth handle with parameters determined by doing lots of
180 * syscalls.
181 */
182 AUTH *
authunix_create_default(void)183 authunix_create_default(void)
184 {
185 int len, i;
186 char machname[MAX_MACHINE_NAME + 1];
187 uid_t uid;
188 gid_t gid;
189 gid_t gids[NGRPS];
190 int gids2[NGRPS];
191
192 if (gethostname(machname, sizeof machname) == -1)
193 return (NULL);
194 machname[MAX_MACHINE_NAME] = 0;
195 uid = geteuid();
196 gid = getegid();
197 if ((len = getgroups(NGRPS, gids)) == -1)
198 return (NULL);
199 if (len > maxgrplist)
200 len = maxgrplist;
201 for (i = 0; i < len; i++)
202 gids2[i] = gids[i];
203 return (authunix_create(machname, uid, gid, len, gids2));
204 }
205 DEF_WEAK(authunix_create_default);
206
207 /*
208 * authunix operations
209 */
210 static void
authunix_nextverf(AUTH * auth)211 authunix_nextverf(AUTH *auth)
212 {
213 /* no action necessary */
214 }
215
216 static bool_t
authunix_marshal(AUTH * auth,XDR * xdrs)217 authunix_marshal(AUTH *auth, XDR *xdrs)
218 {
219 struct audata *au = AUTH_PRIVATE(auth);
220
221 return (XDR_PUTBYTES(xdrs, au->au_marshed, au->au_mpos));
222 }
223
224 static bool_t
authunix_validate(AUTH * auth,struct opaque_auth * verf)225 authunix_validate(AUTH *auth, struct opaque_auth *verf)
226 {
227 struct audata *au;
228 XDR xdrs;
229
230 if (verf->oa_flavor == AUTH_SHORT) {
231 au = AUTH_PRIVATE(auth);
232 xdrmem_create(&xdrs, verf->oa_base, verf->oa_length, XDR_DECODE);
233
234 if (au->au_shcred.oa_base != NULL) {
235 mem_free(au->au_shcred.oa_base,
236 au->au_shcred.oa_length);
237 au->au_shcred.oa_base = NULL;
238 }
239 if (xdr_opaque_auth(&xdrs, &au->au_shcred)) {
240 auth->ah_cred = au->au_shcred;
241 } else {
242 xdrs.x_op = XDR_FREE;
243 (void)xdr_opaque_auth(&xdrs, &au->au_shcred);
244 au->au_shcred.oa_base = NULL;
245 auth->ah_cred = au->au_origcred;
246 }
247 marshal_new_auth(auth);
248 }
249 return (TRUE);
250 }
251
252 static bool_t
authunix_refresh(AUTH * auth)253 authunix_refresh(AUTH *auth)
254 {
255 struct audata *au = AUTH_PRIVATE(auth);
256 struct authunix_parms aup;
257 struct timeval now;
258 XDR xdrs;
259 int stat;
260
261 if (auth->ah_cred.oa_base == au->au_origcred.oa_base) {
262 /* there is no hope. Punt */
263 return (FALSE);
264 }
265 au->au_shfaults ++;
266
267 /* first deserialize the creds back into a struct authunix_parms */
268 aup.aup_machname = NULL;
269 aup.aup_gids = NULL;
270 xdrmem_create(&xdrs, au->au_origcred.oa_base,
271 au->au_origcred.oa_length, XDR_DECODE);
272 stat = xdr_authunix_parms(&xdrs, &aup);
273 if (! stat)
274 goto done;
275
276 /* update the time and serialize in place */
277 (void)WRAP(gettimeofday)(&now, NULL);
278 aup.aup_time = now.tv_sec;
279 xdrs.x_op = XDR_ENCODE;
280 XDR_SETPOS(&xdrs, 0);
281 stat = xdr_authunix_parms(&xdrs, &aup);
282 if (! stat)
283 goto done;
284 auth->ah_cred = au->au_origcred;
285 marshal_new_auth(auth);
286 done:
287 /* free the struct authunix_parms created by deserializing */
288 xdrs.x_op = XDR_FREE;
289 (void)xdr_authunix_parms(&xdrs, &aup);
290 XDR_DESTROY(&xdrs);
291 return (stat);
292 }
293
294 static void
authunix_destroy(AUTH * auth)295 authunix_destroy(AUTH *auth)
296 {
297 struct audata *au = AUTH_PRIVATE(auth);
298
299 mem_free(au->au_origcred.oa_base, au->au_origcred.oa_length);
300
301 if (au->au_shcred.oa_base != NULL)
302 mem_free(au->au_shcred.oa_base, au->au_shcred.oa_length);
303
304 mem_free(auth->ah_private, sizeof(struct audata));
305
306 if (auth->ah_verf.oa_base != NULL)
307 mem_free(auth->ah_verf.oa_base, auth->ah_verf.oa_length);
308
309 mem_free((caddr_t)auth, sizeof(*auth));
310 }
311
312 /*
313 * Marshals (pre-serializes) an auth struct.
314 * sets private data, au_marshed and au_mpos
315 */
316 static void
marshal_new_auth(AUTH * auth)317 marshal_new_auth(AUTH *auth)
318 {
319 XDR xdr_stream;
320 XDR *xdrs = &xdr_stream;
321 struct audata *au = AUTH_PRIVATE(auth);
322
323 xdrmem_create(xdrs, au->au_marshed, MAX_AUTH_BYTES, XDR_ENCODE);
324 if ((! xdr_opaque_auth(xdrs, &(auth->ah_cred))) ||
325 (! xdr_opaque_auth(xdrs, &(auth->ah_verf)))) {
326 /* XXX nothing we can do */
327 } else {
328 au->au_mpos = XDR_GETPOS(xdrs);
329 }
330 XDR_DESTROY(xdrs);
331 }
332