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 (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 27 /* All Rights Reserved */ 28 29 /* 30 * University Copyright- Copyright (c) 1982, 1986, 1988 31 * The Regents of the University of California 32 * All Rights Reserved 33 * 34 * University Acknowledgment- Portions of this document are derived from 35 * software developed by the University of California, Berkeley, and its 36 * contributors. 37 */ 38 39 #pragma ident "%Z%%M% %I% %E% SMI" 40 41 /* 42 * keyserv - server for storing private encryption keys 43 * keyserv(1M) performs multiple functions: it stores secret keys per uid; it 44 * performs public key encryption and decryption operations; and it generates 45 * "random" keys. keyserv(1M) will talk to no one but a local root process on 46 * the local transport only. 47 */ 48 49 #include <stdio.h> 50 #include <stdlib.h> 51 #include <sys/types.h> 52 #include <sys/stat.h> 53 #include <sys/uio.h> 54 #include <unistd.h> 55 #include <string.h> 56 #include <deflt.h> 57 #include <rpc/rpc.h> 58 #include <sys/param.h> 59 #include <sys/file.h> 60 #include <sys/resource.h> 61 #include <pwd.h> 62 #include <rpc/des_crypt.h> 63 #include <rpc/key_prot.h> 64 #include <thread.h> 65 #include "rpc/svc_mt.h" 66 #include <rpcsvc/nis_dhext.h> 67 #include <syslog.h> 68 #include <libscf.h> 69 70 #include "debug.h" 71 #include "keyserv_cache.h" 72 73 #ifdef KEYSERV_RANDOM 74 extern long random(); 75 #endif 76 77 extern keystatus pk_setkey(); 78 extern keystatus pk_encrypt(); 79 extern keystatus pk_decrypt(); 80 extern keystatus pk_netput(); 81 extern keystatus pk_netget(); 82 extern keystatus pk_get_conv_key(); 83 extern bool_t svc_get_local_cred(); 84 85 extern keystatus pk_setkey3(); 86 extern keystatus pk_encrypt3(); 87 extern keystatus pk_decrypt3(); 88 extern keystatus pk_netput3(); 89 extern keystatus pk_netget3(); 90 extern keystatus pk_get_conv_key3(); 91 extern keystatus pk_clear3(); 92 93 extern int init_mechs(); 94 extern int addmasterkey(); 95 extern int storeotherrootkeys(); 96 extern int setdeskeyarray(); 97 98 extern int getdomainname(); 99 100 static void randomize(); 101 static void usage(); 102 static void defaults(); 103 static int getrootkey(); 104 static int get_cache_size(char *); 105 static bool_t get_auth(); 106 107 #ifdef DEBUG 108 extern int test_debug(); 109 extern int real_debug(); 110 int debugging = 1; 111 #else 112 int debugging = 0; 113 #endif 114 115 static void keyprogram(); 116 static des_block masterkey; 117 char *getenv(); 118 static char ROOTKEY[] = "/etc/.rootkey"; 119 120 static char *defaults_file = "/etc/default/keyserv"; 121 static int use_nobody_keys = TRUE; 122 123 /* 124 * Hack to allow the keyserver to use AUTH_DES (for authenticated 125 * NIS+ calls, for example). The only functions that get called 126 * are key_encryptsession_pk, key_decryptsession_pk, and key_gendes. 127 * 128 * The approach is to have the keyserver fill in pointers to local 129 * implementations of these functions, and to call those in key_call(). 130 */ 131 132 bool_t __key_encrypt_pk_2_svc(); 133 bool_t __key_decrypt_pk_2_svc(); 134 bool_t __key_gen_1_svc(); 135 136 extern bool_t (*__key_encryptsession_pk_LOCAL)(); 137 extern bool_t (*__key_decryptsession_pk_LOCAL)(); 138 extern bool_t (*__key_gendes_LOCAL)(); 139 140 static int nthreads = 32; 141 142 /* Disk caching of common keys on by default */ 143 int disk_caching = 1; 144 145 mechanism_t **mechs; 146 147 /* 148 * The default size for all types of mech. 149 * positive integers denote multiples of 1MB 150 * negative integers denote number of entries 151 * same goes for non-null entries in cache_size 152 */ 153 static int default_cache = 1; 154 155 int *cache_size; 156 char **cache_options; 157 158 int 159 main(int argc, char *argv[]) 160 { 161 int sflag = 0, s1flag = 0, s2flag = 0, nflag = 0, dflag = 0, eflag = 0; 162 char *options, *value; 163 extern char *optarg; 164 extern int optind; 165 int c, d; 166 struct rlimit rl; 167 int mode = RPC_SVC_MT_AUTO; 168 int maxrecsz = RPC_MAXDATASIZE; 169 170 void detachfromtty(void); 171 int setmodulus(); 172 int pk_nodefaultkeys(); 173 int svc_create_local_service(); 174 175 char domainname[MAXNETNAMELEN + 1]; 176 177 /* 178 * Set our allowed number of file descriptors to the max 179 * of what the system will allow, limited by FD_SETSIZE. 180 */ 181 if (getrlimit(RLIMIT_NOFILE, &rl) == 0) { 182 rlim_t limit; 183 184 if ((limit = rl.rlim_max) > FD_SETSIZE) 185 limit = FD_SETSIZE; 186 rl.rlim_cur = limit; 187 (void) setrlimit(RLIMIT_NOFILE, &rl); 188 } 189 190 __key_encryptsession_pk_LOCAL = &__key_encrypt_pk_2_svc; 191 __key_decryptsession_pk_LOCAL = &__key_decrypt_pk_2_svc; 192 __key_gendes_LOCAL = &__key_gen_1_svc; 193 194 /* 195 * Pre-option initialisation 196 */ 197 (void) umask(066); /* paranoia */ 198 if (geteuid() != 0) { 199 (void) fprintf(stderr, "%s must be run as root\n", argv[0]); 200 exit(1); 201 } 202 setmodulus(HEXMODULUS); 203 openlog("keyserv", LOG_PID, LOG_DAEMON); 204 205 /* 206 * keyserv will not work with a null domainname. 207 */ 208 if (getdomainname(domainname, MAXNETNAMELEN+1) || 209 (domainname[0] == '\0')) { 210 syslog(LOG_ERR, "could not get a valid domainname.\n"); 211 exit(SMF_EXIT_ERR_CONFIG); 212 } 213 214 /* 215 * Initialise security mechanisms 216 */ 217 cache_size = NULL; 218 cache_options = NULL; 219 if (init_mechs() == -1) { 220 disk_caching = 0; 221 } 222 223 defaults(); 224 225 while ((c = getopt(argc, argv, "ndDet:cs:")) != -1) 226 switch (c) { 227 case 'n': 228 nflag++; 229 break; 230 case 'd': 231 dflag++; 232 use_nobody_keys = FALSE; 233 break; 234 case 'e': 235 eflag++; 236 use_nobody_keys = TRUE; 237 break; 238 case 'D': 239 debugging = 1; 240 break; 241 case 't': 242 nthreads = atoi(optarg); 243 break; 244 case 'c': 245 disk_caching = 0; 246 break; 247 case 's': 248 if (!disk_caching) { 249 fprintf(stderr, "missing configuration file"); 250 fprintf(stderr, " or -c option specified\n"); 251 usage(); 252 } 253 sflag++; 254 /* 255 * Which version of [-s] do we have...? 256 */ 257 if (strchr((const char *) optarg, '=') == NULL) { 258 /* 259 * -s <size> 260 */ 261 if (s1flag) { 262 fprintf(stderr, "duplicate [-s <size>]\n"); 263 usage(); 264 } 265 s1flag++; 266 default_cache = get_cache_size(optarg); 267 break; 268 } 269 /* 270 * -s <mechtype>=<size>[,...] 271 */ 272 s2flag++; 273 options = optarg; 274 while (*options != '\0') { 275 d = getsubopt(&options, cache_options, &value); 276 if (d == -1) { 277 /* Ignore unknown mechtype */ 278 continue; 279 } 280 if (value == NULL) { 281 fprintf(stderr, 282 "missing cache size for mechtype %s\n", 283 cache_options[d]); 284 usage(); 285 } 286 cache_size[d] = get_cache_size(value); 287 } 288 break; 289 default: 290 usage(); 291 break; 292 } 293 294 295 if (dflag && eflag) { 296 (void) fprintf(stderr, "specify only one of -d and -e\n"); 297 usage(); 298 } 299 300 if (use_nobody_keys == FALSE) { 301 pk_nodefaultkeys(); 302 } 303 304 if (optind != argc) { 305 usage(); 306 } 307 308 if (!disk_caching && sflag) { 309 fprintf(stderr, "missing configuration file"); 310 fprintf(stderr, " or -c option specified\n"); 311 usage(); 312 } 313 314 if (debugging) { 315 if (disk_caching) { 316 char **cpp = cache_options; 317 int *ip = cache_size; 318 (void) fprintf(stderr, "default disk cache size: "); 319 if (default_cache < 0) { 320 (void) fprintf(stderr, "%d entries\n", 321 abs(default_cache)); 322 } else { 323 (void) fprintf(stderr, "%dMB\n", default_cache); 324 } 325 326 (void) fprintf(stderr, "supported mechanisms:\n"); 327 (void) fprintf(stderr, "\talias\t\tdisk cache size\n"); 328 (void) fprintf(stderr, "\t=====\t\t===============\n"); 329 while (*cpp != NULL) { 330 (void) fprintf(stderr, "\t%s\t\t", *cpp++); 331 if (*ip < 0) { 332 (void) fprintf(stderr, "%d entries\n", 333 abs(*ip)); 334 } else { 335 (void) fprintf(stderr, "%dMB\n", *ip); 336 } 337 ip++; 338 } 339 } else { 340 (void) fprintf(stderr, 341 "common key disk caching disabled\n"); 342 } 343 } 344 /* 345 * Post-option initialisation 346 */ 347 if (disk_caching) { 348 int i; 349 for (i = 0; mechs[i]; i++) { 350 if ((AUTH_DES_COMPAT_CHK(mechs[i])) || 351 (mechs[i]->keylen < 0) || (mechs[i]->algtype < 0)) 352 continue; 353 create_cache_file(mechs[i]->keylen, mechs[i]->algtype, 354 cache_size[i] ? cache_size[i] : default_cache); 355 } 356 } 357 getrootkey(&masterkey, nflag); 358 359 /* 360 * Set MT mode 361 */ 362 if (nthreads > 0) { 363 (void) rpc_control(RPC_SVC_MTMODE_SET, &mode); 364 (void) rpc_control(RPC_SVC_THRMAX_SET, &nthreads); 365 } 366 367 /* 368 * Enable non-blocking mode and maximum record size checks for 369 * connection oriented transports. 370 */ 371 if (!rpc_control(RPC_SVC_CONNMAXREC_SET, &maxrecsz)) { 372 syslog(LOG_INFO, "unable to set max RPC record size"); 373 } 374 375 if (svc_create_local_service(keyprogram, KEY_PROG, KEY_VERS, 376 "netpath", "keyserv") == 0) { 377 syslog(LOG_ERR, 378 "%s: unable to create service for version %d\n", 379 argv[0], KEY_VERS); 380 exit(1); 381 } 382 383 if (svc_create_local_service(keyprogram, KEY_PROG, KEY_VERS2, 384 "netpath", "keyserv") == 0) { 385 syslog(LOG_ERR, 386 "%s: unable to create service for version %d\n", 387 argv[0], KEY_VERS2); 388 exit(1); 389 } 390 391 if (svc_create_local_service(keyprogram, KEY_PROG, KEY_VERS3, 392 "netpath", "keyserv") == 0) { 393 syslog(LOG_ERR, 394 "%s: unable to create service for version %d\n", 395 argv[0], KEY_VERS3); 396 exit(1); 397 } 398 399 if (!debugging) { 400 detachfromtty(); 401 } 402 403 if (svc_create(keyprogram, KEY_PROG, KEY_VERS, "door") == 0) { 404 syslog(LOG_ERR, 405 "%s: unable to create service over doors for version %d\n", 406 argv[0], KEY_VERS); 407 exit(1); 408 } 409 410 if (svc_create(keyprogram, KEY_PROG, KEY_VERS2, "door") == 0) { 411 syslog(LOG_ERR, 412 "%s: unable to create service over doors for version %d\n", 413 argv[0], KEY_VERS2); 414 exit(1); 415 } 416 417 if (svc_create(keyprogram, KEY_PROG, KEY_VERS3, "door") == 0) { 418 syslog(LOG_ERR, 419 "%s: unable to create service over doors for version %d\n", 420 argv[0], KEY_VERS3); 421 exit(1); 422 } 423 424 svc_run(); 425 abort(); 426 /* NOTREACHED */ 427 return (0); 428 } 429 430 431 /* 432 * In the event that we don't get a root password, we try to 433 * randomize the master key the best we can 434 */ 435 static void 436 randomize(master) 437 des_block *master; 438 { 439 int i; 440 int seed; 441 struct timeval tv; 442 int shift; 443 444 seed = 0; 445 for (i = 0; i < 1024; i++) { 446 (void) gettimeofday(&tv, (struct timezone *)NULL); 447 shift = i % 8 * sizeof (int); 448 seed ^= (tv.tv_usec << shift) | (tv.tv_usec >> (32 - shift)); 449 } 450 #ifdef KEYSERV_RANDOM 451 srandom(seed); 452 master->key.low = random(); 453 master->key.high = random(); 454 srandom(seed); 455 #else 456 /* use stupid dangerous bad rand() */ 457 srand(seed); 458 master->key.low = rand(); 459 master->key.high = rand(); 460 srand(seed); 461 #endif 462 } 463 464 static char * 465 fgets_ignorenul(char *s, int n, FILE *stream) 466 { 467 int fildes = fileno(stream); 468 int i = 0; 469 int rs = 0; 470 char c; 471 472 if (fildes < 0) 473 return (NULL); 474 475 while (i < n - 1) { 476 rs = read(fildes, &c, 1); 477 switch (rs) { 478 case 1: 479 break; 480 case 0: 481 /* EOF */ 482 if (i > 0) 483 s[i] = '\0'; 484 return (NULL); 485 break; 486 default: 487 return (NULL); 488 } 489 switch (c) { 490 case '\0': 491 break; 492 case '\n': 493 s[i] = c; 494 s[++i] = '\0'; 495 return (s); 496 default: 497 if (c != '\0') 498 s[i++] = c; 499 } 500 } 501 s[i] = '\0'; 502 return (s); 503 } 504 505 /* Should last until 16384-bit DH keys */ 506 #define MAXROOTKEY_LINE_LEN 4224 507 #define MAXROOTKEY_LEN 4096 508 #define ROOTKEY_FILE "/etc/.rootkey" 509 510 static int 511 getotherrootkeys(char *name) 512 { 513 FILE *rootkey; 514 char line[MAXROOTKEY_LINE_LEN]; 515 char key[MAXROOTKEY_LEN]; 516 algtype_t algtype; 517 int count = 0; 518 519 if (!(rootkey = fopen(ROOTKEY, "r"))) 520 return (0); 521 522 while (fgets_ignorenul(line, MAXROOTKEY_LINE_LEN, rootkey)) { 523 debug(KEYSERV_DEBUG0, ("ROOTKEY %d: %s\n", count, line)); 524 count++; 525 if (sscanf(line, "%s %d", key, &algtype) < 2) { 526 /* 527 * No encryption algorithm found in the file 528 * (algtype) so default to DES. 529 */ 530 algtype = AUTH_DES_ALGTYPE; 531 } 532 if (!strlen(key)) 533 continue; 534 addmasterkey(key, name, algtype); 535 } 536 fclose(rootkey); 537 return (1); 538 } 539 540 /* 541 * Try to get root's secret key, by prompting if terminal is a tty, else trying 542 * from standard input. 543 * Returns 1 on success. 544 */ 545 static int 546 getrootkey(master, prompt) 547 des_block *master; 548 int prompt; 549 { 550 char *passwd; 551 char name[MAXNETNAMELEN + 1]; 552 char secret[HEXKEYBYTES + 1]; 553 FILE *fp; 554 int passwd2des(); 555 int retval; 556 557 randomize(master); 558 if (!getnetname(name)) { 559 (void) fprintf(stderr, "keyserv: \ 560 failed to generate host's netname when establishing root's key.\n"); 561 return (0); 562 } 563 if (!prompt) { 564 return (getotherrootkeys(name)); 565 } 566 /* 567 * Decrypt yellow pages publickey entry to get secret key 568 */ 569 passwd = getpass("root password:"); 570 passwd2des(passwd, master); 571 if (!getsecretkey(name, secret, passwd)) { 572 (void) fprintf(stderr, 573 "Can't find %s's secret key\n", name); 574 return (0); 575 } 576 if (secret[0] == 0) { 577 (void) fprintf(stderr, 578 "Password does not decrypt secret key for %s\n", name); 579 return (0); 580 } 581 if ((fp = fopen(ROOTKEY, "w")) == NULL) { 582 (void) fprintf(stderr, 583 "Cannot open %s for write\n", ROOTKEY); 584 return (0); 585 } 586 retval = storeotherrootkeys(fp, name, passwd, secret); 587 fclose(fp); 588 return (retval); 589 } 590 591 /* 592 * Procedures to implement RPC service. These procedures are named 593 * differently from the definitions in key_prot.h (generated by rpcgen) 594 * because they take different arguments. 595 */ 596 char * 597 strstatus(status) 598 keystatus status; 599 { 600 switch (status) { 601 case KEY_SUCCESS: 602 return ("KEY_SUCCESS"); 603 case KEY_NOSECRET: 604 return ("KEY_NOSECRET"); 605 case KEY_UNKNOWN: 606 return ("KEY_UNKNOWN"); 607 case KEY_SYSTEMERR: 608 return ("KEY_SYSTEMERR"); 609 case KEY_BADALG: 610 return ("KEY_BADALG"); 611 case KEY_BADLEN: 612 return ("KEY_BADLEN"); 613 default: 614 return ("(bad result code)"); 615 } 616 } 617 618 bool_t 619 __key_set_1_svc(uid, key, status) 620 uid_t uid; 621 keybuf key; 622 keystatus *status; 623 { 624 if (debugging) { 625 (void) fprintf(stderr, "set(%d, %.*s) = ", uid, 626 sizeof (keybuf), key); 627 } 628 *status = pk_setkey(uid, key); 629 if (debugging) { 630 (void) fprintf(stderr, "%s\n", strstatus(*status)); 631 (void) fflush(stderr); 632 } 633 return (TRUE); 634 } 635 636 bool_t 637 __key_encrypt_pk_2_svc(uid, arg, res) 638 uid_t uid; 639 cryptkeyarg2 *arg; 640 cryptkeyres *res; 641 { 642 643 if (debugging) { 644 (void) fprintf(stderr, "encrypt(%d, %s, %08x%08x) = ", uid, 645 arg->remotename, arg->deskey.key.high, 646 arg->deskey.key.low); 647 } 648 res->cryptkeyres_u.deskey = arg->deskey; 649 res->status = pk_encrypt(uid, arg->remotename, &(arg->remotekey), 650 &res->cryptkeyres_u.deskey); 651 if (debugging) { 652 if (res->status == KEY_SUCCESS) { 653 (void) fprintf(stderr, "%08x%08x\n", 654 res->cryptkeyres_u.deskey.key.high, 655 res->cryptkeyres_u.deskey.key.low); 656 } else { 657 (void) fprintf(stderr, "%s\n", strstatus(res->status)); 658 } 659 (void) fflush(stderr); 660 } 661 return (TRUE); 662 } 663 664 bool_t 665 __key_decrypt_pk_2_svc(uid, arg, res) 666 uid_t uid; 667 cryptkeyarg2 *arg; 668 cryptkeyres *res; 669 { 670 671 if (debugging) { 672 (void) fprintf(stderr, "decrypt(%d, %s, %08x%08x) = ", uid, 673 arg->remotename, arg->deskey.key.high, 674 arg->deskey.key.low); 675 } 676 res->cryptkeyres_u.deskey = arg->deskey; 677 res->status = pk_decrypt(uid, arg->remotename, &(arg->remotekey), 678 &res->cryptkeyres_u.deskey); 679 if (debugging) { 680 if (res->status == KEY_SUCCESS) { 681 (void) fprintf(stderr, "%08x%08x\n", 682 res->cryptkeyres_u.deskey.key.high, 683 res->cryptkeyres_u.deskey.key.low); 684 } else { 685 (void) fprintf(stderr, "%s\n", strstatus(res->status)); 686 } 687 (void) fflush(stderr); 688 } 689 return (TRUE); 690 } 691 692 bool_t 693 __key_net_put_2_svc(uid, arg, status) 694 uid_t uid; 695 key_netstarg *arg; 696 keystatus *status; 697 { 698 699 if (debugging) { 700 (void) fprintf(stderr, "net_put(%s, %.*s, %.*s) = ", 701 arg->st_netname, sizeof (arg->st_pub_key), 702 arg->st_pub_key, sizeof (arg->st_priv_key), 703 arg->st_priv_key); 704 }; 705 706 *status = pk_netput(uid, arg); 707 708 if (debugging) { 709 (void) fprintf(stderr, "%s\n", strstatus(*status)); 710 (void) fflush(stderr); 711 } 712 713 return (TRUE); 714 } 715 716 /* ARGSUSED */ 717 bool_t 718 __key_net_get_2_svc(uid, arg, keynetname) 719 uid_t uid; 720 void *arg; 721 key_netstres *keynetname; 722 { 723 724 if (debugging) 725 (void) fprintf(stderr, "net_get(%d) = ", uid); 726 727 keynetname->status = pk_netget(uid, &keynetname->key_netstres_u.knet); 728 if (debugging) { 729 if (keynetname->status == KEY_SUCCESS) { 730 fprintf(stderr, "<%s, %.*s, %.*s>\n", 731 keynetname->key_netstres_u.knet.st_netname, 732 sizeof (keynetname->key_netstres_u.knet.st_pub_key), 733 keynetname->key_netstres_u.knet.st_pub_key, 734 sizeof (keynetname->key_netstres_u.knet.st_priv_key), 735 keynetname->key_netstres_u.knet.st_priv_key); 736 } else { 737 (void) fprintf(stderr, "NOT FOUND\n"); 738 } 739 (void) fflush(stderr); 740 } 741 742 return (TRUE); 743 744 } 745 746 bool_t 747 __key_get_conv_2_svc(uid, arg, res) 748 uid_t uid; 749 keybuf arg; 750 cryptkeyres *res; 751 { 752 753 if (debugging) 754 (void) fprintf(stderr, "get_conv(%d, %.*s) = ", uid, 755 sizeof (arg), arg); 756 757 758 res->status = pk_get_conv_key(uid, arg, res); 759 760 if (debugging) { 761 if (res->status == KEY_SUCCESS) { 762 (void) fprintf(stderr, "%08x%08x\n", 763 res->cryptkeyres_u.deskey.key.high, 764 res->cryptkeyres_u.deskey.key.low); 765 } else { 766 (void) fprintf(stderr, "%s\n", strstatus(res->status)); 767 } 768 (void) fflush(stderr); 769 } 770 return (TRUE); 771 } 772 773 774 bool_t 775 __key_encrypt_1_svc(uid, arg, res) 776 uid_t uid; 777 cryptkeyarg *arg; 778 cryptkeyres *res; 779 { 780 781 if (debugging) { 782 (void) fprintf(stderr, "encrypt(%d, %s, %08x%08x) = ", uid, 783 arg->remotename, arg->deskey.key.high, 784 arg->deskey.key.low); 785 } 786 res->cryptkeyres_u.deskey = arg->deskey; 787 res->status = pk_encrypt(uid, arg->remotename, NULL, 788 &res->cryptkeyres_u.deskey); 789 if (debugging) { 790 if (res->status == KEY_SUCCESS) { 791 (void) fprintf(stderr, "%08x%08x\n", 792 res->cryptkeyres_u.deskey.key.high, 793 res->cryptkeyres_u.deskey.key.low); 794 } else { 795 (void) fprintf(stderr, "%s\n", strstatus(res->status)); 796 } 797 (void) fflush(stderr); 798 } 799 return (TRUE); 800 } 801 802 bool_t 803 __key_decrypt_1_svc(uid, arg, res) 804 uid_t uid; 805 cryptkeyarg *arg; 806 cryptkeyres *res; 807 { 808 if (debugging) { 809 (void) fprintf(stderr, "decrypt(%d, %s, %08x%08x) = ", uid, 810 arg->remotename, arg->deskey.key.high, 811 arg->deskey.key.low); 812 } 813 res->cryptkeyres_u.deskey = arg->deskey; 814 res->status = pk_decrypt(uid, arg->remotename, NULL, 815 &res->cryptkeyres_u.deskey); 816 if (debugging) { 817 if (res->status == KEY_SUCCESS) { 818 (void) fprintf(stderr, "%08x%08x\n", 819 res->cryptkeyres_u.deskey.key.high, 820 res->cryptkeyres_u.deskey.key.low); 821 } else { 822 (void) fprintf(stderr, "%s\n", strstatus(res->status)); 823 } 824 (void) fflush(stderr); 825 } 826 return (TRUE); 827 } 828 829 /* ARGSUSED */ 830 bool_t 831 __key_gen_1_svc(v, s, key) 832 void *v; 833 struct svc_req *s; 834 des_block *key; 835 { 836 struct timeval time; 837 static des_block keygen; 838 static mutex_t keygen_mutex = DEFAULTMUTEX; 839 int r; 840 841 (void) gettimeofday(&time, (struct timezone *)NULL); 842 (void) mutex_lock(&keygen_mutex); 843 keygen.key.high += (time.tv_sec ^ time.tv_usec); 844 keygen.key.low += (time.tv_sec ^ time.tv_usec); 845 r = ecb_crypt((char *)&masterkey, (char *)&keygen, sizeof (keygen), 846 DES_ENCRYPT | DES_HW); 847 if (r != DESERR_NONE && r != DESERR_NOHWDEVICE) { 848 mutex_unlock(&keygen_mutex); 849 return (FALSE); 850 } 851 *key = keygen; 852 mutex_unlock(&keygen_mutex); 853 854 des_setparity_g(key); 855 if (debugging) { 856 (void) fprintf(stderr, "gen() = %08x%08x\n", key->key.high, 857 key->key.low); 858 (void) fflush(stderr); 859 } 860 return (TRUE); 861 } 862 863 /* ARGSUSED */ 864 bool_t 865 __key_getcred_1_svc(uid, name, res) 866 uid_t uid; 867 netnamestr *name; 868 getcredres *res; 869 { 870 struct unixcred *cred; 871 872 cred = &res->getcredres_u.cred; 873 if (!netname2user(*name, (uid_t *)&cred->uid, (gid_t *)&cred->gid, 874 (int *)&cred->gids.gids_len, 875 (gid_t *)cred->gids.gids_val)) { 876 res->status = KEY_UNKNOWN; 877 } else { 878 res->status = KEY_SUCCESS; 879 } 880 if (debugging) { 881 (void) fprintf(stderr, "getcred(%s) = ", *name); 882 if (res->status == KEY_SUCCESS) { 883 (void) fprintf(stderr, "uid=%d, gid=%d, grouplen=%d\n", 884 cred->uid, cred->gid, cred->gids.gids_len); 885 } else { 886 (void) fprintf(stderr, "%s\n", strstatus(res->status)); 887 } 888 (void) fflush(stderr); 889 } 890 return (TRUE); 891 } 892 893 /* 894 * Version 3 procedures follow... 895 */ 896 897 static bool_t 898 __key_set_3_svc(uid_t uid, setkeyarg3 *arg, keystatus *status) 899 { 900 debug(KEYSERV_DEBUG, ("__key_set_3_svc(%d, %d, %d)", 901 uid, arg->algtype, arg->keylen)); 902 *status = pk_setkey3(uid, arg); 903 debug(KEYSERV_DEBUG, ("__key_set_3_svc %s", strstatus(*status))); 904 return (TRUE); 905 } 906 907 static bool_t 908 __key_encrypt_3_svc(uid_t uid, cryptkeyarg3 *arg, cryptkeyres3 *res) 909 { 910 int len, i; 911 des_block *dp; 912 913 debug(KEYSERV_DEBUG, ("encrypt_3(%d %d %s)", uid, 914 arg->deskey.deskeyarray_len, arg->remotename)); 915 res->status = pk_encrypt3(uid, arg, &res->cryptkeyres3_u.deskey); 916 len = res->cryptkeyres3_u.deskey.deskeyarray_len; 917 dp = res->cryptkeyres3_u.deskey.deskeyarray_val; 918 for (i = 0; i < len; i++) { 919 debug(KEYSERV_DEBUG0, ("encrypt_3 retval[%d] == (%x,%x)", 920 i, dp->key.high, dp->key.low)); 921 dp++; 922 } 923 debug(KEYSERV_DEBUG, ("encrypt_3 returned %s", strstatus(res->status))); 924 return (TRUE); 925 } 926 927 static bool_t 928 __key_decrypt_3_svc(uid_t uid, cryptkeyarg3 *arg, cryptkeyres3 *res) 929 { 930 int len, i; 931 des_block *dp; 932 933 debug(KEYSERV_DEBUG, ("decrypt_3(%d, %d, %s)", uid, 934 arg->deskey.deskeyarray_len, arg->remotename)); 935 res->status = pk_decrypt3(uid, arg, &res->cryptkeyres3_u.deskey); 936 len = res->cryptkeyres3_u.deskey.deskeyarray_len; 937 dp = res->cryptkeyres3_u.deskey.deskeyarray_val; 938 for (i = 0; i < len; i++) { 939 debug(KEYSERV_DEBUG0, ("decrypt_3 retval[%d] == (%x,%x)", 940 i, dp->key.high, dp->key.low)); 941 dp++; 942 } 943 debug(KEYSERV_DEBUG, ("decrypt_3 returned %s", strstatus(res->status))); 944 return (TRUE); 945 } 946 947 /* ARGSUSED */ 948 static bool_t 949 __key_gen_3_svc(void *v, keynum_t *kp, deskeyarray *res) 950 { 951 int i; 952 keynum_t keynum = *kp; 953 954 debug(KEYSERV_DEBUG, ("gen_3(%d %x)", keynum, res)); 955 res->deskeyarray_val = 0; 956 if (!setdeskeyarray(res, keynum)) { 957 return (FALSE); 958 } 959 for (i = 0; i < keynum; i++) { 960 debug(KEYSERV_DEBUG, ("gen_3 calling gen_1 %x", 961 res->deskeyarray_val+i)); 962 __key_gen_1_svc((void *) NULL, (struct svc_req *)NULL, 963 res->deskeyarray_val+i); 964 debug(KEYSERV_DEBUG, ("gen_3 val %d %x", 965 i, *(int *)(res->deskeyarray_val+i))); 966 } 967 return (TRUE); 968 } 969 970 static void 971 __key_gen_3_svc_free(deskeyarray *dp) 972 { 973 free(dp->deskeyarray_val); 974 } 975 976 static bool_t 977 __key_getcred_3_svc(uid_t uid, netnamestr *name, getcredres3 *res) 978 { 979 return (__key_getcred_1_svc(uid, name, (getcredres *)res)); 980 } 981 982 static bool_t 983 __key_encrypt_pk_3_svc(uid_t uid, cryptkeyarg3 *arg, cryptkeyres3 *res) 984 { 985 debug(KEYSERV_DEBUG, ("encrypt_pk_3(%d, %s)", uid, arg->remotename)); 986 res->status = pk_encrypt3(uid, arg, &res->cryptkeyres3_u.deskey); 987 debug(KEYSERV_DEBUG, ("encrypt returned %s", strstatus(res->status))); 988 return (TRUE); 989 } 990 991 static void 992 __key_encrypt_pk_3_svc_free(cryptkeyres3 *res) 993 { 994 if (res->status == KEY_SUCCESS) { 995 free(res->cryptkeyres3_u.deskey.deskeyarray_val); 996 } 997 } 998 999 static bool_t 1000 __key_decrypt_pk_3(uid_t uid, cryptkeyarg3 *arg, cryptkeyres3 *res) 1001 { 1002 debug(KEYSERV_DEBUG, ("decrypt_pk_3(%d, %s)", uid, arg->remotename)); 1003 res->status = pk_decrypt3(uid, arg, &res->cryptkeyres3_u.deskey); 1004 debug(KEYSERV_DEBUG, ("encrypt returned %s", strstatus(res->status))); 1005 return (TRUE); 1006 } 1007 1008 static void 1009 __key_decrypt_pk_3_free(cryptkeyres3 *res) 1010 { 1011 if (res->status == KEY_SUCCESS) { 1012 free(res->cryptkeyres3_u.deskey.deskeyarray_val); 1013 } 1014 } 1015 1016 static bool_t 1017 __key_net_put_3_svc(uid_t uid, key_netstarg3 *arg, keystatus *status) 1018 { 1019 debug(KEYSERV_DEBUG, ("net_put_3 (%d, %x)", uid, arg)); 1020 *status = pk_netput3(uid, arg); 1021 debug(KEYSERV_DEBUG, ("net_put_3 ret %s", strstatus(*status))); 1022 return (TRUE); 1023 } 1024 1025 static bool_t 1026 __key_net_get_3_svc(uid_t uid, mechtype *arg, key_netstres3 *keynetname) 1027 { 1028 debug(KEYSERV_DEBUG, ("net_get_3 (%d, %x)", uid, arg)); 1029 keynetname->status = pk_netget3(uid, 1030 arg, &keynetname->key_netstres3_u.knet); 1031 debug(KEYSERV_DEBUG, 1032 ("net_get_3 ret %s", strstatus(keynetname->status))); 1033 return (TRUE); 1034 } 1035 1036 static void 1037 __key_net_get_3_svc_free(key_netstres3 *keynetname) 1038 { 1039 if (keynetname->status == KEY_SUCCESS) { 1040 free(keynetname->key_netstres3_u.knet.st_priv_key.keybuf3_val); 1041 free(keynetname->key_netstres3_u.knet.st_pub_key.keybuf3_val); 1042 free(keynetname->key_netstres3_u.knet.st_netname); 1043 } 1044 } 1045 1046 static bool_t 1047 __key_get_conv_3_svc(uid_t uid, deskeyarg3 *arg, cryptkeyres3 *res) 1048 { 1049 debug(KEYSERV_DEBUG, ("get_conv_3(%d %x %x)", uid, arg, res)); 1050 res->status = pk_get_conv_key3(uid, arg, res); 1051 debug(KEYSERV_DEBUG, 1052 ("get_conv_3 ret %s", strstatus(res->status))); 1053 return (TRUE); 1054 } 1055 1056 /* ARGSUSED */ 1057 static bool_t 1058 __key_clear_3_svc(uid_t uid, void *arg, keystatus *status) 1059 { 1060 debug(KEYSERV_DEBUG, ("clear_3(%d)", uid)); 1061 *status = pk_clear3(uid); 1062 debug(KEYSERV_DEBUG, ("clear_3 ret %s", strstatus(*status))); 1063 return (TRUE); 1064 } 1065 1066 /* 1067 * RPC boilerplate 1068 */ 1069 static void 1070 keyprogram(rqstp, transp) 1071 struct svc_req *rqstp; 1072 SVCXPRT *transp; 1073 { 1074 union { 1075 keybuf key_set_1_arg; 1076 cryptkeyarg key_encrypt_1_arg; 1077 cryptkeyarg key_decrypt_1_arg; 1078 netnamestr key_getcred_1_arg; 1079 cryptkeyarg key_encrypt_2_arg; 1080 cryptkeyarg key_decrypt_2_arg; 1081 netnamestr key_getcred_2_arg; 1082 cryptkeyarg2 key_encrypt_pk_2_arg; 1083 cryptkeyarg2 key_decrypt_pk_2_arg; 1084 key_netstarg key_net_put_2_arg; 1085 netobj key_get_conv_2_arg; 1086 keybuf3 key_set_3_arg; 1087 cryptkeyarg3 key_encrypt_3_arg; 1088 cryptkeyarg3 key_decrypt_3_arg; 1089 cryptkeyarg3 key_encrypt_pk_3_arg; 1090 cryptkeyarg3 key_decrypt_pk_3_arg; 1091 keynum_t key_gen_3_arg; 1092 netnamestr key_getcred_3_arg; 1093 key_netstarg3 key_net_put_3_arg; 1094 key_netstarg3 key_net_get_3_arg; 1095 deskeyarg3 key_get_conv_3_arg; 1096 } argument; 1097 union { 1098 keystatus status; 1099 cryptkeyres cres; 1100 des_block key; 1101 getcredres gres; 1102 key_netstres keynetname; 1103 cryptkeyres3 cres3; 1104 deskeyarray keyarray; 1105 getcredres3 gres3; 1106 key_netstres3 keynetname3; 1107 } result; 1108 uint_t gids[MAXGIDS]; 1109 char netname_str[MAXNETNAMELEN + 1]; 1110 bool_t (*xdr_argument)(), (*xdr_result)(); 1111 bool_t (*local)(); 1112 void (*local_free)() = NULL; 1113 bool_t retval; 1114 uid_t uid; 1115 int check_auth; 1116 1117 switch (rqstp->rq_proc) { 1118 case NULLPROC: 1119 svc_sendreply(transp, xdr_void, (char *)NULL); 1120 return; 1121 1122 case KEY_SET: 1123 xdr_argument = xdr_keybuf; 1124 xdr_result = xdr_int; 1125 local = __key_set_1_svc; 1126 check_auth = 1; 1127 break; 1128 1129 case KEY_ENCRYPT: 1130 xdr_argument = xdr_cryptkeyarg; 1131 xdr_result = xdr_cryptkeyres; 1132 local = __key_encrypt_1_svc; 1133 check_auth = 1; 1134 break; 1135 1136 case KEY_DECRYPT: 1137 xdr_argument = xdr_cryptkeyarg; 1138 xdr_result = xdr_cryptkeyres; 1139 local = __key_decrypt_1_svc; 1140 check_auth = 1; 1141 break; 1142 1143 case KEY_GEN: 1144 xdr_argument = xdr_void; 1145 xdr_result = xdr_des_block; 1146 local = __key_gen_1_svc; 1147 check_auth = 0; 1148 break; 1149 1150 case KEY_GETCRED: 1151 xdr_argument = xdr_netnamestr; 1152 xdr_result = xdr_getcredres; 1153 local = __key_getcred_1_svc; 1154 result.gres.getcredres_u.cred.gids.gids_val = gids; 1155 check_auth = 0; 1156 break; 1157 1158 case KEY_ENCRYPT_PK: 1159 xdr_argument = xdr_cryptkeyarg2; 1160 xdr_result = xdr_cryptkeyres; 1161 local = __key_encrypt_pk_2_svc; 1162 check_auth = 1; 1163 break; 1164 1165 case KEY_DECRYPT_PK: 1166 xdr_argument = xdr_cryptkeyarg2; 1167 xdr_result = xdr_cryptkeyres; 1168 local = __key_decrypt_pk_2_svc; 1169 check_auth = 1; 1170 break; 1171 1172 1173 case KEY_NET_PUT: 1174 xdr_argument = xdr_key_netstarg; 1175 xdr_result = xdr_keystatus; 1176 local = __key_net_put_2_svc; 1177 check_auth = 1; 1178 break; 1179 1180 case KEY_NET_GET: 1181 xdr_argument = (xdrproc_t)xdr_void; 1182 xdr_result = xdr_key_netstres; 1183 local = __key_net_get_2_svc; 1184 result.keynetname.key_netstres_u.knet.st_netname = netname_str; 1185 check_auth = 1; 1186 break; 1187 1188 case KEY_GET_CONV: 1189 xdr_argument = (xdrproc_t)xdr_keybuf; 1190 xdr_result = xdr_cryptkeyres; 1191 local = __key_get_conv_2_svc; 1192 check_auth = 1; 1193 break; 1194 1195 /* 1196 * Version 3 procedures follow... 1197 */ 1198 1199 case KEY_SET_3: 1200 xdr_argument = (xdrproc_t)xdr_setkeyarg3; 1201 xdr_result = xdr_keystatus; 1202 local = __key_set_3_svc; 1203 check_auth = 1; 1204 break; 1205 1206 case KEY_ENCRYPT_3: 1207 xdr_argument = (xdrproc_t)xdr_cryptkeyarg3; 1208 xdr_result = xdr_cryptkeyres3; 1209 local = __key_encrypt_3_svc; 1210 check_auth = 1; 1211 break; 1212 1213 case KEY_DECRYPT_3: 1214 xdr_argument = (xdrproc_t)xdr_cryptkeyarg3; 1215 xdr_result = xdr_cryptkeyres3; 1216 local = __key_decrypt_3_svc; 1217 check_auth = 1; 1218 break; 1219 1220 case KEY_GEN_3: 1221 xdr_argument = (xdrproc_t)xdr_keynum_t; 1222 xdr_result = xdr_deskeyarray; 1223 local = __key_gen_3_svc; 1224 local_free = __key_gen_3_svc_free; 1225 check_auth = 0; 1226 break; 1227 1228 case KEY_GETCRED_3: 1229 xdr_argument = (xdrproc_t)xdr_netnamestr; 1230 xdr_result = xdr_getcredres3; 1231 local = __key_getcred_3_svc; 1232 check_auth = 0; 1233 break; 1234 1235 case KEY_ENCRYPT_PK_3: 1236 xdr_argument = (xdrproc_t)xdr_cryptkeyarg3; 1237 xdr_result = xdr_cryptkeyres3; 1238 local = __key_encrypt_pk_3_svc; 1239 local_free = __key_encrypt_pk_3_svc_free; 1240 check_auth = 1; 1241 break; 1242 1243 case KEY_DECRYPT_PK_3: 1244 xdr_argument = (xdrproc_t)xdr_cryptkeyarg3; 1245 xdr_result = xdr_cryptkeyres3; 1246 local = __key_decrypt_pk_3; 1247 local_free = __key_decrypt_pk_3_free; 1248 check_auth = 1; 1249 break; 1250 1251 case KEY_NET_PUT_3: 1252 xdr_argument = (xdrproc_t)xdr_key_netstarg3; 1253 xdr_result = xdr_keystatus; 1254 local = __key_net_put_3_svc; 1255 check_auth = 1; 1256 break; 1257 1258 case KEY_NET_GET_3: 1259 xdr_argument = (xdrproc_t)xdr_mechtype; 1260 xdr_result = xdr_key_netstres3; 1261 local = __key_net_get_3_svc; 1262 local_free = __key_net_get_3_svc_free; 1263 check_auth = 1; 1264 break; 1265 1266 case KEY_GET_CONV_3: 1267 xdr_argument = (xdrproc_t)xdr_deskeyarg3; 1268 xdr_result = xdr_cryptkeyres3; 1269 local = __key_get_conv_3_svc; 1270 check_auth = 1; 1271 break; 1272 1273 case KEY_CLEAR_3: 1274 xdr_argument = (xdrproc_t)xdr_void; 1275 xdr_result = xdr_keystatus; 1276 local = __key_clear_3_svc; 1277 check_auth = 1; 1278 break; 1279 1280 default: 1281 svcerr_noproc(transp); 1282 return; 1283 } 1284 if (check_auth) { 1285 if (!get_auth(transp, rqstp, &uid)) { 1286 if (debugging) { 1287 (void) fprintf(stderr, 1288 "not local privileged process\n"); 1289 } 1290 svcerr_weakauth(transp); 1291 return; 1292 } 1293 } 1294 1295 memset((char *)&argument, 0, sizeof (argument)); 1296 if (!svc_getargs(transp, xdr_argument, (caddr_t)&argument)) { 1297 svcerr_decode(transp); 1298 return; 1299 } 1300 retval = (*local)(uid, &argument, &result); 1301 if (retval && !svc_sendreply(transp, xdr_result, (char *)&result)) { 1302 if (debugging) 1303 (void) fprintf(stderr, "unable to reply\n"); 1304 svcerr_systemerr(transp); 1305 } 1306 if (!svc_freeargs(transp, xdr_argument, (caddr_t)&argument)) { 1307 if (debugging) 1308 (void) fprintf(stderr, 1309 "unable to free arguments\n"); 1310 exit(1); 1311 } 1312 if (local_free) { 1313 (*local_free)(&result); 1314 } 1315 } 1316 1317 static bool_t 1318 get_auth(trans, rqstp, uid) 1319 SVCXPRT *trans; 1320 struct svc_req *rqstp; 1321 uid_t *uid; 1322 { 1323 svc_local_cred_t cred; 1324 1325 if (!svc_get_local_cred(trans, &cred)) { 1326 if (debugging) 1327 fprintf(stderr, "svc_get_local_cred failed %s %s\n", 1328 trans->xp_netid, trans->xp_tp); 1329 return (FALSE); 1330 } 1331 if (debugging) 1332 fprintf(stderr, "local_uid %d\n", cred.euid); 1333 if (rqstp->rq_cred.oa_flavor == AUTH_SYS || 1334 rqstp->rq_cred.oa_flavor == AUTH_LOOPBACK) { 1335 /* LINTED pointer alignment */ 1336 *uid = ((struct authunix_parms *)rqstp->rq_clntcred)->aup_uid; 1337 return (*uid == cred.euid || cred.euid == 0); 1338 } else { 1339 *uid = cred.euid; 1340 return (TRUE); 1341 } 1342 } 1343 1344 static int 1345 get_cache_size(size) 1346 char *size; 1347 { 1348 int csize, len; 1349 1350 len = (int)strlen(size); 1351 if (len == 0) { 1352 usage(); 1353 } 1354 1355 if (size[len-1] == 'M' || size[len-1] == 'm') { 1356 /* 1357 * cache size in MB 1358 */ 1359 size[len-1] = '\0'; 1360 csize = atoi(size); 1361 } else { 1362 csize = atoi(size); 1363 /* 1364 * negative size indicates number of entries in cache 1365 */ 1366 csize = 0 - csize; 1367 } 1368 1369 if (csize == 0) { 1370 (void) fprintf(stderr, "invalid cache size: %s\n", size); 1371 usage(); 1372 } 1373 1374 return (csize); 1375 } 1376 1377 static void 1378 usage() 1379 { 1380 (void) fprintf(stderr, "usage: \n"); 1381 (void) fprintf(stderr, "keyserv [-c]|[-s "); 1382 (void) fprintf(stderr, "<size>|<mechtype>=<size>[,...]] [-n] [-D] "); 1383 (void) fprintf(stderr, "[-d | -e] "); 1384 (void) fprintf(stderr, "[-t threads]\n"); 1385 (void) fprintf(stderr, "-d disables the use of default keys\n"); 1386 (void) fprintf(stderr, "-e enables the use of default keys\n"); 1387 exit(1); 1388 } 1389 1390 static void 1391 defaults(void) 1392 { 1393 register int flags; 1394 register char *ptr; 1395 1396 if (defopen(defaults_file) == 0) { 1397 /* 1398 * ignore case 1399 */ 1400 flags = defcntl(DC_GETFLAGS, 0); 1401 TURNOFF(flags, DC_CASE); 1402 defcntl(DC_SETFLAGS, flags); 1403 1404 if ((ptr = defread("ENABLE_NOBODY_KEYS=")) != NULL) { 1405 if (strcasecmp(ptr, "NO") == 0) { 1406 use_nobody_keys = FALSE; 1407 } 1408 } 1409 1410 (void) defopen((char *)NULL); 1411 } 1412 } 1413