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 #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 int 635 pk_nodefaultkeys() 636 { 637 nodefaultkeys = 1; 638 return (0); 639 } 640 641 static void 642 freedisklist(struct cacheuid_list *cp) 643 { 644 if (cp == NULL) { 645 return; 646 } 647 free(cp->netname); /* ok even if this is NULL */ 648 freekeybuf3(cp->secretkey); 649 freekeybuf3(cp->publickey); 650 } 651 652 keystatus 653 pk_clear3(uid_t uid) 654 { 655 struct keylenlist *kp; 656 struct algtypelist *ap; 657 struct mechdata *mdp; 658 struct cacheuid_list **cpp, *cp; 659 660 debug(KEYSERV_DEBUG, ("pk_clear3 %d", uid)); 661 for (kp = mechtable.kp; kp != NULL; kp = kp->next) { 662 debug(KEYSERV_DEBUG0, ("pk_clear3 key %d", kp->keylen)); 663 for (ap = kp->ap; ap != NULL; ap = ap->next) { 664 debug(KEYSERV_DEBUG0, 665 ("pk_clear3 alg: %d", ap->algtype)); 666 mutex_lock(&ap->mech.mech_lock); 667 if ((mdp = ap->mech.mechdata) == NULL) { 668 mutex_unlock(&ap->mech.mech_lock); 669 continue; 670 } 671 cpp = mapuid2cache(uid, mdp); 672 if (*cpp == NULL) { 673 mutex_unlock(&ap->mech.mech_lock); 674 continue; 675 } 676 cp = (*cpp)->next; 677 freedisklist(*cpp); 678 *cpp = cp; 679 mutex_unlock(&ap->mech.mech_lock); 680 } 681 } 682 /* XXX clear stuff out of the common key cache as well? */ 683 /* XXX return success only if something was removed? */ 684 return (KEY_SUCCESS); 685 } 686 687 /* 688 * Set the modulus for all our Diffie-Hellman operations 689 */ 690 int 691 setmodulus(modx) 692 char *modx; 693 { 694 MODULUS = mp_xtom(modx); 695 return (0); 696 } 697 698 /* 699 * Encrypt the key using the public key associated with remote_name and the 700 * secret key associated with uid. 701 */ 702 keystatus 703 pk_encrypt(uid, remote_name, remote_key, key) 704 uid_t uid; 705 char *remote_name; 706 netobj *remote_key; 707 des_block *key; 708 { 709 return (pk_crypt(uid, remote_name, remote_key, key, DES_ENCRYPT)); 710 } 711 712 /* 713 * Encrypt the key using the public key associated with remote_name and the 714 * secret key associated with uid using vers 3 715 */ 716 keystatus 717 pk_encrypt3( 718 uid_t uid, 719 cryptkeyarg3 *arg, 720 deskeyarray *key 721 ) 722 { 723 return (pk_crypt3(uid, arg, key, DES_ENCRYPT)); 724 } 725 726 /* 727 * Decrypt the key using the public key associated with remote_name and the 728 * secret key associated with uid. 729 */ 730 keystatus 731 pk_decrypt(uid, remote_name, remote_key, key) 732 uid_t uid; 733 char *remote_name; 734 netobj *remote_key; 735 des_block *key; 736 { 737 return (pk_crypt(uid, remote_name, remote_key, key, DES_DECRYPT)); 738 } 739 740 /* 741 * Decrypt the key using the public key associated with remote_name and the 742 * secret key associated with uid using vers 3 743 */ 744 keystatus 745 pk_decrypt3( 746 uid_t uid, 747 cryptkeyarg3 *arg, 748 deskeyarray *key 749 ) 750 { 751 return (pk_crypt3(uid, arg, key, DES_DECRYPT)); 752 } 753 754 /* 755 * Key storage management 756 */ 757 758 #define KEY_ONLY 0 759 #define KEY_NAME 1 760 struct secretkey_netname_list { 761 uid_t uid; 762 key_netstarg keynetdata; 763 uchar_t sc_flag; 764 struct secretkey_netname_list *next; 765 }; 766 767 #define HASH_UID(x) (x & 0xff) 768 static struct secretkey_netname_list *g_secretkey_netname[KEY_HASH_SIZE]; 769 static rwlock_t g_secretkey_netname_lock = DEFAULTRWLOCK; 770 771 /* 772 * Store the keys and netname for this uid 773 */ 774 static int 775 store_netname(uid, netstore) 776 uid_t uid; 777 key_netstarg *netstore; 778 { 779 struct secretkey_netname_list *new; 780 struct secretkey_netname_list **l; 781 int hash = HASH_UID(uid); 782 783 (void) rw_wrlock(&g_secretkey_netname_lock); 784 for (l = &g_secretkey_netname[hash]; *l != NULL && (*l)->uid != uid; 785 l = &(*l)->next) { 786 } 787 if (*l == NULL) { 788 /* LINTED pointer alignment */ 789 new = (struct secretkey_netname_list *)malloc(sizeof (*new)); 790 if (new == NULL) { 791 (void) rw_unlock(&g_secretkey_netname_lock); 792 return (0); 793 } 794 new->uid = uid; 795 new->next = NULL; 796 *l = new; 797 } else { 798 new = *l; 799 if (new->keynetdata.st_netname) 800 (void) free(new->keynetdata.st_netname); 801 } 802 memcpy(new->keynetdata.st_priv_key, netstore->st_priv_key, 803 HEXKEYBYTES); 804 memcpy(new->keynetdata.st_pub_key, netstore->st_pub_key, HEXKEYBYTES); 805 806 if (netstore->st_netname) 807 new->keynetdata.st_netname = strdup(netstore->st_netname); 808 else 809 new->keynetdata.st_netname = (char *)NULL; 810 new->sc_flag = KEY_NAME; 811 (void) rw_unlock(&g_secretkey_netname_lock); 812 return (1); 813 814 } 815 816 static int 817 appendnetname3(struct mechentry *mp, uid_t uid, key_netstarg3 *net) 818 { 819 struct mechdata *mdp; 820 struct cacheuid_list **cpp, *cp; 821 822 debug(KEYSERV_DEBUG, ("appendnetname3 %x", mp)); 823 if ((mp == NULL) || (net == NULL)) { 824 return (0); 825 } 826 mutex_lock(&mp->mech_lock); 827 if ((mdp = mp->mechdata) == NULL) { 828 mdp = (struct mechdata *)calloc(1, sizeof (*mdp)); 829 if (mdp == NULL) { 830 mutex_unlock(&mp->mech_lock); 831 debug(KEYSERV_INFO, ("appendnetname3 : calloc failed")); 832 return (0); 833 } 834 mp->mechdata = mdp; 835 } 836 cpp = mapuid2cache(uid, mdp); 837 if (*cpp == NULL) { 838 cp = (struct cacheuid_list *)malloc(sizeof (*cp)); 839 if (cp == NULL) { 840 mutex_unlock(&mp->mech_lock); 841 debug(KEYSERV_INFO, ("appendnetname3 : malloc failed")); 842 syslog(LOG_ERR, "file %s line %d: malloc failed", 843 __FILE__, __LINE__); 844 return (0); 845 } 846 memset(cp, 0, sizeof (*cp)); 847 cp->uid = uid; 848 *cpp = cp; 849 } else { 850 cp = *cpp; 851 } 852 freekeybuf3(cp->secretkey); 853 if ((cp->secretkey = cpykeybuf3(&net->st_priv_key)) == NULL) { 854 mutex_unlock(&mp->mech_lock); 855 return (0); 856 } 857 freekeybuf3(cp->publickey); 858 if ((cp->publickey = cpykeybuf3(&net->st_pub_key)) == NULL) { 859 mutex_unlock(&mp->mech_lock); 860 return (0); 861 } 862 free(cp->netname); 863 if (net->st_netname) { 864 cp->netname = strdup(net->st_netname); 865 } else { 866 cp->netname = (char *)NULL; 867 } 868 mutex_unlock(&mp->mech_lock); 869 return (1); 870 } 871 872 keystatus 873 pk_netput(uid, netstore) 874 uid_t uid; 875 key_netstarg *netstore; 876 { 877 878 if (!store_netname(uid, netstore)) { 879 return (KEY_SYSTEMERR); 880 } 881 return (KEY_SUCCESS); 882 } 883 884 /* 885 * Store the keys and netname for this uid vers 3 886 */ 887 static int 888 store_netname3(uid_t uid, key_netstarg3 *net) 889 { 890 struct mechentry *mp; 891 key_netstarg netstore; 892 893 if (net == NULL) { 894 return (0); 895 } 896 if ((mp = getmechtype(net->keylen, net->algtype)) == NULL) { 897 return (0); 898 } 899 if (uid == 0 && CLASSIC_PK_DH(net->keylen, net->algtype)) { 900 memcpy(netstore.st_priv_key, net->st_priv_key.keybuf3_val, 901 HEXKEYBYTES); 902 memset(netstore.st_pub_key, 0, HEXKEYBYTES); 903 netstore.st_netname = net->st_netname; 904 if (pk_netput(uid, &netstore) != KEY_SUCCESS) { 905 (void) fprintf(stderr, 906 "keyserv: could not set root's key and netname.\n"); 907 return (0); 908 } 909 } 910 return (appendnetname3(mp, uid, net)); 911 } 912 913 keystatus 914 pk_netput3(uid_t uid, key_netstarg3 *netstore) 915 { 916 917 if (!store_netname3(uid, netstore)) { 918 return (KEY_SYSTEMERR); 919 } 920 return (KEY_SUCCESS); 921 } 922 923 int 924 addmasterkey(char *master, char *netname, algtype_t algtype) 925 { 926 keybuf3 *secret, *public; 927 int bytelen = strlen(master); 928 keylen_t keylen = bytelen*4; 929 key_netstarg3 tmp; 930 931 if ((secret = setkeybuf3(master, bytelen)) == NULL) { 932 return (0); 933 } 934 if ((public = getkeybuf3(bytelen+1)) == NULL) { 935 /* the +1 is mandated by getpublickey_g() */ 936 return (0); 937 } 938 /* 939 * getpublickey_g(netname, keylen, algtype, 940 * public->keybuf3_val, public->keybuf3_len); 941 * cannot be called since rpc.nisd is not up yet 942 * so we continue to return a zero filled public key 943 * as in the earlier version 944 */ 945 memset(public->keybuf3_val, 0, bytelen+1); 946 tmp.st_priv_key = *secret; 947 free(secret); 948 tmp.st_pub_key = *public; 949 free(public); 950 tmp.st_netname = strdup(netname); 951 tmp.keylen = keylen; 952 tmp.algtype = algtype; 953 return (store_netname3(0, &tmp)); 954 } 955 956 /* 957 * Fetch the keys and netname for this uid 958 */ 959 static int 960 fetch_netname(uid, key_netst) 961 uid_t uid; 962 struct key_netstarg *key_netst; 963 { 964 struct secretkey_netname_list *l; 965 int hash = HASH_UID(uid); 966 967 (void) rw_rdlock(&g_secretkey_netname_lock); 968 for (l = g_secretkey_netname[hash]; l != NULL; l = l->next) { 969 if ((l->uid == uid) && (l->sc_flag == KEY_NAME)) { 970 971 memcpy(key_netst->st_priv_key, 972 l->keynetdata.st_priv_key, HEXKEYBYTES); 973 974 memcpy(key_netst->st_pub_key, 975 l->keynetdata.st_pub_key, HEXKEYBYTES); 976 977 if (l->keynetdata.st_netname) 978 strcpy(key_netst->st_netname, 979 l->keynetdata.st_netname); 980 else 981 key_netst->st_netname = NULL; 982 (void) rw_unlock(&g_secretkey_netname_lock); 983 return (1); 984 } 985 } 986 (void) rw_unlock(&g_secretkey_netname_lock); 987 return (0); 988 } 989 990 static void 991 remove_ref(struct cacheuid_list *cp) 992 { 993 debug(KEYSERV_DEBUG0, ("remove_ref %x", cp)); 994 /* 995 * XXX 996 * if we are going to do this along the lines of vn_rele, 997 * more stuff needs to be done here and the access to refcnt 998 * needs to be mutex locked. Keep it simple for now. 999 */ 1000 cp->refcnt--; 1001 } 1002 1003 static void 1004 add_ref(struct cacheuid_list **cpp) 1005 { 1006 struct cacheuid_list *cp; 1007 1008 if (cpp == NULL) { 1009 return; 1010 } 1011 /*LINTED assignment operator "=" found where "==" was expected*/ 1012 if (cp = *cpp) { 1013 debug(KEYSERV_DEBUG0, ("add_ref %x", cp)); 1014 cp->refcnt++; 1015 } 1016 } 1017 1018 static struct cacheuid_list * 1019 getcachekey3(uid_t uid, struct mechentry *mp) 1020 { 1021 struct cacheuid_list **cpp, *cp; 1022 struct mechdata *mdp; 1023 1024 debug(KEYSERV_DEBUG1, ("getcachekey3 %d %x", uid, mp)); 1025 if (mp == NULL) { 1026 return (0); 1027 } 1028 mutex_lock(&mp->mech_lock); 1029 if ((mdp = mp->mechdata) == NULL) { 1030 mutex_unlock(&mp->mech_lock); 1031 debug(KEYSERV_DEBUG0, ("getcachekey3 ret 0")); 1032 return (0); 1033 } 1034 cpp = mapuid2cache(uid, mdp); 1035 cp = *cpp; 1036 add_ref(cpp); 1037 mutex_unlock(&mp->mech_lock); 1038 debug(KEYSERV_DEBUG0, ("getcachekey3 ret %x", *cpp)); 1039 return (cp); 1040 } 1041 1042 /* 1043 * Fetch any available cache for this uid (vers 3) 1044 */ 1045 static struct cacheuid_list * 1046 getanycache3(uid_t uid) 1047 { 1048 struct keylenlist *kp; 1049 struct algtypelist *ap; 1050 struct mechdata *mdp; 1051 struct cacheuid_list **cpp, *cp; 1052 1053 debug(KEYSERV_DEBUG, ("getanycache3 %d", uid)); 1054 for (kp = mechtable.kp; kp != NULL; kp = kp->next) { 1055 debug(KEYSERV_DEBUG0, ("getanycache3 key %d", kp->keylen)); 1056 for (ap = kp->ap; ap != NULL; ap = ap->next) { 1057 debug(KEYSERV_DEBUG0, 1058 ("getanycache3 alg: %d", ap->algtype)); 1059 mutex_lock(&ap->mech.mech_lock); 1060 if ((mdp = ap->mech.mechdata) == NULL) { 1061 mutex_unlock(&ap->mech.mech_lock); 1062 continue; 1063 } 1064 cpp = mapuid2cache(uid, mdp); 1065 if (*cpp == NULL) { 1066 mutex_unlock(&ap->mech.mech_lock); 1067 continue; 1068 } 1069 cp = *cpp; 1070 cp->refcnt++; 1071 mutex_unlock(&ap->mech.mech_lock); 1072 return (cp); 1073 } 1074 } 1075 return (NULL); 1076 } 1077 1078 static struct cacheuid_list * 1079 fetchcache3(uid_t uid, keylen_t k, algtype_t a) 1080 { 1081 struct mechentry *mp; 1082 struct cacheuid_list *cp; 1083 1084 debug(KEYSERV_DEBUG, ("fetchcache3 %d %d %d", uid, k, a)); 1085 if ((mp = getmechtype(k, a)) == NULL) { 1086 return (NULL); 1087 } 1088 if ((cp = getcachekey3(uid, mp)) == NULL) { 1089 return (NULL); 1090 } 1091 debug(KEYSERV_DEBUG, ("fetchcache3 ret %x", cp)); 1092 return (cp); 1093 } 1094 1095 /* 1096 * Fetch the keys and netname for this uid vers 3 1097 */ 1098 static int 1099 fetch_netname3(uid_t uid, mechtype *net, key_netstarg3 *ret) 1100 { 1101 struct cacheuid_list *cp; 1102 1103 if ((net == NULL) || (ret == NULL)) { 1104 return (0); 1105 } 1106 debug(KEYSERV_DEBUG, ("fetch_netname3 %d %d %d", 1107 uid, net->keylen, net->algtype)); 1108 if (net->keylen == 0) { 1109 cp = getanycache3(uid); 1110 } else { 1111 cp = fetchcache3(uid, net->keylen, net->algtype); 1112 } 1113 debug(KEYSERV_DEBUG, ("fetch_netname3 cp %x", cp)); 1114 if (cp == NULL) { 1115 return (0); 1116 } 1117 debug(KEYSERV_DEBUG, ("fetch_netname3 sec %x", cp->secretkey)); 1118 if (!storekeybuf3(&ret->st_priv_key, cp->secretkey)) { 1119 return (0); 1120 } 1121 debug(KEYSERV_DEBUG, ("fetch_netname3 pub %x", cp->publickey)); 1122 if (!storekeybuf3(&ret->st_pub_key, cp->publickey)) { 1123 return (0); 1124 } 1125 if (cp->netname) { 1126 debug(KEYSERV_DEBUG, ("fetch_netname3 net %s", cp->netname)); 1127 ret->st_netname = strdup(cp->netname); 1128 } else { 1129 ret->st_netname = NULL; 1130 } 1131 remove_ref(cp); 1132 return (1); 1133 } 1134 1135 keystatus 1136 pk_netget(uid, netstore) 1137 uid_t uid; 1138 key_netstarg *netstore; 1139 { 1140 if (!fetch_netname(uid, netstore)) { 1141 return (KEY_SYSTEMERR); 1142 } 1143 return (KEY_SUCCESS); 1144 } 1145 1146 keystatus 1147 pk_netget3(uid_t uid, mechtype *net, key_netstarg3 *ret) 1148 { 1149 if (!fetch_netname3(uid, net, ret)) { 1150 return (KEY_SYSTEMERR); 1151 } 1152 return (KEY_SUCCESS); 1153 } 1154 1155 #define cachehit(pub, sec, list) \ 1156 (memcmp(pub, (list)->public, sizeof (keybuf)) == 0 && \ 1157 memcmp(sec, (list)->secret, sizeof (keybuf)) == 0) 1158 1159 /* 1160 * Try to find the common key in the cache 1161 */ 1162 static int 1163 readcache(pub, sec, deskey, hash) 1164 char *pub; 1165 char *sec; 1166 des_block *deskey; 1167 int hash; 1168 { 1169 register struct cachekey_list **l; 1170 1171 for (l = &g_cachedkeys[hash]; (*l) != NULL && !cachehit(pub, sec, *l); 1172 l = &(*l)->next) 1173 ; 1174 if ((*l) == NULL) 1175 return (0); 1176 *deskey = (*l)->deskey; 1177 return (1); 1178 } 1179 1180 /* 1181 * cache result of expensive multiple precision exponential operation 1182 */ 1183 static int 1184 writecache(pub, sec, deskey, hash) 1185 char *pub; 1186 char *sec; 1187 des_block *deskey; 1188 int hash; 1189 { 1190 struct cachekey_list *new; 1191 1192 new = (struct cachekey_list *)malloc(sizeof (struct cachekey_list)); 1193 if (new == NULL) { 1194 return (0); 1195 } 1196 memcpy(new->public, pub, sizeof (keybuf)); 1197 memcpy(new->secret, sec, sizeof (keybuf)); 1198 new->deskey = *deskey; 1199 1200 new->next = g_cachedkeys[hash]; 1201 g_cachedkeys[hash] = new; 1202 return (1); 1203 } 1204 1205 /* 1206 * Choose middle 64 bits of the common key to use as our des key, possibly 1207 * overwriting the lower order bits by setting parity. 1208 */ 1209 static int 1210 extractdeskey(ck, deskey) 1211 MINT *ck; 1212 des_block *deskey; 1213 { 1214 void _mp_move(MINT *, MINT *); 1215 MINT *a; 1216 short r; 1217 int i; 1218 short base = (1 << 8); 1219 char *k; 1220 1221 a = mp_itom(0); 1222 _mp_move(ck, a); 1223 for (i = 0; i < ((KEYSIZE - 64) / 2) / 8; i++) { 1224 mp_sdiv(a, base, a, &r); 1225 } 1226 k = deskey->c; 1227 for (i = 0; i < 8; i++) { 1228 mp_sdiv(a, base, a, &r); 1229 *k++ = r; 1230 } 1231 mp_mfree(a); 1232 des_setparity((char *)deskey); 1233 return (0); 1234 } 1235 1236 static bool_t 1237 fetchsecretkey(uid, buf) 1238 uid_t uid; 1239 char *buf; 1240 { 1241 struct secretkey_netname_list *l; 1242 int hash = HASH_UID(uid); 1243 1244 (void) rw_rdlock(&g_secretkey_netname_lock); 1245 for (l = g_secretkey_netname[hash]; l != NULL; l = l->next) { 1246 if (l->uid == uid) { 1247 memcpy(buf, l->keynetdata.st_priv_key, 1248 sizeof (keybuf)); 1249 (void) rw_unlock(&g_secretkey_netname_lock); 1250 return (TRUE); 1251 } 1252 } 1253 (void) rw_unlock(&g_secretkey_netname_lock); 1254 return (FALSE); 1255 } 1256 1257 static keybuf3 * 1258 fetchsecretkey3(uid_t uid, keylen_t k, algtype_t a) 1259 { 1260 struct cacheuid_list *cp; 1261 1262 debug(KEYSERV_DEBUG, ("fetchsecretkey3 %d %d %d", uid, k, a)); 1263 if ((cp = fetchcache3(uid, k, a)) == NULL) { 1264 return (NULL); 1265 } 1266 debug(KEYSERV_DEBUG, ("fetchsecretkey3 ret %x", cp->secretkey)); 1267 return (cp->secretkey); 1268 } 1269 1270 /* 1271 * Do the work of pk_encrypt && pk_decrypt 1272 */ 1273 static keystatus 1274 pk_crypt(uid, remote_name, remote_key, key, mode) 1275 uid_t uid; 1276 char *remote_name; 1277 netobj *remote_key; 1278 des_block *key; 1279 int mode; 1280 { 1281 char xsecret[1024]; 1282 char xpublic[1024]; 1283 des_block deskey; 1284 int err; 1285 MINT *public; 1286 MINT *secret; 1287 MINT *common; 1288 char zero[8]; 1289 int hash; 1290 1291 if (!fetchsecretkey(uid, xsecret) || xsecret[0] == 0) { 1292 memset(zero, 0, sizeof (zero)); 1293 if (nodefaultkeys) 1294 return (KEY_NOSECRET); 1295 1296 if (!getsecretkey("nobody", xsecret, zero) || xsecret[0] == 0) { 1297 return (KEY_NOSECRET); 1298 } 1299 } 1300 if (remote_key) { 1301 memcpy(xpublic, remote_key->n_bytes, remote_key->n_len); 1302 } else { 1303 if (!getpublickey(remote_name, xpublic)) { 1304 if (nodefaultkeys || !getpublickey("nobody", xpublic)) 1305 return (KEY_UNKNOWN); 1306 } 1307 } 1308 1309 xsecret[HEXKEYBYTES] = '\0'; 1310 xpublic[HEXKEYBYTES] = '\0'; 1311 1312 hash = hash_keys(xpublic, xsecret); 1313 (void) rw_rdlock(&g_cachedkeys_lock); 1314 if (!readcache(xpublic, xsecret, &deskey, hash)) { 1315 (void) rw_unlock(&g_cachedkeys_lock); 1316 (void) rw_wrlock(&g_cachedkeys_lock); 1317 if (!readcache(xpublic, xsecret, &deskey, hash)) { 1318 public = mp_xtom(xpublic); 1319 secret = mp_xtom(xsecret); 1320 /* Sanity Check on public and private keys */ 1321 if (public == NULL || secret == NULL) { 1322 (void) rw_unlock(&g_cachedkeys_lock); 1323 return (KEY_SYSTEMERR); 1324 } 1325 common = mp_itom(0); 1326 mp_pow(public, secret, MODULUS, common); 1327 extractdeskey(common, &deskey); 1328 writecache(xpublic, xsecret, &deskey, hash); 1329 mp_mfree(secret); 1330 mp_mfree(public); 1331 mp_mfree(common); 1332 } 1333 } 1334 (void) rw_unlock(&g_cachedkeys_lock); 1335 1336 err = ecb_crypt((char *)&deskey, (char *)key, sizeof (des_block), 1337 DES_HW | mode); 1338 if (DES_FAILED(err)) { 1339 return (KEY_SYSTEMERR); 1340 } 1341 return (KEY_SUCCESS); 1342 } 1343 1344 static int 1345 hash_keys3(keybuf3 *p, keybuf3 *s) 1346 { 1347 int i; 1348 int hash = 0; 1349 char *pub = p->keybuf3_val; 1350 char *sec = s->keybuf3_val; 1351 1352 debug(KEYSERV_DEBUG, ("hash_keys3 public %d %s", 1353 p->keybuf3_len, pub)); 1354 debug(KEYSERV_DEBUG, ("hash_keys3 secret %d %s", 1355 s->keybuf3_len, sec)); 1356 for (i = 0; i < s->keybuf3_len; i += 6, pub += 6, sec += 6) { 1357 hash ^= *pub; 1358 hash ^= *sec; 1359 } 1360 debug(KEYSERV_DEBUG, ("hash_keys3 ret %d", hash & 0xff)); 1361 return (hash & 0xff); 1362 } 1363 1364 static struct cachekey3_list ** 1365 map_ps2cache(keybuf3 *public, keybuf3 *secret, struct psdata *pdp) 1366 { 1367 struct cachekey3_list **cpp; 1368 int hash = hash_keys3(public, secret); 1369 1370 debug(KEYSERV_DEBUG, ("map_ps2cache %x %d", pdp, hash)); 1371 for (cpp = &pdp->common[hash]; 1372 *cpp != NULL && !(cachehit3(public, secret, *cpp)); 1373 cpp = &(*cpp)->next) { 1374 debug(KEYSERV_DEBUG0, ("map_ps2cache %x", cpp)); 1375 } 1376 debug(KEYSERV_DEBUG, ("map_ps2cache ret %x", cpp)); 1377 return (cpp); 1378 } 1379 1380 static struct cachekey3_list * 1381 getdeskey3( 1382 keylen_t keylen, 1383 algtype_t algtype, 1384 int desarylen, 1385 keybuf3 *public, 1386 keybuf3 *secret, 1387 uid_t uid 1388 ) 1389 { 1390 struct mechentry *mp; 1391 struct psdata *pdp; 1392 struct cachekey3_list **cpp, *cp, *cachep; 1393 struct cacheuid_list *cu; 1394 int i; 1395 int cached = 0; 1396 1397 debug(KEYSERV_DEBUG, ("getdeskey3 %d %d %d %x %x", 1398 keylen, algtype, desarylen, public, secret)); 1399 if ((mp = getmechtype(keylen, algtype)) == NULL) { 1400 return (0); 1401 } 1402 (void) mutex_lock(&mp->ps_lock); 1403 if ((pdp = mp->psdata) == NULL) { 1404 if ((pdp = (struct psdata *)calloc(1, sizeof (*pdp))) == 1405 NULL) { 1406 mutex_unlock(&mp->ps_lock); 1407 debug(KEYSERV_INFO, ("getdeskey3 : calloc failed")); 1408 return (0); 1409 } 1410 mp->psdata = pdp; 1411 } 1412 debug(KEYSERV_DEBUG, ("getdeskey3 %x", pdp)); 1413 cpp = map_ps2cache(public, secret, pdp); 1414 if (*cpp == NULL) { 1415 debug(KEYSERV_DEBUG, ("getdeskey3 calling fetchcache3")); 1416 if (disk_caching && 1417 (cu = fetchcache3(uid, keylen, algtype)) != NULL) { 1418 debug(KEYSERV_DEBUG, 1419 ("getdeskey3 calling cache_retrieve")); 1420 if ((cachep = cache_retrieve(keylen, algtype, uid, 1421 public, cu->key)) != NULL) { 1422 if (cmpkeybuf3(cachep->secret, cu->secretkey)) { 1423 cached = 1; 1424 } else { 1425 debug(KEYSERV_DEBUG, 1426 ("getdeskey3 calling cache_remove")); 1427 cache_remove(keylen, algtype, 1428 uid, NULL); 1429 } 1430 } 1431 } 1432 if (cached) { 1433 cp = cachep; 1434 } else { 1435 if ((cp = (struct cachekey3_list *) 1436 malloc(sizeof (*cp))) == NULL) { 1437 mutex_unlock(&mp->ps_lock); 1438 debug(KEYSERV_INFO, 1439 ("getdeskey3 : malloc failed")); 1440 syslog(LOG_ERR, 1441 "file %s line %d: malloc failed", 1442 __FILE__, __LINE__); 1443 return (0); 1444 } 1445 cp->refcnt = 0; 1446 cp->next = NULL; 1447 if ((cp->public = cpykeybuf3(public)) == NULL) { 1448 mutex_unlock(&mp->ps_lock); 1449 return (0); 1450 } 1451 if ((cp->secret = cpykeybuf3(secret)) == NULL) { 1452 mutex_unlock(&mp->ps_lock); 1453 return (0); 1454 } 1455 if (!setdeskeyarray(&cp->deskey, desarylen)) { 1456 mutex_unlock(&mp->ps_lock); 1457 return (0); 1458 } 1459 debug(KEYSERV_DEBUG, ("getdeskey3 %x %x %x", 1460 cp->public, cp->secret, 1461 cp->deskey.deskeyarray_val)); 1462 debug(KEYSERV_DEBUG, 1463 ("getdeskey3 calling __gen_common_dhkeys_g")); 1464 if (!__gen_common_dhkeys_g(public->keybuf3_val, 1465 secret->keybuf3_val, 1466 keylen, algtype, 1467 cp->deskey.deskeyarray_val, desarylen)) { 1468 mutex_unlock(&mp->ps_lock); 1469 return (0); 1470 } 1471 for (i = 0; i < desarylen; i++) { 1472 debug(KEYSERV_DEBUG0, 1473 ("getdeskey3 gendh key : (%x,%x)", 1474 cp->deskey.deskeyarray_val[i].key.high, 1475 cp->deskey.deskeyarray_val[i].key.low)); 1476 } 1477 if (disk_caching && cu != NULL) { 1478 debug(KEYSERV_DEBUG, 1479 ("getdeskey3 calling cache_insert")); 1480 cache_insert(keylen, algtype, uid, cp->deskey, 1481 cu->key, public, secret); 1482 } 1483 } 1484 *cpp = cp; 1485 } else { 1486 cp = *cpp; 1487 } 1488 cp->refcnt++; 1489 mutex_unlock(&mp->ps_lock); 1490 debug(KEYSERV_DEBUG, ("getdeskey3 ret %x", cp)); 1491 return (cp); 1492 } 1493 1494 keystatus 1495 pk_get_conv_key3(uid_t uid, deskeyarg3 *arg, cryptkeyres3 *res) 1496 { 1497 keybuf3 *xsecret, *xpublic; 1498 char zero[8]; 1499 struct cachekey3_list *cp; 1500 1501 debug(KEYSERV_DEBUG, ("pk_get_conv_key3 %d %x %x", 1502 uid, arg, res)); 1503 if ((xsecret = fetchsecretkey3(uid, 1504 arg->keylen, arg->algtype)) == NULL) { 1505 if (nodefaultkeys) 1506 return (KEY_NOSECRET); 1507 memset(zero, 0, sizeof (zero)); 1508 if ((xsecret = getkeybuf3(arg->keylen/4+1)) == NULL) { 1509 return (KEY_SYSTEMERR); 1510 } 1511 debug(KEYSERV_DEBUG, 1512 ("pk_get_conv_key3 calling getsecretkey_g")); 1513 if (!getsecretkey_g("nobody", 1514 arg->keylen, arg->algtype, 1515 xsecret->keybuf3_val, xsecret->keybuf3_len, 1516 zero) || *xsecret->keybuf3_val == 0) { /* XXX */ 1517 debug(KEYSERV_DEBUG, 1518 ("pk_get_conv_key3 calling getsecretkey_g failed")); 1519 return (KEY_NOSECRET); 1520 } 1521 debug(KEYSERV_DEBUG, 1522 ("pk_get_conv_key3 calling getsecretkey_g succeeded")); 1523 } 1524 xpublic = &arg->pub_key; 1525 if ((cp = getdeskey3(arg->keylen, arg->algtype, arg->nkeys, 1526 xpublic, xsecret, uid)) == NULL) { 1527 return (KEY_SYSTEMERR); 1528 } 1529 storedeskeyarray(&res->cryptkeyres3_u.deskey, &cp->deskey); 1530 return (KEY_SUCCESS); 1531 } 1532 1533 /* 1534 * Do the work of pk_encrypt3 && pk_decrypt3 1535 */ 1536 static keystatus 1537 pk_crypt3( 1538 uid_t uid, 1539 cryptkeyarg3 *arg, 1540 deskeyarray *key, 1541 int mode 1542 ) 1543 { 1544 keybuf3 *xsecret = NULL, *xpublic = NULL; 1545 char zero[8]; 1546 struct cachekey3_list *cp; 1547 int err; 1548 int xsecret_alloc = 0; 1549 char ivec[8]; 1550 1551 memset(ivec, 0, 8); 1552 debug(KEYSERV_DEBUG1, ("pk_crypt3 %d %x %x %d", 1553 uid, arg, key, mode)); 1554 if ((xsecret = fetchsecretkey3(uid, 1555 arg->keylen, arg->algtype)) == NULL) { 1556 if (nodefaultkeys) 1557 return (KEY_NOSECRET); 1558 memset(zero, 0, sizeof (zero)); 1559 if ((xsecret = getkeybuf3(arg->keylen/4+1)) == NULL) { 1560 return (KEY_SYSTEMERR); 1561 } 1562 xsecret_alloc = 1; 1563 debug(KEYSERV_DEBUG1, ("pk_crypt3 calling getsecretkey_g")); 1564 if (!getsecretkey_g("nobody", 1565 arg->keylen, arg->algtype, 1566 xsecret->keybuf3_val, xsecret->keybuf3_len, 1567 zero) || *xsecret->keybuf3_val == 0) { /* XXX */ 1568 debug(KEYSERV_DEBUG, 1569 ("pk_crypt3 calling getsecretkey_g failed")); 1570 freekeybuf3(xsecret); 1571 return (KEY_NOSECRET); 1572 } 1573 /* XXX optimize to cache nobody's secret key? */ 1574 debug(KEYSERV_DEBUG0, 1575 ("pk_crypt3 calling getsecretkey_g succeeded")); 1576 } 1577 if (arg->remotekey.keybuf3_len) { 1578 if ((xpublic = cpykeybuf3(&arg->remotekey)) == NULL) { 1579 if (xsecret_alloc) freekeybuf3(xsecret); 1580 return (KEY_SYSTEMERR); 1581 } 1582 } else { 1583 if ((xpublic = getkeybuf3(arg->keylen/4+1)) == NULL) { 1584 if (xsecret_alloc) freekeybuf3(xsecret); 1585 return (KEY_SYSTEMERR); 1586 } 1587 debug(KEYSERV_DEBUG1, ("pk_crypt3 calling getpublickey_g")); 1588 if (!getpublickey_g(arg->remotename, 1589 arg->keylen, arg->algtype, 1590 xpublic->keybuf3_val, xpublic->keybuf3_len)) { 1591 debug(KEYSERV_DEBUG0, 1592 ("pk_crypt3 calling getpublickey_g nobody")); 1593 if (nodefaultkeys || !getpublickey_g("nobody", 1594 arg->keylen, arg->algtype, 1595 xpublic->keybuf3_val, xpublic->keybuf3_len)) { 1596 debug(KEYSERV_DEBUG, 1597 ("pk_crypt3 calling getpublickey_g nobody failed")); 1598 if (xsecret_alloc) freekeybuf3(xsecret); 1599 freekeybuf3(xpublic); 1600 return (KEY_UNKNOWN); 1601 } 1602 } 1603 debug(KEYSERV_DEBUG0, 1604 ("pk_crypt3 calling getpublickey_g succeeded")); 1605 } 1606 1607 if ((cp = getdeskey3(arg->keylen, arg->algtype, 1608 arg->deskey.deskeyarray_len, xpublic, xsecret, uid)) == NULL) { 1609 if (xsecret_alloc) freekeybuf3(xsecret); 1610 freekeybuf3(xpublic); 1611 return (KEY_SYSTEMERR); 1612 } 1613 storedeskeyarray(key, &arg->deskey); 1614 if (CLASSIC_PK_DH(arg->keylen, arg->algtype)) { 1615 /*EMPTY*/ 1616 debug(KEYSERV_DEBUG1, 1617 ("pk_crypt3 WARNING received 192-bit key")); 1618 } else { 1619 debug(KEYSERV_DEBUG, 1620 ("pk_crypt3 calling __cbc_triple_crypt")); 1621 err = __cbc_triple_crypt(cp->deskey.deskeyarray_val, 1622 (char *)key->deskeyarray_val, 1623 cp->deskey.deskeyarray_len*sizeof (des_block), 1624 DES_HW | mode, ivec); 1625 if (DES_FAILED(err)) { 1626 debug(KEYSERV_DEBUG, 1627 ("pk_crypt3 calling ecb_crypt/__cbc_triple_crypt failed")); 1628 if (xsecret_alloc) freekeybuf3(xsecret); 1629 freekeybuf3(xpublic); 1630 return (KEY_SYSTEMERR); 1631 } 1632 debug(KEYSERV_DEBUG, 1633 ("pk_crypt3 calling __cbc_triple_crypt succeeded")); 1634 } 1635 if (xsecret_alloc) freekeybuf3(xsecret); 1636 freekeybuf3(xpublic); 1637 return (KEY_SUCCESS); 1638 } 1639 1640 keystatus 1641 pk_get_conv_key(uid, pubkey, result) 1642 uid_t uid; 1643 keybuf pubkey; 1644 cryptkeyres *result; 1645 { 1646 char xsecret[1024]; 1647 char xpublic[1024]; 1648 MINT *public; 1649 MINT *secret; 1650 MINT *common; 1651 char zero[8]; 1652 int hash; 1653 1654 if (!fetchsecretkey(uid, xsecret) || xsecret[0] == 0) { 1655 memset(zero, 0, sizeof (zero)); 1656 if (nodefaultkeys) 1657 return (KEY_NOSECRET); 1658 1659 if (!getsecretkey("nobody", xsecret, zero) || 1660 xsecret[0] == 0) 1661 return (KEY_NOSECRET); 1662 } 1663 1664 memcpy(xpublic, pubkey, sizeof (keybuf)); 1665 xsecret[HEXKEYBYTES] = '\0'; 1666 xpublic[HEXKEYBYTES] = '\0'; 1667 1668 hash = hash_keys(xpublic, xsecret); 1669 (void) rw_rdlock(&g_cachedkeys_lock); 1670 if (!readcache(xpublic, xsecret, &result->cryptkeyres_u.deskey, hash)) { 1671 (void) rw_unlock(&g_cachedkeys_lock); 1672 (void) rw_wrlock(&g_cachedkeys_lock); 1673 if (!readcache(xpublic, xsecret, &result->cryptkeyres_u.deskey, 1674 hash)) { 1675 public = mp_xtom(xpublic); 1676 secret = mp_xtom(xsecret); 1677 /* Sanity Check on public and private keys */ 1678 if (public == NULL || secret == NULL) { 1679 (void) rw_unlock(&g_cachedkeys_lock); 1680 return (KEY_SYSTEMERR); 1681 } 1682 common = mp_itom(0); 1683 mp_pow(public, secret, MODULUS, common); 1684 extractdeskey(common, &result->cryptkeyres_u.deskey); 1685 writecache(xpublic, xsecret, 1686 &result->cryptkeyres_u.deskey, hash); 1687 mp_mfree(secret); 1688 mp_mfree(public); 1689 mp_mfree(common); 1690 } 1691 } 1692 (void) rw_unlock(&g_cachedkeys_lock); 1693 1694 return (KEY_SUCCESS); 1695 } 1696 1697 #define findsec(sec, list) \ 1698 (memcmp(sec, (list)->secret, sizeof (keybuf)) == 0) 1699 1700 /* 1701 * Remove common keys from the cache. 1702 */ 1703 static int 1704 removecache(sec) 1705 char *sec; 1706 { 1707 struct cachekey_list *found; 1708 register struct cachekey_list **l; 1709 int i; 1710 1711 (void) rw_wrlock(&g_cachedkeys_lock); 1712 for (i = 0; i < KEY_HASH_SIZE; i++) { 1713 for (l = &g_cachedkeys[i]; (*l) != NULL; ) { 1714 if (findsec(sec, *l)) { 1715 found = *l; 1716 *l = (*l)->next; 1717 memset((char *)found, 0, 1718 sizeof (struct cachekey_list)); 1719 free(found); 1720 } else { 1721 l = &(*l)->next; 1722 } 1723 } 1724 } 1725 (void) rw_unlock(&g_cachedkeys_lock); 1726 return (1); 1727 } 1728 1729 /* 1730 * Store the secretkey for this uid 1731 */ 1732 int 1733 storesecretkey(uid, key) 1734 uid_t uid; 1735 keybuf key; 1736 { 1737 struct secretkey_netname_list *new; 1738 struct secretkey_netname_list **l; 1739 int hash = HASH_UID(uid); 1740 1741 (void) rw_wrlock(&g_secretkey_netname_lock); 1742 for (l = &g_secretkey_netname[hash]; *l != NULL && (*l)->uid != uid; 1743 l = &(*l)->next) { 1744 } 1745 if (*l == NULL) { 1746 if (key[0] == '\0') { 1747 (void) rw_unlock(&g_secretkey_netname_lock); 1748 return (0); 1749 } 1750 new = (struct secretkey_netname_list *)malloc(sizeof (*new)); 1751 if (new == NULL) { 1752 (void) rw_unlock(&g_secretkey_netname_lock); 1753 return (0); 1754 } 1755 new->uid = uid; 1756 new->sc_flag = KEY_ONLY; 1757 memset(new->keynetdata.st_pub_key, 0, HEXKEYBYTES); 1758 new->keynetdata.st_netname = NULL; 1759 new->next = NULL; 1760 *l = new; 1761 } else { 1762 new = *l; 1763 if (key[0] == '\0') 1764 removecache(new->keynetdata.st_priv_key); 1765 } 1766 1767 memcpy(new->keynetdata.st_priv_key, key, 1768 HEXKEYBYTES); 1769 (void) rw_unlock(&g_secretkey_netname_lock); 1770 return (1); 1771 } 1772 1773 static int 1774 hexdigit(val) 1775 int val; 1776 { 1777 return ("0123456789abcdef"[val]); 1778 } 1779 1780 int 1781 bin2hex(bin, hex, size) 1782 unsigned char *bin; 1783 unsigned char *hex; 1784 int size; 1785 { 1786 int i; 1787 1788 for (i = 0; i < size; i++) { 1789 *hex++ = hexdigit(*bin >> 4); 1790 *hex++ = hexdigit(*bin++ & 0xf); 1791 } 1792 return (0); 1793 } 1794 1795 static int 1796 hexval(dig) 1797 char dig; 1798 { 1799 if ('0' <= dig && dig <= '9') { 1800 return (dig - '0'); 1801 } else if ('a' <= dig && dig <= 'f') { 1802 return (dig - 'a' + 10); 1803 } else if ('A' <= dig && dig <= 'F') { 1804 return (dig - 'A' + 10); 1805 } else { 1806 return (-1); 1807 } 1808 } 1809 1810 int 1811 hex2bin(hex, bin, size) 1812 unsigned char *hex; 1813 unsigned char *bin; 1814 int size; 1815 { 1816 int i; 1817 1818 for (i = 0; i < size; i++) { 1819 *bin = hexval(*hex++) << 4; 1820 *bin++ |= hexval(*hex++); 1821 } 1822 return (0); 1823 } 1824 1825 static int 1826 hash_keys(pub, sec) 1827 char *pub; 1828 char *sec; 1829 { 1830 int i; 1831 int hash = 0; 1832 1833 for (i = 0; i < HEXKEYBYTES; i += 6, pub += 6, sec += 6) { 1834 hash ^= *pub; 1835 hash ^= *sec; 1836 } 1837 return (hash & 0xff); 1838 } 1839 1840 /* 1841 * problem: keyserv loads keys from /etc/.rootkey based on nisauthconf(1M) 1842 * which is too nis+-centric (see secure_rpc(3N)). 1843 * 1844 * So we want to make sure there is always a AUTH_DES compat entry 1845 * in the "list" of nis+ mechs so that the 192bit key always gets loaded so 1846 * non-nis+ services that use AUTH_DES (e.g. nfs) won't get hosed. The real 1847 * hacky part of it is we muck with the array returned from 1848 * __nis_get_mechanisms which we really don't have any business 1849 * doing cause we should not know/care how that is implemented. A better 1850 * way would be to change the __nis_get_mechanisms interface or add another 1851 * one similiar to it that forces the "des" compat entry into the list. 1852 * 1853 * Return ptr to mechs array on success, else NULL on memory errs. 1854 */ 1855 mechanism_t ** 1856 getmechwrap() 1857 { 1858 mechanism_t **mechs = __nis_get_mechanisms(FALSE); 1859 mechanism_t **mechsbak = NULL; 1860 mechanism_t *desmech = NULL; 1861 int i = 0; 1862 1863 if (mechs) { 1864 /* got some valid mechs and possibly the AUTH_DES compat one */ 1865 for (i = 0; mechs[i]; i++) { 1866 if (AUTH_DES_COMPAT_CHK(mechs[i])) 1867 return (mechs); 1868 } 1869 /* i == number of ptrs not counting terminating NULL */ 1870 } 1871 1872 /* AUTH_DES compat entry not found, let's add it */ 1873 if ((desmech = malloc(sizeof (mechanism_t))) == NULL) { 1874 if (mechs) 1875 __nis_release_mechanisms(mechs); 1876 return (NULL); 1877 } 1878 desmech->mechname = NULL; 1879 desmech->alias = NIS_SEC_CF_DES_ALIAS; 1880 desmech->keylen = AUTH_DES_KEYLEN; 1881 desmech->algtype = AUTH_DES_ALGTYPE; 1882 desmech->qop = NULL; 1883 desmech->secserv = rpc_gss_svc_default; 1884 1885 mechsbak = mechs; 1886 /* mechs == NULL and i == 0 is valid "no mechs configed" case */ 1887 if ((mechs = (mechanism_t **)realloc(mechs, 1888 sizeof (mechanism_t *) * (i + 2))) == NULL) { 1889 if (mechsbak) 1890 __nis_release_mechanisms(mechsbak); 1891 free(desmech); 1892 return (NULL); 1893 } 1894 mechs[i] = desmech; 1895 mechs[i+1] = NULL; 1896 1897 return (mechs); 1898 } 1899 1900 int 1901 init_mechs() 1902 { 1903 int nmechs, oldmechseen; 1904 mechanism_t **mechpp; 1905 char **cpp; 1906 1907 if (!(mechs = getmechwrap())) 1908 return (-1); 1909 1910 /* 1911 * find how many mechanisms were specified and also 1912 * setup the mechanism table for unique keylen/algtype pair 1913 */ 1914 nmechs = 0; 1915 for (mechpp = mechs; *mechpp != NULL; mechpp++) { 1916 struct keylenlist **kpp; 1917 struct algtypelist **app; 1918 1919 nmechs++; 1920 if (((*mechpp)->keylen < 0) || ((*mechpp)->algtype < 0)) { 1921 continue; 1922 } 1923 kpp = getkeylen((*mechpp)->keylen); 1924 appendkeylist(kpp, (*mechpp)->keylen); 1925 app = getalgtype(kpp, (*mechpp)->algtype); 1926 appendalgtype(app, (*mechpp)->algtype); 1927 } 1928 1929 /* 1930 * set of mechs for getsubopt() 1931 */ 1932 cache_options = (char **)calloc((size_t)nmechs + 1, 1933 sizeof (*cache_options)); 1934 if (cache_options == NULL) { 1935 (void) fprintf(stderr, "unable to allocate option array"); 1936 return (-1); 1937 } 1938 /* 1939 * cache sizes 1940 */ 1941 cache_size = (int *)calloc((size_t)nmechs, sizeof (int)); 1942 if (cache_size == NULL) { 1943 (void) fprintf(stderr, "unable to allocate cache array"); 1944 return (-1); 1945 } 1946 1947 oldmechseen = 0; 1948 cpp = cache_options; 1949 for (mechpp = mechs; *mechpp != NULL; mechpp++) { 1950 /* 1951 * usual case: a DH-style mechanism type, with an alias 1952 */ 1953 if ((*mechpp)->mechname != NULL && 1954 strncmp((*mechpp)->mechname, DHMECHSTR, 1955 strlen(DHMECHSTR)) == 0 && 1956 (*mechpp)->alias != NULL) { 1957 /* 1958 * Is this trad 192-DH? already added? 1959 */ 1960 if (strcmp((*mechpp)->alias, DESALIAS) == 0) { 1961 if (oldmechseen) { 1962 continue; 1963 } 1964 oldmechseen++; 1965 } 1966 1967 *cpp++ = (*mechpp)->alias; 1968 continue; 1969 } 1970 1971 /* 1972 * HACK: we recognise a special alias for traditional 1973 * 192-bit DH, unless the latter has already been mentioned 1974 * in it's full form 1975 */ 1976 if ((*mechpp)->mechname == NULL && (*mechpp)->alias != NULL && 1977 strcmp((*mechpp)->alias, DES) == 0 && !oldmechseen) { 1978 *cpp++ = DESALIAS; 1979 oldmechseen++; 1980 continue; 1981 } 1982 1983 /* 1984 * Ignore anything else 1985 */ 1986 } 1987 1988 /* Terminate the options list */ 1989 *cpp = NULL; 1990 1991 return (0); 1992 } 1993