Merge branch 'vendor/DIFFUTILS'
[dragonfly.git] / lib / libc / rpc / auth_unix.c
1 /*
2  * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
3  * unrestricted use provided that this legend is included on all tape
4  * media and as a part of the software program in whole or part.  Users
5  * may copy or modify Sun RPC without charge, but are not authorized
6  * to license or distribute it to anyone else except as part of a product or
7  * program developed by the user.
8  *
9  * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
10  * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
11  * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
12  *
13  * Sun RPC is provided with no support and without any obligation on the
14  * part of Sun Microsystems, Inc. to assist in its use, correction,
15  * modification or enhancement.
16  *
17  * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
18  * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
19  * OR ANY PART THEREOF.
20  *
21  * In no event will Sun Microsystems, Inc. be liable for any lost revenue
22  * or profits or other special, indirect and consequential damages, even if
23  * Sun has been advised of the possibility of such damages.
24  *
25  * Sun Microsystems, Inc.
26  * 2550 Garcia Avenue
27  * Mountain View, California  94043
28  *
29  * @(#)auth_unix.c      1.19 87/08/11 Copyr 1984 Sun Micro
30  * @(#)auth_unix.c      2.2 88/08/01 4.0 RPCSRC
31  * $NetBSD: auth_unix.c,v 1.18 2000/07/06 03:03:30 christos Exp $
32  * $FreeBSD: src/lib/libc/rpc/auth_unix.c,v 1.18 2007/06/14 20:07:35 harti Exp $
33  */
34
35 /*
36  * auth_unix.c, Implements UNIX style authentication parameters.
37  *
38  * Copyright (C) 1984, Sun Microsystems, Inc.
39  *
40  * The system is very weak.  The client uses no encryption for it's
41  * credentials and only sends null verifiers.  The server sends backs
42  * null verifiers or optionally a verifier that suggests a new short hand
43  * for the credentials.
44  *
45  */
46
47 #include "namespace.h"
48 #include "reentrant.h"
49 #include <sys/param.h>
50
51 #include <assert.h>
52 #include <err.h>
53 #include <stdio.h>
54 #include <stdlib.h>
55 #include <unistd.h>
56 #include <string.h>
57
58 #include <rpc/types.h>
59 #include <rpc/xdr.h>
60 #include <rpc/auth.h>
61 #include <rpc/auth_unix.h>
62 #include "un-namespace.h"
63 #include "mt_misc.h"
64
65 /* auth_unix.c */
66 static void              authunix_destroy(AUTH *);
67 static bool_t            authunix_marshal(AUTH *, XDR *);
68 static void              authunix_nextverf(AUTH *);
69 static struct auth_ops  *authunix_ops(void);
70 static bool_t            authunix_refresh(AUTH *, void *);
71 static bool_t            authunix_validate(AUTH *, struct opaque_auth *);
72 static void              marshal_new_auth(AUTH *);
73
74 /*
75  * This struct is pointed to by the ah_private field of an auth_handle.
76  */
77 struct audata {
78         struct opaque_auth      au_origcred;    /* original credentials */
79         struct opaque_auth      au_shcred;      /* short hand cred */
80         u_long                  au_shfaults;    /* short hand cache faults */
81         char                    au_marshed[MAX_AUTH_BYTES];
82         u_int                   au_mpos;        /* xdr pos at end of marshed */
83 };
84 #define AUTH_PRIVATE(auth)      ((struct audata *)auth->ah_private)
85
86 /*
87  * Create a unix style authenticator.
88  * Returns an auth handle with the given stuff in it.
89  */
90 AUTH *
91 authunix_create(char *machname, int uid, int gid, int len, int *aup_gids)
92 {
93         struct authunix_parms aup;
94         char mymem[MAX_AUTH_BYTES];
95         struct timeval now;
96         XDR xdrs;
97         AUTH *auth;
98         struct audata *au;
99
100         /*
101          * Allocate and set up auth handle
102          */
103         au = NULL;
104         auth = mem_alloc(sizeof(*auth));
105 #ifndef _KERNEL
106         if (auth == NULL) {
107                 warnx("authunix_create: out of memory");
108                 goto cleanup_authunix_create;
109         }
110 #endif
111         au = mem_alloc(sizeof(*au));
112 #ifndef _KERNEL
113         if (au == NULL) {
114                 warnx("authunix_create: out of memory");
115                 goto cleanup_authunix_create;
116         }
117 #endif
118         auth->ah_ops = authunix_ops();
119         auth->ah_private = (caddr_t)au;
120         auth->ah_verf = au->au_shcred = _null_auth;
121         au->au_shfaults = 0;
122         au->au_origcred.oa_base = NULL;
123
124         /*
125          * fill in param struct from the given params
126          */
127         gettimeofday(&now, NULL);
128         aup.aup_time = now.tv_sec;
129         aup.aup_machname = machname;
130         aup.aup_uid = uid;
131         aup.aup_gid = gid;
132         aup.aup_len = (u_int)len;
133         aup.aup_gids = aup_gids;
134
135         /*
136          * Serialize the parameters into origcred
137          */
138         xdrmem_create(&xdrs, mymem, MAX_AUTH_BYTES, XDR_ENCODE);
139         if (! xdr_authunix_parms(&xdrs, &aup))
140                 abort();
141         au->au_origcred.oa_length = len = XDR_GETPOS(&xdrs);
142         au->au_origcred.oa_flavor = AUTH_UNIX;
143 #ifdef _KERNEL
144         au->au_origcred.oa_base = mem_alloc((u_int) len);
145 #else
146         if ((au->au_origcred.oa_base = mem_alloc((u_int) len)) == NULL) {
147                 warnx("authunix_create: out of memory");
148                 goto cleanup_authunix_create;
149         }
150 #endif
151         memmove(au->au_origcred.oa_base, mymem, (size_t)len);
152
153         /*
154          * set auth handle to reflect new cred.
155          */
156         auth->ah_cred = au->au_origcred;
157         marshal_new_auth(auth);
158         return (auth);
159 #ifndef _KERNEL
160  cleanup_authunix_create:
161         if (auth)
162                 mem_free(auth, sizeof(*auth));
163         if (au) {
164                 if (au->au_origcred.oa_base)
165                         mem_free(au->au_origcred.oa_base, (u_int)len);
166                 mem_free(au, sizeof(*au));
167         }
168         return (NULL);
169 #endif
170 }
171
172 /*
173  * Returns an auth handle with parameters determined by doing lots of
174  * syscalls.
175  */
176 AUTH *
177 authunix_create_default(void)
178 {
179         int len;
180         char machname[MAXHOSTNAMELEN + 1];
181         uid_t uid;
182         gid_t gid;
183         gid_t gids[NGROUPS_MAX];
184
185         if (gethostname(machname, sizeof machname) == -1)
186                 abort();
187         machname[sizeof(machname) - 1] = 0;
188         uid = geteuid();
189         gid = getegid();
190         if ((len = getgroups(NGROUPS_MAX, gids)) < 0)
191                 abort();
192         if (len > NGRPS)
193                 len = NGRPS;
194         /* XXX: interface problem; those should all have been unsigned */
195         return (authunix_create(machname, (int)uid, (int)gid, len,
196             (int *)gids));
197 }
198
199 /*
200  * authunix operations
201  */
202
203 /* ARGSUSED */
204 static void
205 authunix_nextverf(AUTH *auth __unused)
206 {
207         /* no action necessary */
208 }
209
210 static bool_t
211 authunix_marshal(AUTH *auth, XDR *xdrs)
212 {
213         struct audata *au;
214
215         assert(auth != NULL);
216         assert(xdrs != NULL);
217
218         au = AUTH_PRIVATE(auth);
219         return (XDR_PUTBYTES(xdrs, au->au_marshed, au->au_mpos));
220 }
221
222 static bool_t
223 authunix_validate(AUTH *auth, struct opaque_auth *verf)
224 {
225         struct audata *au;
226         XDR xdrs;
227
228         assert(auth != NULL);
229         assert(verf != NULL);
230
231         if (verf->oa_flavor == AUTH_SHORT) {
232                 au = AUTH_PRIVATE(auth);
233                 xdrmem_create(&xdrs, verf->oa_base, verf->oa_length,
234                     XDR_DECODE);
235
236                 if (au->au_shcred.oa_base != NULL) {
237                         mem_free(au->au_shcred.oa_base,
238                             au->au_shcred.oa_length);
239                         au->au_shcred.oa_base = NULL;
240                 }
241                 if (xdr_opaque_auth(&xdrs, &au->au_shcred)) {
242                         auth->ah_cred = au->au_shcred;
243                 } else {
244                         xdrs.x_op = XDR_FREE;
245                         xdr_opaque_auth(&xdrs, &au->au_shcred);
246                         au->au_shcred.oa_base = NULL;
247                         auth->ah_cred = au->au_origcred;
248                 }
249                 marshal_new_auth(auth);
250         }
251         return (TRUE);
252 }
253
254 static bool_t
255 authunix_refresh(AUTH *auth, void *dummy __unused)
256 {
257         struct audata *au = AUTH_PRIVATE(auth);
258         struct authunix_parms aup;
259         struct timeval now;
260         XDR xdrs;
261         int stat;
262
263         assert(auth != NULL);
264
265         if (auth->ah_cred.oa_base == au->au_origcred.oa_base) {
266                 /* there is no hope.  Punt */
267                 return (FALSE);
268         }
269         au->au_shfaults ++;
270
271         /* first deserialize the creds back into a struct authunix_parms */
272         aup.aup_machname = NULL;
273         aup.aup_gids = NULL;
274         xdrmem_create(&xdrs, au->au_origcred.oa_base,
275             au->au_origcred.oa_length, XDR_DECODE);
276         stat = xdr_authunix_parms(&xdrs, &aup);
277         if (! stat)
278                 goto done;
279
280         /* update the time and serialize in place */
281         gettimeofday(&now, NULL);
282         aup.aup_time = now.tv_sec;
283         xdrs.x_op = XDR_ENCODE;
284         XDR_SETPOS(&xdrs, 0);
285         stat = xdr_authunix_parms(&xdrs, &aup);
286         if (! stat)
287                 goto done;
288         auth->ah_cred = au->au_origcred;
289         marshal_new_auth(auth);
290 done:
291         /* free the struct authunix_parms created by deserializing */
292         xdrs.x_op = XDR_FREE;
293         xdr_authunix_parms(&xdrs, &aup);
294         XDR_DESTROY(&xdrs);
295         return (stat);
296 }
297
298 static void
299 authunix_destroy(AUTH *auth)
300 {
301         struct audata *au;
302
303         assert(auth != NULL);
304
305         au = AUTH_PRIVATE(auth);
306         mem_free(au->au_origcred.oa_base, au->au_origcred.oa_length);
307
308         if (au->au_shcred.oa_base != NULL)
309                 mem_free(au->au_shcred.oa_base, au->au_shcred.oa_length);
310
311         mem_free(auth->ah_private, sizeof(struct audata));
312
313         if (auth->ah_verf.oa_base != NULL)
314                 mem_free(auth->ah_verf.oa_base, auth->ah_verf.oa_length);
315
316         mem_free(auth, sizeof(*auth));
317 }
318
319 /*
320  * Marshals (pre-serializes) an auth struct.
321  * sets private data, au_marshed and au_mpos
322  */
323 static void
324 marshal_new_auth(AUTH *auth)
325 {
326         XDR     xdr_stream;
327         XDR     *xdrs = &xdr_stream;
328         struct audata *au;
329
330         assert(auth != NULL);
331
332         au = AUTH_PRIVATE(auth);
333         xdrmem_create(xdrs, au->au_marshed, MAX_AUTH_BYTES, XDR_ENCODE);
334         if ((! xdr_opaque_auth(xdrs, &(auth->ah_cred))) ||
335             (! xdr_opaque_auth(xdrs, &(auth->ah_verf))))
336                 warnx("auth_none.c - Fatal marshalling problem");
337         else
338                 au->au_mpos = XDR_GETPOS(xdrs);
339         XDR_DESTROY(xdrs);
340 }
341
342 static struct auth_ops *
343 authunix_ops(void)
344 {
345         static struct auth_ops ops;
346
347         /* VARIABLES PROTECTED BY ops_lock: ops */
348
349         mutex_lock(&ops_lock);
350         if (ops.ah_nextverf == NULL) {
351                 ops.ah_nextverf = authunix_nextverf;
352                 ops.ah_marshal = authunix_marshal;
353                 ops.ah_validate = authunix_validate;
354                 ops.ah_refresh = authunix_refresh;
355                 ops.ah_destroy = authunix_destroy;
356         }
357         mutex_unlock(&ops_lock);
358         return (&ops);
359 }