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