[BACK]Return to authfd.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / ssh

Diff for /src/usr.bin/ssh/authfd.c between version 1.19 and 1.19.2.2

version 1.19, 2000/04/29 18:11:52 version 1.19.2.2, 2000/11/08 21:30:25
Line 1 
Line 1 
 /*  /*
  *  
  * authfd.c  
  *  
  * Author: Tatu Ylonen <ylo@cs.hut.fi>   * Author: Tatu Ylonen <ylo@cs.hut.fi>
  *  
  * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland   * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
  *                    All rights reserved   *                    All rights reserved
    * Functions for connecting the local authentication agent.
  *   *
  * Created: Wed Mar 29 01:30:28 1995 ylo   * As far as I am concerned, the code I have written for this software
    * can be used freely for any purpose.  Any derived versions of this
    * software must be clearly marked as such, and if the derived work is
    * incompatible with the protocol description in the RFC file, it must be
    * called by a name other than "ssh" or "Secure Shell".
  *   *
  * Functions for connecting the local authentication agent.   * SSH2 implementation,
    * Copyright (c) 2000 Markus Friedl.  All rights reserved.
  *   *
    * Redistribution and use in source and binary forms, with or without
    * modification, are permitted provided that the following conditions
    * are met:
    * 1. Redistributions of source code must retain the above copyright
    *    notice, this list of conditions and the following disclaimer.
    * 2. Redistributions in binary form must reproduce the above copyright
    *    notice, this list of conditions and the following disclaimer in the
    *    documentation and/or other materials provided with the distribution.
    *
    * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
    * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
    * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
    * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
    * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
    * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
    * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */   */
   
 #include "includes.h"  #include "includes.h"
 RCSID("$Id$");  RCSID("$OpenBSD$");
   
 #include "ssh.h"  #include "ssh.h"
 #include "rsa.h"  #include "rsa.h"
 #include "authfd.h"  
 #include "buffer.h"  #include "buffer.h"
 #include "bufaux.h"  #include "bufaux.h"
 #include "xmalloc.h"  #include "xmalloc.h"
 #include "getput.h"  #include "getput.h"
   
 #include <openssl/rsa.h>  #include <openssl/rsa.h>
   #include <openssl/dsa.h>
   #include <openssl/evp.h>
   #include "key.h"
   #include "authfd.h"
   #include "kex.h"
   #include "dsa.h"
   #include "compat.h"
   
   /* helper */
   int     decode_reply(int type);
   
   /* macro to check for "agent failure" message */
   #define agent_failed(x) \
       ((x == SSH_AGENT_FAILURE) || (x == SSH_COM_AGENT2_FAILURE))
   
 /* Returns the number of the authentication fd, or -1 if there is none. */  /* Returns the number of the authentication fd, or -1 if there is none. */
   
 int  int
 ssh_get_authentication_socket()  ssh_get_authentication_socket()
 {  {
         const char *authsocket;          const char *authsocket;
         int sock;          int sock, len;
         struct sockaddr_un sunaddr;          struct sockaddr_un sunaddr;
   
         authsocket = getenv(SSH_AUTHSOCKET_ENV_NAME);          authsocket = getenv(SSH_AUTHSOCKET_ENV_NAME);
Line 41 
Line 75 
   
         sunaddr.sun_family = AF_UNIX;          sunaddr.sun_family = AF_UNIX;
         strlcpy(sunaddr.sun_path, authsocket, sizeof(sunaddr.sun_path));          strlcpy(sunaddr.sun_path, authsocket, sizeof(sunaddr.sun_path));
           sunaddr.sun_len = len = SUN_LEN(&sunaddr)+1;
   
         sock = socket(AF_UNIX, SOCK_STREAM, 0);          sock = socket(AF_UNIX, SOCK_STREAM, 0);
         if (sock < 0)          if (sock < 0)
Line 51 
Line 86 
                 close(sock);                  close(sock);
                 return -1;                  return -1;
         }          }
         if (connect(sock, (struct sockaddr *) & sunaddr, sizeof(sunaddr)) < 0) {          if (connect(sock, (struct sockaddr *) & sunaddr, len) < 0) {
                 close(sock);                  close(sock);
                 return -1;                  return -1;
         }          }
         return sock;          return sock;
 }  }
   
   int
   ssh_request_reply(AuthenticationConnection *auth, Buffer *request, Buffer *reply)
   {
           int l, len;
           char buf[1024];
   
           /* Get the length of the message, and format it in the buffer. */
           len = buffer_len(request);
           PUT_32BIT(buf, len);
   
           /* Send the length and then the packet to the agent. */
           if (atomicio(write, auth->fd, buf, 4) != 4 ||
               atomicio(write, auth->fd, buffer_ptr(request),
               buffer_len(request)) != buffer_len(request)) {
                   error("Error writing to authentication socket.");
                   return 0;
           }
           /*
            * Wait for response from the agent.  First read the length of the
            * response packet.
            */
           len = 4;
           while (len > 0) {
                   l = read(auth->fd, buf + 4 - len, len);
                   if (l <= 0) {
                           error("Error reading response length from authentication socket.");
                           return 0;
                   }
                   len -= l;
           }
   
           /* Extract the length, and check it for sanity. */
           len = GET_32BIT(buf);
           if (len > 256 * 1024)
                   fatal("Authentication response too long: %d", len);
   
           /* Read the rest of the response in to the buffer. */
           buffer_clear(reply);
           while (len > 0) {
                   l = len;
                   if (l > sizeof(buf))
                           l = sizeof(buf);
                   l = read(auth->fd, buf, l);
                   if (l <= 0) {
                           error("Error reading response from authentication socket.");
                           return 0;
                   }
                   buffer_append(reply, (char *) buf, l);
                   len -= l;
           }
           return 1;
   }
   
 /*  /*
  * Closes the agent socket if it should be closed (depends on how it was   * Closes the agent socket if it should be closed (depends on how it was
  * obtained).  The argument must have been returned by   * obtained).  The argument must have been returned by
Line 96 
Line 184 
   
         auth = xmalloc(sizeof(*auth));          auth = xmalloc(sizeof(*auth));
         auth->fd = sock;          auth->fd = sock;
         buffer_init(&auth->packet);  
         buffer_init(&auth->identities);          buffer_init(&auth->identities);
         auth->howmany = 0;          auth->howmany = 0;
   
Line 109 
Line 196 
  */   */
   
 void  void
 ssh_close_authentication_connection(AuthenticationConnection *ac)  ssh_close_authentication_connection(AuthenticationConnection *auth)
 {  {
         buffer_free(&ac->packet);          buffer_free(&auth->identities);
         buffer_free(&ac->identities);          close(auth->fd);
         close(ac->fd);          xfree(auth);
         xfree(ac);  
 }  }
   
 /*  /*
  * Returns the first authentication identity held by the agent.   * Returns the first authentication identity held by the agent.
  * Returns true if an identity is available, 0 otherwise.  
  * The caller must initialize the integers before the call, and free the  
  * comment after a successful call (before calling ssh_get_next_identity).  
  */   */
   
 int  Key *
 ssh_get_first_identity(AuthenticationConnection *auth,  ssh_get_first_identity(AuthenticationConnection *auth, char **comment, int version)
                        BIGNUM *e, BIGNUM *n, char **comment)  
 {  {
         unsigned char msg[8192];          int type, code1 = 0, code2 = 0;
         int len, l;          Buffer request;
   
           switch(version){
           case 1:
                   code1 = SSH_AGENTC_REQUEST_RSA_IDENTITIES;
                   code2 = SSH_AGENT_RSA_IDENTITIES_ANSWER;
                   break;
           case 2:
                   code1 = SSH2_AGENTC_REQUEST_IDENTITIES;
                   code2 = SSH2_AGENT_IDENTITIES_ANSWER;
                   break;
           default:
                   return NULL;
           }
   
         /*          /*
          * Send a message to the agent requesting for a list of the           * Send a message to the agent requesting for a list of the
          * identities it can represent.           * identities it can represent.
          */           */
         msg[0] = 0;          buffer_init(&request);
         msg[1] = 0;          buffer_put_char(&request, code1);
         msg[2] = 0;  
         msg[3] = 1;  
         msg[4] = SSH_AGENTC_REQUEST_RSA_IDENTITIES;  
         if (atomicio(write, auth->fd, msg, 5) != 5) {  
                 error("write auth->fd: %.100s", strerror(errno));  
                 return 0;  
         }  
         /* Read the length of the response.  XXX implement timeouts here. */  
         len = 4;  
         while (len > 0) {  
                 l = read(auth->fd, msg + 4 - len, len);  
                 if (l <= 0) {  
                         error("read auth->fd: %.100s", strerror(errno));  
                         return 0;  
                 }  
                 len -= l;  
         }  
   
         /*  
          * Extract the length, and check it for sanity.  (We cannot trust  
          * authentication agents).  
          */  
         len = GET_32BIT(msg);  
         if (len < 1 || len > 256 * 1024)  
                 fatal("Authentication reply message too long: %d\n", len);  
   
         /* Read the packet itself. */  
         buffer_clear(&auth->identities);          buffer_clear(&auth->identities);
         while (len > 0) {          if (ssh_request_reply(auth, &request, &auth->identities) == 0) {
                 l = len;                  buffer_free(&request);
                 if (l > sizeof(msg))                  return NULL;
                         l = sizeof(msg);  
                 l = read(auth->fd, msg, l);  
                 if (l <= 0)  
                         fatal("Incomplete authentication reply.");  
                 buffer_append(&auth->identities, (char *) msg, l);  
                 len -= l;  
         }          }
           buffer_free(&request);
   
         /* Get message type, and verify that we got a proper answer. */          /* Get message type, and verify that we got a proper answer. */
         buffer_get(&auth->identities, (char *) msg, 1);          type = buffer_get_char(&auth->identities);
         if (msg[0] != SSH_AGENT_RSA_IDENTITIES_ANSWER)          if (agent_failed(type)) {
                 fatal("Bad authentication reply message type: %d", msg[0]);                  return NULL;
           } else if (type != code2) {
                   fatal("Bad authentication reply message type: %d", type);
           }
   
         /* Get the number of entries in the response and check it for sanity. */          /* Get the number of entries in the response and check it for sanity. */
         auth->howmany = buffer_get_int(&auth->identities);          auth->howmany = buffer_get_int(&auth->identities);
         if (auth->howmany > 1024)          if (auth->howmany > 1024)
                 fatal("Too many identities in authentication reply: %d\n", auth->howmany);                  fatal("Too many identities in authentication reply: %d\n",
                       auth->howmany);
   
         /* Return the first entry (if any). */          /* Return the first entry (if any). */
         return ssh_get_next_identity(auth, e, n, comment);          return ssh_get_next_identity(auth, comment, version);
 }  }
   
 /*  Key *
  * Returns the next authentication identity for the agent.  Other functions  ssh_get_next_identity(AuthenticationConnection *auth, char **comment, int version)
  * can be called between this and ssh_get_first_identity or two calls of this  
  * function.  This returns 0 if there are no more identities.  The caller  
  * must free comment after a successful return.  
  */  
   
 int  
 ssh_get_next_identity(AuthenticationConnection *auth,  
                       BIGNUM *e, BIGNUM *n, char **comment)  
 {  {
         unsigned int bits;          unsigned int bits;
           unsigned char *blob;
           unsigned int blen;
           Key *key = NULL;
   
         /* Return failure if no more entries. */          /* Return failure if no more entries. */
         if (auth->howmany <= 0)          if (auth->howmany <= 0)
                 return 0;                  return NULL;
   
         /*          /*
          * Get the next entry from the packet.  These will abort with a fatal           * Get the next entry from the packet.  These will abort with a fatal
          * error if the packet is too short or contains corrupt data.           * error if the packet is too short or contains corrupt data.
          */           */
         bits = buffer_get_int(&auth->identities);          switch(version){
         buffer_get_bignum(&auth->identities, e);          case 1:
         buffer_get_bignum(&auth->identities, n);                  key = key_new(KEY_RSA);
         *comment = buffer_get_string(&auth->identities, NULL);                  bits = buffer_get_int(&auth->identities);
                   buffer_get_bignum(&auth->identities, key->rsa->e);
         if (bits != BN_num_bits(n))                  buffer_get_bignum(&auth->identities, key->rsa->n);
                 log("Warning: identity keysize mismatch: actual %d, announced %u",                  *comment = buffer_get_string(&auth->identities, NULL);
                     BN_num_bits(n), bits);                  if (bits != BN_num_bits(key->rsa->n))
                           log("Warning: identity keysize mismatch: actual %d, announced %u",
                               BN_num_bits(key->rsa->n), bits);
                   break;
           case 2:
                   blob = buffer_get_string(&auth->identities, &blen);
                   *comment = buffer_get_string(&auth->identities, NULL);
                   key = dsa_key_from_blob(blob, blen);
                   xfree(blob);
                   break;
           default:
                   return NULL;
                   break;
           }
         /* Decrement the number of remaining entries. */          /* Decrement the number of remaining entries. */
         auth->howmany--;          auth->howmany--;
           return key;
         return 1;  
 }  }
   
 /*  /*
Line 236 
Line 310 
   
 int  int
 ssh_decrypt_challenge(AuthenticationConnection *auth,  ssh_decrypt_challenge(AuthenticationConnection *auth,
                       BIGNUM* e, BIGNUM *n, BIGNUM *challenge,      Key* key, BIGNUM *challenge,
                       unsigned char session_id[16],      unsigned char session_id[16],
                       unsigned int response_type,      unsigned int response_type,
                       unsigned char response[16])      unsigned char response[16])
 {  {
         Buffer buffer;          Buffer buffer;
         unsigned char buf[8192];          int success = 0;
         int len, l, i;          int i;
           int type;
   
         /* Response type 0 is no longer supported. */          if (key->type != KEY_RSA)
         if (response_type == 0)                  return 0;
                 fatal("Compatibility with ssh protocol version 1.0 no longer supported.");          if (response_type == 0) {
                   log("Compatibility with ssh protocol version 1.0 no longer supported.");
         /* Format a message to the agent. */                  return 0;
         buf[0] = SSH_AGENTC_RSA_CHALLENGE;          }
         buffer_init(&buffer);          buffer_init(&buffer);
         buffer_append(&buffer, (char *) buf, 1);          buffer_put_char(&buffer, SSH_AGENTC_RSA_CHALLENGE);
         buffer_put_int(&buffer, BN_num_bits(n));          buffer_put_int(&buffer, BN_num_bits(key->rsa->n));
         buffer_put_bignum(&buffer, e);          buffer_put_bignum(&buffer, key->rsa->e);
         buffer_put_bignum(&buffer, n);          buffer_put_bignum(&buffer, key->rsa->n);
         buffer_put_bignum(&buffer, challenge);          buffer_put_bignum(&buffer, challenge);
         buffer_append(&buffer, (char *) session_id, 16);          buffer_append(&buffer, (char *) session_id, 16);
         buffer_put_int(&buffer, response_type);          buffer_put_int(&buffer, response_type);
   
         /* Get the length of the message, and format it in the buffer. */          if (ssh_request_reply(auth, &buffer, &buffer) == 0) {
         len = buffer_len(&buffer);  
         PUT_32BIT(buf, len);  
   
         /* Send the length and then the packet to the agent. */  
         if (atomicio(write, auth->fd, buf, 4) != 4 ||  
             atomicio(write, auth->fd, buffer_ptr(&buffer),  
             buffer_len(&buffer)) != buffer_len(&buffer)) {  
                 error("Error writing to authentication socket.");  
 error_cleanup:  
                 buffer_free(&buffer);                  buffer_free(&buffer);
                 return 0;                  return 0;
         }          }
         /*          type = buffer_get_char(&buffer);
          * Wait for response from the agent.  First read the length of the  
          * response packet.          if (agent_failed(type)) {
          */                  log("Agent admitted failure to authenticate using the key.");
         len = 4;          } else if (type != SSH_AGENT_RSA_RESPONSE) {
         while (len > 0) {                  fatal("Bad authentication response: %d", type);
                 l = read(auth->fd, buf + 4 - len, len);          } else {
                 if (l <= 0) {                  success = 1;
                         error("Error reading response length from authentication socket.");                  /*
                         goto error_cleanup;                   * Get the response from the packet.  This will abort with a
                 }                   * fatal error if the packet is corrupt.
                 len -= l;                   */
                   for (i = 0; i < 16; i++)
                           response[i] = buffer_get_char(&buffer);
         }          }
           buffer_free(&buffer);
           return success;
   }
   
         /* Extract the length, and check it for sanity. */  /* ask agent to sign data, returns -1 on error, 0 on success */
         len = GET_32BIT(buf);  int
         if (len > 256 * 1024)  ssh_agent_sign(AuthenticationConnection *auth,
                 fatal("Authentication response too long: %d", len);      Key *key,
       unsigned char **sigp, int *lenp,
       unsigned char *data, int datalen)
   {
           extern int datafellows;
           Buffer msg;
           unsigned char *blob;
           unsigned int blen;
           int type, flags = 0;
           int ret = -1;
   
         /* Read the rest of the response in tothe buffer. */          if (dsa_make_key_blob(key, &blob, &blen) == 0)
         buffer_clear(&buffer);                  return -1;
         while (len > 0) {  
                 l = len;  
                 if (l > sizeof(buf))  
                         l = sizeof(buf);  
                 l = read(auth->fd, buf, l);  
                 if (l <= 0) {  
                         error("Error reading response from authentication socket.");  
                         goto error_cleanup;  
                 }  
                 buffer_append(&buffer, (char *) buf, l);  
                 len -= l;  
         }  
   
         /* Get the type of the packet. */          if (datafellows & SSH_BUG_SIGBLOB)
         buffer_get(&buffer, (char *) buf, 1);                  flags = SSH_AGENT_OLD_SIGNATURE;
   
         /* Check for agent failure message. */          buffer_init(&msg);
         if (buf[0] == SSH_AGENT_FAILURE) {          buffer_put_char(&msg, SSH2_AGENTC_SIGN_REQUEST);
                 log("Agent admitted failure to authenticate using the key.");          buffer_put_string(&msg, blob, blen);
                 goto error_cleanup;          buffer_put_string(&msg, data, datalen);
           buffer_put_int(&msg, flags);
           xfree(blob);
   
           if (ssh_request_reply(auth, &msg, &msg) == 0) {
                   buffer_free(&msg);
                   return -1;
         }          }
         /* Now it must be an authentication response packet. */          type = buffer_get_char(&msg);
         if (buf[0] != SSH_AGENT_RSA_RESPONSE)          if (agent_failed(type)) {
                 fatal("Bad authentication response: %d", buf[0]);                  log("Agent admitted failure to sign using the key.");
           } else if (type != SSH2_AGENT_SIGN_RESPONSE) {
                   fatal("Bad authentication response: %d", type);
           } else {
                   ret = 0;
                   *sigp = buffer_get_string(&msg, lenp);
           }
           buffer_free(&msg);
           return ret;
   }
   
         /*  /* Encode key for a message to the agent. */
          * Get the response from the packet.  This will abort with a fatal  
          * error if the packet is corrupt.  
          */  
         for (i = 0; i < 16; i++)  
                 response[i] = buffer_get_char(&buffer);  
   
         /* The buffer containing the packet is no longer needed. */  void
         buffer_free(&buffer);  ssh_encode_identity_rsa(Buffer *b, RSA *key, const char *comment)
   {
           buffer_clear(b);
           buffer_put_char(b, SSH_AGENTC_ADD_RSA_IDENTITY);
           buffer_put_int(b, BN_num_bits(key->n));
           buffer_put_bignum(b, key->n);
           buffer_put_bignum(b, key->e);
           buffer_put_bignum(b, key->d);
           /* To keep within the protocol: p < q for ssh. in SSL p > q */
           buffer_put_bignum(b, key->iqmp);        /* ssh key->u */
           buffer_put_bignum(b, key->q);   /* ssh key->p, SSL key->q */
           buffer_put_bignum(b, key->p);   /* ssh key->q, SSL key->p */
           buffer_put_string(b, comment, strlen(comment));
   }
   
         /* Correct answer. */  void
         return 1;  ssh_encode_identity_dsa(Buffer *b, DSA *key, const char *comment)
   {
           buffer_clear(b);
           buffer_put_char(b, SSH2_AGENTC_ADD_IDENTITY);
           buffer_put_cstring(b, KEX_DSS);
           buffer_put_bignum2(b, key->p);
           buffer_put_bignum2(b, key->q);
           buffer_put_bignum2(b, key->g);
           buffer_put_bignum2(b, key->pub_key);
           buffer_put_bignum2(b, key->priv_key);
           buffer_put_string(b, comment, strlen(comment));
 }  }
   
 /*  /*
Line 339 
Line 440 
  */   */
   
 int  int
 ssh_add_identity(AuthenticationConnection *auth,  ssh_add_identity(AuthenticationConnection *auth, Key *key, const char *comment)
                  RSA * key, const char *comment)  
 {  {
         Buffer buffer;          Buffer msg;
         unsigned char buf[8192];          int type;
         int len, l, type;  
   
         /* Format a message to the agent. */          buffer_init(&msg);
         buffer_init(&buffer);  
         buffer_put_char(&buffer, SSH_AGENTC_ADD_RSA_IDENTITY);  
         buffer_put_int(&buffer, BN_num_bits(key->n));  
         buffer_put_bignum(&buffer, key->n);  
         buffer_put_bignum(&buffer, key->e);  
         buffer_put_bignum(&buffer, key->d);  
         /* To keep within the protocol: p < q for ssh. in SSL p > q */  
         buffer_put_bignum(&buffer, key->iqmp);  /* ssh key->u */  
         buffer_put_bignum(&buffer, key->q);     /* ssh key->p, SSL key->q */  
         buffer_put_bignum(&buffer, key->p);     /* ssh key->q, SSL key->p */  
         buffer_put_string(&buffer, comment, strlen(comment));  
   
         /* Get the length of the message, and format it in the buffer. */          switch (key->type) {
         len = buffer_len(&buffer);          case KEY_RSA:
         PUT_32BIT(buf, len);                  ssh_encode_identity_rsa(&msg, key->rsa, comment);
                   break;
         /* Send the length and then the packet to the agent. */          case KEY_DSA:
         if (atomicio(write, auth->fd, buf, 4) != 4 ||                  ssh_encode_identity_dsa(&msg, key->dsa, comment);
             atomicio(write, auth->fd, buffer_ptr(&buffer),                  break;
             buffer_len(&buffer)) != buffer_len(&buffer)) {          default:
                 error("Error writing to authentication socket.");                  buffer_free(&msg);
 error_cleanup:  
                 buffer_free(&buffer);  
                 return 0;                  return 0;
                   break;
         }          }
         /* Wait for response from the agent.  First read the length of the          if (ssh_request_reply(auth, &msg, &msg) == 0) {
            response packet. */                  buffer_free(&msg);
         len = 4;  
         while (len > 0) {  
                 l = read(auth->fd, buf + 4 - len, len);  
                 if (l <= 0) {  
                         error("Error reading response length from authentication socket.");  
                         goto error_cleanup;  
                 }  
                 len -= l;  
         }  
   
         /* Extract the length, and check it for sanity. */  
         len = GET_32BIT(buf);  
         if (len > 256 * 1024)  
                 fatal("Add identity response too long: %d", len);  
   
         /* Read the rest of the response in tothe buffer. */  
         buffer_clear(&buffer);  
         while (len > 0) {  
                 l = len;  
                 if (l > sizeof(buf))  
                         l = sizeof(buf);  
                 l = read(auth->fd, buf, l);  
                 if (l <= 0) {  
                         error("Error reading response from authentication socket.");  
                         goto error_cleanup;  
                 }  
                 buffer_append(&buffer, (char *) buf, l);  
                 len -= l;  
         }  
   
         /* Get the type of the packet. */  
         type = buffer_get_char(&buffer);  
         switch (type) {  
         case SSH_AGENT_FAILURE:  
                 buffer_free(&buffer);  
                 return 0;                  return 0;
         case SSH_AGENT_SUCCESS:  
                 buffer_free(&buffer);  
                 return 1;  
         default:  
                 fatal("Bad response to add identity from authentication agent: %d",  
                       type);  
         }          }
         /* NOTREACHED */          type = buffer_get_char(&msg);
         return 0;          buffer_free(&msg);
           return decode_reply(type);
 }  }
   
 /*  /*
Line 427 
Line 474 
  */   */
   
 int  int
 ssh_remove_identity(AuthenticationConnection *auth, RSA *key)  ssh_remove_identity(AuthenticationConnection *auth, Key *key)
 {  {
         Buffer buffer;          Buffer msg;
         unsigned char buf[8192];          int type;
         int len, l, type;          unsigned char *blob;
           unsigned int blen;
   
         /* Format a message to the agent. */          buffer_init(&msg);
         buffer_init(&buffer);  
         buffer_put_char(&buffer, SSH_AGENTC_REMOVE_RSA_IDENTITY);  
         buffer_put_int(&buffer, BN_num_bits(key->n));  
         buffer_put_bignum(&buffer, key->e);  
         buffer_put_bignum(&buffer, key->n);  
   
         /* Get the length of the message, and format it in the buffer. */          if (key->type == KEY_RSA) {
         len = buffer_len(&buffer);                  buffer_put_char(&msg, SSH_AGENTC_REMOVE_RSA_IDENTITY);
         PUT_32BIT(buf, len);                  buffer_put_int(&msg, BN_num_bits(key->rsa->n));
                   buffer_put_bignum(&msg, key->rsa->e);
         /* Send the length and then the packet to the agent. */                  buffer_put_bignum(&msg, key->rsa->n);
         if (atomicio(write, auth->fd, buf, 4) != 4 ||          } else if (key->type == KEY_DSA) {
             atomicio(write, auth->fd, buffer_ptr(&buffer),                  dsa_make_key_blob(key, &blob, &blen);
             buffer_len(&buffer)) != buffer_len(&buffer)) {                  buffer_put_char(&msg, SSH2_AGENTC_REMOVE_IDENTITY);
                 error("Error writing to authentication socket.");                  buffer_put_string(&msg, blob, blen);
 error_cleanup:                  xfree(blob);
                 buffer_free(&buffer);          } else {
                   buffer_free(&msg);
                 return 0;                  return 0;
         }          }
         /*          if (ssh_request_reply(auth, &msg, &msg) == 0) {
          * Wait for response from the agent.  First read the length of the                  buffer_free(&msg);
          * response packet.  
          */  
         len = 4;  
         while (len > 0) {  
                 l = read(auth->fd, buf + 4 - len, len);  
                 if (l <= 0) {  
                         error("Error reading response length from authentication socket.");  
                         goto error_cleanup;  
                 }  
                 len -= l;  
         }  
   
         /* Extract the length, and check it for sanity. */  
         len = GET_32BIT(buf);  
         if (len > 256 * 1024)  
                 fatal("Remove identity response too long: %d", len);  
   
         /* Read the rest of the response in tothe buffer. */  
         buffer_clear(&buffer);  
         while (len > 0) {  
                 l = len;  
                 if (l > sizeof(buf))  
                         l = sizeof(buf);  
                 l = read(auth->fd, buf, l);  
                 if (l <= 0) {  
                         error("Error reading response from authentication socket.");  
                         goto error_cleanup;  
                 }  
                 buffer_append(&buffer, (char *) buf, l);  
                 len -= l;  
         }  
   
         /* Get the type of the packet. */  
         type = buffer_get_char(&buffer);  
         switch (type) {  
         case SSH_AGENT_FAILURE:  
                 buffer_free(&buffer);  
                 return 0;                  return 0;
         case SSH_AGENT_SUCCESS:  
                 buffer_free(&buffer);  
                 return 1;  
         default:  
                 fatal("Bad response to remove identity from authentication agent: %d",  
                       type);  
         }          }
         /* NOTREACHED */          type = buffer_get_char(&msg);
         return 0;          buffer_free(&msg);
           return decode_reply(type);
 }  }
   
 /*  /*
Line 510 
Line 512 
  */   */
   
 int  int
 ssh_remove_all_identities(AuthenticationConnection *auth)  ssh_remove_all_identities(AuthenticationConnection *auth, int version)
 {  {
         Buffer buffer;          Buffer msg;
         unsigned char buf[8192];          int type;
         int len, l, type;          int code = (version==1) ?
                   SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES :
                   SSH2_AGENTC_REMOVE_ALL_IDENTITIES;
   
         /* Get the length of the message, and format it in the buffer. */          buffer_init(&msg);
         PUT_32BIT(buf, 1);          buffer_put_char(&msg, code);
         buf[4] = SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES;  
   
         /* Send the length and then the packet to the agent. */          if (ssh_request_reply(auth, &msg, &msg) == 0) {
         if (atomicio(write, auth->fd, buf, 5) != 5) {                  buffer_free(&msg);
                 error("Error writing to authentication socket.");  
                 return 0;                  return 0;
         }          }
         /*          type = buffer_get_char(&msg);
          * Wait for response from the agent.  First read the length of the          buffer_free(&msg);
          * response packet.          return decode_reply(type);
          */  }
         len = 4;  
         while (len > 0) {  
                 l = read(auth->fd, buf + 4 - len, len);  
                 if (l <= 0) {  
                         error("Error reading response length from authentication socket.");  
                         return 0;  
                 }  
                 len -= l;  
         }  
   
         /* Extract the length, and check it for sanity. */  int
         len = GET_32BIT(buf);  decode_reply(int type)
         if (len > 256 * 1024)  {
                 fatal("Remove identity response too long: %d", len);  
   
         /* Read the rest of the response into the buffer. */  
         buffer_init(&buffer);  
         while (len > 0) {  
                 l = len;  
                 if (l > sizeof(buf))  
                         l = sizeof(buf);  
                 l = read(auth->fd, buf, l);  
                 if (l <= 0) {  
                         error("Error reading response from authentication socket.");  
                         buffer_free(&buffer);  
                         return 0;  
                 }  
                 buffer_append(&buffer, (char *) buf, l);  
                 len -= l;  
         }  
   
         /* Get the type of the packet. */  
         type = buffer_get_char(&buffer);  
         switch (type) {          switch (type) {
         case SSH_AGENT_FAILURE:          case SSH_AGENT_FAILURE:
                 buffer_free(&buffer);          case SSH_COM_AGENT2_FAILURE:
                   log("SSH_AGENT_FAILURE");
                 return 0;                  return 0;
         case SSH_AGENT_SUCCESS:          case SSH_AGENT_SUCCESS:
                 buffer_free(&buffer);  
                 return 1;                  return 1;
         default:          default:
                 fatal("Bad response to remove identity from authentication agent: %d",                  fatal("Bad response from authentication agent: %d", type);
                       type);  
         }          }
         /* NOTREACHED */          /* NOTREACHED */
         return 0;          return 0;

Legend:
Removed from v.1.19  
changed lines
  Added in v.1.19.2.2