1/* $OpenBSD: ssh-agent.c,v 1.172 2011/06/03 01:37:40 dtucker Exp $ */ 2/* 3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 5 * All rights reserved 6 * The authentication agent program. 7 * 8 * As far as I am concerned, the code I have written for this software 9 * can be used freely for any purpose. Any derived versions of this 10 * software must be clearly marked as such, and if the derived work is 11 * incompatible with the protocol description in the RFC file, it must be 12 * called by a name other than "ssh" or "Secure Shell". 13 * 14 * Copyright (c) 2000, 2001 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 39#include <sys/types.h> 40#include <sys/param.h> 41#include <sys/resource.h> 42#include <sys/stat.h> 43#include <sys/socket.h> 44#ifdef HAVE_SYS_TIME_H 45# include <sys/time.h> 46#endif 47#ifdef HAVE_SYS_UN_H 48# include <sys/un.h> 49#endif 50#include "openbsd-compat/sys-queue.h" 51 52#ifdef __APPLE_CRYPTO__ 53#include "ossl-evp.h" 54#include "ossl-md5.h" 55#else 56#include <openssl/evp.h> 57#include <openssl/md5.h> 58#endif 59#include "openbsd-compat/openssl-compat.h" 60 61#include <errno.h> 62#include <fcntl.h> 63#ifdef HAVE_PATHS_H 64# include <paths.h> 65#endif 66#include <signal.h> 67#include <stdarg.h> 68#include <stdio.h> 69#include <stdlib.h> 70#include <time.h> 71#include <string.h> 72#include <unistd.h> 73#ifdef __APPLE_LAUNCHD__ 74#include <launch.h> 75#endif 76 77#include "xmalloc.h" 78#include "ssh.h" 79#include "rsa.h" 80#include "buffer.h" 81#include "key.h" 82#include "authfd.h" 83#include "authfile.h" 84#include "compat.h" 85#include "log.h" 86#include "misc.h" 87#include "keychain.h" 88 89#ifdef ENABLE_PKCS11 90#include "ssh-pkcs11.h" 91#endif 92 93#if defined(HAVE_SYS_PRCTL_H) 94#include <sys/prctl.h> /* For prctl() and PR_SET_DUMPABLE */ 95#endif 96 97typedef enum { 98 AUTH_UNUSED, 99 AUTH_SOCKET, 100 AUTH_CONNECTION 101} sock_type; 102 103typedef struct { 104 int fd; 105 sock_type type; 106 Buffer input; 107 Buffer output; 108 Buffer request; 109} SocketEntry; 110 111u_int sockets_alloc = 0; 112SocketEntry *sockets = NULL; 113 114typedef struct identity { 115 TAILQ_ENTRY(identity) next; 116 Key *key; 117 char *comment; 118 char *provider; 119 u_int death; 120 u_int confirm; 121} Identity; 122 123typedef struct { 124 int nentries; 125 TAILQ_HEAD(idqueue, identity) idlist; 126} Idtab; 127 128/* private key table, one per protocol version */ 129Idtab idtable[3]; 130 131int max_fd = 0; 132 133/* pid of shell == parent of agent */ 134pid_t parent_pid = -1; 135u_int parent_alive_interval = 0; 136 137/* pathname and directory for AUTH_SOCKET */ 138char socket_name[MAXPATHLEN]; 139char socket_dir[MAXPATHLEN]; 140 141/* locking */ 142int locked = 0; 143char *lock_passwd = NULL; 144 145extern char *__progname; 146 147/* Default lifetime (0 == forever) */ 148static int lifetime = 0; 149 150static void 151close_socket(SocketEntry *e) 152{ 153 close(e->fd); 154 e->fd = -1; 155 e->type = AUTH_UNUSED; 156 buffer_free(&e->input); 157 buffer_free(&e->output); 158 buffer_free(&e->request); 159} 160 161static void 162idtab_init(void) 163{ 164 int i; 165 166 for (i = 0; i <=2; i++) { 167 TAILQ_INIT(&idtable[i].idlist); 168 idtable[i].nentries = 0; 169 } 170} 171 172/* return private key table for requested protocol version */ 173static Idtab * 174idtab_lookup(int version) 175{ 176 if (version < 1 || version > 2) 177 fatal("internal error, bad protocol version %d", version); 178 return &idtable[version]; 179} 180 181static void 182free_identity(Identity *id) 183{ 184 key_free(id->key); 185 if (id->provider != NULL) 186 xfree(id->provider); 187 xfree(id->comment); 188 xfree(id); 189} 190 191/* return matching private key for given public key */ 192static Identity * 193lookup_identity(Key *key, int version) 194{ 195 Identity *id; 196 197 Idtab *tab = idtab_lookup(version); 198 TAILQ_FOREACH(id, &tab->idlist, next) { 199 if (key_equal(key, id->key)) 200 return (id); 201 } 202 return (NULL); 203} 204 205/* Check confirmation of keysign request */ 206static int 207confirm_key(Identity *id) 208{ 209 char *p; 210 int ret = -1; 211 212 p = key_fingerprint(id->key, SSH_FP_MD5, SSH_FP_HEX); 213 if (ask_permission("Allow use of key %s?\nKey fingerprint %s.", 214 id->comment, p)) 215 ret = 0; 216 xfree(p); 217 218 return (ret); 219} 220 221/* send list of supported public keys to 'client' */ 222static void 223process_request_identities(SocketEntry *e, int version) 224{ 225 Idtab *tab = idtab_lookup(version); 226 Identity *id; 227 Buffer msg; 228 229 buffer_init(&msg); 230 buffer_put_char(&msg, (version == 1) ? 231 SSH_AGENT_RSA_IDENTITIES_ANSWER : SSH2_AGENT_IDENTITIES_ANSWER); 232 buffer_put_int(&msg, tab->nentries); 233 TAILQ_FOREACH(id, &tab->idlist, next) { 234 if (id->key->type == KEY_RSA1) { 235 buffer_put_int(&msg, BN_num_bits(id->key->rsa->n)); 236 buffer_put_bignum(&msg, id->key->rsa->e); 237 buffer_put_bignum(&msg, id->key->rsa->n); 238 } else { 239 u_char *blob; 240 u_int blen; 241 key_to_blob(id->key, &blob, &blen); 242 buffer_put_string(&msg, blob, blen); 243 xfree(blob); 244 } 245 buffer_put_cstring(&msg, id->comment); 246 } 247 buffer_put_int(&e->output, buffer_len(&msg)); 248 buffer_append(&e->output, buffer_ptr(&msg), buffer_len(&msg)); 249 buffer_free(&msg); 250} 251 252/* ssh1 only */ 253static void 254process_authentication_challenge1(SocketEntry *e) 255{ 256 u_char buf[32], mdbuf[16], session_id[16]; 257 u_int response_type; 258 BIGNUM *challenge; 259 Identity *id; 260 int i, len; 261 Buffer msg; 262 MD5_CTX md; 263 Key *key; 264 265 buffer_init(&msg); 266 key = key_new(KEY_RSA1); 267 if ((challenge = BN_new()) == NULL) 268 fatal("process_authentication_challenge1: BN_new failed"); 269 270 (void) buffer_get_int(&e->request); /* ignored */ 271 buffer_get_bignum(&e->request, key->rsa->e); 272 buffer_get_bignum(&e->request, key->rsa->n); 273 buffer_get_bignum(&e->request, challenge); 274 275 /* Only protocol 1.1 is supported */ 276 if (buffer_len(&e->request) == 0) 277 goto failure; 278 buffer_get(&e->request, session_id, 16); 279 response_type = buffer_get_int(&e->request); 280 if (response_type != 1) 281 goto failure; 282 283 id = lookup_identity(key, 1); 284 if (id != NULL && (!id->confirm || confirm_key(id) == 0)) { 285 Key *private = id->key; 286 /* Decrypt the challenge using the private key. */ 287 if (rsa_private_decrypt(challenge, challenge, private->rsa) <= 0) 288 goto failure; 289 290 /* The response is MD5 of decrypted challenge plus session id. */ 291 len = BN_num_bytes(challenge); 292 if (len <= 0 || len > 32) { 293 logit("process_authentication_challenge: bad challenge length %d", len); 294 goto failure; 295 } 296 memset(buf, 0, 32); 297 BN_bn2bin(challenge, buf + 32 - len); 298 MD5_Init(&md); 299 MD5_Update(&md, buf, 32); 300 MD5_Update(&md, session_id, 16); 301 MD5_Final(mdbuf, &md); 302 303 /* Send the response. */ 304 buffer_put_char(&msg, SSH_AGENT_RSA_RESPONSE); 305 for (i = 0; i < 16; i++) 306 buffer_put_char(&msg, mdbuf[i]); 307 goto send; 308 } 309 310failure: 311 /* Unknown identity or protocol error. Send failure. */ 312 buffer_put_char(&msg, SSH_AGENT_FAILURE); 313send: 314 buffer_put_int(&e->output, buffer_len(&msg)); 315 buffer_append(&e->output, buffer_ptr(&msg), buffer_len(&msg)); 316 key_free(key); 317 BN_clear_free(challenge); 318 buffer_free(&msg); 319} 320 321/* ssh2 only */ 322static void 323process_sign_request2(SocketEntry *e) 324{ 325 u_char *blob, *data, *signature = NULL; 326 u_int blen, dlen, slen = 0; 327 extern int datafellows; 328 int odatafellows; 329 int ok = -1, flags; 330 Buffer msg; 331 Key *key; 332 333 datafellows = 0; 334 335 blob = buffer_get_string(&e->request, &blen); 336 data = buffer_get_string(&e->request, &dlen); 337 338 flags = buffer_get_int(&e->request); 339 odatafellows = datafellows; 340 if (flags & SSH_AGENT_OLD_SIGNATURE) 341 datafellows = SSH_BUG_SIGBLOB; 342 343 key = key_from_blob(blob, blen); 344 if (key != NULL) { 345 Identity *id = lookup_identity(key, 2); 346 if (id != NULL && (!id->confirm || confirm_key(id) == 0)) 347 ok = key_sign(id->key, &signature, &slen, data, dlen); 348 key_free(key); 349 } 350 buffer_init(&msg); 351 if (ok == 0) { 352 buffer_put_char(&msg, SSH2_AGENT_SIGN_RESPONSE); 353 buffer_put_string(&msg, signature, slen); 354 } else { 355 buffer_put_char(&msg, SSH_AGENT_FAILURE); 356 } 357 buffer_put_int(&e->output, buffer_len(&msg)); 358 buffer_append(&e->output, buffer_ptr(&msg), 359 buffer_len(&msg)); 360 buffer_free(&msg); 361 xfree(data); 362 xfree(blob); 363 if (signature != NULL) 364 xfree(signature); 365 datafellows = odatafellows; 366} 367 368/* shared */ 369static void 370process_remove_identity(SocketEntry *e, int version) 371{ 372 u_int blen, bits; 373 int success = 0; 374 Key *key = NULL; 375 u_char *blob; 376 377 switch (version) { 378 case 1: 379 key = key_new(KEY_RSA1); 380 bits = buffer_get_int(&e->request); 381 buffer_get_bignum(&e->request, key->rsa->e); 382 buffer_get_bignum(&e->request, key->rsa->n); 383 384 if (bits != key_size(key)) 385 logit("Warning: identity keysize mismatch: actual %u, announced %u", 386 key_size(key), bits); 387 break; 388 case 2: 389 blob = buffer_get_string(&e->request, &blen); 390 key = key_from_blob(blob, blen); 391 xfree(blob); 392 break; 393 } 394 if (key != NULL) { 395 Identity *id = lookup_identity(key, version); 396 if (id != NULL) { 397 /* 398 * We have this key. Free the old key. Since we 399 * don't want to leave empty slots in the middle of 400 * the array, we actually free the key there and move 401 * all the entries between the empty slot and the end 402 * of the array. 403 */ 404 Idtab *tab = idtab_lookup(version); 405 if (tab->nentries < 1) 406 fatal("process_remove_identity: " 407 "internal error: tab->nentries %d", 408 tab->nentries); 409 TAILQ_REMOVE(&tab->idlist, id, next); 410 free_identity(id); 411 tab->nentries--; 412 success = 1; 413 } 414 key_free(key); 415 } 416 buffer_put_int(&e->output, 1); 417 buffer_put_char(&e->output, 418 success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE); 419} 420 421static void 422process_remove_all_identities(SocketEntry *e, int version) 423{ 424 Idtab *tab = idtab_lookup(version); 425 Identity *id; 426 427 /* Loop over all identities and clear the keys. */ 428 for (id = TAILQ_FIRST(&tab->idlist); id; 429 id = TAILQ_FIRST(&tab->idlist)) { 430 TAILQ_REMOVE(&tab->idlist, id, next); 431 free_identity(id); 432 } 433 434 /* Mark that there are no identities. */ 435 tab->nentries = 0; 436 437 /* Send success. */ 438 buffer_put_int(&e->output, 1); 439 buffer_put_char(&e->output, SSH_AGENT_SUCCESS); 440} 441 442/* removes expired keys and returns number of seconds until the next expiry */ 443static u_int 444reaper(void) 445{ 446 u_int deadline = 0, now = time(NULL); 447 Identity *id, *nxt; 448 int version; 449 Idtab *tab; 450 451 for (version = 1; version < 3; version++) { 452 tab = idtab_lookup(version); 453 for (id = TAILQ_FIRST(&tab->idlist); id; id = nxt) { 454 nxt = TAILQ_NEXT(id, next); 455 if (id->death == 0) 456 continue; 457 if (now >= id->death) { 458 debug("expiring key '%s'", id->comment); 459 TAILQ_REMOVE(&tab->idlist, id, next); 460 free_identity(id); 461 tab->nentries--; 462 } else 463 deadline = (deadline == 0) ? id->death : 464 MIN(deadline, id->death); 465 } 466 } 467 if (deadline == 0 || deadline <= now) 468 return 0; 469 else 470 return (deadline - now); 471} 472 473static void 474process_add_identity(SocketEntry *e, int version) 475{ 476 Idtab *tab = idtab_lookup(version); 477 Identity *id; 478 int type, success = 0, death = 0, confirm = 0; 479 char *type_name, *comment; 480 Key *k = NULL; 481#ifdef OPENSSL_HAS_ECC 482 BIGNUM *exponent; 483 EC_POINT *q; 484 char *curve; 485#endif 486 u_char *cert; 487 u_int len; 488 489 switch (version) { 490 case 1: 491 k = key_new_private(KEY_RSA1); 492 (void) buffer_get_int(&e->request); /* ignored */ 493 buffer_get_bignum(&e->request, k->rsa->n); 494 buffer_get_bignum(&e->request, k->rsa->e); 495 buffer_get_bignum(&e->request, k->rsa->d); 496 buffer_get_bignum(&e->request, k->rsa->iqmp); 497 498 /* SSH and SSL have p and q swapped */ 499 buffer_get_bignum(&e->request, k->rsa->q); /* p */ 500 buffer_get_bignum(&e->request, k->rsa->p); /* q */ 501 502 /* Generate additional parameters */ 503 rsa_generate_additional_parameters(k->rsa); 504 break; 505 case 2: 506 type_name = buffer_get_string(&e->request, NULL); 507 type = key_type_from_name(type_name); 508 switch (type) { 509 case KEY_DSA: 510 k = key_new_private(type); 511 buffer_get_bignum2(&e->request, k->dsa->p); 512 buffer_get_bignum2(&e->request, k->dsa->q); 513 buffer_get_bignum2(&e->request, k->dsa->g); 514 buffer_get_bignum2(&e->request, k->dsa->pub_key); 515 buffer_get_bignum2(&e->request, k->dsa->priv_key); 516 break; 517 case KEY_DSA_CERT_V00: 518 case KEY_DSA_CERT: 519 cert = buffer_get_string(&e->request, &len); 520 if ((k = key_from_blob(cert, len)) == NULL) 521 fatal("Certificate parse failed"); 522 xfree(cert); 523 key_add_private(k); 524 buffer_get_bignum2(&e->request, k->dsa->priv_key); 525 break; 526#ifdef OPENSSL_HAS_ECC 527 case KEY_ECDSA: 528 k = key_new_private(type); 529 k->ecdsa_nid = key_ecdsa_nid_from_name(type_name); 530 curve = buffer_get_string(&e->request, NULL); 531 if (k->ecdsa_nid != key_curve_name_to_nid(curve)) 532 fatal("%s: curve names mismatch", __func__); 533 xfree(curve); 534 k->ecdsa = EC_KEY_new_by_curve_name(k->ecdsa_nid); 535 if (k->ecdsa == NULL) 536 fatal("%s: EC_KEY_new_by_curve_name failed", 537 __func__); 538 q = EC_POINT_new(EC_KEY_get0_group(k->ecdsa)); 539 if (q == NULL) 540 fatal("%s: BN_new failed", __func__); 541 if ((exponent = BN_new()) == NULL) 542 fatal("%s: BN_new failed", __func__); 543 buffer_get_ecpoint(&e->request, 544 EC_KEY_get0_group(k->ecdsa), q); 545 buffer_get_bignum2(&e->request, exponent); 546 if (EC_KEY_set_public_key(k->ecdsa, q) != 1) 547 fatal("%s: EC_KEY_set_public_key failed", 548 __func__); 549 if (EC_KEY_set_private_key(k->ecdsa, exponent) != 1) 550 fatal("%s: EC_KEY_set_private_key failed", 551 __func__); 552 if (key_ec_validate_public(EC_KEY_get0_group(k->ecdsa), 553 EC_KEY_get0_public_key(k->ecdsa)) != 0) 554 fatal("%s: bad ECDSA public key", __func__); 555 if (key_ec_validate_private(k->ecdsa) != 0) 556 fatal("%s: bad ECDSA private key", __func__); 557 BN_clear_free(exponent); 558 EC_POINT_free(q); 559 break; 560 case KEY_ECDSA_CERT: 561 cert = buffer_get_string(&e->request, &len); 562 if ((k = key_from_blob(cert, len)) == NULL) 563 fatal("Certificate parse failed"); 564 xfree(cert); 565 key_add_private(k); 566 if ((exponent = BN_new()) == NULL) 567 fatal("%s: BN_new failed", __func__); 568 buffer_get_bignum2(&e->request, exponent); 569 if (EC_KEY_set_private_key(k->ecdsa, exponent) != 1) 570 fatal("%s: EC_KEY_set_private_key failed", 571 __func__); 572 if (key_ec_validate_public(EC_KEY_get0_group(k->ecdsa), 573 EC_KEY_get0_public_key(k->ecdsa)) != 0 || 574 key_ec_validate_private(k->ecdsa) != 0) 575 fatal("%s: bad ECDSA key", __func__); 576 BN_clear_free(exponent); 577 break; 578#endif /* OPENSSL_HAS_ECC */ 579 case KEY_RSA: 580 k = key_new_private(type); 581 buffer_get_bignum2(&e->request, k->rsa->n); 582 buffer_get_bignum2(&e->request, k->rsa->e); 583 buffer_get_bignum2(&e->request, k->rsa->d); 584 buffer_get_bignum2(&e->request, k->rsa->iqmp); 585 buffer_get_bignum2(&e->request, k->rsa->p); 586 buffer_get_bignum2(&e->request, k->rsa->q); 587 588 /* Generate additional parameters */ 589 rsa_generate_additional_parameters(k->rsa); 590 break; 591 case KEY_RSA_CERT_V00: 592 case KEY_RSA_CERT: 593 cert = buffer_get_string(&e->request, &len); 594 if ((k = key_from_blob(cert, len)) == NULL) 595 fatal("Certificate parse failed"); 596 xfree(cert); 597 key_add_private(k); 598 buffer_get_bignum2(&e->request, k->rsa->d); 599 buffer_get_bignum2(&e->request, k->rsa->iqmp); 600 buffer_get_bignum2(&e->request, k->rsa->p); 601 buffer_get_bignum2(&e->request, k->rsa->q); 602 break; 603 default: 604 xfree(type_name); 605 buffer_clear(&e->request); 606 goto send; 607 } 608 xfree(type_name); 609 break; 610 } 611 /* enable blinding */ 612 switch (k->type) { 613 case KEY_RSA: 614 case KEY_RSA_CERT_V00: 615 case KEY_RSA_CERT: 616 case KEY_RSA1: 617 if (RSA_blinding_on(k->rsa, NULL) != 1) { 618 error("process_add_identity: RSA_blinding_on failed"); 619 key_free(k); 620 goto send; 621 } 622 break; 623 } 624 comment = buffer_get_string(&e->request, NULL); 625 if (k == NULL) { 626 xfree(comment); 627 goto send; 628 } 629 while (buffer_len(&e->request)) { 630 switch ((type = buffer_get_char(&e->request))) { 631 case SSH_AGENT_CONSTRAIN_LIFETIME: 632 death = time(NULL) + buffer_get_int(&e->request); 633 break; 634 case SSH_AGENT_CONSTRAIN_CONFIRM: 635 confirm = 1; 636 break; 637 default: 638 error("process_add_identity: " 639 "Unknown constraint type %d", type); 640 xfree(comment); 641 key_free(k); 642 goto send; 643 } 644 } 645 success = 1; 646 if (lifetime && !death) 647 death = time(NULL) + lifetime; 648 if ((id = lookup_identity(k, version)) == NULL) { 649 id = xcalloc(1, sizeof(Identity)); 650 id->key = k; 651 TAILQ_INSERT_TAIL(&tab->idlist, id, next); 652 /* Increment the number of identities. */ 653 tab->nentries++; 654 } else { 655 key_free(k); 656 xfree(id->comment); 657 } 658 id->comment = comment; 659 id->death = death; 660 id->confirm = confirm; 661send: 662 buffer_put_int(&e->output, 1); 663 buffer_put_char(&e->output, 664 success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE); 665} 666 667/* XXX todo: encrypt sensitive data with passphrase */ 668static void 669process_lock_agent(SocketEntry *e, int lock) 670{ 671 int success = 0; 672 char *passwd; 673 674 passwd = buffer_get_string(&e->request, NULL); 675 if (locked && !lock && strcmp(passwd, lock_passwd) == 0) { 676 locked = 0; 677 memset(lock_passwd, 0, strlen(lock_passwd)); 678 xfree(lock_passwd); 679 lock_passwd = NULL; 680 success = 1; 681 } else if (!locked && lock) { 682 locked = 1; 683 lock_passwd = xstrdup(passwd); 684 success = 1; 685 } 686 memset(passwd, 0, strlen(passwd)); 687 xfree(passwd); 688 689 buffer_put_int(&e->output, 1); 690 buffer_put_char(&e->output, 691 success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE); 692} 693 694static void 695no_identities(SocketEntry *e, u_int type) 696{ 697 Buffer msg; 698 699 buffer_init(&msg); 700 buffer_put_char(&msg, 701 (type == SSH_AGENTC_REQUEST_RSA_IDENTITIES) ? 702 SSH_AGENT_RSA_IDENTITIES_ANSWER : SSH2_AGENT_IDENTITIES_ANSWER); 703 buffer_put_int(&msg, 0); 704 buffer_put_int(&e->output, buffer_len(&msg)); 705 buffer_append(&e->output, buffer_ptr(&msg), buffer_len(&msg)); 706 buffer_free(&msg); 707} 708 709#ifdef ENABLE_PKCS11 710static void 711process_add_smartcard_key(SocketEntry *e) 712{ 713 char *provider = NULL, *pin; 714 int i, type, version, count = 0, success = 0, death = 0, confirm = 0; 715 Key **keys = NULL, *k; 716 Identity *id; 717 Idtab *tab; 718 719 provider = buffer_get_string(&e->request, NULL); 720 pin = buffer_get_string(&e->request, NULL); 721 722 while (buffer_len(&e->request)) { 723 switch ((type = buffer_get_char(&e->request))) { 724 case SSH_AGENT_CONSTRAIN_LIFETIME: 725 death = time(NULL) + buffer_get_int(&e->request); 726 break; 727 case SSH_AGENT_CONSTRAIN_CONFIRM: 728 confirm = 1; 729 break; 730 default: 731 error("process_add_smartcard_key: " 732 "Unknown constraint type %d", type); 733 goto send; 734 } 735 } 736 if (lifetime && !death) 737 death = time(NULL) + lifetime; 738 739 count = pkcs11_add_provider(provider, pin, &keys); 740 for (i = 0; i < count; i++) { 741 k = keys[i]; 742 version = k->type == KEY_RSA1 ? 1 : 2; 743 tab = idtab_lookup(version); 744 if (lookup_identity(k, version) == NULL) { 745 id = xcalloc(1, sizeof(Identity)); 746 id->key = k; 747 id->provider = xstrdup(provider); 748 id->comment = xstrdup(provider); /* XXX */ 749 id->death = death; 750 id->confirm = confirm; 751 TAILQ_INSERT_TAIL(&tab->idlist, id, next); 752 tab->nentries++; 753 success = 1; 754 } else { 755 key_free(k); 756 } 757 keys[i] = NULL; 758 } 759send: 760 if (pin) 761 xfree(pin); 762 if (provider) 763 xfree(provider); 764 if (keys) 765 xfree(keys); 766 buffer_put_int(&e->output, 1); 767 buffer_put_char(&e->output, 768 success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE); 769} 770 771static void 772process_remove_smartcard_key(SocketEntry *e) 773{ 774 char *provider = NULL, *pin = NULL; 775 int version, success = 0; 776 Identity *id, *nxt; 777 Idtab *tab; 778 779 provider = buffer_get_string(&e->request, NULL); 780 pin = buffer_get_string(&e->request, NULL); 781 xfree(pin); 782 783 for (version = 1; version < 3; version++) { 784 tab = idtab_lookup(version); 785 for (id = TAILQ_FIRST(&tab->idlist); id; id = nxt) { 786 nxt = TAILQ_NEXT(id, next); 787 if (!strcmp(provider, id->provider)) { 788 TAILQ_REMOVE(&tab->idlist, id, next); 789 free_identity(id); 790 tab->nentries--; 791 } 792 } 793 } 794 if (pkcs11_del_provider(provider) == 0) 795 success = 1; 796 else 797 error("process_remove_smartcard_key:" 798 " pkcs11_del_provider failed"); 799 xfree(provider); 800 buffer_put_int(&e->output, 1); 801 buffer_put_char(&e->output, 802 success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE); 803} 804#endif /* ENABLE_PKCS11 */ 805 806static int 807add_identity_callback(const char *filename, const char *passphrase) 808{ 809 Key *k; 810 int version; 811 Idtab *tab; 812 813 if ((k = key_load_private(filename, passphrase, NULL)) == NULL) 814 return 1; 815 switch (k->type) { 816 case KEY_RSA: 817 case KEY_RSA1: 818 if (RSA_blinding_on(k->rsa, NULL) != 1) { 819 key_free(k); 820 return 1; 821 } 822 break; 823 } 824 version = k->type == KEY_RSA1 ? 1 : 2; 825 tab = idtab_lookup(version); 826 if (lookup_identity(k, version) == NULL) { 827 Identity *id = xcalloc(1, sizeof(Identity)); 828 id->key = k; 829 id->comment = xstrdup(filename); 830 if (id->comment == NULL) { 831 key_free(k); 832 return 1; 833 } 834 TAILQ_INSERT_TAIL(&tab->idlist, id, next); 835 tab->nentries++; 836 } else { 837 key_free(k); 838 return 1; 839 } 840 841 return 0; 842} 843 844#ifdef KEYCHAIN 845static void 846process_add_from_keychain(SocketEntry *e) 847{ 848 int result; 849 850 result = add_identities_using_keychain(&add_identity_callback); 851 852 /* Start thread to wait for keychain notifications. */ 853 keychain_thread_init(); 854 855 /* e will be NULL when ssh-agent adds keys on its own at startup */ 856 if (e) { 857 buffer_put_int(&e->output, 1); 858 buffer_put_char(&e->output, 859 result ? SSH_AGENT_FAILURE : SSH_AGENT_SUCCESS); 860 } 861} 862#endif /* KEYCHAIN */ 863 864/* dispatch incoming messages */ 865 866static void 867process_message(SocketEntry *e) 868{ 869 u_int msg_len, type; 870 u_char *cp; 871 872 if (buffer_len(&e->input) < 5) 873 return; /* Incomplete message. */ 874 cp = buffer_ptr(&e->input); 875 msg_len = get_u32(cp); 876 if (msg_len > 256 * 1024) { 877 close_socket(e); 878 return; 879 } 880 if (buffer_len(&e->input) < msg_len + 4) 881 return; 882 883 /* move the current input to e->request */ 884 buffer_consume(&e->input, 4); 885 buffer_clear(&e->request); 886 buffer_append(&e->request, buffer_ptr(&e->input), msg_len); 887 buffer_consume(&e->input, msg_len); 888 type = buffer_get_char(&e->request); 889 890 /* check wheter agent is locked */ 891 if (locked && type != SSH_AGENTC_UNLOCK) { 892 buffer_clear(&e->request); 893 switch (type) { 894 case SSH_AGENTC_REQUEST_RSA_IDENTITIES: 895 case SSH2_AGENTC_REQUEST_IDENTITIES: 896 /* send empty lists */ 897 no_identities(e, type); 898 break; 899 default: 900 /* send a fail message for all other request types */ 901 buffer_put_int(&e->output, 1); 902 buffer_put_char(&e->output, SSH_AGENT_FAILURE); 903 } 904 return; 905 } 906 907 debug("type %d", type); 908 switch (type) { 909 case SSH_AGENTC_LOCK: 910 case SSH_AGENTC_UNLOCK: 911 process_lock_agent(e, type == SSH_AGENTC_LOCK); 912 break; 913 /* ssh1 */ 914 case SSH_AGENTC_RSA_CHALLENGE: 915 process_authentication_challenge1(e); 916 break; 917 case SSH_AGENTC_REQUEST_RSA_IDENTITIES: 918 process_request_identities(e, 1); 919 break; 920 case SSH_AGENTC_ADD_RSA_IDENTITY: 921 case SSH_AGENTC_ADD_RSA_ID_CONSTRAINED: 922 process_add_identity(e, 1); 923 break; 924 case SSH_AGENTC_REMOVE_RSA_IDENTITY: 925 process_remove_identity(e, 1); 926 break; 927 case SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES: 928 process_remove_all_identities(e, 1); 929 break; 930 /* ssh2 */ 931 case SSH2_AGENTC_SIGN_REQUEST: 932 process_sign_request2(e); 933 break; 934 case SSH2_AGENTC_REQUEST_IDENTITIES: 935 process_request_identities(e, 2); 936 break; 937 case SSH2_AGENTC_ADD_IDENTITY: 938 case SSH2_AGENTC_ADD_ID_CONSTRAINED: 939 process_add_identity(e, 2); 940 break; 941 case SSH2_AGENTC_REMOVE_IDENTITY: 942 process_remove_identity(e, 2); 943 break; 944 case SSH2_AGENTC_REMOVE_ALL_IDENTITIES: 945 process_remove_all_identities(e, 2); 946 break; 947#ifdef ENABLE_PKCS11 948 case SSH_AGENTC_ADD_SMARTCARD_KEY: 949 case SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED: 950 process_add_smartcard_key(e); 951 break; 952 case SSH_AGENTC_REMOVE_SMARTCARD_KEY: 953 process_remove_smartcard_key(e); 954 break; 955#endif /* ENABLE_PKCS11 */ 956#ifdef KEYCHAIN 957 case SSH_AGENTC_ADD_FROM_KEYCHAIN: 958 process_add_from_keychain(e); 959 break; 960#endif /* KEYCHAIN */ 961 default: 962 /* Unknown message. Respond with failure. */ 963 error("Unknown message %d", type); 964 buffer_clear(&e->request); 965 buffer_put_int(&e->output, 1); 966 buffer_put_char(&e->output, SSH_AGENT_FAILURE); 967 break; 968 } 969} 970 971static void 972new_socket(sock_type type, int fd) 973{ 974 u_int i, old_alloc, new_alloc; 975 976 set_nonblock(fd); 977 978 if (fd > max_fd) 979 max_fd = fd; 980 981 for (i = 0; i < sockets_alloc; i++) 982 if (sockets[i].type == AUTH_UNUSED) { 983 sockets[i].fd = fd; 984 buffer_init(&sockets[i].input); 985 buffer_init(&sockets[i].output); 986 buffer_init(&sockets[i].request); 987 sockets[i].type = type; 988 return; 989 } 990 old_alloc = sockets_alloc; 991 new_alloc = sockets_alloc + 10; 992 sockets = xrealloc(sockets, new_alloc, sizeof(sockets[0])); 993 for (i = old_alloc; i < new_alloc; i++) 994 sockets[i].type = AUTH_UNUSED; 995 sockets_alloc = new_alloc; 996 sockets[old_alloc].fd = fd; 997 buffer_init(&sockets[old_alloc].input); 998 buffer_init(&sockets[old_alloc].output); 999 buffer_init(&sockets[old_alloc].request); 1000 sockets[old_alloc].type = type; 1001} 1002 1003static int 1004prepare_select(fd_set **fdrp, fd_set **fdwp, int *fdl, u_int *nallocp, 1005 struct timeval **tvpp) 1006{ 1007 u_int i, sz, deadline; 1008 int n = 0; 1009 static struct timeval tv; 1010 1011 for (i = 0; i < sockets_alloc; i++) { 1012 switch (sockets[i].type) { 1013 case AUTH_SOCKET: 1014 case AUTH_CONNECTION: 1015 n = MAX(n, sockets[i].fd); 1016 break; 1017 case AUTH_UNUSED: 1018 break; 1019 default: 1020 fatal("Unknown socket type %d", sockets[i].type); 1021 break; 1022 } 1023 } 1024 1025 sz = howmany(n+1, NFDBITS) * sizeof(fd_mask); 1026 if (*fdrp == NULL || sz > *nallocp) { 1027 if (*fdrp) 1028 xfree(*fdrp); 1029 if (*fdwp) 1030 xfree(*fdwp); 1031 *fdrp = xmalloc(sz); 1032 *fdwp = xmalloc(sz); 1033 *nallocp = sz; 1034 } 1035 if (n < *fdl) 1036 debug("XXX shrink: %d < %d", n, *fdl); 1037 *fdl = n; 1038 memset(*fdrp, 0, sz); 1039 memset(*fdwp, 0, sz); 1040 1041 for (i = 0; i < sockets_alloc; i++) { 1042 switch (sockets[i].type) { 1043 case AUTH_SOCKET: 1044 case AUTH_CONNECTION: 1045 FD_SET(sockets[i].fd, *fdrp); 1046 if (buffer_len(&sockets[i].output) > 0) 1047 FD_SET(sockets[i].fd, *fdwp); 1048 break; 1049 default: 1050 break; 1051 } 1052 } 1053 deadline = reaper(); 1054 if (parent_alive_interval != 0) 1055 deadline = (deadline == 0) ? parent_alive_interval : 1056 MIN(deadline, parent_alive_interval); 1057 if (deadline == 0) { 1058 *tvpp = NULL; 1059 } else { 1060 tv.tv_sec = deadline; 1061 tv.tv_usec = 0; 1062 *tvpp = &tv; 1063 } 1064 return (1); 1065} 1066 1067static void 1068after_select(fd_set *readset, fd_set *writeset) 1069{ 1070 struct sockaddr_un sunaddr; 1071 socklen_t slen; 1072 char buf[1024]; 1073 int len, sock; 1074 u_int i, orig_alloc; 1075 uid_t euid; 1076 gid_t egid; 1077 1078 for (i = 0, orig_alloc = sockets_alloc; i < orig_alloc; i++) 1079 switch (sockets[i].type) { 1080 case AUTH_UNUSED: 1081 break; 1082 case AUTH_SOCKET: 1083 if (FD_ISSET(sockets[i].fd, readset)) { 1084 slen = sizeof(sunaddr); 1085 sock = accept(sockets[i].fd, 1086 (struct sockaddr *)&sunaddr, &slen); 1087 if (sock < 0) { 1088 error("accept from AUTH_SOCKET: %s", 1089 strerror(errno)); 1090 break; 1091 } 1092 if (getpeereid(sock, &euid, &egid) < 0) { 1093 error("getpeereid %d failed: %s", 1094 sock, strerror(errno)); 1095 close(sock); 1096 break; 1097 } 1098 if ((euid != 0) && (getuid() != euid)) { 1099 error("uid mismatch: " 1100 "peer euid %u != uid %u", 1101 (u_int) euid, (u_int) getuid()); 1102 close(sock); 1103 break; 1104 } 1105 new_socket(AUTH_CONNECTION, sock); 1106 } 1107 break; 1108 case AUTH_CONNECTION: 1109 if (buffer_len(&sockets[i].output) > 0 && 1110 FD_ISSET(sockets[i].fd, writeset)) { 1111 len = write(sockets[i].fd, 1112 buffer_ptr(&sockets[i].output), 1113 buffer_len(&sockets[i].output)); 1114 if (len == -1 && (errno == EAGAIN || 1115 errno == EWOULDBLOCK || 1116 errno == EINTR)) 1117 continue; 1118 if (len <= 0) { 1119 close_socket(&sockets[i]); 1120 break; 1121 } 1122 buffer_consume(&sockets[i].output, len); 1123 } 1124 if (FD_ISSET(sockets[i].fd, readset)) { 1125 len = read(sockets[i].fd, buf, sizeof(buf)); 1126 if (len == -1 && (errno == EAGAIN || 1127 errno == EWOULDBLOCK || 1128 errno == EINTR)) 1129 continue; 1130 if (len <= 0) { 1131 close_socket(&sockets[i]); 1132 break; 1133 } 1134 buffer_append(&sockets[i].input, buf, len); 1135 process_message(&sockets[i]); 1136 } 1137 break; 1138 default: 1139 fatal("Unknown type %d", sockets[i].type); 1140 } 1141} 1142 1143static void 1144cleanup_socket(void) 1145{ 1146 if (socket_name[0]) 1147 unlink(socket_name); 1148 if (socket_dir[0]) 1149 rmdir(socket_dir); 1150} 1151 1152void 1153cleanup_exit(int i) 1154{ 1155 cleanup_socket(); 1156 _exit(i); 1157} 1158 1159/*ARGSUSED*/ 1160static void 1161cleanup_handler(int sig) 1162{ 1163 cleanup_socket(); 1164#ifdef ENABLE_PKCS11 1165 pkcs11_terminate(); 1166#endif 1167 _exit(2); 1168} 1169 1170static void 1171check_parent_exists(void) 1172{ 1173 /* 1174 * If our parent has exited then getppid() will return (pid_t)1, 1175 * so testing for that should be safe. 1176 */ 1177 if (parent_pid != -1 && getppid() != parent_pid) { 1178 /* printf("Parent has died - Authentication agent exiting.\n"); */ 1179 cleanup_socket(); 1180 _exit(2); 1181 } 1182} 1183 1184static void 1185usage(void) 1186{ 1187 fprintf(stderr, "usage: %s [options] [command [arg ...]]\n", 1188 __progname); 1189 fprintf(stderr, "Options:\n"); 1190 fprintf(stderr, " -c Generate C-shell commands on stdout.\n"); 1191 fprintf(stderr, " -s Generate Bourne shell commands on stdout.\n"); 1192 fprintf(stderr, " -k Kill the current agent.\n"); 1193 fprintf(stderr, " -d Debug mode.\n"); 1194 fprintf(stderr, " -a socket Bind agent socket to given name.\n"); 1195 fprintf(stderr, " -t life Default identity lifetime (seconds).\n"); 1196 exit(1); 1197} 1198 1199int 1200main(int ac, char **av) 1201{ 1202#ifdef __APPLE_LAUNCHD__ 1203 int c_flag = 0, d_flag = 0, k_flag = 0, s_flag = 0, l_flag = 0; 1204#else 1205 int c_flag = 0, d_flag = 0, k_flag = 0, s_flag = 0; 1206#endif 1207 int sock, fd, ch, result, saved_errno; 1208 u_int nalloc; 1209 char *shell, *format, *pidstr, *agentsocket = NULL; 1210 fd_set *readsetp = NULL, *writesetp = NULL; 1211 struct sockaddr_un sunaddr; 1212#ifdef HAVE_SETRLIMIT 1213 struct rlimit rlim; 1214#endif 1215 int prev_mask; 1216 extern int optind; 1217 extern char *optarg; 1218 pid_t pid; 1219 char pidstrbuf[1 + 3 * sizeof pid]; 1220 struct timeval *tvp = NULL; 1221 size_t len; 1222 1223 /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ 1224 sanitise_stdfd(); 1225 1226 /* drop */ 1227 setegid(getgid()); 1228 setgid(getgid()); 1229 1230#if defined(HAVE_PRCTL) && defined(PR_SET_DUMPABLE) 1231 /* Disable ptrace on Linux without sgid bit */ 1232 prctl(PR_SET_DUMPABLE, 0); 1233#endif 1234 1235 OpenSSL_add_all_algorithms(); 1236 1237 __progname = ssh_get_progname(av[0]); 1238 seed_rng(); 1239 1240#ifdef __APPLE_LAUNCHD__ 1241 while ((ch = getopt(ac, av, "cdklsa:t:")) != -1) { 1242#else 1243 while ((ch = getopt(ac, av, "cdksa:t:")) != -1) { 1244#endif 1245 switch (ch) { 1246 case 'c': 1247 if (s_flag) 1248 usage(); 1249 c_flag++; 1250 break; 1251 case 'k': 1252 k_flag++; 1253 break; 1254#ifdef __APPLE_LAUNCHD__ 1255 case 'l': 1256 l_flag++; 1257 break; 1258#endif 1259 case 's': 1260 if (c_flag) 1261 usage(); 1262 s_flag++; 1263 break; 1264 case 'd': 1265 if (d_flag) 1266 usage(); 1267 d_flag++; 1268 break; 1269 case 'a': 1270 agentsocket = optarg; 1271 break; 1272 case 't': 1273 if ((lifetime = convtime(optarg)) == -1) { 1274 fprintf(stderr, "Invalid lifetime\n"); 1275 usage(); 1276 } 1277 break; 1278 default: 1279 usage(); 1280 } 1281 } 1282 ac -= optind; 1283 av += optind; 1284 1285#ifdef __APPPLE_LAUNCHD__ 1286 if (ac > 0 && (c_flag || k_flag || s_flag || d_flag || l_flag)) 1287#else 1288 if (ac > 0 && (c_flag || k_flag || s_flag || d_flag)) 1289#endif 1290 usage(); 1291 1292 if (ac == 0 && !c_flag && !s_flag) { 1293 shell = getenv("SHELL"); 1294 if (shell != NULL && (len = strlen(shell)) > 2 && 1295 strncmp(shell + len - 3, "csh", 3) == 0) 1296 c_flag = 1; 1297 } 1298 if (k_flag) { 1299 const char *errstr = NULL; 1300 1301 pidstr = getenv(SSH_AGENTPID_ENV_NAME); 1302 if (pidstr == NULL) { 1303 fprintf(stderr, "%s not set, cannot kill agent\n", 1304 SSH_AGENTPID_ENV_NAME); 1305 exit(1); 1306 } 1307 pid = (int)strtonum(pidstr, 2, INT_MAX, &errstr); 1308 if (errstr) { 1309 fprintf(stderr, 1310 "%s=\"%s\", which is not a good PID: %s\n", 1311 SSH_AGENTPID_ENV_NAME, pidstr, errstr); 1312 exit(1); 1313 } 1314 if (kill(pid, SIGTERM) == -1) { 1315 perror("kill"); 1316 exit(1); 1317 } 1318 format = c_flag ? "unsetenv %s;\n" : "unset %s;\n"; 1319 printf(format, SSH_AUTHSOCKET_ENV_NAME); 1320 printf(format, SSH_AGENTPID_ENV_NAME); 1321 printf("echo Agent pid %ld killed;\n", (long)pid); 1322 exit(0); 1323 } 1324 parent_pid = getpid(); 1325 1326 if (agentsocket == NULL) { 1327 /* Create private directory for agent socket */ 1328 mktemp_proto(socket_dir, sizeof(socket_dir)); 1329 if (mkdtemp(socket_dir) == NULL) { 1330 perror("mkdtemp: private socket dir"); 1331 exit(1); 1332 } 1333 snprintf(socket_name, sizeof socket_name, "%s/agent.%ld", socket_dir, 1334 (long)parent_pid); 1335 } else { 1336 /* Try to use specified agent socket */ 1337 socket_dir[0] = '\0'; 1338 strlcpy(socket_name, agentsocket, sizeof socket_name); 1339 } 1340 1341 /* 1342 * Create socket early so it will exist before command gets run from 1343 * the parent. 1344 */ 1345#ifdef __APPLE_LAUNCHD__ 1346 if (l_flag) { 1347 launch_data_t resp, msg, tmp; 1348 size_t listeners_i; 1349 1350 msg = launch_data_new_string(LAUNCH_KEY_CHECKIN); 1351 1352 resp = launch_msg(msg); 1353 1354 if (NULL == resp) { 1355 perror("launch_msg"); 1356 exit(1); 1357 } 1358 launch_data_free(msg); 1359 switch (launch_data_get_type(resp)) { 1360 case LAUNCH_DATA_ERRNO: 1361 errno = launch_data_get_errno(resp); 1362 perror("launch_msg response"); 1363 exit(1); 1364 case LAUNCH_DATA_DICTIONARY: 1365 break; 1366 default: 1367 fprintf(stderr, "launch_msg unknown response"); 1368 exit(1); 1369 } 1370 tmp = launch_data_dict_lookup(resp, LAUNCH_JOBKEY_SOCKETS); 1371 1372 if (NULL == tmp) { 1373 fprintf(stderr, "no sockets\n"); 1374 exit(1); 1375 } 1376 1377 tmp = launch_data_dict_lookup(tmp, "Listeners"); 1378 1379 if (NULL == tmp) { 1380 fprintf(stderr, "no known listeners\n"); 1381 exit(1); 1382 } 1383 1384 for (listeners_i = 0; listeners_i < launch_data_array_get_count(tmp); listeners_i++) { 1385 launch_data_t obj_at_ind = launch_data_array_get_index(tmp, listeners_i); 1386 new_socket(AUTH_SOCKET, launch_data_get_fd(obj_at_ind)); 1387 } 1388 1389 launch_data_free(resp); 1390 } else { 1391#endif 1392 sock = socket(AF_UNIX, SOCK_STREAM, 0); 1393 if (sock < 0) { 1394 perror("socket"); 1395 *socket_name = '\0'; /* Don't unlink any existing file */ 1396 cleanup_exit(1); 1397 } 1398 memset(&sunaddr, 0, sizeof(sunaddr)); 1399 sunaddr.sun_family = AF_UNIX; 1400 strlcpy(sunaddr.sun_path, socket_name, sizeof(sunaddr.sun_path)); 1401 prev_mask = umask(0177); 1402 if (bind(sock, (struct sockaddr *) &sunaddr, sizeof(sunaddr)) < 0) { 1403 perror("bind"); 1404 *socket_name = '\0'; /* Don't unlink any existing file */ 1405 umask(prev_mask); 1406 cleanup_exit(1); 1407 } 1408 umask(prev_mask); 1409 if (listen(sock, SSH_LISTEN_BACKLOG) < 0) { 1410 perror("listen"); 1411 cleanup_exit(1); 1412 } 1413#ifdef __APPLE_LAUNCHD__ 1414 } 1415#endif 1416 1417#ifdef __APPLE_LAUNCHD__ 1418 if (l_flag) 1419 goto skip2; 1420#endif 1421 1422 /* 1423 * Fork, and have the parent execute the command, if any, or present 1424 * the socket data. The child continues as the authentication agent. 1425 */ 1426 if (d_flag) { 1427 log_init(__progname, SYSLOG_LEVEL_DEBUG1, SYSLOG_FACILITY_AUTH, 1); 1428 format = c_flag ? "setenv %s %s;\n" : "%s=%s; export %s;\n"; 1429 printf(format, SSH_AUTHSOCKET_ENV_NAME, socket_name, 1430 SSH_AUTHSOCKET_ENV_NAME); 1431 printf("echo Agent pid %ld;\n", (long)parent_pid); 1432 goto skip; 1433 } 1434 pid = fork(); 1435 if (pid == -1) { 1436 perror("fork"); 1437 cleanup_exit(1); 1438 } 1439 if (pid != 0) { /* Parent - execute the given command. */ 1440 close(sock); 1441 snprintf(pidstrbuf, sizeof pidstrbuf, "%ld", (long)pid); 1442 if (ac == 0) { 1443 format = c_flag ? "setenv %s %s;\n" : "%s=%s; export %s;\n"; 1444 printf(format, SSH_AUTHSOCKET_ENV_NAME, socket_name, 1445 SSH_AUTHSOCKET_ENV_NAME); 1446 printf(format, SSH_AGENTPID_ENV_NAME, pidstrbuf, 1447 SSH_AGENTPID_ENV_NAME); 1448 printf("echo Agent pid %ld;\n", (long)pid); 1449 exit(0); 1450 } 1451 if (setenv(SSH_AUTHSOCKET_ENV_NAME, socket_name, 1) == -1 || 1452 setenv(SSH_AGENTPID_ENV_NAME, pidstrbuf, 1) == -1) { 1453 perror("setenv"); 1454 exit(1); 1455 } 1456 execvp(av[0], av); 1457 perror(av[0]); 1458 exit(1); 1459 } 1460 /* child */ 1461 log_init(__progname, SYSLOG_LEVEL_INFO, SYSLOG_FACILITY_AUTH, 0); 1462 1463 if (setsid() == -1) { 1464 error("setsid: %s", strerror(errno)); 1465 cleanup_exit(1); 1466 } 1467 1468 (void)chdir("/"); 1469 if ((fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) { 1470 /* XXX might close listen socket */ 1471 (void)dup2(fd, STDIN_FILENO); 1472 (void)dup2(fd, STDOUT_FILENO); 1473 (void)dup2(fd, STDERR_FILENO); 1474 if (fd > 2) 1475 close(fd); 1476 } 1477 1478#ifdef HAVE_SETRLIMIT 1479 /* deny core dumps, since memory contains unencrypted private keys */ 1480 rlim.rlim_cur = rlim.rlim_max = 0; 1481 if (setrlimit(RLIMIT_CORE, &rlim) < 0) { 1482 error("setrlimit RLIMIT_CORE: %s", strerror(errno)); 1483 cleanup_exit(1); 1484 } 1485#endif 1486 1487skip: 1488 1489#ifdef ENABLE_PKCS11 1490 pkcs11_init(0); 1491#endif 1492 new_socket(AUTH_SOCKET, sock); 1493skip2: 1494 if (ac > 0) 1495 parent_alive_interval = 10; 1496 idtab_init(); 1497 if (!d_flag) 1498 signal(SIGINT, SIG_IGN); 1499 signal(SIGPIPE, SIG_IGN); 1500 signal(SIGHUP, cleanup_handler); 1501 signal(SIGTERM, cleanup_handler); 1502 nalloc = 0; 1503 1504#ifdef KEYCHAIN 1505 process_add_from_keychain(NULL); 1506#endif 1507 1508 while (1) { 1509 prepare_select(&readsetp, &writesetp, &max_fd, &nalloc, &tvp); 1510 result = select(max_fd + 1, readsetp, writesetp, NULL, tvp); 1511 saved_errno = errno; 1512 if (parent_alive_interval != 0) 1513 check_parent_exists(); 1514 (void) reaper(); /* remove expired keys */ 1515 if (result < 0) { 1516 if (saved_errno == EINTR) 1517 continue; 1518 fatal("select: %s", strerror(saved_errno)); 1519 } else if (result > 0) 1520 after_select(readsetp, writesetp); 1521 } 1522 /* NOTREACHED */ 1523} 1524