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