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