1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
27 /* All Rights Reserved */
28 /*
29 * Portions of this source code were derived from Berkeley
30 * 4.3 BSD under license from the Regents of the University of
31 * California.
32 */
33
34 /*
35 * auth_sys.c, Implements UNIX (system) style authentication parameters.
36 *
37 * The system is very weak. The client uses no encryption for its
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 #include "mt.h"
44 #include "rpc_mt.h"
45 #include <alloca.h>
46 #include <stdio.h>
47 #include <syslog.h>
48 #include <stdlib.h>
49 #include <unistd.h>
50 #include <string.h>
51 #include <rpc/types.h>
52 #include <rpc/xdr.h>
53 #include <rpc/auth.h>
54 #include <rpc/auth_sys.h>
55 #include <synch.h>
56
57 extern int gethostname(char *, int);
58 extern bool_t xdr_opaque_auth(XDR *, struct opaque_auth *);
59
60 static struct auth_ops *authsys_ops(void);
61
62 /*
63 * This struct is pointed to by the ah_private field of an auth_handle.
64 */
65 struct audata {
66 struct opaque_auth au_origcred; /* original credentials */
67 struct opaque_auth au_shcred; /* short hand cred */
68 uint_t au_shfaults; /* short hand cache faults */
69 char au_marshed[MAX_AUTH_BYTES];
70 uint_t au_mpos; /* xdr pos at end of marshed */
71 };
72 #define AUTH_PRIVATE(auth) ((struct audata *)auth->ah_private)
73
74 static void marshal_new_auth();
75
76 static const char auth_sys_str[] = "%s : %s";
77 static const char authsys_create_str[] = "authsys_create";
78 static const char __no_mem_auth[] = "out of memory";
79
80 /*
81 * Create a (sys) unix style authenticator.
82 * Returns an auth handle with the given stuff in it.
83 */
84 AUTH *
authsys_create(const char * machname,const uid_t uid,const gid_t gid,const int len,const gid_t * aup_gids)85 authsys_create(const char *machname, const uid_t uid, const gid_t gid,
86 const int len, const gid_t *aup_gids)
87 {
88 struct authsys_parms aup;
89 char mymem[MAX_AUTH_BYTES];
90 struct timeval now;
91 XDR xdrs;
92 AUTH *auth;
93 struct audata *au;
94
95 /*
96 * Allocate and set up auth handle
97 */
98 auth = malloc(sizeof (*auth));
99 if (auth == NULL) {
100 (void) syslog(LOG_ERR, auth_sys_str, authsys_create_str,
101 __no_mem_auth);
102 return (NULL);
103 }
104 au = malloc(sizeof (*au));
105 if (au == NULL) {
106 (void) syslog(LOG_ERR, auth_sys_str, authsys_create_str,
107 __no_mem_auth);
108 free(auth);
109 return (NULL);
110 }
111 auth->ah_ops = authsys_ops();
112 auth->ah_private = (caddr_t)au;
113 auth->ah_verf = au->au_shcred = _null_auth;
114 au->au_shfaults = 0;
115
116 /*
117 * fill in param struct from the given params
118 */
119 (void) gettimeofday(&now, (struct timezone *)0);
120 aup.aup_time = now.tv_sec;
121 aup.aup_machname = (char *)machname;
122 aup.aup_uid = uid;
123 aup.aup_gid = gid;
124 aup.aup_len = (uint_t)len;
125 aup.aup_gids = (gid_t *)aup_gids;
126
127 /*
128 * Serialize the parameters into origcred
129 */
130 xdrmem_create(&xdrs, mymem, MAX_AUTH_BYTES, XDR_ENCODE);
131 if (!xdr_authsys_parms(&xdrs, &aup)) {
132 (void) syslog(LOG_ERR, auth_sys_str, authsys_create_str,
133 ": xdr_authsys_parms failed");
134 return (NULL);
135 }
136 au->au_origcred.oa_length = XDR_GETPOS(&xdrs);
137 au->au_origcred.oa_flavor = AUTH_SYS;
138 if ((au->au_origcred.oa_base = malloc(au->au_origcred.oa_length)) ==
139 NULL) {
140 (void) syslog(LOG_ERR, auth_sys_str, authsys_create_str,
141 __no_mem_auth);
142 free(au);
143 free(auth);
144 return (NULL);
145 }
146 (void) memcpy(au->au_origcred.oa_base, mymem,
147 (size_t)au->au_origcred.oa_length);
148
149 /*
150 * set auth handle to reflect new cred.
151 */
152 auth->ah_cred = au->au_origcred;
153 (void) marshal_new_auth(auth);
154 return (auth);
155 }
156
157 /*
158 * authsys_create_default is a public interface.
159 *
160 * Returns an auth handle with parameters determined by doing lots of
161 * syscalls.
162 */
163
164 static const char authsys_def_str[] =
165 "authsys_create_default: get%s failed: %m";
166
167 AUTH *
authsys_create_default(void)168 authsys_create_default(void)
169 {
170 int len;
171 char machname[MAX_MACHINE_NAME + 1];
172 uid_t uid;
173 gid_t gid;
174 int maxgrp = getgroups(0, NULL);
175 gid_t *gids = alloca(maxgrp * sizeof (gid_t));
176
177 if (gethostname(machname, MAX_MACHINE_NAME) == -1) {
178 (void) syslog(LOG_ERR, authsys_def_str, "hostname");
179 return (NULL);
180 }
181 machname[MAX_MACHINE_NAME] = 0;
182 uid = geteuid();
183 gid = getegid();
184 if ((len = getgroups(maxgrp, gids)) < 0) {
185 (void) syslog(LOG_ERR, authsys_def_str, "groups");
186 return (NULL);
187 }
188 if (len > NGRPS)
189 len = NGRPS;
190 return (authsys_create(machname, uid, gid, len, gids));
191 }
192
193 /*
194 * authsys_create_ruid() is a private routine and is a
195 * variant of authsys_create_default().
196 *
197 * authsys_create_default() is using the effective uid.
198 * authsys_create_ruid() is using the real uid.
199 *
200 * This routine is used by key_call_ext() in key_call.c
201 */
202 AUTH *
authsys_create_ruid(void)203 authsys_create_ruid(void)
204 {
205 int len;
206 char machname[MAX_MACHINE_NAME + 1];
207 uid_t uid;
208 gid_t gid;
209 int maxgrp = getgroups(0, NULL);
210 gid_t *gids = alloca(maxgrp * sizeof (gid_t));
211 AUTH *res;
212
213 if (gethostname(machname, MAX_MACHINE_NAME) == -1) {
214 (void) syslog(LOG_ERR,
215 "authsys_create_ruid:gethostname failed");
216 return (NULL);
217 }
218 machname[MAX_MACHINE_NAME] = 0;
219 uid = getuid();
220 gid = getgid();
221 if ((len = getgroups(maxgrp, gids)) < 0) {
222 (void) syslog(LOG_ERR,
223 "authsys_create_ruid:getgroups failed");
224 return (NULL);
225 }
226 if (len > NGRPS)
227 len = NGRPS;
228 res = authsys_create(machname, uid, gid, len, gids);
229 return (res);
230 }
231
232 /*
233 * authsys operations
234 */
235
236 /*ARGSUSED*/
237 static void
authsys_nextverf(AUTH * auth)238 authsys_nextverf(AUTH *auth)
239 {
240 /* no action necessary */
241 }
242
243 static bool_t
authsys_marshal(AUTH * auth,XDR * xdrs)244 authsys_marshal(AUTH *auth, XDR *xdrs)
245 {
246 /* LINTED pointer alignment */
247 struct audata *au = AUTH_PRIVATE(auth);
248
249 return (XDR_PUTBYTES(xdrs, au->au_marshed, au->au_mpos));
250 }
251
252 static bool_t
authsys_validate(AUTH * auth,struct opaque_auth * verf)253 authsys_validate(AUTH *auth, struct opaque_auth *verf)
254 {
255 struct audata *au;
256 XDR xdrs;
257
258 if (verf->oa_flavor == AUTH_SHORT) {
259 /* LINTED pointer alignment */
260 au = AUTH_PRIVATE(auth);
261 xdrmem_create(&xdrs, verf->oa_base,
262 verf->oa_length, XDR_DECODE);
263
264 if (au->au_shcred.oa_base != NULL) {
265 free(au->au_shcred.oa_base);
266 au->au_shcred.oa_base = NULL;
267 }
268 if (xdr_opaque_auth(&xdrs, &au->au_shcred)) {
269 auth->ah_cred = au->au_shcred;
270 } else {
271 xdrs.x_op = XDR_FREE;
272 (void) xdr_opaque_auth(&xdrs, &au->au_shcred);
273 au->au_shcred.oa_base = NULL;
274 auth->ah_cred = au->au_origcred;
275 }
276 (void) marshal_new_auth(auth);
277 }
278 return (TRUE);
279 }
280
281 /*ARGSUSED*/
282 static bool_t
authsys_refresh(AUTH * auth,void * dummy)283 authsys_refresh(AUTH *auth, void *dummy)
284 {
285 /* LINTED pointer alignment */
286 struct audata *au = AUTH_PRIVATE(auth);
287 struct authsys_parms aup;
288 struct timeval now;
289 XDR xdrs;
290 int stat;
291
292 if (auth->ah_cred.oa_base == au->au_origcred.oa_base)
293 return (FALSE); /* there is no hope. Punt */
294 au->au_shfaults ++;
295
296 /* first deserialize the creds back into a struct authsys_parms */
297 aup.aup_machname = NULL;
298 aup.aup_gids = NULL;
299 xdrmem_create(&xdrs, au->au_origcred.oa_base,
300 au->au_origcred.oa_length, XDR_DECODE);
301 stat = xdr_authsys_parms(&xdrs, &aup);
302 if (!stat)
303 goto done;
304
305 /* update the time and serialize in place */
306 (void) gettimeofday(&now, (struct timezone *)0);
307 aup.aup_time = now.tv_sec;
308 xdrs.x_op = XDR_ENCODE;
309 XDR_SETPOS(&xdrs, 0);
310 stat = xdr_authsys_parms(&xdrs, &aup);
311 if (!stat)
312 goto done;
313 auth->ah_cred = au->au_origcred;
314 (void) marshal_new_auth(auth);
315 done:
316 /* free the struct authsys_parms created by deserializing */
317 xdrs.x_op = XDR_FREE;
318 (void) xdr_authsys_parms(&xdrs, &aup);
319 XDR_DESTROY(&xdrs);
320 return (stat);
321 }
322
323 static void
authsys_destroy(AUTH * auth)324 authsys_destroy(AUTH *auth)
325 {
326 /* LINTED pointer alignment */
327 struct audata *au = AUTH_PRIVATE(auth);
328
329 free(au->au_origcred.oa_base);
330 if (au->au_shcred.oa_base != NULL)
331 free(au->au_shcred.oa_base);
332 free(auth->ah_private);
333 if (auth->ah_verf.oa_base != NULL)
334 free(auth->ah_verf.oa_base);
335 free(auth);
336 }
337
338 /*
339 * Marshals (pre-serializes) an auth struct.
340 * sets private data, au_marshed and au_mpos
341 */
342
343 static const char marshal_new_auth_str[] =
344 "marshal_new_auth - Fatal marshalling problem";
345 static void
marshal_new_auth(AUTH * auth)346 marshal_new_auth(AUTH *auth)
347 {
348 XDR xdr_stream;
349 XDR *xdrs = &xdr_stream;
350 /* LINTED pointer alignment */
351 struct audata *au = AUTH_PRIVATE(auth);
352
353 xdrmem_create(xdrs, au->au_marshed, MAX_AUTH_BYTES, XDR_ENCODE);
354 if ((!xdr_opaque_auth(xdrs, &(auth->ah_cred))) ||
355 (!xdr_opaque_auth(xdrs, &(auth->ah_verf)))) {
356 (void) syslog(LOG_ERR, marshal_new_auth_str);
357 } else {
358 au->au_mpos = XDR_GETPOS(xdrs);
359 }
360 XDR_DESTROY(xdrs);
361 }
362
363 static struct auth_ops *
authsys_ops(void)364 authsys_ops(void)
365 {
366 static struct auth_ops ops;
367 extern mutex_t ops_lock;
368
369 /* VARIABLES PROTECTED BY ops_lock: ops */
370
371 (void) mutex_lock(&ops_lock);
372 if (ops.ah_nextverf == NULL) {
373 ops.ah_nextverf = authsys_nextverf;
374 ops.ah_marshal = authsys_marshal;
375 ops.ah_validate = authsys_validate;
376 ops.ah_refresh = authsys_refresh;
377 ops.ah_destroy = authsys_destroy;
378 }
379 (void) mutex_unlock(&ops_lock);
380 return (&ops);
381 }
382