174462Salfred/* $NetBSD: auth_unix.c,v 1.18 2000/07/06 03:03:30 christos Exp $ */ 274462Salfred 3261046Smav/*- 4261046Smav * Copyright (c) 2009, Sun Microsystems, Inc. 5261046Smav * All rights reserved. 68870Srgrimes * 7261046Smav * Redistribution and use in source and binary forms, with or without 8261046Smav * modification, are permitted provided that the following conditions are met: 9261046Smav * - Redistributions of source code must retain the above copyright notice, 10261046Smav * this list of conditions and the following disclaimer. 11261046Smav * - Redistributions in binary form must reproduce the above copyright notice, 12261046Smav * this list of conditions and the following disclaimer in the documentation 13261046Smav * and/or other materials provided with the distribution. 14261046Smav * - Neither the name of Sun Microsystems, Inc. nor the names of its 15261046Smav * contributors may be used to endorse or promote products derived 16261046Smav * from this software without specific prior written permission. 17261046Smav * 18261046Smav * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19261046Smav * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20261046Smav * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21261046Smav * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22261046Smav * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23261046Smav * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24261046Smav * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25261046Smav * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26261046Smav * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27261046Smav * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28261046Smav * 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: stable/10/lib/libc/rpc/auth_unix.c 309487 2016-12-03 17:27:28Z ngie $"); 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 * 94309487Sngieauthunix_create(char *machname, u_int uid, u_int gid, int len, u_int *aup_gids) 951901Swollman{ 961901Swollman struct authunix_parms aup; 971901Swollman char mymem[MAX_AUTH_BYTES]; 981901Swollman struct timeval now; 991901Swollman XDR xdrs; 10074462Salfred AUTH *auth; 10174462Salfred struct audata *au; 1021901Swollman 1031901Swollman /* 1041901Swollman * Allocate and set up auth handle 1051901Swollman */ 10674462Salfred au = NULL; 10774462Salfred auth = mem_alloc(sizeof(*auth)); 10855206Speter#ifndef _KERNEL 1091901Swollman if (auth == NULL) { 11074462Salfred warnx("authunix_create: out of memory"); 11174462Salfred goto cleanup_authunix_create; 1121901Swollman } 1131901Swollman#endif 11474462Salfred au = mem_alloc(sizeof(*au)); 11555206Speter#ifndef _KERNEL 1161901Swollman if (au == NULL) { 11774462Salfred warnx("authunix_create: out of memory"); 11874462Salfred goto cleanup_authunix_create; 1191901Swollman } 1201901Swollman#endif 12174462Salfred auth->ah_ops = authunix_ops(); 1221901Swollman auth->ah_private = (caddr_t)au; 1231901Swollman auth->ah_verf = au->au_shcred = _null_auth; 1241901Swollman au->au_shfaults = 0; 12574462Salfred au->au_origcred.oa_base = NULL; 1261901Swollman 1271901Swollman /* 1281901Swollman * fill in param struct from the given params 1291901Swollman */ 13074462Salfred (void)gettimeofday(&now, NULL); 1311901Swollman aup.aup_time = now.tv_sec; 1321901Swollman aup.aup_machname = machname; 1331901Swollman aup.aup_uid = uid; 1341901Swollman aup.aup_gid = gid; 13574462Salfred aup.aup_len = (u_int)len; 1361901Swollman aup.aup_gids = aup_gids; 1371901Swollman 1381901Swollman /* 1391901Swollman * Serialize the parameters into origcred 1401901Swollman */ 1411901Swollman xdrmem_create(&xdrs, mymem, MAX_AUTH_BYTES, XDR_ENCODE); 14274462Salfred if (! xdr_authunix_parms(&xdrs, &aup)) 1431901Swollman abort(); 1441901Swollman au->au_origcred.oa_length = len = XDR_GETPOS(&xdrs); 1451901Swollman au->au_origcred.oa_flavor = AUTH_UNIX; 14655206Speter#ifdef _KERNEL 1471901Swollman au->au_origcred.oa_base = mem_alloc((u_int) len); 1481901Swollman#else 1491901Swollman if ((au->au_origcred.oa_base = mem_alloc((u_int) len)) == NULL) { 15074462Salfred warnx("authunix_create: out of memory"); 15174462Salfred goto cleanup_authunix_create; 1521901Swollman } 1531901Swollman#endif 15474462Salfred memmove(au->au_origcred.oa_base, mymem, (size_t)len); 1551901Swollman 1561901Swollman /* 1571901Swollman * set auth handle to reflect new cred. 1581901Swollman */ 1591901Swollman auth->ah_cred = au->au_origcred; 1601901Swollman marshal_new_auth(auth); 1611901Swollman return (auth); 16274462Salfred#ifndef _KERNEL 16374462Salfred cleanup_authunix_create: 16474462Salfred if (auth) 16574462Salfred mem_free(auth, sizeof(*auth)); 16674462Salfred if (au) { 16774462Salfred if (au->au_origcred.oa_base) 16874462Salfred mem_free(au->au_origcred.oa_base, (u_int)len); 16974462Salfred mem_free(au, sizeof(*au)); 17074462Salfred } 17174462Salfred return (NULL); 17274462Salfred#endif 1731901Swollman} 1741901Swollman 1751901Swollman/* 1761901Swollman * Returns an auth handle with parameters determined by doing lots of 1771901Swollman * syscalls. 1781901Swollman */ 1791901SwollmanAUTH * 180309487Sngieauthunix_create_default(void) 1811901Swollman{ 182235143Skib AUTH *auth; 183194494Sbrooks int ngids; 184194494Sbrooks long ngids_max; 18574462Salfred char machname[MAXHOSTNAMELEN + 1]; 18674462Salfred uid_t uid; 18774462Salfred gid_t gid; 188194494Sbrooks gid_t *gids; 1891901Swollman 190194494Sbrooks ngids_max = sysconf(_SC_NGROUPS_MAX) + 1; 191194494Sbrooks gids = malloc(sizeof(gid_t) * ngids_max); 192194494Sbrooks if (gids == NULL) 193194494Sbrooks return (NULL); 194194494Sbrooks 19574462Salfred if (gethostname(machname, sizeof machname) == -1) 1961901Swollman abort(); 19774462Salfred machname[sizeof(machname) - 1] = 0; 19874462Salfred uid = geteuid(); 19974462Salfred gid = getegid(); 200194494Sbrooks if ((ngids = getgroups(ngids_max, gids)) < 0) 2011901Swollman abort(); 202194494Sbrooks if (ngids > NGRPS) 203194494Sbrooks ngids = NGRPS; 204241181Spfg /* XXX: interface problem; we should translate from uid_t and gid_t */ 205241141Spfg auth = authunix_create(machname, uid, gid, ngids, gids); 206235143Skib free(gids); 207235143Skib return (auth); 2081901Swollman} 2091901Swollman 2101901Swollman/* 2111901Swollman * authunix operations 2121901Swollman */ 2131901Swollman 21474462Salfred/* ARGSUSED */ 2151901Swollmanstatic void 216309487Sngieauthunix_nextverf(AUTH *auth) 2171901Swollman{ 2181901Swollman /* no action necessary */ 2191901Swollman} 2201901Swollman 2211901Swollmanstatic bool_t 222309487Sngieauthunix_marshal(AUTH *auth, XDR *xdrs) 2231901Swollman{ 22474462Salfred struct audata *au; 2251901Swollman 22674462Salfred assert(auth != NULL); 22774462Salfred assert(xdrs != NULL); 22874462Salfred 22974462Salfred au = AUTH_PRIVATE(auth); 2301901Swollman return (XDR_PUTBYTES(xdrs, au->au_marshed, au->au_mpos)); 2311901Swollman} 2321901Swollman 2331901Swollmanstatic bool_t 234309487Sngieauthunix_validate(AUTH *auth, struct opaque_auth *verf) 2351901Swollman{ 23674462Salfred struct audata *au; 2371901Swollman XDR xdrs; 2381901Swollman 23974462Salfred assert(auth != NULL); 24074462Salfred assert(verf != NULL); 24174462Salfred 24274462Salfred if (verf->oa_flavor == AUTH_SHORT) { 2431901Swollman au = AUTH_PRIVATE(auth); 24474462Salfred xdrmem_create(&xdrs, verf->oa_base, verf->oa_length, 24574462Salfred XDR_DECODE); 2461901Swollman 2471901Swollman if (au->au_shcred.oa_base != NULL) { 2481901Swollman mem_free(au->au_shcred.oa_base, 2491901Swollman au->au_shcred.oa_length); 2501901Swollman au->au_shcred.oa_base = NULL; 2511901Swollman } 2521901Swollman if (xdr_opaque_auth(&xdrs, &au->au_shcred)) { 2531901Swollman auth->ah_cred = au->au_shcred; 2541901Swollman } else { 2551901Swollman xdrs.x_op = XDR_FREE; 2561901Swollman (void)xdr_opaque_auth(&xdrs, &au->au_shcred); 2571901Swollman au->au_shcred.oa_base = NULL; 2581901Swollman auth->ah_cred = au->au_origcred; 2591901Swollman } 2601901Swollman marshal_new_auth(auth); 2611901Swollman } 2621901Swollman return (TRUE); 2631901Swollman} 2641901Swollman 2651901Swollmanstatic bool_t 26674462Salfredauthunix_refresh(AUTH *auth, void *dummy) 2671901Swollman{ 26874462Salfred struct audata *au = AUTH_PRIVATE(auth); 2691901Swollman struct authunix_parms aup; 2701901Swollman struct timeval now; 2711901Swollman XDR xdrs; 27274462Salfred int stat; 2731901Swollman 27474462Salfred assert(auth != NULL); 27574462Salfred 2761901Swollman if (auth->ah_cred.oa_base == au->au_origcred.oa_base) { 2771901Swollman /* there is no hope. Punt */ 2781901Swollman return (FALSE); 2791901Swollman } 2801901Swollman au->au_shfaults ++; 2811901Swollman 2821901Swollman /* first deserialize the creds back into a struct authunix_parms */ 2831901Swollman aup.aup_machname = NULL; 28474462Salfred aup.aup_gids = NULL; 2851901Swollman xdrmem_create(&xdrs, au->au_origcred.oa_base, 2861901Swollman au->au_origcred.oa_length, XDR_DECODE); 2871901Swollman stat = xdr_authunix_parms(&xdrs, &aup); 2888870Srgrimes if (! stat) 2891901Swollman goto done; 2901901Swollman 2911901Swollman /* update the time and serialize in place */ 29274462Salfred (void)gettimeofday(&now, NULL); 2931901Swollman aup.aup_time = now.tv_sec; 2941901Swollman xdrs.x_op = XDR_ENCODE; 2951901Swollman XDR_SETPOS(&xdrs, 0); 2961901Swollman stat = xdr_authunix_parms(&xdrs, &aup); 2971901Swollman if (! stat) 2981901Swollman goto done; 2991901Swollman auth->ah_cred = au->au_origcred; 3001901Swollman marshal_new_auth(auth); 3011901Swollmandone: 3021901Swollman /* free the struct authunix_parms created by deserializing */ 3031901Swollman xdrs.x_op = XDR_FREE; 3041901Swollman (void)xdr_authunix_parms(&xdrs, &aup); 3051901Swollman XDR_DESTROY(&xdrs); 3061901Swollman return (stat); 3071901Swollman} 3081901Swollman 3091901Swollmanstatic void 310309487Sngieauthunix_destroy(AUTH *auth) 3111901Swollman{ 31274462Salfred struct audata *au; 3131901Swollman 31474462Salfred assert(auth != NULL); 31574462Salfred 31674462Salfred au = AUTH_PRIVATE(auth); 3171901Swollman mem_free(au->au_origcred.oa_base, au->au_origcred.oa_length); 3181901Swollman 3191901Swollman if (au->au_shcred.oa_base != NULL) 3201901Swollman mem_free(au->au_shcred.oa_base, au->au_shcred.oa_length); 3211901Swollman 3221901Swollman mem_free(auth->ah_private, sizeof(struct audata)); 3231901Swollman 3241901Swollman if (auth->ah_verf.oa_base != NULL) 3251901Swollman mem_free(auth->ah_verf.oa_base, auth->ah_verf.oa_length); 3261901Swollman 32774462Salfred mem_free(auth, sizeof(*auth)); 3281901Swollman} 3291901Swollman 3301901Swollman/* 3311901Swollman * Marshals (pre-serializes) an auth struct. 3321901Swollman * sets private data, au_marshed and au_mpos 3331901Swollman */ 33411666Sphkstatic void 335309487Sngiemarshal_new_auth(AUTH *auth) 3361901Swollman{ 33774462Salfred XDR xdr_stream; 33874462Salfred XDR *xdrs = &xdr_stream; 33974462Salfred struct audata *au; 3401901Swollman 34174462Salfred assert(auth != NULL); 34274462Salfred 34374462Salfred au = AUTH_PRIVATE(auth); 3441901Swollman xdrmem_create(xdrs, au->au_marshed, MAX_AUTH_BYTES, XDR_ENCODE); 3451901Swollman if ((! xdr_opaque_auth(xdrs, &(auth->ah_cred))) || 34674462Salfred (! xdr_opaque_auth(xdrs, &(auth->ah_verf)))) 34774462Salfred warnx("auth_none.c - Fatal marshalling problem"); 34874462Salfred else 3491901Swollman au->au_mpos = XDR_GETPOS(xdrs); 3501901Swollman XDR_DESTROY(xdrs); 3511901Swollman} 35274462Salfred 35374462Salfredstatic struct auth_ops * 354309487Sngieauthunix_ops(void) 35574462Salfred{ 35674462Salfred static struct auth_ops ops; 35774462Salfred 35874462Salfred /* VARIABLES PROTECTED BY ops_lock: ops */ 35974462Salfred 36074462Salfred mutex_lock(&ops_lock); 36174462Salfred if (ops.ah_nextverf == NULL) { 36274462Salfred ops.ah_nextverf = authunix_nextverf; 36374462Salfred ops.ah_marshal = authunix_marshal; 36474462Salfred ops.ah_validate = authunix_validate; 36574462Salfred ops.ah_refresh = authunix_refresh; 36674462Salfred ops.ah_destroy = authunix_destroy; 36774462Salfred } 36874462Salfred mutex_unlock(&ops_lock); 36974462Salfred return (&ops); 37074462Salfred} 371