18360efbdSAlfred Perlstein /* $NetBSD: auth_unix.c,v 1.18 2000/07/06 03:03:30 christos Exp $ */ 28360efbdSAlfred Perlstein 399064799SGarrett Wollman /* 499064799SGarrett Wollman * Sun RPC is a product of Sun Microsystems, Inc. and is provided for 599064799SGarrett Wollman * unrestricted use provided that this legend is included on all tape 699064799SGarrett Wollman * media and as a part of the software program in whole or part. Users 799064799SGarrett Wollman * may copy or modify Sun RPC without charge, but are not authorized 899064799SGarrett Wollman * to license or distribute it to anyone else except as part of a product or 999064799SGarrett Wollman * program developed by the user. 1099064799SGarrett Wollman * 1199064799SGarrett Wollman * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE 1299064799SGarrett Wollman * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR 1399064799SGarrett Wollman * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. 1499064799SGarrett Wollman * 1599064799SGarrett Wollman * Sun RPC is provided with no support and without any obligation on the 1699064799SGarrett Wollman * part of Sun Microsystems, Inc. to assist in its use, correction, 1799064799SGarrett Wollman * modification or enhancement. 1899064799SGarrett Wollman * 1999064799SGarrett Wollman * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE 2099064799SGarrett Wollman * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC 2199064799SGarrett Wollman * OR ANY PART THEREOF. 2299064799SGarrett Wollman * 2399064799SGarrett Wollman * In no event will Sun Microsystems, Inc. be liable for any lost revenue 2499064799SGarrett Wollman * or profits or other special, indirect and consequential damages, even if 2599064799SGarrett Wollman * Sun has been advised of the possibility of such damages. 2699064799SGarrett Wollman * 2799064799SGarrett Wollman * Sun Microsystems, Inc. 2899064799SGarrett Wollman * 2550 Garcia Avenue 2999064799SGarrett Wollman * Mountain View, California 94043 3099064799SGarrett Wollman */ 3199064799SGarrett Wollman 3299064799SGarrett Wollman #if defined(LIBC_SCCS) && !defined(lint) 33a986ef57SDavid E. O'Brien static char *sccsid2 = "@(#)auth_unix.c 1.19 87/08/11 Copyr 1984 Sun Micro"; 348360efbdSAlfred Perlstein static char *sccsid = "@(#)auth_unix.c 2.2 88/08/01 4.0 RPCSRC"; 3599064799SGarrett Wollman #endif 36d3d20c82SDavid E. O'Brien #include <sys/cdefs.h> 37d3d20c82SDavid E. O'Brien __FBSDID("$FreeBSD$"); 3899064799SGarrett Wollman 3999064799SGarrett Wollman /* 4099064799SGarrett Wollman * auth_unix.c, Implements UNIX style authentication parameters. 4199064799SGarrett Wollman * 4299064799SGarrett Wollman * Copyright (C) 1984, Sun Microsystems, Inc. 4399064799SGarrett Wollman * 4499064799SGarrett Wollman * The system is very weak. The client uses no encryption for it's 4599064799SGarrett Wollman * credentials and only sends null verifiers. The server sends backs 4699064799SGarrett Wollman * null verifiers or optionally a verifier that suggests a new short hand 4799064799SGarrett Wollman * for the credentials. 4899064799SGarrett Wollman * 4999064799SGarrett Wollman */ 5099064799SGarrett Wollman 518360efbdSAlfred Perlstein #include "namespace.h" 529f5afc13SIan Dowse #include "reentrant.h" 538360efbdSAlfred Perlstein #include <sys/param.h> 548360efbdSAlfred Perlstein 558360efbdSAlfred Perlstein #include <assert.h> 568360efbdSAlfred Perlstein #include <err.h> 5799064799SGarrett Wollman #include <stdio.h> 5899064799SGarrett Wollman #include <stdlib.h> 594c3af266SPoul-Henning Kamp #include <unistd.h> 604c3af266SPoul-Henning Kamp #include <string.h> 6199064799SGarrett Wollman 6299064799SGarrett Wollman #include <rpc/types.h> 6399064799SGarrett Wollman #include <rpc/xdr.h> 6499064799SGarrett Wollman #include <rpc/auth.h> 6599064799SGarrett Wollman #include <rpc/auth_unix.h> 668360efbdSAlfred Perlstein #include "un-namespace.h" 67235baf26SDaniel Eischen #include "mt_misc.h" 6899064799SGarrett Wollman 698360efbdSAlfred Perlstein /* auth_unix.c */ 708360efbdSAlfred Perlstein static void authunix_nextverf (AUTH *); 718360efbdSAlfred Perlstein static bool_t authunix_marshal (AUTH *, XDR *); 728360efbdSAlfred Perlstein static bool_t authunix_validate (AUTH *, struct opaque_auth *); 738360efbdSAlfred Perlstein static bool_t authunix_refresh (AUTH *, void *); 748360efbdSAlfred Perlstein static void authunix_destroy (AUTH *); 758360efbdSAlfred Perlstein static void marshal_new_auth (AUTH *); 768360efbdSAlfred Perlstein static struct auth_ops *authunix_ops (void); 7799064799SGarrett Wollman 7899064799SGarrett Wollman /* 7999064799SGarrett Wollman * This struct is pointed to by the ah_private field of an auth_handle. 8099064799SGarrett Wollman */ 8199064799SGarrett Wollman struct audata { 8299064799SGarrett Wollman struct opaque_auth au_origcred; /* original credentials */ 8399064799SGarrett Wollman struct opaque_auth au_shcred; /* short hand cred */ 8499064799SGarrett Wollman u_long au_shfaults; /* short hand cache faults */ 8599064799SGarrett Wollman char au_marshed[MAX_AUTH_BYTES]; 8699064799SGarrett Wollman u_int au_mpos; /* xdr pos at end of marshed */ 8799064799SGarrett Wollman }; 8899064799SGarrett Wollman #define AUTH_PRIVATE(auth) ((struct audata *)auth->ah_private) 8999064799SGarrett Wollman 9099064799SGarrett Wollman /* 9199064799SGarrett Wollman * Create a unix style authenticator. 9299064799SGarrett Wollman * Returns an auth handle with the given stuff in it. 9399064799SGarrett Wollman */ 9499064799SGarrett Wollman AUTH * 9599064799SGarrett Wollman authunix_create(machname, uid, gid, len, aup_gids) 9699064799SGarrett Wollman char *machname; 97*0d1040e5SPedro F. Giffuni u_int uid; 98*0d1040e5SPedro F. Giffuni u_int gid; 998360efbdSAlfred Perlstein int len; 100*0d1040e5SPedro F. Giffuni u_int *aup_gids; 10199064799SGarrett Wollman { 10299064799SGarrett Wollman struct authunix_parms aup; 10399064799SGarrett Wollman char mymem[MAX_AUTH_BYTES]; 10499064799SGarrett Wollman struct timeval now; 10599064799SGarrett Wollman XDR xdrs; 1068360efbdSAlfred Perlstein AUTH *auth; 1078360efbdSAlfred Perlstein struct audata *au; 10899064799SGarrett Wollman 10999064799SGarrett Wollman /* 11099064799SGarrett Wollman * Allocate and set up auth handle 11199064799SGarrett Wollman */ 1128360efbdSAlfred Perlstein au = NULL; 1138360efbdSAlfred Perlstein auth = mem_alloc(sizeof(*auth)); 114c4473420SPeter Wemm #ifndef _KERNEL 11599064799SGarrett Wollman if (auth == NULL) { 1168360efbdSAlfred Perlstein warnx("authunix_create: out of memory"); 1178360efbdSAlfred Perlstein goto cleanup_authunix_create; 11899064799SGarrett Wollman } 11999064799SGarrett Wollman #endif 1208360efbdSAlfred Perlstein au = mem_alloc(sizeof(*au)); 121c4473420SPeter Wemm #ifndef _KERNEL 12299064799SGarrett Wollman if (au == NULL) { 1238360efbdSAlfred Perlstein warnx("authunix_create: out of memory"); 1248360efbdSAlfred Perlstein goto cleanup_authunix_create; 12599064799SGarrett Wollman } 12699064799SGarrett Wollman #endif 1278360efbdSAlfred Perlstein auth->ah_ops = authunix_ops(); 12899064799SGarrett Wollman auth->ah_private = (caddr_t)au; 12999064799SGarrett Wollman auth->ah_verf = au->au_shcred = _null_auth; 13099064799SGarrett Wollman au->au_shfaults = 0; 1318360efbdSAlfred Perlstein au->au_origcred.oa_base = NULL; 13299064799SGarrett Wollman 13399064799SGarrett Wollman /* 13499064799SGarrett Wollman * fill in param struct from the given params 13599064799SGarrett Wollman */ 1368360efbdSAlfred Perlstein (void)gettimeofday(&now, NULL); 13799064799SGarrett Wollman aup.aup_time = now.tv_sec; 13899064799SGarrett Wollman aup.aup_machname = machname; 13999064799SGarrett Wollman aup.aup_uid = uid; 14099064799SGarrett Wollman aup.aup_gid = gid; 14199064799SGarrett Wollman aup.aup_len = (u_int)len; 14299064799SGarrett Wollman aup.aup_gids = aup_gids; 14399064799SGarrett Wollman 14499064799SGarrett Wollman /* 14599064799SGarrett Wollman * Serialize the parameters into origcred 14699064799SGarrett Wollman */ 14799064799SGarrett Wollman xdrmem_create(&xdrs, mymem, MAX_AUTH_BYTES, XDR_ENCODE); 14899064799SGarrett Wollman if (! xdr_authunix_parms(&xdrs, &aup)) 14999064799SGarrett Wollman abort(); 15099064799SGarrett Wollman au->au_origcred.oa_length = len = XDR_GETPOS(&xdrs); 15199064799SGarrett Wollman au->au_origcred.oa_flavor = AUTH_UNIX; 152c4473420SPeter Wemm #ifdef _KERNEL 15399064799SGarrett Wollman au->au_origcred.oa_base = mem_alloc((u_int) len); 15499064799SGarrett Wollman #else 15599064799SGarrett Wollman if ((au->au_origcred.oa_base = mem_alloc((u_int) len)) == NULL) { 1568360efbdSAlfred Perlstein warnx("authunix_create: out of memory"); 1578360efbdSAlfred Perlstein goto cleanup_authunix_create; 15899064799SGarrett Wollman } 15999064799SGarrett Wollman #endif 1608360efbdSAlfred Perlstein memmove(au->au_origcred.oa_base, mymem, (size_t)len); 16199064799SGarrett Wollman 16299064799SGarrett Wollman /* 16399064799SGarrett Wollman * set auth handle to reflect new cred. 16499064799SGarrett Wollman */ 16599064799SGarrett Wollman auth->ah_cred = au->au_origcred; 16699064799SGarrett Wollman marshal_new_auth(auth); 16799064799SGarrett Wollman return (auth); 1688360efbdSAlfred Perlstein #ifndef _KERNEL 1698360efbdSAlfred Perlstein cleanup_authunix_create: 1708360efbdSAlfred Perlstein if (auth) 1718360efbdSAlfred Perlstein mem_free(auth, sizeof(*auth)); 1728360efbdSAlfred Perlstein if (au) { 1738360efbdSAlfred Perlstein if (au->au_origcred.oa_base) 1748360efbdSAlfred Perlstein mem_free(au->au_origcred.oa_base, (u_int)len); 1758360efbdSAlfred Perlstein mem_free(au, sizeof(*au)); 1768360efbdSAlfred Perlstein } 1778360efbdSAlfred Perlstein return (NULL); 1788360efbdSAlfred Perlstein #endif 17999064799SGarrett Wollman } 18099064799SGarrett Wollman 18199064799SGarrett Wollman /* 18299064799SGarrett Wollman * Returns an auth handle with parameters determined by doing lots of 18399064799SGarrett Wollman * syscalls. 18499064799SGarrett Wollman */ 18599064799SGarrett Wollman AUTH * 18699064799SGarrett Wollman authunix_create_default() 18799064799SGarrett Wollman { 1889a36eaa3SKonstantin Belousov AUTH *auth; 18954404cfbSBrooks Davis int ngids; 19054404cfbSBrooks Davis long ngids_max; 1918360efbdSAlfred Perlstein char machname[MAXHOSTNAMELEN + 1]; 1928360efbdSAlfred Perlstein uid_t uid; 1938360efbdSAlfred Perlstein gid_t gid; 19454404cfbSBrooks Davis gid_t *gids; 19554404cfbSBrooks Davis 19654404cfbSBrooks Davis ngids_max = sysconf(_SC_NGROUPS_MAX) + 1; 19754404cfbSBrooks Davis gids = malloc(sizeof(gid_t) * ngids_max); 19854404cfbSBrooks Davis if (gids == NULL) 19954404cfbSBrooks Davis return (NULL); 20099064799SGarrett Wollman 2018360efbdSAlfred Perlstein if (gethostname(machname, sizeof machname) == -1) 20299064799SGarrett Wollman abort(); 2038360efbdSAlfred Perlstein machname[sizeof(machname) - 1] = 0; 2048360efbdSAlfred Perlstein uid = geteuid(); 2058360efbdSAlfred Perlstein gid = getegid(); 20654404cfbSBrooks Davis if ((ngids = getgroups(ngids_max, gids)) < 0) 20799064799SGarrett Wollman abort(); 20854404cfbSBrooks Davis if (ngids > NGRPS) 20954404cfbSBrooks Davis ngids = NGRPS; 210*0d1040e5SPedro F. Giffuni /* XXX: interface problem; we should translate from uid_t and gid_t */ 211f3c3ef7bSPedro F. Giffuni auth = authunix_create(machname, uid, gid, ngids, gids); 2129a36eaa3SKonstantin Belousov free(gids); 2139a36eaa3SKonstantin Belousov return (auth); 21499064799SGarrett Wollman } 21599064799SGarrett Wollman 21699064799SGarrett Wollman /* 21799064799SGarrett Wollman * authunix operations 21899064799SGarrett Wollman */ 21999064799SGarrett Wollman 2208360efbdSAlfred Perlstein /* ARGSUSED */ 22199064799SGarrett Wollman static void 22299064799SGarrett Wollman authunix_nextverf(auth) 22399064799SGarrett Wollman AUTH *auth; 22499064799SGarrett Wollman { 22599064799SGarrett Wollman /* no action necessary */ 22699064799SGarrett Wollman } 22799064799SGarrett Wollman 22899064799SGarrett Wollman static bool_t 22999064799SGarrett Wollman authunix_marshal(auth, xdrs) 23099064799SGarrett Wollman AUTH *auth; 23199064799SGarrett Wollman XDR *xdrs; 23299064799SGarrett Wollman { 2338360efbdSAlfred Perlstein struct audata *au; 23499064799SGarrett Wollman 2358360efbdSAlfred Perlstein assert(auth != NULL); 2368360efbdSAlfred Perlstein assert(xdrs != NULL); 2378360efbdSAlfred Perlstein 2388360efbdSAlfred Perlstein au = AUTH_PRIVATE(auth); 23999064799SGarrett Wollman return (XDR_PUTBYTES(xdrs, au->au_marshed, au->au_mpos)); 24099064799SGarrett Wollman } 24199064799SGarrett Wollman 24299064799SGarrett Wollman static bool_t 24399064799SGarrett Wollman authunix_validate(auth, verf) 2448360efbdSAlfred Perlstein AUTH *auth; 2458360efbdSAlfred Perlstein struct opaque_auth *verf; 24699064799SGarrett Wollman { 2478360efbdSAlfred Perlstein struct audata *au; 24899064799SGarrett Wollman XDR xdrs; 24999064799SGarrett Wollman 2508360efbdSAlfred Perlstein assert(auth != NULL); 2518360efbdSAlfred Perlstein assert(verf != NULL); 2528360efbdSAlfred Perlstein 2538360efbdSAlfred Perlstein if (verf->oa_flavor == AUTH_SHORT) { 25499064799SGarrett Wollman au = AUTH_PRIVATE(auth); 2558360efbdSAlfred Perlstein xdrmem_create(&xdrs, verf->oa_base, verf->oa_length, 2568360efbdSAlfred Perlstein XDR_DECODE); 25799064799SGarrett Wollman 25899064799SGarrett Wollman if (au->au_shcred.oa_base != NULL) { 25999064799SGarrett Wollman mem_free(au->au_shcred.oa_base, 26099064799SGarrett Wollman au->au_shcred.oa_length); 26199064799SGarrett Wollman au->au_shcred.oa_base = NULL; 26299064799SGarrett Wollman } 26399064799SGarrett Wollman if (xdr_opaque_auth(&xdrs, &au->au_shcred)) { 26499064799SGarrett Wollman auth->ah_cred = au->au_shcred; 26599064799SGarrett Wollman } else { 26699064799SGarrett Wollman xdrs.x_op = XDR_FREE; 26799064799SGarrett Wollman (void)xdr_opaque_auth(&xdrs, &au->au_shcred); 26899064799SGarrett Wollman au->au_shcred.oa_base = NULL; 26999064799SGarrett Wollman auth->ah_cred = au->au_origcred; 27099064799SGarrett Wollman } 27199064799SGarrett Wollman marshal_new_auth(auth); 27299064799SGarrett Wollman } 27399064799SGarrett Wollman return (TRUE); 27499064799SGarrett Wollman } 27599064799SGarrett Wollman 27699064799SGarrett Wollman static bool_t 2778360efbdSAlfred Perlstein authunix_refresh(AUTH *auth, void *dummy) 27899064799SGarrett Wollman { 2798360efbdSAlfred Perlstein struct audata *au = AUTH_PRIVATE(auth); 28099064799SGarrett Wollman struct authunix_parms aup; 28199064799SGarrett Wollman struct timeval now; 28299064799SGarrett Wollman XDR xdrs; 2838360efbdSAlfred Perlstein int stat; 2848360efbdSAlfred Perlstein 2858360efbdSAlfred Perlstein assert(auth != NULL); 28699064799SGarrett Wollman 28799064799SGarrett Wollman if (auth->ah_cred.oa_base == au->au_origcred.oa_base) { 28899064799SGarrett Wollman /* there is no hope. Punt */ 28999064799SGarrett Wollman return (FALSE); 29099064799SGarrett Wollman } 29199064799SGarrett Wollman au->au_shfaults ++; 29299064799SGarrett Wollman 29399064799SGarrett Wollman /* first deserialize the creds back into a struct authunix_parms */ 29499064799SGarrett Wollman aup.aup_machname = NULL; 2958360efbdSAlfred Perlstein aup.aup_gids = NULL; 29699064799SGarrett Wollman xdrmem_create(&xdrs, au->au_origcred.oa_base, 29799064799SGarrett Wollman au->au_origcred.oa_length, XDR_DECODE); 29899064799SGarrett Wollman stat = xdr_authunix_parms(&xdrs, &aup); 29999064799SGarrett Wollman if (! stat) 30099064799SGarrett Wollman goto done; 30199064799SGarrett Wollman 30299064799SGarrett Wollman /* update the time and serialize in place */ 3038360efbdSAlfred Perlstein (void)gettimeofday(&now, NULL); 30499064799SGarrett Wollman aup.aup_time = now.tv_sec; 30599064799SGarrett Wollman xdrs.x_op = XDR_ENCODE; 30699064799SGarrett Wollman XDR_SETPOS(&xdrs, 0); 30799064799SGarrett Wollman stat = xdr_authunix_parms(&xdrs, &aup); 30899064799SGarrett Wollman if (! stat) 30999064799SGarrett Wollman goto done; 31099064799SGarrett Wollman auth->ah_cred = au->au_origcred; 31199064799SGarrett Wollman marshal_new_auth(auth); 31299064799SGarrett Wollman done: 31399064799SGarrett Wollman /* free the struct authunix_parms created by deserializing */ 31499064799SGarrett Wollman xdrs.x_op = XDR_FREE; 31599064799SGarrett Wollman (void)xdr_authunix_parms(&xdrs, &aup); 31699064799SGarrett Wollman XDR_DESTROY(&xdrs); 31799064799SGarrett Wollman return (stat); 31899064799SGarrett Wollman } 31999064799SGarrett Wollman 32099064799SGarrett Wollman static void 32199064799SGarrett Wollman authunix_destroy(auth) 3228360efbdSAlfred Perlstein AUTH *auth; 32399064799SGarrett Wollman { 3248360efbdSAlfred Perlstein struct audata *au; 32599064799SGarrett Wollman 3268360efbdSAlfred Perlstein assert(auth != NULL); 3278360efbdSAlfred Perlstein 3288360efbdSAlfred Perlstein au = AUTH_PRIVATE(auth); 32999064799SGarrett Wollman mem_free(au->au_origcred.oa_base, au->au_origcred.oa_length); 33099064799SGarrett Wollman 33199064799SGarrett Wollman if (au->au_shcred.oa_base != NULL) 33299064799SGarrett Wollman mem_free(au->au_shcred.oa_base, au->au_shcred.oa_length); 33399064799SGarrett Wollman 33499064799SGarrett Wollman mem_free(auth->ah_private, sizeof(struct audata)); 33599064799SGarrett Wollman 33699064799SGarrett Wollman if (auth->ah_verf.oa_base != NULL) 33799064799SGarrett Wollman mem_free(auth->ah_verf.oa_base, auth->ah_verf.oa_length); 33899064799SGarrett Wollman 3398360efbdSAlfred Perlstein mem_free(auth, sizeof(*auth)); 34099064799SGarrett Wollman } 34199064799SGarrett Wollman 34299064799SGarrett Wollman /* 34399064799SGarrett Wollman * Marshals (pre-serializes) an auth struct. 34499064799SGarrett Wollman * sets private data, au_marshed and au_mpos 34599064799SGarrett Wollman */ 3464c3af266SPoul-Henning Kamp static void 34799064799SGarrett Wollman marshal_new_auth(auth) 3488360efbdSAlfred Perlstein AUTH *auth; 34999064799SGarrett Wollman { 35099064799SGarrett Wollman XDR xdr_stream; 3518360efbdSAlfred Perlstein XDR *xdrs = &xdr_stream; 3528360efbdSAlfred Perlstein struct audata *au; 35399064799SGarrett Wollman 3548360efbdSAlfred Perlstein assert(auth != NULL); 3558360efbdSAlfred Perlstein 3568360efbdSAlfred Perlstein au = AUTH_PRIVATE(auth); 35799064799SGarrett Wollman xdrmem_create(xdrs, au->au_marshed, MAX_AUTH_BYTES, XDR_ENCODE); 35899064799SGarrett Wollman if ((! xdr_opaque_auth(xdrs, &(auth->ah_cred))) || 3598360efbdSAlfred Perlstein (! xdr_opaque_auth(xdrs, &(auth->ah_verf)))) 3608360efbdSAlfred Perlstein warnx("auth_none.c - Fatal marshalling problem"); 3618360efbdSAlfred Perlstein else 36299064799SGarrett Wollman au->au_mpos = XDR_GETPOS(xdrs); 36399064799SGarrett Wollman XDR_DESTROY(xdrs); 36499064799SGarrett Wollman } 3658360efbdSAlfred Perlstein 3668360efbdSAlfred Perlstein static struct auth_ops * 3678360efbdSAlfred Perlstein authunix_ops() 3688360efbdSAlfred Perlstein { 3698360efbdSAlfred Perlstein static struct auth_ops ops; 3708360efbdSAlfred Perlstein 3718360efbdSAlfred Perlstein /* VARIABLES PROTECTED BY ops_lock: ops */ 3728360efbdSAlfred Perlstein 3738360efbdSAlfred Perlstein mutex_lock(&ops_lock); 3748360efbdSAlfred Perlstein if (ops.ah_nextverf == NULL) { 3758360efbdSAlfred Perlstein ops.ah_nextverf = authunix_nextverf; 3768360efbdSAlfred Perlstein ops.ah_marshal = authunix_marshal; 3778360efbdSAlfred Perlstein ops.ah_validate = authunix_validate; 3788360efbdSAlfred Perlstein ops.ah_refresh = authunix_refresh; 3798360efbdSAlfred Perlstein ops.ah_destroy = authunix_destroy; 3808360efbdSAlfred Perlstein } 3818360efbdSAlfred Perlstein mutex_unlock(&ops_lock); 3828360efbdSAlfred Perlstein return (&ops); 3838360efbdSAlfred Perlstein } 384