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