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