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