[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.11 and 1.12

version 1.11, 1999/11/18 11:09:39 version 1.12, 1999/11/23 22:25:52
Line 31 
Line 31 
 int  int
 ssh_get_authentication_socket()  ssh_get_authentication_socket()
 {  {
   const char *authsocket;          const char *authsocket;
   int sock;          int sock;
   struct sockaddr_un sunaddr;          struct sockaddr_un sunaddr;
   
   authsocket = getenv(SSH_AUTHSOCKET_ENV_NAME);          authsocket = getenv(SSH_AUTHSOCKET_ENV_NAME);
   if (!authsocket)          if (!authsocket)
     return -1;                  return -1;
   
   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));
   
   sock = socket(AF_UNIX, SOCK_STREAM, 0);  
   if (sock < 0)  
     return -1;  
   
   /* close on exec */          sock = socket(AF_UNIX, SOCK_STREAM, 0);
   if (fcntl(sock, F_SETFD, 1) == -1)          if (sock < 0)
     {                  return -1;
       close(sock);  
       return -1;  
     }  
   
   if (connect(sock, (struct sockaddr *)&sunaddr, sizeof(sunaddr)) < 0)  
     {  
       close(sock);  
       return -1;  
     }  
   
   return sock;          /* close on exec */
           if (fcntl(sock, F_SETFD, 1) == -1) {
                   close(sock);
                   return -1;
           }
           if (connect(sock, (struct sockaddr *) & sunaddr, sizeof(sunaddr)) < 0) {
                   close(sock);
                   return -1;
           }
           return sock;
 }  }
   
 /* 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
    ssh_get_authentication_socket(). */     ssh_get_authentication_socket(). */
   
 void ssh_close_authentication_socket(int sock)  void
   ssh_close_authentication_socket(int sock)
 {  {
   if (getenv(SSH_AUTHSOCKET_ENV_NAME))          if (getenv(SSH_AUTHSOCKET_ENV_NAME))
     close(sock);                  close(sock);
 }  }
   
 /* Opens and connects a private socket for communication with the  /* Opens and connects a private socket for communication with the
Line 78 
Line 75 
    Returns NULL if an error occurred and the connection could not be     Returns NULL if an error occurred and the connection could not be
    opened. */     opened. */
   
 AuthenticationConnection *ssh_get_authentication_connection()  AuthenticationConnection *
   ssh_get_authentication_connection()
 {  {
   AuthenticationConnection *auth;          AuthenticationConnection *auth;
   int sock;          int sock;
   
   sock = ssh_get_authentication_socket();  
   
   /* Fail if we couldn't obtain a connection.  This happens if we exited          sock = ssh_get_authentication_socket();
      due to a timeout. */  
   if (sock < 0)  
     return NULL;  
   
   /* Applocate the connection structure and initialize it. */          /* Fail if we couldn't obtain a connection.  This happens if we
   auth = xmalloc(sizeof(*auth));             exited due to a timeout. */
   auth->fd = sock;          if (sock < 0)
   buffer_init(&auth->packet);                  return NULL;
   buffer_init(&auth->identities);  
   auth->howmany = 0;  
   
   return auth;          /* Applocate the connection structure and initialize it. */
           auth = xmalloc(sizeof(*auth));
           auth->fd = sock;
           buffer_init(&auth->packet);
           buffer_init(&auth->identities);
           auth->howmany = 0;
   
           return auth;
 }  }
   
 /* Closes the connection to the authentication agent and frees any associated  /* Closes the connection to the authentication agent and frees any associated
    memory. */     memory. */
   
 void ssh_close_authentication_connection(AuthenticationConnection *ac)  void
   ssh_close_authentication_connection(AuthenticationConnection *ac)
 {  {
   buffer_free(&ac->packet);          buffer_free(&ac->packet);
   buffer_free(&ac->identities);          buffer_free(&ac->identities);
   close(ac->fd);          close(ac->fd);
   /* Free the connection data structure. */          xfree(ac);
   xfree(ac);  
 }  }
   
 /* Returns the first authentication identity held by the agent.  /* Returns the first authentication identity held by the agent.
Line 121 
Line 119 
 ssh_get_first_identity(AuthenticationConnection *auth,  ssh_get_first_identity(AuthenticationConnection *auth,
                        BIGNUM *e, BIGNUM *n, char **comment)                         BIGNUM *e, BIGNUM *n, char **comment)
 {  {
   unsigned char msg[8192];          unsigned char msg[8192];
   int len, l;          int len, l;
   
   /* Send a message to the agent requesting for a list of the identities          /* Send a message to the agent requesting for a list of the
      it can represent. */             identities it can represent. */
   msg[0] = 0;          msg[0] = 0;
   msg[1] = 0;          msg[1] = 0;
   msg[2] = 0;          msg[2] = 0;
   msg[3] = 1;          msg[3] = 1;
   msg[4] = SSH_AGENTC_REQUEST_RSA_IDENTITIES;          msg[4] = SSH_AGENTC_REQUEST_RSA_IDENTITIES;
   if (write(auth->fd, msg, 5) != 5)          if (write(auth->fd, msg, 5) != 5) {
     {                  error("write auth->fd: %.100s", strerror(errno));
       error("write auth->fd: %.100s", strerror(errno));                  return 0;
       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;
           }
   
   /* Read the length of the response.  XXX implement timeouts here. */          /* Extract the length, and check it for sanity.  (We cannot trust
   len = 4;             authentication agents). */
   while (len > 0)          len = GET_32BIT(msg);
     {          if (len < 1 || len > 256 * 1024)
       l = read(auth->fd, msg + 4 - len, len);                  fatal("Authentication reply message too long: %d\n", len);
       if (l <= 0)  
         {          /* Read the packet itself. */
           error("read auth->fd: %.100s", strerror(errno));          buffer_clear(&auth->identities);
           return 0;          while (len > 0) {
                   l = len;
                   if (l > sizeof(msg))
                           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;
         }          }
       len -= l;  
     }  
   
   /* Extract the length, and check it for sanity.  (We cannot trust          /* Get message type, and verify that we got a proper answer. */
      authentication agents). */          buffer_get(&auth->identities, (char *) msg, 1);
   len = GET_32BIT(msg);          if (msg[0] != SSH_AGENT_RSA_IDENTITIES_ANSWER)
   if (len < 1 || len > 256*1024)                  fatal("Bad authentication reply message type: %d", msg[0]);
     fatal("Authentication reply message too long: %d\n", len);  
   
   /* Read the packet itself. */          /* Get the number of entries in the response and check it for sanity. */
   buffer_clear(&auth->identities);          auth->howmany = buffer_get_int(&auth->identities);
   while (len > 0)          if (auth->howmany > 1024)
     {                  fatal("Too many identities in authentication reply: %d\n", auth->howmany);
       l = len;  
       if (l > sizeof(msg))  
         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;  
     }  
   
   /* Get message type, and verify that we got a proper answer. */  
   buffer_get(&auth->identities, (char *)msg, 1);  
   if (msg[0] != SSH_AGENT_RSA_IDENTITIES_ANSWER)  
     fatal("Bad authentication reply message type: %d", msg[0]);  
   
   /* Get the number of entries in the response and check it for sanity. */  
   auth->howmany = buffer_get_int(&auth->identities);  
   if (auth->howmany > 1024)  
     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, e, n, comment);
 }  }
   
 /* Returns the next authentication identity for the agent.  Other functions  /* Returns the next authentication identity for the agent.  Other functions
Line 193 
Line 186 
 ssh_get_next_identity(AuthenticationConnection *auth,  ssh_get_next_identity(AuthenticationConnection *auth,
                       BIGNUM *e, BIGNUM *n, char **comment)                        BIGNUM *e, BIGNUM *n, char **comment)
 {  {
   unsigned int bits;          unsigned int bits;
   
   /* Return failure if no more entries. */          /* Return failure if no more entries. */
   if (auth->howmany <= 0)          if (auth->howmany <= 0)
     return 0;                  return 0;
   
   /* 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
      error if the packet is too short or contains corrupt data. */             fatal error if the packet is too short or contains corrupt data. */
   bits = buffer_get_int(&auth->identities);          bits = buffer_get_int(&auth->identities);
   buffer_get_bignum(&auth->identities, e);          buffer_get_bignum(&auth->identities, e);
   buffer_get_bignum(&auth->identities, n);          buffer_get_bignum(&auth->identities, n);
   *comment = buffer_get_string(&auth->identities, NULL);          *comment = buffer_get_string(&auth->identities, NULL);
   
   if (bits != BN_num_bits(n))          if (bits != BN_num_bits(n))
     error("Warning: keysize mismatch: actual %d, announced %u",                  error("Warning: keysize mismatch: actual %d, announced %u",
           BN_num_bits(n), bits);                        BN_num_bits(n), bits);
   
   /* Decrement the number of remaining entries. */          /* Decrement the number of remaining entries. */
   auth->howmany--;          auth->howmany--;
   
   return 1;          return 1;
 }  }
   
 /* Generates a random challenge, sends it to the agent, and waits for response  /* Generates a random challenge, sends it to the agent, and waits for response
Line 224 
Line 217 
   
 int  int
 ssh_decrypt_challenge(AuthenticationConnection *auth,  ssh_decrypt_challenge(AuthenticationConnection *auth,
                       BIGNUM *e, BIGNUM *n, BIGNUM *challenge,                        BIGNUM* e, BIGNUM *n, 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];          unsigned char buf[8192];
   int len, l, i;          int len, l, i;
   
   /* Response type 0 is no longer supported. */          /* Response type 0 is no longer supported. */
   if (response_type == 0)          if (response_type == 0)
     fatal("Compatibility with ssh protocol version 1.0 no longer supported.");                  fatal("Compatibility with ssh protocol version 1.0 no longer supported.");
   
   /* Format a message to the agent. */          /* Format a message to the agent. */
   buf[0] = SSH_AGENTC_RSA_CHALLENGE;          buf[0] = SSH_AGENTC_RSA_CHALLENGE;
   buffer_init(&buffer);          buffer_init(&buffer);
   buffer_append(&buffer, (char *)buf, 1);          buffer_append(&buffer, (char *) buf, 1);
   buffer_put_int(&buffer, BN_num_bits(n));          buffer_put_int(&buffer, BN_num_bits(n));
   buffer_put_bignum(&buffer, e);          buffer_put_bignum(&buffer, e);
   buffer_put_bignum(&buffer, n);          buffer_put_bignum(&buffer, 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. */          /* Get the length of the message, and format it in the buffer. */
   len = buffer_len(&buffer);          len = buffer_len(&buffer);
   PUT_32BIT(buf, len);          PUT_32BIT(buf, len);
   
   /* Send the length and then the packet to the agent. */          /* Send the length and then the packet to the agent. */
   if (write(auth->fd, buf, 4) != 4 ||          if (write(auth->fd, buf, 4) != 4 ||
       write(auth->fd, buffer_ptr(&buffer), buffer_len(&buffer)) !=              write(auth->fd, buffer_ptr(&buffer), buffer_len(&buffer)) !=
         buffer_len(&buffer))              buffer_len(&buffer)) {
     {                  error("Error writing to authentication socket.");
       error("Error writing to authentication socket.");  error_cleanup:
     error_cleanup:                  buffer_free(&buffer);
       buffer_free(&buffer);                  return 0;
       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.");  
           goto error_cleanup;  
         }          }
       len -= l;          /* 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.");
                           goto error_cleanup;
                   }
                   len -= l;
           }
   
   /* Extract the length, and check it for sanity. */          /* Extract the length, and check it for sanity. */
   len = GET_32BIT(buf);          len = GET_32BIT(buf);
   if (len > 256*1024)          if (len > 256 * 1024)
     fatal("Authentication response too long: %d", len);                  fatal("Authentication response too long: %d", len);
   
   /* Read the rest of the response in tothe buffer. */          /* Read the rest of the response in tothe buffer. */
   buffer_clear(&buffer);          buffer_clear(&buffer);
   while (len > 0)          while (len > 0) {
     {                  l = len;
       l = len;                  if (l > sizeof(buf))
       if (l > sizeof(buf))                          l = sizeof(buf);
         l = sizeof(buf);                  l = read(auth->fd, buf, l);
       l = read(auth->fd, buf, l);                  if (l <= 0) {
       if (l <= 0)                          error("Error reading response from authentication socket.");
         {                          goto error_cleanup;
           error("Error reading response from authentication socket.");                  }
           goto error_cleanup;                  buffer_append(&buffer, (char *) buf, l);
                   len -= l;
         }          }
       buffer_append(&buffer, (char *)buf, l);  
       len -= l;  
     }  
   
   /* Get the type of the packet. */          /* Get the type of the packet. */
   buffer_get(&buffer, (char *)buf, 1);          buffer_get(&buffer, (char *) buf, 1);
   
   /* Check for agent failure message. */          /* Check for agent failure message. */
   if (buf[0] == SSH_AGENT_FAILURE)          if (buf[0] == SSH_AGENT_FAILURE) {
     {                  log("Agent admitted failure to authenticate using the key.");
       log("Agent admitted failure to authenticate using the key.");                  goto error_cleanup;
       goto error_cleanup;          }
     }          /* Now it must be an authentication response packet. */
           if (buf[0] != SSH_AGENT_RSA_RESPONSE)
   /* Now it must be an authentication response packet. */                  fatal("Bad authentication response: %d", buf[0]);
   if (buf[0] != SSH_AGENT_RSA_RESPONSE)  
     fatal("Bad authentication response: %d", buf[0]);  
   
   /* Get the response from the packet.  This will abort with a fatal error          /* Get the response from the packet.  This will abort with a fatal
      if the packet is corrupt. */             error if the packet is corrupt. */
   for (i = 0; i < 16; i++)          for (i = 0; i < 16; i++)
     response[i] = buffer_get_char(&buffer);                  response[i] = buffer_get_char(&buffer);
   
   /* The buffer containing the packet is no longer needed. */          /* The buffer containing the packet is no longer needed. */
   buffer_free(&buffer);          buffer_free(&buffer);
   
   /* Correct answer. */          /* Correct answer. */
   return 1;          return 1;
 }  }
   
 /* Adds an identity to the authentication server.  This call is not meant to  /* Adds an identity to the authentication server.  This call is not meant to
    be used by normal applications. */     be used by normal applications. */
   
 int ssh_add_identity(AuthenticationConnection *auth,  int
                      RSA *key, const char *comment)  ssh_add_identity(AuthenticationConnection *auth,
                    RSA * key, const char *comment)
 {  {
   Buffer buffer;          Buffer buffer;
   unsigned char buf[8192];          unsigned char buf[8192];
   int len, l, type;          int len, l, type;
   
   /* Format a message to the agent. */          /* Format a message to the agent. */
   buffer_init(&buffer);          buffer_init(&buffer);
   buffer_put_char(&buffer, SSH_AGENTC_ADD_RSA_IDENTITY);          buffer_put_char(&buffer, SSH_AGENTC_ADD_RSA_IDENTITY);
   buffer_put_int(&buffer, BN_num_bits(key->n));          buffer_put_int(&buffer, BN_num_bits(key->n));
   buffer_put_bignum(&buffer, key->n);          buffer_put_bignum(&buffer, key->n);
   buffer_put_bignum(&buffer, key->e);          buffer_put_bignum(&buffer, key->e);
   buffer_put_bignum(&buffer, key->d);          buffer_put_bignum(&buffer, key->d);
   /* To keep within the protocol: p < q for ssh. in SSL p > q */          /* 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->iqmp);  /* ssh key->u */
   buffer_put_bignum(&buffer, key->q); /* ssh key->p, SSL key->q */          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_bignum(&buffer, key->p);     /* ssh key->q, SSL key->p */
   buffer_put_string(&buffer, comment, strlen(comment));          buffer_put_string(&buffer, comment, strlen(comment));
   
   /* Get the length of the message, and format it in the buffer. */          /* Get the length of the message, and format it in the buffer. */
   len = buffer_len(&buffer);          len = buffer_len(&buffer);
   PUT_32BIT(buf, len);          PUT_32BIT(buf, len);
   
   /* Send the length and then the packet to the agent. */          /* Send the length and then the packet to the agent. */
   if (write(auth->fd, buf, 4) != 4 ||          if (write(auth->fd, buf, 4) != 4 ||
       write(auth->fd, buffer_ptr(&buffer), buffer_len(&buffer)) !=              write(auth->fd, buffer_ptr(&buffer), buffer_len(&buffer)) !=
         buffer_len(&buffer))              buffer_len(&buffer)) {
     {                  error("Error writing to authentication socket.");
       error("Error writing to authentication socket.");  error_cleanup:
     error_cleanup:                  buffer_free(&buffer);
       buffer_free(&buffer);                  return 0;
       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.");  
           goto error_cleanup;  
         }          }
       len -= l;          /* 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.");
                           goto error_cleanup;
                   }
                   len -= l;
           }
   
   /* Extract the length, and check it for sanity. */          /* Extract the length, and check it for sanity. */
   len = GET_32BIT(buf);          len = GET_32BIT(buf);
   if (len > 256*1024)          if (len > 256 * 1024)
     fatal("Add identity response too long: %d", len);                  fatal("Add identity response too long: %d", len);
   
   /* Read the rest of the response in tothe buffer. */          /* Read the rest of the response in tothe buffer. */
   buffer_clear(&buffer);          buffer_clear(&buffer);
   while (len > 0)          while (len > 0) {
     {                  l = len;
       l = len;                  if (l > sizeof(buf))
       if (l > sizeof(buf))                          l = sizeof(buf);
         l = sizeof(buf);                  l = read(auth->fd, buf, l);
       l = read(auth->fd, buf, l);                  if (l <= 0) {
       if (l <= 0)                          error("Error reading response from authentication socket.");
         {                          goto error_cleanup;
           error("Error reading response from authentication socket.");                  }
           goto error_cleanup;                  buffer_append(&buffer, (char *) buf, l);
                   len -= l;
         }          }
       buffer_append(&buffer, (char *)buf, l);  
       len -= l;  
     }  
   
   /* Get the type of the packet. */          /* Get the type of the packet. */
   type = buffer_get_char(&buffer);          type = buffer_get_char(&buffer);
   switch (type)          switch (type) {
     {          case SSH_AGENT_FAILURE:
     case SSH_AGENT_FAILURE:                  buffer_free(&buffer);
       buffer_free(&buffer);                  return 0;
       return 0;          case SSH_AGENT_SUCCESS:
     case SSH_AGENT_SUCCESS:                  buffer_free(&buffer);
       buffer_free(&buffer);                  return 1;
       return 1;          default:
     default:                  fatal("Bad response to add identity from authentication agent: %d",
       fatal("Bad response to add identity from authentication agent: %d",                        type);
             type);          }
     }          /* NOTREACHED */
   /*NOTREACHED*/          return 0;
   return 0;  }
 }  
   
 /* Removes an identity from the authentication server.  This call is not meant  /* Removes an identity from the authentication server.  This call is not meant
    to be used by normal applications. */     to be used by normal applications. */
   
 int ssh_remove_identity(AuthenticationConnection *auth, RSA *key)  int
   ssh_remove_identity(AuthenticationConnection *auth, RSA *key)
 {  {
   Buffer buffer;          Buffer buffer;
   unsigned char buf[8192];          unsigned char buf[8192];
   int len, l, type;          int len, l, type;
   
   /* Format a message to the agent. */          /* Format a message to the agent. */
   buffer_init(&buffer);          buffer_init(&buffer);
   buffer_put_char(&buffer, SSH_AGENTC_REMOVE_RSA_IDENTITY);          buffer_put_char(&buffer, SSH_AGENTC_REMOVE_RSA_IDENTITY);
   buffer_put_int(&buffer, BN_num_bits(key->n));          buffer_put_int(&buffer, BN_num_bits(key->n));
   buffer_put_bignum(&buffer, key->e);          buffer_put_bignum(&buffer, key->e);
   buffer_put_bignum(&buffer, key->n);          buffer_put_bignum(&buffer, key->n);
   
   /* Get the length of the message, and format it in the buffer. */          /* Get the length of the message, and format it in the buffer. */
   len = buffer_len(&buffer);          len = buffer_len(&buffer);
   PUT_32BIT(buf, len);          PUT_32BIT(buf, len);
   
   /* Send the length and then the packet to the agent. */          /* Send the length and then the packet to the agent. */
   if (write(auth->fd, buf, 4) != 4 ||          if (write(auth->fd, buf, 4) != 4 ||
       write(auth->fd, buffer_ptr(&buffer), buffer_len(&buffer)) !=              write(auth->fd, buffer_ptr(&buffer), buffer_len(&buffer)) !=
         buffer_len(&buffer))              buffer_len(&buffer)) {
     {                  error("Error writing to authentication socket.");
       error("Error writing to authentication socket.");  error_cleanup:
     error_cleanup:                  buffer_free(&buffer);
       buffer_free(&buffer);                  return 0;
       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.");  
           goto error_cleanup;  
         }          }
       len -= l;          /* 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.");
                           goto error_cleanup;
                   }
                   len -= l;
           }
   
   /* Extract the length, and check it for sanity. */          /* Extract the length, and check it for sanity. */
   len = GET_32BIT(buf);          len = GET_32BIT(buf);
   if (len > 256*1024)          if (len > 256 * 1024)
     fatal("Remove identity response too long: %d", len);                  fatal("Remove identity response too long: %d", len);
   
   /* Read the rest of the response in tothe buffer. */          /* Read the rest of the response in tothe buffer. */
   buffer_clear(&buffer);          buffer_clear(&buffer);
   while (len > 0)          while (len > 0) {
     {                  l = len;
       l = len;                  if (l > sizeof(buf))
       if (l > sizeof(buf))                          l = sizeof(buf);
         l = sizeof(buf);                  l = read(auth->fd, buf, l);
       l = read(auth->fd, buf, l);                  if (l <= 0) {
       if (l <= 0)                          error("Error reading response from authentication socket.");
         {                          goto error_cleanup;
           error("Error reading response from authentication socket.");                  }
           goto error_cleanup;                  buffer_append(&buffer, (char *) buf, l);
                   len -= l;
         }          }
       buffer_append(&buffer, (char *)buf, l);  
       len -= l;  
     }  
   
   /* Get the type of the packet. */          /* Get the type of the packet. */
   type = buffer_get_char(&buffer);          type = buffer_get_char(&buffer);
   switch (type)          switch (type) {
     {          case SSH_AGENT_FAILURE:
     case SSH_AGENT_FAILURE:                  buffer_free(&buffer);
       buffer_free(&buffer);                  return 0;
       return 0;          case SSH_AGENT_SUCCESS:
     case SSH_AGENT_SUCCESS:                  buffer_free(&buffer);
       buffer_free(&buffer);                  return 1;
       return 1;          default:
     default:                  fatal("Bad response to remove identity from authentication agent: %d",
       fatal("Bad response to remove identity from authentication agent: %d",                        type);
             type);          }
     }          /* NOTREACHED */
   /*NOTREACHED*/          return 0;
   return 0;  }
 }  
   
 /* Removes all identities from the agent.  This call is not meant  /* Removes all identities from the agent.  This call is not meant
    to be used by normal applications. */     to be used by normal applications. */
   
 int ssh_remove_all_identities(AuthenticationConnection *auth)  int
   ssh_remove_all_identities(AuthenticationConnection *auth)
 {  {
   Buffer buffer;          Buffer buffer;
   unsigned char buf[8192];          unsigned char buf[8192];
   int len, l, type;          int len, l, type;
   
   /* Get the length of the message, and format it in the buffer. */          /* Get the length of the message, and format it in the buffer. */
   PUT_32BIT(buf, 1);          PUT_32BIT(buf, 1);
   buf[4] = SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES;          buf[4] = SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES;
   
   /* Send the length and then the packet to the agent. */          /* Send the length and then the packet to the agent. */
   if (write(auth->fd, buf, 5) != 5)          if (write(auth->fd, buf, 5) != 5) {
     {                  error("Error writing to authentication socket.");
       error("Error writing to authentication socket.");                  return 0;
       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;          /* 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. */          /* Extract the length, and check it for sanity. */
   len = GET_32BIT(buf);          len = GET_32BIT(buf);
   if (len > 256*1024)          if (len > 256 * 1024)
     fatal("Remove identity response too long: %d", len);                  fatal("Remove identity response too long: %d", len);
   
   /* Read the rest of the response into the buffer. */          /* Read the rest of the response into the buffer. */
   buffer_init(&buffer);          buffer_init(&buffer);
   while (len > 0)          while (len > 0) {
     {                  l = len;
       l = len;                  if (l > sizeof(buf))
       if (l > sizeof(buf))                          l = sizeof(buf);
         l = sizeof(buf);                  l = read(auth->fd, buf, l);
       l = read(auth->fd, buf, l);                  if (l <= 0) {
       if (l <= 0)                          error("Error reading response from authentication socket.");
         {                          buffer_free(&buffer);
           error("Error reading response from authentication socket.");                          return 0;
           buffer_free(&buffer);                  }
           return 0;                  buffer_append(&buffer, (char *) buf, l);
                   len -= l;
         }          }
       buffer_append(&buffer, (char *)buf, l);  
       len -= l;  
     }  
   
   /* Get the type of the packet. */          /* Get the type of the packet. */
   type = buffer_get_char(&buffer);          type = buffer_get_char(&buffer);
   switch (type)          switch (type) {
     {          case SSH_AGENT_FAILURE:
     case SSH_AGENT_FAILURE:                  buffer_free(&buffer);
       buffer_free(&buffer);                  return 0;
       return 0;          case SSH_AGENT_SUCCESS:
     case SSH_AGENT_SUCCESS:                  buffer_free(&buffer);
       buffer_free(&buffer);                  return 1;
       return 1;          default:
     default:                  fatal("Bad response to remove identity from authentication agent: %d",
       fatal("Bad response to remove identity from authentication agent: %d",                        type);
             type);          }
     }          /* NOTREACHED */
   /*NOTREACHED*/          return 0;
   return 0;  }
 }  

Legend:
Removed from v.1.11  
changed lines
  Added in v.1.12