17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 57c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 67c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 77c478bd9Sstevel@tonic-gate * with the License. 87c478bd9Sstevel@tonic-gate * 97c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 107c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 117c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 127c478bd9Sstevel@tonic-gate * and limitations under the License. 137c478bd9Sstevel@tonic-gate * 147c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 157c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 167c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 177c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 187c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 197c478bd9Sstevel@tonic-gate * 207c478bd9Sstevel@tonic-gate * CDDL HEADER END 217c478bd9Sstevel@tonic-gate */ 227c478bd9Sstevel@tonic-gate /* 237c478bd9Sstevel@tonic-gate * Copyright 2003 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 287c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 297c478bd9Sstevel@tonic-gate 307c478bd9Sstevel@tonic-gate /* 317c478bd9Sstevel@tonic-gate * Portions of this source code were derived from Berkeley 4.3 BSD 327c478bd9Sstevel@tonic-gate * under license from the Regents of the University of California. 337c478bd9Sstevel@tonic-gate */ 347c478bd9Sstevel@tonic-gate 357c478bd9Sstevel@tonic-gate /* 367c478bd9Sstevel@tonic-gate * auth_loopb.c, implements UNIX style authentication parameters in the 377c478bd9Sstevel@tonic-gate * kernel. Interfaces with svc_auth_loopback on the server. See 387c478bd9Sstevel@tonic-gate * auth_loopb.c for the user level implementation of the loopback auth. 397c478bd9Sstevel@tonic-gate * 407c478bd9Sstevel@tonic-gate */ 417c478bd9Sstevel@tonic-gate 427c478bd9Sstevel@tonic-gate #include <sys/param.h> 437c478bd9Sstevel@tonic-gate #include <sys/time.h> 447c478bd9Sstevel@tonic-gate #include <sys/types.h> 457c478bd9Sstevel@tonic-gate #include <sys/systm.h> 467c478bd9Sstevel@tonic-gate #include <sys/user.h> 477c478bd9Sstevel@tonic-gate #include <sys/proc.h> 487c478bd9Sstevel@tonic-gate #include <sys/utsname.h> 497c478bd9Sstevel@tonic-gate #include <sys/cred.h> 507c478bd9Sstevel@tonic-gate #include <sys/kmem.h> 517c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h> 527c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h> 537c478bd9Sstevel@tonic-gate 547c478bd9Sstevel@tonic-gate #include <rpc/types.h> 557c478bd9Sstevel@tonic-gate #include <rpc/xdr.h> 567c478bd9Sstevel@tonic-gate #include <rpc/auth.h> 577c478bd9Sstevel@tonic-gate #include <rpc/auth_unix.h> 587c478bd9Sstevel@tonic-gate #include <rpc/clnt.h> 597c478bd9Sstevel@tonic-gate #include <rpc/rpc_msg.h> 607c478bd9Sstevel@tonic-gate 617c478bd9Sstevel@tonic-gate /* 627c478bd9Sstevel@tonic-gate * Unix authenticator operations vector 637c478bd9Sstevel@tonic-gate */ 647c478bd9Sstevel@tonic-gate static void authloopback_nextverf(AUTH *); 657c478bd9Sstevel@tonic-gate static bool_t authloopback_marshal(AUTH *, XDR *, struct cred *); 667c478bd9Sstevel@tonic-gate static bool_t authloopback_validate(AUTH *, struct opaque_auth *); 677c478bd9Sstevel@tonic-gate static bool_t authloopback_refresh(AUTH *, struct rpc_msg *, cred_t *); 687c478bd9Sstevel@tonic-gate static void authloopback_destroy(AUTH *); 697c478bd9Sstevel@tonic-gate 707c478bd9Sstevel@tonic-gate static struct auth_ops authloopback_ops = { 717c478bd9Sstevel@tonic-gate authloopback_nextverf, 727c478bd9Sstevel@tonic-gate authloopback_marshal, 737c478bd9Sstevel@tonic-gate authloopback_validate, 747c478bd9Sstevel@tonic-gate authloopback_refresh, 757c478bd9Sstevel@tonic-gate authloopback_destroy, 767c478bd9Sstevel@tonic-gate authany_wrap, 777c478bd9Sstevel@tonic-gate authany_unwrap 787c478bd9Sstevel@tonic-gate }; 797c478bd9Sstevel@tonic-gate 807c478bd9Sstevel@tonic-gate /* 817c478bd9Sstevel@tonic-gate * Create a kernel unix style authenticator. 827c478bd9Sstevel@tonic-gate * Returns an auth handle. 837c478bd9Sstevel@tonic-gate */ 847c478bd9Sstevel@tonic-gate AUTH * 857c478bd9Sstevel@tonic-gate authloopback_create(void) 867c478bd9Sstevel@tonic-gate { 877c478bd9Sstevel@tonic-gate /* 887c478bd9Sstevel@tonic-gate * Allocate and set up auth handle 897c478bd9Sstevel@tonic-gate */ 907c478bd9Sstevel@tonic-gate return (kmem_cache_alloc(authloopback_cache, KM_SLEEP)); 917c478bd9Sstevel@tonic-gate } 927c478bd9Sstevel@tonic-gate 937c478bd9Sstevel@tonic-gate /* 947c478bd9Sstevel@tonic-gate * The constructor of the authloopback_cache. 957c478bd9Sstevel@tonic-gate */ 967c478bd9Sstevel@tonic-gate /* ARGSUSED */ 977c478bd9Sstevel@tonic-gate int 987c478bd9Sstevel@tonic-gate authloopback_init(void *buf, void *cdrarg, int kmflags) 997c478bd9Sstevel@tonic-gate { 1007c478bd9Sstevel@tonic-gate AUTH *auth = (AUTH *)buf; 1017c478bd9Sstevel@tonic-gate 1027c478bd9Sstevel@tonic-gate auth->ah_ops = &authloopback_ops; 1037c478bd9Sstevel@tonic-gate auth->ah_cred.oa_flavor = AUTH_LOOPBACK; 1047c478bd9Sstevel@tonic-gate auth->ah_verf = _null_auth; 1057c478bd9Sstevel@tonic-gate 1067c478bd9Sstevel@tonic-gate return (0); 1077c478bd9Sstevel@tonic-gate } 1087c478bd9Sstevel@tonic-gate 1097c478bd9Sstevel@tonic-gate /* 1107c478bd9Sstevel@tonic-gate * authloopback operations 1117c478bd9Sstevel@tonic-gate */ 1127c478bd9Sstevel@tonic-gate /* ARGSUSED */ 1137c478bd9Sstevel@tonic-gate static void 1147c478bd9Sstevel@tonic-gate authloopback_nextverf(AUTH *auth) 1157c478bd9Sstevel@tonic-gate { 1167c478bd9Sstevel@tonic-gate 1177c478bd9Sstevel@tonic-gate /* no action necessary */ 1187c478bd9Sstevel@tonic-gate } 1197c478bd9Sstevel@tonic-gate 1207c478bd9Sstevel@tonic-gate static bool_t 1217c478bd9Sstevel@tonic-gate authloopback_marshal(AUTH *auth, XDR *xdrs, struct cred *cr) 1227c478bd9Sstevel@tonic-gate { 1237c478bd9Sstevel@tonic-gate char *sercred; 1247c478bd9Sstevel@tonic-gate XDR xdrm; 125*0e91b739SMarcel Telka bool_t ret; 126*0e91b739SMarcel Telka uint32_t gidlen, credsize, namelen, rounded_namelen; 1277c478bd9Sstevel@tonic-gate int32_t *ptr; 128*0e91b739SMarcel Telka char *nodename = uts_nodename(); 129*0e91b739SMarcel Telka uint32_t maxgidlen; 130*0e91b739SMarcel Telka uint_t startpos; 131*0e91b739SMarcel Telka 132*0e91b739SMarcel Telka ASSERT(xdrs->x_op == XDR_ENCODE); 133*0e91b739SMarcel Telka ASSERT(auth->ah_cred.oa_flavor == AUTH_LOOPBACK); 134*0e91b739SMarcel Telka ASSERT(auth->ah_verf.oa_flavor == AUTH_NONE); 135*0e91b739SMarcel Telka ASSERT(auth->ah_verf.oa_length == 0); 1367c478bd9Sstevel@tonic-gate 1377c478bd9Sstevel@tonic-gate /* 1387c478bd9Sstevel@tonic-gate * First we try a fast path to get through 1397c478bd9Sstevel@tonic-gate * this very common operation. 1407c478bd9Sstevel@tonic-gate */ 141*0e91b739SMarcel Telka namelen = (uint32_t)strlen(nodename); 142*0e91b739SMarcel Telka if (namelen > MAX_MACHINE_NAME) 1437c478bd9Sstevel@tonic-gate return (FALSE); 1447c478bd9Sstevel@tonic-gate rounded_namelen = RNDUP(namelen); 145*0e91b739SMarcel Telka 146*0e91b739SMarcel Telka /* 147*0e91b739SMarcel Telka * NFIELDS is a number of the following fields we are going to encode: 148*0e91b739SMarcel Telka * - stamp 149*0e91b739SMarcel Telka * - strlen(machinename) 150*0e91b739SMarcel Telka * - uid 151*0e91b739SMarcel Telka * - gid 152*0e91b739SMarcel Telka * - the number of gids 153*0e91b739SMarcel Telka */ 154*0e91b739SMarcel Telka #define NFIELDS 5 155*0e91b739SMarcel Telka CTASSERT(NFIELDS * BYTES_PER_XDR_UNIT + RNDUP(MAX_MACHINE_NAME) <= 156*0e91b739SMarcel Telka MAX_AUTH_BYTES); 157*0e91b739SMarcel Telka maxgidlen = (MAX_AUTH_BYTES - NFIELDS * BYTES_PER_XDR_UNIT - 158*0e91b739SMarcel Telka rounded_namelen) / BYTES_PER_XDR_UNIT; 159*0e91b739SMarcel Telka 160*0e91b739SMarcel Telka gidlen = crgetngroups(cr); 161*0e91b739SMarcel Telka if (gidlen > maxgidlen) 162*0e91b739SMarcel Telka return (FALSE); 163*0e91b739SMarcel Telka 164*0e91b739SMarcel Telka credsize = NFIELDS * BYTES_PER_XDR_UNIT + rounded_namelen + 165*0e91b739SMarcel Telka gidlen * BYTES_PER_XDR_UNIT; 166*0e91b739SMarcel Telka ASSERT(credsize <= MAX_AUTH_BYTES); 167*0e91b739SMarcel Telka #undef NFIELDS 168*0e91b739SMarcel Telka 169*0e91b739SMarcel Telka /* 170*0e91b739SMarcel Telka * We need to marshal both cred and verf parts of the rpc_msg body 171*0e91b739SMarcel Telka * (call_body). For the cred part we need to inline the auth_flavor 172*0e91b739SMarcel Telka * and the opaque auth body size. Then we inline the credsize bytes of 173*0e91b739SMarcel Telka * the opaque auth body for the cred part. Finally we add the 174*0e91b739SMarcel Telka * AUTH_NONE verifier (its auth_flavor and the opaque auth body size). 175*0e91b739SMarcel Telka */ 176*0e91b739SMarcel Telka ptr = XDR_INLINE(xdrs, 2 * BYTES_PER_XDR_UNIT + credsize + 177*0e91b739SMarcel Telka 2 * BYTES_PER_XDR_UNIT); 178*0e91b739SMarcel Telka if (ptr != NULL) { 1797c478bd9Sstevel@tonic-gate /* 1807c478bd9Sstevel@tonic-gate * We can do the fast path. 1817c478bd9Sstevel@tonic-gate */ 182*0e91b739SMarcel Telka const gid_t *gp = crgetgroups(cr); 183*0e91b739SMarcel Telka 184*0e91b739SMarcel Telka IXDR_PUT_U_INT32(ptr, AUTH_LOOPBACK); /* cred flavor */ 185*0e91b739SMarcel Telka IXDR_PUT_U_INT32(ptr, credsize); /* cred len */ 186*0e91b739SMarcel Telka 1877c478bd9Sstevel@tonic-gate IXDR_PUT_INT32(ptr, gethrestime_sec()); 188*0e91b739SMarcel Telka IXDR_PUT_U_INT32(ptr, namelen); 189*0e91b739SMarcel Telka bcopy(nodename, ptr, namelen); 190*0e91b739SMarcel Telka if ((rounded_namelen - namelen) > 0) 191*0e91b739SMarcel Telka bzero((char *)ptr + namelen, rounded_namelen - namelen); 1927c478bd9Sstevel@tonic-gate ptr += rounded_namelen / BYTES_PER_XDR_UNIT; 193*0e91b739SMarcel Telka IXDR_PUT_U_INT32(ptr, crgetuid(cr)); 194*0e91b739SMarcel Telka IXDR_PUT_U_INT32(ptr, crgetgid(cr)); 195*0e91b739SMarcel Telka IXDR_PUT_U_INT32(ptr, gidlen); 196*0e91b739SMarcel Telka while (gidlen-- > 0) 197*0e91b739SMarcel Telka IXDR_PUT_U_INT32(ptr, *gp++); 198*0e91b739SMarcel Telka 199*0e91b739SMarcel Telka IXDR_PUT_U_INT32(ptr, AUTH_NONE); /* verf flavor */ 200*0e91b739SMarcel Telka IXDR_PUT_U_INT32(ptr, 0); /* verf len */ 201*0e91b739SMarcel Telka 2027c478bd9Sstevel@tonic-gate return (TRUE); 2037c478bd9Sstevel@tonic-gate } 204*0e91b739SMarcel Telka 2057c478bd9Sstevel@tonic-gate sercred = kmem_alloc(MAX_AUTH_BYTES, KM_SLEEP); 206*0e91b739SMarcel Telka 2077c478bd9Sstevel@tonic-gate /* 208*0e91b739SMarcel Telka * Serialize the auth body data into sercred. 2097c478bd9Sstevel@tonic-gate */ 2107c478bd9Sstevel@tonic-gate xdrmem_create(&xdrm, sercred, MAX_AUTH_BYTES, XDR_ENCODE); 211*0e91b739SMarcel Telka startpos = XDR_GETPOS(&xdrm); 212*0e91b739SMarcel Telka if (!xdr_authloopback(&xdrm, cr)) { 2137c478bd9Sstevel@tonic-gate printf("authloopback_marshal: xdr_authloopback failed\n"); 2147c478bd9Sstevel@tonic-gate ret = FALSE; 2157c478bd9Sstevel@tonic-gate goto done; 2167c478bd9Sstevel@tonic-gate } 2177c478bd9Sstevel@tonic-gate 2187c478bd9Sstevel@tonic-gate /* 219*0e91b739SMarcel Telka * Make opaque auth credentials to point at the serialized auth body 220*0e91b739SMarcel Telka * data. 2217c478bd9Sstevel@tonic-gate */ 222*0e91b739SMarcel Telka auth->ah_cred.oa_base = sercred; 223*0e91b739SMarcel Telka auth->ah_cred.oa_length = XDR_GETPOS(&xdrm) - startpos; 224*0e91b739SMarcel Telka ASSERT(auth->ah_cred.oa_length <= MAX_AUTH_BYTES); 2257c478bd9Sstevel@tonic-gate 2267c478bd9Sstevel@tonic-gate /* 227*0e91b739SMarcel Telka * serialize credentials and verifier (null) 2287c478bd9Sstevel@tonic-gate */ 2297c478bd9Sstevel@tonic-gate if ((xdr_opaque_auth(xdrs, &(auth->ah_cred))) && 2307c478bd9Sstevel@tonic-gate (xdr_opaque_auth(xdrs, &(auth->ah_verf)))) 2317c478bd9Sstevel@tonic-gate ret = TRUE; 2327c478bd9Sstevel@tonic-gate else 2337c478bd9Sstevel@tonic-gate ret = FALSE; 234*0e91b739SMarcel Telka 2357c478bd9Sstevel@tonic-gate done: 236*0e91b739SMarcel Telka XDR_DESTROY(&xdrm); 2377c478bd9Sstevel@tonic-gate kmem_free(sercred, MAX_AUTH_BYTES); 238*0e91b739SMarcel Telka 2397c478bd9Sstevel@tonic-gate return (ret); 2407c478bd9Sstevel@tonic-gate } 2417c478bd9Sstevel@tonic-gate 2427c478bd9Sstevel@tonic-gate /* ARGSUSED */ 2437c478bd9Sstevel@tonic-gate static bool_t 2447c478bd9Sstevel@tonic-gate authloopback_validate(AUTH *auth, struct opaque_auth *verf) 2457c478bd9Sstevel@tonic-gate { 2467c478bd9Sstevel@tonic-gate return (TRUE); 2477c478bd9Sstevel@tonic-gate } 2487c478bd9Sstevel@tonic-gate 2497c478bd9Sstevel@tonic-gate /* ARGSUSED */ 2507c478bd9Sstevel@tonic-gate static bool_t 2517c478bd9Sstevel@tonic-gate authloopback_refresh(AUTH *auth, struct rpc_msg *msg, cred_t *cr) 2527c478bd9Sstevel@tonic-gate { 2537c478bd9Sstevel@tonic-gate return (FALSE); 2547c478bd9Sstevel@tonic-gate } 2557c478bd9Sstevel@tonic-gate 2567c478bd9Sstevel@tonic-gate static void 2577c478bd9Sstevel@tonic-gate authloopback_destroy(register AUTH *auth) 2587c478bd9Sstevel@tonic-gate { 2597c478bd9Sstevel@tonic-gate kmem_cache_free(authloopback_cache, auth); 2607c478bd9Sstevel@tonic-gate } 261