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