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 2007 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 28 /* All Rights Reserved */ 29 /* 30 * Portions of this source code were derived from Berkeley 31 * 4.3 BSD under license from the Regents of the University of 32 * California. 33 */ 34 35 /* 36 * Interface to keyserver 37 * 38 * setsecretkey(key) - set your secret key 39 * encryptsessionkey(agent, deskey) - encrypt a session key to talk to agent 40 * decryptsessionkey(agent, deskey) - decrypt ditto 41 * gendeskey(deskey) - generate a secure des key 42 */ 43 44 #include "mt.h" 45 #include "rpc_mt.h" 46 #include <errno.h> 47 #include <rpc/rpc.h> 48 #include <rpc/key_prot.h> 49 #include <stdio.h> 50 #include <syslog.h> 51 #include <string.h> 52 #include <stdlib.h> 53 #include <unistd.h> 54 #include <sys/types.h> 55 #include <sys/stat.h> 56 57 #define CLASSIC_PK_DH(k, a) (((k) == 192) && ((a) == 0)) 58 59 #ifdef DEBUG 60 #define debug(msg) (void) fprintf(stderr, "%s\n", msg); 61 #else 62 #define debug(msg) 63 #endif /* DEBUG */ 64 65 int key_call(rpcproc_t, xdrproc_t, char *, xdrproc_t, char *); 66 int key_call_ext(rpcproc_t, xdrproc_t, char *, xdrproc_t, char *, int); 67 int key_setnet(struct key_netstarg *); 68 69 /* 70 * Hack to allow the keyserver to use AUTH_DES (for authenticated 71 * NIS+ calls, for example). The only functions that get called 72 * are key_encryptsession_pk, key_decryptsession_pk, and key_gendes. 73 * 74 * The approach is to have the keyserver fill in pointers to local 75 * implementations of these functions, and to call those in key_call(). 76 */ 77 78 bool_t (*__key_encryptsession_pk_LOCAL)() = NULL; 79 bool_t (*__key_decryptsession_pk_LOCAL)() = NULL; 80 bool_t (*__key_gendes_LOCAL)() = NULL; 81 82 83 int 84 key_setsecret(const char *secretkey) 85 { 86 char netName[MAXNETNAMELEN+1]; 87 struct key_netstarg netst; 88 int ret; 89 90 if (getnetname(netName) == 0) { 91 debug("getnetname failed"); 92 return (-1); 93 } 94 95 (void) memcpy(netst.st_priv_key, secretkey, HEXKEYBYTES); 96 netst.st_pub_key[0] = 0; 97 netst.st_netname = netName; 98 99 /* 100 * Actual key login 101 * We perform the KEY_NET_PUT instead of the SET_KEY 102 * rpc call because key_secretkey_is_set function uses 103 * the KEY_NET_GET call which expects the netname to be 104 * set along with the key. Keylogin also uses KEY_NET_PUT. 105 */ 106 ret = key_setnet(&netst); 107 108 /* erase our copy of the secret key */ 109 (void) memset(netst.st_priv_key, '\0', HEXKEYBYTES); 110 111 if (ret == 1) 112 return (0); 113 114 return (-1); 115 } 116 117 int 118 key_setsecret_g( 119 char *secretkey, 120 keylen_t keylen, 121 algtype_t algtype, 122 des_block userkey) 123 { 124 setkeyarg3 arg; 125 keystatus status; 126 127 if (CLASSIC_PK_DH(keylen, algtype)) 128 return (key_setsecret(secretkey)); 129 arg.key.keybuf3_len = keylen/4 + 1; 130 arg.key.keybuf3_val = secretkey; 131 arg.algtype = algtype; 132 arg.keylen = keylen; 133 arg.userkey = userkey; 134 if (!key_call((rpcproc_t)KEY_SET_3, xdr_setkeyarg3, (char *)&arg, 135 xdr_keystatus, (char *)&status)) 136 return (-1); 137 if (status != KEY_SUCCESS) { 138 debug("set3 status is nonzero"); 139 return (-1); 140 } 141 return (0); 142 } 143 144 int 145 key_removesecret_g_ext(int use_uid) 146 { 147 keystatus status; 148 149 if (!key_call_ext((rpcproc_t)KEY_CLEAR_3, xdr_void, NULL, 150 xdr_keystatus, (char *)&status, use_uid)) { 151 debug("remove secret key call failed"); 152 return (-1); 153 } 154 if (status != KEY_SUCCESS) { 155 debug("remove secret status is nonzero"); 156 return (-1); 157 } 158 return (0); 159 } 160 161 /* 162 * Use effective uid. 163 */ 164 int 165 key_removesecret_g(void) 166 { 167 return (key_removesecret_g_ext(0)); 168 } 169 170 /* 171 * Use real uid. 172 */ 173 int 174 key_removesecret_g_ruid(void) 175 { 176 return (key_removesecret_g_ext(1)); 177 } 178 179 /* 180 * key_secretkey_is_set() returns 1 if the keyserver has a secret key 181 * stored for the caller's effective uid if use_ruid is 0 or 182 * stored for the caller's real uid if use_ruid is 1. 183 * it returns 0 otherwise. 184 * 185 * N.B.: The KEY_NET_GET key call is undocumented. Applications shouldn't 186 * be using it, because it allows them to get the user's secret key. 187 * 188 */ 189 int 190 key_secretkey_is_set_ext(int use_ruid) 191 { 192 struct key_netstres kres; 193 194 (void) memset(&kres, 0, sizeof (kres)); 195 if (key_call_ext((rpcproc_t)KEY_NET_GET, xdr_void, NULL, 196 xdr_key_netstres, (char *)&kres, use_ruid) && 197 (kres.status == KEY_SUCCESS) && 198 (kres.key_netstres_u.knet.st_priv_key[0] != 0)) { 199 /* avoid leaving secret key in memory */ 200 (void) memset(kres.key_netstres_u.knet.st_priv_key, 0, 201 HEXKEYBYTES); 202 xdr_free(xdr_key_netstres, (char *)&kres); 203 return (1); 204 } 205 return (0); 206 } 207 208 /* 209 * Use effective uid. 210 */ 211 int 212 key_secretkey_is_set(void) 213 { 214 return (key_secretkey_is_set_ext(0)); 215 } 216 217 /* 218 * Use real uid. 219 */ 220 int 221 key_secretkey_is_set_ruid(void) 222 { 223 return (key_secretkey_is_set_ext(1)); 224 } 225 226 /* 227 * key_secretkey_is_set_g_ext() returns 1 if the keyserver has a secret key 228 * stored for the caller's uid, it returns 0 otherwise. 229 * If (use_ruid == 0), for the caller's effective uid. 230 * If (use_ruid == 1), for the caller's real uid. 231 * 232 * N.B.: The KEY_NET_GET_3 key call is undocumented. Applications shouldn't 233 * be using it, because it allows them to get the user's secret key. 234 */ 235 int 236 key_secretkey_is_set_g_ext(keylen_t keylen, algtype_t algtype, int use_ruid) 237 { 238 mechtype arg; 239 key_netstres3 kres; 240 241 /* 242 * key_secretkey_is_set_g_ext is tricky because keylen == 0 243 * means check if any key exists for the caller (old/new, 192/1024 ...) 244 * Rather than handle this on the server side, we call the old 245 * routine if keylen == 0 and try the newer stuff only if that fails 246 */ 247 if ((keylen == 0) && key_secretkey_is_set_ext(use_ruid)) 248 return (1); 249 if (CLASSIC_PK_DH(keylen, algtype)) 250 return (key_secretkey_is_set_ext(use_ruid)); 251 arg.keylen = keylen; 252 arg.algtype = algtype; 253 (void) memset(&kres, 0, sizeof (kres)); 254 if (key_call_ext((rpcproc_t)KEY_NET_GET_3, xdr_mechtype, (char *)&arg, 255 xdr_key_netstres3, (char *)&kres, use_ruid) && 256 (kres.status == KEY_SUCCESS) && 257 (kres.key_netstres3_u.knet.st_priv_key.keybuf3_len != 0)) { 258 /* avoid leaving secret key in memory */ 259 (void) memset(kres.key_netstres3_u.knet.st_priv_key.keybuf3_val, 260 0, kres.key_netstres3_u.knet.st_priv_key.keybuf3_len); 261 xdr_free(xdr_key_netstres3, (char *)&kres); 262 return (1); 263 } 264 return (0); 265 } 266 267 /* 268 * Use effective uid. 269 */ 270 int 271 key_secretkey_is_set_g(keylen_t keylen, algtype_t algtype) 272 { 273 return (key_secretkey_is_set_g_ext(keylen, algtype, 0)); 274 } 275 276 /* 277 * Use real uid. 278 */ 279 int 280 key_secretkey_is_set_g_ruid(keylen_t keylen, algtype_t algtype) 281 { 282 return (key_secretkey_is_set_g_ext(keylen, algtype, 1)); 283 } 284 285 286 int 287 key_encryptsession_pk(const char *remotename, netobj *remotekey, 288 des_block *deskey) 289 { 290 cryptkeyarg2 arg; 291 cryptkeyres res; 292 293 arg.remotename = (char *)remotename; 294 arg.remotekey = *remotekey; 295 arg.deskey = *deskey; 296 if (!key_call((rpcproc_t)KEY_ENCRYPT_PK, xdr_cryptkeyarg2, (char *)&arg, 297 xdr_cryptkeyres, (char *)&res)) 298 return (-1); 299 if (res.status != KEY_SUCCESS) { 300 debug("encrypt status is nonzero"); 301 return (-1); 302 } 303 *deskey = res.cryptkeyres_u.deskey; 304 return (0); 305 } 306 307 int 308 key_encryptsession_pk_g( 309 const char *remotename, 310 const char *remotekey, 311 keylen_t remotekeylen, 312 algtype_t algtype, 313 des_block deskey[], 314 keynum_t keynum 315 ) 316 { 317 cryptkeyarg3 arg; 318 cryptkeyres3 res; 319 320 if (CLASSIC_PK_DH(remotekeylen, algtype)) { 321 int i; 322 netobj npk; 323 324 npk.n_len = remotekeylen/4 + 1; 325 npk.n_bytes = (char *)remotekey; 326 for (i = 0; i < keynum; i++) { 327 if (key_encryptsession_pk(remotename, &npk, &deskey[i])) 328 return (-1); 329 } 330 return (0); 331 } 332 arg.remotename = (char *)remotename; 333 arg.remotekey.keybuf3_len = remotekeylen/4 + 1; 334 arg.remotekey.keybuf3_val = (char *)remotekey; 335 arg.keylen = remotekeylen; 336 arg.algtype = algtype; 337 arg.deskey.deskeyarray_len = keynum; 338 arg.deskey.deskeyarray_val = deskey; 339 (void) memset(&res, 0, sizeof (res)); 340 res.cryptkeyres3_u.deskey.deskeyarray_val = deskey; 341 if (!key_call((rpcproc_t)KEY_ENCRYPT_PK_3, 342 xdr_cryptkeyarg3, (char *)&arg, 343 xdr_cryptkeyres3, (char *)&res)) 344 return (-1); 345 if (res.status != KEY_SUCCESS) { 346 debug("encrypt3 status is nonzero"); 347 return (-1); 348 } 349 if (res.cryptkeyres3_u.deskey.deskeyarray_len != keynum) { 350 debug("number of keys don't match"); 351 return (-1); 352 } 353 return (0); 354 } 355 356 int 357 key_decryptsession_pk(const char *remotename, netobj *remotekey, 358 des_block *deskey) 359 { 360 cryptkeyarg2 arg; 361 cryptkeyres res; 362 363 arg.remotename = (char *)remotename; 364 arg.remotekey = *remotekey; 365 arg.deskey = *deskey; 366 if (!key_call((rpcproc_t)KEY_DECRYPT_PK, xdr_cryptkeyarg2, (char *)&arg, 367 xdr_cryptkeyres, (char *)&res)) 368 return (-1); 369 if (res.status != KEY_SUCCESS) { 370 debug("decrypt status is nonzero"); 371 return (-1); 372 } 373 *deskey = res.cryptkeyres_u.deskey; 374 return (0); 375 } 376 377 int 378 key_decryptsession_pk_g( 379 const char *remotename, 380 const char *remotekey, 381 keylen_t remotekeylen, 382 algtype_t algtype, 383 des_block deskey[], 384 keynum_t keynum 385 ) 386 { 387 cryptkeyarg3 arg; 388 cryptkeyres3 res; 389 390 if (CLASSIC_PK_DH(remotekeylen, algtype)) { 391 int i; 392 netobj npk; 393 394 npk.n_len = remotekeylen/4 + 1; 395 npk.n_bytes = (char *)remotekey; 396 for (i = 0; i < keynum; i++) { 397 if (key_decryptsession_pk(remotename, 398 &npk, &deskey[i])) 399 return (-1); 400 } 401 return (0); 402 } 403 arg.remotename = (char *)remotename; 404 arg.remotekey.keybuf3_len = remotekeylen/4 + 1; 405 arg.remotekey.keybuf3_val = (char *)remotekey; 406 arg.deskey.deskeyarray_len = keynum; 407 arg.deskey.deskeyarray_val = deskey; 408 arg.algtype = algtype; 409 arg.keylen = remotekeylen; 410 (void) memset(&res, 0, sizeof (res)); 411 res.cryptkeyres3_u.deskey.deskeyarray_val = deskey; 412 if (!key_call((rpcproc_t)KEY_DECRYPT_PK_3, 413 xdr_cryptkeyarg3, (char *)&arg, 414 xdr_cryptkeyres3, (char *)&res)) 415 return (-1); 416 if (res.status != KEY_SUCCESS) { 417 debug("decrypt3 status is nonzero"); 418 return (-1); 419 } 420 if (res.cryptkeyres3_u.deskey.deskeyarray_len != keynum) { 421 debug("number of keys don't match"); 422 return (-1); 423 } 424 return (0); 425 } 426 427 int 428 key_encryptsession(const char *remotename, des_block *deskey) 429 { 430 cryptkeyarg arg; 431 cryptkeyres res; 432 433 arg.remotename = (char *)remotename; 434 arg.deskey = *deskey; 435 if (!key_call((rpcproc_t)KEY_ENCRYPT, xdr_cryptkeyarg, (char *)&arg, 436 xdr_cryptkeyres, (char *)&res)) 437 return (-1); 438 if (res.status != KEY_SUCCESS) { 439 debug("encrypt status is nonzero"); 440 return (-1); 441 } 442 *deskey = res.cryptkeyres_u.deskey; 443 return (0); 444 } 445 446 int 447 key_encryptsession_g( 448 const char *remotename, 449 keylen_t keylen, 450 algtype_t algtype, 451 des_block deskey[], 452 keynum_t keynum 453 ) 454 { 455 cryptkeyarg3 arg; 456 cryptkeyres3 res; 457 458 if (CLASSIC_PK_DH(keylen, algtype)) 459 return (key_encryptsession(remotename, deskey)); 460 arg.remotename = (char *)remotename; 461 arg.algtype = algtype; 462 arg.keylen = keylen; 463 arg.deskey.deskeyarray_len = keynum; 464 arg.deskey.deskeyarray_val = deskey; 465 arg.remotekey.keybuf3_len = 0; 466 (void) memset(&res, 0, sizeof (res)); 467 res.cryptkeyres3_u.deskey.deskeyarray_val = deskey; 468 if (!key_call((rpcproc_t)KEY_ENCRYPT_3, xdr_cryptkeyarg3, (char *)&arg, 469 xdr_cryptkeyres3, (char *)&res)) 470 return (-1); 471 if (res.status != KEY_SUCCESS) { 472 debug("encrypt3 status is nonzero"); 473 return (-1); 474 } 475 if (res.cryptkeyres3_u.deskey.deskeyarray_len != keynum) { 476 debug("encrypt3 didn't return same number of keys"); 477 return (-1); 478 } 479 return (0); 480 } 481 482 483 int 484 key_decryptsession(const char *remotename, des_block *deskey) 485 { 486 cryptkeyarg arg; 487 cryptkeyres res; 488 489 arg.remotename = (char *)remotename; 490 arg.deskey = *deskey; 491 if (!key_call((rpcproc_t)KEY_DECRYPT, xdr_cryptkeyarg, (char *)&arg, 492 xdr_cryptkeyres, (char *)&res)) 493 return (-1); 494 if (res.status != KEY_SUCCESS) { 495 debug("decrypt status is nonzero"); 496 return (-1); 497 } 498 *deskey = res.cryptkeyres_u.deskey; 499 return (0); 500 } 501 502 int 503 key_decryptsession_g( 504 const char *remotename, 505 keylen_t keylen, 506 algtype_t algtype, 507 des_block deskey[], 508 keynum_t keynum 509 ) 510 { 511 cryptkeyarg3 arg; 512 cryptkeyres3 res; 513 514 if (CLASSIC_PK_DH(keylen, algtype)) 515 return (key_decryptsession(remotename, deskey)); 516 arg.remotename = (char *)remotename; 517 arg.algtype = algtype; 518 arg.keylen = keylen; 519 arg.deskey.deskeyarray_len = keynum; 520 arg.deskey.deskeyarray_val = deskey; 521 arg.remotekey.keybuf3_len = 0; 522 (void) memset(&res, 0, sizeof (res)); 523 res.cryptkeyres3_u.deskey.deskeyarray_val = deskey; 524 if (!key_call((rpcproc_t)KEY_DECRYPT_3, xdr_cryptkeyarg3, (char *)&arg, 525 xdr_cryptkeyres3, (char *)&res)) 526 return (-1); 527 if (res.status != KEY_SUCCESS) { 528 debug("decrypt3 status is nonzero"); 529 return (-1); 530 } 531 if (res.cryptkeyres3_u.deskey.deskeyarray_len != keynum) { 532 debug("decrypt3 didn't return same number of keys"); 533 return (-1); 534 } 535 return (0); 536 } 537 538 int 539 key_gendes(des_block *key) 540 { 541 if (!key_call((rpcproc_t)KEY_GEN, xdr_void, NULL, 542 xdr_des_block, (char *)key)) 543 return (-1); 544 return (0); 545 } 546 547 int 548 key_gendes_g( 549 des_block deskey[], 550 keynum_t keynum 551 ) 552 { 553 deskeyarray res; 554 555 res.deskeyarray_val = deskey; 556 if (!key_call((rpcproc_t)KEY_GEN_3, xdr_keynum_t, (char *)&keynum, 557 xdr_deskeyarray, (char *)&res)) 558 return (-1); 559 if (res.deskeyarray_len != keynum) { 560 debug("return length doesn't match\n"); 561 return (-1); 562 } 563 return (0); 564 } 565 566 /* 567 * Call KEY_NET_PUT Operation to the keyserv. 568 * 569 * If use_ruid == 0, use effective uid. 570 * If use_ruid == 1, use real uid. 571 */ 572 int 573 key_setnet_ext(struct key_netstarg *arg, int use_ruid) 574 { 575 keystatus status; 576 577 if (!key_call_ext((rpcproc_t)KEY_NET_PUT, xdr_key_netstarg, 578 (char *)arg, xdr_keystatus, (char *)&status, use_ruid)) 579 return (-1); 580 581 if (status != KEY_SUCCESS) { 582 debug("key_setnet status is nonzero"); 583 return (-1); 584 } 585 return (1); 586 } 587 588 /* 589 * Use effective uid. 590 */ 591 int 592 key_setnet(struct key_netstarg *arg) 593 { 594 return (key_setnet_ext(arg, 0)); 595 } 596 597 /* 598 * Use real uid. 599 */ 600 int 601 key_setnet_ruid(struct key_netstarg *arg) 602 { 603 return (key_setnet_ext(arg, 1)); 604 } 605 606 /* 607 * Input netname, secret and public keys (hex string representation) 608 * of length skeylen/pkeylen (bits), and algorithm type. One, but not 609 * both, of skey or pkey may have zero length. If both lengths are 610 * specified, they must be the same. 611 * 612 * Call KEY_NET_PUT_3 Operation to the keyserv. 613 * Stores the specified netname/pkey/skey triplet in the keyserv. 614 * 615 * If (use_ruid == 1), use real uid. 616 * If (use_ruid == 0), use effective uid. 617 */ 618 int 619 key_setnet_g_ext( 620 const char *netname, 621 const char *skey, 622 keylen_t skeylen, 623 const char *pkey, 624 keylen_t pkeylen, 625 algtype_t algtype, 626 int use_ruid) 627 { 628 key_netstarg3 arg; 629 keystatus status; 630 631 arg.st_netname = (char *)netname; 632 arg.algtype = algtype; 633 if (skeylen == 0) { 634 arg.st_priv_key.keybuf3_len = 0; 635 } else { 636 arg.st_priv_key.keybuf3_len = skeylen/4 + 1; 637 } 638 arg.st_priv_key.keybuf3_val = (char *)skey; 639 if (pkeylen == 0) { 640 arg.st_pub_key.keybuf3_len = 0; 641 } else { 642 arg.st_pub_key.keybuf3_len = pkeylen/4 + 1; 643 } 644 arg.st_pub_key.keybuf3_val = (char *)pkey; 645 if (skeylen == 0) { 646 if (pkeylen == 0) { 647 debug("keylens are both 0"); 648 return (-1); 649 } 650 arg.keylen = pkeylen; 651 } else { 652 if ((pkeylen != 0) && (skeylen != pkeylen)) { 653 debug("keylens don't match"); 654 return (-1); 655 } 656 arg.keylen = skeylen; 657 } 658 if (CLASSIC_PK_DH(arg.keylen, arg.algtype)) { 659 key_netstarg tmp; 660 661 if (skeylen != 0) { 662 (void) memcpy(&tmp.st_priv_key, skey, 663 sizeof (tmp.st_priv_key)); 664 } else { 665 (void) memset(&tmp.st_priv_key, 0, 666 sizeof (tmp.st_priv_key)); 667 } 668 if (pkeylen != 0) { 669 (void) memcpy(&tmp.st_pub_key, skey, 670 sizeof (tmp.st_pub_key)); 671 } else { 672 (void) memset(&tmp.st_pub_key, 0, 673 sizeof (tmp.st_pub_key)); 674 } 675 tmp.st_netname = (char *)netname; 676 return (key_setnet(&tmp)); 677 } 678 if (!key_call_ext((rpcproc_t)KEY_NET_PUT_3, 679 xdr_key_netstarg3, (char *)&arg, 680 xdr_keystatus, (char *)&status, use_ruid)) { 681 return (-1); 682 } 683 684 if (status != KEY_SUCCESS) { 685 debug("key_setnet3 status is nonzero"); 686 return (-1); 687 } 688 return (0); 689 } 690 691 /* 692 * Use effective uid. 693 */ 694 int 695 key_setnet_g(const char *netname, const char *skey, keylen_t skeylen, 696 const char *pkey, keylen_t pkeylen, algtype_t algtype) 697 { 698 return (key_setnet_g_ext(netname, skey, skeylen, pkey, pkeylen, 699 algtype, 0)); 700 } 701 702 /* 703 * Use real uid. 704 */ 705 int 706 key_setnet_g_ruid(const char *netname, const char *skey, keylen_t skeylen, 707 const char *pkey, keylen_t pkeylen, algtype_t algtype) 708 { 709 return (key_setnet_g_ext(netname, skey, skeylen, pkey, pkeylen, 710 algtype, 1)); 711 } 712 713 int 714 key_get_conv(char *pkey, des_block *deskey) 715 { 716 cryptkeyres res; 717 718 if (!key_call((rpcproc_t)KEY_GET_CONV, xdr_keybuf, pkey, 719 xdr_cryptkeyres, (char *)&res)) 720 return (-1); 721 if (res.status != KEY_SUCCESS) { 722 debug("get_conv status is nonzero"); 723 return (-1); 724 } 725 *deskey = res.cryptkeyres_u.deskey; 726 return (0); 727 } 728 729 int 730 key_get_conv_g( 731 const char *pkey, 732 keylen_t pkeylen, 733 algtype_t algtype, 734 des_block deskey[], 735 keynum_t keynum 736 ) 737 { 738 deskeyarg3 arg; 739 cryptkeyres3 res; 740 741 if (CLASSIC_PK_DH(pkeylen, algtype)) 742 return (key_get_conv((char *)pkey, deskey)); 743 arg.pub_key.keybuf3_len = pkeylen/4 + 1; 744 arg.pub_key.keybuf3_val = (char *)pkey; 745 arg.nkeys = keynum; 746 arg.algtype = algtype; 747 arg.keylen = pkeylen; 748 (void) memset(&res, 0, sizeof (res)); 749 res.cryptkeyres3_u.deskey.deskeyarray_val = deskey; 750 if (!key_call((rpcproc_t)KEY_GET_CONV_3, xdr_deskeyarg3, (char *)&arg, 751 xdr_cryptkeyres3, (char *)&res)) 752 return (-1); 753 if (res.status != KEY_SUCCESS) { 754 debug("get_conv3 status is nonzero"); 755 return (-1); 756 } 757 if (res.cryptkeyres3_u.deskey.deskeyarray_len != keynum) { 758 debug("get_conv3 number of keys dont match"); 759 return (-1); 760 } 761 return (0); 762 } 763 764 struct key_call_private { 765 CLIENT *client; /* Client handle */ 766 pid_t pid; /* process-id at moment of creation */ 767 int fd; /* client handle fd */ 768 dev_t rdev; /* device client handle is using */ 769 }; 770 771 static void set_rdev(struct key_call_private *); 772 static int check_rdev(struct key_call_private *); 773 774 static void 775 key_call_destroy(void *vp) 776 { 777 struct key_call_private *kcp = (struct key_call_private *)vp; 778 779 if (kcp != NULL && kcp->client != NULL) { 780 (void) check_rdev(kcp); 781 clnt_destroy(kcp->client); 782 free(kcp); 783 } 784 } 785 786 static pthread_key_t key_call_key = PTHREAD_ONCE_KEY_NP; 787 788 void 789 _key_call_fini(void) 790 { 791 struct key_call_private *kcp; 792 793 if ((kcp = pthread_getspecific(key_call_key)) != NULL) { 794 key_call_destroy(kcp); 795 (void) pthread_setspecific(key_call_key, NULL); 796 } 797 } 798 799 /* 800 * Keep the handle cached. This call may be made quite often. 801 */ 802 static CLIENT * 803 getkeyserv_handle(int vers, int stale) 804 { 805 struct key_call_private *kcp = NULL; 806 int _update_did(); 807 808 kcp = thr_get_storage(&key_call_key, sizeof (*kcp), key_call_destroy); 809 if (kcp == NULL) { 810 syslog(LOG_CRIT, "getkeyserv_handle: out of memory"); 811 return (NULL); 812 } 813 814 /* 815 * if pid has changed, destroy client and rebuild 816 * or if stale is '1' then destroy client and rebuild 817 */ 818 if (kcp->client && 819 (!check_rdev(kcp) || kcp->pid != getpid() || stale)) { 820 clnt_destroy(kcp->client); 821 kcp->client = NULL; 822 } 823 if (kcp->client) { 824 int fd; 825 /* 826 * Change the version number to the new one. 827 */ 828 clnt_control(kcp->client, CLSET_VERS, (void *)&vers); 829 if (!_update_did(kcp->client, vers)) { 830 if (rpc_createerr.cf_stat == RPC_SYSTEMERROR) 831 syslog(LOG_DEBUG, "getkeyserv_handle: " 832 "out of memory!"); 833 return (NULL); 834 } 835 /* Update fd in kcp because it was reopened in _update_did */ 836 if (clnt_control(kcp->client, CLGET_FD, (void *)&fd) && 837 (fd >= 0)) 838 (void) fcntl(fd, F_SETFD, FD_CLOEXEC); /* close exec */ 839 kcp->fd = fd; 840 return (kcp->client); 841 } 842 843 if ((kcp->client = clnt_door_create(KEY_PROG, vers, 0)) == NULL) 844 return (NULL); 845 846 kcp->pid = getpid(); 847 set_rdev(kcp); 848 (void) fcntl(kcp->fd, F_SETFD, FD_CLOEXEC); /* close on exec */ 849 850 return (kcp->client); 851 } 852 853 /* 854 * RPC calls to the keyserv. 855 * 856 * If (use_ruid == 1), use real uid. 857 * If (use_ruid == 0), use effective uid. 858 * Returns 0 on failure, 1 on success 859 */ 860 int 861 key_call_ext(rpcproc_t proc, xdrproc_t xdr_arg, char *arg, xdrproc_t xdr_rslt, 862 char *rslt, int use_ruid) 863 { 864 CLIENT *clnt; 865 struct timeval wait_time = {0, 0}; 866 enum clnt_stat status; 867 int vers; 868 869 if (proc == KEY_ENCRYPT_PK && __key_encryptsession_pk_LOCAL) { 870 cryptkeyres res; 871 bool_t r; 872 r = (*__key_encryptsession_pk_LOCAL)(geteuid(), arg, &res); 873 if (r == TRUE) { 874 /* LINTED pointer alignment */ 875 *(cryptkeyres*)rslt = res; 876 return (1); 877 } 878 return (0); 879 } 880 if (proc == KEY_DECRYPT_PK && __key_decryptsession_pk_LOCAL) { 881 cryptkeyres res; 882 bool_t r; 883 r = (*__key_decryptsession_pk_LOCAL)(geteuid(), arg, &res); 884 if (r == TRUE) { 885 /* LINTED pointer alignment */ 886 *(cryptkeyres*)rslt = res; 887 return (1); 888 } 889 return (0); 890 } 891 if (proc == KEY_GEN && __key_gendes_LOCAL) { 892 des_block res; 893 bool_t r; 894 r = (*__key_gendes_LOCAL)(geteuid(), 0, &res); 895 if (r == TRUE) { 896 /* LINTED pointer alignment */ 897 *(des_block*)rslt = res; 898 return (1); 899 } 900 return (0); 901 } 902 903 if ((proc == KEY_ENCRYPT_PK) || (proc == KEY_DECRYPT_PK) || 904 (proc == KEY_NET_GET) || (proc == KEY_NET_PUT) || 905 (proc == KEY_GET_CONV)) 906 vers = 2; /* talk to version 2 */ 907 else 908 vers = 1; /* talk to version 1 */ 909 910 clnt = getkeyserv_handle(vers, 0); 911 if (clnt == NULL) 912 return (0); 913 914 auth_destroy(clnt->cl_auth); 915 if (use_ruid) 916 clnt->cl_auth = authsys_create_ruid(); 917 else 918 clnt->cl_auth = authnone_create(); 919 920 status = CLNT_CALL(clnt, proc, xdr_arg, arg, xdr_rslt, 921 rslt, wait_time); 922 923 switch (status) { 924 case RPC_SUCCESS: 925 return (1); 926 927 case RPC_CANTRECV: 928 /* 929 * keyserv was probably restarted, so we'll try once more 930 */ 931 if ((clnt = getkeyserv_handle(vers, 1)) == NULL) 932 return (0); 933 934 auth_destroy(clnt->cl_auth); 935 if (use_ruid) 936 clnt->cl_auth = authsys_create_ruid(); 937 else 938 clnt->cl_auth = authnone_create(); 939 940 941 if (CLNT_CALL(clnt, proc, xdr_arg, arg, xdr_rslt, rslt, 942 wait_time) == RPC_SUCCESS) 943 return (1); 944 return (0); 945 946 default: 947 return (0); 948 } 949 } 950 951 /* 952 * Use effective uid. 953 */ 954 int 955 key_call(rpcproc_t proc, xdrproc_t xdr_arg, char *arg, xdrproc_t xdr_rslt, 956 char *rslt) 957 { 958 return (key_call_ext(proc, xdr_arg, arg, xdr_rslt, rslt, 0)); 959 } 960 961 /* 962 * Use real uid. 963 */ 964 int 965 key_call_ruid(rpcproc_t proc, xdrproc_t xdr_arg, char *arg, 966 xdrproc_t xdr_rslt, char *rslt) 967 { 968 return (key_call_ext(proc, xdr_arg, arg, xdr_rslt, rslt, 1)); 969 } 970 971 static void 972 set_rdev(struct key_call_private *kcp) 973 { 974 int fd; 975 struct stat stbuf; 976 977 if (clnt_control(kcp->client, CLGET_FD, (char *)&fd) != TRUE || 978 fstat(fd, &stbuf) == -1) { 979 syslog(LOG_DEBUG, "keyserv_client: can't get info"); 980 kcp->fd = -1; 981 return; 982 } 983 kcp->fd = fd; 984 kcp->rdev = stbuf.st_rdev; 985 } 986 987 static int 988 check_rdev(struct key_call_private *kcp) 989 { 990 struct stat stbuf; 991 992 if (kcp->fd == -1) 993 return (1); /* can't check it, assume it is okay */ 994 995 if (fstat(kcp->fd, &stbuf) == -1) { 996 syslog(LOG_DEBUG, "keyserv_client: can't stat %d", kcp->fd); 997 /* could be because file descriptor was closed */ 998 /* it's not our file descriptor, so don't try to close it */ 999 clnt_control(kcp->client, CLSET_FD_NCLOSE, NULL); 1000 1001 return (0); 1002 } 1003 if (kcp->rdev != stbuf.st_rdev) { 1004 syslog(LOG_DEBUG, 1005 "keyserv_client: fd %d changed, old=0x%x, new=0x%x", 1006 kcp->fd, kcp->rdev, stbuf.st_rdev); 1007 /* it's not our file descriptor, so don't try to close it */ 1008 clnt_control(kcp->client, CLSET_FD_NCLOSE, NULL); 1009 return (0); 1010 } 1011 return (1); /* fd is okay */ 1012 } 1013