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