1 /* $OpenBSD: ssh-agent.c,v 1.185 2014/04/29 18:01:49 markus 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 <sys/types.h> 38 #include <sys/time.h> 39 #include <sys/queue.h> 40 #include <sys/resource.h> 41 #include <sys/types.h> 42 #include <sys/socket.h> 43 #include <sys/un.h> 44 #include <sys/param.h> 45 46 #ifdef WITH_OPENSSL 47 #include <openssl/evp.h> 48 #endif 49 50 #include <errno.h> 51 #include <fcntl.h> 52 #include <paths.h> 53 #include <signal.h> 54 #include <stdlib.h> 55 #include <stdio.h> 56 #include <string.h> 57 #include <time.h> 58 #include <unistd.h> 59 60 #include "xmalloc.h" 61 #include "ssh.h" 62 #include "rsa.h" 63 #include "buffer.h" 64 #include "key.h" 65 #include "authfd.h" 66 #include "compat.h" 67 #include "log.h" 68 #include "misc.h" 69 #include "digest.h" 70 71 #ifdef ENABLE_PKCS11 72 #include "ssh-pkcs11.h" 73 #endif 74 75 typedef enum { 76 AUTH_UNUSED, 77 AUTH_SOCKET, 78 AUTH_CONNECTION 79 } sock_type; 80 81 typedef struct { 82 int fd; 83 sock_type type; 84 Buffer input; 85 Buffer output; 86 Buffer request; 87 } SocketEntry; 88 89 u_int sockets_alloc = 0; 90 SocketEntry *sockets = NULL; 91 92 typedef struct identity { 93 TAILQ_ENTRY(identity) next; 94 Key *key; 95 char *comment; 96 char *provider; 97 time_t death; 98 u_int confirm; 99 } Identity; 100 101 typedef struct { 102 int nentries; 103 TAILQ_HEAD(idqueue, identity) idlist; 104 } Idtab; 105 106 /* private key table, one per protocol version */ 107 Idtab idtable[3]; 108 109 int max_fd = 0; 110 111 /* pid of shell == parent of agent */ 112 pid_t parent_pid = -1; 113 time_t parent_alive_interval = 0; 114 115 /* pathname and directory for AUTH_SOCKET */ 116 char socket_name[MAXPATHLEN]; 117 char socket_dir[MAXPATHLEN]; 118 119 /* locking */ 120 int locked = 0; 121 char *lock_passwd = NULL; 122 123 extern char *__progname; 124 125 /* Default lifetime in seconds (0 == forever) */ 126 static long lifetime = 0; 127 128 static void 129 close_socket(SocketEntry *e) 130 { 131 close(e->fd); 132 e->fd = -1; 133 e->type = AUTH_UNUSED; 134 buffer_free(&e->input); 135 buffer_free(&e->output); 136 buffer_free(&e->request); 137 } 138 139 static void 140 idtab_init(void) 141 { 142 int i; 143 144 for (i = 0; i <=2; i++) { 145 TAILQ_INIT(&idtable[i].idlist); 146 idtable[i].nentries = 0; 147 } 148 } 149 150 /* return private key table for requested protocol version */ 151 static Idtab * 152 idtab_lookup(int version) 153 { 154 if (version < 1 || version > 2) 155 fatal("internal error, bad protocol version %d", version); 156 return &idtable[version]; 157 } 158 159 static void 160 free_identity(Identity *id) 161 { 162 key_free(id->key); 163 free(id->provider); 164 free(id->comment); 165 free(id); 166 } 167 168 /* return matching private key for given public key */ 169 static Identity * 170 lookup_identity(Key *key, int version) 171 { 172 Identity *id; 173 174 Idtab *tab = idtab_lookup(version); 175 TAILQ_FOREACH(id, &tab->idlist, next) { 176 if (key_equal(key, id->key)) 177 return (id); 178 } 179 return (NULL); 180 } 181 182 /* Check confirmation of keysign request */ 183 static int 184 confirm_key(Identity *id) 185 { 186 char *p; 187 int ret = -1; 188 189 p = key_fingerprint(id->key, SSH_FP_MD5, SSH_FP_HEX); 190 if (ask_permission("Allow use of key %s?\nKey fingerprint %s.", 191 id->comment, p)) 192 ret = 0; 193 free(p); 194 195 return (ret); 196 } 197 198 /* send list of supported public keys to 'client' */ 199 static void 200 process_request_identities(SocketEntry *e, int version) 201 { 202 Idtab *tab = idtab_lookup(version); 203 Identity *id; 204 Buffer msg; 205 206 buffer_init(&msg); 207 buffer_put_char(&msg, (version == 1) ? 208 SSH_AGENT_RSA_IDENTITIES_ANSWER : SSH2_AGENT_IDENTITIES_ANSWER); 209 buffer_put_int(&msg, tab->nentries); 210 TAILQ_FOREACH(id, &tab->idlist, next) { 211 if (id->key->type == KEY_RSA1) { 212 #ifdef WITH_SSH1 213 buffer_put_int(&msg, BN_num_bits(id->key->rsa->n)); 214 buffer_put_bignum(&msg, id->key->rsa->e); 215 buffer_put_bignum(&msg, id->key->rsa->n); 216 #endif 217 } else { 218 u_char *blob; 219 u_int blen; 220 key_to_blob(id->key, &blob, &blen); 221 buffer_put_string(&msg, blob, blen); 222 free(blob); 223 } 224 buffer_put_cstring(&msg, id->comment); 225 } 226 buffer_put_int(&e->output, buffer_len(&msg)); 227 buffer_append(&e->output, buffer_ptr(&msg), buffer_len(&msg)); 228 buffer_free(&msg); 229 } 230 231 #ifdef WITH_SSH1 232 /* ssh1 only */ 233 static void 234 process_authentication_challenge1(SocketEntry *e) 235 { 236 u_char buf[32], mdbuf[16], session_id[16]; 237 u_int response_type; 238 BIGNUM *challenge; 239 Identity *id; 240 int i, len; 241 Buffer msg; 242 struct ssh_digest_ctx *md; 243 Key *key; 244 245 buffer_init(&msg); 246 key = key_new(KEY_RSA1); 247 if ((challenge = BN_new()) == NULL) 248 fatal("process_authentication_challenge1: BN_new failed"); 249 250 (void) buffer_get_int(&e->request); /* ignored */ 251 buffer_get_bignum(&e->request, key->rsa->e); 252 buffer_get_bignum(&e->request, key->rsa->n); 253 buffer_get_bignum(&e->request, challenge); 254 255 /* Only protocol 1.1 is supported */ 256 if (buffer_len(&e->request) == 0) 257 goto failure; 258 buffer_get(&e->request, session_id, 16); 259 response_type = buffer_get_int(&e->request); 260 if (response_type != 1) 261 goto failure; 262 263 id = lookup_identity(key, 1); 264 if (id != NULL && (!id->confirm || confirm_key(id) == 0)) { 265 Key *private = id->key; 266 /* Decrypt the challenge using the private key. */ 267 if (rsa_private_decrypt(challenge, challenge, private->rsa) <= 0) 268 goto failure; 269 270 /* The response is MD5 of decrypted challenge plus session id. */ 271 len = BN_num_bytes(challenge); 272 if (len <= 0 || len > 32) { 273 logit("process_authentication_challenge: bad challenge length %d", len); 274 goto failure; 275 } 276 memset(buf, 0, 32); 277 BN_bn2bin(challenge, buf + 32 - len); 278 if ((md = ssh_digest_start(SSH_DIGEST_MD5)) == NULL || 279 ssh_digest_update(md, buf, 32) < 0 || 280 ssh_digest_update(md, session_id, 16) < 0 || 281 ssh_digest_final(md, mdbuf, sizeof(mdbuf)) < 0) 282 fatal("%s: md5 failed", __func__); 283 ssh_digest_free(md); 284 285 /* Send the response. */ 286 buffer_put_char(&msg, SSH_AGENT_RSA_RESPONSE); 287 for (i = 0; i < 16; i++) 288 buffer_put_char(&msg, mdbuf[i]); 289 goto send; 290 } 291 292 failure: 293 /* Unknown identity or protocol error. Send failure. */ 294 buffer_put_char(&msg, SSH_AGENT_FAILURE); 295 send: 296 buffer_put_int(&e->output, buffer_len(&msg)); 297 buffer_append(&e->output, buffer_ptr(&msg), buffer_len(&msg)); 298 key_free(key); 299 BN_clear_free(challenge); 300 buffer_free(&msg); 301 } 302 #endif 303 304 /* ssh2 only */ 305 static void 306 process_sign_request2(SocketEntry *e) 307 { 308 u_char *blob, *data, *signature = NULL; 309 u_int blen, dlen, slen = 0; 310 extern int datafellows; 311 int odatafellows; 312 int ok = -1, flags; 313 Buffer msg; 314 Key *key; 315 316 datafellows = 0; 317 318 blob = buffer_get_string(&e->request, &blen); 319 data = buffer_get_string(&e->request, &dlen); 320 321 flags = buffer_get_int(&e->request); 322 odatafellows = datafellows; 323 if (flags & SSH_AGENT_OLD_SIGNATURE) 324 datafellows = SSH_BUG_SIGBLOB; 325 326 key = key_from_blob(blob, blen); 327 if (key != NULL) { 328 Identity *id = lookup_identity(key, 2); 329 if (id != NULL && (!id->confirm || confirm_key(id) == 0)) 330 ok = key_sign(id->key, &signature, &slen, data, dlen); 331 key_free(key); 332 } 333 buffer_init(&msg); 334 if (ok == 0) { 335 buffer_put_char(&msg, SSH2_AGENT_SIGN_RESPONSE); 336 buffer_put_string(&msg, signature, slen); 337 } else { 338 buffer_put_char(&msg, SSH_AGENT_FAILURE); 339 } 340 buffer_put_int(&e->output, buffer_len(&msg)); 341 buffer_append(&e->output, buffer_ptr(&msg), 342 buffer_len(&msg)); 343 buffer_free(&msg); 344 free(data); 345 free(blob); 346 free(signature); 347 datafellows = odatafellows; 348 } 349 350 /* shared */ 351 static void 352 process_remove_identity(SocketEntry *e, int version) 353 { 354 u_int blen, bits; 355 int success = 0; 356 Key *key = NULL; 357 u_char *blob; 358 359 switch (version) { 360 case 1: 361 key = key_new(KEY_RSA1); 362 bits = buffer_get_int(&e->request); 363 buffer_get_bignum(&e->request, key->rsa->e); 364 buffer_get_bignum(&e->request, key->rsa->n); 365 366 if (bits != key_size(key)) 367 logit("Warning: identity keysize mismatch: actual %u, announced %u", 368 key_size(key), bits); 369 break; 370 case 2: 371 blob = buffer_get_string(&e->request, &blen); 372 key = key_from_blob(blob, blen); 373 free(blob); 374 break; 375 } 376 if (key != NULL) { 377 Identity *id = lookup_identity(key, version); 378 if (id != NULL) { 379 /* 380 * We have this key. Free the old key. Since we 381 * don't want to leave empty slots in the middle of 382 * the array, we actually free the key there and move 383 * all the entries between the empty slot and the end 384 * of the array. 385 */ 386 Idtab *tab = idtab_lookup(version); 387 if (tab->nentries < 1) 388 fatal("process_remove_identity: " 389 "internal error: tab->nentries %d", 390 tab->nentries); 391 TAILQ_REMOVE(&tab->idlist, id, next); 392 free_identity(id); 393 tab->nentries--; 394 success = 1; 395 } 396 key_free(key); 397 } 398 buffer_put_int(&e->output, 1); 399 buffer_put_char(&e->output, 400 success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE); 401 } 402 403 static void 404 process_remove_all_identities(SocketEntry *e, int version) 405 { 406 Idtab *tab = idtab_lookup(version); 407 Identity *id; 408 409 /* Loop over all identities and clear the keys. */ 410 for (id = TAILQ_FIRST(&tab->idlist); id; 411 id = TAILQ_FIRST(&tab->idlist)) { 412 TAILQ_REMOVE(&tab->idlist, id, next); 413 free_identity(id); 414 } 415 416 /* Mark that there are no identities. */ 417 tab->nentries = 0; 418 419 /* Send success. */ 420 buffer_put_int(&e->output, 1); 421 buffer_put_char(&e->output, SSH_AGENT_SUCCESS); 422 } 423 424 /* removes expired keys and returns number of seconds until the next expiry */ 425 static time_t 426 reaper(void) 427 { 428 time_t deadline = 0, now = monotime(); 429 Identity *id, *nxt; 430 int version; 431 Idtab *tab; 432 433 for (version = 1; version < 3; version++) { 434 tab = idtab_lookup(version); 435 for (id = TAILQ_FIRST(&tab->idlist); id; id = nxt) { 436 nxt = TAILQ_NEXT(id, next); 437 if (id->death == 0) 438 continue; 439 if (now >= id->death) { 440 debug("expiring key '%s'", id->comment); 441 TAILQ_REMOVE(&tab->idlist, id, next); 442 free_identity(id); 443 tab->nentries--; 444 } else 445 deadline = (deadline == 0) ? id->death : 446 MIN(deadline, id->death); 447 } 448 } 449 if (deadline == 0 || deadline <= now) 450 return 0; 451 else 452 return (deadline - now); 453 } 454 455 static void 456 process_add_identity(SocketEntry *e, int version) 457 { 458 Idtab *tab = idtab_lookup(version); 459 Identity *id; 460 int type, success = 0, confirm = 0; 461 char *comment; 462 time_t death = 0; 463 Key *k = NULL; 464 465 switch (version) { 466 case 1: 467 k = key_new_private(KEY_RSA1); 468 (void) buffer_get_int(&e->request); /* ignored */ 469 buffer_get_bignum(&e->request, k->rsa->n); 470 buffer_get_bignum(&e->request, k->rsa->e); 471 buffer_get_bignum(&e->request, k->rsa->d); 472 buffer_get_bignum(&e->request, k->rsa->iqmp); 473 474 /* SSH and SSL have p and q swapped */ 475 buffer_get_bignum(&e->request, k->rsa->q); /* p */ 476 buffer_get_bignum(&e->request, k->rsa->p); /* q */ 477 478 /* Generate additional parameters */ 479 rsa_generate_additional_parameters(k->rsa); 480 481 /* enable blinding */ 482 if (RSA_blinding_on(k->rsa, NULL) != 1) { 483 error("process_add_identity: RSA_blinding_on failed"); 484 key_free(k); 485 goto send; 486 } 487 break; 488 case 2: 489 k = key_private_deserialize(&e->request); 490 if (k == NULL) { 491 buffer_clear(&e->request); 492 goto send; 493 } 494 break; 495 } 496 comment = buffer_get_string(&e->request, NULL); 497 if (k == NULL) { 498 free(comment); 499 goto send; 500 } 501 while (buffer_len(&e->request)) { 502 switch ((type = buffer_get_char(&e->request))) { 503 case SSH_AGENT_CONSTRAIN_LIFETIME: 504 death = monotime() + buffer_get_int(&e->request); 505 break; 506 case SSH_AGENT_CONSTRAIN_CONFIRM: 507 confirm = 1; 508 break; 509 default: 510 error("process_add_identity: " 511 "Unknown constraint type %d", type); 512 free(comment); 513 key_free(k); 514 goto send; 515 } 516 } 517 success = 1; 518 if (lifetime && !death) 519 death = monotime() + lifetime; 520 if ((id = lookup_identity(k, version)) == NULL) { 521 id = xcalloc(1, sizeof(Identity)); 522 id->key = k; 523 TAILQ_INSERT_TAIL(&tab->idlist, id, next); 524 /* Increment the number of identities. */ 525 tab->nentries++; 526 } else { 527 key_free(k); 528 free(id->comment); 529 } 530 id->comment = comment; 531 id->death = death; 532 id->confirm = confirm; 533 send: 534 buffer_put_int(&e->output, 1); 535 buffer_put_char(&e->output, 536 success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE); 537 } 538 539 /* XXX todo: encrypt sensitive data with passphrase */ 540 static void 541 process_lock_agent(SocketEntry *e, int lock) 542 { 543 int success = 0; 544 char *passwd; 545 546 passwd = buffer_get_string(&e->request, NULL); 547 if (locked && !lock && strcmp(passwd, lock_passwd) == 0) { 548 locked = 0; 549 explicit_bzero(lock_passwd, strlen(lock_passwd)); 550 free(lock_passwd); 551 lock_passwd = NULL; 552 success = 1; 553 } else if (!locked && lock) { 554 locked = 1; 555 lock_passwd = xstrdup(passwd); 556 success = 1; 557 } 558 explicit_bzero(passwd, strlen(passwd)); 559 free(passwd); 560 561 buffer_put_int(&e->output, 1); 562 buffer_put_char(&e->output, 563 success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE); 564 } 565 566 static void 567 no_identities(SocketEntry *e, u_int type) 568 { 569 Buffer msg; 570 571 buffer_init(&msg); 572 buffer_put_char(&msg, 573 (type == SSH_AGENTC_REQUEST_RSA_IDENTITIES) ? 574 SSH_AGENT_RSA_IDENTITIES_ANSWER : SSH2_AGENT_IDENTITIES_ANSWER); 575 buffer_put_int(&msg, 0); 576 buffer_put_int(&e->output, buffer_len(&msg)); 577 buffer_append(&e->output, buffer_ptr(&msg), buffer_len(&msg)); 578 buffer_free(&msg); 579 } 580 581 #ifdef ENABLE_PKCS11 582 static void 583 process_add_smartcard_key(SocketEntry *e) 584 { 585 char *provider = NULL, *pin; 586 int i, type, version, count = 0, success = 0, confirm = 0; 587 time_t death = 0; 588 Key **keys = NULL, *k; 589 Identity *id; 590 Idtab *tab; 591 592 provider = buffer_get_string(&e->request, NULL); 593 pin = buffer_get_string(&e->request, NULL); 594 595 while (buffer_len(&e->request)) { 596 switch ((type = buffer_get_char(&e->request))) { 597 case SSH_AGENT_CONSTRAIN_LIFETIME: 598 death = monotime() + buffer_get_int(&e->request); 599 break; 600 case SSH_AGENT_CONSTRAIN_CONFIRM: 601 confirm = 1; 602 break; 603 default: 604 error("process_add_smartcard_key: " 605 "Unknown constraint type %d", type); 606 goto send; 607 } 608 } 609 if (lifetime && !death) 610 death = monotime() + lifetime; 611 612 count = pkcs11_add_provider(provider, pin, &keys); 613 for (i = 0; i < count; i++) { 614 k = keys[i]; 615 version = k->type == KEY_RSA1 ? 1 : 2; 616 tab = idtab_lookup(version); 617 if (lookup_identity(k, version) == NULL) { 618 id = xcalloc(1, sizeof(Identity)); 619 id->key = k; 620 id->provider = xstrdup(provider); 621 id->comment = xstrdup(provider); /* XXX */ 622 id->death = death; 623 id->confirm = confirm; 624 TAILQ_INSERT_TAIL(&tab->idlist, id, next); 625 tab->nentries++; 626 success = 1; 627 } else { 628 key_free(k); 629 } 630 keys[i] = NULL; 631 } 632 send: 633 free(pin); 634 free(provider); 635 free(keys); 636 buffer_put_int(&e->output, 1); 637 buffer_put_char(&e->output, 638 success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE); 639 } 640 641 static void 642 process_remove_smartcard_key(SocketEntry *e) 643 { 644 char *provider = NULL, *pin = NULL; 645 int version, success = 0; 646 Identity *id, *nxt; 647 Idtab *tab; 648 649 provider = buffer_get_string(&e->request, NULL); 650 pin = buffer_get_string(&e->request, NULL); 651 free(pin); 652 653 for (version = 1; version < 3; version++) { 654 tab = idtab_lookup(version); 655 for (id = TAILQ_FIRST(&tab->idlist); id; id = nxt) { 656 nxt = TAILQ_NEXT(id, next); 657 /* Skip file--based keys */ 658 if (id->provider == NULL) 659 continue; 660 if (!strcmp(provider, id->provider)) { 661 TAILQ_REMOVE(&tab->idlist, id, next); 662 free_identity(id); 663 tab->nentries--; 664 } 665 } 666 } 667 if (pkcs11_del_provider(provider) == 0) 668 success = 1; 669 else 670 error("process_remove_smartcard_key:" 671 " pkcs11_del_provider failed"); 672 free(provider); 673 buffer_put_int(&e->output, 1); 674 buffer_put_char(&e->output, 675 success ? SSH_AGENT_SUCCESS : SSH_AGENT_FAILURE); 676 } 677 #endif /* ENABLE_PKCS11 */ 678 679 /* dispatch incoming messages */ 680 681 static void 682 process_message(SocketEntry *e) 683 { 684 u_int msg_len, type; 685 u_char *cp; 686 687 if (buffer_len(&e->input) < 5) 688 return; /* Incomplete message. */ 689 cp = buffer_ptr(&e->input); 690 msg_len = get_u32(cp); 691 if (msg_len > 256 * 1024) { 692 close_socket(e); 693 return; 694 } 695 if (buffer_len(&e->input) < msg_len + 4) 696 return; 697 698 /* move the current input to e->request */ 699 buffer_consume(&e->input, 4); 700 buffer_clear(&e->request); 701 buffer_append(&e->request, buffer_ptr(&e->input), msg_len); 702 buffer_consume(&e->input, msg_len); 703 type = buffer_get_char(&e->request); 704 705 /* check wheter agent is locked */ 706 if (locked && type != SSH_AGENTC_UNLOCK) { 707 buffer_clear(&e->request); 708 switch (type) { 709 case SSH_AGENTC_REQUEST_RSA_IDENTITIES: 710 case SSH2_AGENTC_REQUEST_IDENTITIES: 711 /* send empty lists */ 712 no_identities(e, type); 713 break; 714 default: 715 /* send a fail message for all other request types */ 716 buffer_put_int(&e->output, 1); 717 buffer_put_char(&e->output, SSH_AGENT_FAILURE); 718 } 719 return; 720 } 721 722 debug("type %d", type); 723 switch (type) { 724 case SSH_AGENTC_LOCK: 725 case SSH_AGENTC_UNLOCK: 726 process_lock_agent(e, type == SSH_AGENTC_LOCK); 727 break; 728 #ifdef WITH_SSH1 729 /* ssh1 */ 730 case SSH_AGENTC_RSA_CHALLENGE: 731 process_authentication_challenge1(e); 732 break; 733 case SSH_AGENTC_REQUEST_RSA_IDENTITIES: 734 process_request_identities(e, 1); 735 break; 736 case SSH_AGENTC_ADD_RSA_IDENTITY: 737 case SSH_AGENTC_ADD_RSA_ID_CONSTRAINED: 738 process_add_identity(e, 1); 739 break; 740 case SSH_AGENTC_REMOVE_RSA_IDENTITY: 741 process_remove_identity(e, 1); 742 break; 743 case SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES: 744 process_remove_all_identities(e, 1); 745 break; 746 #endif 747 /* ssh2 */ 748 case SSH2_AGENTC_SIGN_REQUEST: 749 process_sign_request2(e); 750 break; 751 case SSH2_AGENTC_REQUEST_IDENTITIES: 752 process_request_identities(e, 2); 753 break; 754 case SSH2_AGENTC_ADD_IDENTITY: 755 case SSH2_AGENTC_ADD_ID_CONSTRAINED: 756 process_add_identity(e, 2); 757 break; 758 case SSH2_AGENTC_REMOVE_IDENTITY: 759 process_remove_identity(e, 2); 760 break; 761 case SSH2_AGENTC_REMOVE_ALL_IDENTITIES: 762 process_remove_all_identities(e, 2); 763 break; 764 #ifdef ENABLE_PKCS11 765 case SSH_AGENTC_ADD_SMARTCARD_KEY: 766 case SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED: 767 process_add_smartcard_key(e); 768 break; 769 case SSH_AGENTC_REMOVE_SMARTCARD_KEY: 770 process_remove_smartcard_key(e); 771 break; 772 #endif /* ENABLE_PKCS11 */ 773 default: 774 /* Unknown message. Respond with failure. */ 775 error("Unknown message %d", type); 776 buffer_clear(&e->request); 777 buffer_put_int(&e->output, 1); 778 buffer_put_char(&e->output, SSH_AGENT_FAILURE); 779 break; 780 } 781 } 782 783 static void 784 new_socket(sock_type type, int fd) 785 { 786 u_int i, old_alloc, new_alloc; 787 788 set_nonblock(fd); 789 790 if (fd > max_fd) 791 max_fd = fd; 792 793 for (i = 0; i < sockets_alloc; i++) 794 if (sockets[i].type == AUTH_UNUSED) { 795 sockets[i].fd = fd; 796 buffer_init(&sockets[i].input); 797 buffer_init(&sockets[i].output); 798 buffer_init(&sockets[i].request); 799 sockets[i].type = type; 800 return; 801 } 802 old_alloc = sockets_alloc; 803 new_alloc = sockets_alloc + 10; 804 sockets = xrealloc(sockets, new_alloc, sizeof(sockets[0])); 805 for (i = old_alloc; i < new_alloc; i++) 806 sockets[i].type = AUTH_UNUSED; 807 sockets_alloc = new_alloc; 808 sockets[old_alloc].fd = fd; 809 buffer_init(&sockets[old_alloc].input); 810 buffer_init(&sockets[old_alloc].output); 811 buffer_init(&sockets[old_alloc].request); 812 sockets[old_alloc].type = type; 813 } 814 815 static int 816 prepare_select(fd_set **fdrp, fd_set **fdwp, int *fdl, u_int *nallocp, 817 struct timeval **tvpp) 818 { 819 u_int i, sz; 820 int n = 0; 821 static struct timeval tv; 822 time_t deadline; 823 824 for (i = 0; i < sockets_alloc; i++) { 825 switch (sockets[i].type) { 826 case AUTH_SOCKET: 827 case AUTH_CONNECTION: 828 n = MAX(n, sockets[i].fd); 829 break; 830 case AUTH_UNUSED: 831 break; 832 default: 833 fatal("Unknown socket type %d", sockets[i].type); 834 break; 835 } 836 } 837 838 sz = howmany(n+1, NFDBITS) * sizeof(fd_mask); 839 if (*fdrp == NULL || sz > *nallocp) { 840 free(*fdrp); 841 free(*fdwp); 842 *fdrp = xmalloc(sz); 843 *fdwp = xmalloc(sz); 844 *nallocp = sz; 845 } 846 if (n < *fdl) 847 debug("XXX shrink: %d < %d", n, *fdl); 848 *fdl = n; 849 memset(*fdrp, 0, sz); 850 memset(*fdwp, 0, sz); 851 852 for (i = 0; i < sockets_alloc; i++) { 853 switch (sockets[i].type) { 854 case AUTH_SOCKET: 855 case AUTH_CONNECTION: 856 FD_SET(sockets[i].fd, *fdrp); 857 if (buffer_len(&sockets[i].output) > 0) 858 FD_SET(sockets[i].fd, *fdwp); 859 break; 860 default: 861 break; 862 } 863 } 864 deadline = reaper(); 865 if (parent_alive_interval != 0) 866 deadline = (deadline == 0) ? parent_alive_interval : 867 MIN(deadline, parent_alive_interval); 868 if (deadline == 0) { 869 *tvpp = NULL; 870 } else { 871 tv.tv_sec = deadline; 872 tv.tv_usec = 0; 873 *tvpp = &tv; 874 } 875 return (1); 876 } 877 878 static void 879 after_select(fd_set *readset, fd_set *writeset) 880 { 881 struct sockaddr_un sunaddr; 882 socklen_t slen; 883 char buf[1024]; 884 int len, sock; 885 u_int i, orig_alloc; 886 uid_t euid; 887 gid_t egid; 888 889 for (i = 0, orig_alloc = sockets_alloc; i < orig_alloc; i++) 890 switch (sockets[i].type) { 891 case AUTH_UNUSED: 892 break; 893 case AUTH_SOCKET: 894 if (FD_ISSET(sockets[i].fd, readset)) { 895 slen = sizeof(sunaddr); 896 sock = accept(sockets[i].fd, 897 (struct sockaddr *)&sunaddr, &slen); 898 if (sock < 0) { 899 error("accept from AUTH_SOCKET: %s", 900 strerror(errno)); 901 break; 902 } 903 if (getpeereid(sock, &euid, &egid) < 0) { 904 error("getpeereid %d failed: %s", 905 sock, strerror(errno)); 906 close(sock); 907 break; 908 } 909 if ((euid != 0) && (getuid() != euid)) { 910 error("uid mismatch: " 911 "peer euid %u != uid %u", 912 (u_int) euid, (u_int) getuid()); 913 close(sock); 914 break; 915 } 916 new_socket(AUTH_CONNECTION, sock); 917 } 918 break; 919 case AUTH_CONNECTION: 920 if (buffer_len(&sockets[i].output) > 0 && 921 FD_ISSET(sockets[i].fd, writeset)) { 922 len = write(sockets[i].fd, 923 buffer_ptr(&sockets[i].output), 924 buffer_len(&sockets[i].output)); 925 if (len == -1 && (errno == EAGAIN || 926 errno == EINTR)) 927 continue; 928 if (len <= 0) { 929 close_socket(&sockets[i]); 930 break; 931 } 932 buffer_consume(&sockets[i].output, len); 933 } 934 if (FD_ISSET(sockets[i].fd, readset)) { 935 len = read(sockets[i].fd, buf, sizeof(buf)); 936 if (len == -1 && (errno == EAGAIN || 937 errno == EINTR)) 938 continue; 939 if (len <= 0) { 940 close_socket(&sockets[i]); 941 break; 942 } 943 buffer_append(&sockets[i].input, buf, len); 944 process_message(&sockets[i]); 945 } 946 break; 947 default: 948 fatal("Unknown type %d", sockets[i].type); 949 } 950 } 951 952 static void 953 cleanup_socket(void) 954 { 955 if (socket_name[0]) 956 unlink(socket_name); 957 if (socket_dir[0]) 958 rmdir(socket_dir); 959 } 960 961 void 962 cleanup_exit(int i) 963 { 964 cleanup_socket(); 965 _exit(i); 966 } 967 968 /*ARGSUSED*/ 969 static void 970 cleanup_handler(int sig) 971 { 972 cleanup_socket(); 973 #ifdef ENABLE_PKCS11 974 pkcs11_terminate(); 975 #endif 976 _exit(2); 977 } 978 979 static void 980 check_parent_exists(void) 981 { 982 /* 983 * If our parent has exited then getppid() will return (pid_t)1, 984 * so testing for that should be safe. 985 */ 986 if (parent_pid != -1 && getppid() != parent_pid) { 987 /* printf("Parent has died - Authentication agent exiting.\n"); */ 988 cleanup_socket(); 989 _exit(2); 990 } 991 } 992 993 static void 994 usage(void) 995 { 996 fprintf(stderr, 997 "usage: ssh-agent [-c | -s] [-d] [-a bind_address] [-t life]\n" 998 " [command [arg ...]]\n" 999 " ssh-agent [-c | -s] -k\n"); 1000 exit(1); 1001 } 1002 1003 int 1004 main(int ac, char **av) 1005 { 1006 int c_flag = 0, d_flag = 0, k_flag = 0, s_flag = 0; 1007 int sock, fd, ch, result, saved_errno; 1008 u_int nalloc; 1009 char *shell, *format, *pidstr, *agentsocket = NULL; 1010 fd_set *readsetp = NULL, *writesetp = NULL; 1011 struct sockaddr_un sunaddr; 1012 struct rlimit rlim; 1013 extern int optind; 1014 extern char *optarg; 1015 pid_t pid; 1016 char pidstrbuf[1 + 3 * sizeof pid]; 1017 struct timeval *tvp = NULL; 1018 size_t len; 1019 1020 /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ 1021 sanitise_stdfd(); 1022 1023 /* drop */ 1024 setegid(getgid()); 1025 setgid(getgid()); 1026 1027 #ifdef WITH_OPENSSL 1028 OpenSSL_add_all_algorithms(); 1029 #endif 1030 1031 while ((ch = getopt(ac, av, "cdksa:t:")) != -1) { 1032 switch (ch) { 1033 case 'c': 1034 if (s_flag) 1035 usage(); 1036 c_flag++; 1037 break; 1038 case 'k': 1039 k_flag++; 1040 break; 1041 case 's': 1042 if (c_flag) 1043 usage(); 1044 s_flag++; 1045 break; 1046 case 'd': 1047 if (d_flag) 1048 usage(); 1049 d_flag++; 1050 break; 1051 case 'a': 1052 agentsocket = optarg; 1053 break; 1054 case 't': 1055 if ((lifetime = convtime(optarg)) == -1) { 1056 fprintf(stderr, "Invalid lifetime\n"); 1057 usage(); 1058 } 1059 break; 1060 default: 1061 usage(); 1062 } 1063 } 1064 ac -= optind; 1065 av += optind; 1066 1067 if (ac > 0 && (c_flag || k_flag || s_flag || d_flag)) 1068 usage(); 1069 1070 if (ac == 0 && !c_flag && !s_flag) { 1071 shell = getenv("SHELL"); 1072 if (shell != NULL && (len = strlen(shell)) > 2 && 1073 strncmp(shell + len - 3, "csh", 3) == 0) 1074 c_flag = 1; 1075 } 1076 if (k_flag) { 1077 const char *errstr = NULL; 1078 1079 pidstr = getenv(SSH_AGENTPID_ENV_NAME); 1080 if (pidstr == NULL) { 1081 fprintf(stderr, "%s not set, cannot kill agent\n", 1082 SSH_AGENTPID_ENV_NAME); 1083 exit(1); 1084 } 1085 pid = (int)strtonum(pidstr, 2, INT_MAX, &errstr); 1086 if (errstr) { 1087 fprintf(stderr, 1088 "%s=\"%s\", which is not a good PID: %s\n", 1089 SSH_AGENTPID_ENV_NAME, pidstr, errstr); 1090 exit(1); 1091 } 1092 if (kill(pid, SIGTERM) == -1) { 1093 perror("kill"); 1094 exit(1); 1095 } 1096 format = c_flag ? "unsetenv %s;\n" : "unset %s;\n"; 1097 printf(format, SSH_AUTHSOCKET_ENV_NAME); 1098 printf(format, SSH_AGENTPID_ENV_NAME); 1099 printf("echo Agent pid %ld killed;\n", (long)pid); 1100 exit(0); 1101 } 1102 parent_pid = getpid(); 1103 1104 if (agentsocket == NULL) { 1105 /* Create private directory for agent socket */ 1106 mktemp_proto(socket_dir, sizeof(socket_dir)); 1107 if (mkdtemp(socket_dir) == NULL) { 1108 perror("mkdtemp: private socket dir"); 1109 exit(1); 1110 } 1111 snprintf(socket_name, sizeof socket_name, "%s/agent.%ld", socket_dir, 1112 (long)parent_pid); 1113 } else { 1114 /* Try to use specified agent socket */ 1115 socket_dir[0] = '\0'; 1116 strlcpy(socket_name, agentsocket, sizeof socket_name); 1117 } 1118 1119 /* 1120 * Create socket early so it will exist before command gets run from 1121 * the parent. 1122 */ 1123 sock = socket(AF_UNIX, SOCK_STREAM, 0); 1124 if (sock < 0) { 1125 perror("socket"); 1126 *socket_name = '\0'; /* Don't unlink any existing file */ 1127 cleanup_exit(1); 1128 } 1129 memset(&sunaddr, 0, sizeof(sunaddr)); 1130 sunaddr.sun_family = AF_UNIX; 1131 strlcpy(sunaddr.sun_path, socket_name, sizeof(sunaddr.sun_path)); 1132 if (bind(sock, (struct sockaddr *)&sunaddr, sizeof(sunaddr)) < 0) { 1133 perror("bind"); 1134 *socket_name = '\0'; /* Don't unlink any existing file */ 1135 cleanup_exit(1); 1136 } 1137 if (listen(sock, SSH_LISTEN_BACKLOG) < 0) { 1138 perror("listen"); 1139 cleanup_exit(1); 1140 } 1141 1142 /* 1143 * Fork, and have the parent execute the command, if any, or present 1144 * the socket data. The child continues as the authentication agent. 1145 */ 1146 if (d_flag) { 1147 log_init(__progname, SYSLOG_LEVEL_DEBUG1, SYSLOG_FACILITY_AUTH, 1); 1148 format = c_flag ? "setenv %s %s;\n" : "%s=%s; export %s;\n"; 1149 printf(format, SSH_AUTHSOCKET_ENV_NAME, socket_name, 1150 SSH_AUTHSOCKET_ENV_NAME); 1151 printf("echo Agent pid %ld;\n", (long)parent_pid); 1152 goto skip; 1153 } 1154 pid = fork(); 1155 if (pid == -1) { 1156 perror("fork"); 1157 cleanup_exit(1); 1158 } 1159 if (pid != 0) { /* Parent - execute the given command. */ 1160 close(sock); 1161 snprintf(pidstrbuf, sizeof pidstrbuf, "%ld", (long)pid); 1162 if (ac == 0) { 1163 format = c_flag ? "setenv %s %s;\n" : "%s=%s; export %s;\n"; 1164 printf(format, SSH_AUTHSOCKET_ENV_NAME, socket_name, 1165 SSH_AUTHSOCKET_ENV_NAME); 1166 printf(format, SSH_AGENTPID_ENV_NAME, pidstrbuf, 1167 SSH_AGENTPID_ENV_NAME); 1168 printf("echo Agent pid %ld;\n", (long)pid); 1169 exit(0); 1170 } 1171 if (setenv(SSH_AUTHSOCKET_ENV_NAME, socket_name, 1) == -1 || 1172 setenv(SSH_AGENTPID_ENV_NAME, pidstrbuf, 1) == -1) { 1173 perror("setenv"); 1174 exit(1); 1175 } 1176 execvp(av[0], av); 1177 perror(av[0]); 1178 exit(1); 1179 } 1180 /* child */ 1181 log_init(__progname, SYSLOG_LEVEL_INFO, SYSLOG_FACILITY_AUTH, 0); 1182 1183 if (setsid() == -1) { 1184 error("setsid: %s", strerror(errno)); 1185 cleanup_exit(1); 1186 } 1187 1188 (void)chdir("/"); 1189 if ((fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) { 1190 /* XXX might close listen socket */ 1191 (void)dup2(fd, STDIN_FILENO); 1192 (void)dup2(fd, STDOUT_FILENO); 1193 (void)dup2(fd, STDERR_FILENO); 1194 if (fd > 2) 1195 close(fd); 1196 } 1197 1198 /* deny core dumps, since memory contains unencrypted private keys */ 1199 rlim.rlim_cur = rlim.rlim_max = 0; 1200 if (setrlimit(RLIMIT_CORE, &rlim) < 0) { 1201 error("setrlimit RLIMIT_CORE: %s", strerror(errno)); 1202 cleanup_exit(1); 1203 } 1204 1205 skip: 1206 1207 #ifdef ENABLE_PKCS11 1208 pkcs11_init(0); 1209 #endif 1210 new_socket(AUTH_SOCKET, sock); 1211 if (ac > 0) 1212 parent_alive_interval = 10; 1213 idtab_init(); 1214 signal(SIGPIPE, SIG_IGN); 1215 signal(SIGINT, d_flag ? cleanup_handler : SIG_IGN); 1216 signal(SIGHUP, cleanup_handler); 1217 signal(SIGTERM, cleanup_handler); 1218 nalloc = 0; 1219 1220 while (1) { 1221 prepare_select(&readsetp, &writesetp, &max_fd, &nalloc, &tvp); 1222 result = select(max_fd + 1, readsetp, writesetp, NULL, tvp); 1223 saved_errno = errno; 1224 if (parent_alive_interval != 0) 1225 check_parent_exists(); 1226 (void) reaper(); /* remove expired keys */ 1227 if (result < 0) { 1228 if (saved_errno == EINTR) 1229 continue; 1230 fatal("select: %s", strerror(saved_errno)); 1231 } else if (result > 0) 1232 after_select(readsetp, writesetp); 1233 } 1234 /* NOTREACHED */ 1235 } 1236