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