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