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