174462Salfred/* $NetBSD: auth_unix.c,v 1.18 2000/07/06 03:03:30 christos Exp $ */ 274462Salfred 3261057Smav/*- 4261057Smav * Copyright (c) 2009, Sun Microsystems, Inc. 5261057Smav * All rights reserved. 68870Srgrimes * 7261057Smav * Redistribution and use in source and binary forms, with or without 8261057Smav * modification, are permitted provided that the following conditions are met: 9261057Smav * - Redistributions of source code must retain the above copyright notice, 10261057Smav * this list of conditions and the following disclaimer. 11261057Smav * - Redistributions in binary form must reproduce the above copyright notice, 12261057Smav * this list of conditions and the following disclaimer in the documentation 13261057Smav * and/or other materials provided with the distribution. 14261057Smav * - Neither the name of Sun Microsystems, Inc. nor the names of its 15261057Smav * contributors may be used to endorse or promote products derived 16261057Smav * from this software without specific prior written permission. 17261057Smav * 18261057Smav * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19261057Smav * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20261057Smav * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21261057Smav * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22261057Smav * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23261057Smav * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24261057Smav * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25261057Smav * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26261057Smav * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27261057Smav * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28261057Smav * POSSIBILITY OF SUCH DAMAGE. 291901Swollman */ 301901Swollman 311901Swollman#if defined(LIBC_SCCS) && !defined(lint) 32136581Sobrienstatic char *sccsid2 = "@(#)auth_unix.c 1.19 87/08/11 Copyr 1984 Sun Micro"; 3374462Salfredstatic char *sccsid = "@(#)auth_unix.c 2.2 88/08/01 4.0 RPCSRC"; 341901Swollman#endif 3592990Sobrien#include <sys/cdefs.h> 3692990Sobrien__FBSDID("$FreeBSD$"); 371901Swollman 381901Swollman/* 398870Srgrimes * auth_unix.c, Implements UNIX style authentication parameters. 408870Srgrimes * 411901Swollman * Copyright (C) 1984, Sun Microsystems, Inc. 421901Swollman * 431901Swollman * The system is very weak. The client uses no encryption for it's 441901Swollman * credentials and only sends null verifiers. The server sends backs 451901Swollman * null verifiers or optionally a verifier that suggests a new short hand 461901Swollman * for the credentials. 471901Swollman * 481901Swollman */ 491901Swollman 5075094Siedowse#include "namespace.h" 5174462Salfred#include "reentrant.h" 5274462Salfred#include <sys/param.h> 5374462Salfred 5474462Salfred#include <assert.h> 5574462Salfred#include <err.h> 561901Swollman#include <stdio.h> 571901Swollman#include <stdlib.h> 5811666Sphk#include <unistd.h> 5911666Sphk#include <string.h> 601901Swollman 611901Swollman#include <rpc/types.h> 621901Swollman#include <rpc/xdr.h> 631901Swollman#include <rpc/auth.h> 641901Swollman#include <rpc/auth_unix.h> 6574462Salfred#include "un-namespace.h" 66156090Sdeischen#include "mt_misc.h" 671901Swollman 6874462Salfred/* auth_unix.c */ 6974462Salfredstatic void authunix_nextverf (AUTH *); 7074462Salfredstatic bool_t authunix_marshal (AUTH *, XDR *); 7174462Salfredstatic bool_t authunix_validate (AUTH *, struct opaque_auth *); 7274462Salfredstatic bool_t authunix_refresh (AUTH *, void *); 7374462Salfredstatic void authunix_destroy (AUTH *); 7474462Salfredstatic void marshal_new_auth (AUTH *); 7574462Salfredstatic struct auth_ops *authunix_ops (void); 761901Swollman 771901Swollman/* 781901Swollman * This struct is pointed to by the ah_private field of an auth_handle. 791901Swollman */ 801901Swollmanstruct audata { 811901Swollman struct opaque_auth au_origcred; /* original credentials */ 821901Swollman struct opaque_auth au_shcred; /* short hand cred */ 831901Swollman u_long au_shfaults; /* short hand cache faults */ 841901Swollman char au_marshed[MAX_AUTH_BYTES]; 851901Swollman u_int au_mpos; /* xdr pos at end of marshed */ 861901Swollman}; 871901Swollman#define AUTH_PRIVATE(auth) ((struct audata *)auth->ah_private) 881901Swollman 891994Swollman/* 901901Swollman * Create a unix style authenticator. 911901Swollman * Returns an auth handle with the given stuff in it. 921901Swollman */ 931901SwollmanAUTH * 941901Swollmanauthunix_create(machname, uid, gid, len, aup_gids) 951901Swollman char *machname; 96241309Spfg u_int uid; 97241309Spfg u_int gid; 9874462Salfred int len; 99241309Spfg u_int *aup_gids; 1001901Swollman{ 1011901Swollman struct authunix_parms aup; 1021901Swollman char mymem[MAX_AUTH_BYTES]; 1031901Swollman struct timeval now; 1041901Swollman XDR xdrs; 10574462Salfred AUTH *auth; 10674462Salfred struct audata *au; 1071901Swollman 1081901Swollman /* 1091901Swollman * Allocate and set up auth handle 1101901Swollman */ 11174462Salfred au = NULL; 11274462Salfred auth = mem_alloc(sizeof(*auth)); 11355206Speter#ifndef _KERNEL 1141901Swollman if (auth == NULL) { 11574462Salfred warnx("authunix_create: out of memory"); 11674462Salfred goto cleanup_authunix_create; 1171901Swollman } 1181901Swollman#endif 11974462Salfred au = mem_alloc(sizeof(*au)); 12055206Speter#ifndef _KERNEL 1211901Swollman if (au == NULL) { 12274462Salfred warnx("authunix_create: out of memory"); 12374462Salfred goto cleanup_authunix_create; 1241901Swollman } 1251901Swollman#endif 12674462Salfred auth->ah_ops = authunix_ops(); 1271901Swollman auth->ah_private = (caddr_t)au; 1281901Swollman auth->ah_verf = au->au_shcred = _null_auth; 1291901Swollman au->au_shfaults = 0; 13074462Salfred au->au_origcred.oa_base = NULL; 1311901Swollman 1321901Swollman /* 1331901Swollman * fill in param struct from the given params 1341901Swollman */ 13574462Salfred (void)gettimeofday(&now, NULL); 1361901Swollman aup.aup_time = now.tv_sec; 1371901Swollman aup.aup_machname = machname; 1381901Swollman aup.aup_uid = uid; 1391901Swollman aup.aup_gid = gid; 14074462Salfred aup.aup_len = (u_int)len; 1411901Swollman aup.aup_gids = aup_gids; 1421901Swollman 1431901Swollman /* 1441901Swollman * Serialize the parameters into origcred 1451901Swollman */ 1461901Swollman xdrmem_create(&xdrs, mymem, MAX_AUTH_BYTES, XDR_ENCODE); 14774462Salfred if (! xdr_authunix_parms(&xdrs, &aup)) 1481901Swollman abort(); 1491901Swollman au->au_origcred.oa_length = len = XDR_GETPOS(&xdrs); 1501901Swollman au->au_origcred.oa_flavor = AUTH_UNIX; 15155206Speter#ifdef _KERNEL 1521901Swollman au->au_origcred.oa_base = mem_alloc((u_int) len); 1531901Swollman#else 1541901Swollman if ((au->au_origcred.oa_base = mem_alloc((u_int) len)) == NULL) { 15574462Salfred warnx("authunix_create: out of memory"); 15674462Salfred goto cleanup_authunix_create; 1571901Swollman } 1581901Swollman#endif 15974462Salfred memmove(au->au_origcred.oa_base, mymem, (size_t)len); 1601901Swollman 1611901Swollman /* 1621901Swollman * set auth handle to reflect new cred. 1631901Swollman */ 1641901Swollman auth->ah_cred = au->au_origcred; 1651901Swollman marshal_new_auth(auth); 1661901Swollman return (auth); 16774462Salfred#ifndef _KERNEL 16874462Salfred cleanup_authunix_create: 16974462Salfred if (auth) 17074462Salfred mem_free(auth, sizeof(*auth)); 17174462Salfred if (au) { 17274462Salfred if (au->au_origcred.oa_base) 17374462Salfred mem_free(au->au_origcred.oa_base, (u_int)len); 17474462Salfred mem_free(au, sizeof(*au)); 17574462Salfred } 17674462Salfred return (NULL); 17774462Salfred#endif 1781901Swollman} 1791901Swollman 1801901Swollman/* 1811901Swollman * Returns an auth handle with parameters determined by doing lots of 1821901Swollman * syscalls. 1831901Swollman */ 1841901SwollmanAUTH * 1851901Swollmanauthunix_create_default() 1861901Swollman{ 187235466Skib AUTH *auth; 188194494Sbrooks int ngids; 189194494Sbrooks long ngids_max; 19074462Salfred char machname[MAXHOSTNAMELEN + 1]; 191241309Spfg u_int uid; 192241309Spfg u_int gid; 193241309Spfg u_int *gids; 1941901Swollman 195194494Sbrooks ngids_max = sysconf(_SC_NGROUPS_MAX) + 1; 196194494Sbrooks gids = malloc(sizeof(gid_t) * ngids_max); 197194494Sbrooks if (gids == NULL) 198194494Sbrooks return (NULL); 199194494Sbrooks 20074462Salfred if (gethostname(machname, sizeof machname) == -1) 2011901Swollman abort(); 20274462Salfred machname[sizeof(machname) - 1] = 0; 20374462Salfred uid = geteuid(); 20474462Salfred gid = getegid(); 205194494Sbrooks if ((ngids = getgroups(ngids_max, gids)) < 0) 2061901Swollman abort(); 207194494Sbrooks if (ngids > NGRPS) 208194494Sbrooks ngids = NGRPS; 209241309Spfg /* XXX: interface problem; we should translate from uid_t and gid_t */ 210241309Spfg auth = authunix_create(machname, uid, gid, ngids, gids); 211235466Skib free(gids); 212235466Skib return (auth); 2131901Swollman} 2141901Swollman 2151901Swollman/* 2161901Swollman * authunix operations 2171901Swollman */ 2181901Swollman 21974462Salfred/* ARGSUSED */ 2201901Swollmanstatic void 2211901Swollmanauthunix_nextverf(auth) 2221901Swollman AUTH *auth; 2231901Swollman{ 2241901Swollman /* no action necessary */ 2251901Swollman} 2261901Swollman 2271901Swollmanstatic bool_t 2281901Swollmanauthunix_marshal(auth, xdrs) 2291901Swollman AUTH *auth; 2301901Swollman XDR *xdrs; 2311901Swollman{ 23274462Salfred struct audata *au; 2331901Swollman 23474462Salfred assert(auth != NULL); 23574462Salfred assert(xdrs != NULL); 23674462Salfred 23774462Salfred au = AUTH_PRIVATE(auth); 2381901Swollman return (XDR_PUTBYTES(xdrs, au->au_marshed, au->au_mpos)); 2391901Swollman} 2401901Swollman 2411901Swollmanstatic bool_t 2421901Swollmanauthunix_validate(auth, verf) 24374462Salfred AUTH *auth; 24474462Salfred struct opaque_auth *verf; 2451901Swollman{ 24674462Salfred struct audata *au; 2471901Swollman XDR xdrs; 2481901Swollman 24974462Salfred assert(auth != NULL); 25074462Salfred assert(verf != NULL); 25174462Salfred 25274462Salfred if (verf->oa_flavor == AUTH_SHORT) { 2531901Swollman au = AUTH_PRIVATE(auth); 25474462Salfred xdrmem_create(&xdrs, verf->oa_base, verf->oa_length, 25574462Salfred XDR_DECODE); 2561901Swollman 2571901Swollman if (au->au_shcred.oa_base != NULL) { 2581901Swollman mem_free(au->au_shcred.oa_base, 2591901Swollman au->au_shcred.oa_length); 2601901Swollman au->au_shcred.oa_base = NULL; 2611901Swollman } 2621901Swollman if (xdr_opaque_auth(&xdrs, &au->au_shcred)) { 2631901Swollman auth->ah_cred = au->au_shcred; 2641901Swollman } else { 2651901Swollman xdrs.x_op = XDR_FREE; 2661901Swollman (void)xdr_opaque_auth(&xdrs, &au->au_shcred); 2671901Swollman au->au_shcred.oa_base = NULL; 2681901Swollman auth->ah_cred = au->au_origcred; 2691901Swollman } 2701901Swollman marshal_new_auth(auth); 2711901Swollman } 2721901Swollman return (TRUE); 2731901Swollman} 2741901Swollman 2751901Swollmanstatic bool_t 27674462Salfredauthunix_refresh(AUTH *auth, void *dummy) 2771901Swollman{ 27874462Salfred struct audata *au = AUTH_PRIVATE(auth); 2791901Swollman struct authunix_parms aup; 2801901Swollman struct timeval now; 2811901Swollman XDR xdrs; 28274462Salfred int stat; 2831901Swollman 28474462Salfred assert(auth != NULL); 28574462Salfred 2861901Swollman if (auth->ah_cred.oa_base == au->au_origcred.oa_base) { 2871901Swollman /* there is no hope. Punt */ 2881901Swollman return (FALSE); 2891901Swollman } 2901901Swollman au->au_shfaults ++; 2911901Swollman 2921901Swollman /* first deserialize the creds back into a struct authunix_parms */ 2931901Swollman aup.aup_machname = NULL; 29474462Salfred aup.aup_gids = NULL; 2951901Swollman xdrmem_create(&xdrs, au->au_origcred.oa_base, 2961901Swollman au->au_origcred.oa_length, XDR_DECODE); 2971901Swollman stat = xdr_authunix_parms(&xdrs, &aup); 2988870Srgrimes if (! stat) 2991901Swollman goto done; 3001901Swollman 3011901Swollman /* update the time and serialize in place */ 30274462Salfred (void)gettimeofday(&now, NULL); 3031901Swollman aup.aup_time = now.tv_sec; 3041901Swollman xdrs.x_op = XDR_ENCODE; 3051901Swollman XDR_SETPOS(&xdrs, 0); 3061901Swollman stat = xdr_authunix_parms(&xdrs, &aup); 3071901Swollman if (! stat) 3081901Swollman goto done; 3091901Swollman auth->ah_cred = au->au_origcred; 3101901Swollman marshal_new_auth(auth); 3111901Swollmandone: 3121901Swollman /* free the struct authunix_parms created by deserializing */ 3131901Swollman xdrs.x_op = XDR_FREE; 3141901Swollman (void)xdr_authunix_parms(&xdrs, &aup); 3151901Swollman XDR_DESTROY(&xdrs); 3161901Swollman return (stat); 3171901Swollman} 3181901Swollman 3191901Swollmanstatic void 3201901Swollmanauthunix_destroy(auth) 32174462Salfred AUTH *auth; 3221901Swollman{ 32374462Salfred struct audata *au; 3241901Swollman 32574462Salfred assert(auth != NULL); 32674462Salfred 32774462Salfred au = AUTH_PRIVATE(auth); 3281901Swollman mem_free(au->au_origcred.oa_base, au->au_origcred.oa_length); 3291901Swollman 3301901Swollman if (au->au_shcred.oa_base != NULL) 3311901Swollman mem_free(au->au_shcred.oa_base, au->au_shcred.oa_length); 3321901Swollman 3331901Swollman mem_free(auth->ah_private, sizeof(struct audata)); 3341901Swollman 3351901Swollman if (auth->ah_verf.oa_base != NULL) 3361901Swollman mem_free(auth->ah_verf.oa_base, auth->ah_verf.oa_length); 3371901Swollman 33874462Salfred mem_free(auth, sizeof(*auth)); 3391901Swollman} 3401901Swollman 3411901Swollman/* 3421901Swollman * Marshals (pre-serializes) an auth struct. 3431901Swollman * sets private data, au_marshed and au_mpos 3441901Swollman */ 34511666Sphkstatic void 3461901Swollmanmarshal_new_auth(auth) 34774462Salfred AUTH *auth; 3481901Swollman{ 34974462Salfred XDR xdr_stream; 35074462Salfred XDR *xdrs = &xdr_stream; 35174462Salfred struct audata *au; 3521901Swollman 35374462Salfred assert(auth != NULL); 35474462Salfred 35574462Salfred au = AUTH_PRIVATE(auth); 3561901Swollman xdrmem_create(xdrs, au->au_marshed, MAX_AUTH_BYTES, XDR_ENCODE); 3571901Swollman if ((! xdr_opaque_auth(xdrs, &(auth->ah_cred))) || 35874462Salfred (! xdr_opaque_auth(xdrs, &(auth->ah_verf)))) 35974462Salfred warnx("auth_none.c - Fatal marshalling problem"); 36074462Salfred else 3611901Swollman au->au_mpos = XDR_GETPOS(xdrs); 3621901Swollman XDR_DESTROY(xdrs); 3631901Swollman} 36474462Salfred 36574462Salfredstatic struct auth_ops * 36674462Salfredauthunix_ops() 36774462Salfred{ 36874462Salfred static struct auth_ops ops; 36974462Salfred 37074462Salfred /* VARIABLES PROTECTED BY ops_lock: ops */ 37174462Salfred 37274462Salfred mutex_lock(&ops_lock); 37374462Salfred if (ops.ah_nextverf == NULL) { 37474462Salfred ops.ah_nextverf = authunix_nextverf; 37574462Salfred ops.ah_marshal = authunix_marshal; 37674462Salfred ops.ah_validate = authunix_validate; 37774462Salfred ops.ah_refresh = authunix_refresh; 37874462Salfred ops.ah_destroy = authunix_destroy; 37974462Salfred } 38074462Salfred mutex_unlock(&ops_lock); 38174462Salfred return (&ops); 38274462Salfred} 383