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 1998 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 #pragma ident "%Z%%M% %I% %E% SMI" 38 39 /* 40 * Do the real work of the keyserver. 41 * Store secret keys. Compute common keys, 42 * and use them to decrypt and encrypt DES keys. 43 * Cache the common keys, so the expensive computation is avoided. 44 */ 45 #include <stdio.h> 46 #include <stdlib.h> 47 #include <mp.h> 48 #include <rpc/rpc.h> 49 #include <rpc/key_prot.h> 50 #include <rpc/des_crypt.h> 51 #include <rpcsvc/nis_dhext.h> 52 #include <sys/errno.h> 53 #include <string.h> 54 #include <thread.h> 55 #include <syslog.h> 56 57 #include "debug.h" 58 #include "keyserv_cache.h" 59 60 extern char ROOTKEY[]; 61 extern mechanism_t **mechs; 62 extern char **cache_options; 63 extern int *cache_size; 64 extern int disk_caching; 65 66 static MINT *MODULUS; 67 static int hash_keys(); 68 static keystatus pk_crypt(); 69 static keystatus pk_crypt3(); 70 static int nodefaultkeys = 0; 71 72 #define DES "des" 73 #define DESALIAS "dh192-0" 74 #define DHMECHSTR "diffie_hellman" 75 #define CLASSIC_PK_DH(k, a) (((k) == 192) && ((a) == 0)) 76 77 /* 78 * Exponential caching management 79 */ 80 struct cachekey_list { 81 keybuf secret; 82 keybuf public; 83 des_block deskey; 84 struct cachekey_list *next; 85 }; 86 #define KEY_HASH_SIZE 256 87 static struct cachekey_list *g_cachedkeys[KEY_HASH_SIZE]; 88 static rwlock_t g_cachedkeys_lock = DEFAULTRWLOCK; 89 90 #ifdef DEBUG 91 int 92 test_debug(debug_level level, char *file, int line) 93 { 94 if (level < debugging) 95 return (0); 96 fprintf(stderr, "file %s,\tline %d :\t", file, line); 97 return (1); 98 } 99 100 int 101 real_debug(char *fmt, ...) 102 { 103 va_list args; 104 105 va_start(args, fmt); 106 (void) vfprintf(stderr, fmt, args); 107 va_end(args); 108 fprintf(stderr, "\n"); 109 fflush(stderr); 110 return (1); 111 } 112 #endif /* DEBUG */ 113 114 struct cacheuid_list { 115 uid_t uid; 116 int refcnt; 117 keybuf3 *secretkey; 118 keybuf3 *publickey; 119 netnamestr netname; 120 des_block key; 121 struct cacheuid_list *next; 122 }; 123 124 #define NUMHASHBUCKETS 256 125 #define HASH_UID(x) (x & 0xff) 126 127 struct mechdata { 128 struct cacheuid_list *bucket[NUMHASHBUCKETS]; 129 }; 130 131 struct psdata { 132 struct cachekey3_list *common[NUMHASHBUCKETS]; 133 }; 134 135 struct mechentry { 136 mutex_t mech_lock; 137 struct mechdata *mechdata; 138 mutex_t ps_lock; 139 struct psdata *psdata; 140 }; 141 142 /* 143 * we don't need to worry about locking for the keylen + algtype 144 * sparse array because it is created once and for all during 145 * initialization when there are no threads. The mechentry field 146 * and everything underneath it needs protection and this is what 147 * the *_lock fields are for. 148 */ 149 struct algtypelist { 150 algtype_t algtype; 151 struct algtypelist *next; 152 struct mechentry mech; 153 }; 154 155 struct keylenlist { 156 keylen_t keylen; 157 struct algtypelist *ap; 158 struct keylenlist *next; 159 }; 160 161 #define KEYSERV_VERSION "1.0" 162 163 static struct mechtable { 164 char *version; 165 struct keylenlist *kp; 166 } mechtable = {KEYSERV_VERSION, NULL}; 167 168 static struct keylenlist ** 169 getkeylen(keylen_t k) 170 { 171 struct keylenlist **kpp; 172 173 debug(KEYSERV_DEBUG1, ("getkeylen key: %d", k)); 174 for (kpp = &mechtable.kp; 175 *kpp != NULL && (*kpp)->keylen != k; 176 kpp = &(*kpp)->next) 177 debug(KEYSERV_DEBUG0, ("getkeylen failed %x", kpp)); 178 debug(KEYSERV_DEBUG0, ("getkeylen return: %x", kpp)); 179 return (kpp); 180 } 181 182 static void 183 appendkeylist(struct keylenlist **kpp, keylen_t k) 184 { 185 struct keylenlist *kp; 186 187 if (*kpp == NULL) { 188 kp = (struct keylenlist *)malloc(sizeof (*kp)); 189 if (kp == NULL) { 190 debug(KEYSERV_INFO, ("appendkeylist : malloc failed")); 191 return; 192 } 193 debug(KEYSERV_DEBUG, ("appendkeylist : %x %x %d", kpp, kp, k)); 194 kp->keylen = k; 195 kp->ap = NULL; 196 kp->next = NULL; 197 *kpp = kp; 198 } else { 199 /*EMPTY*/ 200 /* do nothing; only happens for multiple algtypes */ 201 debug(KEYSERV_DEBUG0, 202 ("appendkeylist called for non tail element")); 203 } 204 } 205 206 static struct algtypelist ** 207 getalgtype(struct keylenlist **kpp, algtype_t a) 208 { 209 struct algtypelist **app; 210 211 debug(KEYSERV_DEBUG1, ("getalgtype key: %d", a)); 212 for (app = &(*kpp)->ap; 213 *app != NULL && (*app)->algtype != a; 214 app = &(*app)->next) 215 debug(KEYSERV_DEBUG0, ("getalgtype key: %x", app)); 216 debug(KEYSERV_DEBUG0, ("getalgtype return: %x", app)); 217 return (app); 218 } 219 220 static void 221 appendalgtype(struct algtypelist **app, algtype_t a) 222 { 223 struct algtypelist *ap; 224 225 if (*app == NULL) { 226 ap = (struct algtypelist *)malloc(sizeof (*ap)); 227 if (ap == NULL) { 228 debug(KEYSERV_INFO, ("appendalgtype : malloc failed")); 229 return; 230 } 231 debug(KEYSERV_DEBUG, ("appendalgtype : %x %x %d", app, ap, a)); 232 ap->algtype = a; 233 mutex_init(&ap->mech.mech_lock, USYNC_THREAD, NULL); 234 mutex_init(&ap->mech.ps_lock, USYNC_THREAD, NULL); 235 ap->mech.mechdata = NULL; 236 ap->mech.psdata = NULL; 237 ap->next = NULL; 238 *app = ap; 239 } else { 240 /*EMPTY*/ 241 /* don't mind duplicate (keylen,algtype) paris for now. */ 242 debug(KEYSERV_DEBUG0, 243 ("appendalgtype called for non tail element")); 244 } 245 } 246 247 static struct mechentry * 248 getmechtype(keylen_t k, algtype_t a) 249 { 250 struct keylenlist **kpp; 251 struct algtypelist **app; 252 253 debug(KEYSERV_DEBUG1, ("getmechtype %d %d", k, a)); 254 kpp = getkeylen(k); 255 if (*kpp == NULL) { 256 debug(KEYSERV_DEBUG0, ("getmechtype %d not found in keys", k)); 257 return (0); 258 } 259 app = getalgtype(kpp, a); 260 if (*app == NULL) { 261 debug(KEYSERV_DEBUG0, ("getmechtype %d not found in algs", a)); 262 return (0); 263 } 264 debug(KEYSERV_DEBUG0, ("getmechtype found %x", app)); 265 debug(KEYSERV_DEBUG0, ("getmechtype return %x", &(*app)->mech)); 266 return (&(*app)->mech); 267 } 268 269 static keybuf3 * 270 getkeybuf3(int k) 271 { 272 keybuf3 *buf; 273 274 debug(KEYSERV_DEBUG, ("getkeybuf3 malloc %d", k)); 275 buf = (keybuf3 *) malloc(sizeof (*buf)); 276 if (buf == NULL) { 277 debug(KEYSERV_DEBUG, ("getkeybuf3 malloc failed")); 278 syslog(LOG_ERR, "file %s line %d: malloc failed", 279 __FILE__, __LINE__); 280 return (NULL); 281 } 282 buf->keybuf3_len = k; 283 /* XXX special case k==0 */ 284 if (k == 0) { 285 buf->keybuf3_val = NULL; 286 } else { 287 buf->keybuf3_val = (char *)malloc(k); 288 if (buf->keybuf3_val == NULL) { 289 debug(KEYSERV_DEBUG, ("getkeybuf3 malloc failed")); 290 free(buf); 291 syslog(LOG_ERR, "file %s line %d: malloc failed", 292 __FILE__, __LINE__); 293 return (NULL); 294 } 295 } 296 debug(KEYSERV_DEBUG1, ("getkeybuf3 ret %x", buf)); 297 return (buf); 298 } 299 300 static void 301 freekeybuf3(keybuf3 *kp) 302 { 303 debug(KEYSERV_DEBUG1, ("freekeybuf3 %x", kp)); 304 if (kp == NULL) 305 return; 306 if (kp->keybuf3_val) { 307 /* XXX kp->keybuf3_len != 0? */ 308 free(kp->keybuf3_val); 309 } 310 free(kp); 311 } 312 313 static keybuf3 * 314 cpykeybuf3(keybuf3 *src) 315 { 316 keybuf3 *dst; 317 318 if (src == NULL) { 319 return (NULL); 320 } 321 if ((dst = getkeybuf3(src->keybuf3_len)) == NULL) { 322 return (NULL); 323 } 324 memcpy(dst->keybuf3_val, src->keybuf3_val, src->keybuf3_len); 325 debug(KEYSERV_DEBUG0, ("cpykeybuf3 ret %x", dst)); 326 return (dst); 327 } 328 329 static keybuf3 * 330 setkeybuf3(char *src, int len) 331 { 332 keybuf3 *dst; 333 334 if ((dst = getkeybuf3(++len)) == NULL) { 335 return (NULL); 336 } 337 memcpy(dst->keybuf3_val, src, len); 338 return (dst); 339 } 340 341 static int 342 cmpkeybuf3(keybuf3 *k1, keybuf3 *k2) 343 { 344 if ((k1 == NULL) || (k2 == NULL)) { 345 syslog(LOG_ERR, "cmpkeybuf3: invalid parameter: %x, %x", 346 k1, k2); 347 return (0); 348 } 349 if (k1->keybuf3_len != k2->keybuf3_len) { 350 return (0); 351 } 352 return (!memcmp(k1->keybuf3_val, k2->keybuf3_val, k1->keybuf3_len)); 353 } 354 355 static int 356 storekeybuf3(keybuf3 *dst, keybuf3 *src) 357 { 358 keybuf3 *tmp; 359 360 if ((tmp = cpykeybuf3(src)) == NULL) { 361 return (0); 362 } 363 *dst = *tmp; 364 free(tmp); /* but not the contents */ 365 debug(KEYSERV_DEBUG0, ("storekeybuf3 ret %d %x", 366 dst->keybuf3_len, dst->keybuf3_val)); 367 return (1); 368 } 369 370 static deskeyarray * 371 getdeskeyarray(int k) 372 { 373 deskeyarray *buf; 374 375 debug(KEYSERV_DEBUG, ("getdeskeyarray malloc %d", k)); 376 buf = (deskeyarray *) malloc(sizeof (*buf)); 377 if (buf == NULL) { 378 debug(KEYSERV_DEBUG, ("getdeskeyarray malloc failed")); 379 syslog(LOG_ERR, "file %s line %d: malloc failed", 380 __FILE__, __LINE__); 381 return (NULL); 382 } 383 buf->deskeyarray_len = k; 384 /* XXX special case k==0 */ 385 if (k == 0) { 386 buf->deskeyarray_val = NULL; 387 } else { 388 buf->deskeyarray_val = (des_block *) 389 malloc(k * sizeof (des_block)); 390 if (buf->deskeyarray_val == NULL) { 391 debug(KEYSERV_DEBUG, ("getdeskeyarray malloc failed")); 392 free(buf); 393 syslog(LOG_ERR, "file %s line %d: malloc failed", 394 __FILE__, __LINE__); 395 return (NULL); 396 } 397 } 398 debug(KEYSERV_DEBUG1, ("getdeskeyarray ret %x", buf)); 399 return (buf); 400 } 401 402 static deskeyarray * 403 cpydeskeyarray(deskeyarray *src) 404 { 405 deskeyarray *dst; 406 407 if (src == NULL) { 408 return (NULL); 409 } 410 if ((dst = getdeskeyarray(src->deskeyarray_len)) == NULL) { 411 return (NULL); 412 } 413 memcpy(dst->deskeyarray_val, src->deskeyarray_val, 414 src->deskeyarray_len * sizeof (des_block)); 415 debug(KEYSERV_DEBUG0, ("cpydeskeyarray ret %x", dst)); 416 return (dst); 417 } 418 419 static int 420 storedeskeyarray(deskeyarray *dst, deskeyarray *src) 421 { 422 deskeyarray *tmp; 423 424 if ((tmp = cpydeskeyarray(src)) == NULL) { 425 return (0); 426 } 427 *dst = *tmp; 428 free(tmp); /* but not the contents */ 429 debug(KEYSERV_DEBUG0, ("storedeskeyarray ret %d %x", 430 dst->deskeyarray_len, dst->deskeyarray_val)); 431 return (1); 432 } 433 434 int 435 setdeskeyarray(deskeyarray *dst, int k) 436 { 437 deskeyarray *tmp; 438 439 if ((tmp = getdeskeyarray(k)) == NULL) { 440 return (0); 441 } 442 *dst = *tmp; 443 free(tmp); /* but not the contents */ 444 debug(KEYSERV_DEBUG0, ("setdeskeyarray ret %d %x", 445 dst->deskeyarray_len, dst->deskeyarray_val)); 446 return (1); 447 } 448 449 static int 450 cachehit3(keybuf3 *public, keybuf3 *secret, struct cachekey3_list *cp) 451 { 452 return (cmpkeybuf3(public, cp->public) && 453 cmpkeybuf3(secret, cp->secret)); 454 } 455 456 static struct cacheuid_list ** 457 mapuid2cache(uid_t uid, struct mechdata *mdp) 458 { 459 struct cacheuid_list **cpp; 460 int hash = HASH_UID(uid); 461 462 debug(KEYSERV_DEBUG, ("mapuid2cache %d %d %x", uid, hash, mdp)); 463 for (cpp = &mdp->bucket[hash]; 464 *cpp != NULL && (*cpp)->uid != uid; 465 cpp = &(*cpp)->next) { 466 debug(KEYSERV_DEBUG0, ("mapuid2cache %x", cpp)); 467 } 468 debug(KEYSERV_DEBUG, ("mapuid2cache ret %x", cpp)); 469 return (cpp); 470 } 471 472 static int 473 appendsecretkey3(struct mechentry *mp, uid_t uid, setkeyarg3 *skey) 474 { 475 struct mechdata *mdp; 476 struct cacheuid_list **cpp, *cp; 477 keybuf3 nullkey = {0, NULL}; 478 479 debug(KEYSERV_DEBUG, ("appendsecretkey3 %x", mp)); 480 if ((skey == NULL) || (mp == NULL)) { 481 return (0); 482 } 483 if (skey->key.keybuf3_len == 0) { 484 return (0); 485 } 486 mutex_lock(&mp->mech_lock); 487 if ((mdp = mp->mechdata) == NULL) { 488 mdp = (struct mechdata *)calloc(1, sizeof (*mdp)); 489 if (mdp == NULL) { 490 mutex_unlock(&mp->mech_lock); 491 debug(KEYSERV_INFO, 492 ("appendsecretkey3 : calloc failed")); 493 return (0); 494 } 495 mp->mechdata = mdp; 496 } 497 cpp = mapuid2cache(uid, mdp); 498 if (*cpp == NULL) { 499 cp = (struct cacheuid_list *)malloc(sizeof (*cp)); 500 if (cp == NULL) { 501 mutex_unlock(&mp->mech_lock); 502 debug(KEYSERV_INFO, 503 ("appendsecretkey3 : malloc failed")); 504 syslog(LOG_ERR, "file %s line %d: malloc failed", 505 __FILE__, __LINE__); 506 return (0); 507 } 508 memset(cp, 0, sizeof (*cp)); 509 cp->uid = uid; 510 *cpp = cp; 511 } else { 512 cp = *cpp; 513 } 514 freekeybuf3(cp->secretkey); 515 if ((cp->secretkey = cpykeybuf3(&skey->key)) == NULL) { 516 mutex_unlock(&mp->mech_lock); 517 return (0); 518 } 519 freekeybuf3(cp->publickey); 520 if ((cp->publickey = cpykeybuf3(&nullkey)) == NULL) { 521 mutex_unlock(&mp->mech_lock); 522 return (0); 523 } 524 mutex_unlock(&mp->mech_lock); 525 return (1); 526 } 527 528 /* 529 * Store the vers 3 secretkey for this uid 530 */ 531 static int 532 storesecretkey3(uid_t uid, setkeyarg3 *skey) 533 { 534 struct mechentry *mp; 535 536 if (skey == NULL) { 537 return (0); 538 } 539 if ((mp = getmechtype(skey->keylen, skey->algtype)) == NULL) { 540 return (0); 541 } 542 return (appendsecretkey3(mp, uid, skey)); 543 } 544 545 /* 546 * Set the vers 3 secretkey key for this uid 547 */ 548 keystatus 549 pk_setkey3(uid_t uid, setkeyarg3 *skey) 550 { 551 if (!storesecretkey3(uid, skey)) { 552 return (KEY_SYSTEMERR); 553 } 554 return (KEY_SUCCESS); 555 } 556 557 /* 558 * Set the secretkey key for this uid 559 */ 560 keystatus 561 pk_setkey(uid, skey) 562 uid_t uid; 563 keybuf skey; 564 { 565 int storesecretkey(uid_t, keybuf); 566 567 if (!storesecretkey(uid, skey)) { 568 return (KEY_SYSTEMERR); 569 } 570 return (KEY_SUCCESS); 571 } 572 573 int 574 storeotherrootkeys(FILE *fp, char *netname, char *passwd, char *osecret) 575 { 576 des_block master; 577 struct keylenlist *kp; 578 struct algtypelist *ap; 579 keybuf3 *secret; 580 setkeyarg3 skey; 581 582 debug(KEYSERV_DEBUG, ("storeotherrootkeys %s %s", 583 netname, passwd)); 584 passwd2des_g(passwd, netname, strlen(netname), &master, FALSE); 585 for (kp = mechtable.kp; kp != NULL; kp = kp->next) { 586 debug(KEYSERV_DEBUG0, 587 ("storeotherrootkeys key %d", kp->keylen)); 588 for (ap = kp->ap; ap != NULL; ap = ap->next) { 589 debug(KEYSERV_DEBUG, 590 ("storeotherrootkeys alg: %d", ap->algtype)); 591 if ((secret = getkeybuf3(kp->keylen/4+1)) == NULL) { 592 return (0); 593 } 594 debug(KEYSERV_DEBUG, 595 ("storeotherrootkeys calling getsecretkey_g")); 596 if (!getsecretkey_g(netname, 597 kp->keylen, ap->algtype, 598 secret->keybuf3_val, secret->keybuf3_len, 599 passwd)) { 600 debug(KEYSERV_INFO, 601 ("Can't find %s's secret key", netname)); 602 return (0); 603 } 604 if (*secret->keybuf3_val == 0) { /* XXX */ 605 debug(KEYSERV_INFO, 606 ("Password does not decrypt secret key for %s", 607 netname)); 608 return (0); 609 } 610 skey.key = *secret; 611 free(secret); /* but not the buffer it points to */ 612 skey.userkey = master; 613 skey.keylen = kp->keylen; 614 skey.algtype = ap->algtype; 615 if (CLASSIC_PK_DH(kp->keylen, ap->algtype)) { 616 pk_setkey((uid_t)0, osecret); 617 fprintf(fp, "%s\n", osecret); 618 } 619 if (pk_setkey3(0, &skey) != KEY_SUCCESS) { 620 return (0); 621 } 622 if (!CLASSIC_PK_DH(kp->keylen, ap->algtype)) { 623 fprintf(fp, "%s %d\n", skey.key.keybuf3_val, 624 ap->algtype); 625 } 626 } 627 } 628 return (1); 629 } 630 631 /* 632 * prohibit the nobody key on this machine k (the -d flag) 633 */ 634 pk_nodefaultkeys() 635 { 636 nodefaultkeys = 1; 637 return (0); 638 } 639 640 static void 641 freedisklist(struct cacheuid_list *cp) 642 { 643 if (cp == NULL) { 644 return; 645 } 646 free(cp->netname); /* ok even if this is NULL */ 647 freekeybuf3(cp->secretkey); 648 freekeybuf3(cp->publickey); 649 } 650 651 keystatus 652 pk_clear3(uid_t uid) 653 { 654 struct keylenlist *kp; 655 struct algtypelist *ap; 656 struct mechdata *mdp; 657 struct cacheuid_list **cpp, *cp; 658 659 debug(KEYSERV_DEBUG, ("pk_clear3 %d", uid)); 660 for (kp = mechtable.kp; kp != NULL; kp = kp->next) { 661 debug(KEYSERV_DEBUG0, ("pk_clear3 key %d", kp->keylen)); 662 for (ap = kp->ap; ap != NULL; ap = ap->next) { 663 debug(KEYSERV_DEBUG0, 664 ("pk_clear3 alg: %d", ap->algtype)); 665 mutex_lock(&ap->mech.mech_lock); 666 if ((mdp = ap->mech.mechdata) == NULL) { 667 mutex_unlock(&ap->mech.mech_lock); 668 continue; 669 } 670 cpp = mapuid2cache(uid, mdp); 671 if (*cpp == NULL) { 672 mutex_unlock(&ap->mech.mech_lock); 673 continue; 674 } 675 cp = (*cpp)->next; 676 freedisklist(*cpp); 677 *cpp = cp; 678 mutex_unlock(&ap->mech.mech_lock); 679 } 680 } 681 /* XXX clear stuff out of the common key cache as well? */ 682 /* XXX return success only if something was removed? */ 683 return (KEY_SUCCESS); 684 } 685 686 /* 687 * Set the modulus for all our Diffie-Hellman operations 688 */ 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 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 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 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 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 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 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 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 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 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 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 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 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 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 * 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 * 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 * 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 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 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 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 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 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 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 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 * 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 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 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 ** 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 * 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 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 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 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 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 storesecretkey(uid, key) 1731 uid_t uid; 1732 keybuf key; 1733 { 1734 struct secretkey_netname_list *new; 1735 struct secretkey_netname_list **l; 1736 int hash = HASH_UID(uid); 1737 1738 (void) rw_wrlock(&g_secretkey_netname_lock); 1739 for (l = &g_secretkey_netname[hash]; *l != NULL && (*l)->uid != uid; 1740 l = &(*l)->next) { 1741 } 1742 if (*l == NULL) { 1743 if (key[0] == '\0') { 1744 (void) rw_unlock(&g_secretkey_netname_lock); 1745 return (0); 1746 } 1747 new = (struct secretkey_netname_list *)malloc(sizeof (*new)); 1748 if (new == NULL) { 1749 (void) rw_unlock(&g_secretkey_netname_lock); 1750 return (0); 1751 } 1752 new->uid = uid; 1753 new->sc_flag = KEY_ONLY; 1754 memset(new->keynetdata.st_pub_key, 0, HEXKEYBYTES); 1755 new->keynetdata.st_netname = NULL; 1756 new->next = NULL; 1757 *l = new; 1758 } else { 1759 new = *l; 1760 if (key[0] == '\0') 1761 removecache(new->keynetdata.st_priv_key); 1762 } 1763 1764 memcpy(new->keynetdata.st_priv_key, key, 1765 HEXKEYBYTES); 1766 (void) rw_unlock(&g_secretkey_netname_lock); 1767 return (1); 1768 } 1769 1770 static 1771 hexdigit(val) 1772 int val; 1773 { 1774 return ("0123456789abcdef"[val]); 1775 } 1776 1777 bin2hex(bin, hex, size) 1778 unsigned char *bin; 1779 unsigned char *hex; 1780 int size; 1781 { 1782 int i; 1783 1784 for (i = 0; i < size; i++) { 1785 *hex++ = hexdigit(*bin >> 4); 1786 *hex++ = hexdigit(*bin++ & 0xf); 1787 } 1788 return (0); 1789 } 1790 1791 static 1792 hexval(dig) 1793 char dig; 1794 { 1795 if ('0' <= dig && dig <= '9') { 1796 return (dig - '0'); 1797 } else if ('a' <= dig && dig <= 'f') { 1798 return (dig - 'a' + 10); 1799 } else if ('A' <= dig && dig <= 'F') { 1800 return (dig - 'A' + 10); 1801 } else { 1802 return (-1); 1803 } 1804 } 1805 1806 hex2bin(hex, bin, size) 1807 unsigned char *hex; 1808 unsigned char *bin; 1809 int size; 1810 { 1811 int i; 1812 1813 for (i = 0; i < size; i++) { 1814 *bin = hexval(*hex++) << 4; 1815 *bin++ |= hexval(*hex++); 1816 } 1817 return (0); 1818 } 1819 1820 static int 1821 hash_keys(pub, sec) 1822 char *pub; 1823 char *sec; 1824 { 1825 int i; 1826 int hash = 0; 1827 1828 for (i = 0; i < HEXKEYBYTES; i += 6, pub += 6, sec += 6) { 1829 hash ^= *pub; 1830 hash ^= *sec; 1831 } 1832 return (hash & 0xff); 1833 } 1834 1835 /* 1836 * problem: keyserv loads keys from /etc/.rootkey based on nisauthconf(1M) 1837 * which is too nis+-centric (see secure_rpc(3N)). 1838 * 1839 * So we want to make sure there is always a AUTH_DES compat entry 1840 * in the "list" of nis+ mechs so that the 192bit key always gets loaded so 1841 * non-nis+ services that use AUTH_DES (e.g. nfs) won't get hosed. The real 1842 * hacky part of it is we muck with the array returned from 1843 * __nis_get_mechanisms which we really don't have any business 1844 * doing cause we should not know/care how that is implemented. A better 1845 * way would be to change the __nis_get_mechanisms interface or add another 1846 * one similiar to it that forces the "des" compat entry into the list. 1847 * 1848 * Return ptr to mechs array on success, else NULL on memory errs. 1849 */ 1850 mechanism_t ** 1851 getmechwrap() 1852 { 1853 mechanism_t **mechs = __nis_get_mechanisms(FALSE); 1854 mechanism_t **mechsbak = NULL; 1855 mechanism_t *desmech = NULL; 1856 int i = 0; 1857 1858 if (mechs) { 1859 /* got some valid mechs and possibly the AUTH_DES compat one */ 1860 for (i = 0; mechs[i]; i++) { 1861 if (AUTH_DES_COMPAT_CHK(mechs[i])) 1862 return (mechs); 1863 } 1864 /* i == number of ptrs not counting terminating NULL */ 1865 } 1866 1867 /* AUTH_DES compat entry not found, let's add it */ 1868 if ((desmech = malloc(sizeof (mechanism_t))) == NULL) { 1869 if (mechs) 1870 __nis_release_mechanisms(mechs); 1871 return (NULL); 1872 } 1873 desmech->mechname = NULL; 1874 desmech->alias = NIS_SEC_CF_DES_ALIAS; 1875 desmech->keylen = AUTH_DES_KEYLEN; 1876 desmech->algtype = AUTH_DES_ALGTYPE; 1877 desmech->qop = NULL; 1878 desmech->secserv = rpc_gss_svc_default; 1879 1880 mechsbak = mechs; 1881 /* mechs == NULL and i == 0 is valid "no mechs configed" case */ 1882 if ((mechs = (mechanism_t **)realloc(mechs, 1883 sizeof (mechanism_t *) * (i + 2))) == NULL) { 1884 if (mechsbak) 1885 __nis_release_mechanisms(mechsbak); 1886 free(desmech); 1887 return (NULL); 1888 } 1889 mechs[i] = desmech; 1890 mechs[i+1] = NULL; 1891 1892 return (mechs); 1893 } 1894 1895 int 1896 init_mechs() 1897 { 1898 int nmechs, oldmechseen; 1899 mechanism_t **mechpp; 1900 char **cpp; 1901 1902 if (!(mechs = getmechwrap())) 1903 return (-1); 1904 1905 /* 1906 * find how many mechanisms were specified and also 1907 * setup the mechanism table for unique keylen/algtype pair 1908 */ 1909 nmechs = 0; 1910 for (mechpp = mechs; *mechpp != NULL; mechpp++) { 1911 struct keylenlist **kpp; 1912 struct algtypelist **app; 1913 1914 nmechs++; 1915 if (((*mechpp)->keylen < 0) || ((*mechpp)->algtype < 0)) { 1916 continue; 1917 } 1918 kpp = getkeylen((*mechpp)->keylen); 1919 appendkeylist(kpp, (*mechpp)->keylen); 1920 app = getalgtype(kpp, (*mechpp)->algtype); 1921 appendalgtype(app, (*mechpp)->algtype); 1922 } 1923 1924 /* 1925 * set of mechs for getsubopt() 1926 */ 1927 cache_options = (char **)calloc((size_t)nmechs + 1, 1928 sizeof (*cache_options)); 1929 if (cache_options == NULL) { 1930 (void) fprintf(stderr, "unable to allocate option array"); 1931 return (-1); 1932 } 1933 /* 1934 * cache sizes 1935 */ 1936 cache_size = (int *)calloc((size_t)nmechs, sizeof (int)); 1937 if (cache_size == NULL) { 1938 (void) fprintf(stderr, "unable to allocate cache array"); 1939 return (-1); 1940 } 1941 1942 oldmechseen = 0; 1943 cpp = cache_options; 1944 for (mechpp = mechs; *mechpp != NULL; mechpp++) { 1945 /* 1946 * usual case: a DH-style mechanism type, with an alias 1947 */ 1948 if ((*mechpp)->mechname != NULL && 1949 strncmp((*mechpp)->mechname, DHMECHSTR, 1950 strlen(DHMECHSTR)) == 0 && 1951 (*mechpp)->alias != NULL) { 1952 /* 1953 * Is this trad 192-DH? already added? 1954 */ 1955 if (strcmp((*mechpp)->alias, DESALIAS) == 0) { 1956 if (oldmechseen) { 1957 continue; 1958 } 1959 oldmechseen++; 1960 } 1961 1962 *cpp++ = (*mechpp)->alias; 1963 continue; 1964 } 1965 1966 /* 1967 * HACK: we recognise a special alias for traditional 1968 * 192-bit DH, unless the latter has already been mentioned 1969 * in it's full form 1970 */ 1971 if ((*mechpp)->mechname == NULL && (*mechpp)->alias != NULL && 1972 strcmp((*mechpp)->alias, DES) == 0 && !oldmechseen) { 1973 *cpp++ = DESALIAS; 1974 oldmechseen++; 1975 continue; 1976 } 1977 1978 /* 1979 * Ignore anything else 1980 */ 1981 } 1982 1983 /* Terminate the options list */ 1984 *cpp = NULL; 1985 1986 return (0); 1987 } 1988