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 5f48205beScasper * Common Development and Distribution License (the "License"). 6f48205beScasper * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 21*6935f61bSMarcel Telka 22*6935f61bSMarcel Telka /* 23*6935f61bSMarcel Telka * Copyright 2015 Nexenta Systems, Inc. All rights reserved. 24*6935f61bSMarcel Telka */ 25*6935f61bSMarcel Telka 267c478bd9Sstevel@tonic-gate /* 27f48205beScasper * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 287c478bd9Sstevel@tonic-gate * Use is subject to license terms. 297c478bd9Sstevel@tonic-gate */ 307c478bd9Sstevel@tonic-gate 317c478bd9Sstevel@tonic-gate /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 327c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 337c478bd9Sstevel@tonic-gate 347c478bd9Sstevel@tonic-gate /* 357c478bd9Sstevel@tonic-gate * Portions of this source code were derived from Berkeley 4.3 BSD 367c478bd9Sstevel@tonic-gate * under license from the Regents of the University of California. 377c478bd9Sstevel@tonic-gate */ 387c478bd9Sstevel@tonic-gate 397c478bd9Sstevel@tonic-gate /* 407c478bd9Sstevel@tonic-gate * key_call.c, Interface to keyserver 417c478bd9Sstevel@tonic-gate * key_encryptsession(agent, deskey, cr)-encrypt a session key to talk to agent 427c478bd9Sstevel@tonic-gate * key_decryptsession(agent, deskey) - decrypt ditto 437c478bd9Sstevel@tonic-gate * key_gendes(deskey) - generate a secure des key 447c478bd9Sstevel@tonic-gate * key_getnetname(netname, cr) - get the netname from the keyserv 457c478bd9Sstevel@tonic-gate * netname2user(...) - get unix credential for given name (kernel only) 467c478bd9Sstevel@tonic-gate */ 477c478bd9Sstevel@tonic-gate 487c478bd9Sstevel@tonic-gate #include <sys/param.h> 497c478bd9Sstevel@tonic-gate #include <sys/types.h> 507c478bd9Sstevel@tonic-gate #include <sys/time.h> 517c478bd9Sstevel@tonic-gate #include <sys/systm.h> 527c478bd9Sstevel@tonic-gate #include <sys/user.h> 537c478bd9Sstevel@tonic-gate #include <sys/proc.h> 547c478bd9Sstevel@tonic-gate #include <sys/pathname.h> 557c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h> 567c478bd9Sstevel@tonic-gate #include <sys/vnode.h> 577c478bd9Sstevel@tonic-gate #include <sys/uio.h> 587c478bd9Sstevel@tonic-gate #include <sys/debug.h> 597c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h> 607c478bd9Sstevel@tonic-gate 617c478bd9Sstevel@tonic-gate #include <rpc/rpc.h> 627c478bd9Sstevel@tonic-gate #include <rpc/key_prot.h> 637c478bd9Sstevel@tonic-gate 647c478bd9Sstevel@tonic-gate #define KEY_TIMEOUT 30 /* per-try timeout in seconds */ 657c478bd9Sstevel@tonic-gate #define KEY_NRETRY 6 /* number of retries */ 667c478bd9Sstevel@tonic-gate 677c478bd9Sstevel@tonic-gate struct auth_globals { 687c478bd9Sstevel@tonic-gate struct knetconfig auth_config; 697c478bd9Sstevel@tonic-gate }; 707c478bd9Sstevel@tonic-gate 717c478bd9Sstevel@tonic-gate static struct timeval keytrytimeout = { KEY_TIMEOUT, 0 }; 727c478bd9Sstevel@tonic-gate 737c478bd9Sstevel@tonic-gate static enum clnt_stat key_call(rpcproc_t, xdrproc_t, char *, xdrproc_t, char *, 747c478bd9Sstevel@tonic-gate cred_t *); 757c478bd9Sstevel@tonic-gate 767c478bd9Sstevel@tonic-gate /* ARGSUSED */ 777c478bd9Sstevel@tonic-gate void * 787c478bd9Sstevel@tonic-gate auth_zone_init(zoneid_t zoneid) 797c478bd9Sstevel@tonic-gate { 807c478bd9Sstevel@tonic-gate struct auth_globals *authg; 817c478bd9Sstevel@tonic-gate 827c478bd9Sstevel@tonic-gate authg = kmem_zalloc(sizeof (*authg), KM_SLEEP); 837c478bd9Sstevel@tonic-gate return (authg); 847c478bd9Sstevel@tonic-gate } 857c478bd9Sstevel@tonic-gate 867c478bd9Sstevel@tonic-gate /* ARGSUSED */ 877c478bd9Sstevel@tonic-gate void 887c478bd9Sstevel@tonic-gate auth_zone_fini(zoneid_t zoneid, void *data) 897c478bd9Sstevel@tonic-gate { 907c478bd9Sstevel@tonic-gate struct auth_globals *authg = data; 917c478bd9Sstevel@tonic-gate 927c478bd9Sstevel@tonic-gate kmem_free(authg, sizeof (*authg)); 937c478bd9Sstevel@tonic-gate } 947c478bd9Sstevel@tonic-gate 957c478bd9Sstevel@tonic-gate enum clnt_stat 967c478bd9Sstevel@tonic-gate key_encryptsession(char *remotename, des_block *deskey, cred_t *cr) 977c478bd9Sstevel@tonic-gate { 987c478bd9Sstevel@tonic-gate cryptkeyarg arg; 997c478bd9Sstevel@tonic-gate cryptkeyres res; 1007c478bd9Sstevel@tonic-gate enum clnt_stat stat; 1017c478bd9Sstevel@tonic-gate 1027c478bd9Sstevel@tonic-gate RPCLOG(8, "key_encryptsession(%s, ", remotename); 1037c478bd9Sstevel@tonic-gate RPCLOG(8, "%x", *(uint32_t *)deskey); 1047c478bd9Sstevel@tonic-gate RPCLOG(8, "%x)\n", *(((uint32_t *)(deskey))+1)); 1057c478bd9Sstevel@tonic-gate 1067c478bd9Sstevel@tonic-gate arg.remotename = remotename; 1077c478bd9Sstevel@tonic-gate arg.deskey = *deskey; 1087c478bd9Sstevel@tonic-gate if ((stat = key_call(KEY_ENCRYPT, xdr_cryptkeyarg, (char *)&arg, 1097c478bd9Sstevel@tonic-gate xdr_cryptkeyres, (char *)&res, cr)) != RPC_SUCCESS) { 1107c478bd9Sstevel@tonic-gate RPCLOG(1, "key_encryptsession(%d, ", (int)crgetuid(cr)); 1117c478bd9Sstevel@tonic-gate RPCLOG(1, "%s): ", remotename); 1127c478bd9Sstevel@tonic-gate RPCLOG(1, "rpc status %d ", stat); 1137c478bd9Sstevel@tonic-gate RPCLOG(1, "(%s)\n", clnt_sperrno(stat)); 1147c478bd9Sstevel@tonic-gate return (stat); 1157c478bd9Sstevel@tonic-gate } 1167c478bd9Sstevel@tonic-gate 1177c478bd9Sstevel@tonic-gate if (res.status != KEY_SUCCESS) { 1187c478bd9Sstevel@tonic-gate RPCLOG(1, "key_encryptsession(%d, ", (int)crgetuid(cr)); 1197c478bd9Sstevel@tonic-gate RPCLOG(1, "%s): ", remotename); 1207c478bd9Sstevel@tonic-gate RPCLOG(1, "key status %d\n", res.status); 1217c478bd9Sstevel@tonic-gate return (RPC_FAILED); /* XXX */ 1227c478bd9Sstevel@tonic-gate } 1237c478bd9Sstevel@tonic-gate *deskey = res.cryptkeyres_u.deskey; 1247c478bd9Sstevel@tonic-gate return (RPC_SUCCESS); 1257c478bd9Sstevel@tonic-gate } 1267c478bd9Sstevel@tonic-gate 1277c478bd9Sstevel@tonic-gate enum clnt_stat 1287c478bd9Sstevel@tonic-gate key_decryptsession(char *remotename, des_block *deskey) 1297c478bd9Sstevel@tonic-gate { 1307c478bd9Sstevel@tonic-gate cryptkeyarg arg; 1317c478bd9Sstevel@tonic-gate cryptkeyres res; 1327c478bd9Sstevel@tonic-gate enum clnt_stat stat; 1337c478bd9Sstevel@tonic-gate 1347c478bd9Sstevel@tonic-gate RPCLOG(8, "key_decryptsession(%s, ", remotename); 1357c478bd9Sstevel@tonic-gate RPCLOG(2, "%x", *(uint32_t *)deskey); 1367c478bd9Sstevel@tonic-gate RPCLOG(2, "%x)\n", *(((uint32_t *)(deskey))+1)); 1377c478bd9Sstevel@tonic-gate 1387c478bd9Sstevel@tonic-gate arg.remotename = remotename; 1397c478bd9Sstevel@tonic-gate arg.deskey = *deskey; 1407c478bd9Sstevel@tonic-gate if ((stat = key_call(KEY_DECRYPT, xdr_cryptkeyarg, (char *)&arg, 1417c478bd9Sstevel@tonic-gate xdr_cryptkeyres, (char *)&res, kcred)) != RPC_SUCCESS) { 1427c478bd9Sstevel@tonic-gate RPCLOG(1, "key_decryptsession(%s): ", remotename); 1437c478bd9Sstevel@tonic-gate RPCLOG(1, "rpc status %d ", stat); 1447c478bd9Sstevel@tonic-gate RPCLOG(1, "(%s)\n", clnt_sperrno(stat)); 1457c478bd9Sstevel@tonic-gate return (stat); 1467c478bd9Sstevel@tonic-gate } 1477c478bd9Sstevel@tonic-gate 1487c478bd9Sstevel@tonic-gate if (res.status != KEY_SUCCESS) { 1497c478bd9Sstevel@tonic-gate RPCLOG(1, "key_decryptsession(%s): ", remotename); 1507c478bd9Sstevel@tonic-gate RPCLOG(1, "key status %d\n", res.status); 1517c478bd9Sstevel@tonic-gate return (RPC_FAILED); /* XXX */ 1527c478bd9Sstevel@tonic-gate } 1537c478bd9Sstevel@tonic-gate *deskey = res.cryptkeyres_u.deskey; 1547c478bd9Sstevel@tonic-gate return (RPC_SUCCESS); 1557c478bd9Sstevel@tonic-gate } 1567c478bd9Sstevel@tonic-gate 1577c478bd9Sstevel@tonic-gate enum clnt_stat 1587c478bd9Sstevel@tonic-gate key_gendes(des_block *key) 1597c478bd9Sstevel@tonic-gate { 1607c478bd9Sstevel@tonic-gate 1617c478bd9Sstevel@tonic-gate return (key_call(KEY_GEN, xdr_void, NULL, xdr_des_block, (char *)key, 1627c478bd9Sstevel@tonic-gate CRED())); 1637c478bd9Sstevel@tonic-gate } 1647c478bd9Sstevel@tonic-gate 1657c478bd9Sstevel@tonic-gate /* 1667c478bd9Sstevel@tonic-gate * Call up to keyserv to get the netname of the client based 1677c478bd9Sstevel@tonic-gate * on its uid. The netname is written into the string that "netname" 1687c478bd9Sstevel@tonic-gate * points to; the caller is responsible for ensuring that sufficient space 1697c478bd9Sstevel@tonic-gate * is available. 1707c478bd9Sstevel@tonic-gate */ 1717c478bd9Sstevel@tonic-gate enum clnt_stat 1727c478bd9Sstevel@tonic-gate key_getnetname(netname, cr) 1737c478bd9Sstevel@tonic-gate char *netname; 1747c478bd9Sstevel@tonic-gate cred_t *cr; 1757c478bd9Sstevel@tonic-gate { 1767c478bd9Sstevel@tonic-gate key_netstres kres; 1777c478bd9Sstevel@tonic-gate enum clnt_stat stat; 1787c478bd9Sstevel@tonic-gate 1797c478bd9Sstevel@tonic-gate /* 1807c478bd9Sstevel@tonic-gate * Look up the keyserv interface routines to see if 1817c478bd9Sstevel@tonic-gate * netname is stored there. 1827c478bd9Sstevel@tonic-gate */ 1837c478bd9Sstevel@tonic-gate kres.key_netstres_u.knet.st_netname = netname; 1847c478bd9Sstevel@tonic-gate if ((stat = key_call((rpcproc_t)KEY_NET_GET, xdr_void, NULL, 1857c478bd9Sstevel@tonic-gate xdr_key_netstres, (char *)&kres, cr)) != RPC_SUCCESS) { 1867c478bd9Sstevel@tonic-gate RPCLOG(1, "key_getnetname(%d): ", (int)crgetuid(cr)); 1877c478bd9Sstevel@tonic-gate RPCLOG(1, "rpc status %d ", stat); 1887c478bd9Sstevel@tonic-gate RPCLOG(1, "(%s)\n", clnt_sperrno(stat)); 1897c478bd9Sstevel@tonic-gate return (stat); 1907c478bd9Sstevel@tonic-gate } 1917c478bd9Sstevel@tonic-gate 1927c478bd9Sstevel@tonic-gate if (kres.status != KEY_SUCCESS) { 1937c478bd9Sstevel@tonic-gate RPCLOG(1, "key_getnetname(%d): ", (int)crgetuid(cr)); 1947c478bd9Sstevel@tonic-gate RPCLOG(1, "key status %d\n", kres.status); 1957c478bd9Sstevel@tonic-gate return (RPC_FAILED); 1967c478bd9Sstevel@tonic-gate } 1977c478bd9Sstevel@tonic-gate 1987c478bd9Sstevel@tonic-gate return (RPC_SUCCESS); 1997c478bd9Sstevel@tonic-gate } 2007c478bd9Sstevel@tonic-gate 2017c478bd9Sstevel@tonic-gate enum clnt_stat 202f48205beScasper netname2user(char *name, uid_t *uid, gid_t *gid, int *len, gid_t *groups) 2037c478bd9Sstevel@tonic-gate { 2047c478bd9Sstevel@tonic-gate struct getcredres res; 2057c478bd9Sstevel@tonic-gate enum clnt_stat stat; 2067c478bd9Sstevel@tonic-gate 2077c478bd9Sstevel@tonic-gate res.getcredres_u.cred.gids.gids_val = (uint_t *)groups; 2087c478bd9Sstevel@tonic-gate if ((stat = key_call(KEY_GETCRED, xdr_netnamestr, (char *)&name, 2097c478bd9Sstevel@tonic-gate xdr_getcredres, (char *)&res, CRED())) != RPC_SUCCESS) { 2107c478bd9Sstevel@tonic-gate RPCLOG(1, "netname2user(%s): ", name); 2117c478bd9Sstevel@tonic-gate RPCLOG(1, "rpc status %d ", stat); 2127c478bd9Sstevel@tonic-gate RPCLOG(1, "(%s)\n", clnt_sperrno(stat)); 2137c478bd9Sstevel@tonic-gate return (stat); 2147c478bd9Sstevel@tonic-gate } 2157c478bd9Sstevel@tonic-gate 2167c478bd9Sstevel@tonic-gate if (res.status != KEY_SUCCESS) { 2177c478bd9Sstevel@tonic-gate RPCLOG(1, "netname2user(%s): ", name); 2187c478bd9Sstevel@tonic-gate RPCLOG(1, "key status %d\n", res.status); 2197c478bd9Sstevel@tonic-gate return (RPC_FAILED); /* XXX */ 2207c478bd9Sstevel@tonic-gate } 2217c478bd9Sstevel@tonic-gate *uid = res.getcredres_u.cred.uid; 2227c478bd9Sstevel@tonic-gate *gid = res.getcredres_u.cred.gid; 2237c478bd9Sstevel@tonic-gate *len = res.getcredres_u.cred.gids.gids_len; 2247c478bd9Sstevel@tonic-gate return (RPC_SUCCESS); 2257c478bd9Sstevel@tonic-gate } 2267c478bd9Sstevel@tonic-gate 2277c478bd9Sstevel@tonic-gate #define NC_LOOPBACK "loopback" /* XXX */ 2287c478bd9Sstevel@tonic-gate char loopback_name[] = NC_LOOPBACK; 2297c478bd9Sstevel@tonic-gate 2307c478bd9Sstevel@tonic-gate static enum clnt_stat 2317c478bd9Sstevel@tonic-gate key_call(rpcproc_t procn, xdrproc_t xdr_args, caddr_t args, 2327c478bd9Sstevel@tonic-gate xdrproc_t xdr_rslt, caddr_t rslt, cred_t *cr) 2337c478bd9Sstevel@tonic-gate { 2347c478bd9Sstevel@tonic-gate struct netbuf netaddr; 2357c478bd9Sstevel@tonic-gate CLIENT *client; 2367c478bd9Sstevel@tonic-gate enum clnt_stat stat; 2377c478bd9Sstevel@tonic-gate vnode_t *vp; 2387c478bd9Sstevel@tonic-gate int error; 2397c478bd9Sstevel@tonic-gate struct auth_globals *authg; 2407c478bd9Sstevel@tonic-gate struct knetconfig *configp; 2417c478bd9Sstevel@tonic-gate k_sigset_t smask; 2427c478bd9Sstevel@tonic-gate 2437c478bd9Sstevel@tonic-gate authg = zone_getspecific(auth_zone_key, curproc->p_zone); 2447c478bd9Sstevel@tonic-gate configp = &authg->auth_config; 2457c478bd9Sstevel@tonic-gate 246*6935f61bSMarcel Telka /* strlen("localhost.keyserv") is 17 */ 247*6935f61bSMarcel Telka netaddr.len = netaddr.maxlen = 17; 248*6935f61bSMarcel Telka netaddr.buf = "localhost.keyserv"; 2497c478bd9Sstevel@tonic-gate 2507c478bd9Sstevel@tonic-gate /* 2517c478bd9Sstevel@tonic-gate * filch a knetconfig structure. 2527c478bd9Sstevel@tonic-gate */ 2537c478bd9Sstevel@tonic-gate if (configp->knc_rdev == 0) { 2547c478bd9Sstevel@tonic-gate if ((error = lookupname("/dev/ticlts", UIO_SYSSPACE, 2557c478bd9Sstevel@tonic-gate FOLLOW, NULLVPP, &vp)) != 0) { 2567c478bd9Sstevel@tonic-gate RPCLOG(1, "key_call: lookupname: %d\n", error); 2577c478bd9Sstevel@tonic-gate return (RPC_UNKNOWNPROTO); 2587c478bd9Sstevel@tonic-gate } 2597c478bd9Sstevel@tonic-gate configp->knc_rdev = vp->v_rdev; 2607c478bd9Sstevel@tonic-gate configp->knc_protofmly = loopback_name; 2617c478bd9Sstevel@tonic-gate VN_RELE(vp); 2627c478bd9Sstevel@tonic-gate } 2637c478bd9Sstevel@tonic-gate configp->knc_semantics = NC_TPI_CLTS; 2647c478bd9Sstevel@tonic-gate RPCLOG(8, "key_call: procn %d, ", procn); 2657c478bd9Sstevel@tonic-gate RPCLOG(8, "rdev %lx, ", configp->knc_rdev); 2667c478bd9Sstevel@tonic-gate RPCLOG(8, "len %d, ", netaddr.len); 2677c478bd9Sstevel@tonic-gate RPCLOG(8, "maxlen %d, ", netaddr.maxlen); 2687c478bd9Sstevel@tonic-gate RPCLOG(8, "name %p\n", (void *)netaddr.buf); 2697c478bd9Sstevel@tonic-gate 2707c478bd9Sstevel@tonic-gate /* 2717c478bd9Sstevel@tonic-gate * now call the proper stuff. 2727c478bd9Sstevel@tonic-gate */ 2737c478bd9Sstevel@tonic-gate error = clnt_tli_kcreate(configp, &netaddr, KEY_PROG, KEY_VERS, 2747c478bd9Sstevel@tonic-gate 0, KEY_NRETRY, cr, &client); 2757c478bd9Sstevel@tonic-gate 2767c478bd9Sstevel@tonic-gate if (error != 0) { 2777c478bd9Sstevel@tonic-gate RPCLOG(1, "key_call: clnt_tli_kcreate: error %d\n", error); 2787c478bd9Sstevel@tonic-gate switch (error) { 2797c478bd9Sstevel@tonic-gate case EINTR: 2807c478bd9Sstevel@tonic-gate return (RPC_INTR); 2817c478bd9Sstevel@tonic-gate case ETIMEDOUT: 2827c478bd9Sstevel@tonic-gate return (RPC_TIMEDOUT); 2837c478bd9Sstevel@tonic-gate default: 2847c478bd9Sstevel@tonic-gate return (RPC_FAILED); /* XXX */ 2857c478bd9Sstevel@tonic-gate } 2867c478bd9Sstevel@tonic-gate } 2877c478bd9Sstevel@tonic-gate 2887c478bd9Sstevel@tonic-gate auth_destroy(client->cl_auth); 2897c478bd9Sstevel@tonic-gate client->cl_auth = authloopback_create(); 2907c478bd9Sstevel@tonic-gate if (client->cl_auth == NULL) { 2917c478bd9Sstevel@tonic-gate clnt_destroy(client); 2927c478bd9Sstevel@tonic-gate RPCLOG(1, "key_call: authloopback_create: error %d\n", EINTR); 2937c478bd9Sstevel@tonic-gate return (RPC_INTR); 2947c478bd9Sstevel@tonic-gate } 2957c478bd9Sstevel@tonic-gate 2967c478bd9Sstevel@tonic-gate /* Mask out all signals except SIGHUP, SIGQUIT, and SIGTERM. */ 2977c478bd9Sstevel@tonic-gate sigintr(&smask, 0); 2987c478bd9Sstevel@tonic-gate stat = clnt_call(client, procn, xdr_args, args, xdr_rslt, rslt, 2997c478bd9Sstevel@tonic-gate keytrytimeout); 3007c478bd9Sstevel@tonic-gate sigunintr(&smask); 3017c478bd9Sstevel@tonic-gate 3027c478bd9Sstevel@tonic-gate auth_destroy(client->cl_auth); 3037c478bd9Sstevel@tonic-gate clnt_destroy(client); 3047c478bd9Sstevel@tonic-gate if (stat != RPC_SUCCESS) { 3057c478bd9Sstevel@tonic-gate RPCLOG(1, "key_call: keyserver clnt_call failed: stat %d ", 3067c478bd9Sstevel@tonic-gate stat); 3077c478bd9Sstevel@tonic-gate RPCLOG(1, "(%s)\n", clnt_sperrno(stat)); 3087c478bd9Sstevel@tonic-gate RPCLOG0(1, "\n"); 3097c478bd9Sstevel@tonic-gate return (stat); 3107c478bd9Sstevel@tonic-gate } 3117c478bd9Sstevel@tonic-gate RPCLOG(8, "key call: (%d) ok\n", procn); 3127c478bd9Sstevel@tonic-gate return (RPC_SUCCESS); 3137c478bd9Sstevel@tonic-gate } 314