auth_unix.c revision 1.22.8.2 1 1.22.8.2 yamt /* $NetBSD: auth_unix.c,v 1.22.8.2 2014/05/22 11:36:53 yamt Exp $ */
2 1.2 cgd
3 1.1 cgd /*
4 1.22.8.2 yamt * Copyright (c) 2010, Oracle America, Inc.
5 1.1 cgd *
6 1.22.8.2 yamt * Redistribution and use in source and binary forms, with or without
7 1.22.8.2 yamt * modification, are permitted provided that the following conditions are
8 1.22.8.2 yamt * met:
9 1.22.8.2 yamt *
10 1.22.8.2 yamt * * Redistributions of source code must retain the above copyright
11 1.22.8.2 yamt * notice, this list of conditions and the following disclaimer.
12 1.22.8.2 yamt * * Redistributions in binary form must reproduce the above
13 1.22.8.2 yamt * copyright notice, this list of conditions and the following
14 1.22.8.2 yamt * disclaimer in the documentation and/or other materials
15 1.22.8.2 yamt * provided with the distribution.
16 1.22.8.2 yamt * * Neither the name of the "Oracle America, Inc." nor the names of its
17 1.22.8.2 yamt * contributors may be used to endorse or promote products derived
18 1.22.8.2 yamt * from this software without specific prior written permission.
19 1.22.8.2 yamt *
20 1.22.8.2 yamt * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 1.22.8.2 yamt * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 1.22.8.2 yamt * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 1.22.8.2 yamt * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 1.22.8.2 yamt * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
25 1.22.8.2 yamt * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 1.22.8.2 yamt * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
27 1.22.8.2 yamt * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 1.22.8.2 yamt * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29 1.22.8.2 yamt * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30 1.22.8.2 yamt * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 1.22.8.2 yamt * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 1.1 cgd */
33 1.1 cgd
34 1.5 christos #include <sys/cdefs.h>
35 1.1 cgd #if defined(LIBC_SCCS) && !defined(lint)
36 1.5 christos #if 0
37 1.5 christos static char *sccsid = "@(#)auth_unix.c 1.19 87/08/11 Copyr 1984 Sun Micro";
38 1.5 christos static char *sccsid = "@(#)auth_unix.c 2.2 88/08/01 4.0 RPCSRC";
39 1.5 christos #else
40 1.22.8.2 yamt __RCSID("$NetBSD: auth_unix.c,v 1.22.8.2 2014/05/22 11:36:53 yamt Exp $");
41 1.5 christos #endif
42 1.1 cgd #endif
43 1.1 cgd
44 1.1 cgd /*
45 1.1 cgd * auth_unix.c, Implements UNIX style authentication parameters.
46 1.1 cgd *
47 1.1 cgd * Copyright (C) 1984, Sun Microsystems, Inc.
48 1.1 cgd *
49 1.1 cgd * The system is very weak. The client uses no encryption for it's
50 1.1 cgd * credentials and only sends null verifiers. The server sends backs
51 1.9 lukem * null verifiers or optionally a verifier that suggests a new short hand
52 1.1 cgd * for the credentials.
53 1.1 cgd *
54 1.1 cgd */
55 1.1 cgd
56 1.6 jtc #include "namespace.h"
57 1.17 fvdl #include "reentrant.h"
58 1.11 mrg #include <sys/param.h>
59 1.11 mrg
60 1.15 lukem #include <assert.h>
61 1.10 lukem #include <err.h>
62 1.1 cgd #include <stdio.h>
63 1.1 cgd #include <stdlib.h>
64 1.4 cgd #include <string.h>
65 1.4 cgd #include <unistd.h>
66 1.1 cgd
67 1.1 cgd #include <rpc/types.h>
68 1.1 cgd #include <rpc/xdr.h>
69 1.1 cgd #include <rpc/auth.h>
70 1.1 cgd #include <rpc/auth_unix.h>
71 1.6 jtc
72 1.6 jtc #ifdef __weak_alias
73 1.16 mycroft __weak_alias(authunix_create,_authunix_create)
74 1.16 mycroft __weak_alias(authunix_create_default,_authunix_create_default)
75 1.6 jtc #endif
76 1.1 cgd
77 1.5 christos
78 1.5 christos /* auth_unix.c */
79 1.22.8.1 yamt static void authunix_nextverf(AUTH *);
80 1.22.8.1 yamt static bool_t authunix_marshal(AUTH *, XDR *);
81 1.22.8.1 yamt static bool_t authunix_validate(AUTH *, struct opaque_auth *);
82 1.22.8.1 yamt static bool_t authunix_refresh(AUTH *);
83 1.22.8.1 yamt static void authunix_destroy(AUTH *);
84 1.22.8.1 yamt static void marshal_new_auth(AUTH *);
85 1.22.8.1 yamt static const struct auth_ops *authunix_ops(void);
86 1.1 cgd
87 1.1 cgd /*
88 1.1 cgd * This struct is pointed to by the ah_private field of an auth_handle.
89 1.1 cgd */
90 1.1 cgd struct audata {
91 1.1 cgd struct opaque_auth au_origcred; /* original credentials */
92 1.9 lukem struct opaque_auth au_shcred; /* short hand cred */
93 1.9 lukem u_long au_shfaults; /* short hand cache faults */
94 1.1 cgd char au_marshed[MAX_AUTH_BYTES];
95 1.9 lukem u_int au_mpos; /* xdr pos at end of marshed */
96 1.1 cgd };
97 1.1 cgd #define AUTH_PRIVATE(auth) ((struct audata *)auth->ah_private)
98 1.1 cgd
99 1.1 cgd /*
100 1.1 cgd * Create a unix style authenticator.
101 1.1 cgd * Returns an auth handle with the given stuff in it.
102 1.1 cgd */
103 1.1 cgd AUTH *
104 1.22.8.1 yamt authunix_create(char *machname, int uid, int gid, int len, int *aup_gids)
105 1.1 cgd {
106 1.1 cgd struct authunix_parms aup;
107 1.1 cgd char mymem[MAX_AUTH_BYTES];
108 1.1 cgd struct timeval now;
109 1.1 cgd XDR xdrs;
110 1.10 lukem AUTH *auth;
111 1.10 lukem struct audata *au;
112 1.1 cgd
113 1.1 cgd /*
114 1.1 cgd * Allocate and set up auth handle
115 1.1 cgd */
116 1.14 lukem au = NULL;
117 1.18 christos auth = mem_alloc(sizeof(*auth));
118 1.1 cgd #ifndef KERNEL
119 1.1 cgd if (auth == NULL) {
120 1.22.8.2 yamt warn("%s: out of memory", __func__);
121 1.14 lukem goto cleanup_authunix_create;
122 1.1 cgd }
123 1.1 cgd #endif
124 1.18 christos au = mem_alloc(sizeof(*au));
125 1.1 cgd #ifndef KERNEL
126 1.1 cgd if (au == NULL) {
127 1.22.8.2 yamt warn("%s: out of memory", __func__);
128 1.14 lukem goto cleanup_authunix_create;
129 1.1 cgd }
130 1.1 cgd #endif
131 1.17 fvdl auth->ah_ops = authunix_ops();
132 1.13 christos auth->ah_private = au;
133 1.1 cgd auth->ah_verf = au->au_shcred = _null_auth;
134 1.1 cgd au->au_shfaults = 0;
135 1.14 lukem au->au_origcred.oa_base = NULL;
136 1.1 cgd
137 1.1 cgd /*
138 1.1 cgd * fill in param struct from the given params
139 1.1 cgd */
140 1.18 christos (void)gettimeofday(&now, NULL);
141 1.22 christos aup.aup_time = (u_long)now.tv_sec; /* XXX: truncate on 32 bit */
142 1.9 lukem aup.aup_machname = machname;
143 1.1 cgd aup.aup_uid = uid;
144 1.1 cgd aup.aup_gid = gid;
145 1.9 lukem aup.aup_len = (u_int)len;
146 1.9 lukem aup.aup_gids = aup_gids;
147 1.1 cgd
148 1.1 cgd /*
149 1.1 cgd * Serialize the parameters into origcred
150 1.1 cgd */
151 1.1 cgd xdrmem_create(&xdrs, mymem, MAX_AUTH_BYTES, XDR_ENCODE);
152 1.1 cgd if (! xdr_authunix_parms(&xdrs, &aup))
153 1.1 cgd abort();
154 1.9 lukem au->au_origcred.oa_length = len = XDR_GETPOS(&xdrs);
155 1.1 cgd au->au_origcred.oa_flavor = AUTH_UNIX;
156 1.1 cgd #ifdef KERNEL
157 1.21 christos au->au_origcred.oa_base = mem_alloc((size_t)len);
158 1.1 cgd #else
159 1.21 christos if ((au->au_origcred.oa_base = mem_alloc((size_t)len)) == NULL) {
160 1.22.8.2 yamt warn("%s: out of memory", __func__);
161 1.14 lukem goto cleanup_authunix_create;
162 1.1 cgd }
163 1.1 cgd #endif
164 1.10 lukem memmove(au->au_origcred.oa_base, mymem, (size_t)len);
165 1.1 cgd
166 1.1 cgd /*
167 1.1 cgd * set auth handle to reflect new cred.
168 1.1 cgd */
169 1.1 cgd auth->ah_cred = au->au_origcred;
170 1.1 cgd marshal_new_auth(auth);
171 1.1 cgd return (auth);
172 1.14 lukem #ifndef KERNEL
173 1.14 lukem cleanup_authunix_create:
174 1.14 lukem if (auth)
175 1.14 lukem mem_free(auth, sizeof(*auth));
176 1.14 lukem if (au) {
177 1.14 lukem if (au->au_origcred.oa_base)
178 1.14 lukem mem_free(au->au_origcred.oa_base, (u_int)len);
179 1.14 lukem mem_free(au, sizeof(*au));
180 1.14 lukem }
181 1.14 lukem return (NULL);
182 1.14 lukem #endif
183 1.1 cgd }
184 1.1 cgd
185 1.1 cgd /*
186 1.1 cgd * Returns an auth handle with parameters determined by doing lots of
187 1.1 cgd * syscalls.
188 1.1 cgd */
189 1.1 cgd AUTH *
190 1.22.8.1 yamt authunix_create_default(void)
191 1.1 cgd {
192 1.10 lukem int len;
193 1.11 mrg char machname[MAXHOSTNAMELEN + 1];
194 1.13 christos uid_t uid;
195 1.13 christos gid_t gid;
196 1.13 christos gid_t gids[NGRPS];
197 1.1 cgd
198 1.11 mrg if (gethostname(machname, sizeof machname) == -1)
199 1.1 cgd abort();
200 1.11 mrg machname[sizeof(machname) - 1] = 0;
201 1.1 cgd uid = geteuid();
202 1.1 cgd gid = getegid();
203 1.1 cgd if ((len = getgroups(NGRPS, gids)) < 0)
204 1.1 cgd abort();
205 1.13 christos /* XXX: interface problem; those should all have been unsigned */
206 1.13 christos return (authunix_create(machname, (int)uid, (int)gid, len,
207 1.13 christos (int *)gids));
208 1.1 cgd }
209 1.1 cgd
210 1.1 cgd /*
211 1.1 cgd * authunix operations
212 1.1 cgd */
213 1.1 cgd
214 1.13 christos /* ARGSUSED */
215 1.1 cgd static void
216 1.22.8.1 yamt authunix_nextverf(AUTH *auth)
217 1.1 cgd {
218 1.1 cgd /* no action necessary */
219 1.1 cgd }
220 1.1 cgd
221 1.1 cgd static bool_t
222 1.22.8.1 yamt authunix_marshal(AUTH *auth, XDR *xdrs)
223 1.1 cgd {
224 1.15 lukem struct audata *au;
225 1.15 lukem
226 1.15 lukem _DIAGASSERT(auth != NULL);
227 1.15 lukem _DIAGASSERT(xdrs != NULL);
228 1.1 cgd
229 1.15 lukem au = AUTH_PRIVATE(auth);
230 1.1 cgd return (XDR_PUTBYTES(xdrs, au->au_marshed, au->au_mpos));
231 1.1 cgd }
232 1.1 cgd
233 1.1 cgd static bool_t
234 1.22.8.1 yamt authunix_validate(AUTH *auth, struct opaque_auth *verf)
235 1.1 cgd {
236 1.10 lukem struct audata *au;
237 1.1 cgd XDR xdrs;
238 1.1 cgd
239 1.15 lukem _DIAGASSERT(auth != NULL);
240 1.15 lukem _DIAGASSERT(verf != NULL);
241 1.15 lukem
242 1.5 christos if (verf->oa_flavor == AUTH_SHORT) {
243 1.1 cgd au = AUTH_PRIVATE(auth);
244 1.14 lukem xdrmem_create(&xdrs, verf->oa_base, verf->oa_length,
245 1.14 lukem XDR_DECODE);
246 1.1 cgd
247 1.1 cgd if (au->au_shcred.oa_base != NULL) {
248 1.1 cgd mem_free(au->au_shcred.oa_base,
249 1.1 cgd au->au_shcred.oa_length);
250 1.1 cgd au->au_shcred.oa_base = NULL;
251 1.1 cgd }
252 1.1 cgd if (xdr_opaque_auth(&xdrs, &au->au_shcred)) {
253 1.1 cgd auth->ah_cred = au->au_shcred;
254 1.1 cgd } else {
255 1.1 cgd xdrs.x_op = XDR_FREE;
256 1.1 cgd (void)xdr_opaque_auth(&xdrs, &au->au_shcred);
257 1.1 cgd au->au_shcred.oa_base = NULL;
258 1.1 cgd auth->ah_cred = au->au_origcred;
259 1.1 cgd }
260 1.1 cgd marshal_new_auth(auth);
261 1.1 cgd }
262 1.1 cgd return (TRUE);
263 1.1 cgd }
264 1.1 cgd
265 1.1 cgd static bool_t
266 1.22.8.1 yamt authunix_refresh(AUTH *auth)
267 1.1 cgd {
268 1.10 lukem struct audata *au = AUTH_PRIVATE(auth);
269 1.1 cgd struct authunix_parms aup;
270 1.1 cgd struct timeval now;
271 1.1 cgd XDR xdrs;
272 1.10 lukem int stat;
273 1.1 cgd
274 1.15 lukem _DIAGASSERT(auth != NULL);
275 1.15 lukem
276 1.1 cgd if (auth->ah_cred.oa_base == au->au_origcred.oa_base) {
277 1.1 cgd /* there is no hope. Punt */
278 1.1 cgd return (FALSE);
279 1.1 cgd }
280 1.20 simonb au->au_shfaults++;
281 1.1 cgd
282 1.1 cgd /* first deserialize the creds back into a struct authunix_parms */
283 1.1 cgd aup.aup_machname = NULL;
284 1.18 christos aup.aup_gids = NULL;
285 1.1 cgd xdrmem_create(&xdrs, au->au_origcred.oa_base,
286 1.1 cgd au->au_origcred.oa_length, XDR_DECODE);
287 1.1 cgd stat = xdr_authunix_parms(&xdrs, &aup);
288 1.1 cgd if (! stat)
289 1.1 cgd goto done;
290 1.1 cgd
291 1.1 cgd /* update the time and serialize in place */
292 1.18 christos (void)gettimeofday(&now, NULL);
293 1.22 christos aup.aup_time = (u_long)now.tv_sec; /* XXX: truncate on 32 bit */
294 1.1 cgd xdrs.x_op = XDR_ENCODE;
295 1.1 cgd XDR_SETPOS(&xdrs, 0);
296 1.1 cgd stat = xdr_authunix_parms(&xdrs, &aup);
297 1.1 cgd if (! stat)
298 1.1 cgd goto done;
299 1.1 cgd auth->ah_cred = au->au_origcred;
300 1.1 cgd marshal_new_auth(auth);
301 1.1 cgd done:
302 1.1 cgd /* free the struct authunix_parms created by deserializing */
303 1.1 cgd xdrs.x_op = XDR_FREE;
304 1.1 cgd (void)xdr_authunix_parms(&xdrs, &aup);
305 1.1 cgd XDR_DESTROY(&xdrs);
306 1.1 cgd return (stat);
307 1.1 cgd }
308 1.1 cgd
309 1.1 cgd static void
310 1.22.8.1 yamt authunix_destroy(AUTH *auth)
311 1.1 cgd {
312 1.15 lukem struct audata *au;
313 1.15 lukem
314 1.15 lukem _DIAGASSERT(auth != NULL);
315 1.1 cgd
316 1.15 lukem au = AUTH_PRIVATE(auth);
317 1.1 cgd mem_free(au->au_origcred.oa_base, au->au_origcred.oa_length);
318 1.1 cgd
319 1.1 cgd if (au->au_shcred.oa_base != NULL)
320 1.1 cgd mem_free(au->au_shcred.oa_base, au->au_shcred.oa_length);
321 1.1 cgd
322 1.1 cgd mem_free(auth->ah_private, sizeof(struct audata));
323 1.1 cgd
324 1.1 cgd if (auth->ah_verf.oa_base != NULL)
325 1.1 cgd mem_free(auth->ah_verf.oa_base, auth->ah_verf.oa_length);
326 1.1 cgd
327 1.13 christos mem_free(auth, sizeof(*auth));
328 1.1 cgd }
329 1.1 cgd
330 1.1 cgd /*
331 1.1 cgd * Marshals (pre-serializes) an auth struct.
332 1.1 cgd * sets private data, au_marshed and au_mpos
333 1.1 cgd */
334 1.3 jtc static void
335 1.22.8.1 yamt marshal_new_auth(AUTH *auth)
336 1.1 cgd {
337 1.10 lukem XDR xdr_stream;
338 1.10 lukem XDR *xdrs = &xdr_stream;
339 1.15 lukem struct audata *au;
340 1.15 lukem
341 1.15 lukem _DIAGASSERT(auth != NULL);
342 1.1 cgd
343 1.15 lukem au = AUTH_PRIVATE(auth);
344 1.1 cgd xdrmem_create(xdrs, au->au_marshed, MAX_AUTH_BYTES, XDR_ENCODE);
345 1.1 cgd if ((! xdr_opaque_auth(xdrs, &(auth->ah_cred))) ||
346 1.10 lukem (! xdr_opaque_auth(xdrs, &(auth->ah_verf))))
347 1.22.8.2 yamt warnx("%s: Fatal marshalling problem", __func__);
348 1.10 lukem else
349 1.1 cgd au->au_mpos = XDR_GETPOS(xdrs);
350 1.1 cgd XDR_DESTROY(xdrs);
351 1.17 fvdl }
352 1.17 fvdl
353 1.17 fvdl static const struct auth_ops *
354 1.22.8.1 yamt authunix_ops(void)
355 1.17 fvdl {
356 1.17 fvdl static struct auth_ops ops;
357 1.19 thorpej #ifdef _REENTRANT
358 1.17 fvdl extern mutex_t ops_lock;
359 1.17 fvdl #endif
360 1.17 fvdl
361 1.17 fvdl /* VARIABLES PROTECTED BY ops_lock: ops */
362 1.17 fvdl
363 1.17 fvdl mutex_lock(&ops_lock);
364 1.17 fvdl if (ops.ah_nextverf == NULL) {
365 1.17 fvdl ops.ah_nextverf = authunix_nextverf;
366 1.17 fvdl ops.ah_marshal = authunix_marshal;
367 1.17 fvdl ops.ah_validate = authunix_validate;
368 1.17 fvdl ops.ah_refresh = authunix_refresh;
369 1.17 fvdl ops.ah_destroy = authunix_destroy;
370 1.17 fvdl }
371 1.17 fvdl mutex_unlock(&ops_lock);
372 1.17 fvdl return (&ops);
373 1.1 cgd }
374