18360efbdSAlfred Perlstein /* $NetBSD: auth_unix.c,v 1.18 2000/07/06 03:03:30 christos Exp $ */ 28360efbdSAlfred Perlstein 32e322d37SHiroki Sato /*- 42e322d37SHiroki Sato * Copyright (c) 2009, Sun Microsystems, Inc. 52e322d37SHiroki Sato * All rights reserved. 699064799SGarrett Wollman * 72e322d37SHiroki Sato * Redistribution and use in source and binary forms, with or without 82e322d37SHiroki Sato * modification, are permitted provided that the following conditions are met: 92e322d37SHiroki Sato * - Redistributions of source code must retain the above copyright notice, 102e322d37SHiroki Sato * this list of conditions and the following disclaimer. 112e322d37SHiroki Sato * - Redistributions in binary form must reproduce the above copyright notice, 122e322d37SHiroki Sato * this list of conditions and the following disclaimer in the documentation 132e322d37SHiroki Sato * and/or other materials provided with the distribution. 142e322d37SHiroki Sato * - Neither the name of Sun Microsystems, Inc. nor the names of its 152e322d37SHiroki Sato * contributors may be used to endorse or promote products derived 162e322d37SHiroki Sato * from this software without specific prior written permission. 1799064799SGarrett Wollman * 182e322d37SHiroki Sato * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 192e322d37SHiroki Sato * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 202e322d37SHiroki Sato * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 212e322d37SHiroki Sato * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 222e322d37SHiroki Sato * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 232e322d37SHiroki Sato * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 242e322d37SHiroki Sato * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 252e322d37SHiroki Sato * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 262e322d37SHiroki Sato * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 272e322d37SHiroki Sato * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 282e322d37SHiroki Sato * POSSIBILITY OF SUCH DAMAGE. 2999064799SGarrett Wollman */ 3099064799SGarrett Wollman 3199064799SGarrett Wollman #if defined(LIBC_SCCS) && !defined(lint) 32a986ef57SDavid E. O'Brien static char *sccsid2 = "@(#)auth_unix.c 1.19 87/08/11 Copyr 1984 Sun Micro"; 338360efbdSAlfred Perlstein static char *sccsid = "@(#)auth_unix.c 2.2 88/08/01 4.0 RPCSRC"; 3499064799SGarrett Wollman #endif 35d3d20c82SDavid E. O'Brien #include <sys/cdefs.h> 36d3d20c82SDavid E. O'Brien __FBSDID("$FreeBSD$"); 3799064799SGarrett Wollman 3899064799SGarrett Wollman /* 3999064799SGarrett Wollman * auth_unix.c, Implements UNIX style authentication parameters. 4099064799SGarrett Wollman * 4199064799SGarrett Wollman * Copyright (C) 1984, Sun Microsystems, Inc. 4299064799SGarrett Wollman * 4399064799SGarrett Wollman * The system is very weak. The client uses no encryption for it's 4499064799SGarrett Wollman * credentials and only sends null verifiers. The server sends backs 4599064799SGarrett Wollman * null verifiers or optionally a verifier that suggests a new short hand 4699064799SGarrett Wollman * for the credentials. 4799064799SGarrett Wollman * 4899064799SGarrett Wollman */ 4999064799SGarrett Wollman 508360efbdSAlfred Perlstein #include "namespace.h" 519f5afc13SIan Dowse #include "reentrant.h" 528360efbdSAlfred Perlstein #include <sys/param.h> 538360efbdSAlfred Perlstein 548360efbdSAlfred Perlstein #include <assert.h> 558360efbdSAlfred Perlstein #include <err.h> 5699064799SGarrett Wollman #include <stdio.h> 5799064799SGarrett Wollman #include <stdlib.h> 584c3af266SPoul-Henning Kamp #include <unistd.h> 594c3af266SPoul-Henning Kamp #include <string.h> 6099064799SGarrett Wollman 6199064799SGarrett Wollman #include <rpc/types.h> 6299064799SGarrett Wollman #include <rpc/xdr.h> 6399064799SGarrett Wollman #include <rpc/auth.h> 6499064799SGarrett Wollman #include <rpc/auth_unix.h> 658360efbdSAlfred Perlstein #include "un-namespace.h" 66235baf26SDaniel Eischen #include "mt_misc.h" 6799064799SGarrett Wollman 688360efbdSAlfred Perlstein /* auth_unix.c */ 698360efbdSAlfred Perlstein static void authunix_nextverf (AUTH *); 708360efbdSAlfred Perlstein static bool_t authunix_marshal (AUTH *, XDR *); 718360efbdSAlfred Perlstein static bool_t authunix_validate (AUTH *, struct opaque_auth *); 728360efbdSAlfred Perlstein static bool_t authunix_refresh (AUTH *, void *); 738360efbdSAlfred Perlstein static void authunix_destroy (AUTH *); 748360efbdSAlfred Perlstein static void marshal_new_auth (AUTH *); 758360efbdSAlfred Perlstein static struct auth_ops *authunix_ops (void); 7699064799SGarrett Wollman 7799064799SGarrett Wollman /* 7899064799SGarrett Wollman * This struct is pointed to by the ah_private field of an auth_handle. 7999064799SGarrett Wollman */ 8099064799SGarrett Wollman struct audata { 8199064799SGarrett Wollman struct opaque_auth au_origcred; /* original credentials */ 8299064799SGarrett Wollman struct opaque_auth au_shcred; /* short hand cred */ 8399064799SGarrett Wollman u_long au_shfaults; /* short hand cache faults */ 8499064799SGarrett Wollman char au_marshed[MAX_AUTH_BYTES]; 8599064799SGarrett Wollman u_int au_mpos; /* xdr pos at end of marshed */ 8699064799SGarrett Wollman }; 8799064799SGarrett Wollman #define AUTH_PRIVATE(auth) ((struct audata *)auth->ah_private) 8899064799SGarrett Wollman 8999064799SGarrett Wollman /* 9099064799SGarrett Wollman * Create a unix style authenticator. 9199064799SGarrett Wollman * Returns an auth handle with the given stuff in it. 9299064799SGarrett Wollman */ 9399064799SGarrett Wollman AUTH * 94*587cf682SCraig Rodrigues authunix_create(char *machname, u_int uid, u_int gid, int len, u_int *aup_gids) 9599064799SGarrett Wollman { 9699064799SGarrett Wollman struct authunix_parms aup; 9799064799SGarrett Wollman char mymem[MAX_AUTH_BYTES]; 9899064799SGarrett Wollman struct timeval now; 9999064799SGarrett Wollman XDR xdrs; 1008360efbdSAlfred Perlstein AUTH *auth; 1018360efbdSAlfred Perlstein struct audata *au; 10299064799SGarrett Wollman 10399064799SGarrett Wollman /* 10499064799SGarrett Wollman * Allocate and set up auth handle 10599064799SGarrett Wollman */ 1068360efbdSAlfred Perlstein au = NULL; 1078360efbdSAlfred Perlstein auth = mem_alloc(sizeof(*auth)); 108c4473420SPeter Wemm #ifndef _KERNEL 10999064799SGarrett Wollman if (auth == NULL) { 1108360efbdSAlfred Perlstein warnx("authunix_create: out of memory"); 1118360efbdSAlfred Perlstein goto cleanup_authunix_create; 11299064799SGarrett Wollman } 11399064799SGarrett Wollman #endif 1148360efbdSAlfred Perlstein au = mem_alloc(sizeof(*au)); 115c4473420SPeter Wemm #ifndef _KERNEL 11699064799SGarrett Wollman if (au == NULL) { 1178360efbdSAlfred Perlstein warnx("authunix_create: out of memory"); 1188360efbdSAlfred Perlstein goto cleanup_authunix_create; 11999064799SGarrett Wollman } 12099064799SGarrett Wollman #endif 1218360efbdSAlfred Perlstein auth->ah_ops = authunix_ops(); 12299064799SGarrett Wollman auth->ah_private = (caddr_t)au; 12399064799SGarrett Wollman auth->ah_verf = au->au_shcred = _null_auth; 12499064799SGarrett Wollman au->au_shfaults = 0; 1258360efbdSAlfred Perlstein au->au_origcred.oa_base = NULL; 12699064799SGarrett Wollman 12799064799SGarrett Wollman /* 12899064799SGarrett Wollman * fill in param struct from the given params 12999064799SGarrett Wollman */ 1308360efbdSAlfred Perlstein (void)gettimeofday(&now, NULL); 13199064799SGarrett Wollman aup.aup_time = now.tv_sec; 13299064799SGarrett Wollman aup.aup_machname = machname; 13399064799SGarrett Wollman aup.aup_uid = uid; 13499064799SGarrett Wollman aup.aup_gid = gid; 13599064799SGarrett Wollman aup.aup_len = (u_int)len; 13699064799SGarrett Wollman aup.aup_gids = aup_gids; 13799064799SGarrett Wollman 13899064799SGarrett Wollman /* 13999064799SGarrett Wollman * Serialize the parameters into origcred 14099064799SGarrett Wollman */ 14199064799SGarrett Wollman xdrmem_create(&xdrs, mymem, MAX_AUTH_BYTES, XDR_ENCODE); 14299064799SGarrett Wollman if (! xdr_authunix_parms(&xdrs, &aup)) 14399064799SGarrett Wollman abort(); 14499064799SGarrett Wollman au->au_origcred.oa_length = len = XDR_GETPOS(&xdrs); 14599064799SGarrett Wollman au->au_origcred.oa_flavor = AUTH_UNIX; 146c4473420SPeter Wemm #ifdef _KERNEL 14799064799SGarrett Wollman au->au_origcred.oa_base = mem_alloc((u_int) len); 14899064799SGarrett Wollman #else 14999064799SGarrett Wollman if ((au->au_origcred.oa_base = mem_alloc((u_int) len)) == NULL) { 1508360efbdSAlfred Perlstein warnx("authunix_create: out of memory"); 1518360efbdSAlfred Perlstein goto cleanup_authunix_create; 15299064799SGarrett Wollman } 15399064799SGarrett Wollman #endif 1548360efbdSAlfred Perlstein memmove(au->au_origcred.oa_base, mymem, (size_t)len); 15599064799SGarrett Wollman 15699064799SGarrett Wollman /* 15799064799SGarrett Wollman * set auth handle to reflect new cred. 15899064799SGarrett Wollman */ 15999064799SGarrett Wollman auth->ah_cred = au->au_origcred; 16099064799SGarrett Wollman marshal_new_auth(auth); 16199064799SGarrett Wollman return (auth); 1628360efbdSAlfred Perlstein #ifndef _KERNEL 1638360efbdSAlfred Perlstein cleanup_authunix_create: 1648360efbdSAlfred Perlstein if (auth) 1658360efbdSAlfred Perlstein mem_free(auth, sizeof(*auth)); 1668360efbdSAlfred Perlstein if (au) { 1678360efbdSAlfred Perlstein if (au->au_origcred.oa_base) 1688360efbdSAlfred Perlstein mem_free(au->au_origcred.oa_base, (u_int)len); 1698360efbdSAlfred Perlstein mem_free(au, sizeof(*au)); 1708360efbdSAlfred Perlstein } 1718360efbdSAlfred Perlstein return (NULL); 1728360efbdSAlfred Perlstein #endif 17399064799SGarrett Wollman } 17499064799SGarrett Wollman 17599064799SGarrett Wollman /* 17699064799SGarrett Wollman * Returns an auth handle with parameters determined by doing lots of 17799064799SGarrett Wollman * syscalls. 17899064799SGarrett Wollman */ 17999064799SGarrett Wollman AUTH * 180*587cf682SCraig Rodrigues authunix_create_default(void) 18199064799SGarrett Wollman { 1829a36eaa3SKonstantin Belousov AUTH *auth; 18354404cfbSBrooks Davis int ngids; 18454404cfbSBrooks Davis long ngids_max; 1858360efbdSAlfred Perlstein char machname[MAXHOSTNAMELEN + 1]; 1868360efbdSAlfred Perlstein uid_t uid; 1878360efbdSAlfred Perlstein gid_t gid; 18854404cfbSBrooks Davis gid_t *gids; 18954404cfbSBrooks Davis 19054404cfbSBrooks Davis ngids_max = sysconf(_SC_NGROUPS_MAX) + 1; 19154404cfbSBrooks Davis gids = malloc(sizeof(gid_t) * ngids_max); 19254404cfbSBrooks Davis if (gids == NULL) 19354404cfbSBrooks Davis return (NULL); 19499064799SGarrett Wollman 1958360efbdSAlfred Perlstein if (gethostname(machname, sizeof machname) == -1) 19699064799SGarrett Wollman abort(); 1978360efbdSAlfred Perlstein machname[sizeof(machname) - 1] = 0; 1988360efbdSAlfred Perlstein uid = geteuid(); 1998360efbdSAlfred Perlstein gid = getegid(); 20054404cfbSBrooks Davis if ((ngids = getgroups(ngids_max, gids)) < 0) 20199064799SGarrett Wollman abort(); 20254404cfbSBrooks Davis if (ngids > NGRPS) 20354404cfbSBrooks Davis ngids = NGRPS; 2040d1040e5SPedro F. Giffuni /* XXX: interface problem; we should translate from uid_t and gid_t */ 205f3c3ef7bSPedro F. Giffuni auth = authunix_create(machname, uid, gid, ngids, gids); 2069a36eaa3SKonstantin Belousov free(gids); 2079a36eaa3SKonstantin Belousov return (auth); 20899064799SGarrett Wollman } 20999064799SGarrett Wollman 21099064799SGarrett Wollman /* 21199064799SGarrett Wollman * authunix operations 21299064799SGarrett Wollman */ 21399064799SGarrett Wollman 2148360efbdSAlfred Perlstein /* ARGSUSED */ 21599064799SGarrett Wollman static void 216*587cf682SCraig Rodrigues authunix_nextverf(AUTH *auth) 21799064799SGarrett Wollman { 21899064799SGarrett Wollman /* no action necessary */ 21999064799SGarrett Wollman } 22099064799SGarrett Wollman 22199064799SGarrett Wollman static bool_t 222*587cf682SCraig Rodrigues authunix_marshal(AUTH *auth, XDR *xdrs) 22399064799SGarrett Wollman { 2248360efbdSAlfred Perlstein struct audata *au; 22599064799SGarrett Wollman 2268360efbdSAlfred Perlstein assert(auth != NULL); 2278360efbdSAlfred Perlstein assert(xdrs != NULL); 2288360efbdSAlfred Perlstein 2298360efbdSAlfred Perlstein au = AUTH_PRIVATE(auth); 23099064799SGarrett Wollman return (XDR_PUTBYTES(xdrs, au->au_marshed, au->au_mpos)); 23199064799SGarrett Wollman } 23299064799SGarrett Wollman 23399064799SGarrett Wollman static bool_t 234*587cf682SCraig Rodrigues authunix_validate(AUTH *auth, struct opaque_auth *verf) 23599064799SGarrett Wollman { 2368360efbdSAlfred Perlstein struct audata *au; 23799064799SGarrett Wollman XDR xdrs; 23899064799SGarrett Wollman 2398360efbdSAlfred Perlstein assert(auth != NULL); 2408360efbdSAlfred Perlstein assert(verf != NULL); 2418360efbdSAlfred Perlstein 2428360efbdSAlfred Perlstein if (verf->oa_flavor == AUTH_SHORT) { 24399064799SGarrett Wollman au = AUTH_PRIVATE(auth); 2448360efbdSAlfred Perlstein xdrmem_create(&xdrs, verf->oa_base, verf->oa_length, 2458360efbdSAlfred Perlstein XDR_DECODE); 24699064799SGarrett Wollman 24799064799SGarrett Wollman if (au->au_shcred.oa_base != NULL) { 24899064799SGarrett Wollman mem_free(au->au_shcred.oa_base, 24999064799SGarrett Wollman au->au_shcred.oa_length); 25099064799SGarrett Wollman au->au_shcred.oa_base = NULL; 25199064799SGarrett Wollman } 25299064799SGarrett Wollman if (xdr_opaque_auth(&xdrs, &au->au_shcred)) { 25399064799SGarrett Wollman auth->ah_cred = au->au_shcred; 25499064799SGarrett Wollman } else { 25599064799SGarrett Wollman xdrs.x_op = XDR_FREE; 25699064799SGarrett Wollman (void)xdr_opaque_auth(&xdrs, &au->au_shcred); 25799064799SGarrett Wollman au->au_shcred.oa_base = NULL; 25899064799SGarrett Wollman auth->ah_cred = au->au_origcred; 25999064799SGarrett Wollman } 26099064799SGarrett Wollman marshal_new_auth(auth); 26199064799SGarrett Wollman } 26299064799SGarrett Wollman return (TRUE); 26399064799SGarrett Wollman } 26499064799SGarrett Wollman 26599064799SGarrett Wollman static bool_t 2668360efbdSAlfred Perlstein authunix_refresh(AUTH *auth, void *dummy) 26799064799SGarrett Wollman { 2688360efbdSAlfred Perlstein struct audata *au = AUTH_PRIVATE(auth); 26999064799SGarrett Wollman struct authunix_parms aup; 27099064799SGarrett Wollman struct timeval now; 27199064799SGarrett Wollman XDR xdrs; 2728360efbdSAlfred Perlstein int stat; 2738360efbdSAlfred Perlstein 2748360efbdSAlfred Perlstein assert(auth != NULL); 27599064799SGarrett Wollman 27699064799SGarrett Wollman if (auth->ah_cred.oa_base == au->au_origcred.oa_base) { 27799064799SGarrett Wollman /* there is no hope. Punt */ 27899064799SGarrett Wollman return (FALSE); 27999064799SGarrett Wollman } 28099064799SGarrett Wollman au->au_shfaults ++; 28199064799SGarrett Wollman 28299064799SGarrett Wollman /* first deserialize the creds back into a struct authunix_parms */ 28399064799SGarrett Wollman aup.aup_machname = NULL; 2848360efbdSAlfred Perlstein aup.aup_gids = NULL; 28599064799SGarrett Wollman xdrmem_create(&xdrs, au->au_origcred.oa_base, 28699064799SGarrett Wollman au->au_origcred.oa_length, XDR_DECODE); 28799064799SGarrett Wollman stat = xdr_authunix_parms(&xdrs, &aup); 28899064799SGarrett Wollman if (! stat) 28999064799SGarrett Wollman goto done; 29099064799SGarrett Wollman 29199064799SGarrett Wollman /* update the time and serialize in place */ 2928360efbdSAlfred Perlstein (void)gettimeofday(&now, NULL); 29399064799SGarrett Wollman aup.aup_time = now.tv_sec; 29499064799SGarrett Wollman xdrs.x_op = XDR_ENCODE; 29599064799SGarrett Wollman XDR_SETPOS(&xdrs, 0); 29699064799SGarrett Wollman stat = xdr_authunix_parms(&xdrs, &aup); 29799064799SGarrett Wollman if (! stat) 29899064799SGarrett Wollman goto done; 29999064799SGarrett Wollman auth->ah_cred = au->au_origcred; 30099064799SGarrett Wollman marshal_new_auth(auth); 30199064799SGarrett Wollman done: 30299064799SGarrett Wollman /* free the struct authunix_parms created by deserializing */ 30399064799SGarrett Wollman xdrs.x_op = XDR_FREE; 30499064799SGarrett Wollman (void)xdr_authunix_parms(&xdrs, &aup); 30599064799SGarrett Wollman XDR_DESTROY(&xdrs); 30699064799SGarrett Wollman return (stat); 30799064799SGarrett Wollman } 30899064799SGarrett Wollman 30999064799SGarrett Wollman static void 310*587cf682SCraig Rodrigues authunix_destroy(AUTH *auth) 31199064799SGarrett Wollman { 3128360efbdSAlfred Perlstein struct audata *au; 31399064799SGarrett Wollman 3148360efbdSAlfred Perlstein assert(auth != NULL); 3158360efbdSAlfred Perlstein 3168360efbdSAlfred Perlstein au = AUTH_PRIVATE(auth); 31799064799SGarrett Wollman mem_free(au->au_origcred.oa_base, au->au_origcred.oa_length); 31899064799SGarrett Wollman 31999064799SGarrett Wollman if (au->au_shcred.oa_base != NULL) 32099064799SGarrett Wollman mem_free(au->au_shcred.oa_base, au->au_shcred.oa_length); 32199064799SGarrett Wollman 32299064799SGarrett Wollman mem_free(auth->ah_private, sizeof(struct audata)); 32399064799SGarrett Wollman 32499064799SGarrett Wollman if (auth->ah_verf.oa_base != NULL) 32599064799SGarrett Wollman mem_free(auth->ah_verf.oa_base, auth->ah_verf.oa_length); 32699064799SGarrett Wollman 3278360efbdSAlfred Perlstein mem_free(auth, sizeof(*auth)); 32899064799SGarrett Wollman } 32999064799SGarrett Wollman 33099064799SGarrett Wollman /* 33199064799SGarrett Wollman * Marshals (pre-serializes) an auth struct. 33299064799SGarrett Wollman * sets private data, au_marshed and au_mpos 33399064799SGarrett Wollman */ 3344c3af266SPoul-Henning Kamp static void 335*587cf682SCraig Rodrigues marshal_new_auth(AUTH *auth) 33699064799SGarrett Wollman { 33799064799SGarrett Wollman XDR xdr_stream; 3388360efbdSAlfred Perlstein XDR *xdrs = &xdr_stream; 3398360efbdSAlfred Perlstein struct audata *au; 34099064799SGarrett Wollman 3418360efbdSAlfred Perlstein assert(auth != NULL); 3428360efbdSAlfred Perlstein 3438360efbdSAlfred Perlstein au = AUTH_PRIVATE(auth); 34499064799SGarrett Wollman xdrmem_create(xdrs, au->au_marshed, MAX_AUTH_BYTES, XDR_ENCODE); 34599064799SGarrett Wollman if ((! xdr_opaque_auth(xdrs, &(auth->ah_cred))) || 3468360efbdSAlfred Perlstein (! xdr_opaque_auth(xdrs, &(auth->ah_verf)))) 3478360efbdSAlfred Perlstein warnx("auth_none.c - Fatal marshalling problem"); 3488360efbdSAlfred Perlstein else 34999064799SGarrett Wollman au->au_mpos = XDR_GETPOS(xdrs); 35099064799SGarrett Wollman XDR_DESTROY(xdrs); 35199064799SGarrett Wollman } 3528360efbdSAlfred Perlstein 3538360efbdSAlfred Perlstein static struct auth_ops * 354*587cf682SCraig Rodrigues authunix_ops(void) 3558360efbdSAlfred Perlstein { 3568360efbdSAlfred Perlstein static struct auth_ops ops; 3578360efbdSAlfred Perlstein 3588360efbdSAlfred Perlstein /* VARIABLES PROTECTED BY ops_lock: ops */ 3598360efbdSAlfred Perlstein 3608360efbdSAlfred Perlstein mutex_lock(&ops_lock); 3618360efbdSAlfred Perlstein if (ops.ah_nextverf == NULL) { 3628360efbdSAlfred Perlstein ops.ah_nextverf = authunix_nextverf; 3638360efbdSAlfred Perlstein ops.ah_marshal = authunix_marshal; 3648360efbdSAlfred Perlstein ops.ah_validate = authunix_validate; 3658360efbdSAlfred Perlstein ops.ah_refresh = authunix_refresh; 3668360efbdSAlfred Perlstein ops.ah_destroy = authunix_destroy; 3678360efbdSAlfred Perlstein } 3688360efbdSAlfred Perlstein mutex_unlock(&ops_lock); 3698360efbdSAlfred Perlstein return (&ops); 3708360efbdSAlfred Perlstein } 371