1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate /* 23*0Sstevel@tonic-gate * Copyright 2003 Sun Microsystems, Inc. All rights reserved. 24*0Sstevel@tonic-gate * Use is subject to license terms. 25*0Sstevel@tonic-gate */ 26*0Sstevel@tonic-gate 27*0Sstevel@tonic-gate /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 28*0Sstevel@tonic-gate /* All Rights Reserved */ 29*0Sstevel@tonic-gate 30*0Sstevel@tonic-gate /* 31*0Sstevel@tonic-gate * Portions of this source code were derived from Berkeley 4.3 BSD 32*0Sstevel@tonic-gate * under license from the Regents of the University of California. 33*0Sstevel@tonic-gate */ 34*0Sstevel@tonic-gate 35*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 36*0Sstevel@tonic-gate 37*0Sstevel@tonic-gate /* 38*0Sstevel@tonic-gate * key_call.c, Interface to keyserver 39*0Sstevel@tonic-gate * key_encryptsession(agent, deskey, cr)-encrypt a session key to talk to agent 40*0Sstevel@tonic-gate * key_decryptsession(agent, deskey) - decrypt ditto 41*0Sstevel@tonic-gate * key_gendes(deskey) - generate a secure des key 42*0Sstevel@tonic-gate * key_getnetname(netname, cr) - get the netname from the keyserv 43*0Sstevel@tonic-gate * netname2user(...) - get unix credential for given name (kernel only) 44*0Sstevel@tonic-gate */ 45*0Sstevel@tonic-gate 46*0Sstevel@tonic-gate #include <sys/param.h> 47*0Sstevel@tonic-gate #include <sys/types.h> 48*0Sstevel@tonic-gate #include <sys/time.h> 49*0Sstevel@tonic-gate #include <sys/systm.h> 50*0Sstevel@tonic-gate #include <sys/user.h> 51*0Sstevel@tonic-gate #include <sys/proc.h> 52*0Sstevel@tonic-gate #include <sys/pathname.h> 53*0Sstevel@tonic-gate #include <sys/sysmacros.h> 54*0Sstevel@tonic-gate #include <sys/vnode.h> 55*0Sstevel@tonic-gate #include <sys/uio.h> 56*0Sstevel@tonic-gate #include <sys/debug.h> 57*0Sstevel@tonic-gate #include <sys/utsname.h> 58*0Sstevel@tonic-gate #include <sys/cmn_err.h> 59*0Sstevel@tonic-gate 60*0Sstevel@tonic-gate #include <rpc/rpc.h> 61*0Sstevel@tonic-gate #include <rpc/key_prot.h> 62*0Sstevel@tonic-gate 63*0Sstevel@tonic-gate #define KEY_TIMEOUT 30 /* per-try timeout in seconds */ 64*0Sstevel@tonic-gate #define KEY_NRETRY 6 /* number of retries */ 65*0Sstevel@tonic-gate 66*0Sstevel@tonic-gate struct auth_globals { 67*0Sstevel@tonic-gate struct knetconfig auth_config; 68*0Sstevel@tonic-gate char auth_keyname[SYS_NMLN+16]; 69*0Sstevel@tonic-gate }; 70*0Sstevel@tonic-gate 71*0Sstevel@tonic-gate static struct timeval keytrytimeout = { KEY_TIMEOUT, 0 }; 72*0Sstevel@tonic-gate 73*0Sstevel@tonic-gate static enum clnt_stat key_call(rpcproc_t, xdrproc_t, char *, xdrproc_t, char *, 74*0Sstevel@tonic-gate cred_t *); 75*0Sstevel@tonic-gate 76*0Sstevel@tonic-gate /* ARGSUSED */ 77*0Sstevel@tonic-gate void * 78*0Sstevel@tonic-gate auth_zone_init(zoneid_t zoneid) 79*0Sstevel@tonic-gate { 80*0Sstevel@tonic-gate struct auth_globals *authg; 81*0Sstevel@tonic-gate 82*0Sstevel@tonic-gate authg = kmem_zalloc(sizeof (*authg), KM_SLEEP); 83*0Sstevel@tonic-gate return (authg); 84*0Sstevel@tonic-gate } 85*0Sstevel@tonic-gate 86*0Sstevel@tonic-gate /* ARGSUSED */ 87*0Sstevel@tonic-gate void 88*0Sstevel@tonic-gate auth_zone_fini(zoneid_t zoneid, void *data) 89*0Sstevel@tonic-gate { 90*0Sstevel@tonic-gate struct auth_globals *authg = data; 91*0Sstevel@tonic-gate 92*0Sstevel@tonic-gate kmem_free(authg, sizeof (*authg)); 93*0Sstevel@tonic-gate } 94*0Sstevel@tonic-gate 95*0Sstevel@tonic-gate enum clnt_stat 96*0Sstevel@tonic-gate key_encryptsession(char *remotename, des_block *deskey, cred_t *cr) 97*0Sstevel@tonic-gate { 98*0Sstevel@tonic-gate cryptkeyarg arg; 99*0Sstevel@tonic-gate cryptkeyres res; 100*0Sstevel@tonic-gate enum clnt_stat stat; 101*0Sstevel@tonic-gate 102*0Sstevel@tonic-gate RPCLOG(8, "key_encryptsession(%s, ", remotename); 103*0Sstevel@tonic-gate RPCLOG(8, "%x", *(uint32_t *)deskey); 104*0Sstevel@tonic-gate RPCLOG(8, "%x)\n", *(((uint32_t *)(deskey))+1)); 105*0Sstevel@tonic-gate 106*0Sstevel@tonic-gate arg.remotename = remotename; 107*0Sstevel@tonic-gate arg.deskey = *deskey; 108*0Sstevel@tonic-gate if ((stat = key_call(KEY_ENCRYPT, xdr_cryptkeyarg, (char *)&arg, 109*0Sstevel@tonic-gate xdr_cryptkeyres, (char *)&res, cr)) != RPC_SUCCESS) { 110*0Sstevel@tonic-gate RPCLOG(1, "key_encryptsession(%d, ", (int)crgetuid(cr)); 111*0Sstevel@tonic-gate RPCLOG(1, "%s): ", remotename); 112*0Sstevel@tonic-gate RPCLOG(1, "rpc status %d ", stat); 113*0Sstevel@tonic-gate RPCLOG(1, "(%s)\n", clnt_sperrno(stat)); 114*0Sstevel@tonic-gate return (stat); 115*0Sstevel@tonic-gate } 116*0Sstevel@tonic-gate 117*0Sstevel@tonic-gate if (res.status != KEY_SUCCESS) { 118*0Sstevel@tonic-gate RPCLOG(1, "key_encryptsession(%d, ", (int)crgetuid(cr)); 119*0Sstevel@tonic-gate RPCLOG(1, "%s): ", remotename); 120*0Sstevel@tonic-gate RPCLOG(1, "key status %d\n", res.status); 121*0Sstevel@tonic-gate return (RPC_FAILED); /* XXX */ 122*0Sstevel@tonic-gate } 123*0Sstevel@tonic-gate *deskey = res.cryptkeyres_u.deskey; 124*0Sstevel@tonic-gate return (RPC_SUCCESS); 125*0Sstevel@tonic-gate } 126*0Sstevel@tonic-gate 127*0Sstevel@tonic-gate enum clnt_stat 128*0Sstevel@tonic-gate key_decryptsession(char *remotename, des_block *deskey) 129*0Sstevel@tonic-gate { 130*0Sstevel@tonic-gate cryptkeyarg arg; 131*0Sstevel@tonic-gate cryptkeyres res; 132*0Sstevel@tonic-gate enum clnt_stat stat; 133*0Sstevel@tonic-gate 134*0Sstevel@tonic-gate RPCLOG(8, "key_decryptsession(%s, ", remotename); 135*0Sstevel@tonic-gate RPCLOG(2, "%x", *(uint32_t *)deskey); 136*0Sstevel@tonic-gate RPCLOG(2, "%x)\n", *(((uint32_t *)(deskey))+1)); 137*0Sstevel@tonic-gate 138*0Sstevel@tonic-gate arg.remotename = remotename; 139*0Sstevel@tonic-gate arg.deskey = *deskey; 140*0Sstevel@tonic-gate if ((stat = key_call(KEY_DECRYPT, xdr_cryptkeyarg, (char *)&arg, 141*0Sstevel@tonic-gate xdr_cryptkeyres, (char *)&res, kcred)) != RPC_SUCCESS) { 142*0Sstevel@tonic-gate RPCLOG(1, "key_decryptsession(%s): ", remotename); 143*0Sstevel@tonic-gate RPCLOG(1, "rpc status %d ", stat); 144*0Sstevel@tonic-gate RPCLOG(1, "(%s)\n", clnt_sperrno(stat)); 145*0Sstevel@tonic-gate return (stat); 146*0Sstevel@tonic-gate } 147*0Sstevel@tonic-gate 148*0Sstevel@tonic-gate if (res.status != KEY_SUCCESS) { 149*0Sstevel@tonic-gate RPCLOG(1, "key_decryptsession(%s): ", remotename); 150*0Sstevel@tonic-gate RPCLOG(1, "key status %d\n", res.status); 151*0Sstevel@tonic-gate return (RPC_FAILED); /* XXX */ 152*0Sstevel@tonic-gate } 153*0Sstevel@tonic-gate *deskey = res.cryptkeyres_u.deskey; 154*0Sstevel@tonic-gate return (RPC_SUCCESS); 155*0Sstevel@tonic-gate } 156*0Sstevel@tonic-gate 157*0Sstevel@tonic-gate enum clnt_stat 158*0Sstevel@tonic-gate key_gendes(des_block *key) 159*0Sstevel@tonic-gate { 160*0Sstevel@tonic-gate 161*0Sstevel@tonic-gate return (key_call(KEY_GEN, xdr_void, NULL, xdr_des_block, (char *)key, 162*0Sstevel@tonic-gate CRED())); 163*0Sstevel@tonic-gate } 164*0Sstevel@tonic-gate 165*0Sstevel@tonic-gate /* 166*0Sstevel@tonic-gate * Call up to keyserv to get the netname of the client based 167*0Sstevel@tonic-gate * on its uid. The netname is written into the string that "netname" 168*0Sstevel@tonic-gate * points to; the caller is responsible for ensuring that sufficient space 169*0Sstevel@tonic-gate * is available. 170*0Sstevel@tonic-gate */ 171*0Sstevel@tonic-gate enum clnt_stat 172*0Sstevel@tonic-gate key_getnetname(netname, cr) 173*0Sstevel@tonic-gate char *netname; 174*0Sstevel@tonic-gate cred_t *cr; 175*0Sstevel@tonic-gate { 176*0Sstevel@tonic-gate key_netstres kres; 177*0Sstevel@tonic-gate enum clnt_stat stat; 178*0Sstevel@tonic-gate 179*0Sstevel@tonic-gate /* 180*0Sstevel@tonic-gate * Look up the keyserv interface routines to see if 181*0Sstevel@tonic-gate * netname is stored there. 182*0Sstevel@tonic-gate */ 183*0Sstevel@tonic-gate kres.key_netstres_u.knet.st_netname = netname; 184*0Sstevel@tonic-gate if ((stat = key_call((rpcproc_t)KEY_NET_GET, xdr_void, NULL, 185*0Sstevel@tonic-gate xdr_key_netstres, (char *)&kres, cr)) != RPC_SUCCESS) { 186*0Sstevel@tonic-gate RPCLOG(1, "key_getnetname(%d): ", (int)crgetuid(cr)); 187*0Sstevel@tonic-gate RPCLOG(1, "rpc status %d ", stat); 188*0Sstevel@tonic-gate RPCLOG(1, "(%s)\n", clnt_sperrno(stat)); 189*0Sstevel@tonic-gate return (stat); 190*0Sstevel@tonic-gate } 191*0Sstevel@tonic-gate 192*0Sstevel@tonic-gate if (kres.status != KEY_SUCCESS) { 193*0Sstevel@tonic-gate RPCLOG(1, "key_getnetname(%d): ", (int)crgetuid(cr)); 194*0Sstevel@tonic-gate RPCLOG(1, "key status %d\n", kres.status); 195*0Sstevel@tonic-gate return (RPC_FAILED); 196*0Sstevel@tonic-gate } 197*0Sstevel@tonic-gate 198*0Sstevel@tonic-gate return (RPC_SUCCESS); 199*0Sstevel@tonic-gate } 200*0Sstevel@tonic-gate 201*0Sstevel@tonic-gate enum clnt_stat 202*0Sstevel@tonic-gate netname2user(char *name, uid_t *uid, gid_t *gid, int *len, int *groups) 203*0Sstevel@tonic-gate { 204*0Sstevel@tonic-gate struct getcredres res; 205*0Sstevel@tonic-gate enum clnt_stat stat; 206*0Sstevel@tonic-gate 207*0Sstevel@tonic-gate res.getcredres_u.cred.gids.gids_val = (uint_t *)groups; 208*0Sstevel@tonic-gate if ((stat = key_call(KEY_GETCRED, xdr_netnamestr, (char *)&name, 209*0Sstevel@tonic-gate xdr_getcredres, (char *)&res, CRED())) != RPC_SUCCESS) { 210*0Sstevel@tonic-gate RPCLOG(1, "netname2user(%s): ", name); 211*0Sstevel@tonic-gate RPCLOG(1, "rpc status %d ", stat); 212*0Sstevel@tonic-gate RPCLOG(1, "(%s)\n", clnt_sperrno(stat)); 213*0Sstevel@tonic-gate return (stat); 214*0Sstevel@tonic-gate } 215*0Sstevel@tonic-gate 216*0Sstevel@tonic-gate if (res.status != KEY_SUCCESS) { 217*0Sstevel@tonic-gate RPCLOG(1, "netname2user(%s): ", name); 218*0Sstevel@tonic-gate RPCLOG(1, "key status %d\n", res.status); 219*0Sstevel@tonic-gate return (RPC_FAILED); /* XXX */ 220*0Sstevel@tonic-gate } 221*0Sstevel@tonic-gate *uid = res.getcredres_u.cred.uid; 222*0Sstevel@tonic-gate *gid = res.getcredres_u.cred.gid; 223*0Sstevel@tonic-gate *len = res.getcredres_u.cred.gids.gids_len; 224*0Sstevel@tonic-gate return (RPC_SUCCESS); 225*0Sstevel@tonic-gate } 226*0Sstevel@tonic-gate 227*0Sstevel@tonic-gate #define NC_LOOPBACK "loopback" /* XXX */ 228*0Sstevel@tonic-gate char loopback_name[] = NC_LOOPBACK; 229*0Sstevel@tonic-gate 230*0Sstevel@tonic-gate static enum clnt_stat 231*0Sstevel@tonic-gate key_call(rpcproc_t procn, xdrproc_t xdr_args, caddr_t args, 232*0Sstevel@tonic-gate xdrproc_t xdr_rslt, caddr_t rslt, cred_t *cr) 233*0Sstevel@tonic-gate { 234*0Sstevel@tonic-gate struct netbuf netaddr; 235*0Sstevel@tonic-gate CLIENT *client; 236*0Sstevel@tonic-gate enum clnt_stat stat; 237*0Sstevel@tonic-gate vnode_t *vp; 238*0Sstevel@tonic-gate int error; 239*0Sstevel@tonic-gate struct auth_globals *authg; 240*0Sstevel@tonic-gate char *keyname; 241*0Sstevel@tonic-gate struct knetconfig *configp; 242*0Sstevel@tonic-gate k_sigset_t smask; 243*0Sstevel@tonic-gate 244*0Sstevel@tonic-gate authg = zone_getspecific(auth_zone_key, curproc->p_zone); 245*0Sstevel@tonic-gate keyname = authg->auth_keyname; 246*0Sstevel@tonic-gate configp = &authg->auth_config; 247*0Sstevel@tonic-gate 248*0Sstevel@tonic-gate /* 249*0Sstevel@tonic-gate * Using a global here is obviously busted and fraught with danger. 250*0Sstevel@tonic-gate */ 251*0Sstevel@tonic-gate (void) strcpy(keyname, uts_nodename()); 252*0Sstevel@tonic-gate netaddr.len = strlen(keyname); 253*0Sstevel@tonic-gate (void) strcpy(&keyname[netaddr.len], ".keyserv"); 254*0Sstevel@tonic-gate 255*0Sstevel@tonic-gate netaddr.buf = keyname; 256*0Sstevel@tonic-gate /* 257*0Sstevel@tonic-gate * 8 = strlen(".keyserv"); 258*0Sstevel@tonic-gate */ 259*0Sstevel@tonic-gate netaddr.len = netaddr.maxlen = netaddr.len + 8; 260*0Sstevel@tonic-gate 261*0Sstevel@tonic-gate /* 262*0Sstevel@tonic-gate * filch a knetconfig structure. 263*0Sstevel@tonic-gate */ 264*0Sstevel@tonic-gate if (configp->knc_rdev == 0) { 265*0Sstevel@tonic-gate if ((error = lookupname("/dev/ticlts", UIO_SYSSPACE, 266*0Sstevel@tonic-gate FOLLOW, NULLVPP, &vp)) != 0) { 267*0Sstevel@tonic-gate RPCLOG(1, "key_call: lookupname: %d\n", error); 268*0Sstevel@tonic-gate return (RPC_UNKNOWNPROTO); 269*0Sstevel@tonic-gate } 270*0Sstevel@tonic-gate configp->knc_rdev = vp->v_rdev; 271*0Sstevel@tonic-gate configp->knc_protofmly = loopback_name; 272*0Sstevel@tonic-gate VN_RELE(vp); 273*0Sstevel@tonic-gate } 274*0Sstevel@tonic-gate configp->knc_semantics = NC_TPI_CLTS; 275*0Sstevel@tonic-gate RPCLOG(8, "key_call: procn %d, ", procn); 276*0Sstevel@tonic-gate RPCLOG(8, "rdev %lx, ", configp->knc_rdev); 277*0Sstevel@tonic-gate RPCLOG(8, "len %d, ", netaddr.len); 278*0Sstevel@tonic-gate RPCLOG(8, "maxlen %d, ", netaddr.maxlen); 279*0Sstevel@tonic-gate RPCLOG(8, "name %p\n", (void *)netaddr.buf); 280*0Sstevel@tonic-gate 281*0Sstevel@tonic-gate /* 282*0Sstevel@tonic-gate * now call the proper stuff. 283*0Sstevel@tonic-gate */ 284*0Sstevel@tonic-gate error = clnt_tli_kcreate(configp, &netaddr, KEY_PROG, KEY_VERS, 285*0Sstevel@tonic-gate 0, KEY_NRETRY, cr, &client); 286*0Sstevel@tonic-gate 287*0Sstevel@tonic-gate if (error != 0) { 288*0Sstevel@tonic-gate RPCLOG(1, "key_call: clnt_tli_kcreate: error %d\n", error); 289*0Sstevel@tonic-gate switch (error) { 290*0Sstevel@tonic-gate case EINTR: 291*0Sstevel@tonic-gate return (RPC_INTR); 292*0Sstevel@tonic-gate case ETIMEDOUT: 293*0Sstevel@tonic-gate return (RPC_TIMEDOUT); 294*0Sstevel@tonic-gate default: 295*0Sstevel@tonic-gate return (RPC_FAILED); /* XXX */ 296*0Sstevel@tonic-gate } 297*0Sstevel@tonic-gate } 298*0Sstevel@tonic-gate 299*0Sstevel@tonic-gate auth_destroy(client->cl_auth); 300*0Sstevel@tonic-gate client->cl_auth = authloopback_create(); 301*0Sstevel@tonic-gate if (client->cl_auth == NULL) { 302*0Sstevel@tonic-gate clnt_destroy(client); 303*0Sstevel@tonic-gate RPCLOG(1, "key_call: authloopback_create: error %d\n", EINTR); 304*0Sstevel@tonic-gate return (RPC_INTR); 305*0Sstevel@tonic-gate } 306*0Sstevel@tonic-gate 307*0Sstevel@tonic-gate /* Mask out all signals except SIGHUP, SIGQUIT, and SIGTERM. */ 308*0Sstevel@tonic-gate sigintr(&smask, 0); 309*0Sstevel@tonic-gate stat = clnt_call(client, procn, xdr_args, args, xdr_rslt, rslt, 310*0Sstevel@tonic-gate keytrytimeout); 311*0Sstevel@tonic-gate sigunintr(&smask); 312*0Sstevel@tonic-gate 313*0Sstevel@tonic-gate auth_destroy(client->cl_auth); 314*0Sstevel@tonic-gate clnt_destroy(client); 315*0Sstevel@tonic-gate if (stat != RPC_SUCCESS) { 316*0Sstevel@tonic-gate RPCLOG(1, "key_call: keyserver clnt_call failed: stat %d ", 317*0Sstevel@tonic-gate stat); 318*0Sstevel@tonic-gate RPCLOG(1, "(%s)\n", clnt_sperrno(stat)); 319*0Sstevel@tonic-gate RPCLOG0(1, "\n"); 320*0Sstevel@tonic-gate return (stat); 321*0Sstevel@tonic-gate } 322*0Sstevel@tonic-gate RPCLOG(8, "key call: (%d) ok\n", procn); 323*0Sstevel@tonic-gate return (RPC_SUCCESS); 324*0Sstevel@tonic-gate } 325