GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: lib/libc/rpc/auth_unix.c Lines: 0 110 0.0 %
Date: 2017-11-07 Branches: 0 44 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: auth_unix.c,v 1.26 2015/11/01 03:45:29 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 it's
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 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 *
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)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
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 *
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)) < 0)
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
211
authunix_nextverf(AUTH *auth)
212
{
213
	/* no action necessary */
214
}
215
216
static bool_t
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
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
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)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
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
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
}