1/* $OpenBSD: authfd.c,v 1.86 2011/07/06 18:09:21 tedu 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 * Functions for connecting the local authentication agent. 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 * SSH2 implementation, 15 * Copyright (c) 2000 Markus Friedl. All rights reserved. 16 * 17 * Redistribution and use in source and binary forms, with or without 18 * modification, are permitted provided that the following conditions 19 * are met: 20 * 1. Redistributions of source code must retain the above copyright 21 * notice, this list of conditions and the following disclaimer. 22 * 2. Redistributions in binary form must reproduce the above copyright 23 * notice, this list of conditions and the following disclaimer in the 24 * documentation and/or other materials provided with the distribution. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 27 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 28 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 29 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 30 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 31 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 35 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 36 */ 37 38#include "includes.h" 39 40#include <sys/types.h> 41#include <sys/un.h> 42#include <sys/socket.h> 43 44#ifdef __APPLE_CRYPTO__ 45#include "ossl-evp.h" 46#include "ossl-crypto.h" 47#else 48#include <openssl/evp.h> 49 50#include <openssl/crypto.h> 51#endif /* __APPLE_CRYPTO__ */ 52#include <fcntl.h> 53#include <stdlib.h> 54#include <signal.h> 55#include <stdarg.h> 56#include <string.h> 57#include <unistd.h> 58 59#include "xmalloc.h" 60#include "ssh.h" 61#include "rsa.h" 62#include "buffer.h" 63#include "key.h" 64#include "authfd.h" 65#include "cipher.h" 66#include "kex.h" 67#include "compat.h" 68#include "log.h" 69#include "atomicio.h" 70#include "misc.h" 71 72static int agent_present = 0; 73 74/* helper */ 75int decode_reply(int type); 76 77/* macro to check for "agent failure" message */ 78#define agent_failed(x) \ 79 ((x == SSH_AGENT_FAILURE) || (x == SSH_COM_AGENT2_FAILURE) || \ 80 (x == SSH2_AGENT_FAILURE)) 81 82int 83ssh_agent_present(void) 84{ 85 int authfd; 86 87 if (agent_present) 88 return 1; 89 if ((authfd = ssh_get_authentication_socket()) == -1) 90 return 0; 91 else { 92 ssh_close_authentication_socket(authfd); 93 return 1; 94 } 95} 96 97/* Returns the number of the authentication fd, or -1 if there is none. */ 98 99int 100ssh_get_authentication_socket(void) 101{ 102 const char *authsocket; 103 int sock; 104 struct sockaddr_un sunaddr; 105 106 authsocket = getenv(SSH_AUTHSOCKET_ENV_NAME); 107 if (!authsocket) 108 return -1; 109 110 bzero(&sunaddr, sizeof(sunaddr)); 111 sunaddr.sun_family = AF_UNIX; 112 strlcpy(sunaddr.sun_path, authsocket, sizeof(sunaddr.sun_path)); 113 114 sock = socket(AF_UNIX, SOCK_STREAM, 0); 115 if (sock < 0) 116 return -1; 117 118 /* close on exec */ 119 if (fcntl(sock, F_SETFD, FD_CLOEXEC) == -1) { 120 close(sock); 121 return -1; 122 } 123 if (connect(sock, (struct sockaddr *)&sunaddr, sizeof sunaddr) < 0) { 124 close(sock); 125 return -1; 126 } 127 agent_present = 1; 128 return sock; 129} 130 131static int 132ssh_request_reply(AuthenticationConnection *auth, Buffer *request, Buffer *reply) 133{ 134 u_int l, len; 135 char buf[1024]; 136 137 /* Get the length of the message, and format it in the buffer. */ 138 len = buffer_len(request); 139 put_u32(buf, len); 140 141 /* Send the length and then the packet to the agent. */ 142 if (atomicio(vwrite, auth->fd, buf, 4) != 4 || 143 atomicio(vwrite, auth->fd, buffer_ptr(request), 144 buffer_len(request)) != buffer_len(request)) { 145 error("Error writing to authentication socket."); 146 return 0; 147 } 148 /* 149 * Wait for response from the agent. First read the length of the 150 * response packet. 151 */ 152 if (atomicio(read, auth->fd, buf, 4) != 4) { 153 error("Error reading response length from authentication socket."); 154 return 0; 155 } 156 157 /* Extract the length, and check it for sanity. */ 158 len = get_u32(buf); 159 if (len > 256 * 1024) 160 fatal("Authentication response too long: %u", len); 161 162 /* Read the rest of the response in to the buffer. */ 163 buffer_clear(reply); 164 while (len > 0) { 165 l = len; 166 if (l > sizeof(buf)) 167 l = sizeof(buf); 168 if (atomicio(read, auth->fd, buf, l) != l) { 169 error("Error reading response from authentication socket."); 170 return 0; 171 } 172 buffer_append(reply, buf, l); 173 len -= l; 174 } 175 return 1; 176} 177 178/* 179 * Closes the agent socket if it should be closed (depends on how it was 180 * obtained). The argument must have been returned by 181 * ssh_get_authentication_socket(). 182 */ 183 184void 185ssh_close_authentication_socket(int sock) 186{ 187 if (getenv(SSH_AUTHSOCKET_ENV_NAME)) 188 close(sock); 189} 190 191/* 192 * Opens and connects a private socket for communication with the 193 * authentication agent. Returns the file descriptor (which must be 194 * shut down and closed by the caller when no longer needed). 195 * Returns NULL if an error occurred and the connection could not be 196 * opened. 197 */ 198 199AuthenticationConnection * 200ssh_get_authentication_connection(void) 201{ 202 AuthenticationConnection *auth; 203 int sock; 204 205 sock = ssh_get_authentication_socket(); 206 207 /* 208 * Fail if we couldn't obtain a connection. This happens if we 209 * exited due to a timeout. 210 */ 211 if (sock < 0) 212 return NULL; 213 214 auth = xmalloc(sizeof(*auth)); 215 auth->fd = sock; 216 buffer_init(&auth->identities); 217 auth->howmany = 0; 218 219 return auth; 220} 221 222/* 223 * Closes the connection to the authentication agent and frees any associated 224 * memory. 225 */ 226 227void 228ssh_close_authentication_connection(AuthenticationConnection *auth) 229{ 230 buffer_free(&auth->identities); 231 close(auth->fd); 232 xfree(auth); 233} 234 235/* Lock/unlock agent */ 236int 237ssh_lock_agent(AuthenticationConnection *auth, int lock, const char *password) 238{ 239 int type; 240 Buffer msg; 241 242 buffer_init(&msg); 243 buffer_put_char(&msg, lock ? SSH_AGENTC_LOCK : SSH_AGENTC_UNLOCK); 244 buffer_put_cstring(&msg, password); 245 246 if (ssh_request_reply(auth, &msg, &msg) == 0) { 247 buffer_free(&msg); 248 return 0; 249 } 250 type = buffer_get_char(&msg); 251 buffer_free(&msg); 252 return decode_reply(type); 253} 254 255/* 256 * Returns the first authentication identity held by the agent. 257 */ 258 259int 260ssh_get_num_identities(AuthenticationConnection *auth, int version) 261{ 262 int type, code1 = 0, code2 = 0; 263 Buffer request; 264 265 switch (version) { 266 case 1: 267 code1 = SSH_AGENTC_REQUEST_RSA_IDENTITIES; 268 code2 = SSH_AGENT_RSA_IDENTITIES_ANSWER; 269 break; 270 case 2: 271 code1 = SSH2_AGENTC_REQUEST_IDENTITIES; 272 code2 = SSH2_AGENT_IDENTITIES_ANSWER; 273 break; 274 default: 275 return 0; 276 } 277 278 /* 279 * Send a message to the agent requesting for a list of the 280 * identities it can represent. 281 */ 282 buffer_init(&request); 283 buffer_put_char(&request, code1); 284 285 buffer_clear(&auth->identities); 286 if (ssh_request_reply(auth, &request, &auth->identities) == 0) { 287 buffer_free(&request); 288 return 0; 289 } 290 buffer_free(&request); 291 292 /* Get message type, and verify that we got a proper answer. */ 293 type = buffer_get_char(&auth->identities); 294 if (agent_failed(type)) { 295 return 0; 296 } else if (type != code2) { 297 fatal("Bad authentication reply message type: %d", type); 298 } 299 300 /* Get the number of entries in the response and check it for sanity. */ 301 auth->howmany = buffer_get_int(&auth->identities); 302 if ((u_int)auth->howmany > 1024) 303 fatal("Too many identities in authentication reply: %d", 304 auth->howmany); 305 306 return auth->howmany; 307} 308 309Key * 310ssh_get_first_identity(AuthenticationConnection *auth, char **comment, int version) 311{ 312 /* get number of identities and return the first entry (if any). */ 313 if (ssh_get_num_identities(auth, version) > 0) 314 return ssh_get_next_identity(auth, comment, version); 315 return NULL; 316} 317 318Key * 319ssh_get_next_identity(AuthenticationConnection *auth, char **comment, int version) 320{ 321 int keybits; 322 u_int bits; 323 u_char *blob; 324 u_int blen; 325 Key *key = NULL; 326 327 /* Return failure if no more entries. */ 328 if (auth->howmany <= 0) 329 return NULL; 330 331 /* 332 * Get the next entry from the packet. These will abort with a fatal 333 * error if the packet is too short or contains corrupt data. 334 */ 335 switch (version) { 336 case 1: 337 key = key_new(KEY_RSA1); 338 bits = buffer_get_int(&auth->identities); 339 buffer_get_bignum(&auth->identities, key->rsa->e); 340 buffer_get_bignum(&auth->identities, key->rsa->n); 341 *comment = buffer_get_string(&auth->identities, NULL); 342 keybits = BN_num_bits(key->rsa->n); 343 if (keybits < 0 || bits != (u_int)keybits) 344 logit("Warning: identity keysize mismatch: actual %d, announced %u", 345 BN_num_bits(key->rsa->n), bits); 346 break; 347 case 2: 348 blob = buffer_get_string(&auth->identities, &blen); 349 *comment = buffer_get_string(&auth->identities, NULL); 350 key = key_from_blob(blob, blen); 351 xfree(blob); 352 break; 353 default: 354 return NULL; 355 } 356 /* Decrement the number of remaining entries. */ 357 auth->howmany--; 358 return key; 359} 360 361/* 362 * Generates a random challenge, sends it to the agent, and waits for 363 * response from the agent. Returns true (non-zero) if the agent gave the 364 * correct answer, zero otherwise. Response type selects the style of 365 * response desired, with 0 corresponding to protocol version 1.0 (no longer 366 * supported) and 1 corresponding to protocol version 1.1. 367 */ 368 369int 370ssh_decrypt_challenge(AuthenticationConnection *auth, 371 Key* key, BIGNUM *challenge, 372 u_char session_id[16], 373 u_int response_type, 374 u_char response[16]) 375{ 376 Buffer buffer; 377 int success = 0; 378 int i; 379 int type; 380 381 if (key->type != KEY_RSA1) 382 return 0; 383 if (response_type == 0) { 384 logit("Compatibility with ssh protocol version 1.0 no longer supported."); 385 return 0; 386 } 387 buffer_init(&buffer); 388 buffer_put_char(&buffer, SSH_AGENTC_RSA_CHALLENGE); 389 buffer_put_int(&buffer, BN_num_bits(key->rsa->n)); 390 buffer_put_bignum(&buffer, key->rsa->e); 391 buffer_put_bignum(&buffer, key->rsa->n); 392 buffer_put_bignum(&buffer, challenge); 393 buffer_append(&buffer, session_id, 16); 394 buffer_put_int(&buffer, response_type); 395 396 if (ssh_request_reply(auth, &buffer, &buffer) == 0) { 397 buffer_free(&buffer); 398 return 0; 399 } 400 type = buffer_get_char(&buffer); 401 402 if (agent_failed(type)) { 403 logit("Agent admitted failure to authenticate using the key."); 404 } else if (type != SSH_AGENT_RSA_RESPONSE) { 405 fatal("Bad authentication response: %d", type); 406 } else { 407 success = 1; 408 /* 409 * Get the response from the packet. This will abort with a 410 * fatal error if the packet is corrupt. 411 */ 412 for (i = 0; i < 16; i++) 413 response[i] = (u_char)buffer_get_char(&buffer); 414 } 415 buffer_free(&buffer); 416 return success; 417} 418 419/* ask agent to sign data, returns -1 on error, 0 on success */ 420int 421ssh_agent_sign(AuthenticationConnection *auth, 422 Key *key, 423 u_char **sigp, u_int *lenp, 424 u_char *data, u_int datalen) 425{ 426 extern int datafellows; 427 Buffer msg; 428 u_char *blob; 429 u_int blen; 430 int type, flags = 0; 431 int ret = -1; 432 433 if (key_to_blob(key, &blob, &blen) == 0) 434 return -1; 435 436 if (datafellows & SSH_BUG_SIGBLOB) 437 flags = SSH_AGENT_OLD_SIGNATURE; 438 439 buffer_init(&msg); 440 buffer_put_char(&msg, SSH2_AGENTC_SIGN_REQUEST); 441 buffer_put_string(&msg, blob, blen); 442 buffer_put_string(&msg, data, datalen); 443 buffer_put_int(&msg, flags); 444 xfree(blob); 445 446 if (ssh_request_reply(auth, &msg, &msg) == 0) { 447 buffer_free(&msg); 448 return -1; 449 } 450 type = buffer_get_char(&msg); 451 if (agent_failed(type)) { 452 logit("Agent admitted failure to sign using the key."); 453 } else if (type != SSH2_AGENT_SIGN_RESPONSE) { 454 fatal("Bad authentication response: %d", type); 455 } else { 456 ret = 0; 457 *sigp = buffer_get_string(&msg, lenp); 458 } 459 buffer_free(&msg); 460 return ret; 461} 462 463/* Encode key for a message to the agent. */ 464 465static void 466ssh_encode_identity_rsa1(Buffer *b, RSA *key, const char *comment) 467{ 468 buffer_put_int(b, BN_num_bits(key->n)); 469 buffer_put_bignum(b, key->n); 470 buffer_put_bignum(b, key->e); 471 buffer_put_bignum(b, key->d); 472 /* To keep within the protocol: p < q for ssh. in SSL p > q */ 473 buffer_put_bignum(b, key->iqmp); /* ssh key->u */ 474 buffer_put_bignum(b, key->q); /* ssh key->p, SSL key->q */ 475 buffer_put_bignum(b, key->p); /* ssh key->q, SSL key->p */ 476 buffer_put_cstring(b, comment); 477} 478 479static void 480ssh_encode_identity_ssh2(Buffer *b, Key *key, const char *comment) 481{ 482 buffer_put_cstring(b, key_ssh_name(key)); 483 switch (key->type) { 484 case KEY_RSA: 485 buffer_put_bignum2(b, key->rsa->n); 486 buffer_put_bignum2(b, key->rsa->e); 487 buffer_put_bignum2(b, key->rsa->d); 488 buffer_put_bignum2(b, key->rsa->iqmp); 489 buffer_put_bignum2(b, key->rsa->p); 490 buffer_put_bignum2(b, key->rsa->q); 491 break; 492 case KEY_RSA_CERT_V00: 493 case KEY_RSA_CERT: 494 if (key->cert == NULL || buffer_len(&key->cert->certblob) == 0) 495 fatal("%s: no cert/certblob", __func__); 496 buffer_put_string(b, buffer_ptr(&key->cert->certblob), 497 buffer_len(&key->cert->certblob)); 498 buffer_put_bignum2(b, key->rsa->d); 499 buffer_put_bignum2(b, key->rsa->iqmp); 500 buffer_put_bignum2(b, key->rsa->p); 501 buffer_put_bignum2(b, key->rsa->q); 502 break; 503 case KEY_DSA: 504 buffer_put_bignum2(b, key->dsa->p); 505 buffer_put_bignum2(b, key->dsa->q); 506 buffer_put_bignum2(b, key->dsa->g); 507 buffer_put_bignum2(b, key->dsa->pub_key); 508 buffer_put_bignum2(b, key->dsa->priv_key); 509 break; 510 case KEY_DSA_CERT_V00: 511 case KEY_DSA_CERT: 512 if (key->cert == NULL || buffer_len(&key->cert->certblob) == 0) 513 fatal("%s: no cert/certblob", __func__); 514 buffer_put_string(b, buffer_ptr(&key->cert->certblob), 515 buffer_len(&key->cert->certblob)); 516 buffer_put_bignum2(b, key->dsa->priv_key); 517 break; 518#ifdef OPENSSL_HAS_ECC 519 case KEY_ECDSA: 520 buffer_put_cstring(b, key_curve_nid_to_name(key->ecdsa_nid)); 521 buffer_put_ecpoint(b, EC_KEY_get0_group(key->ecdsa), 522 EC_KEY_get0_public_key(key->ecdsa)); 523 buffer_put_bignum2(b, EC_KEY_get0_private_key(key->ecdsa)); 524 break; 525 case KEY_ECDSA_CERT: 526 if (key->cert == NULL || buffer_len(&key->cert->certblob) == 0) 527 fatal("%s: no cert/certblob", __func__); 528 buffer_put_string(b, buffer_ptr(&key->cert->certblob), 529 buffer_len(&key->cert->certblob)); 530 buffer_put_bignum2(b, EC_KEY_get0_private_key(key->ecdsa)); 531 break; 532#endif 533 } 534 buffer_put_cstring(b, comment); 535} 536 537/* 538 * Adds an identity to the authentication server. This call is not meant to 539 * be used by normal applications. 540 */ 541 542int 543ssh_add_identity_constrained(AuthenticationConnection *auth, Key *key, 544 const char *comment, u_int life, u_int confirm) 545{ 546 Buffer msg; 547 int type, constrained = (life || confirm); 548 549 buffer_init(&msg); 550 551 switch (key->type) { 552 case KEY_RSA1: 553 type = constrained ? 554 SSH_AGENTC_ADD_RSA_ID_CONSTRAINED : 555 SSH_AGENTC_ADD_RSA_IDENTITY; 556 buffer_put_char(&msg, type); 557 ssh_encode_identity_rsa1(&msg, key->rsa, comment); 558 break; 559 case KEY_RSA: 560 case KEY_RSA_CERT: 561 case KEY_RSA_CERT_V00: 562 case KEY_DSA: 563 case KEY_DSA_CERT: 564 case KEY_DSA_CERT_V00: 565 case KEY_ECDSA: 566 case KEY_ECDSA_CERT: 567 type = constrained ? 568 SSH2_AGENTC_ADD_ID_CONSTRAINED : 569 SSH2_AGENTC_ADD_IDENTITY; 570 buffer_put_char(&msg, type); 571 ssh_encode_identity_ssh2(&msg, key, comment); 572 break; 573 default: 574 buffer_free(&msg); 575 return 0; 576 } 577 if (constrained) { 578 if (life != 0) { 579 buffer_put_char(&msg, SSH_AGENT_CONSTRAIN_LIFETIME); 580 buffer_put_int(&msg, life); 581 } 582 if (confirm != 0) 583 buffer_put_char(&msg, SSH_AGENT_CONSTRAIN_CONFIRM); 584 } 585 if (ssh_request_reply(auth, &msg, &msg) == 0) { 586 buffer_free(&msg); 587 return 0; 588 } 589 type = buffer_get_char(&msg); 590 buffer_free(&msg); 591 return decode_reply(type); 592} 593 594/* 595 * Removes an identity from the authentication server. This call is not 596 * meant to be used by normal applications. 597 */ 598 599int 600ssh_remove_identity(AuthenticationConnection *auth, Key *key) 601{ 602 Buffer msg; 603 int type; 604 u_char *blob; 605 u_int blen; 606 607 buffer_init(&msg); 608 609 if (key->type == KEY_RSA1) { 610 buffer_put_char(&msg, SSH_AGENTC_REMOVE_RSA_IDENTITY); 611 buffer_put_int(&msg, BN_num_bits(key->rsa->n)); 612 buffer_put_bignum(&msg, key->rsa->e); 613 buffer_put_bignum(&msg, key->rsa->n); 614 } else if (key_type_plain(key->type) == KEY_DSA || 615 key_type_plain(key->type) == KEY_RSA || 616 key_type_plain(key->type) == KEY_ECDSA) { 617 key_to_blob(key, &blob, &blen); 618 buffer_put_char(&msg, SSH2_AGENTC_REMOVE_IDENTITY); 619 buffer_put_string(&msg, blob, blen); 620 xfree(blob); 621 } else { 622 buffer_free(&msg); 623 return 0; 624 } 625 if (ssh_request_reply(auth, &msg, &msg) == 0) { 626 buffer_free(&msg); 627 return 0; 628 } 629 type = buffer_get_char(&msg); 630 buffer_free(&msg); 631 return decode_reply(type); 632} 633 634int 635ssh_update_card(AuthenticationConnection *auth, int add, 636 const char *reader_id, const char *pin, u_int life, u_int confirm) 637{ 638 Buffer msg; 639 int type, constrained = (life || confirm); 640 641 if (add) { 642 type = constrained ? 643 SSH_AGENTC_ADD_SMARTCARD_KEY_CONSTRAINED : 644 SSH_AGENTC_ADD_SMARTCARD_KEY; 645 } else 646 type = SSH_AGENTC_REMOVE_SMARTCARD_KEY; 647 648 buffer_init(&msg); 649 buffer_put_char(&msg, type); 650 buffer_put_cstring(&msg, reader_id); 651 buffer_put_cstring(&msg, pin); 652 653 if (constrained) { 654 if (life != 0) { 655 buffer_put_char(&msg, SSH_AGENT_CONSTRAIN_LIFETIME); 656 buffer_put_int(&msg, life); 657 } 658 if (confirm != 0) 659 buffer_put_char(&msg, SSH_AGENT_CONSTRAIN_CONFIRM); 660 } 661 662 if (ssh_request_reply(auth, &msg, &msg) == 0) { 663 buffer_free(&msg); 664 return 0; 665 } 666 type = buffer_get_char(&msg); 667 buffer_free(&msg); 668 return decode_reply(type); 669} 670 671/* 672 * Removes all identities from the agent. This call is not meant to be used 673 * by normal applications. 674 */ 675 676int 677ssh_remove_all_identities(AuthenticationConnection *auth, int version) 678{ 679 Buffer msg; 680 int type; 681 int code = (version==1) ? 682 SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES : 683 SSH2_AGENTC_REMOVE_ALL_IDENTITIES; 684 685 buffer_init(&msg); 686 buffer_put_char(&msg, code); 687 688 if (ssh_request_reply(auth, &msg, &msg) == 0) { 689 buffer_free(&msg); 690 return 0; 691 } 692 type = buffer_get_char(&msg); 693 buffer_free(&msg); 694 return decode_reply(type); 695} 696 697/* 698 * Adds identities using passphrases stored in the keychain. This call is not 699 * meant to be used by normal applications. 700 */ 701 702int 703ssh_add_from_keychain(AuthenticationConnection *auth) 704{ 705 Buffer msg; 706 int type; 707 708 buffer_init(&msg); 709 buffer_put_char(&msg, SSH_AGENTC_ADD_FROM_KEYCHAIN); 710 711 if (ssh_request_reply(auth, &msg, &msg) == 0) { 712 buffer_free(&msg); 713 return 0; 714 } 715 type = buffer_get_char(&msg); 716 buffer_free(&msg); 717 return decode_reply(type); 718} 719 720int 721decode_reply(int type) 722{ 723 switch (type) { 724 case SSH_AGENT_FAILURE: 725 case SSH_COM_AGENT2_FAILURE: 726 case SSH2_AGENT_FAILURE: 727 logit("SSH_AGENT_FAILURE"); 728 return 0; 729 case SSH_AGENT_SUCCESS: 730 return 1; 731 default: 732 fatal("Bad response from authentication agent: %d", type); 733 } 734 /* NOTREACHED */ 735 return 0; 736} 737