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