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