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