xref: /openbsd-src/lib/libc/rpc/auth_unix.c (revision 8d4335cb9be89a0813640b54b89d23507be8c423)
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