1 /* $NetBSD: auth_unix.c,v 1.13 1998/11/15 17:24:07 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 #include <sys/cdefs.h> 33 #if defined(LIBC_SCCS) && !defined(lint) 34 #if 0 35 static char *sccsid = "@(#)auth_unix.c 1.19 87/08/11 Copyr 1984 Sun Micro"; 36 static char *sccsid = "@(#)auth_unix.c 2.2 88/08/01 4.0 RPCSRC"; 37 #else 38 __RCSID("$NetBSD: auth_unix.c,v 1.13 1998/11/15 17:24:07 christos Exp $"); 39 #endif 40 #endif 41 42 /* 43 * auth_unix.c, Implements UNIX style authentication parameters. 44 * 45 * Copyright (C) 1984, Sun Microsystems, Inc. 46 * 47 * The system is very weak. The client uses no encryption for it's 48 * credentials and only sends null verifiers. The server sends backs 49 * null verifiers or optionally a verifier that suggests a new short hand 50 * for the credentials. 51 * 52 */ 53 54 #include "namespace.h" 55 56 #include <sys/param.h> 57 58 #include <err.h> 59 #include <stdio.h> 60 #include <stdlib.h> 61 #include <string.h> 62 #include <unistd.h> 63 64 #include <rpc/types.h> 65 #include <rpc/xdr.h> 66 #include <rpc/auth.h> 67 #include <rpc/auth_unix.h> 68 69 #ifdef __weak_alias 70 __weak_alias(authunix_create,_authunix_create); 71 __weak_alias(authunix_create_default,_authunix_create_default); 72 #endif 73 74 75 /* auth_unix.c */ 76 static void authunix_nextverf __P((AUTH *)); 77 static bool_t authunix_marshal __P((AUTH *, XDR *)); 78 static bool_t authunix_validate __P((AUTH *, struct opaque_auth *)); 79 static bool_t authunix_refresh __P((AUTH *)); 80 static void authunix_destroy __P((AUTH *)); 81 static void marshal_new_auth __P((AUTH *)); 82 83 /* 84 * Unix authenticator operations vector 85 */ 86 static const struct auth_ops auth_unix_ops = { 87 authunix_nextverf, 88 authunix_marshal, 89 authunix_validate, 90 authunix_refresh, 91 authunix_destroy 92 }; 93 94 /* 95 * This struct is pointed to by the ah_private field of an auth_handle. 96 */ 97 struct audata { 98 struct opaque_auth au_origcred; /* original credentials */ 99 struct opaque_auth au_shcred; /* short hand cred */ 100 u_long au_shfaults; /* short hand cache faults */ 101 char au_marshed[MAX_AUTH_BYTES]; 102 u_int au_mpos; /* xdr pos at end of marshed */ 103 }; 104 #define AUTH_PRIVATE(auth) ((struct audata *)auth->ah_private) 105 106 /* 107 * Create a unix style authenticator. 108 * Returns an auth handle with the given stuff in it. 109 */ 110 AUTH * 111 authunix_create(machname, uid, gid, len, aup_gids) 112 char *machname; 113 int uid; 114 int gid; 115 int len; 116 int *aup_gids; 117 { 118 struct authunix_parms aup; 119 char mymem[MAX_AUTH_BYTES]; 120 struct timeval now; 121 XDR xdrs; 122 AUTH *auth; 123 struct audata *au; 124 125 /* 126 * Allocate and set up auth handle 127 */ 128 auth = (AUTH *)mem_alloc(sizeof(*auth)); 129 #ifndef KERNEL 130 if (auth == NULL) { 131 warnx("authunix_create: out of memory"); 132 return (NULL); 133 } 134 #endif 135 au = (struct audata *)mem_alloc(sizeof(*au)); 136 #ifndef KERNEL 137 if (au == NULL) { 138 warnx("authunix_create: out of memory"); 139 return (NULL); 140 } 141 #endif 142 auth->ah_ops = &auth_unix_ops; 143 auth->ah_private = au; 144 auth->ah_verf = au->au_shcred = _null_auth; 145 au->au_shfaults = 0; 146 147 /* 148 * fill in param struct from the given params 149 */ 150 (void)gettimeofday(&now, (struct timezone *)0); 151 aup.aup_time = now.tv_sec; 152 aup.aup_machname = machname; 153 aup.aup_uid = uid; 154 aup.aup_gid = gid; 155 aup.aup_len = (u_int)len; 156 aup.aup_gids = aup_gids; 157 158 /* 159 * Serialize the parameters into origcred 160 */ 161 xdrmem_create(&xdrs, mymem, MAX_AUTH_BYTES, XDR_ENCODE); 162 if (! xdr_authunix_parms(&xdrs, &aup)) 163 abort(); 164 au->au_origcred.oa_length = len = XDR_GETPOS(&xdrs); 165 au->au_origcred.oa_flavor = AUTH_UNIX; 166 #ifdef KERNEL 167 au->au_origcred.oa_base = mem_alloc((u_int) len); 168 #else 169 if ((au->au_origcred.oa_base = mem_alloc((u_int) len)) == NULL) { 170 warnx("authunix_create: out of memory"); 171 return (NULL); 172 } 173 #endif 174 memmove(au->au_origcred.oa_base, mymem, (size_t)len); 175 176 /* 177 * set auth handle to reflect new cred. 178 */ 179 auth->ah_cred = au->au_origcred; 180 marshal_new_auth(auth); 181 return (auth); 182 } 183 184 /* 185 * Returns an auth handle with parameters determined by doing lots of 186 * syscalls. 187 */ 188 AUTH * 189 authunix_create_default() 190 { 191 int len; 192 char machname[MAXHOSTNAMELEN + 1]; 193 uid_t uid; 194 gid_t gid; 195 gid_t gids[NGRPS]; 196 197 if (gethostname(machname, sizeof machname) == -1) 198 abort(); 199 machname[sizeof(machname) - 1] = 0; 200 uid = geteuid(); 201 gid = getegid(); 202 if ((len = getgroups(NGRPS, gids)) < 0) 203 abort(); 204 /* XXX: interface problem; those should all have been unsigned */ 205 return (authunix_create(machname, (int)uid, (int)gid, len, 206 (int *)gids)); 207 } 208 209 /* 210 * authunix operations 211 */ 212 213 /* ARGSUSED */ 214 static void 215 authunix_nextverf(auth) 216 AUTH *auth; 217 { 218 /* no action necessary */ 219 } 220 221 static bool_t 222 authunix_marshal(auth, xdrs) 223 AUTH *auth; 224 XDR *xdrs; 225 { 226 struct audata *au = AUTH_PRIVATE(auth); 227 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 if (verf->oa_flavor == AUTH_SHORT) { 240 au = AUTH_PRIVATE(auth); 241 xdrmem_create(&xdrs, verf->oa_base, verf->oa_length, XDR_DECODE); 242 243 if (au->au_shcred.oa_base != NULL) { 244 mem_free(au->au_shcred.oa_base, 245 au->au_shcred.oa_length); 246 au->au_shcred.oa_base = NULL; 247 } 248 if (xdr_opaque_auth(&xdrs, &au->au_shcred)) { 249 auth->ah_cred = au->au_shcred; 250 } else { 251 xdrs.x_op = XDR_FREE; 252 (void)xdr_opaque_auth(&xdrs, &au->au_shcred); 253 au->au_shcred.oa_base = NULL; 254 auth->ah_cred = au->au_origcred; 255 } 256 marshal_new_auth(auth); 257 } 258 return (TRUE); 259 } 260 261 static bool_t 262 authunix_refresh(auth) 263 AUTH *auth; 264 { 265 struct audata *au = AUTH_PRIVATE(auth); 266 struct authunix_parms aup; 267 struct timeval now; 268 XDR xdrs; 269 int stat; 270 271 if (auth->ah_cred.oa_base == au->au_origcred.oa_base) { 272 /* there is no hope. Punt */ 273 return (FALSE); 274 } 275 au->au_shfaults ++; 276 277 /* first deserialize the creds back into a struct authunix_parms */ 278 aup.aup_machname = NULL; 279 aup.aup_gids = (int *)NULL; 280 xdrmem_create(&xdrs, au->au_origcred.oa_base, 281 au->au_origcred.oa_length, XDR_DECODE); 282 stat = xdr_authunix_parms(&xdrs, &aup); 283 if (! stat) 284 goto done; 285 286 /* update the time and serialize in place */ 287 (void)gettimeofday(&now, (struct timezone *)0); 288 aup.aup_time = now.tv_sec; 289 xdrs.x_op = XDR_ENCODE; 290 XDR_SETPOS(&xdrs, 0); 291 stat = xdr_authunix_parms(&xdrs, &aup); 292 if (! stat) 293 goto done; 294 auth->ah_cred = au->au_origcred; 295 marshal_new_auth(auth); 296 done: 297 /* free the struct authunix_parms created by deserializing */ 298 xdrs.x_op = XDR_FREE; 299 (void)xdr_authunix_parms(&xdrs, &aup); 300 XDR_DESTROY(&xdrs); 301 return (stat); 302 } 303 304 static void 305 authunix_destroy(auth) 306 AUTH *auth; 307 { 308 struct audata *au = AUTH_PRIVATE(auth); 309 310 mem_free(au->au_origcred.oa_base, au->au_origcred.oa_length); 311 312 if (au->au_shcred.oa_base != NULL) 313 mem_free(au->au_shcred.oa_base, au->au_shcred.oa_length); 314 315 mem_free(auth->ah_private, sizeof(struct audata)); 316 317 if (auth->ah_verf.oa_base != NULL) 318 mem_free(auth->ah_verf.oa_base, auth->ah_verf.oa_length); 319 320 mem_free(auth, sizeof(*auth)); 321 } 322 323 /* 324 * Marshals (pre-serializes) an auth struct. 325 * sets private data, au_marshed and au_mpos 326 */ 327 static void 328 marshal_new_auth(auth) 329 AUTH *auth; 330 { 331 XDR xdr_stream; 332 XDR *xdrs = &xdr_stream; 333 struct audata *au = AUTH_PRIVATE(auth); 334 335 xdrmem_create(xdrs, au->au_marshed, MAX_AUTH_BYTES, XDR_ENCODE); 336 if ((! xdr_opaque_auth(xdrs, &(auth->ah_cred))) || 337 (! xdr_opaque_auth(xdrs, &(auth->ah_verf)))) 338 warnx("auth_none.c - Fatal marshalling problem"); 339 else 340 au->au_mpos = XDR_GETPOS(xdrs); 341 XDR_DESTROY(xdrs); 342 } 343