1 /* 2 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * All rights reserved 5 * The authentication agent program. 6 * 7 * As far as I am concerned, the code I have written for this software 8 * can be used freely for any purpose. Any derived versions of this 9 * software must be clearly marked as such, and if the derived work is 10 * incompatible with the protocol description in the RFC file, it must be 11 * called by a name other than "ssh" or "Secure Shell". 12 * 13 * SSH2 implementation, 14 * Copyright (c) 2000 Markus Friedl. All rights reserved. 15 * 16 * Redistribution and use in source and binary forms, with or without 17 * modification, are permitted provided that the following conditions 18 * are met: 19 * 1. Redistributions of source code must retain the above copyright 20 * notice, this list of conditions and the following disclaimer. 21 * 2. Redistributions in binary form must reproduce the above copyright 22 * notice, this list of conditions and the following disclaimer in the 23 * documentation and/or other materials provided with the distribution. 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 26 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 27 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 28 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 29 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 30 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 31 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 32 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 33 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 34 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35 */ 36 37 #include "includes.h" 38 RCSID("$OpenBSD: ssh-agent.c,v 1.35 2000/09/07 20:27:54 deraadt Exp $"); 39 RCSID("$FreeBSD$"); 40 41 #include "ssh.h" 42 #include "rsa.h" 43 #include "buffer.h" 44 #include "bufaux.h" 45 #include "xmalloc.h" 46 #include "packet.h" 47 #include "getput.h" 48 #include "mpaux.h" 49 50 #include <openssl/evp.h> 51 #include <openssl/md5.h> 52 #include <openssl/dsa.h> 53 #include <openssl/rsa.h> 54 #include "key.h" 55 #include "authfd.h" 56 #include "dsa.h" 57 #include "kex.h" 58 59 typedef struct { 60 int fd; 61 enum { 62 AUTH_UNUSED, AUTH_SOCKET, AUTH_CONNECTION 63 } type; 64 Buffer input; 65 Buffer output; 66 } SocketEntry; 67 68 unsigned int sockets_alloc = 0; 69 SocketEntry *sockets = NULL; 70 71 typedef struct { 72 Key *key; 73 char *comment; 74 } Identity; 75 76 typedef struct { 77 int nentries; 78 Identity *identities; 79 } Idtab; 80 81 /* private key table, one per protocol version */ 82 Idtab idtable[3]; 83 84 int max_fd = 0; 85 86 /* pid of shell == parent of agent */ 87 pid_t parent_pid = -1; 88 89 /* pathname and directory for AUTH_SOCKET */ 90 char socket_name[1024]; 91 char socket_dir[1024]; 92 93 extern char *__progname; 94 95 void 96 idtab_init(void) 97 { 98 int i; 99 for (i = 0; i <=2; i++){ 100 idtable[i].identities = NULL; 101 idtable[i].nentries = 0; 102 } 103 } 104 105 /* return private key table for requested protocol version */ 106 Idtab * 107 idtab_lookup(int version) 108 { 109 if (version < 1 || version > 2) 110 fatal("internal error, bad protocol version %d", version); 111 return &idtable[version]; 112 } 113 114 /* return matching private key for given public key */ 115 Key * 116 lookup_private_key(Key *key, int *idx, int version) 117 { 118 int i; 119 Idtab *tab = idtab_lookup(version); 120 for (i = 0; i < tab->nentries; i++) { 121 if (key_equal(key, tab->identities[i].key)) { 122 if (idx != NULL) 123 *idx = i; 124 return tab->identities[i].key; 125 } 126 } 127 return NULL; 128 } 129 130 /* send list of supported public keys to 'client' */ 131 void 132 process_request_identities(SocketEntry *e, int version) 133 { 134 Idtab *tab = idtab_lookup(version); 135 Buffer msg; 136 int i; 137 138 buffer_init(&msg); 139 buffer_put_char(&msg, (version == 1) ? 140 SSH_AGENT_RSA_IDENTITIES_ANSWER : SSH2_AGENT_IDENTITIES_ANSWER); 141 buffer_put_int(&msg, tab->nentries); 142 for (i = 0; i < tab->nentries; i++) { 143 Identity *id = &tab->identities[i]; 144 if (id->key->type == KEY_RSA) { 145 buffer_put_int(&msg, BN_num_bits(id->key->rsa->n)); 146 buffer_put_bignum(&msg, id->key->rsa->e); 147 buffer_put_bignum(&msg, id->key->rsa->n); 148 } else { 149 unsigned char *blob; 150 unsigned int blen; 151 dsa_make_key_blob(id->key, &blob, &blen); 152 buffer_put_string(&msg, blob, blen); 153 xfree(blob); 154 } 155 buffer_put_cstring(&msg, id->comment); 156 } 157 buffer_put_int(&e->output, buffer_len(&msg)); 158 buffer_append(&e->output, buffer_ptr(&msg), buffer_len(&msg)); 159 buffer_free(&msg); 160 } 161 162 /* ssh1 only */ 163 void 164 process_authentication_challenge1(SocketEntry *e) 165 { 166 Key *key, *private; 167 BIGNUM *challenge; 168 int i, len; 169 Buffer msg; 170 MD5_CTX md; 171 unsigned char buf[32], mdbuf[16], session_id[16]; 172 unsigned int response_type; 173 174 buffer_init(&msg); 175 key = key_new(KEY_RSA); 176 challenge = BN_new(); 177 178 buffer_get_int(&e->input); /* ignored */ 179 buffer_get_bignum(&e->input, key->rsa->e); 180 buffer_get_bignum(&e->input, key->rsa->n); 181 buffer_get_bignum(&e->input, challenge); 182 183 /* Only protocol 1.1 is supported */ 184 if (buffer_len(&e->input) == 0) 185 goto failure; 186 buffer_get(&e->input, (char *) session_id, 16); 187 response_type = buffer_get_int(&e->input); 188 if (response_type != 1) 189 goto failure; 190 191 private = lookup_private_key(key, NULL, 1); 192 if (private != NULL) { 193 /* Decrypt the challenge using the private key. */ 194 rsa_private_decrypt(challenge, challenge, private->rsa); 195 196 /* The response is MD5 of decrypted challenge plus session id. */ 197 len = BN_num_bytes(challenge); 198 if (len <= 0 || len > 32) { 199 log("process_authentication_challenge: bad challenge length %d", len); 200 goto failure; 201 } 202 memset(buf, 0, 32); 203 BN_bn2bin(challenge, buf + 32 - len); 204 MD5_Init(&md); 205 MD5_Update(&md, buf, 32); 206 MD5_Update(&md, session_id, 16); 207 MD5_Final(mdbuf, &md); 208 209 /* Send the response. */ 210 buffer_put_char(&msg, SSH_AGENT_RSA_RESPONSE); 211 for (i = 0; i < 16; i++) 212 buffer_put_char(&msg, mdbuf[i]); 213 goto send; 214 } 215 216 failure: 217 /* Unknown identity or protocol error. Send failure. */ 218 buffer_put_char(&msg, SSH_AGENT_FAILURE); 219 send: 220 buffer_put_int(&e->output, buffer_len(&msg)); 221 buffer_append(&e->output, buffer_ptr(&msg), buffer_len(&msg)); 222 key_free(key); 223 BN_clear_free(challenge); 224 buffer_free(&msg); 225 } 226 227 /* ssh2 only */ 228 void 229 process_sign_request2(SocketEntry *e) 230 { 231 extern int datafellows; 232 Key *key, *private; 233 unsigned char *blob, *data, *signature = NULL; 234 unsigned int blen, dlen, slen = 0; 235 Buffer msg; 236 int ok = -1; 237 238 datafellows = 0; 239 240 blob = buffer_get_string(&e->input, &blen); 241 data = buffer_get_string(&e->input, &dlen); 242 buffer_get_int(&e->input); /* flags, unused */ 243 244 key = dsa_key_from_blob(blob, blen); 245 if (key != NULL) { 246 private = lookup_private_key(key, NULL, 2); 247 if (private != NULL) 248 ok = dsa_sign(private, &signature, &slen, data, dlen); 249 } 250 key_free(key); 251 buffer_init(&msg); 252 if (ok == 0) { 253 buffer_put_char(&msg, SSH2_AGENT_SIGN_RESPONSE); 254 buffer_put_string(&msg, signature, slen); 255 } else { 256 buffer_put_char(&msg, SSH_AGENT_FAILURE); 257 } 258 buffer_put_int(&e->output, buffer_len(&msg)); 259 buffer_append(&e->output, buffer_ptr(&msg), 260 buffer_len(&msg)); 261 buffer_free(&msg); 262 xfree(data); 263 xfree(blob); 264 if (signature != NULL) 265 xfree(signature); 266 } 267 268 /* shared */ 269 void 270 process_remove_identity(SocketEntry *e, int version) 271 { 272 Key *key = NULL, *private; 273 unsigned char *blob; 274 unsigned int blen; 275 unsigned int bits; 276 int success = 0; 277 278 switch(version){ 279 case 1: 280 key = key_new(KEY_RSA); 281 bits = buffer_get_int(&e->input); 282 buffer_get_bignum(&e->input, key->rsa->e); 283 buffer_get_bignum(&e->input, key->rsa->n); 284 285 if (bits != key_size(key)) 286 log("Warning: identity keysize mismatch: actual %d, announced %d", 287 key_size(key), bits); 288 break; 289 case 2: 290 blob = buffer_get_string(&e->input, &blen); 291 key = dsa_key_from_blob(blob, blen); 292 xfree(blob); 293 break; 294 } 295 if (key != NULL) { 296 int idx; 297 private = lookup_private_key(key, &idx, version); 298 if (private != NULL) { 299 /* 300 * We have this key. Free the old key. Since we 301 * don\'t want to leave empty slots in the middle of 302 * the array, we actually free the key there and copy 303 * data from the last entry. 304 */ 305 Idtab *tab = idtab_lookup(version); 306 key_free(tab->identities[idx].key); 307 xfree(tab->identities[idx].comment); 308 if (idx != tab->nentries) 309 tab->identities[idx] = tab->identities[tab->nentries]; 310 tab->nentries--; 311 success = 1; 312 } 313 key_free(key); 314 } 315 buffer_put_int(&e->output, 1); 316 buffer_put_char(&e->output, 317 success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE); 318 } 319 320 void 321 process_remove_all_identities(SocketEntry *e, int version) 322 { 323 unsigned int i; 324 Idtab *tab = idtab_lookup(version); 325 326 /* Loop over all identities and clear the keys. */ 327 for (i = 0; i < tab->nentries; i++) { 328 key_free(tab->identities[i].key); 329 xfree(tab->identities[i].comment); 330 } 331 332 /* Mark that there are no identities. */ 333 tab->nentries = 0; 334 335 /* Send success. */ 336 buffer_put_int(&e->output, 1); 337 buffer_put_char(&e->output, SSH_AGENT_SUCCESS); 338 return; 339 } 340 341 void 342 process_add_identity(SocketEntry *e, int version) 343 { 344 Key *k = NULL; 345 RSA *rsa; 346 BIGNUM *aux; 347 BN_CTX *ctx; 348 char *type; 349 char *comment; 350 int success = 0; 351 Idtab *tab = idtab_lookup(version); 352 353 switch (version) { 354 case 1: 355 k = key_new(KEY_RSA); 356 rsa = k->rsa; 357 358 /* allocate mem for private key */ 359 /* XXX rsa->n and rsa->e are already allocated */ 360 rsa->d = BN_new(); 361 rsa->iqmp = BN_new(); 362 rsa->q = BN_new(); 363 rsa->p = BN_new(); 364 rsa->dmq1 = BN_new(); 365 rsa->dmp1 = BN_new(); 366 367 buffer_get_int(&e->input); /* ignored */ 368 369 buffer_get_bignum(&e->input, rsa->n); 370 buffer_get_bignum(&e->input, rsa->e); 371 buffer_get_bignum(&e->input, rsa->d); 372 buffer_get_bignum(&e->input, rsa->iqmp); 373 374 /* SSH and SSL have p and q swapped */ 375 buffer_get_bignum(&e->input, rsa->q); /* p */ 376 buffer_get_bignum(&e->input, rsa->p); /* q */ 377 378 /* Generate additional parameters */ 379 aux = BN_new(); 380 ctx = BN_CTX_new(); 381 382 BN_sub(aux, rsa->q, BN_value_one()); 383 BN_mod(rsa->dmq1, rsa->d, aux, ctx); 384 385 BN_sub(aux, rsa->p, BN_value_one()); 386 BN_mod(rsa->dmp1, rsa->d, aux, ctx); 387 388 BN_clear_free(aux); 389 BN_CTX_free(ctx); 390 391 break; 392 case 2: 393 type = buffer_get_string(&e->input, NULL); 394 if (strcmp(type, KEX_DSS)) { 395 buffer_clear(&e->input); 396 xfree(type); 397 goto send; 398 } 399 xfree(type); 400 401 k = key_new(KEY_DSA); 402 403 /* allocate mem for private key */ 404 k->dsa->priv_key = BN_new(); 405 406 buffer_get_bignum2(&e->input, k->dsa->p); 407 buffer_get_bignum2(&e->input, k->dsa->q); 408 buffer_get_bignum2(&e->input, k->dsa->g); 409 buffer_get_bignum2(&e->input, k->dsa->pub_key); 410 buffer_get_bignum2(&e->input, k->dsa->priv_key); 411 412 break; 413 } 414 415 comment = buffer_get_string(&e->input, NULL); 416 if (k == NULL) { 417 xfree(comment); 418 goto send; 419 } 420 success = 1; 421 if (lookup_private_key(k, NULL, version) == NULL) { 422 if (tab->nentries == 0) 423 tab->identities = xmalloc(sizeof(Identity)); 424 else 425 tab->identities = xrealloc(tab->identities, 426 (tab->nentries + 1) * sizeof(Identity)); 427 tab->identities[tab->nentries].key = k; 428 tab->identities[tab->nentries].comment = comment; 429 /* Increment the number of identities. */ 430 tab->nentries++; 431 } else { 432 key_free(k); 433 xfree(comment); 434 } 435 send: 436 buffer_put_int(&e->output, 1); 437 buffer_put_char(&e->output, 438 success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE); 439 } 440 441 /* dispatch incoming messages */ 442 443 void 444 process_message(SocketEntry *e) 445 { 446 unsigned int msg_len; 447 unsigned int type; 448 unsigned char *cp; 449 if (buffer_len(&e->input) < 5) 450 return; /* Incomplete message. */ 451 cp = (unsigned char *) buffer_ptr(&e->input); 452 msg_len = GET_32BIT(cp); 453 if (msg_len > 256 * 1024) { 454 shutdown(e->fd, SHUT_RDWR); 455 close(e->fd); 456 e->type = AUTH_UNUSED; 457 return; 458 } 459 if (buffer_len(&e->input) < msg_len + 4) 460 return; 461 buffer_consume(&e->input, 4); 462 type = buffer_get_char(&e->input); 463 464 switch (type) { 465 /* ssh1 */ 466 case SSH_AGENTC_RSA_CHALLENGE: 467 process_authentication_challenge1(e); 468 break; 469 case SSH_AGENTC_REQUEST_RSA_IDENTITIES: 470 process_request_identities(e, 1); 471 break; 472 case SSH_AGENTC_ADD_RSA_IDENTITY: 473 process_add_identity(e, 1); 474 break; 475 case SSH_AGENTC_REMOVE_RSA_IDENTITY: 476 process_remove_identity(e, 1); 477 break; 478 case SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES: 479 process_remove_all_identities(e, 1); 480 break; 481 /* ssh2 */ 482 case SSH2_AGENTC_SIGN_REQUEST: 483 process_sign_request2(e); 484 break; 485 case SSH2_AGENTC_REQUEST_IDENTITIES: 486 process_request_identities(e, 2); 487 break; 488 case SSH2_AGENTC_ADD_IDENTITY: 489 process_add_identity(e, 2); 490 break; 491 case SSH2_AGENTC_REMOVE_IDENTITY: 492 process_remove_identity(e, 2); 493 break; 494 case SSH2_AGENTC_REMOVE_ALL_IDENTITIES: 495 process_remove_all_identities(e, 2); 496 break; 497 default: 498 /* Unknown message. Respond with failure. */ 499 error("Unknown message %d", type); 500 buffer_clear(&e->input); 501 buffer_put_int(&e->output, 1); 502 buffer_put_char(&e->output, SSH_AGENT_FAILURE); 503 break; 504 } 505 } 506 507 void 508 new_socket(int type, int fd) 509 { 510 unsigned int i, old_alloc; 511 if (fcntl(fd, F_SETFL, O_NONBLOCK) < 0) 512 error("fcntl O_NONBLOCK: %s", strerror(errno)); 513 514 if (fd > max_fd) 515 max_fd = fd; 516 517 for (i = 0; i < sockets_alloc; i++) 518 if (sockets[i].type == AUTH_UNUSED) { 519 sockets[i].fd = fd; 520 sockets[i].type = type; 521 buffer_init(&sockets[i].input); 522 buffer_init(&sockets[i].output); 523 return; 524 } 525 old_alloc = sockets_alloc; 526 sockets_alloc += 10; 527 if (sockets) 528 sockets = xrealloc(sockets, sockets_alloc * sizeof(sockets[0])); 529 else 530 sockets = xmalloc(sockets_alloc * sizeof(sockets[0])); 531 for (i = old_alloc; i < sockets_alloc; i++) 532 sockets[i].type = AUTH_UNUSED; 533 sockets[old_alloc].type = type; 534 sockets[old_alloc].fd = fd; 535 buffer_init(&sockets[old_alloc].input); 536 buffer_init(&sockets[old_alloc].output); 537 } 538 539 void 540 prepare_select(fd_set *readset, fd_set *writeset) 541 { 542 unsigned int i; 543 for (i = 0; i < sockets_alloc; i++) 544 switch (sockets[i].type) { 545 case AUTH_SOCKET: 546 case AUTH_CONNECTION: 547 FD_SET(sockets[i].fd, readset); 548 if (buffer_len(&sockets[i].output) > 0) 549 FD_SET(sockets[i].fd, writeset); 550 break; 551 case AUTH_UNUSED: 552 break; 553 default: 554 fatal("Unknown socket type %d", sockets[i].type); 555 break; 556 } 557 } 558 559 void 560 after_select(fd_set *readset, fd_set *writeset) 561 { 562 unsigned int i; 563 int len, sock; 564 socklen_t slen; 565 char buf[1024]; 566 struct sockaddr_un sunaddr; 567 568 for (i = 0; i < sockets_alloc; i++) 569 switch (sockets[i].type) { 570 case AUTH_UNUSED: 571 break; 572 case AUTH_SOCKET: 573 if (FD_ISSET(sockets[i].fd, readset)) { 574 slen = sizeof(sunaddr); 575 sock = accept(sockets[i].fd, (struct sockaddr *) & sunaddr, &slen); 576 if (sock < 0) { 577 perror("accept from AUTH_SOCKET"); 578 break; 579 } 580 new_socket(AUTH_CONNECTION, sock); 581 } 582 break; 583 case AUTH_CONNECTION: 584 if (buffer_len(&sockets[i].output) > 0 && 585 FD_ISSET(sockets[i].fd, writeset)) { 586 len = write(sockets[i].fd, buffer_ptr(&sockets[i].output), 587 buffer_len(&sockets[i].output)); 588 if (len <= 0) { 589 shutdown(sockets[i].fd, SHUT_RDWR); 590 close(sockets[i].fd); 591 sockets[i].type = AUTH_UNUSED; 592 buffer_free(&sockets[i].input); 593 buffer_free(&sockets[i].output); 594 break; 595 } 596 buffer_consume(&sockets[i].output, len); 597 } 598 if (FD_ISSET(sockets[i].fd, readset)) { 599 len = read(sockets[i].fd, buf, sizeof(buf)); 600 if (len <= 0) { 601 shutdown(sockets[i].fd, SHUT_RDWR); 602 close(sockets[i].fd); 603 sockets[i].type = AUTH_UNUSED; 604 buffer_free(&sockets[i].input); 605 buffer_free(&sockets[i].output); 606 break; 607 } 608 buffer_append(&sockets[i].input, buf, len); 609 process_message(&sockets[i]); 610 } 611 break; 612 default: 613 fatal("Unknown type %d", sockets[i].type); 614 } 615 } 616 617 void 618 check_parent_exists(int sig) 619 { 620 if (parent_pid != -1 && kill(parent_pid, 0) < 0) { 621 /* printf("Parent has died - Authentication agent exiting.\n"); */ 622 exit(1); 623 } 624 signal(SIGALRM, check_parent_exists); 625 alarm(10); 626 } 627 628 void 629 cleanup_socket(void) 630 { 631 remove(socket_name); 632 rmdir(socket_dir); 633 } 634 635 void 636 cleanup_exit(int i) 637 { 638 cleanup_socket(); 639 exit(i); 640 } 641 642 void 643 usage() 644 { 645 fprintf(stderr, "ssh-agent version %s\n", SSH_VERSION); 646 fprintf(stderr, "Usage: %s [-c | -s] [-k] [command {args...]]\n", 647 __progname); 648 exit(1); 649 } 650 651 int 652 main(int ac, char **av) 653 { 654 fd_set readset, writeset; 655 int sock, c_flag = 0, k_flag = 0, s_flag = 0, ch; 656 struct sockaddr_un sunaddr; 657 pid_t pid; 658 char *shell, *format, *pidstr, pidstrbuf[1 + 3 * sizeof pid]; 659 660 /* check if RSA support exists */ 661 if (rsa_alive() == 0) { 662 fprintf(stderr, 663 "%s: no RSA support in libssl and libcrypto. See ssl(8).\n", 664 __progname); 665 exit(1); 666 } 667 while ((ch = getopt(ac, av, "cks")) != -1) { 668 switch (ch) { 669 case 'c': 670 if (s_flag) 671 usage(); 672 c_flag++; 673 break; 674 case 'k': 675 k_flag++; 676 break; 677 case 's': 678 if (c_flag) 679 usage(); 680 s_flag++; 681 break; 682 default: 683 usage(); 684 } 685 } 686 ac -= optind; 687 av += optind; 688 689 if (ac > 0 && (c_flag || k_flag || s_flag)) 690 usage(); 691 692 if (ac == 0 && !c_flag && !k_flag && !s_flag) { 693 shell = getenv("SHELL"); 694 if (shell != NULL && strncmp(shell + strlen(shell) - 3, "csh", 3) == 0) 695 c_flag = 1; 696 } 697 if (k_flag) { 698 pidstr = getenv(SSH_AGENTPID_ENV_NAME); 699 if (pidstr == NULL) { 700 fprintf(stderr, "%s not set, cannot kill agent\n", 701 SSH_AGENTPID_ENV_NAME); 702 exit(1); 703 } 704 pid = atoi(pidstr); 705 if (pid < 1) { /* XXX PID_MAX check too */ 706 /* Yes, PID_MAX check please */ 707 fprintf(stderr, "%s=\"%s\", which is not a good PID\n", 708 SSH_AGENTPID_ENV_NAME, pidstr); 709 exit(1); 710 } 711 if (kill(pid, SIGTERM) == -1) { 712 perror("kill"); 713 exit(1); 714 } 715 format = c_flag ? "unsetenv %s;\n" : "unset %s;\n"; 716 printf(format, SSH_AUTHSOCKET_ENV_NAME); 717 printf(format, SSH_AGENTPID_ENV_NAME); 718 printf("echo Agent pid %d killed;\n", pid); 719 exit(0); 720 } 721 parent_pid = getpid(); 722 723 /* Create private directory for agent socket */ 724 strlcpy(socket_dir, "/tmp/ssh-XXXXXXXX", sizeof socket_dir); 725 if (mkdtemp(socket_dir) == NULL) { 726 perror("mkdtemp: private socket dir"); 727 exit(1); 728 } 729 snprintf(socket_name, sizeof socket_name, "%s/agent.%d", socket_dir, 730 parent_pid); 731 732 /* 733 * Create socket early so it will exist before command gets run from 734 * the parent. 735 */ 736 sock = socket(AF_UNIX, SOCK_STREAM, 0); 737 if (sock < 0) { 738 perror("socket"); 739 cleanup_exit(1); 740 } 741 memset(&sunaddr, 0, sizeof(sunaddr)); 742 sunaddr.sun_family = AF_UNIX; 743 strlcpy(sunaddr.sun_path, socket_name, sizeof(sunaddr.sun_path)); 744 if (bind(sock, (struct sockaddr *) & sunaddr, sizeof(sunaddr)) < 0) { 745 perror("bind"); 746 cleanup_exit(1); 747 } 748 if (listen(sock, 5) < 0) { 749 perror("listen"); 750 cleanup_exit(1); 751 } 752 /* 753 * Fork, and have the parent execute the command, if any, or present 754 * the socket data. The child continues as the authentication agent. 755 */ 756 pid = fork(); 757 if (pid == -1) { 758 perror("fork"); 759 exit(1); 760 } 761 if (pid != 0) { /* Parent - execute the given command. */ 762 close(sock); 763 snprintf(pidstrbuf, sizeof pidstrbuf, "%d", pid); 764 if (ac == 0) { 765 format = c_flag ? "setenv %s %s;\n" : "%s=%s; export %s;\n"; 766 printf(format, SSH_AUTHSOCKET_ENV_NAME, socket_name, 767 SSH_AUTHSOCKET_ENV_NAME); 768 printf(format, SSH_AGENTPID_ENV_NAME, pidstrbuf, 769 SSH_AGENTPID_ENV_NAME); 770 printf("echo Agent pid %d;\n", pid); 771 exit(0); 772 } 773 setenv(SSH_AUTHSOCKET_ENV_NAME, socket_name, 1); 774 setenv(SSH_AGENTPID_ENV_NAME, pidstrbuf, 1); 775 execvp(av[0], av); 776 perror(av[0]); 777 exit(1); 778 } 779 close(0); 780 close(1); 781 close(2); 782 783 if (setsid() == -1) { 784 perror("setsid"); 785 cleanup_exit(1); 786 } 787 if (atexit(cleanup_socket) < 0) { 788 perror("atexit"); 789 cleanup_exit(1); 790 } 791 new_socket(AUTH_SOCKET, sock); 792 if (ac > 0) { 793 signal(SIGALRM, check_parent_exists); 794 alarm(10); 795 } 796 idtab_init(); 797 signal(SIGINT, SIG_IGN); 798 signal(SIGPIPE, SIG_IGN); 799 signal(SIGHUP, cleanup_exit); 800 signal(SIGTERM, cleanup_exit); 801 while (1) { 802 FD_ZERO(&readset); 803 FD_ZERO(&writeset); 804 prepare_select(&readset, &writeset); 805 if (select(max_fd + 1, &readset, &writeset, NULL, NULL) < 0) { 806 if (errno == EINTR) 807 continue; 808 exit(1); 809 } 810 after_select(&readset, &writeset); 811 } 812 /* NOTREACHED */ 813 } 814