xref: /titanic_54/usr/src/cmd/keyserv/setkey.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright 1998 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate /*
28*7c478bd9Sstevel@tonic-gate  * University Copyright- Copyright (c) 1982, 1986, 1988
29*7c478bd9Sstevel@tonic-gate  * The Regents of the University of California
30*7c478bd9Sstevel@tonic-gate  * All Rights Reserved
31*7c478bd9Sstevel@tonic-gate  *
32*7c478bd9Sstevel@tonic-gate  * University Acknowledgment- Portions of this document are derived from
33*7c478bd9Sstevel@tonic-gate  * software developed by the University of California, Berkeley, and its
34*7c478bd9Sstevel@tonic-gate  * contributors.
35*7c478bd9Sstevel@tonic-gate  */
36*7c478bd9Sstevel@tonic-gate 
37*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
38*7c478bd9Sstevel@tonic-gate 
39*7c478bd9Sstevel@tonic-gate /*
40*7c478bd9Sstevel@tonic-gate  * Do the real work of the keyserver.
41*7c478bd9Sstevel@tonic-gate  * Store secret keys. Compute common keys,
42*7c478bd9Sstevel@tonic-gate  * and use them to decrypt and encrypt DES keys.
43*7c478bd9Sstevel@tonic-gate  * Cache the common keys, so the expensive computation is avoided.
44*7c478bd9Sstevel@tonic-gate  */
45*7c478bd9Sstevel@tonic-gate #include <stdio.h>
46*7c478bd9Sstevel@tonic-gate #include <stdlib.h>
47*7c478bd9Sstevel@tonic-gate #include <mp.h>
48*7c478bd9Sstevel@tonic-gate #include <rpc/rpc.h>
49*7c478bd9Sstevel@tonic-gate #include <rpc/key_prot.h>
50*7c478bd9Sstevel@tonic-gate #include <rpc/des_crypt.h>
51*7c478bd9Sstevel@tonic-gate #include <rpcsvc/nis_dhext.h>
52*7c478bd9Sstevel@tonic-gate #include <sys/errno.h>
53*7c478bd9Sstevel@tonic-gate #include <string.h>
54*7c478bd9Sstevel@tonic-gate #include <thread.h>
55*7c478bd9Sstevel@tonic-gate #include <syslog.h>
56*7c478bd9Sstevel@tonic-gate 
57*7c478bd9Sstevel@tonic-gate #include "debug.h"
58*7c478bd9Sstevel@tonic-gate #include "keyserv_cache.h"
59*7c478bd9Sstevel@tonic-gate 
60*7c478bd9Sstevel@tonic-gate extern char ROOTKEY[];
61*7c478bd9Sstevel@tonic-gate extern mechanism_t **mechs;
62*7c478bd9Sstevel@tonic-gate extern char **cache_options;
63*7c478bd9Sstevel@tonic-gate extern int *cache_size;
64*7c478bd9Sstevel@tonic-gate extern int disk_caching;
65*7c478bd9Sstevel@tonic-gate 
66*7c478bd9Sstevel@tonic-gate static MINT *MODULUS;
67*7c478bd9Sstevel@tonic-gate static int hash_keys();
68*7c478bd9Sstevel@tonic-gate static keystatus pk_crypt();
69*7c478bd9Sstevel@tonic-gate static keystatus pk_crypt3();
70*7c478bd9Sstevel@tonic-gate static int nodefaultkeys = 0;
71*7c478bd9Sstevel@tonic-gate 
72*7c478bd9Sstevel@tonic-gate #define	DES		"des"
73*7c478bd9Sstevel@tonic-gate #define	DESALIAS	"dh192-0"
74*7c478bd9Sstevel@tonic-gate #define	DHMECHSTR	"diffie_hellman"
75*7c478bd9Sstevel@tonic-gate #define	CLASSIC_PK_DH(k, a)	(((k) == 192) && ((a) == 0))
76*7c478bd9Sstevel@tonic-gate 
77*7c478bd9Sstevel@tonic-gate /*
78*7c478bd9Sstevel@tonic-gate  * Exponential caching management
79*7c478bd9Sstevel@tonic-gate  */
80*7c478bd9Sstevel@tonic-gate struct cachekey_list {
81*7c478bd9Sstevel@tonic-gate 	keybuf secret;
82*7c478bd9Sstevel@tonic-gate 	keybuf public;
83*7c478bd9Sstevel@tonic-gate 	des_block deskey;
84*7c478bd9Sstevel@tonic-gate 	struct cachekey_list *next;
85*7c478bd9Sstevel@tonic-gate };
86*7c478bd9Sstevel@tonic-gate #define	KEY_HASH_SIZE	256
87*7c478bd9Sstevel@tonic-gate static struct cachekey_list *g_cachedkeys[KEY_HASH_SIZE];
88*7c478bd9Sstevel@tonic-gate static rwlock_t g_cachedkeys_lock = DEFAULTRWLOCK;
89*7c478bd9Sstevel@tonic-gate 
90*7c478bd9Sstevel@tonic-gate #ifdef DEBUG
91*7c478bd9Sstevel@tonic-gate int
92*7c478bd9Sstevel@tonic-gate test_debug(debug_level level, char *file, int line)
93*7c478bd9Sstevel@tonic-gate {
94*7c478bd9Sstevel@tonic-gate 	if (level < debugging)
95*7c478bd9Sstevel@tonic-gate 		return (0);
96*7c478bd9Sstevel@tonic-gate 	fprintf(stderr, "file %s,\tline %d :\t", file, line);
97*7c478bd9Sstevel@tonic-gate 	return (1);
98*7c478bd9Sstevel@tonic-gate }
99*7c478bd9Sstevel@tonic-gate 
100*7c478bd9Sstevel@tonic-gate int
101*7c478bd9Sstevel@tonic-gate real_debug(char *fmt, ...)
102*7c478bd9Sstevel@tonic-gate {
103*7c478bd9Sstevel@tonic-gate 	va_list args;
104*7c478bd9Sstevel@tonic-gate 
105*7c478bd9Sstevel@tonic-gate 	va_start(args, fmt);
106*7c478bd9Sstevel@tonic-gate 	(void) vfprintf(stderr, fmt, args);
107*7c478bd9Sstevel@tonic-gate 	va_end(args);
108*7c478bd9Sstevel@tonic-gate 	fprintf(stderr, "\n");
109*7c478bd9Sstevel@tonic-gate 	fflush(stderr);
110*7c478bd9Sstevel@tonic-gate 	return (1);
111*7c478bd9Sstevel@tonic-gate }
112*7c478bd9Sstevel@tonic-gate #endif /* DEBUG */
113*7c478bd9Sstevel@tonic-gate 
114*7c478bd9Sstevel@tonic-gate struct cacheuid_list {
115*7c478bd9Sstevel@tonic-gate 	uid_t uid;
116*7c478bd9Sstevel@tonic-gate 	int refcnt;
117*7c478bd9Sstevel@tonic-gate 	keybuf3 *secretkey;
118*7c478bd9Sstevel@tonic-gate 	keybuf3 *publickey;
119*7c478bd9Sstevel@tonic-gate 	netnamestr netname;
120*7c478bd9Sstevel@tonic-gate 	des_block key;
121*7c478bd9Sstevel@tonic-gate 	struct cacheuid_list *next;
122*7c478bd9Sstevel@tonic-gate };
123*7c478bd9Sstevel@tonic-gate 
124*7c478bd9Sstevel@tonic-gate #define	NUMHASHBUCKETS	256
125*7c478bd9Sstevel@tonic-gate #define	HASH_UID(x) (x & 0xff)
126*7c478bd9Sstevel@tonic-gate 
127*7c478bd9Sstevel@tonic-gate struct mechdata {
128*7c478bd9Sstevel@tonic-gate 	struct cacheuid_list *bucket[NUMHASHBUCKETS];
129*7c478bd9Sstevel@tonic-gate };
130*7c478bd9Sstevel@tonic-gate 
131*7c478bd9Sstevel@tonic-gate struct psdata {
132*7c478bd9Sstevel@tonic-gate 	struct cachekey3_list *common[NUMHASHBUCKETS];
133*7c478bd9Sstevel@tonic-gate };
134*7c478bd9Sstevel@tonic-gate 
135*7c478bd9Sstevel@tonic-gate struct mechentry {
136*7c478bd9Sstevel@tonic-gate 	mutex_t mech_lock;
137*7c478bd9Sstevel@tonic-gate 	struct mechdata *mechdata;
138*7c478bd9Sstevel@tonic-gate 	mutex_t ps_lock;
139*7c478bd9Sstevel@tonic-gate 	struct psdata *psdata;
140*7c478bd9Sstevel@tonic-gate };
141*7c478bd9Sstevel@tonic-gate 
142*7c478bd9Sstevel@tonic-gate /*
143*7c478bd9Sstevel@tonic-gate  * we don't need to worry about locking for the keylen + algtype
144*7c478bd9Sstevel@tonic-gate  * sparse array because it is created once and for all during
145*7c478bd9Sstevel@tonic-gate  * initialization when there are no threads. The mechentry field
146*7c478bd9Sstevel@tonic-gate  * and everything underneath it needs protection and this is what
147*7c478bd9Sstevel@tonic-gate  * the *_lock fields are for.
148*7c478bd9Sstevel@tonic-gate  */
149*7c478bd9Sstevel@tonic-gate struct algtypelist {
150*7c478bd9Sstevel@tonic-gate 	algtype_t algtype;
151*7c478bd9Sstevel@tonic-gate 	struct algtypelist *next;
152*7c478bd9Sstevel@tonic-gate 	struct mechentry mech;
153*7c478bd9Sstevel@tonic-gate };
154*7c478bd9Sstevel@tonic-gate 
155*7c478bd9Sstevel@tonic-gate struct keylenlist {
156*7c478bd9Sstevel@tonic-gate 	keylen_t keylen;
157*7c478bd9Sstevel@tonic-gate 	struct algtypelist *ap;
158*7c478bd9Sstevel@tonic-gate 	struct keylenlist *next;
159*7c478bd9Sstevel@tonic-gate };
160*7c478bd9Sstevel@tonic-gate 
161*7c478bd9Sstevel@tonic-gate #define	KEYSERV_VERSION	"1.0"
162*7c478bd9Sstevel@tonic-gate 
163*7c478bd9Sstevel@tonic-gate static struct mechtable {
164*7c478bd9Sstevel@tonic-gate 	char *version;
165*7c478bd9Sstevel@tonic-gate 	struct keylenlist *kp;
166*7c478bd9Sstevel@tonic-gate } mechtable = {KEYSERV_VERSION, NULL};
167*7c478bd9Sstevel@tonic-gate 
168*7c478bd9Sstevel@tonic-gate static struct keylenlist **
169*7c478bd9Sstevel@tonic-gate getkeylen(keylen_t k)
170*7c478bd9Sstevel@tonic-gate {
171*7c478bd9Sstevel@tonic-gate 	struct keylenlist **kpp;
172*7c478bd9Sstevel@tonic-gate 
173*7c478bd9Sstevel@tonic-gate 	debug(KEYSERV_DEBUG1, ("getkeylen key: %d", k));
174*7c478bd9Sstevel@tonic-gate 	for (kpp = &mechtable.kp;
175*7c478bd9Sstevel@tonic-gate 		*kpp != NULL && (*kpp)->keylen != k;
176*7c478bd9Sstevel@tonic-gate 		kpp = &(*kpp)->next)
177*7c478bd9Sstevel@tonic-gate 		debug(KEYSERV_DEBUG0, ("getkeylen failed %x", kpp));
178*7c478bd9Sstevel@tonic-gate 	debug(KEYSERV_DEBUG0, ("getkeylen return: %x", kpp));
179*7c478bd9Sstevel@tonic-gate 	return (kpp);
180*7c478bd9Sstevel@tonic-gate }
181*7c478bd9Sstevel@tonic-gate 
182*7c478bd9Sstevel@tonic-gate static void
183*7c478bd9Sstevel@tonic-gate appendkeylist(struct keylenlist **kpp, keylen_t k)
184*7c478bd9Sstevel@tonic-gate {
185*7c478bd9Sstevel@tonic-gate 	struct keylenlist *kp;
186*7c478bd9Sstevel@tonic-gate 
187*7c478bd9Sstevel@tonic-gate 	if (*kpp == NULL) {
188*7c478bd9Sstevel@tonic-gate 		kp = (struct keylenlist *)malloc(sizeof (*kp));
189*7c478bd9Sstevel@tonic-gate 		if (kp == NULL) {
190*7c478bd9Sstevel@tonic-gate 			debug(KEYSERV_INFO, ("appendkeylist : malloc failed"));
191*7c478bd9Sstevel@tonic-gate 			return;
192*7c478bd9Sstevel@tonic-gate 		}
193*7c478bd9Sstevel@tonic-gate 		debug(KEYSERV_DEBUG, ("appendkeylist : %x %x %d", kpp, kp, k));
194*7c478bd9Sstevel@tonic-gate 		kp->keylen = k;
195*7c478bd9Sstevel@tonic-gate 		kp->ap = NULL;
196*7c478bd9Sstevel@tonic-gate 		kp->next = NULL;
197*7c478bd9Sstevel@tonic-gate 		*kpp = kp;
198*7c478bd9Sstevel@tonic-gate 	} else {
199*7c478bd9Sstevel@tonic-gate 		/*EMPTY*/
200*7c478bd9Sstevel@tonic-gate 		/* do nothing; only happens for multiple algtypes */
201*7c478bd9Sstevel@tonic-gate 		debug(KEYSERV_DEBUG0,
202*7c478bd9Sstevel@tonic-gate 			("appendkeylist called for non tail element"));
203*7c478bd9Sstevel@tonic-gate 	}
204*7c478bd9Sstevel@tonic-gate }
205*7c478bd9Sstevel@tonic-gate 
206*7c478bd9Sstevel@tonic-gate static struct algtypelist **
207*7c478bd9Sstevel@tonic-gate getalgtype(struct keylenlist **kpp, algtype_t a)
208*7c478bd9Sstevel@tonic-gate {
209*7c478bd9Sstevel@tonic-gate 	struct algtypelist **app;
210*7c478bd9Sstevel@tonic-gate 
211*7c478bd9Sstevel@tonic-gate 	debug(KEYSERV_DEBUG1, ("getalgtype key: %d", a));
212*7c478bd9Sstevel@tonic-gate 	for (app = &(*kpp)->ap;
213*7c478bd9Sstevel@tonic-gate 		*app != NULL && (*app)->algtype != a;
214*7c478bd9Sstevel@tonic-gate 		app = &(*app)->next)
215*7c478bd9Sstevel@tonic-gate 		debug(KEYSERV_DEBUG0, ("getalgtype key: %x", app));
216*7c478bd9Sstevel@tonic-gate 	debug(KEYSERV_DEBUG0, ("getalgtype return: %x", app));
217*7c478bd9Sstevel@tonic-gate 	return (app);
218*7c478bd9Sstevel@tonic-gate }
219*7c478bd9Sstevel@tonic-gate 
220*7c478bd9Sstevel@tonic-gate static void
221*7c478bd9Sstevel@tonic-gate appendalgtype(struct algtypelist **app, algtype_t a)
222*7c478bd9Sstevel@tonic-gate {
223*7c478bd9Sstevel@tonic-gate 	struct algtypelist *ap;
224*7c478bd9Sstevel@tonic-gate 
225*7c478bd9Sstevel@tonic-gate 	if (*app == NULL) {
226*7c478bd9Sstevel@tonic-gate 		ap = (struct algtypelist *)malloc(sizeof (*ap));
227*7c478bd9Sstevel@tonic-gate 		if (ap == NULL) {
228*7c478bd9Sstevel@tonic-gate 			debug(KEYSERV_INFO, ("appendalgtype : malloc failed"));
229*7c478bd9Sstevel@tonic-gate 			return;
230*7c478bd9Sstevel@tonic-gate 		}
231*7c478bd9Sstevel@tonic-gate 		debug(KEYSERV_DEBUG, ("appendalgtype : %x %x %d", app, ap, a));
232*7c478bd9Sstevel@tonic-gate 		ap->algtype = a;
233*7c478bd9Sstevel@tonic-gate 		mutex_init(&ap->mech.mech_lock, USYNC_THREAD, NULL);
234*7c478bd9Sstevel@tonic-gate 		mutex_init(&ap->mech.ps_lock, USYNC_THREAD, NULL);
235*7c478bd9Sstevel@tonic-gate 		ap->mech.mechdata = NULL;
236*7c478bd9Sstevel@tonic-gate 		ap->mech.psdata = NULL;
237*7c478bd9Sstevel@tonic-gate 		ap->next = NULL;
238*7c478bd9Sstevel@tonic-gate 		*app = ap;
239*7c478bd9Sstevel@tonic-gate 	} else {
240*7c478bd9Sstevel@tonic-gate 		/*EMPTY*/
241*7c478bd9Sstevel@tonic-gate 		/* don't mind duplicate (keylen,algtype) paris for now. */
242*7c478bd9Sstevel@tonic-gate 		debug(KEYSERV_DEBUG0,
243*7c478bd9Sstevel@tonic-gate 			("appendalgtype called for non tail element"));
244*7c478bd9Sstevel@tonic-gate 	}
245*7c478bd9Sstevel@tonic-gate }
246*7c478bd9Sstevel@tonic-gate 
247*7c478bd9Sstevel@tonic-gate static struct mechentry *
248*7c478bd9Sstevel@tonic-gate getmechtype(keylen_t k, algtype_t a)
249*7c478bd9Sstevel@tonic-gate {
250*7c478bd9Sstevel@tonic-gate 	struct keylenlist **kpp;
251*7c478bd9Sstevel@tonic-gate 	struct algtypelist **app;
252*7c478bd9Sstevel@tonic-gate 
253*7c478bd9Sstevel@tonic-gate 	debug(KEYSERV_DEBUG1, ("getmechtype %d %d", k, a));
254*7c478bd9Sstevel@tonic-gate 	kpp = getkeylen(k);
255*7c478bd9Sstevel@tonic-gate 	if (*kpp == NULL) {
256*7c478bd9Sstevel@tonic-gate 		debug(KEYSERV_DEBUG0, ("getmechtype %d not found in keys", k));
257*7c478bd9Sstevel@tonic-gate 		return (0);
258*7c478bd9Sstevel@tonic-gate 	}
259*7c478bd9Sstevel@tonic-gate 	app = getalgtype(kpp, a);
260*7c478bd9Sstevel@tonic-gate 	if (*app == NULL) {
261*7c478bd9Sstevel@tonic-gate 		debug(KEYSERV_DEBUG0, ("getmechtype %d not found in algs", a));
262*7c478bd9Sstevel@tonic-gate 		return (0);
263*7c478bd9Sstevel@tonic-gate 	}
264*7c478bd9Sstevel@tonic-gate 	debug(KEYSERV_DEBUG0, ("getmechtype found %x", app));
265*7c478bd9Sstevel@tonic-gate 	debug(KEYSERV_DEBUG0, ("getmechtype return %x", &(*app)->mech));
266*7c478bd9Sstevel@tonic-gate 	return (&(*app)->mech);
267*7c478bd9Sstevel@tonic-gate }
268*7c478bd9Sstevel@tonic-gate 
269*7c478bd9Sstevel@tonic-gate static keybuf3 *
270*7c478bd9Sstevel@tonic-gate getkeybuf3(int k)
271*7c478bd9Sstevel@tonic-gate {
272*7c478bd9Sstevel@tonic-gate 	keybuf3 *buf;
273*7c478bd9Sstevel@tonic-gate 
274*7c478bd9Sstevel@tonic-gate 	debug(KEYSERV_DEBUG, ("getkeybuf3 malloc %d", k));
275*7c478bd9Sstevel@tonic-gate 	buf = (keybuf3 *) malloc(sizeof (*buf));
276*7c478bd9Sstevel@tonic-gate 	if (buf == NULL) {
277*7c478bd9Sstevel@tonic-gate 		debug(KEYSERV_DEBUG, ("getkeybuf3 malloc failed"));
278*7c478bd9Sstevel@tonic-gate 		syslog(LOG_ERR, "file %s line %d: malloc failed",
279*7c478bd9Sstevel@tonic-gate 			__FILE__, __LINE__);
280*7c478bd9Sstevel@tonic-gate 		return (NULL);
281*7c478bd9Sstevel@tonic-gate 	}
282*7c478bd9Sstevel@tonic-gate 	buf->keybuf3_len = k;
283*7c478bd9Sstevel@tonic-gate 	/* XXX special case k==0 */
284*7c478bd9Sstevel@tonic-gate 	if (k == 0) {
285*7c478bd9Sstevel@tonic-gate 		buf->keybuf3_val = NULL;
286*7c478bd9Sstevel@tonic-gate 	} else {
287*7c478bd9Sstevel@tonic-gate 		buf->keybuf3_val = (char *)malloc(k);
288*7c478bd9Sstevel@tonic-gate 		if (buf->keybuf3_val == NULL) {
289*7c478bd9Sstevel@tonic-gate 			debug(KEYSERV_DEBUG, ("getkeybuf3 malloc failed"));
290*7c478bd9Sstevel@tonic-gate 			free(buf);
291*7c478bd9Sstevel@tonic-gate 			syslog(LOG_ERR, "file %s line %d: malloc failed",
292*7c478bd9Sstevel@tonic-gate 				__FILE__, __LINE__);
293*7c478bd9Sstevel@tonic-gate 			return (NULL);
294*7c478bd9Sstevel@tonic-gate 		}
295*7c478bd9Sstevel@tonic-gate 	}
296*7c478bd9Sstevel@tonic-gate 	debug(KEYSERV_DEBUG1, ("getkeybuf3 ret %x", buf));
297*7c478bd9Sstevel@tonic-gate 	return (buf);
298*7c478bd9Sstevel@tonic-gate }
299*7c478bd9Sstevel@tonic-gate 
300*7c478bd9Sstevel@tonic-gate static void
301*7c478bd9Sstevel@tonic-gate freekeybuf3(keybuf3 *kp)
302*7c478bd9Sstevel@tonic-gate {
303*7c478bd9Sstevel@tonic-gate 	debug(KEYSERV_DEBUG1, ("freekeybuf3 %x", kp));
304*7c478bd9Sstevel@tonic-gate 	if (kp == NULL)
305*7c478bd9Sstevel@tonic-gate 		return;
306*7c478bd9Sstevel@tonic-gate 	if (kp->keybuf3_val) {
307*7c478bd9Sstevel@tonic-gate 		/* XXX kp->keybuf3_len != 0? */
308*7c478bd9Sstevel@tonic-gate 		free(kp->keybuf3_val);
309*7c478bd9Sstevel@tonic-gate 	}
310*7c478bd9Sstevel@tonic-gate 	free(kp);
311*7c478bd9Sstevel@tonic-gate }
312*7c478bd9Sstevel@tonic-gate 
313*7c478bd9Sstevel@tonic-gate static keybuf3 *
314*7c478bd9Sstevel@tonic-gate cpykeybuf3(keybuf3 *src)
315*7c478bd9Sstevel@tonic-gate {
316*7c478bd9Sstevel@tonic-gate 	keybuf3 *dst;
317*7c478bd9Sstevel@tonic-gate 
318*7c478bd9Sstevel@tonic-gate 	if (src == NULL) {
319*7c478bd9Sstevel@tonic-gate 		return (NULL);
320*7c478bd9Sstevel@tonic-gate 	}
321*7c478bd9Sstevel@tonic-gate 	if ((dst = getkeybuf3(src->keybuf3_len)) == NULL) {
322*7c478bd9Sstevel@tonic-gate 		return (NULL);
323*7c478bd9Sstevel@tonic-gate 	}
324*7c478bd9Sstevel@tonic-gate 	memcpy(dst->keybuf3_val, src->keybuf3_val, src->keybuf3_len);
325*7c478bd9Sstevel@tonic-gate 	debug(KEYSERV_DEBUG0, ("cpykeybuf3 ret %x", dst));
326*7c478bd9Sstevel@tonic-gate 	return (dst);
327*7c478bd9Sstevel@tonic-gate }
328*7c478bd9Sstevel@tonic-gate 
329*7c478bd9Sstevel@tonic-gate static keybuf3 *
330*7c478bd9Sstevel@tonic-gate setkeybuf3(char *src, int len)
331*7c478bd9Sstevel@tonic-gate {
332*7c478bd9Sstevel@tonic-gate 	keybuf3 *dst;
333*7c478bd9Sstevel@tonic-gate 
334*7c478bd9Sstevel@tonic-gate 	if ((dst = getkeybuf3(++len)) == NULL) {
335*7c478bd9Sstevel@tonic-gate 		return (NULL);
336*7c478bd9Sstevel@tonic-gate 	}
337*7c478bd9Sstevel@tonic-gate 	memcpy(dst->keybuf3_val, src, len);
338*7c478bd9Sstevel@tonic-gate 	return (dst);
339*7c478bd9Sstevel@tonic-gate }
340*7c478bd9Sstevel@tonic-gate 
341*7c478bd9Sstevel@tonic-gate static int
342*7c478bd9Sstevel@tonic-gate cmpkeybuf3(keybuf3 *k1, keybuf3 *k2)
343*7c478bd9Sstevel@tonic-gate {
344*7c478bd9Sstevel@tonic-gate 	if ((k1 == NULL) || (k2 == NULL)) {
345*7c478bd9Sstevel@tonic-gate 		syslog(LOG_ERR, "cmpkeybuf3: invalid parameter: %x, %x",
346*7c478bd9Sstevel@tonic-gate 			k1, k2);
347*7c478bd9Sstevel@tonic-gate 		return (0);
348*7c478bd9Sstevel@tonic-gate 	}
349*7c478bd9Sstevel@tonic-gate 	if (k1->keybuf3_len != k2->keybuf3_len) {
350*7c478bd9Sstevel@tonic-gate 		return (0);
351*7c478bd9Sstevel@tonic-gate 	}
352*7c478bd9Sstevel@tonic-gate 	return (!memcmp(k1->keybuf3_val, k2->keybuf3_val, k1->keybuf3_len));
353*7c478bd9Sstevel@tonic-gate }
354*7c478bd9Sstevel@tonic-gate 
355*7c478bd9Sstevel@tonic-gate static int
356*7c478bd9Sstevel@tonic-gate storekeybuf3(keybuf3 *dst, keybuf3 *src)
357*7c478bd9Sstevel@tonic-gate {
358*7c478bd9Sstevel@tonic-gate 	keybuf3 *tmp;
359*7c478bd9Sstevel@tonic-gate 
360*7c478bd9Sstevel@tonic-gate 	if ((tmp = cpykeybuf3(src)) == NULL) {
361*7c478bd9Sstevel@tonic-gate 		return (0);
362*7c478bd9Sstevel@tonic-gate 	}
363*7c478bd9Sstevel@tonic-gate 	*dst = *tmp;
364*7c478bd9Sstevel@tonic-gate 	free(tmp); /* but not the contents */
365*7c478bd9Sstevel@tonic-gate 	debug(KEYSERV_DEBUG0, ("storekeybuf3 ret %d %x",
366*7c478bd9Sstevel@tonic-gate 		dst->keybuf3_len, dst->keybuf3_val));
367*7c478bd9Sstevel@tonic-gate 	return (1);
368*7c478bd9Sstevel@tonic-gate }
369*7c478bd9Sstevel@tonic-gate 
370*7c478bd9Sstevel@tonic-gate static deskeyarray *
371*7c478bd9Sstevel@tonic-gate getdeskeyarray(int k)
372*7c478bd9Sstevel@tonic-gate {
373*7c478bd9Sstevel@tonic-gate 	deskeyarray *buf;
374*7c478bd9Sstevel@tonic-gate 
375*7c478bd9Sstevel@tonic-gate 	debug(KEYSERV_DEBUG, ("getdeskeyarray malloc %d", k));
376*7c478bd9Sstevel@tonic-gate 	buf = (deskeyarray *) malloc(sizeof (*buf));
377*7c478bd9Sstevel@tonic-gate 	if (buf == NULL) {
378*7c478bd9Sstevel@tonic-gate 		debug(KEYSERV_DEBUG, ("getdeskeyarray malloc failed"));
379*7c478bd9Sstevel@tonic-gate 		syslog(LOG_ERR, "file %s line %d: malloc failed",
380*7c478bd9Sstevel@tonic-gate 			__FILE__, __LINE__);
381*7c478bd9Sstevel@tonic-gate 		return (NULL);
382*7c478bd9Sstevel@tonic-gate 	}
383*7c478bd9Sstevel@tonic-gate 	buf->deskeyarray_len = k;
384*7c478bd9Sstevel@tonic-gate 	/* XXX special case k==0 */
385*7c478bd9Sstevel@tonic-gate 	if (k == 0) {
386*7c478bd9Sstevel@tonic-gate 		buf->deskeyarray_val = NULL;
387*7c478bd9Sstevel@tonic-gate 	} else {
388*7c478bd9Sstevel@tonic-gate 		buf->deskeyarray_val = (des_block *)
389*7c478bd9Sstevel@tonic-gate 			malloc(k * sizeof (des_block));
390*7c478bd9Sstevel@tonic-gate 		if (buf->deskeyarray_val == NULL) {
391*7c478bd9Sstevel@tonic-gate 			debug(KEYSERV_DEBUG, ("getdeskeyarray malloc failed"));
392*7c478bd9Sstevel@tonic-gate 			free(buf);
393*7c478bd9Sstevel@tonic-gate 			syslog(LOG_ERR, "file %s line %d: malloc failed",
394*7c478bd9Sstevel@tonic-gate 				__FILE__, __LINE__);
395*7c478bd9Sstevel@tonic-gate 			return (NULL);
396*7c478bd9Sstevel@tonic-gate 		}
397*7c478bd9Sstevel@tonic-gate 	}
398*7c478bd9Sstevel@tonic-gate 	debug(KEYSERV_DEBUG1, ("getdeskeyarray ret %x", buf));
399*7c478bd9Sstevel@tonic-gate 	return (buf);
400*7c478bd9Sstevel@tonic-gate }
401*7c478bd9Sstevel@tonic-gate 
402*7c478bd9Sstevel@tonic-gate static deskeyarray *
403*7c478bd9Sstevel@tonic-gate cpydeskeyarray(deskeyarray *src)
404*7c478bd9Sstevel@tonic-gate {
405*7c478bd9Sstevel@tonic-gate 	deskeyarray *dst;
406*7c478bd9Sstevel@tonic-gate 
407*7c478bd9Sstevel@tonic-gate 	if (src == NULL) {
408*7c478bd9Sstevel@tonic-gate 		return (NULL);
409*7c478bd9Sstevel@tonic-gate 	}
410*7c478bd9Sstevel@tonic-gate 	if ((dst = getdeskeyarray(src->deskeyarray_len)) == NULL) {
411*7c478bd9Sstevel@tonic-gate 		return (NULL);
412*7c478bd9Sstevel@tonic-gate 	}
413*7c478bd9Sstevel@tonic-gate 	memcpy(dst->deskeyarray_val, src->deskeyarray_val,
414*7c478bd9Sstevel@tonic-gate 		src->deskeyarray_len * sizeof (des_block));
415*7c478bd9Sstevel@tonic-gate 	debug(KEYSERV_DEBUG0, ("cpydeskeyarray ret %x", dst));
416*7c478bd9Sstevel@tonic-gate 	return (dst);
417*7c478bd9Sstevel@tonic-gate }
418*7c478bd9Sstevel@tonic-gate 
419*7c478bd9Sstevel@tonic-gate static int
420*7c478bd9Sstevel@tonic-gate storedeskeyarray(deskeyarray *dst, deskeyarray *src)
421*7c478bd9Sstevel@tonic-gate {
422*7c478bd9Sstevel@tonic-gate 	deskeyarray *tmp;
423*7c478bd9Sstevel@tonic-gate 
424*7c478bd9Sstevel@tonic-gate 	if ((tmp = cpydeskeyarray(src)) == NULL) {
425*7c478bd9Sstevel@tonic-gate 		return (0);
426*7c478bd9Sstevel@tonic-gate 	}
427*7c478bd9Sstevel@tonic-gate 	*dst = *tmp;
428*7c478bd9Sstevel@tonic-gate 	free(tmp); /* but not the contents */
429*7c478bd9Sstevel@tonic-gate 	debug(KEYSERV_DEBUG0, ("storedeskeyarray ret %d %x",
430*7c478bd9Sstevel@tonic-gate 		dst->deskeyarray_len, dst->deskeyarray_val));
431*7c478bd9Sstevel@tonic-gate 	return (1);
432*7c478bd9Sstevel@tonic-gate }
433*7c478bd9Sstevel@tonic-gate 
434*7c478bd9Sstevel@tonic-gate int
435*7c478bd9Sstevel@tonic-gate setdeskeyarray(deskeyarray *dst, int k)
436*7c478bd9Sstevel@tonic-gate {
437*7c478bd9Sstevel@tonic-gate 	deskeyarray *tmp;
438*7c478bd9Sstevel@tonic-gate 
439*7c478bd9Sstevel@tonic-gate 	if ((tmp = getdeskeyarray(k)) == NULL) {
440*7c478bd9Sstevel@tonic-gate 		return (0);
441*7c478bd9Sstevel@tonic-gate 	}
442*7c478bd9Sstevel@tonic-gate 	*dst = *tmp;
443*7c478bd9Sstevel@tonic-gate 	free(tmp); /* but not the contents */
444*7c478bd9Sstevel@tonic-gate 	debug(KEYSERV_DEBUG0, ("setdeskeyarray ret %d %x",
445*7c478bd9Sstevel@tonic-gate 		dst->deskeyarray_len, dst->deskeyarray_val));
446*7c478bd9Sstevel@tonic-gate 	return (1);
447*7c478bd9Sstevel@tonic-gate }
448*7c478bd9Sstevel@tonic-gate 
449*7c478bd9Sstevel@tonic-gate static int
450*7c478bd9Sstevel@tonic-gate cachehit3(keybuf3 *public, keybuf3 *secret, struct cachekey3_list *cp)
451*7c478bd9Sstevel@tonic-gate {
452*7c478bd9Sstevel@tonic-gate 	return (cmpkeybuf3(public, cp->public) &&
453*7c478bd9Sstevel@tonic-gate 		cmpkeybuf3(secret, cp->secret));
454*7c478bd9Sstevel@tonic-gate }
455*7c478bd9Sstevel@tonic-gate 
456*7c478bd9Sstevel@tonic-gate static struct cacheuid_list **
457*7c478bd9Sstevel@tonic-gate mapuid2cache(uid_t uid, struct mechdata *mdp)
458*7c478bd9Sstevel@tonic-gate {
459*7c478bd9Sstevel@tonic-gate 	struct cacheuid_list **cpp;
460*7c478bd9Sstevel@tonic-gate 	int hash = HASH_UID(uid);
461*7c478bd9Sstevel@tonic-gate 
462*7c478bd9Sstevel@tonic-gate 	debug(KEYSERV_DEBUG, ("mapuid2cache %d %d %x", uid, hash, mdp));
463*7c478bd9Sstevel@tonic-gate 	for (cpp = &mdp->bucket[hash];
464*7c478bd9Sstevel@tonic-gate 		*cpp != NULL && (*cpp)->uid != uid;
465*7c478bd9Sstevel@tonic-gate 		cpp = &(*cpp)->next) {
466*7c478bd9Sstevel@tonic-gate 		debug(KEYSERV_DEBUG0, ("mapuid2cache %x", cpp));
467*7c478bd9Sstevel@tonic-gate 	}
468*7c478bd9Sstevel@tonic-gate 	debug(KEYSERV_DEBUG, ("mapuid2cache ret %x", cpp));
469*7c478bd9Sstevel@tonic-gate 	return (cpp);
470*7c478bd9Sstevel@tonic-gate }
471*7c478bd9Sstevel@tonic-gate 
472*7c478bd9Sstevel@tonic-gate static int
473*7c478bd9Sstevel@tonic-gate appendsecretkey3(struct mechentry *mp, uid_t uid, setkeyarg3 *skey)
474*7c478bd9Sstevel@tonic-gate {
475*7c478bd9Sstevel@tonic-gate 	struct mechdata *mdp;
476*7c478bd9Sstevel@tonic-gate 	struct cacheuid_list **cpp, *cp;
477*7c478bd9Sstevel@tonic-gate 	keybuf3 nullkey = {0, NULL};
478*7c478bd9Sstevel@tonic-gate 
479*7c478bd9Sstevel@tonic-gate 	debug(KEYSERV_DEBUG, ("appendsecretkey3 %x", mp));
480*7c478bd9Sstevel@tonic-gate 	if ((skey == NULL) || (mp == NULL)) {
481*7c478bd9Sstevel@tonic-gate 		return (0);
482*7c478bd9Sstevel@tonic-gate 	}
483*7c478bd9Sstevel@tonic-gate 	if (skey->key.keybuf3_len == 0) {
484*7c478bd9Sstevel@tonic-gate 		return (0);
485*7c478bd9Sstevel@tonic-gate 	}
486*7c478bd9Sstevel@tonic-gate 	mutex_lock(&mp->mech_lock);
487*7c478bd9Sstevel@tonic-gate 	if ((mdp = mp->mechdata) == NULL) {
488*7c478bd9Sstevel@tonic-gate 		mdp = (struct mechdata *)calloc(1, sizeof (*mdp));
489*7c478bd9Sstevel@tonic-gate 		if (mdp == NULL) {
490*7c478bd9Sstevel@tonic-gate 			mutex_unlock(&mp->mech_lock);
491*7c478bd9Sstevel@tonic-gate 			debug(KEYSERV_INFO,
492*7c478bd9Sstevel@tonic-gate 				("appendsecretkey3 : calloc failed"));
493*7c478bd9Sstevel@tonic-gate 			return (0);
494*7c478bd9Sstevel@tonic-gate 		}
495*7c478bd9Sstevel@tonic-gate 		mp->mechdata = mdp;
496*7c478bd9Sstevel@tonic-gate 	}
497*7c478bd9Sstevel@tonic-gate 	cpp = mapuid2cache(uid, mdp);
498*7c478bd9Sstevel@tonic-gate 	if (*cpp == NULL) {
499*7c478bd9Sstevel@tonic-gate 		cp = (struct cacheuid_list *)malloc(sizeof (*cp));
500*7c478bd9Sstevel@tonic-gate 		if (cp == NULL) {
501*7c478bd9Sstevel@tonic-gate 			mutex_unlock(&mp->mech_lock);
502*7c478bd9Sstevel@tonic-gate 			debug(KEYSERV_INFO,
503*7c478bd9Sstevel@tonic-gate 				("appendsecretkey3 : malloc failed"));
504*7c478bd9Sstevel@tonic-gate 			syslog(LOG_ERR, "file %s line %d: malloc failed",
505*7c478bd9Sstevel@tonic-gate 				__FILE__, __LINE__);
506*7c478bd9Sstevel@tonic-gate 			return (0);
507*7c478bd9Sstevel@tonic-gate 		}
508*7c478bd9Sstevel@tonic-gate 		memset(cp, 0, sizeof (*cp));
509*7c478bd9Sstevel@tonic-gate 		cp->uid = uid;
510*7c478bd9Sstevel@tonic-gate 		*cpp = cp;
511*7c478bd9Sstevel@tonic-gate 	} else {
512*7c478bd9Sstevel@tonic-gate 		cp = *cpp;
513*7c478bd9Sstevel@tonic-gate 	}
514*7c478bd9Sstevel@tonic-gate 	freekeybuf3(cp->secretkey);
515*7c478bd9Sstevel@tonic-gate 	if ((cp->secretkey = cpykeybuf3(&skey->key)) == NULL) {
516*7c478bd9Sstevel@tonic-gate 		mutex_unlock(&mp->mech_lock);
517*7c478bd9Sstevel@tonic-gate 		return (0);
518*7c478bd9Sstevel@tonic-gate 	}
519*7c478bd9Sstevel@tonic-gate 	freekeybuf3(cp->publickey);
520*7c478bd9Sstevel@tonic-gate 	if ((cp->publickey = cpykeybuf3(&nullkey)) == NULL) {
521*7c478bd9Sstevel@tonic-gate 		mutex_unlock(&mp->mech_lock);
522*7c478bd9Sstevel@tonic-gate 		return (0);
523*7c478bd9Sstevel@tonic-gate 	}
524*7c478bd9Sstevel@tonic-gate 	mutex_unlock(&mp->mech_lock);
525*7c478bd9Sstevel@tonic-gate 	return (1);
526*7c478bd9Sstevel@tonic-gate }
527*7c478bd9Sstevel@tonic-gate 
528*7c478bd9Sstevel@tonic-gate /*
529*7c478bd9Sstevel@tonic-gate  * Store the vers 3 secretkey for this uid
530*7c478bd9Sstevel@tonic-gate  */
531*7c478bd9Sstevel@tonic-gate static int
532*7c478bd9Sstevel@tonic-gate storesecretkey3(uid_t uid, setkeyarg3 *skey)
533*7c478bd9Sstevel@tonic-gate {
534*7c478bd9Sstevel@tonic-gate 	struct mechentry *mp;
535*7c478bd9Sstevel@tonic-gate 
536*7c478bd9Sstevel@tonic-gate 	if (skey == NULL) {
537*7c478bd9Sstevel@tonic-gate 		return (0);
538*7c478bd9Sstevel@tonic-gate 	}
539*7c478bd9Sstevel@tonic-gate 	if ((mp = getmechtype(skey->keylen, skey->algtype)) == NULL) {
540*7c478bd9Sstevel@tonic-gate 		return (0);
541*7c478bd9Sstevel@tonic-gate 	}
542*7c478bd9Sstevel@tonic-gate 	return (appendsecretkey3(mp, uid, skey));
543*7c478bd9Sstevel@tonic-gate }
544*7c478bd9Sstevel@tonic-gate 
545*7c478bd9Sstevel@tonic-gate /*
546*7c478bd9Sstevel@tonic-gate  * Set the vers 3 secretkey key for this uid
547*7c478bd9Sstevel@tonic-gate  */
548*7c478bd9Sstevel@tonic-gate keystatus
549*7c478bd9Sstevel@tonic-gate pk_setkey3(uid_t uid, setkeyarg3 *skey)
550*7c478bd9Sstevel@tonic-gate {
551*7c478bd9Sstevel@tonic-gate 	if (!storesecretkey3(uid, skey)) {
552*7c478bd9Sstevel@tonic-gate 		return (KEY_SYSTEMERR);
553*7c478bd9Sstevel@tonic-gate 	}
554*7c478bd9Sstevel@tonic-gate 	return (KEY_SUCCESS);
555*7c478bd9Sstevel@tonic-gate }
556*7c478bd9Sstevel@tonic-gate 
557*7c478bd9Sstevel@tonic-gate /*
558*7c478bd9Sstevel@tonic-gate  * Set the secretkey key for this uid
559*7c478bd9Sstevel@tonic-gate  */
560*7c478bd9Sstevel@tonic-gate keystatus
561*7c478bd9Sstevel@tonic-gate pk_setkey(uid, skey)
562*7c478bd9Sstevel@tonic-gate 	uid_t uid;
563*7c478bd9Sstevel@tonic-gate 	keybuf skey;
564*7c478bd9Sstevel@tonic-gate {
565*7c478bd9Sstevel@tonic-gate 	int storesecretkey(uid_t, keybuf);
566*7c478bd9Sstevel@tonic-gate 
567*7c478bd9Sstevel@tonic-gate 	if (!storesecretkey(uid, skey)) {
568*7c478bd9Sstevel@tonic-gate 		return (KEY_SYSTEMERR);
569*7c478bd9Sstevel@tonic-gate 	}
570*7c478bd9Sstevel@tonic-gate 	return (KEY_SUCCESS);
571*7c478bd9Sstevel@tonic-gate }
572*7c478bd9Sstevel@tonic-gate 
573*7c478bd9Sstevel@tonic-gate int
574*7c478bd9Sstevel@tonic-gate storeotherrootkeys(FILE *fp, char *netname, char *passwd, char *osecret)
575*7c478bd9Sstevel@tonic-gate {
576*7c478bd9Sstevel@tonic-gate 	des_block master;
577*7c478bd9Sstevel@tonic-gate 	struct keylenlist *kp;
578*7c478bd9Sstevel@tonic-gate 	struct algtypelist *ap;
579*7c478bd9Sstevel@tonic-gate 	keybuf3 *secret;
580*7c478bd9Sstevel@tonic-gate 	setkeyarg3 skey;
581*7c478bd9Sstevel@tonic-gate 
582*7c478bd9Sstevel@tonic-gate 	debug(KEYSERV_DEBUG, ("storeotherrootkeys %s %s",
583*7c478bd9Sstevel@tonic-gate 		netname, passwd));
584*7c478bd9Sstevel@tonic-gate 	passwd2des_g(passwd, netname, strlen(netname), &master, FALSE);
585*7c478bd9Sstevel@tonic-gate 	for (kp = mechtable.kp; kp != NULL; kp = kp->next) {
586*7c478bd9Sstevel@tonic-gate 		debug(KEYSERV_DEBUG0,
587*7c478bd9Sstevel@tonic-gate 			("storeotherrootkeys key %d", kp->keylen));
588*7c478bd9Sstevel@tonic-gate 		for (ap = kp->ap; ap != NULL; ap = ap->next) {
589*7c478bd9Sstevel@tonic-gate 			debug(KEYSERV_DEBUG,
590*7c478bd9Sstevel@tonic-gate 				("storeotherrootkeys alg: %d", ap->algtype));
591*7c478bd9Sstevel@tonic-gate 			if ((secret = getkeybuf3(kp->keylen/4+1)) == NULL) {
592*7c478bd9Sstevel@tonic-gate 				return (0);
593*7c478bd9Sstevel@tonic-gate 			}
594*7c478bd9Sstevel@tonic-gate 			debug(KEYSERV_DEBUG,
595*7c478bd9Sstevel@tonic-gate 				("storeotherrootkeys calling getsecretkey_g"));
596*7c478bd9Sstevel@tonic-gate 			if (!getsecretkey_g(netname,
597*7c478bd9Sstevel@tonic-gate 				kp->keylen, ap->algtype,
598*7c478bd9Sstevel@tonic-gate 				secret->keybuf3_val, secret->keybuf3_len,
599*7c478bd9Sstevel@tonic-gate 				passwd)) {
600*7c478bd9Sstevel@tonic-gate 				debug(KEYSERV_INFO,
601*7c478bd9Sstevel@tonic-gate 				("Can't find %s's secret key", netname));
602*7c478bd9Sstevel@tonic-gate 				return (0);
603*7c478bd9Sstevel@tonic-gate 			}
604*7c478bd9Sstevel@tonic-gate 			if (*secret->keybuf3_val == 0) { /* XXX */
605*7c478bd9Sstevel@tonic-gate 				debug(KEYSERV_INFO,
606*7c478bd9Sstevel@tonic-gate 				("Password does not decrypt secret key for %s",
607*7c478bd9Sstevel@tonic-gate 					netname));
608*7c478bd9Sstevel@tonic-gate 				return (0);
609*7c478bd9Sstevel@tonic-gate 			}
610*7c478bd9Sstevel@tonic-gate 			skey.key = *secret;
611*7c478bd9Sstevel@tonic-gate 			free(secret); /* but not the buffer it points to */
612*7c478bd9Sstevel@tonic-gate 			skey.userkey = master;
613*7c478bd9Sstevel@tonic-gate 			skey.keylen = kp->keylen;
614*7c478bd9Sstevel@tonic-gate 			skey.algtype = ap->algtype;
615*7c478bd9Sstevel@tonic-gate 			if (CLASSIC_PK_DH(kp->keylen, ap->algtype)) {
616*7c478bd9Sstevel@tonic-gate 				pk_setkey((uid_t)0, osecret);
617*7c478bd9Sstevel@tonic-gate 				fprintf(fp, "%s\n", osecret);
618*7c478bd9Sstevel@tonic-gate 			}
619*7c478bd9Sstevel@tonic-gate 			if (pk_setkey3(0, &skey) != KEY_SUCCESS) {
620*7c478bd9Sstevel@tonic-gate 				return (0);
621*7c478bd9Sstevel@tonic-gate 			}
622*7c478bd9Sstevel@tonic-gate 			if (!CLASSIC_PK_DH(kp->keylen, ap->algtype)) {
623*7c478bd9Sstevel@tonic-gate 				fprintf(fp, "%s %d\n", skey.key.keybuf3_val,
624*7c478bd9Sstevel@tonic-gate 					ap->algtype);
625*7c478bd9Sstevel@tonic-gate 			}
626*7c478bd9Sstevel@tonic-gate 		}
627*7c478bd9Sstevel@tonic-gate 	}
628*7c478bd9Sstevel@tonic-gate 	return (1);
629*7c478bd9Sstevel@tonic-gate }
630*7c478bd9Sstevel@tonic-gate 
631*7c478bd9Sstevel@tonic-gate /*
632*7c478bd9Sstevel@tonic-gate  * prohibit the nobody key on this machine k (the -d flag)
633*7c478bd9Sstevel@tonic-gate  */
634*7c478bd9Sstevel@tonic-gate pk_nodefaultkeys()
635*7c478bd9Sstevel@tonic-gate {
636*7c478bd9Sstevel@tonic-gate 	nodefaultkeys = 1;
637*7c478bd9Sstevel@tonic-gate 	return (0);
638*7c478bd9Sstevel@tonic-gate }
639*7c478bd9Sstevel@tonic-gate 
640*7c478bd9Sstevel@tonic-gate static void
641*7c478bd9Sstevel@tonic-gate freedisklist(struct cacheuid_list *cp)
642*7c478bd9Sstevel@tonic-gate {
643*7c478bd9Sstevel@tonic-gate 	if (cp == NULL) {
644*7c478bd9Sstevel@tonic-gate 		return;
645*7c478bd9Sstevel@tonic-gate 	}
646*7c478bd9Sstevel@tonic-gate 	free(cp->netname); /* ok even if this is NULL */
647*7c478bd9Sstevel@tonic-gate 	freekeybuf3(cp->secretkey);
648*7c478bd9Sstevel@tonic-gate 	freekeybuf3(cp->publickey);
649*7c478bd9Sstevel@tonic-gate }
650*7c478bd9Sstevel@tonic-gate 
651*7c478bd9Sstevel@tonic-gate keystatus
652*7c478bd9Sstevel@tonic-gate pk_clear3(uid_t uid)
653*7c478bd9Sstevel@tonic-gate {
654*7c478bd9Sstevel@tonic-gate 	struct keylenlist *kp;
655*7c478bd9Sstevel@tonic-gate 	struct algtypelist *ap;
656*7c478bd9Sstevel@tonic-gate 	struct mechdata *mdp;
657*7c478bd9Sstevel@tonic-gate 	struct cacheuid_list **cpp, *cp;
658*7c478bd9Sstevel@tonic-gate 
659*7c478bd9Sstevel@tonic-gate 	debug(KEYSERV_DEBUG, ("pk_clear3 %d", uid));
660*7c478bd9Sstevel@tonic-gate 	for (kp = mechtable.kp; kp != NULL; kp = kp->next) {
661*7c478bd9Sstevel@tonic-gate 		debug(KEYSERV_DEBUG0, ("pk_clear3 key %d", kp->keylen));
662*7c478bd9Sstevel@tonic-gate 		for (ap = kp->ap; ap != NULL; ap = ap->next) {
663*7c478bd9Sstevel@tonic-gate 			debug(KEYSERV_DEBUG0,
664*7c478bd9Sstevel@tonic-gate 				("pk_clear3 alg: %d", ap->algtype));
665*7c478bd9Sstevel@tonic-gate 			mutex_lock(&ap->mech.mech_lock);
666*7c478bd9Sstevel@tonic-gate 			if ((mdp = ap->mech.mechdata) == NULL) {
667*7c478bd9Sstevel@tonic-gate 				mutex_unlock(&ap->mech.mech_lock);
668*7c478bd9Sstevel@tonic-gate 				continue;
669*7c478bd9Sstevel@tonic-gate 			}
670*7c478bd9Sstevel@tonic-gate 			cpp = mapuid2cache(uid, mdp);
671*7c478bd9Sstevel@tonic-gate 			if (*cpp == NULL) {
672*7c478bd9Sstevel@tonic-gate 				mutex_unlock(&ap->mech.mech_lock);
673*7c478bd9Sstevel@tonic-gate 				continue;
674*7c478bd9Sstevel@tonic-gate 			}
675*7c478bd9Sstevel@tonic-gate 			cp = (*cpp)->next;
676*7c478bd9Sstevel@tonic-gate 			freedisklist(*cpp);
677*7c478bd9Sstevel@tonic-gate 			*cpp = cp;
678*7c478bd9Sstevel@tonic-gate 			mutex_unlock(&ap->mech.mech_lock);
679*7c478bd9Sstevel@tonic-gate 		}
680*7c478bd9Sstevel@tonic-gate 	}
681*7c478bd9Sstevel@tonic-gate 	/* XXX clear stuff out of the common key cache as well? */
682*7c478bd9Sstevel@tonic-gate 	/* XXX return success only if something was removed? */
683*7c478bd9Sstevel@tonic-gate 	return (KEY_SUCCESS);
684*7c478bd9Sstevel@tonic-gate }
685*7c478bd9Sstevel@tonic-gate 
686*7c478bd9Sstevel@tonic-gate /*
687*7c478bd9Sstevel@tonic-gate  * Set the modulus for all our Diffie-Hellman operations
688*7c478bd9Sstevel@tonic-gate  */
689*7c478bd9Sstevel@tonic-gate setmodulus(modx)
690*7c478bd9Sstevel@tonic-gate 	char *modx;
691*7c478bd9Sstevel@tonic-gate {
692*7c478bd9Sstevel@tonic-gate 	MODULUS = mp_xtom(modx);
693*7c478bd9Sstevel@tonic-gate 	return (0);
694*7c478bd9Sstevel@tonic-gate }
695*7c478bd9Sstevel@tonic-gate 
696*7c478bd9Sstevel@tonic-gate /*
697*7c478bd9Sstevel@tonic-gate  * Encrypt the key using the public key associated with remote_name and the
698*7c478bd9Sstevel@tonic-gate  * secret key associated with uid.
699*7c478bd9Sstevel@tonic-gate  */
700*7c478bd9Sstevel@tonic-gate keystatus
701*7c478bd9Sstevel@tonic-gate pk_encrypt(uid, remote_name, remote_key, key)
702*7c478bd9Sstevel@tonic-gate 	uid_t uid;
703*7c478bd9Sstevel@tonic-gate 	char *remote_name;
704*7c478bd9Sstevel@tonic-gate 	netobj	*remote_key;
705*7c478bd9Sstevel@tonic-gate 	des_block *key;
706*7c478bd9Sstevel@tonic-gate {
707*7c478bd9Sstevel@tonic-gate 	return (pk_crypt(uid, remote_name, remote_key, key, DES_ENCRYPT));
708*7c478bd9Sstevel@tonic-gate }
709*7c478bd9Sstevel@tonic-gate 
710*7c478bd9Sstevel@tonic-gate /*
711*7c478bd9Sstevel@tonic-gate  * Encrypt the key using the public key associated with remote_name and the
712*7c478bd9Sstevel@tonic-gate  * secret key associated with uid using vers 3
713*7c478bd9Sstevel@tonic-gate  */
714*7c478bd9Sstevel@tonic-gate keystatus
715*7c478bd9Sstevel@tonic-gate pk_encrypt3(
716*7c478bd9Sstevel@tonic-gate 	uid_t uid,
717*7c478bd9Sstevel@tonic-gate 	cryptkeyarg3 *arg,
718*7c478bd9Sstevel@tonic-gate 	deskeyarray *key
719*7c478bd9Sstevel@tonic-gate )
720*7c478bd9Sstevel@tonic-gate {
721*7c478bd9Sstevel@tonic-gate 	return (pk_crypt3(uid, arg, key, DES_ENCRYPT));
722*7c478bd9Sstevel@tonic-gate }
723*7c478bd9Sstevel@tonic-gate 
724*7c478bd9Sstevel@tonic-gate /*
725*7c478bd9Sstevel@tonic-gate  * Decrypt the key using the public key associated with remote_name and the
726*7c478bd9Sstevel@tonic-gate  * secret key associated with uid.
727*7c478bd9Sstevel@tonic-gate  */
728*7c478bd9Sstevel@tonic-gate keystatus
729*7c478bd9Sstevel@tonic-gate pk_decrypt(uid, remote_name, remote_key, key)
730*7c478bd9Sstevel@tonic-gate 	uid_t uid;
731*7c478bd9Sstevel@tonic-gate 	char *remote_name;
732*7c478bd9Sstevel@tonic-gate 	netobj *remote_key;
733*7c478bd9Sstevel@tonic-gate 	des_block *key;
734*7c478bd9Sstevel@tonic-gate {
735*7c478bd9Sstevel@tonic-gate 	return (pk_crypt(uid, remote_name, remote_key, key, DES_DECRYPT));
736*7c478bd9Sstevel@tonic-gate }
737*7c478bd9Sstevel@tonic-gate 
738*7c478bd9Sstevel@tonic-gate /*
739*7c478bd9Sstevel@tonic-gate  * Decrypt the key using the public key associated with remote_name and the
740*7c478bd9Sstevel@tonic-gate  * secret key associated with uid using vers 3
741*7c478bd9Sstevel@tonic-gate  */
742*7c478bd9Sstevel@tonic-gate keystatus
743*7c478bd9Sstevel@tonic-gate pk_decrypt3(
744*7c478bd9Sstevel@tonic-gate 	uid_t uid,
745*7c478bd9Sstevel@tonic-gate 	cryptkeyarg3 *arg,
746*7c478bd9Sstevel@tonic-gate 	deskeyarray *key
747*7c478bd9Sstevel@tonic-gate )
748*7c478bd9Sstevel@tonic-gate {
749*7c478bd9Sstevel@tonic-gate 	return (pk_crypt3(uid, arg, key, DES_DECRYPT));
750*7c478bd9Sstevel@tonic-gate }
751*7c478bd9Sstevel@tonic-gate 
752*7c478bd9Sstevel@tonic-gate /*
753*7c478bd9Sstevel@tonic-gate  * Key storage management
754*7c478bd9Sstevel@tonic-gate  */
755*7c478bd9Sstevel@tonic-gate 
756*7c478bd9Sstevel@tonic-gate #define	KEY_ONLY 0
757*7c478bd9Sstevel@tonic-gate #define	KEY_NAME 1
758*7c478bd9Sstevel@tonic-gate struct secretkey_netname_list {
759*7c478bd9Sstevel@tonic-gate 	uid_t uid;
760*7c478bd9Sstevel@tonic-gate 	key_netstarg keynetdata;
761*7c478bd9Sstevel@tonic-gate 	uchar_t sc_flag;
762*7c478bd9Sstevel@tonic-gate 	struct secretkey_netname_list *next;
763*7c478bd9Sstevel@tonic-gate };
764*7c478bd9Sstevel@tonic-gate 
765*7c478bd9Sstevel@tonic-gate #define	HASH_UID(x)	(x & 0xff)
766*7c478bd9Sstevel@tonic-gate static struct secretkey_netname_list *g_secretkey_netname[KEY_HASH_SIZE];
767*7c478bd9Sstevel@tonic-gate static rwlock_t g_secretkey_netname_lock = DEFAULTRWLOCK;
768*7c478bd9Sstevel@tonic-gate 
769*7c478bd9Sstevel@tonic-gate /*
770*7c478bd9Sstevel@tonic-gate  * Store the keys and netname for this uid
771*7c478bd9Sstevel@tonic-gate  */
772*7c478bd9Sstevel@tonic-gate static int
773*7c478bd9Sstevel@tonic-gate store_netname(uid, netstore)
774*7c478bd9Sstevel@tonic-gate 	uid_t uid;
775*7c478bd9Sstevel@tonic-gate 	key_netstarg *netstore;
776*7c478bd9Sstevel@tonic-gate {
777*7c478bd9Sstevel@tonic-gate 	struct secretkey_netname_list *new;
778*7c478bd9Sstevel@tonic-gate 	struct secretkey_netname_list **l;
779*7c478bd9Sstevel@tonic-gate 	int hash = HASH_UID(uid);
780*7c478bd9Sstevel@tonic-gate 
781*7c478bd9Sstevel@tonic-gate 	(void) rw_wrlock(&g_secretkey_netname_lock);
782*7c478bd9Sstevel@tonic-gate 	for (l = &g_secretkey_netname[hash]; *l != NULL && (*l)->uid != uid;
783*7c478bd9Sstevel@tonic-gate 			l = &(*l)->next) {
784*7c478bd9Sstevel@tonic-gate 	}
785*7c478bd9Sstevel@tonic-gate 	if (*l == NULL) {
786*7c478bd9Sstevel@tonic-gate /* LINTED pointer alignment */
787*7c478bd9Sstevel@tonic-gate 		new = (struct secretkey_netname_list *)malloc(sizeof (*new));
788*7c478bd9Sstevel@tonic-gate 		if (new == NULL) {
789*7c478bd9Sstevel@tonic-gate 			(void) rw_unlock(&g_secretkey_netname_lock);
790*7c478bd9Sstevel@tonic-gate 			return (0);
791*7c478bd9Sstevel@tonic-gate 		}
792*7c478bd9Sstevel@tonic-gate 		new->uid = uid;
793*7c478bd9Sstevel@tonic-gate 		new->next = NULL;
794*7c478bd9Sstevel@tonic-gate 		*l = new;
795*7c478bd9Sstevel@tonic-gate 	} else {
796*7c478bd9Sstevel@tonic-gate 		new = *l;
797*7c478bd9Sstevel@tonic-gate 		if (new->keynetdata.st_netname)
798*7c478bd9Sstevel@tonic-gate 			(void) free(new->keynetdata.st_netname);
799*7c478bd9Sstevel@tonic-gate 	}
800*7c478bd9Sstevel@tonic-gate 	memcpy(new->keynetdata.st_priv_key, netstore->st_priv_key,
801*7c478bd9Sstevel@tonic-gate 		HEXKEYBYTES);
802*7c478bd9Sstevel@tonic-gate 	memcpy(new->keynetdata.st_pub_key, netstore->st_pub_key, HEXKEYBYTES);
803*7c478bd9Sstevel@tonic-gate 
804*7c478bd9Sstevel@tonic-gate 	if (netstore->st_netname)
805*7c478bd9Sstevel@tonic-gate 		new->keynetdata.st_netname = strdup(netstore->st_netname);
806*7c478bd9Sstevel@tonic-gate 	else
807*7c478bd9Sstevel@tonic-gate 		new->keynetdata.st_netname = (char *)NULL;
808*7c478bd9Sstevel@tonic-gate 	new->sc_flag = KEY_NAME;
809*7c478bd9Sstevel@tonic-gate 	(void) rw_unlock(&g_secretkey_netname_lock);
810*7c478bd9Sstevel@tonic-gate 	return (1);
811*7c478bd9Sstevel@tonic-gate 
812*7c478bd9Sstevel@tonic-gate }
813*7c478bd9Sstevel@tonic-gate 
814*7c478bd9Sstevel@tonic-gate static int
815*7c478bd9Sstevel@tonic-gate appendnetname3(struct mechentry *mp, uid_t uid, key_netstarg3 *net)
816*7c478bd9Sstevel@tonic-gate {
817*7c478bd9Sstevel@tonic-gate 	struct mechdata *mdp;
818*7c478bd9Sstevel@tonic-gate 	struct cacheuid_list **cpp, *cp;
819*7c478bd9Sstevel@tonic-gate 
820*7c478bd9Sstevel@tonic-gate 	debug(KEYSERV_DEBUG, ("appendnetname3 %x", mp));
821*7c478bd9Sstevel@tonic-gate 	if ((mp == NULL) || (net == NULL)) {
822*7c478bd9Sstevel@tonic-gate 		return (0);
823*7c478bd9Sstevel@tonic-gate 	}
824*7c478bd9Sstevel@tonic-gate 	mutex_lock(&mp->mech_lock);
825*7c478bd9Sstevel@tonic-gate 	if ((mdp = mp->mechdata) == NULL) {
826*7c478bd9Sstevel@tonic-gate 		mdp = (struct mechdata *)calloc(1, sizeof (*mdp));
827*7c478bd9Sstevel@tonic-gate 		if (mdp == NULL) {
828*7c478bd9Sstevel@tonic-gate 			mutex_unlock(&mp->mech_lock);
829*7c478bd9Sstevel@tonic-gate 			debug(KEYSERV_INFO, ("appendnetname3 : calloc failed"));
830*7c478bd9Sstevel@tonic-gate 			return (0);
831*7c478bd9Sstevel@tonic-gate 		}
832*7c478bd9Sstevel@tonic-gate 		mp->mechdata = mdp;
833*7c478bd9Sstevel@tonic-gate 	}
834*7c478bd9Sstevel@tonic-gate 	cpp = mapuid2cache(uid, mdp);
835*7c478bd9Sstevel@tonic-gate 	if (*cpp == NULL) {
836*7c478bd9Sstevel@tonic-gate 		cp = (struct cacheuid_list *)malloc(sizeof (*cp));
837*7c478bd9Sstevel@tonic-gate 		if (cp == NULL) {
838*7c478bd9Sstevel@tonic-gate 			mutex_unlock(&mp->mech_lock);
839*7c478bd9Sstevel@tonic-gate 			debug(KEYSERV_INFO, ("appendnetname3 : malloc failed"));
840*7c478bd9Sstevel@tonic-gate 			syslog(LOG_ERR, "file %s line %d: malloc failed",
841*7c478bd9Sstevel@tonic-gate 				__FILE__, __LINE__);
842*7c478bd9Sstevel@tonic-gate 			return (0);
843*7c478bd9Sstevel@tonic-gate 		}
844*7c478bd9Sstevel@tonic-gate 		memset(cp, 0, sizeof (*cp));
845*7c478bd9Sstevel@tonic-gate 		cp->uid = uid;
846*7c478bd9Sstevel@tonic-gate 		*cpp = cp;
847*7c478bd9Sstevel@tonic-gate 	} else {
848*7c478bd9Sstevel@tonic-gate 		cp = *cpp;
849*7c478bd9Sstevel@tonic-gate 	}
850*7c478bd9Sstevel@tonic-gate 	freekeybuf3(cp->secretkey);
851*7c478bd9Sstevel@tonic-gate 	if ((cp->secretkey = cpykeybuf3(&net->st_priv_key)) == NULL) {
852*7c478bd9Sstevel@tonic-gate 		mutex_unlock(&mp->mech_lock);
853*7c478bd9Sstevel@tonic-gate 		return (0);
854*7c478bd9Sstevel@tonic-gate 	}
855*7c478bd9Sstevel@tonic-gate 	freekeybuf3(cp->publickey);
856*7c478bd9Sstevel@tonic-gate 	if ((cp->publickey = cpykeybuf3(&net->st_pub_key)) == NULL) {
857*7c478bd9Sstevel@tonic-gate 		mutex_unlock(&mp->mech_lock);
858*7c478bd9Sstevel@tonic-gate 		return (0);
859*7c478bd9Sstevel@tonic-gate 	}
860*7c478bd9Sstevel@tonic-gate 	free(cp->netname);
861*7c478bd9Sstevel@tonic-gate 	if (net->st_netname) {
862*7c478bd9Sstevel@tonic-gate 		cp->netname = strdup(net->st_netname);
863*7c478bd9Sstevel@tonic-gate 	} else {
864*7c478bd9Sstevel@tonic-gate 		cp->netname = (char *)NULL;
865*7c478bd9Sstevel@tonic-gate 	}
866*7c478bd9Sstevel@tonic-gate 	mutex_unlock(&mp->mech_lock);
867*7c478bd9Sstevel@tonic-gate 	return (1);
868*7c478bd9Sstevel@tonic-gate }
869*7c478bd9Sstevel@tonic-gate 
870*7c478bd9Sstevel@tonic-gate keystatus
871*7c478bd9Sstevel@tonic-gate pk_netput(uid, netstore)
872*7c478bd9Sstevel@tonic-gate 	uid_t uid;
873*7c478bd9Sstevel@tonic-gate 	key_netstarg *netstore;
874*7c478bd9Sstevel@tonic-gate {
875*7c478bd9Sstevel@tonic-gate 
876*7c478bd9Sstevel@tonic-gate 	if (!store_netname(uid, netstore)) {
877*7c478bd9Sstevel@tonic-gate 		return (KEY_SYSTEMERR);
878*7c478bd9Sstevel@tonic-gate 	}
879*7c478bd9Sstevel@tonic-gate 	return (KEY_SUCCESS);
880*7c478bd9Sstevel@tonic-gate }
881*7c478bd9Sstevel@tonic-gate 
882*7c478bd9Sstevel@tonic-gate /*
883*7c478bd9Sstevel@tonic-gate  * Store the keys and netname for this uid vers 3
884*7c478bd9Sstevel@tonic-gate  */
885*7c478bd9Sstevel@tonic-gate static int
886*7c478bd9Sstevel@tonic-gate store_netname3(uid_t uid, key_netstarg3 *net)
887*7c478bd9Sstevel@tonic-gate {
888*7c478bd9Sstevel@tonic-gate 	struct mechentry *mp;
889*7c478bd9Sstevel@tonic-gate 	key_netstarg netstore;
890*7c478bd9Sstevel@tonic-gate 
891*7c478bd9Sstevel@tonic-gate 	if (net == NULL) {
892*7c478bd9Sstevel@tonic-gate 		return (0);
893*7c478bd9Sstevel@tonic-gate 	}
894*7c478bd9Sstevel@tonic-gate 	if ((mp = getmechtype(net->keylen, net->algtype)) == NULL) {
895*7c478bd9Sstevel@tonic-gate 		return (0);
896*7c478bd9Sstevel@tonic-gate 	}
897*7c478bd9Sstevel@tonic-gate 	if (uid == 0 && CLASSIC_PK_DH(net->keylen, net->algtype)) {
898*7c478bd9Sstevel@tonic-gate 		memcpy(netstore.st_priv_key, net->st_priv_key.keybuf3_val,
899*7c478bd9Sstevel@tonic-gate 			HEXKEYBYTES);
900*7c478bd9Sstevel@tonic-gate 		memset(netstore.st_pub_key, 0, HEXKEYBYTES);
901*7c478bd9Sstevel@tonic-gate 		netstore.st_netname = net->st_netname;
902*7c478bd9Sstevel@tonic-gate 		if (pk_netput(uid, &netstore) != KEY_SUCCESS) {
903*7c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr,
904*7c478bd9Sstevel@tonic-gate 			"keyserv: could not set root's key and netname.\n");
905*7c478bd9Sstevel@tonic-gate 			return (0);
906*7c478bd9Sstevel@tonic-gate 		}
907*7c478bd9Sstevel@tonic-gate 	}
908*7c478bd9Sstevel@tonic-gate 	return (appendnetname3(mp, uid, net));
909*7c478bd9Sstevel@tonic-gate }
910*7c478bd9Sstevel@tonic-gate 
911*7c478bd9Sstevel@tonic-gate keystatus
912*7c478bd9Sstevel@tonic-gate pk_netput3(uid_t uid, key_netstarg3 *netstore)
913*7c478bd9Sstevel@tonic-gate {
914*7c478bd9Sstevel@tonic-gate 
915*7c478bd9Sstevel@tonic-gate 	if (!store_netname3(uid, netstore)) {
916*7c478bd9Sstevel@tonic-gate 		return (KEY_SYSTEMERR);
917*7c478bd9Sstevel@tonic-gate 	}
918*7c478bd9Sstevel@tonic-gate 	return (KEY_SUCCESS);
919*7c478bd9Sstevel@tonic-gate }
920*7c478bd9Sstevel@tonic-gate 
921*7c478bd9Sstevel@tonic-gate int
922*7c478bd9Sstevel@tonic-gate addmasterkey(char *master, char *netname, algtype_t algtype)
923*7c478bd9Sstevel@tonic-gate {
924*7c478bd9Sstevel@tonic-gate 	keybuf3 *secret, *public;
925*7c478bd9Sstevel@tonic-gate 	int bytelen = strlen(master);
926*7c478bd9Sstevel@tonic-gate 	keylen_t keylen = bytelen*4;
927*7c478bd9Sstevel@tonic-gate 	key_netstarg3 tmp;
928*7c478bd9Sstevel@tonic-gate 
929*7c478bd9Sstevel@tonic-gate 	if ((secret = setkeybuf3(master, bytelen)) == NULL) {
930*7c478bd9Sstevel@tonic-gate 		return (0);
931*7c478bd9Sstevel@tonic-gate 	}
932*7c478bd9Sstevel@tonic-gate 	if ((public = getkeybuf3(bytelen+1)) == NULL) {
933*7c478bd9Sstevel@tonic-gate 		/* the +1 is mandated by getpublickey_g() */
934*7c478bd9Sstevel@tonic-gate 		return (0);
935*7c478bd9Sstevel@tonic-gate 	}
936*7c478bd9Sstevel@tonic-gate 	/*
937*7c478bd9Sstevel@tonic-gate 	 * getpublickey_g(netname, keylen, algtype,
938*7c478bd9Sstevel@tonic-gate 	 *  public->keybuf3_val, public->keybuf3_len);
939*7c478bd9Sstevel@tonic-gate 	 * cannot be called since rpc.nisd is not up yet
940*7c478bd9Sstevel@tonic-gate 	 * so we continue to return a zero filled public key
941*7c478bd9Sstevel@tonic-gate 	 * as in the earlier version
942*7c478bd9Sstevel@tonic-gate 	 */
943*7c478bd9Sstevel@tonic-gate 	memset(public->keybuf3_val, 0, bytelen+1);
944*7c478bd9Sstevel@tonic-gate 	tmp.st_priv_key = *secret;
945*7c478bd9Sstevel@tonic-gate 	free(secret);
946*7c478bd9Sstevel@tonic-gate 	tmp.st_pub_key = *public;
947*7c478bd9Sstevel@tonic-gate 	free(public);
948*7c478bd9Sstevel@tonic-gate 	tmp.st_netname = strdup(netname);
949*7c478bd9Sstevel@tonic-gate 	tmp.keylen = keylen;
950*7c478bd9Sstevel@tonic-gate 	tmp.algtype = algtype;
951*7c478bd9Sstevel@tonic-gate 	return (store_netname3(0, &tmp));
952*7c478bd9Sstevel@tonic-gate }
953*7c478bd9Sstevel@tonic-gate 
954*7c478bd9Sstevel@tonic-gate /*
955*7c478bd9Sstevel@tonic-gate  * Fetch the keys and netname for this uid
956*7c478bd9Sstevel@tonic-gate  */
957*7c478bd9Sstevel@tonic-gate static int
958*7c478bd9Sstevel@tonic-gate fetch_netname(uid, key_netst)
959*7c478bd9Sstevel@tonic-gate 	uid_t uid;
960*7c478bd9Sstevel@tonic-gate 	struct key_netstarg *key_netst;
961*7c478bd9Sstevel@tonic-gate {
962*7c478bd9Sstevel@tonic-gate 	struct secretkey_netname_list *l;
963*7c478bd9Sstevel@tonic-gate 	int hash = HASH_UID(uid);
964*7c478bd9Sstevel@tonic-gate 
965*7c478bd9Sstevel@tonic-gate 	(void) rw_rdlock(&g_secretkey_netname_lock);
966*7c478bd9Sstevel@tonic-gate 	for (l = g_secretkey_netname[hash]; l != NULL; l = l->next) {
967*7c478bd9Sstevel@tonic-gate 		if ((l->uid == uid) && (l->sc_flag == KEY_NAME)) {
968*7c478bd9Sstevel@tonic-gate 
969*7c478bd9Sstevel@tonic-gate 			memcpy(key_netst->st_priv_key,
970*7c478bd9Sstevel@tonic-gate 				l->keynetdata.st_priv_key, HEXKEYBYTES);
971*7c478bd9Sstevel@tonic-gate 
972*7c478bd9Sstevel@tonic-gate 			memcpy(key_netst->st_pub_key,
973*7c478bd9Sstevel@tonic-gate 				l->keynetdata.st_pub_key, HEXKEYBYTES);
974*7c478bd9Sstevel@tonic-gate 
975*7c478bd9Sstevel@tonic-gate 			if (l->keynetdata.st_netname)
976*7c478bd9Sstevel@tonic-gate 				strcpy(key_netst->st_netname,
977*7c478bd9Sstevel@tonic-gate 						l->keynetdata.st_netname);
978*7c478bd9Sstevel@tonic-gate 			else
979*7c478bd9Sstevel@tonic-gate 				key_netst->st_netname = NULL;
980*7c478bd9Sstevel@tonic-gate 			(void) rw_unlock(&g_secretkey_netname_lock);
981*7c478bd9Sstevel@tonic-gate 			return (1);
982*7c478bd9Sstevel@tonic-gate 		}
983*7c478bd9Sstevel@tonic-gate 	}
984*7c478bd9Sstevel@tonic-gate 	(void) rw_unlock(&g_secretkey_netname_lock);
985*7c478bd9Sstevel@tonic-gate 	return (0);
986*7c478bd9Sstevel@tonic-gate }
987*7c478bd9Sstevel@tonic-gate 
988*7c478bd9Sstevel@tonic-gate static void
989*7c478bd9Sstevel@tonic-gate remove_ref(struct cacheuid_list *cp)
990*7c478bd9Sstevel@tonic-gate {
991*7c478bd9Sstevel@tonic-gate 	debug(KEYSERV_DEBUG0, ("remove_ref %x", cp));
992*7c478bd9Sstevel@tonic-gate 	/*
993*7c478bd9Sstevel@tonic-gate 	 * XXX
994*7c478bd9Sstevel@tonic-gate 	 * if we are going to do this along the lines of vn_rele,
995*7c478bd9Sstevel@tonic-gate 	 * more stuff needs to be done here and the access to refcnt
996*7c478bd9Sstevel@tonic-gate 	 * needs to be mutex locked. Keep it simple for now.
997*7c478bd9Sstevel@tonic-gate 	 */
998*7c478bd9Sstevel@tonic-gate 	cp->refcnt--;
999*7c478bd9Sstevel@tonic-gate }
1000*7c478bd9Sstevel@tonic-gate 
1001*7c478bd9Sstevel@tonic-gate static void
1002*7c478bd9Sstevel@tonic-gate add_ref(struct cacheuid_list **cpp)
1003*7c478bd9Sstevel@tonic-gate {
1004*7c478bd9Sstevel@tonic-gate 	struct cacheuid_list *cp;
1005*7c478bd9Sstevel@tonic-gate 
1006*7c478bd9Sstevel@tonic-gate 	if (cpp == NULL) {
1007*7c478bd9Sstevel@tonic-gate 		return;
1008*7c478bd9Sstevel@tonic-gate 	}
1009*7c478bd9Sstevel@tonic-gate 	/*LINTED assignment operator "=" found where "==" was expected*/
1010*7c478bd9Sstevel@tonic-gate 	if (cp = *cpp) {
1011*7c478bd9Sstevel@tonic-gate 		debug(KEYSERV_DEBUG0, ("add_ref %x", cp));
1012*7c478bd9Sstevel@tonic-gate 		cp->refcnt++;
1013*7c478bd9Sstevel@tonic-gate 	}
1014*7c478bd9Sstevel@tonic-gate }
1015*7c478bd9Sstevel@tonic-gate 
1016*7c478bd9Sstevel@tonic-gate static struct cacheuid_list *
1017*7c478bd9Sstevel@tonic-gate getcachekey3(uid_t uid, struct mechentry *mp)
1018*7c478bd9Sstevel@tonic-gate {
1019*7c478bd9Sstevel@tonic-gate 	struct cacheuid_list **cpp, *cp;
1020*7c478bd9Sstevel@tonic-gate 	struct mechdata *mdp;
1021*7c478bd9Sstevel@tonic-gate 
1022*7c478bd9Sstevel@tonic-gate 	debug(KEYSERV_DEBUG1, ("getcachekey3 %d %x", uid, mp));
1023*7c478bd9Sstevel@tonic-gate 	if (mp == NULL) {
1024*7c478bd9Sstevel@tonic-gate 		return (0);
1025*7c478bd9Sstevel@tonic-gate 	}
1026*7c478bd9Sstevel@tonic-gate 	mutex_lock(&mp->mech_lock);
1027*7c478bd9Sstevel@tonic-gate 	if ((mdp = mp->mechdata) == NULL) {
1028*7c478bd9Sstevel@tonic-gate 		mutex_unlock(&mp->mech_lock);
1029*7c478bd9Sstevel@tonic-gate 		debug(KEYSERV_DEBUG0, ("getcachekey3 ret 0"));
1030*7c478bd9Sstevel@tonic-gate 		return (0);
1031*7c478bd9Sstevel@tonic-gate 	}
1032*7c478bd9Sstevel@tonic-gate 	cpp = mapuid2cache(uid, mdp);
1033*7c478bd9Sstevel@tonic-gate 	cp = *cpp;
1034*7c478bd9Sstevel@tonic-gate 	add_ref(cpp);
1035*7c478bd9Sstevel@tonic-gate 	mutex_unlock(&mp->mech_lock);
1036*7c478bd9Sstevel@tonic-gate 	debug(KEYSERV_DEBUG0, ("getcachekey3 ret %x", *cpp));
1037*7c478bd9Sstevel@tonic-gate 	return (cp);
1038*7c478bd9Sstevel@tonic-gate }
1039*7c478bd9Sstevel@tonic-gate 
1040*7c478bd9Sstevel@tonic-gate /*
1041*7c478bd9Sstevel@tonic-gate  * Fetch any available cache for this uid (vers 3)
1042*7c478bd9Sstevel@tonic-gate  */
1043*7c478bd9Sstevel@tonic-gate static struct cacheuid_list *
1044*7c478bd9Sstevel@tonic-gate getanycache3(uid_t uid)
1045*7c478bd9Sstevel@tonic-gate {
1046*7c478bd9Sstevel@tonic-gate 	struct keylenlist *kp;
1047*7c478bd9Sstevel@tonic-gate 	struct algtypelist *ap;
1048*7c478bd9Sstevel@tonic-gate 	struct mechdata *mdp;
1049*7c478bd9Sstevel@tonic-gate 	struct cacheuid_list **cpp, *cp;
1050*7c478bd9Sstevel@tonic-gate 
1051*7c478bd9Sstevel@tonic-gate 	debug(KEYSERV_DEBUG, ("getanycache3 %d", uid));
1052*7c478bd9Sstevel@tonic-gate 	for (kp = mechtable.kp; kp != NULL; kp = kp->next) {
1053*7c478bd9Sstevel@tonic-gate 		debug(KEYSERV_DEBUG0, ("getanycache3 key %d", kp->keylen));
1054*7c478bd9Sstevel@tonic-gate 		for (ap = kp->ap; ap != NULL; ap = ap->next) {
1055*7c478bd9Sstevel@tonic-gate 			debug(KEYSERV_DEBUG0,
1056*7c478bd9Sstevel@tonic-gate 				("getanycache3 alg: %d", ap->algtype));
1057*7c478bd9Sstevel@tonic-gate 			mutex_lock(&ap->mech.mech_lock);
1058*7c478bd9Sstevel@tonic-gate 			if ((mdp = ap->mech.mechdata) == NULL) {
1059*7c478bd9Sstevel@tonic-gate 				mutex_unlock(&ap->mech.mech_lock);
1060*7c478bd9Sstevel@tonic-gate 				continue;
1061*7c478bd9Sstevel@tonic-gate 			}
1062*7c478bd9Sstevel@tonic-gate 			cpp = mapuid2cache(uid, mdp);
1063*7c478bd9Sstevel@tonic-gate 			if (*cpp == NULL) {
1064*7c478bd9Sstevel@tonic-gate 				mutex_unlock(&ap->mech.mech_lock);
1065*7c478bd9Sstevel@tonic-gate 				continue;
1066*7c478bd9Sstevel@tonic-gate 			}
1067*7c478bd9Sstevel@tonic-gate 			cp = *cpp;
1068*7c478bd9Sstevel@tonic-gate 			cp->refcnt++;
1069*7c478bd9Sstevel@tonic-gate 			mutex_unlock(&ap->mech.mech_lock);
1070*7c478bd9Sstevel@tonic-gate 			return (cp);
1071*7c478bd9Sstevel@tonic-gate 		}
1072*7c478bd9Sstevel@tonic-gate 	}
1073*7c478bd9Sstevel@tonic-gate 	return (NULL);
1074*7c478bd9Sstevel@tonic-gate }
1075*7c478bd9Sstevel@tonic-gate 
1076*7c478bd9Sstevel@tonic-gate static struct cacheuid_list *
1077*7c478bd9Sstevel@tonic-gate fetchcache3(uid_t uid, keylen_t k, algtype_t a)
1078*7c478bd9Sstevel@tonic-gate {
1079*7c478bd9Sstevel@tonic-gate 	struct mechentry *mp;
1080*7c478bd9Sstevel@tonic-gate 	struct cacheuid_list *cp;
1081*7c478bd9Sstevel@tonic-gate 
1082*7c478bd9Sstevel@tonic-gate 	debug(KEYSERV_DEBUG, ("fetchcache3 %d %d %d", uid, k, a));
1083*7c478bd9Sstevel@tonic-gate 	if ((mp = getmechtype(k, a)) == NULL) {
1084*7c478bd9Sstevel@tonic-gate 		return (NULL);
1085*7c478bd9Sstevel@tonic-gate 	}
1086*7c478bd9Sstevel@tonic-gate 	if ((cp = getcachekey3(uid, mp)) == NULL) {
1087*7c478bd9Sstevel@tonic-gate 		return (NULL);
1088*7c478bd9Sstevel@tonic-gate 	}
1089*7c478bd9Sstevel@tonic-gate 	debug(KEYSERV_DEBUG, ("fetchcache3 ret %x", cp));
1090*7c478bd9Sstevel@tonic-gate 	return (cp);
1091*7c478bd9Sstevel@tonic-gate }
1092*7c478bd9Sstevel@tonic-gate 
1093*7c478bd9Sstevel@tonic-gate /*
1094*7c478bd9Sstevel@tonic-gate  * Fetch the keys and netname for this uid vers 3
1095*7c478bd9Sstevel@tonic-gate  */
1096*7c478bd9Sstevel@tonic-gate static int
1097*7c478bd9Sstevel@tonic-gate fetch_netname3(uid_t uid, mechtype *net, key_netstarg3 *ret)
1098*7c478bd9Sstevel@tonic-gate {
1099*7c478bd9Sstevel@tonic-gate 	struct cacheuid_list *cp;
1100*7c478bd9Sstevel@tonic-gate 
1101*7c478bd9Sstevel@tonic-gate 	if ((net == NULL) || (ret == NULL)) {
1102*7c478bd9Sstevel@tonic-gate 		return (0);
1103*7c478bd9Sstevel@tonic-gate 	}
1104*7c478bd9Sstevel@tonic-gate 	debug(KEYSERV_DEBUG, ("fetch_netname3 %d %d %d",
1105*7c478bd9Sstevel@tonic-gate 		uid, net->keylen, net->algtype));
1106*7c478bd9Sstevel@tonic-gate 	if (net->keylen == 0) {
1107*7c478bd9Sstevel@tonic-gate 		cp = getanycache3(uid);
1108*7c478bd9Sstevel@tonic-gate 	} else {
1109*7c478bd9Sstevel@tonic-gate 		cp = fetchcache3(uid, net->keylen, net->algtype);
1110*7c478bd9Sstevel@tonic-gate 	}
1111*7c478bd9Sstevel@tonic-gate 	debug(KEYSERV_DEBUG, ("fetch_netname3 cp %x", cp));
1112*7c478bd9Sstevel@tonic-gate 	if (cp == NULL) {
1113*7c478bd9Sstevel@tonic-gate 		return (0);
1114*7c478bd9Sstevel@tonic-gate 	}
1115*7c478bd9Sstevel@tonic-gate 	debug(KEYSERV_DEBUG, ("fetch_netname3 sec %x", cp->secretkey));
1116*7c478bd9Sstevel@tonic-gate 	if (!storekeybuf3(&ret->st_priv_key, cp->secretkey)) {
1117*7c478bd9Sstevel@tonic-gate 		return (0);
1118*7c478bd9Sstevel@tonic-gate 	}
1119*7c478bd9Sstevel@tonic-gate 	debug(KEYSERV_DEBUG, ("fetch_netname3 pub %x", cp->publickey));
1120*7c478bd9Sstevel@tonic-gate 	if (!storekeybuf3(&ret->st_pub_key, cp->publickey)) {
1121*7c478bd9Sstevel@tonic-gate 		return (0);
1122*7c478bd9Sstevel@tonic-gate 	}
1123*7c478bd9Sstevel@tonic-gate 	if (cp->netname) {
1124*7c478bd9Sstevel@tonic-gate 		debug(KEYSERV_DEBUG, ("fetch_netname3 net %s", cp->netname));
1125*7c478bd9Sstevel@tonic-gate 		ret->st_netname = strdup(cp->netname);
1126*7c478bd9Sstevel@tonic-gate 	} else {
1127*7c478bd9Sstevel@tonic-gate 		ret->st_netname = NULL;
1128*7c478bd9Sstevel@tonic-gate 	}
1129*7c478bd9Sstevel@tonic-gate 	remove_ref(cp);
1130*7c478bd9Sstevel@tonic-gate 	return (1);
1131*7c478bd9Sstevel@tonic-gate }
1132*7c478bd9Sstevel@tonic-gate 
1133*7c478bd9Sstevel@tonic-gate keystatus
1134*7c478bd9Sstevel@tonic-gate pk_netget(uid, netstore)
1135*7c478bd9Sstevel@tonic-gate 	uid_t uid;
1136*7c478bd9Sstevel@tonic-gate 	key_netstarg *netstore;
1137*7c478bd9Sstevel@tonic-gate {
1138*7c478bd9Sstevel@tonic-gate 	if (!fetch_netname(uid, netstore)) {
1139*7c478bd9Sstevel@tonic-gate 		return (KEY_SYSTEMERR);
1140*7c478bd9Sstevel@tonic-gate 	}
1141*7c478bd9Sstevel@tonic-gate 	return (KEY_SUCCESS);
1142*7c478bd9Sstevel@tonic-gate }
1143*7c478bd9Sstevel@tonic-gate 
1144*7c478bd9Sstevel@tonic-gate keystatus
1145*7c478bd9Sstevel@tonic-gate pk_netget3(uid_t uid, mechtype *net, key_netstarg3 *ret)
1146*7c478bd9Sstevel@tonic-gate {
1147*7c478bd9Sstevel@tonic-gate 	if (!fetch_netname3(uid, net, ret)) {
1148*7c478bd9Sstevel@tonic-gate 		return (KEY_SYSTEMERR);
1149*7c478bd9Sstevel@tonic-gate 	}
1150*7c478bd9Sstevel@tonic-gate 	return (KEY_SUCCESS);
1151*7c478bd9Sstevel@tonic-gate }
1152*7c478bd9Sstevel@tonic-gate 
1153*7c478bd9Sstevel@tonic-gate #define	cachehit(pub, sec, list)	\
1154*7c478bd9Sstevel@tonic-gate 		(memcmp(pub, (list)->public, sizeof (keybuf)) == 0 && \
1155*7c478bd9Sstevel@tonic-gate 		memcmp(sec, (list)->secret, sizeof (keybuf)) == 0)
1156*7c478bd9Sstevel@tonic-gate 
1157*7c478bd9Sstevel@tonic-gate /*
1158*7c478bd9Sstevel@tonic-gate  * Try to find the common key in the cache
1159*7c478bd9Sstevel@tonic-gate  */
1160*7c478bd9Sstevel@tonic-gate static
1161*7c478bd9Sstevel@tonic-gate readcache(pub, sec, deskey, hash)
1162*7c478bd9Sstevel@tonic-gate 	char *pub;
1163*7c478bd9Sstevel@tonic-gate 	char *sec;
1164*7c478bd9Sstevel@tonic-gate 	des_block *deskey;
1165*7c478bd9Sstevel@tonic-gate 	int hash;
1166*7c478bd9Sstevel@tonic-gate {
1167*7c478bd9Sstevel@tonic-gate 	register struct cachekey_list **l;
1168*7c478bd9Sstevel@tonic-gate 
1169*7c478bd9Sstevel@tonic-gate 	for (l = &g_cachedkeys[hash]; (*l) != NULL && !cachehit(pub, sec, *l);
1170*7c478bd9Sstevel@tonic-gate 		l = &(*l)->next)
1171*7c478bd9Sstevel@tonic-gate 		;
1172*7c478bd9Sstevel@tonic-gate 	if ((*l) == NULL)
1173*7c478bd9Sstevel@tonic-gate 		return (0);
1174*7c478bd9Sstevel@tonic-gate 	*deskey = (*l)->deskey;
1175*7c478bd9Sstevel@tonic-gate 	return (1);
1176*7c478bd9Sstevel@tonic-gate }
1177*7c478bd9Sstevel@tonic-gate 
1178*7c478bd9Sstevel@tonic-gate /*
1179*7c478bd9Sstevel@tonic-gate  * cache result of expensive multiple precision exponential operation
1180*7c478bd9Sstevel@tonic-gate  */
1181*7c478bd9Sstevel@tonic-gate static
1182*7c478bd9Sstevel@tonic-gate writecache(pub, sec, deskey, hash)
1183*7c478bd9Sstevel@tonic-gate 	char *pub;
1184*7c478bd9Sstevel@tonic-gate 	char *sec;
1185*7c478bd9Sstevel@tonic-gate 	des_block *deskey;
1186*7c478bd9Sstevel@tonic-gate 	int hash;
1187*7c478bd9Sstevel@tonic-gate {
1188*7c478bd9Sstevel@tonic-gate 	struct cachekey_list *new;
1189*7c478bd9Sstevel@tonic-gate 
1190*7c478bd9Sstevel@tonic-gate 	new = (struct cachekey_list *)malloc(sizeof (struct cachekey_list));
1191*7c478bd9Sstevel@tonic-gate 	if (new == NULL) {
1192*7c478bd9Sstevel@tonic-gate 		return (0);
1193*7c478bd9Sstevel@tonic-gate 	}
1194*7c478bd9Sstevel@tonic-gate 	memcpy(new->public, pub, sizeof (keybuf));
1195*7c478bd9Sstevel@tonic-gate 	memcpy(new->secret, sec, sizeof (keybuf));
1196*7c478bd9Sstevel@tonic-gate 	new->deskey = *deskey;
1197*7c478bd9Sstevel@tonic-gate 
1198*7c478bd9Sstevel@tonic-gate 	new->next = g_cachedkeys[hash];
1199*7c478bd9Sstevel@tonic-gate 	g_cachedkeys[hash] = new;
1200*7c478bd9Sstevel@tonic-gate 	return (1);
1201*7c478bd9Sstevel@tonic-gate }
1202*7c478bd9Sstevel@tonic-gate 
1203*7c478bd9Sstevel@tonic-gate /*
1204*7c478bd9Sstevel@tonic-gate  * Choose middle 64 bits of the common key to use as our des key, possibly
1205*7c478bd9Sstevel@tonic-gate  * overwriting the lower order bits by setting parity.
1206*7c478bd9Sstevel@tonic-gate  */
1207*7c478bd9Sstevel@tonic-gate static
1208*7c478bd9Sstevel@tonic-gate extractdeskey(ck, deskey)
1209*7c478bd9Sstevel@tonic-gate 	MINT *ck;
1210*7c478bd9Sstevel@tonic-gate 	des_block *deskey;
1211*7c478bd9Sstevel@tonic-gate {
1212*7c478bd9Sstevel@tonic-gate 	void _mp_move(MINT *, MINT *);
1213*7c478bd9Sstevel@tonic-gate 	MINT *a;
1214*7c478bd9Sstevel@tonic-gate 	short r;
1215*7c478bd9Sstevel@tonic-gate 	int i;
1216*7c478bd9Sstevel@tonic-gate 	short base = (1 << 8);
1217*7c478bd9Sstevel@tonic-gate 	char *k;
1218*7c478bd9Sstevel@tonic-gate 
1219*7c478bd9Sstevel@tonic-gate 	a = mp_itom(0);
1220*7c478bd9Sstevel@tonic-gate 	_mp_move(ck, a);
1221*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < ((KEYSIZE - 64) / 2) / 8; i++) {
1222*7c478bd9Sstevel@tonic-gate 		mp_sdiv(a, base, a, &r);
1223*7c478bd9Sstevel@tonic-gate 	}
1224*7c478bd9Sstevel@tonic-gate 	k = deskey->c;
1225*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < 8; i++) {
1226*7c478bd9Sstevel@tonic-gate 		mp_sdiv(a, base, a, &r);
1227*7c478bd9Sstevel@tonic-gate 		*k++ = r;
1228*7c478bd9Sstevel@tonic-gate 	}
1229*7c478bd9Sstevel@tonic-gate 	mp_mfree(a);
1230*7c478bd9Sstevel@tonic-gate 	des_setparity((char *)deskey);
1231*7c478bd9Sstevel@tonic-gate 	return (0);
1232*7c478bd9Sstevel@tonic-gate }
1233*7c478bd9Sstevel@tonic-gate 
1234*7c478bd9Sstevel@tonic-gate static bool_t
1235*7c478bd9Sstevel@tonic-gate fetchsecretkey(uid, buf)
1236*7c478bd9Sstevel@tonic-gate 	uid_t uid;
1237*7c478bd9Sstevel@tonic-gate 	char *buf;
1238*7c478bd9Sstevel@tonic-gate {
1239*7c478bd9Sstevel@tonic-gate 	struct secretkey_netname_list *l;
1240*7c478bd9Sstevel@tonic-gate 	int hash = HASH_UID(uid);
1241*7c478bd9Sstevel@tonic-gate 
1242*7c478bd9Sstevel@tonic-gate 	(void) rw_rdlock(&g_secretkey_netname_lock);
1243*7c478bd9Sstevel@tonic-gate 	for (l = g_secretkey_netname[hash]; l != NULL; l = l->next) {
1244*7c478bd9Sstevel@tonic-gate 		if (l->uid == uid) {
1245*7c478bd9Sstevel@tonic-gate 			memcpy(buf, l->keynetdata.st_priv_key,
1246*7c478bd9Sstevel@tonic-gate 				sizeof (keybuf));
1247*7c478bd9Sstevel@tonic-gate 			(void) rw_unlock(&g_secretkey_netname_lock);
1248*7c478bd9Sstevel@tonic-gate 			return (TRUE);
1249*7c478bd9Sstevel@tonic-gate 		}
1250*7c478bd9Sstevel@tonic-gate 	}
1251*7c478bd9Sstevel@tonic-gate 	(void) rw_unlock(&g_secretkey_netname_lock);
1252*7c478bd9Sstevel@tonic-gate 	return (FALSE);
1253*7c478bd9Sstevel@tonic-gate }
1254*7c478bd9Sstevel@tonic-gate 
1255*7c478bd9Sstevel@tonic-gate static keybuf3 *
1256*7c478bd9Sstevel@tonic-gate fetchsecretkey3(uid_t uid, keylen_t k, algtype_t a)
1257*7c478bd9Sstevel@tonic-gate {
1258*7c478bd9Sstevel@tonic-gate 	struct cacheuid_list *cp;
1259*7c478bd9Sstevel@tonic-gate 
1260*7c478bd9Sstevel@tonic-gate 	debug(KEYSERV_DEBUG, ("fetchsecretkey3 %d %d %d", uid, k, a));
1261*7c478bd9Sstevel@tonic-gate 	if ((cp = fetchcache3(uid, k, a)) == NULL) {
1262*7c478bd9Sstevel@tonic-gate 		return (NULL);
1263*7c478bd9Sstevel@tonic-gate 	}
1264*7c478bd9Sstevel@tonic-gate 	debug(KEYSERV_DEBUG, ("fetchsecretkey3 ret %x", cp->secretkey));
1265*7c478bd9Sstevel@tonic-gate 	return (cp->secretkey);
1266*7c478bd9Sstevel@tonic-gate }
1267*7c478bd9Sstevel@tonic-gate 
1268*7c478bd9Sstevel@tonic-gate /*
1269*7c478bd9Sstevel@tonic-gate  * Do the work of pk_encrypt && pk_decrypt
1270*7c478bd9Sstevel@tonic-gate  */
1271*7c478bd9Sstevel@tonic-gate static keystatus
1272*7c478bd9Sstevel@tonic-gate pk_crypt(uid, remote_name, remote_key, key, mode)
1273*7c478bd9Sstevel@tonic-gate 	uid_t uid;
1274*7c478bd9Sstevel@tonic-gate 	char *remote_name;
1275*7c478bd9Sstevel@tonic-gate 	netobj *remote_key;
1276*7c478bd9Sstevel@tonic-gate 	des_block *key;
1277*7c478bd9Sstevel@tonic-gate 	int mode;
1278*7c478bd9Sstevel@tonic-gate {
1279*7c478bd9Sstevel@tonic-gate 	char xsecret[1024];
1280*7c478bd9Sstevel@tonic-gate 	char xpublic[1024];
1281*7c478bd9Sstevel@tonic-gate 	des_block deskey;
1282*7c478bd9Sstevel@tonic-gate 	int err;
1283*7c478bd9Sstevel@tonic-gate 	MINT *public;
1284*7c478bd9Sstevel@tonic-gate 	MINT *secret;
1285*7c478bd9Sstevel@tonic-gate 	MINT *common;
1286*7c478bd9Sstevel@tonic-gate 	char zero[8];
1287*7c478bd9Sstevel@tonic-gate 	int hash;
1288*7c478bd9Sstevel@tonic-gate 
1289*7c478bd9Sstevel@tonic-gate 	if (!fetchsecretkey(uid, xsecret) || xsecret[0] == 0) {
1290*7c478bd9Sstevel@tonic-gate 		memset(zero, 0, sizeof (zero));
1291*7c478bd9Sstevel@tonic-gate 		if (nodefaultkeys)
1292*7c478bd9Sstevel@tonic-gate 			return (KEY_NOSECRET);
1293*7c478bd9Sstevel@tonic-gate 
1294*7c478bd9Sstevel@tonic-gate 		if (!getsecretkey("nobody", xsecret, zero) || xsecret[0] == 0) {
1295*7c478bd9Sstevel@tonic-gate 			return (KEY_NOSECRET);
1296*7c478bd9Sstevel@tonic-gate 		}
1297*7c478bd9Sstevel@tonic-gate 	}
1298*7c478bd9Sstevel@tonic-gate 	if (remote_key) {
1299*7c478bd9Sstevel@tonic-gate 		memcpy(xpublic, remote_key->n_bytes, remote_key->n_len);
1300*7c478bd9Sstevel@tonic-gate 	} else {
1301*7c478bd9Sstevel@tonic-gate 		if (!getpublickey(remote_name, xpublic)) {
1302*7c478bd9Sstevel@tonic-gate 			if (nodefaultkeys || !getpublickey("nobody", xpublic))
1303*7c478bd9Sstevel@tonic-gate 				return (KEY_UNKNOWN);
1304*7c478bd9Sstevel@tonic-gate 		}
1305*7c478bd9Sstevel@tonic-gate 	}
1306*7c478bd9Sstevel@tonic-gate 
1307*7c478bd9Sstevel@tonic-gate 	xsecret[HEXKEYBYTES] = '\0';
1308*7c478bd9Sstevel@tonic-gate 	xpublic[HEXKEYBYTES] = '\0';
1309*7c478bd9Sstevel@tonic-gate 
1310*7c478bd9Sstevel@tonic-gate 	hash = hash_keys(xpublic, xsecret);
1311*7c478bd9Sstevel@tonic-gate 	(void) rw_rdlock(&g_cachedkeys_lock);
1312*7c478bd9Sstevel@tonic-gate 	if (!readcache(xpublic, xsecret, &deskey, hash)) {
1313*7c478bd9Sstevel@tonic-gate 		(void) rw_unlock(&g_cachedkeys_lock);
1314*7c478bd9Sstevel@tonic-gate 		(void) rw_wrlock(&g_cachedkeys_lock);
1315*7c478bd9Sstevel@tonic-gate 		if (!readcache(xpublic, xsecret, &deskey, hash)) {
1316*7c478bd9Sstevel@tonic-gate 			public = mp_xtom(xpublic);
1317*7c478bd9Sstevel@tonic-gate 			secret = mp_xtom(xsecret);
1318*7c478bd9Sstevel@tonic-gate 			/* Sanity Check on public and private keys */
1319*7c478bd9Sstevel@tonic-gate 			if (public == NULL || secret == NULL) {
1320*7c478bd9Sstevel@tonic-gate 				(void) rw_unlock(&g_cachedkeys_lock);
1321*7c478bd9Sstevel@tonic-gate 				return (KEY_SYSTEMERR);
1322*7c478bd9Sstevel@tonic-gate 			}
1323*7c478bd9Sstevel@tonic-gate 			common = mp_itom(0);
1324*7c478bd9Sstevel@tonic-gate 			mp_pow(public, secret, MODULUS, common);
1325*7c478bd9Sstevel@tonic-gate 			extractdeskey(common, &deskey);
1326*7c478bd9Sstevel@tonic-gate 			writecache(xpublic, xsecret, &deskey, hash);
1327*7c478bd9Sstevel@tonic-gate 			mp_mfree(secret);
1328*7c478bd9Sstevel@tonic-gate 			mp_mfree(public);
1329*7c478bd9Sstevel@tonic-gate 			mp_mfree(common);
1330*7c478bd9Sstevel@tonic-gate 		}
1331*7c478bd9Sstevel@tonic-gate 	}
1332*7c478bd9Sstevel@tonic-gate 	(void) rw_unlock(&g_cachedkeys_lock);
1333*7c478bd9Sstevel@tonic-gate 
1334*7c478bd9Sstevel@tonic-gate 	err = ecb_crypt((char *)&deskey, (char *)key, sizeof (des_block),
1335*7c478bd9Sstevel@tonic-gate 		DES_HW | mode);
1336*7c478bd9Sstevel@tonic-gate 	if (DES_FAILED(err)) {
1337*7c478bd9Sstevel@tonic-gate 		return (KEY_SYSTEMERR);
1338*7c478bd9Sstevel@tonic-gate 	}
1339*7c478bd9Sstevel@tonic-gate 	return (KEY_SUCCESS);
1340*7c478bd9Sstevel@tonic-gate }
1341*7c478bd9Sstevel@tonic-gate 
1342*7c478bd9Sstevel@tonic-gate static int
1343*7c478bd9Sstevel@tonic-gate hash_keys3(keybuf3 *p, keybuf3 *s)
1344*7c478bd9Sstevel@tonic-gate {
1345*7c478bd9Sstevel@tonic-gate 	int i;
1346*7c478bd9Sstevel@tonic-gate 	int hash = 0;
1347*7c478bd9Sstevel@tonic-gate 	char *pub = p->keybuf3_val;
1348*7c478bd9Sstevel@tonic-gate 	char *sec = s->keybuf3_val;
1349*7c478bd9Sstevel@tonic-gate 
1350*7c478bd9Sstevel@tonic-gate 	debug(KEYSERV_DEBUG, ("hash_keys3 public %d %s",
1351*7c478bd9Sstevel@tonic-gate 		p->keybuf3_len, pub));
1352*7c478bd9Sstevel@tonic-gate 	debug(KEYSERV_DEBUG, ("hash_keys3 secret %d %s",
1353*7c478bd9Sstevel@tonic-gate 		s->keybuf3_len, sec));
1354*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < s->keybuf3_len; i += 6, pub += 6, sec += 6) {
1355*7c478bd9Sstevel@tonic-gate 		hash ^= *pub;
1356*7c478bd9Sstevel@tonic-gate 		hash ^= *sec;
1357*7c478bd9Sstevel@tonic-gate 	}
1358*7c478bd9Sstevel@tonic-gate 	debug(KEYSERV_DEBUG, ("hash_keys3 ret %d", hash & 0xff));
1359*7c478bd9Sstevel@tonic-gate 	return (hash & 0xff);
1360*7c478bd9Sstevel@tonic-gate }
1361*7c478bd9Sstevel@tonic-gate 
1362*7c478bd9Sstevel@tonic-gate static struct cachekey3_list **
1363*7c478bd9Sstevel@tonic-gate map_ps2cache(keybuf3 *public, keybuf3 *secret, struct psdata *pdp)
1364*7c478bd9Sstevel@tonic-gate {
1365*7c478bd9Sstevel@tonic-gate 	struct cachekey3_list **cpp;
1366*7c478bd9Sstevel@tonic-gate 	int hash = hash_keys3(public, secret);
1367*7c478bd9Sstevel@tonic-gate 
1368*7c478bd9Sstevel@tonic-gate 	debug(KEYSERV_DEBUG, ("map_ps2cache %x %d", pdp, hash));
1369*7c478bd9Sstevel@tonic-gate 	for (cpp = &pdp->common[hash];
1370*7c478bd9Sstevel@tonic-gate 		*cpp != NULL && !(cachehit3(public, secret, *cpp));
1371*7c478bd9Sstevel@tonic-gate 		cpp = &(*cpp)->next) {
1372*7c478bd9Sstevel@tonic-gate 		debug(KEYSERV_DEBUG0, ("map_ps2cache %x", cpp));
1373*7c478bd9Sstevel@tonic-gate 	}
1374*7c478bd9Sstevel@tonic-gate 	debug(KEYSERV_DEBUG, ("map_ps2cache ret %x", cpp));
1375*7c478bd9Sstevel@tonic-gate 	return (cpp);
1376*7c478bd9Sstevel@tonic-gate }
1377*7c478bd9Sstevel@tonic-gate 
1378*7c478bd9Sstevel@tonic-gate static struct cachekey3_list *
1379*7c478bd9Sstevel@tonic-gate getdeskey3(
1380*7c478bd9Sstevel@tonic-gate 	keylen_t keylen,
1381*7c478bd9Sstevel@tonic-gate 	algtype_t algtype,
1382*7c478bd9Sstevel@tonic-gate 	int desarylen,
1383*7c478bd9Sstevel@tonic-gate 	keybuf3 *public,
1384*7c478bd9Sstevel@tonic-gate 	keybuf3 *secret,
1385*7c478bd9Sstevel@tonic-gate 	uid_t uid
1386*7c478bd9Sstevel@tonic-gate )
1387*7c478bd9Sstevel@tonic-gate {
1388*7c478bd9Sstevel@tonic-gate 	struct mechentry *mp;
1389*7c478bd9Sstevel@tonic-gate 	struct psdata *pdp;
1390*7c478bd9Sstevel@tonic-gate 	struct cachekey3_list **cpp, *cp, *cachep;
1391*7c478bd9Sstevel@tonic-gate 	struct cacheuid_list *cu;
1392*7c478bd9Sstevel@tonic-gate 	int i;
1393*7c478bd9Sstevel@tonic-gate 	int cached = 0;
1394*7c478bd9Sstevel@tonic-gate 
1395*7c478bd9Sstevel@tonic-gate 	debug(KEYSERV_DEBUG, ("getdeskey3 %d %d %d %x %x",
1396*7c478bd9Sstevel@tonic-gate 		keylen, algtype, desarylen, public, secret));
1397*7c478bd9Sstevel@tonic-gate 	if ((mp = getmechtype(keylen, algtype)) == NULL) {
1398*7c478bd9Sstevel@tonic-gate 		return (0);
1399*7c478bd9Sstevel@tonic-gate 	}
1400*7c478bd9Sstevel@tonic-gate 	(void) mutex_lock(&mp->ps_lock);
1401*7c478bd9Sstevel@tonic-gate 	if ((pdp = mp->psdata) == NULL) {
1402*7c478bd9Sstevel@tonic-gate 		if ((pdp = (struct psdata *)calloc(1, sizeof (*pdp))) ==
1403*7c478bd9Sstevel@tonic-gate 			NULL) {
1404*7c478bd9Sstevel@tonic-gate 			mutex_unlock(&mp->ps_lock);
1405*7c478bd9Sstevel@tonic-gate 			debug(KEYSERV_INFO, ("getdeskey3 : calloc failed"));
1406*7c478bd9Sstevel@tonic-gate 			return (0);
1407*7c478bd9Sstevel@tonic-gate 		}
1408*7c478bd9Sstevel@tonic-gate 		mp->psdata = pdp;
1409*7c478bd9Sstevel@tonic-gate 	}
1410*7c478bd9Sstevel@tonic-gate 	debug(KEYSERV_DEBUG, ("getdeskey3 %x", pdp));
1411*7c478bd9Sstevel@tonic-gate 	cpp = map_ps2cache(public, secret, pdp);
1412*7c478bd9Sstevel@tonic-gate 	if (*cpp == NULL) {
1413*7c478bd9Sstevel@tonic-gate 		debug(KEYSERV_DEBUG, ("getdeskey3 calling fetchcache3"));
1414*7c478bd9Sstevel@tonic-gate 		if (disk_caching &&
1415*7c478bd9Sstevel@tonic-gate 			(cu = fetchcache3(uid, keylen, algtype)) != NULL) {
1416*7c478bd9Sstevel@tonic-gate 			debug(KEYSERV_DEBUG,
1417*7c478bd9Sstevel@tonic-gate 				("getdeskey3 calling cache_retrieve"));
1418*7c478bd9Sstevel@tonic-gate 			if ((cachep = cache_retrieve(keylen, algtype, uid,
1419*7c478bd9Sstevel@tonic-gate 				public, cu->key)) != NULL) {
1420*7c478bd9Sstevel@tonic-gate 				if (cmpkeybuf3(cachep->secret, cu->secretkey)) {
1421*7c478bd9Sstevel@tonic-gate 					cached = 1;
1422*7c478bd9Sstevel@tonic-gate 				} else {
1423*7c478bd9Sstevel@tonic-gate 					debug(KEYSERV_DEBUG,
1424*7c478bd9Sstevel@tonic-gate 					("getdeskey3 calling cache_remove"));
1425*7c478bd9Sstevel@tonic-gate 					cache_remove(keylen, algtype,
1426*7c478bd9Sstevel@tonic-gate 						uid, NULL);
1427*7c478bd9Sstevel@tonic-gate 				}
1428*7c478bd9Sstevel@tonic-gate 			}
1429*7c478bd9Sstevel@tonic-gate 		}
1430*7c478bd9Sstevel@tonic-gate 		if (cached) {
1431*7c478bd9Sstevel@tonic-gate 			cp = cachep;
1432*7c478bd9Sstevel@tonic-gate 		} else {
1433*7c478bd9Sstevel@tonic-gate 			if ((cp = (struct cachekey3_list *)
1434*7c478bd9Sstevel@tonic-gate 				malloc(sizeof (*cp))) == NULL) {
1435*7c478bd9Sstevel@tonic-gate 				mutex_unlock(&mp->ps_lock);
1436*7c478bd9Sstevel@tonic-gate 				debug(KEYSERV_INFO,
1437*7c478bd9Sstevel@tonic-gate 					("getdeskey3 : malloc failed"));
1438*7c478bd9Sstevel@tonic-gate 				syslog(LOG_ERR,
1439*7c478bd9Sstevel@tonic-gate 					"file %s line %d: malloc failed",
1440*7c478bd9Sstevel@tonic-gate 					__FILE__, __LINE__);
1441*7c478bd9Sstevel@tonic-gate 				return (0);
1442*7c478bd9Sstevel@tonic-gate 			}
1443*7c478bd9Sstevel@tonic-gate 			cp->refcnt = 0;
1444*7c478bd9Sstevel@tonic-gate 			cp->next = NULL;
1445*7c478bd9Sstevel@tonic-gate 			if ((cp->public = cpykeybuf3(public)) == NULL) {
1446*7c478bd9Sstevel@tonic-gate 				mutex_unlock(&mp->ps_lock);
1447*7c478bd9Sstevel@tonic-gate 				return (0);
1448*7c478bd9Sstevel@tonic-gate 			}
1449*7c478bd9Sstevel@tonic-gate 			if ((cp->secret = cpykeybuf3(secret)) == NULL) {
1450*7c478bd9Sstevel@tonic-gate 				mutex_unlock(&mp->ps_lock);
1451*7c478bd9Sstevel@tonic-gate 				return (0);
1452*7c478bd9Sstevel@tonic-gate 			}
1453*7c478bd9Sstevel@tonic-gate 			if (!setdeskeyarray(&cp->deskey, desarylen)) {
1454*7c478bd9Sstevel@tonic-gate 				mutex_unlock(&mp->ps_lock);
1455*7c478bd9Sstevel@tonic-gate 				return (0);
1456*7c478bd9Sstevel@tonic-gate 			}
1457*7c478bd9Sstevel@tonic-gate 			debug(KEYSERV_DEBUG, ("getdeskey3 %x %x %x",
1458*7c478bd9Sstevel@tonic-gate 				cp->public, cp->secret,
1459*7c478bd9Sstevel@tonic-gate 				cp->deskey.deskeyarray_val));
1460*7c478bd9Sstevel@tonic-gate 			debug(KEYSERV_DEBUG,
1461*7c478bd9Sstevel@tonic-gate 				("getdeskey3 calling __gen_common_dhkeys_g"));
1462*7c478bd9Sstevel@tonic-gate 			if (!__gen_common_dhkeys_g(public->keybuf3_val,
1463*7c478bd9Sstevel@tonic-gate 				secret->keybuf3_val,
1464*7c478bd9Sstevel@tonic-gate 				keylen, algtype,
1465*7c478bd9Sstevel@tonic-gate 				cp->deskey.deskeyarray_val, desarylen)) {
1466*7c478bd9Sstevel@tonic-gate 				mutex_unlock(&mp->ps_lock);
1467*7c478bd9Sstevel@tonic-gate 				return (0);
1468*7c478bd9Sstevel@tonic-gate 			}
1469*7c478bd9Sstevel@tonic-gate 			for (i = 0; i < desarylen; i++) {
1470*7c478bd9Sstevel@tonic-gate 				debug(KEYSERV_DEBUG0,
1471*7c478bd9Sstevel@tonic-gate 					("getdeskey3 gendh key : (%x,%x)",
1472*7c478bd9Sstevel@tonic-gate 					cp->deskey.deskeyarray_val[i].key.high,
1473*7c478bd9Sstevel@tonic-gate 					cp->deskey.deskeyarray_val[i].key.low));
1474*7c478bd9Sstevel@tonic-gate 			}
1475*7c478bd9Sstevel@tonic-gate 			if (disk_caching && cu != NULL) {
1476*7c478bd9Sstevel@tonic-gate 				debug(KEYSERV_DEBUG,
1477*7c478bd9Sstevel@tonic-gate 					("getdeskey3 calling cache_insert"));
1478*7c478bd9Sstevel@tonic-gate 				cache_insert(keylen, algtype, uid, cp->deskey,
1479*7c478bd9Sstevel@tonic-gate 					cu->key, public, secret);
1480*7c478bd9Sstevel@tonic-gate 			}
1481*7c478bd9Sstevel@tonic-gate 		}
1482*7c478bd9Sstevel@tonic-gate 		*cpp = cp;
1483*7c478bd9Sstevel@tonic-gate 	} else {
1484*7c478bd9Sstevel@tonic-gate 		cp = *cpp;
1485*7c478bd9Sstevel@tonic-gate 	}
1486*7c478bd9Sstevel@tonic-gate 	cp->refcnt++;
1487*7c478bd9Sstevel@tonic-gate 	mutex_unlock(&mp->ps_lock);
1488*7c478bd9Sstevel@tonic-gate 	debug(KEYSERV_DEBUG, ("getdeskey3 ret %x", cp));
1489*7c478bd9Sstevel@tonic-gate 	return (cp);
1490*7c478bd9Sstevel@tonic-gate }
1491*7c478bd9Sstevel@tonic-gate 
1492*7c478bd9Sstevel@tonic-gate keystatus
1493*7c478bd9Sstevel@tonic-gate pk_get_conv_key3(uid_t uid, deskeyarg3 *arg, cryptkeyres3 *res)
1494*7c478bd9Sstevel@tonic-gate {
1495*7c478bd9Sstevel@tonic-gate 	keybuf3 *xsecret, *xpublic;
1496*7c478bd9Sstevel@tonic-gate 	char zero[8];
1497*7c478bd9Sstevel@tonic-gate 	struct cachekey3_list *cp;
1498*7c478bd9Sstevel@tonic-gate 
1499*7c478bd9Sstevel@tonic-gate 	debug(KEYSERV_DEBUG, ("pk_get_conv_key3 %d %x %x",
1500*7c478bd9Sstevel@tonic-gate 		uid, arg, res));
1501*7c478bd9Sstevel@tonic-gate 	if ((xsecret = fetchsecretkey3(uid,
1502*7c478bd9Sstevel@tonic-gate 		arg->keylen, arg->algtype)) == NULL) {
1503*7c478bd9Sstevel@tonic-gate 		if (nodefaultkeys)
1504*7c478bd9Sstevel@tonic-gate 			return (KEY_NOSECRET);
1505*7c478bd9Sstevel@tonic-gate 		memset(zero, 0, sizeof (zero));
1506*7c478bd9Sstevel@tonic-gate 		if ((xsecret = getkeybuf3(arg->keylen/4+1)) == NULL) {
1507*7c478bd9Sstevel@tonic-gate 			return (KEY_SYSTEMERR);
1508*7c478bd9Sstevel@tonic-gate 		}
1509*7c478bd9Sstevel@tonic-gate 		debug(KEYSERV_DEBUG,
1510*7c478bd9Sstevel@tonic-gate 			("pk_get_conv_key3 calling getsecretkey_g"));
1511*7c478bd9Sstevel@tonic-gate 		if (!getsecretkey_g("nobody",
1512*7c478bd9Sstevel@tonic-gate 			arg->keylen, arg->algtype,
1513*7c478bd9Sstevel@tonic-gate 			xsecret->keybuf3_val, xsecret->keybuf3_len,
1514*7c478bd9Sstevel@tonic-gate 			zero) || *xsecret->keybuf3_val == 0) { /* XXX */
1515*7c478bd9Sstevel@tonic-gate 			debug(KEYSERV_DEBUG,
1516*7c478bd9Sstevel@tonic-gate 			("pk_get_conv_key3 calling getsecretkey_g failed"));
1517*7c478bd9Sstevel@tonic-gate 			return (KEY_NOSECRET);
1518*7c478bd9Sstevel@tonic-gate 		}
1519*7c478bd9Sstevel@tonic-gate 		debug(KEYSERV_DEBUG,
1520*7c478bd9Sstevel@tonic-gate 			("pk_get_conv_key3 calling getsecretkey_g succeeded"));
1521*7c478bd9Sstevel@tonic-gate 	}
1522*7c478bd9Sstevel@tonic-gate 	xpublic = &arg->pub_key;
1523*7c478bd9Sstevel@tonic-gate 	if ((cp = getdeskey3(arg->keylen, arg->algtype, arg->nkeys,
1524*7c478bd9Sstevel@tonic-gate 		xpublic, xsecret, uid)) == NULL) {
1525*7c478bd9Sstevel@tonic-gate 		return (KEY_SYSTEMERR);
1526*7c478bd9Sstevel@tonic-gate 	}
1527*7c478bd9Sstevel@tonic-gate 	storedeskeyarray(&res->cryptkeyres3_u.deskey, &cp->deskey);
1528*7c478bd9Sstevel@tonic-gate 	return (KEY_SUCCESS);
1529*7c478bd9Sstevel@tonic-gate }
1530*7c478bd9Sstevel@tonic-gate 
1531*7c478bd9Sstevel@tonic-gate /*
1532*7c478bd9Sstevel@tonic-gate  * Do the work of pk_encrypt3 && pk_decrypt3
1533*7c478bd9Sstevel@tonic-gate  */
1534*7c478bd9Sstevel@tonic-gate static keystatus
1535*7c478bd9Sstevel@tonic-gate pk_crypt3(
1536*7c478bd9Sstevel@tonic-gate 	uid_t uid,
1537*7c478bd9Sstevel@tonic-gate 	cryptkeyarg3 *arg,
1538*7c478bd9Sstevel@tonic-gate 	deskeyarray *key,
1539*7c478bd9Sstevel@tonic-gate 	int mode
1540*7c478bd9Sstevel@tonic-gate )
1541*7c478bd9Sstevel@tonic-gate {
1542*7c478bd9Sstevel@tonic-gate 	keybuf3 *xsecret = NULL, *xpublic = NULL;
1543*7c478bd9Sstevel@tonic-gate 	char zero[8];
1544*7c478bd9Sstevel@tonic-gate 	struct cachekey3_list *cp;
1545*7c478bd9Sstevel@tonic-gate 	int err;
1546*7c478bd9Sstevel@tonic-gate 	int xsecret_alloc = 0;
1547*7c478bd9Sstevel@tonic-gate 	char ivec[8];
1548*7c478bd9Sstevel@tonic-gate 
1549*7c478bd9Sstevel@tonic-gate 	memset(ivec, 0, 8);
1550*7c478bd9Sstevel@tonic-gate 	debug(KEYSERV_DEBUG1, ("pk_crypt3 %d %x %x %d",
1551*7c478bd9Sstevel@tonic-gate 		uid, arg, key, mode));
1552*7c478bd9Sstevel@tonic-gate 	if ((xsecret = fetchsecretkey3(uid,
1553*7c478bd9Sstevel@tonic-gate 		arg->keylen, arg->algtype)) == NULL) {
1554*7c478bd9Sstevel@tonic-gate 		if (nodefaultkeys)
1555*7c478bd9Sstevel@tonic-gate 			return (KEY_NOSECRET);
1556*7c478bd9Sstevel@tonic-gate 		memset(zero, 0, sizeof (zero));
1557*7c478bd9Sstevel@tonic-gate 		if ((xsecret = getkeybuf3(arg->keylen/4+1)) == NULL) {
1558*7c478bd9Sstevel@tonic-gate 			return (KEY_SYSTEMERR);
1559*7c478bd9Sstevel@tonic-gate 		}
1560*7c478bd9Sstevel@tonic-gate 		xsecret_alloc = 1;
1561*7c478bd9Sstevel@tonic-gate 		debug(KEYSERV_DEBUG1, ("pk_crypt3 calling getsecretkey_g"));
1562*7c478bd9Sstevel@tonic-gate 		if (!getsecretkey_g("nobody",
1563*7c478bd9Sstevel@tonic-gate 			arg->keylen, arg->algtype,
1564*7c478bd9Sstevel@tonic-gate 			xsecret->keybuf3_val, xsecret->keybuf3_len,
1565*7c478bd9Sstevel@tonic-gate 			zero) || *xsecret->keybuf3_val == 0) { /* XXX */
1566*7c478bd9Sstevel@tonic-gate 			debug(KEYSERV_DEBUG,
1567*7c478bd9Sstevel@tonic-gate 				("pk_crypt3 calling getsecretkey_g failed"));
1568*7c478bd9Sstevel@tonic-gate 			freekeybuf3(xsecret);
1569*7c478bd9Sstevel@tonic-gate 			return (KEY_NOSECRET);
1570*7c478bd9Sstevel@tonic-gate 		}
1571*7c478bd9Sstevel@tonic-gate 		/* XXX optimize to cache nobody's secret key? */
1572*7c478bd9Sstevel@tonic-gate 		debug(KEYSERV_DEBUG0,
1573*7c478bd9Sstevel@tonic-gate 			("pk_crypt3 calling getsecretkey_g succeeded"));
1574*7c478bd9Sstevel@tonic-gate 	}
1575*7c478bd9Sstevel@tonic-gate 	if (arg->remotekey.keybuf3_len) {
1576*7c478bd9Sstevel@tonic-gate 		if ((xpublic = cpykeybuf3(&arg->remotekey)) == NULL) {
1577*7c478bd9Sstevel@tonic-gate 			if (xsecret_alloc) freekeybuf3(xsecret);
1578*7c478bd9Sstevel@tonic-gate 			return (KEY_SYSTEMERR);
1579*7c478bd9Sstevel@tonic-gate 		}
1580*7c478bd9Sstevel@tonic-gate 	} else {
1581*7c478bd9Sstevel@tonic-gate 		if ((xpublic = getkeybuf3(arg->keylen/4+1)) == NULL) {
1582*7c478bd9Sstevel@tonic-gate 			if (xsecret_alloc) freekeybuf3(xsecret);
1583*7c478bd9Sstevel@tonic-gate 			return (KEY_SYSTEMERR);
1584*7c478bd9Sstevel@tonic-gate 		}
1585*7c478bd9Sstevel@tonic-gate 		debug(KEYSERV_DEBUG1, ("pk_crypt3 calling getpublickey_g"));
1586*7c478bd9Sstevel@tonic-gate 		if (!getpublickey_g(arg->remotename,
1587*7c478bd9Sstevel@tonic-gate 			arg->keylen, arg->algtype,
1588*7c478bd9Sstevel@tonic-gate 			xpublic->keybuf3_val, xpublic->keybuf3_len)) {
1589*7c478bd9Sstevel@tonic-gate 			debug(KEYSERV_DEBUG0,
1590*7c478bd9Sstevel@tonic-gate 				("pk_crypt3 calling getpublickey_g nobody"));
1591*7c478bd9Sstevel@tonic-gate 			if (nodefaultkeys || !getpublickey_g("nobody",
1592*7c478bd9Sstevel@tonic-gate 				arg->keylen, arg->algtype,
1593*7c478bd9Sstevel@tonic-gate 				xpublic->keybuf3_val, xpublic->keybuf3_len)) {
1594*7c478bd9Sstevel@tonic-gate 				debug(KEYSERV_DEBUG,
1595*7c478bd9Sstevel@tonic-gate 			("pk_crypt3 calling getpublickey_g nobody failed"));
1596*7c478bd9Sstevel@tonic-gate 				if (xsecret_alloc) freekeybuf3(xsecret);
1597*7c478bd9Sstevel@tonic-gate 				freekeybuf3(xpublic);
1598*7c478bd9Sstevel@tonic-gate 				return (KEY_UNKNOWN);
1599*7c478bd9Sstevel@tonic-gate 			}
1600*7c478bd9Sstevel@tonic-gate 		}
1601*7c478bd9Sstevel@tonic-gate 		debug(KEYSERV_DEBUG0,
1602*7c478bd9Sstevel@tonic-gate 			("pk_crypt3 calling getpublickey_g succeeded"));
1603*7c478bd9Sstevel@tonic-gate 	}
1604*7c478bd9Sstevel@tonic-gate 
1605*7c478bd9Sstevel@tonic-gate 	if ((cp = getdeskey3(arg->keylen, arg->algtype,
1606*7c478bd9Sstevel@tonic-gate 		arg->deskey.deskeyarray_len, xpublic, xsecret, uid)) == NULL) {
1607*7c478bd9Sstevel@tonic-gate 		if (xsecret_alloc) freekeybuf3(xsecret);
1608*7c478bd9Sstevel@tonic-gate 		freekeybuf3(xpublic);
1609*7c478bd9Sstevel@tonic-gate 		return (KEY_SYSTEMERR);
1610*7c478bd9Sstevel@tonic-gate 	}
1611*7c478bd9Sstevel@tonic-gate 	storedeskeyarray(key, &arg->deskey);
1612*7c478bd9Sstevel@tonic-gate 	if (CLASSIC_PK_DH(arg->keylen, arg->algtype)) {
1613*7c478bd9Sstevel@tonic-gate 		/*EMPTY*/
1614*7c478bd9Sstevel@tonic-gate 		debug(KEYSERV_DEBUG1,
1615*7c478bd9Sstevel@tonic-gate 			("pk_crypt3 WARNING received 192-bit key"));
1616*7c478bd9Sstevel@tonic-gate 	} else {
1617*7c478bd9Sstevel@tonic-gate 		debug(KEYSERV_DEBUG,
1618*7c478bd9Sstevel@tonic-gate 			("pk_crypt3 calling __cbc_triple_crypt"));
1619*7c478bd9Sstevel@tonic-gate 		err = __cbc_triple_crypt(cp->deskey.deskeyarray_val,
1620*7c478bd9Sstevel@tonic-gate 			(char *)key->deskeyarray_val,
1621*7c478bd9Sstevel@tonic-gate 			cp->deskey.deskeyarray_len*sizeof (des_block),
1622*7c478bd9Sstevel@tonic-gate 			DES_HW | mode, ivec);
1623*7c478bd9Sstevel@tonic-gate 		if (DES_FAILED(err)) {
1624*7c478bd9Sstevel@tonic-gate 			debug(KEYSERV_DEBUG,
1625*7c478bd9Sstevel@tonic-gate 		("pk_crypt3 calling ecb_crypt/__cbc_triple_crypt failed"));
1626*7c478bd9Sstevel@tonic-gate 			if (xsecret_alloc) freekeybuf3(xsecret);
1627*7c478bd9Sstevel@tonic-gate 			freekeybuf3(xpublic);
1628*7c478bd9Sstevel@tonic-gate 			return (KEY_SYSTEMERR);
1629*7c478bd9Sstevel@tonic-gate 		}
1630*7c478bd9Sstevel@tonic-gate 		debug(KEYSERV_DEBUG,
1631*7c478bd9Sstevel@tonic-gate 			("pk_crypt3 calling __cbc_triple_crypt succeeded"));
1632*7c478bd9Sstevel@tonic-gate 	}
1633*7c478bd9Sstevel@tonic-gate 	if (xsecret_alloc) freekeybuf3(xsecret);
1634*7c478bd9Sstevel@tonic-gate 	freekeybuf3(xpublic);
1635*7c478bd9Sstevel@tonic-gate 	return (KEY_SUCCESS);
1636*7c478bd9Sstevel@tonic-gate }
1637*7c478bd9Sstevel@tonic-gate 
1638*7c478bd9Sstevel@tonic-gate keystatus
1639*7c478bd9Sstevel@tonic-gate pk_get_conv_key(uid, pubkey, result)
1640*7c478bd9Sstevel@tonic-gate 	uid_t uid;
1641*7c478bd9Sstevel@tonic-gate 	keybuf pubkey;
1642*7c478bd9Sstevel@tonic-gate 	cryptkeyres *result;
1643*7c478bd9Sstevel@tonic-gate {
1644*7c478bd9Sstevel@tonic-gate 	char xsecret[1024];
1645*7c478bd9Sstevel@tonic-gate 	char xpublic[1024];
1646*7c478bd9Sstevel@tonic-gate 	MINT *public;
1647*7c478bd9Sstevel@tonic-gate 	MINT *secret;
1648*7c478bd9Sstevel@tonic-gate 	MINT *common;
1649*7c478bd9Sstevel@tonic-gate 	char zero[8];
1650*7c478bd9Sstevel@tonic-gate 	int hash;
1651*7c478bd9Sstevel@tonic-gate 
1652*7c478bd9Sstevel@tonic-gate 	if (!fetchsecretkey(uid, xsecret) || xsecret[0] == 0) {
1653*7c478bd9Sstevel@tonic-gate 		memset(zero, 0, sizeof (zero));
1654*7c478bd9Sstevel@tonic-gate 		if (nodefaultkeys)
1655*7c478bd9Sstevel@tonic-gate 			return (KEY_NOSECRET);
1656*7c478bd9Sstevel@tonic-gate 
1657*7c478bd9Sstevel@tonic-gate 		if (!getsecretkey("nobody", xsecret, zero) ||
1658*7c478bd9Sstevel@tonic-gate 			xsecret[0] == 0)
1659*7c478bd9Sstevel@tonic-gate 			return (KEY_NOSECRET);
1660*7c478bd9Sstevel@tonic-gate 	}
1661*7c478bd9Sstevel@tonic-gate 
1662*7c478bd9Sstevel@tonic-gate 	memcpy(xpublic, pubkey, sizeof (keybuf));
1663*7c478bd9Sstevel@tonic-gate 	xsecret[HEXKEYBYTES] = '\0';
1664*7c478bd9Sstevel@tonic-gate 	xpublic[HEXKEYBYTES] = '\0';
1665*7c478bd9Sstevel@tonic-gate 
1666*7c478bd9Sstevel@tonic-gate 	hash = hash_keys(xpublic, xsecret);
1667*7c478bd9Sstevel@tonic-gate 	(void) rw_rdlock(&g_cachedkeys_lock);
1668*7c478bd9Sstevel@tonic-gate 	if (!readcache(xpublic, xsecret, &result->cryptkeyres_u.deskey, hash)) {
1669*7c478bd9Sstevel@tonic-gate 		(void) rw_unlock(&g_cachedkeys_lock);
1670*7c478bd9Sstevel@tonic-gate 		(void) rw_wrlock(&g_cachedkeys_lock);
1671*7c478bd9Sstevel@tonic-gate 		if (!readcache(xpublic, xsecret, &result->cryptkeyres_u.deskey,
1672*7c478bd9Sstevel@tonic-gate 									hash)) {
1673*7c478bd9Sstevel@tonic-gate 			public = mp_xtom(xpublic);
1674*7c478bd9Sstevel@tonic-gate 			secret = mp_xtom(xsecret);
1675*7c478bd9Sstevel@tonic-gate 			/* Sanity Check on public and private keys */
1676*7c478bd9Sstevel@tonic-gate 			if (public == NULL || secret == NULL) {
1677*7c478bd9Sstevel@tonic-gate 				(void) rw_unlock(&g_cachedkeys_lock);
1678*7c478bd9Sstevel@tonic-gate 				return (KEY_SYSTEMERR);
1679*7c478bd9Sstevel@tonic-gate 			}
1680*7c478bd9Sstevel@tonic-gate 			common = mp_itom(0);
1681*7c478bd9Sstevel@tonic-gate 			mp_pow(public, secret, MODULUS, common);
1682*7c478bd9Sstevel@tonic-gate 			extractdeskey(common, &result->cryptkeyres_u.deskey);
1683*7c478bd9Sstevel@tonic-gate 			writecache(xpublic, xsecret,
1684*7c478bd9Sstevel@tonic-gate 					&result->cryptkeyres_u.deskey, hash);
1685*7c478bd9Sstevel@tonic-gate 			mp_mfree(secret);
1686*7c478bd9Sstevel@tonic-gate 			mp_mfree(public);
1687*7c478bd9Sstevel@tonic-gate 			mp_mfree(common);
1688*7c478bd9Sstevel@tonic-gate 		}
1689*7c478bd9Sstevel@tonic-gate 	}
1690*7c478bd9Sstevel@tonic-gate 	(void) rw_unlock(&g_cachedkeys_lock);
1691*7c478bd9Sstevel@tonic-gate 
1692*7c478bd9Sstevel@tonic-gate 	return (KEY_SUCCESS);
1693*7c478bd9Sstevel@tonic-gate }
1694*7c478bd9Sstevel@tonic-gate 
1695*7c478bd9Sstevel@tonic-gate #define	findsec(sec, list)	\
1696*7c478bd9Sstevel@tonic-gate 		(memcmp(sec, (list)->secret, sizeof (keybuf)) == 0)
1697*7c478bd9Sstevel@tonic-gate 
1698*7c478bd9Sstevel@tonic-gate /*
1699*7c478bd9Sstevel@tonic-gate  * Remove common keys from the cache.
1700*7c478bd9Sstevel@tonic-gate  */
1701*7c478bd9Sstevel@tonic-gate static
1702*7c478bd9Sstevel@tonic-gate removecache(sec)
1703*7c478bd9Sstevel@tonic-gate 	char *sec;
1704*7c478bd9Sstevel@tonic-gate {
1705*7c478bd9Sstevel@tonic-gate 	struct cachekey_list *found;
1706*7c478bd9Sstevel@tonic-gate 	register struct cachekey_list **l;
1707*7c478bd9Sstevel@tonic-gate 	int i;
1708*7c478bd9Sstevel@tonic-gate 
1709*7c478bd9Sstevel@tonic-gate 	(void) rw_wrlock(&g_cachedkeys_lock);
1710*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < KEY_HASH_SIZE; i++) {
1711*7c478bd9Sstevel@tonic-gate 		for (l = &g_cachedkeys[i]; (*l) != NULL; ) {
1712*7c478bd9Sstevel@tonic-gate 			if (findsec(sec, *l)) {
1713*7c478bd9Sstevel@tonic-gate 				found = *l;
1714*7c478bd9Sstevel@tonic-gate 				*l = (*l)->next;
1715*7c478bd9Sstevel@tonic-gate 				memset((char *)found, 0,
1716*7c478bd9Sstevel@tonic-gate 					sizeof (struct cachekey_list));
1717*7c478bd9Sstevel@tonic-gate 				free(found);
1718*7c478bd9Sstevel@tonic-gate 			} else {
1719*7c478bd9Sstevel@tonic-gate 				l = &(*l)->next;
1720*7c478bd9Sstevel@tonic-gate 			}
1721*7c478bd9Sstevel@tonic-gate 		}
1722*7c478bd9Sstevel@tonic-gate 	}
1723*7c478bd9Sstevel@tonic-gate 	(void) rw_unlock(&g_cachedkeys_lock);
1724*7c478bd9Sstevel@tonic-gate 	return (1);
1725*7c478bd9Sstevel@tonic-gate }
1726*7c478bd9Sstevel@tonic-gate 
1727*7c478bd9Sstevel@tonic-gate /*
1728*7c478bd9Sstevel@tonic-gate  * Store the secretkey for this uid
1729*7c478bd9Sstevel@tonic-gate  */
1730*7c478bd9Sstevel@tonic-gate storesecretkey(uid, key)
1731*7c478bd9Sstevel@tonic-gate 	uid_t uid;
1732*7c478bd9Sstevel@tonic-gate 	keybuf key;
1733*7c478bd9Sstevel@tonic-gate {
1734*7c478bd9Sstevel@tonic-gate 	struct secretkey_netname_list *new;
1735*7c478bd9Sstevel@tonic-gate 	struct secretkey_netname_list **l;
1736*7c478bd9Sstevel@tonic-gate 	int hash = HASH_UID(uid);
1737*7c478bd9Sstevel@tonic-gate 
1738*7c478bd9Sstevel@tonic-gate 	(void) rw_wrlock(&g_secretkey_netname_lock);
1739*7c478bd9Sstevel@tonic-gate 	for (l = &g_secretkey_netname[hash]; *l != NULL && (*l)->uid != uid;
1740*7c478bd9Sstevel@tonic-gate 			l = &(*l)->next) {
1741*7c478bd9Sstevel@tonic-gate 	}
1742*7c478bd9Sstevel@tonic-gate 	if (*l == NULL) {
1743*7c478bd9Sstevel@tonic-gate 		if (key[0] == '\0') {
1744*7c478bd9Sstevel@tonic-gate 			(void) rw_unlock(&g_secretkey_netname_lock);
1745*7c478bd9Sstevel@tonic-gate 			return (0);
1746*7c478bd9Sstevel@tonic-gate 		}
1747*7c478bd9Sstevel@tonic-gate 		new = (struct secretkey_netname_list *)malloc(sizeof (*new));
1748*7c478bd9Sstevel@tonic-gate 		if (new == NULL) {
1749*7c478bd9Sstevel@tonic-gate 			(void) rw_unlock(&g_secretkey_netname_lock);
1750*7c478bd9Sstevel@tonic-gate 			return (0);
1751*7c478bd9Sstevel@tonic-gate 		}
1752*7c478bd9Sstevel@tonic-gate 		new->uid = uid;
1753*7c478bd9Sstevel@tonic-gate 		new->sc_flag = KEY_ONLY;
1754*7c478bd9Sstevel@tonic-gate 		memset(new->keynetdata.st_pub_key, 0, HEXKEYBYTES);
1755*7c478bd9Sstevel@tonic-gate 		new->keynetdata.st_netname = NULL;
1756*7c478bd9Sstevel@tonic-gate 		new->next = NULL;
1757*7c478bd9Sstevel@tonic-gate 		*l = new;
1758*7c478bd9Sstevel@tonic-gate 	} else {
1759*7c478bd9Sstevel@tonic-gate 		new = *l;
1760*7c478bd9Sstevel@tonic-gate 		if (key[0] == '\0')
1761*7c478bd9Sstevel@tonic-gate 			removecache(new->keynetdata.st_priv_key);
1762*7c478bd9Sstevel@tonic-gate 	}
1763*7c478bd9Sstevel@tonic-gate 
1764*7c478bd9Sstevel@tonic-gate 	memcpy(new->keynetdata.st_priv_key, key,
1765*7c478bd9Sstevel@tonic-gate 		HEXKEYBYTES);
1766*7c478bd9Sstevel@tonic-gate 	(void) rw_unlock(&g_secretkey_netname_lock);
1767*7c478bd9Sstevel@tonic-gate 	return (1);
1768*7c478bd9Sstevel@tonic-gate }
1769*7c478bd9Sstevel@tonic-gate 
1770*7c478bd9Sstevel@tonic-gate static
1771*7c478bd9Sstevel@tonic-gate hexdigit(val)
1772*7c478bd9Sstevel@tonic-gate 	int val;
1773*7c478bd9Sstevel@tonic-gate {
1774*7c478bd9Sstevel@tonic-gate 	return ("0123456789abcdef"[val]);
1775*7c478bd9Sstevel@tonic-gate }
1776*7c478bd9Sstevel@tonic-gate 
1777*7c478bd9Sstevel@tonic-gate bin2hex(bin, hex, size)
1778*7c478bd9Sstevel@tonic-gate 	unsigned char *bin;
1779*7c478bd9Sstevel@tonic-gate 	unsigned char *hex;
1780*7c478bd9Sstevel@tonic-gate 	int size;
1781*7c478bd9Sstevel@tonic-gate {
1782*7c478bd9Sstevel@tonic-gate 	int i;
1783*7c478bd9Sstevel@tonic-gate 
1784*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < size; i++) {
1785*7c478bd9Sstevel@tonic-gate 		*hex++ = hexdigit(*bin >> 4);
1786*7c478bd9Sstevel@tonic-gate 		*hex++ = hexdigit(*bin++ & 0xf);
1787*7c478bd9Sstevel@tonic-gate 	}
1788*7c478bd9Sstevel@tonic-gate 	return (0);
1789*7c478bd9Sstevel@tonic-gate }
1790*7c478bd9Sstevel@tonic-gate 
1791*7c478bd9Sstevel@tonic-gate static
1792*7c478bd9Sstevel@tonic-gate hexval(dig)
1793*7c478bd9Sstevel@tonic-gate 	char dig;
1794*7c478bd9Sstevel@tonic-gate {
1795*7c478bd9Sstevel@tonic-gate 	if ('0' <= dig && dig <= '9') {
1796*7c478bd9Sstevel@tonic-gate 		return (dig - '0');
1797*7c478bd9Sstevel@tonic-gate 	} else if ('a' <= dig && dig <= 'f') {
1798*7c478bd9Sstevel@tonic-gate 		return (dig - 'a' + 10);
1799*7c478bd9Sstevel@tonic-gate 	} else if ('A' <= dig && dig <= 'F') {
1800*7c478bd9Sstevel@tonic-gate 		return (dig - 'A' + 10);
1801*7c478bd9Sstevel@tonic-gate 	} else {
1802*7c478bd9Sstevel@tonic-gate 		return (-1);
1803*7c478bd9Sstevel@tonic-gate 	}
1804*7c478bd9Sstevel@tonic-gate }
1805*7c478bd9Sstevel@tonic-gate 
1806*7c478bd9Sstevel@tonic-gate hex2bin(hex, bin, size)
1807*7c478bd9Sstevel@tonic-gate 	unsigned char *hex;
1808*7c478bd9Sstevel@tonic-gate 	unsigned char *bin;
1809*7c478bd9Sstevel@tonic-gate 	int size;
1810*7c478bd9Sstevel@tonic-gate {
1811*7c478bd9Sstevel@tonic-gate 	int i;
1812*7c478bd9Sstevel@tonic-gate 
1813*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < size; i++) {
1814*7c478bd9Sstevel@tonic-gate 		*bin = hexval(*hex++) << 4;
1815*7c478bd9Sstevel@tonic-gate 		*bin++ |= hexval(*hex++);
1816*7c478bd9Sstevel@tonic-gate 	}
1817*7c478bd9Sstevel@tonic-gate 	return (0);
1818*7c478bd9Sstevel@tonic-gate }
1819*7c478bd9Sstevel@tonic-gate 
1820*7c478bd9Sstevel@tonic-gate static int
1821*7c478bd9Sstevel@tonic-gate hash_keys(pub, sec)
1822*7c478bd9Sstevel@tonic-gate 	char *pub;
1823*7c478bd9Sstevel@tonic-gate 	char *sec;
1824*7c478bd9Sstevel@tonic-gate {
1825*7c478bd9Sstevel@tonic-gate 	int i;
1826*7c478bd9Sstevel@tonic-gate 	int hash = 0;
1827*7c478bd9Sstevel@tonic-gate 
1828*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < HEXKEYBYTES; i += 6, pub += 6, sec += 6) {
1829*7c478bd9Sstevel@tonic-gate 		hash ^= *pub;
1830*7c478bd9Sstevel@tonic-gate 		hash ^= *sec;
1831*7c478bd9Sstevel@tonic-gate 	}
1832*7c478bd9Sstevel@tonic-gate 	return (hash & 0xff);
1833*7c478bd9Sstevel@tonic-gate }
1834*7c478bd9Sstevel@tonic-gate 
1835*7c478bd9Sstevel@tonic-gate /*
1836*7c478bd9Sstevel@tonic-gate  * problem:  keyserv loads keys from /etc/.rootkey based on nisauthconf(1M)
1837*7c478bd9Sstevel@tonic-gate  *           which is too nis+-centric (see secure_rpc(3N)).
1838*7c478bd9Sstevel@tonic-gate  *
1839*7c478bd9Sstevel@tonic-gate  * So we want to make sure there is always a AUTH_DES compat entry
1840*7c478bd9Sstevel@tonic-gate  * in the "list" of nis+ mechs so that the 192bit key always gets loaded so
1841*7c478bd9Sstevel@tonic-gate  * non-nis+ services that use AUTH_DES (e.g. nfs) won't get hosed.  The real
1842*7c478bd9Sstevel@tonic-gate  * hacky part of it is we muck with the array returned from
1843*7c478bd9Sstevel@tonic-gate  * __nis_get_mechanisms which we really don't have any business
1844*7c478bd9Sstevel@tonic-gate  * doing cause we should not know/care how that is implemented.  A better
1845*7c478bd9Sstevel@tonic-gate  * way would be to change the __nis_get_mechanisms interface or add another
1846*7c478bd9Sstevel@tonic-gate  * one similiar to it that forces the "des" compat entry into the list.
1847*7c478bd9Sstevel@tonic-gate  *
1848*7c478bd9Sstevel@tonic-gate  * Return ptr to mechs array on success, else NULL on memory errs.
1849*7c478bd9Sstevel@tonic-gate  */
1850*7c478bd9Sstevel@tonic-gate mechanism_t **
1851*7c478bd9Sstevel@tonic-gate getmechwrap()
1852*7c478bd9Sstevel@tonic-gate {
1853*7c478bd9Sstevel@tonic-gate 	mechanism_t	**mechs = __nis_get_mechanisms(FALSE);
1854*7c478bd9Sstevel@tonic-gate 	mechanism_t	**mechsbak = NULL;
1855*7c478bd9Sstevel@tonic-gate 	mechanism_t	*desmech = NULL;
1856*7c478bd9Sstevel@tonic-gate 	int		i = 0;
1857*7c478bd9Sstevel@tonic-gate 
1858*7c478bd9Sstevel@tonic-gate 	if (mechs) {
1859*7c478bd9Sstevel@tonic-gate 		/* got some valid mechs and possibly the AUTH_DES compat one */
1860*7c478bd9Sstevel@tonic-gate 		for (i = 0; mechs[i]; i++) {
1861*7c478bd9Sstevel@tonic-gate 			if (AUTH_DES_COMPAT_CHK(mechs[i]))
1862*7c478bd9Sstevel@tonic-gate 				return (mechs);
1863*7c478bd9Sstevel@tonic-gate 		}
1864*7c478bd9Sstevel@tonic-gate 		/* i == number of ptrs not counting terminating NULL */
1865*7c478bd9Sstevel@tonic-gate 	}
1866*7c478bd9Sstevel@tonic-gate 
1867*7c478bd9Sstevel@tonic-gate 	/* AUTH_DES compat entry not found, let's add it */
1868*7c478bd9Sstevel@tonic-gate 	if ((desmech = malloc(sizeof (mechanism_t))) == NULL) {
1869*7c478bd9Sstevel@tonic-gate 		if (mechs)
1870*7c478bd9Sstevel@tonic-gate 			__nis_release_mechanisms(mechs);
1871*7c478bd9Sstevel@tonic-gate 		return (NULL);
1872*7c478bd9Sstevel@tonic-gate 	}
1873*7c478bd9Sstevel@tonic-gate 	desmech->mechname = NULL;
1874*7c478bd9Sstevel@tonic-gate 	desmech->alias = NIS_SEC_CF_DES_ALIAS;
1875*7c478bd9Sstevel@tonic-gate 	desmech->keylen = AUTH_DES_KEYLEN;
1876*7c478bd9Sstevel@tonic-gate 	desmech->algtype = AUTH_DES_ALGTYPE;
1877*7c478bd9Sstevel@tonic-gate 	desmech->qop = NULL;
1878*7c478bd9Sstevel@tonic-gate 	desmech->secserv = rpc_gss_svc_default;
1879*7c478bd9Sstevel@tonic-gate 
1880*7c478bd9Sstevel@tonic-gate 	mechsbak = mechs;
1881*7c478bd9Sstevel@tonic-gate 	/* mechs == NULL and i == 0 is valid "no mechs configed" case */
1882*7c478bd9Sstevel@tonic-gate 	if ((mechs = (mechanism_t **)realloc(mechs,
1883*7c478bd9Sstevel@tonic-gate 			sizeof (mechanism_t *) * (i + 2))) == NULL) {
1884*7c478bd9Sstevel@tonic-gate 		if (mechsbak)
1885*7c478bd9Sstevel@tonic-gate 			__nis_release_mechanisms(mechsbak);
1886*7c478bd9Sstevel@tonic-gate 		free(desmech);
1887*7c478bd9Sstevel@tonic-gate 		return (NULL);
1888*7c478bd9Sstevel@tonic-gate 	}
1889*7c478bd9Sstevel@tonic-gate 	mechs[i] = desmech;
1890*7c478bd9Sstevel@tonic-gate 	mechs[i+1] = NULL;
1891*7c478bd9Sstevel@tonic-gate 
1892*7c478bd9Sstevel@tonic-gate 	return (mechs);
1893*7c478bd9Sstevel@tonic-gate }
1894*7c478bd9Sstevel@tonic-gate 
1895*7c478bd9Sstevel@tonic-gate int
1896*7c478bd9Sstevel@tonic-gate init_mechs()
1897*7c478bd9Sstevel@tonic-gate {
1898*7c478bd9Sstevel@tonic-gate 	int nmechs, oldmechseen;
1899*7c478bd9Sstevel@tonic-gate 	mechanism_t **mechpp;
1900*7c478bd9Sstevel@tonic-gate 	char **cpp;
1901*7c478bd9Sstevel@tonic-gate 
1902*7c478bd9Sstevel@tonic-gate 	if (!(mechs = getmechwrap()))
1903*7c478bd9Sstevel@tonic-gate 		return (-1);
1904*7c478bd9Sstevel@tonic-gate 
1905*7c478bd9Sstevel@tonic-gate 	/*
1906*7c478bd9Sstevel@tonic-gate 	 * find how many mechanisms were specified and also
1907*7c478bd9Sstevel@tonic-gate 	 * setup the mechanism table for unique keylen/algtype pair
1908*7c478bd9Sstevel@tonic-gate 	 */
1909*7c478bd9Sstevel@tonic-gate 	nmechs = 0;
1910*7c478bd9Sstevel@tonic-gate 	for (mechpp = mechs; *mechpp != NULL; mechpp++) {
1911*7c478bd9Sstevel@tonic-gate 		struct keylenlist **kpp;
1912*7c478bd9Sstevel@tonic-gate 		struct algtypelist **app;
1913*7c478bd9Sstevel@tonic-gate 
1914*7c478bd9Sstevel@tonic-gate 		nmechs++;
1915*7c478bd9Sstevel@tonic-gate 		if (((*mechpp)->keylen < 0) || ((*mechpp)->algtype < 0)) {
1916*7c478bd9Sstevel@tonic-gate 			continue;
1917*7c478bd9Sstevel@tonic-gate 		}
1918*7c478bd9Sstevel@tonic-gate 		kpp = getkeylen((*mechpp)->keylen);
1919*7c478bd9Sstevel@tonic-gate 		appendkeylist(kpp, (*mechpp)->keylen);
1920*7c478bd9Sstevel@tonic-gate 		app = getalgtype(kpp, (*mechpp)->algtype);
1921*7c478bd9Sstevel@tonic-gate 		appendalgtype(app, (*mechpp)->algtype);
1922*7c478bd9Sstevel@tonic-gate 	}
1923*7c478bd9Sstevel@tonic-gate 
1924*7c478bd9Sstevel@tonic-gate 	/*
1925*7c478bd9Sstevel@tonic-gate 	 * set of mechs for getsubopt()
1926*7c478bd9Sstevel@tonic-gate 	 */
1927*7c478bd9Sstevel@tonic-gate 	cache_options = (char **)calloc((size_t)nmechs + 1,
1928*7c478bd9Sstevel@tonic-gate 	    sizeof (*cache_options));
1929*7c478bd9Sstevel@tonic-gate 	if (cache_options == NULL) {
1930*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "unable to allocate option array");
1931*7c478bd9Sstevel@tonic-gate 		return (-1);
1932*7c478bd9Sstevel@tonic-gate 	}
1933*7c478bd9Sstevel@tonic-gate 	/*
1934*7c478bd9Sstevel@tonic-gate 	 * cache sizes
1935*7c478bd9Sstevel@tonic-gate 	 */
1936*7c478bd9Sstevel@tonic-gate 	cache_size = (int *)calloc((size_t)nmechs, sizeof (int));
1937*7c478bd9Sstevel@tonic-gate 	if (cache_size == NULL) {
1938*7c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "unable to allocate cache array");
1939*7c478bd9Sstevel@tonic-gate 		return (-1);
1940*7c478bd9Sstevel@tonic-gate 	}
1941*7c478bd9Sstevel@tonic-gate 
1942*7c478bd9Sstevel@tonic-gate 	oldmechseen = 0;
1943*7c478bd9Sstevel@tonic-gate 	cpp = cache_options;
1944*7c478bd9Sstevel@tonic-gate 	for (mechpp = mechs; *mechpp != NULL; mechpp++) {
1945*7c478bd9Sstevel@tonic-gate 		/*
1946*7c478bd9Sstevel@tonic-gate 		 * usual case: a DH-style mechanism type, with an alias
1947*7c478bd9Sstevel@tonic-gate 		 */
1948*7c478bd9Sstevel@tonic-gate 		if ((*mechpp)->mechname != NULL &&
1949*7c478bd9Sstevel@tonic-gate 		    strncmp((*mechpp)->mechname, DHMECHSTR,
1950*7c478bd9Sstevel@tonic-gate 		    strlen(DHMECHSTR)) == 0 &&
1951*7c478bd9Sstevel@tonic-gate 		    (*mechpp)->alias != NULL) {
1952*7c478bd9Sstevel@tonic-gate 			/*
1953*7c478bd9Sstevel@tonic-gate 			 * Is this trad 192-DH? already added?
1954*7c478bd9Sstevel@tonic-gate 			 */
1955*7c478bd9Sstevel@tonic-gate 			if (strcmp((*mechpp)->alias, DESALIAS) == 0) {
1956*7c478bd9Sstevel@tonic-gate 				if (oldmechseen) {
1957*7c478bd9Sstevel@tonic-gate 					continue;
1958*7c478bd9Sstevel@tonic-gate 				}
1959*7c478bd9Sstevel@tonic-gate 				oldmechseen++;
1960*7c478bd9Sstevel@tonic-gate 			}
1961*7c478bd9Sstevel@tonic-gate 
1962*7c478bd9Sstevel@tonic-gate 			*cpp++ = (*mechpp)->alias;
1963*7c478bd9Sstevel@tonic-gate 			continue;
1964*7c478bd9Sstevel@tonic-gate 		}
1965*7c478bd9Sstevel@tonic-gate 
1966*7c478bd9Sstevel@tonic-gate 		/*
1967*7c478bd9Sstevel@tonic-gate 		 * HACK: we recognise a special alias for traditional
1968*7c478bd9Sstevel@tonic-gate 		 * 192-bit DH, unless the latter has already been mentioned
1969*7c478bd9Sstevel@tonic-gate 		 * in it's full form
1970*7c478bd9Sstevel@tonic-gate 		 */
1971*7c478bd9Sstevel@tonic-gate 		if ((*mechpp)->mechname == NULL && (*mechpp)->alias != NULL &&
1972*7c478bd9Sstevel@tonic-gate 		    strcmp((*mechpp)->alias, DES) == 0 && !oldmechseen) {
1973*7c478bd9Sstevel@tonic-gate 			*cpp++ = DESALIAS;
1974*7c478bd9Sstevel@tonic-gate 			oldmechseen++;
1975*7c478bd9Sstevel@tonic-gate 			continue;
1976*7c478bd9Sstevel@tonic-gate 		}
1977*7c478bd9Sstevel@tonic-gate 
1978*7c478bd9Sstevel@tonic-gate 		/*
1979*7c478bd9Sstevel@tonic-gate 		 * Ignore anything else
1980*7c478bd9Sstevel@tonic-gate 		 */
1981*7c478bd9Sstevel@tonic-gate 	}
1982*7c478bd9Sstevel@tonic-gate 
1983*7c478bd9Sstevel@tonic-gate 	/* Terminate the options list */
1984*7c478bd9Sstevel@tonic-gate 	*cpp = NULL;
1985*7c478bd9Sstevel@tonic-gate 
1986*7c478bd9Sstevel@tonic-gate 	return (0);
1987*7c478bd9Sstevel@tonic-gate }
1988