1 /* $NetBSD: auth_unix.c,v 1.18 2000/07/06 03:03:30 christos Exp $ */ 2 3 /* 4 * Sun RPC is a product of Sun Microsystems, Inc. and is provided for 5 * unrestricted use provided that this legend is included on all tape 6 * media and as a part of the software program in whole or part. Users 7 * may copy or modify Sun RPC without charge, but are not authorized 8 * to license or distribute it to anyone else except as part of a product or 9 * program developed by the user. 10 * 11 * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE 12 * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR 13 * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. 14 * 15 * Sun RPC is provided with no support and without any obligation on the 16 * part of Sun Microsystems, Inc. to assist in its use, correction, 17 * modification or enhancement. 18 * 19 * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE 20 * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC 21 * OR ANY PART THEREOF. 22 * 23 * In no event will Sun Microsystems, Inc. be liable for any lost revenue 24 * or profits or other special, indirect and consequential damages, even if 25 * Sun has been advised of the possibility of such damages. 26 * 27 * Sun Microsystems, Inc. 28 * 2550 Garcia Avenue 29 * Mountain View, California 94043 30 */ 31 32 #if defined(LIBC_SCCS) && !defined(lint) 33 static char *sccsid2 = "@(#)auth_unix.c 1.19 87/08/11 Copyr 1984 Sun Micro"; 34 static char *sccsid = "@(#)auth_unix.c 2.2 88/08/01 4.0 RPCSRC"; 35 #endif 36 #include <sys/cdefs.h> 37 __FBSDID("$FreeBSD$"); 38 39 /* 40 * auth_unix.c, Implements UNIX style authentication parameters. 41 * 42 * Copyright (C) 1984, Sun Microsystems, Inc. 43 * 44 * The system is very weak. The client uses no encryption for it's 45 * credentials and only sends null verifiers. The server sends backs 46 * null verifiers or optionally a verifier that suggests a new short hand 47 * for the credentials. 48 * 49 */ 50 51 #include "namespace.h" 52 #include "reentrant.h" 53 #include <sys/param.h> 54 55 #include <assert.h> 56 #include <err.h> 57 #include <stdio.h> 58 #include <stdlib.h> 59 #include <unistd.h> 60 #include <string.h> 61 62 #include <rpc/types.h> 63 #include <rpc/xdr.h> 64 #include <rpc/auth.h> 65 #include <rpc/auth_unix.h> 66 #include "un-namespace.h" 67 68 /* auth_unix.c */ 69 static void authunix_nextverf (AUTH *); 70 static bool_t authunix_marshal (AUTH *, XDR *); 71 static bool_t authunix_validate (AUTH *, struct opaque_auth *); 72 static bool_t authunix_refresh (AUTH *, void *); 73 static void authunix_destroy (AUTH *); 74 static void marshal_new_auth (AUTH *); 75 static struct auth_ops *authunix_ops (void); 76 77 /* 78 * This struct is pointed to by the ah_private field of an auth_handle. 79 */ 80 struct audata { 81 struct opaque_auth au_origcred; /* original credentials */ 82 struct opaque_auth au_shcred; /* short hand cred */ 83 u_long au_shfaults; /* short hand cache faults */ 84 char au_marshed[MAX_AUTH_BYTES]; 85 u_int au_mpos; /* xdr pos at end of marshed */ 86 }; 87 #define AUTH_PRIVATE(auth) ((struct audata *)auth->ah_private) 88 89 /* 90 * Create a unix style authenticator. 91 * Returns an auth handle with the given stuff in it. 92 */ 93 AUTH * 94 authunix_create(machname, uid, gid, len, aup_gids) 95 char *machname; 96 int uid; 97 int gid; 98 int len; 99 int *aup_gids; 100 { 101 struct authunix_parms aup; 102 char mymem[MAX_AUTH_BYTES]; 103 struct timeval now; 104 XDR xdrs; 105 AUTH *auth; 106 struct audata *au; 107 108 /* 109 * Allocate and set up auth handle 110 */ 111 au = NULL; 112 auth = mem_alloc(sizeof(*auth)); 113 #ifndef _KERNEL 114 if (auth == NULL) { 115 warnx("authunix_create: out of memory"); 116 goto cleanup_authunix_create; 117 } 118 #endif 119 au = mem_alloc(sizeof(*au)); 120 #ifndef _KERNEL 121 if (au == NULL) { 122 warnx("authunix_create: out of memory"); 123 goto cleanup_authunix_create; 124 } 125 #endif 126 auth->ah_ops = authunix_ops(); 127 auth->ah_private = (caddr_t)au; 128 auth->ah_verf = au->au_shcred = _null_auth; 129 au->au_shfaults = 0; 130 au->au_origcred.oa_base = NULL; 131 132 /* 133 * fill in param struct from the given params 134 */ 135 (void)gettimeofday(&now, NULL); 136 aup.aup_time = now.tv_sec; 137 aup.aup_machname = machname; 138 aup.aup_uid = uid; 139 aup.aup_gid = gid; 140 aup.aup_len = (u_int)len; 141 aup.aup_gids = aup_gids; 142 143 /* 144 * Serialize the parameters into origcred 145 */ 146 xdrmem_create(&xdrs, mymem, MAX_AUTH_BYTES, XDR_ENCODE); 147 if (! xdr_authunix_parms(&xdrs, &aup)) 148 abort(); 149 au->au_origcred.oa_length = len = XDR_GETPOS(&xdrs); 150 au->au_origcred.oa_flavor = AUTH_UNIX; 151 #ifdef _KERNEL 152 au->au_origcred.oa_base = mem_alloc((u_int) len); 153 #else 154 if ((au->au_origcred.oa_base = mem_alloc((u_int) len)) == NULL) { 155 warnx("authunix_create: out of memory"); 156 goto cleanup_authunix_create; 157 } 158 #endif 159 memmove(au->au_origcred.oa_base, mymem, (size_t)len); 160 161 /* 162 * set auth handle to reflect new cred. 163 */ 164 auth->ah_cred = au->au_origcred; 165 marshal_new_auth(auth); 166 return (auth); 167 #ifndef _KERNEL 168 cleanup_authunix_create: 169 if (auth) 170 mem_free(auth, sizeof(*auth)); 171 if (au) { 172 if (au->au_origcred.oa_base) 173 mem_free(au->au_origcred.oa_base, (u_int)len); 174 mem_free(au, sizeof(*au)); 175 } 176 return (NULL); 177 #endif 178 } 179 180 /* 181 * Returns an auth handle with parameters determined by doing lots of 182 * syscalls. 183 */ 184 AUTH * 185 authunix_create_default() 186 { 187 int len; 188 char machname[MAXHOSTNAMELEN + 1]; 189 uid_t uid; 190 gid_t gid; 191 gid_t gids[NGRPS]; 192 193 if (gethostname(machname, sizeof machname) == -1) 194 abort(); 195 machname[sizeof(machname) - 1] = 0; 196 uid = geteuid(); 197 gid = getegid(); 198 if ((len = getgroups(NGRPS, gids)) < 0) 199 abort(); 200 /* XXX: interface problem; those should all have been unsigned */ 201 return (authunix_create(machname, (int)uid, (int)gid, len, 202 (int *)gids)); 203 } 204 205 /* 206 * authunix operations 207 */ 208 209 /* ARGSUSED */ 210 static void 211 authunix_nextverf(auth) 212 AUTH *auth; 213 { 214 /* no action necessary */ 215 } 216 217 static bool_t 218 authunix_marshal(auth, xdrs) 219 AUTH *auth; 220 XDR *xdrs; 221 { 222 struct audata *au; 223 224 assert(auth != NULL); 225 assert(xdrs != NULL); 226 227 au = AUTH_PRIVATE(auth); 228 return (XDR_PUTBYTES(xdrs, au->au_marshed, au->au_mpos)); 229 } 230 231 static bool_t 232 authunix_validate(auth, verf) 233 AUTH *auth; 234 struct opaque_auth *verf; 235 { 236 struct audata *au; 237 XDR xdrs; 238 239 assert(auth != NULL); 240 assert(verf != NULL); 241 242 if (verf->oa_flavor == AUTH_SHORT) { 243 au = AUTH_PRIVATE(auth); 244 xdrmem_create(&xdrs, verf->oa_base, verf->oa_length, 245 XDR_DECODE); 246 247 if (au->au_shcred.oa_base != NULL) { 248 mem_free(au->au_shcred.oa_base, 249 au->au_shcred.oa_length); 250 au->au_shcred.oa_base = NULL; 251 } 252 if (xdr_opaque_auth(&xdrs, &au->au_shcred)) { 253 auth->ah_cred = au->au_shcred; 254 } else { 255 xdrs.x_op = XDR_FREE; 256 (void)xdr_opaque_auth(&xdrs, &au->au_shcred); 257 au->au_shcred.oa_base = NULL; 258 auth->ah_cred = au->au_origcred; 259 } 260 marshal_new_auth(auth); 261 } 262 return (TRUE); 263 } 264 265 static bool_t 266 authunix_refresh(AUTH *auth, void *dummy) 267 { 268 struct audata *au = AUTH_PRIVATE(auth); 269 struct authunix_parms aup; 270 struct timeval now; 271 XDR xdrs; 272 int stat; 273 274 assert(auth != NULL); 275 276 if (auth->ah_cred.oa_base == au->au_origcred.oa_base) { 277 /* there is no hope. Punt */ 278 return (FALSE); 279 } 280 au->au_shfaults ++; 281 282 /* first deserialize the creds back into a struct authunix_parms */ 283 aup.aup_machname = NULL; 284 aup.aup_gids = NULL; 285 xdrmem_create(&xdrs, au->au_origcred.oa_base, 286 au->au_origcred.oa_length, XDR_DECODE); 287 stat = xdr_authunix_parms(&xdrs, &aup); 288 if (! stat) 289 goto done; 290 291 /* update the time and serialize in place */ 292 (void)gettimeofday(&now, NULL); 293 aup.aup_time = now.tv_sec; 294 xdrs.x_op = XDR_ENCODE; 295 XDR_SETPOS(&xdrs, 0); 296 stat = xdr_authunix_parms(&xdrs, &aup); 297 if (! stat) 298 goto done; 299 auth->ah_cred = au->au_origcred; 300 marshal_new_auth(auth); 301 done: 302 /* free the struct authunix_parms created by deserializing */ 303 xdrs.x_op = XDR_FREE; 304 (void)xdr_authunix_parms(&xdrs, &aup); 305 XDR_DESTROY(&xdrs); 306 return (stat); 307 } 308 309 static void 310 authunix_destroy(auth) 311 AUTH *auth; 312 { 313 struct audata *au; 314 315 assert(auth != NULL); 316 317 au = AUTH_PRIVATE(auth); 318 mem_free(au->au_origcred.oa_base, au->au_origcred.oa_length); 319 320 if (au->au_shcred.oa_base != NULL) 321 mem_free(au->au_shcred.oa_base, au->au_shcred.oa_length); 322 323 mem_free(auth->ah_private, sizeof(struct audata)); 324 325 if (auth->ah_verf.oa_base != NULL) 326 mem_free(auth->ah_verf.oa_base, auth->ah_verf.oa_length); 327 328 mem_free(auth, sizeof(*auth)); 329 } 330 331 /* 332 * Marshals (pre-serializes) an auth struct. 333 * sets private data, au_marshed and au_mpos 334 */ 335 static void 336 marshal_new_auth(auth) 337 AUTH *auth; 338 { 339 XDR xdr_stream; 340 XDR *xdrs = &xdr_stream; 341 struct audata *au; 342 343 assert(auth != NULL); 344 345 au = AUTH_PRIVATE(auth); 346 xdrmem_create(xdrs, au->au_marshed, MAX_AUTH_BYTES, XDR_ENCODE); 347 if ((! xdr_opaque_auth(xdrs, &(auth->ah_cred))) || 348 (! xdr_opaque_auth(xdrs, &(auth->ah_verf)))) 349 warnx("auth_none.c - Fatal marshalling problem"); 350 else 351 au->au_mpos = XDR_GETPOS(xdrs); 352 XDR_DESTROY(xdrs); 353 } 354 355 static struct auth_ops * 356 authunix_ops() 357 { 358 static struct auth_ops ops; 359 extern mutex_t ops_lock; 360 361 /* VARIABLES PROTECTED BY ops_lock: ops */ 362 363 mutex_lock(&ops_lock); 364 if (ops.ah_nextverf == NULL) { 365 ops.ah_nextverf = authunix_nextverf; 366 ops.ah_marshal = authunix_marshal; 367 ops.ah_validate = authunix_validate; 368 ops.ah_refresh = authunix_refresh; 369 ops.ah_destroy = authunix_destroy; 370 } 371 mutex_unlock(&ops_lock); 372 return (&ops); 373 } 374