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 * 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 * 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 * 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 238 authsys_nextverf(AUTH *auth) 239 { 240 /* no action necessary */ 241 } 242 243 static bool_t 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 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 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 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 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 * 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