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