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