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

Diff for /src/usr.bin/ssh/sshconnect.c between version 1.137.2.2 and 1.138

version 1.137.2.2, 2004/03/04 18:18:17 version 1.138, 2003/04/08 20:21:29
Line 33 
Line 33 
 #include "misc.h"  #include "misc.h"
 #include "readpass.h"  #include "readpass.h"
   
 #include "dns.h"  
   
 char *client_version_string = NULL;  char *client_version_string = NULL;
 char *server_version_string = NULL;  char *server_version_string = NULL;
   
 int matching_host_key_dns = 0;  
   
 /* import */  /* import */
 extern Options options;  extern Options options;
 extern char *__progname;  extern char *__progname;
Line 48 
Line 44 
 extern pid_t proxy_command_pid;  extern pid_t proxy_command_pid;
   
 static int show_other_keys(const char *, Key *);  static int show_other_keys(const char *, Key *);
 static void warn_changed_key(Key *);  
   
 /*  /*
  * Connect to the given ssh server using a proxy command.   * Connect to the given ssh server using a proxy command.
Line 70 
Line 65 
          * Build the final command string in the buffer by making the           * Build the final command string in the buffer by making the
          * appropriate substitutions to the given proxy command.           * appropriate substitutions to the given proxy command.
          *           *
          * Use "exec" to avoid "sh -c" processes on some platforms           * Use "exec" to avoid "sh -c" processes on some platforms
          * (e.g. Solaris)           * (e.g. Solaris)
          */           */
         buffer_init(&command);          buffer_init(&command);
Line 164 
Line 159 
  * Creates a (possibly privileged) socket for use as the ssh connection.   * Creates a (possibly privileged) socket for use as the ssh connection.
  */   */
 static int  static int
 ssh_create_socket(int privileged, struct addrinfo *ai)  ssh_create_socket(int privileged, int family)
 {  {
         int sock, gaierr;          int sock, gaierr;
         struct addrinfo hints, *res;          struct addrinfo hints, *res;
Line 176 
Line 171 
         if (privileged) {          if (privileged) {
                 int p = IPPORT_RESERVED - 1;                  int p = IPPORT_RESERVED - 1;
                 PRIV_START;                  PRIV_START;
                 sock = rresvport_af(&p, ai->ai_family);                  sock = rresvport_af(&p, family);
                 PRIV_END;                  PRIV_END;
                 if (sock < 0)                  if (sock < 0)
                         error("rresvport: af=%d %.100s", ai->ai_family,                          error("rresvport: af=%d %.100s", family, strerror(errno));
                             strerror(errno));  
                 else                  else
                         debug("Allocated local port %d.", p);                          debug("Allocated local port %d.", p);
                 return sock;                  return sock;
         }          }
         sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);          sock = socket(family, SOCK_STREAM, 0);
         if (sock < 0)          if (sock < 0)
                 error("socket: %.100s", strerror(errno));                  error("socket: %.100s", strerror(errno));
   
Line 194 
Line 188 
                 return sock;                  return sock;
   
         memset(&hints, 0, sizeof(hints));          memset(&hints, 0, sizeof(hints));
         hints.ai_family = ai->ai_family;          hints.ai_family = family;
         hints.ai_socktype = ai->ai_socktype;          hints.ai_socktype = SOCK_STREAM;
         hints.ai_protocol = ai->ai_protocol;  
         hints.ai_flags = AI_PASSIVE;          hints.ai_flags = AI_PASSIVE;
         gaierr = getaddrinfo(options.bind_address, "0", &hints, &res);          gaierr = getaddrinfo(options.bind_address, "0", &hints, &res);
         if (gaierr) {          if (gaierr) {
Line 215 
Line 208 
         return sock;          return sock;
 }  }
   
 static int  
 timeout_connect(int sockfd, const struct sockaddr *serv_addr,  
     socklen_t addrlen, int timeout)  
 {  
         fd_set *fdset;  
         struct timeval tv;  
         socklen_t optlen;  
         int fdsetsz, optval, rc, result = -1;  
   
         if (timeout <= 0)  
                 return (connect(sockfd, serv_addr, addrlen));  
   
         set_nonblock(sockfd);  
         rc = connect(sockfd, serv_addr, addrlen);  
         if (rc == 0) {  
                 unset_nonblock(sockfd);  
                 return (0);  
         }  
         if (errno != EINPROGRESS)  
                 return (-1);  
   
         fdsetsz = howmany(sockfd + 1, NFDBITS) * sizeof(fd_mask);  
         fdset = (fd_set *)xmalloc(fdsetsz);  
   
         memset(fdset, 0, fdsetsz);  
         FD_SET(sockfd, fdset);  
         tv.tv_sec = timeout;  
         tv.tv_usec = 0;  
   
         for(;;) {  
                 rc = select(sockfd + 1, NULL, fdset, NULL, &tv);  
                 if (rc != -1 || errno != EINTR)  
                         break;  
         }  
   
         switch(rc) {  
         case 0:  
                 /* Timed out */  
                 errno = ETIMEDOUT;  
                 break;  
         case -1:  
                 /* Select error */  
                 debug("select: %s", strerror(errno));  
                 break;  
         case 1:  
                 /* Completed or failed */  
                 optval = 0;  
                 optlen = sizeof(optval);  
                 if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &optval,  
                     &optlen) == -1) {  
                         debug("getsockopt: %s", strerror(errno));  
                         break;  
                 }  
                 if (optval != 0) {  
                         errno = optval;  
                         break;  
                 }  
                 result = 0;  
                 unset_nonblock(sockfd);  
                 break;  
         default:  
                 /* Should not occur */  
                 fatal("Bogus return (%d) from select()", rc);  
         }  
   
         xfree(fdset);  
         return (result);  
 }  
   
 /*  /*
  * Opens a TCP/IP connection to the remote server on the given host.   * Opens a TCP/IP connection to the remote server on the given host.
  * The address of the remote host will be returned in hostaddr.   * The address of the remote host will be returned in hostaddr.
Line 367 
Line 291 
                                 host, ntop, strport);                                  host, ntop, strport);
   
                         /* Create a socket for connecting. */                          /* Create a socket for connecting. */
                         sock = ssh_create_socket(needpriv, ai);                          sock = ssh_create_socket(needpriv, ai->ai_family);
                         if (sock < 0)                          if (sock < 0)
                                 /* Any error is already output */                                  /* Any error is already output */
                                 continue;                                  continue;
   
                         if (timeout_connect(sock, ai->ai_addr, ai->ai_addrlen,                          if (connect(sock, ai->ai_addr, ai->ai_addrlen) >= 0) {
                             options.connection_timeout) >= 0) {  
                                 /* Successful connection. */                                  /* Successful connection. */
                                 memcpy(hostaddr, ai->ai_addr, ai->ai_addrlen);                                  memcpy(hostaddr, ai->ai_addr, ai->ai_addrlen);
                                 break;                                  break;
Line 412 
Line 335 
   
         debug("Connection established.");          debug("Connection established.");
   
         /* Set SO_KEEPALIVE if requested. */          /* Set keepalives if requested. */
         if (options.tcp_keep_alive &&          if (options.keepalives &&
             setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (void *)&on,              setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (void *)&on,
             sizeof(on)) < 0)              sizeof(on)) < 0)
                 error("setsockopt SO_KEEPALIVE: %.100s", strerror(errno));                  error("setsockopt SO_KEEPALIVE: %.100s", strerror(errno));
Line 518 
Line 441 
             compat20 ? PROTOCOL_MAJOR_2 : PROTOCOL_MAJOR_1,              compat20 ? PROTOCOL_MAJOR_2 : PROTOCOL_MAJOR_1,
             compat20 ? PROTOCOL_MINOR_2 : minor1,              compat20 ? PROTOCOL_MINOR_2 : minor1,
             SSH_VERSION);              SSH_VERSION);
         if (atomicio(vwrite, connection_out, buf, strlen(buf)) != strlen(buf))          if (atomicio(write, connection_out, buf, strlen(buf)) != strlen(buf))
                 fatal("write: %.100s", strerror(errno));                  fatal("write: %.100s", strerror(errno));
         client_version_string = xstrdup(buf);          client_version_string = xstrdup(buf);
         chop(client_version_string);          chop(client_version_string);
Line 560 
Line 483 
     int readonly, const char *user_hostfile, const char *system_hostfile)      int readonly, const char *user_hostfile, const char *system_hostfile)
 {  {
         Key *file_key;          Key *file_key;
         const char *type = key_type(host_key);          char *type = key_type(host_key);
         char *ip = NULL;          char *ip = NULL;
         char hostline[1000], *hostp, *fp;          char hostline[1000], *hostp, *fp;
         HostStatus host_status;          HostStatus host_status;
Line 568 
Line 491 
         int local = 0, host_ip_differ = 0;          int local = 0, host_ip_differ = 0;
         char ntop[NI_MAXHOST];          char ntop[NI_MAXHOST];
         char msg[1024];          char msg[1024];
         int len, host_line, ip_line;          int len, host_line, ip_line, has_keys;
         const char *host_file = NULL, *ip_file = NULL;          const char *host_file = NULL, *ip_file = NULL;
   
         /*          /*
Line 709 
Line 632 
                             "have requested strict checking.", type, host);                              "have requested strict checking.", type, host);
                         goto fail;                          goto fail;
                 } else if (options.strict_host_key_checking == 2) {                  } else if (options.strict_host_key_checking == 2) {
                         char msg1[1024], msg2[1024];                          has_keys = show_other_keys(host, host_key);
   
                         if (show_other_keys(host, host_key))  
                                 snprintf(msg1, sizeof(msg1),  
                                    "\nbut keys of different type are already"  
                                    " known for this host.");  
                         else  
                                 snprintf(msg1, sizeof(msg1), ".");  
                         /* The default */                          /* The default */
                         fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX);                          fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX);
                         msg2[0] = '\0';  
                         if (options.verify_host_key_dns) {  
                                 if (matching_host_key_dns)  
                                         snprintf(msg2, sizeof(msg2),  
                                             "Matching host key fingerprint"  
                                             " found in DNS.\n");  
                                 else  
                                         snprintf(msg2, sizeof(msg2),  
                                             "No matching host key fingerprint"  
                                             " found in DNS.\n");  
                         }  
                         snprintf(msg, sizeof(msg),                          snprintf(msg, sizeof(msg),
                             "The authenticity of host '%.200s (%s)' can't be "                              "The authenticity of host '%.200s (%s)' can't be "
                             "established%s\n"                              "established%s\n"
                             "%s key fingerprint is %s.\n%s"                              "%s key fingerprint is %s.\n"
                             "Are you sure you want to continue connecting "                              "Are you sure you want to continue connecting "
                             "(yes/no)? ",                              "(yes/no)? ",
                             host, ip, msg1, type, fp, msg2);                              host, ip,
                               has_keys ? ",\nbut keys of different type are already "
                               "known for this host." : ".",
                               type, fp);
                         xfree(fp);                          xfree(fp);
                         if (!confirm(msg))                          if (!confirm(msg))
                                 goto fail;                                  goto fail;
Line 779 
Line 687 
                                 error("Offending key for IP in %s:%d", ip_file, ip_line);                                  error("Offending key for IP in %s:%d", ip_file, ip_line);
                 }                  }
                 /* The host key has changed. */                  /* The host key has changed. */
                 warn_changed_key(host_key);                  fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX);
                   error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
                   error("@    WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!     @");
                   error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
                   error("IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!");
                   error("Someone could be eavesdropping on you right now (man-in-the-middle attack)!");
                   error("It is also possible that the %s host key has just been changed.", type);
                   error("The fingerprint for the %s key sent by the remote host is\n%s.",
                       type, fp);
                   error("Please contact your system administrator.");
                 error("Add correct host key in %.100s to get rid of this message.",                  error("Add correct host key in %.100s to get rid of this message.",
                     user_hostfile);                      user_hostfile);
                 error("Offending key in %s:%d", host_file, host_line);                  error("Offending key in %s:%d", host_file, host_line);
                   xfree(fp);
   
                 /*                  /*
                  * If strict host key checking is in use, the user will have                   * If strict host key checking is in use, the user will have
Line 796 
Line 714 
   
                 /*                  /*
                  * If strict host key checking has not been requested, allow                   * If strict host key checking has not been requested, allow
                  * the connection but without MITM-able authentication or                   * the connection but without password authentication or
                  * agent forwarding.                   * agent forwarding.
                  */                   */
                 if (options.password_authentication) {                  if (options.password_authentication) {
Line 804 
Line 722 
                             "man-in-the-middle attacks.");                              "man-in-the-middle attacks.");
                         options.password_authentication = 0;                          options.password_authentication = 0;
                 }                  }
                 if (options.kbd_interactive_authentication) {  
                         error("Keyboard-interactive authentication is disabled"  
                             " to avoid man-in-the-middle attacks.");  
                         options.kbd_interactive_authentication = 0;  
                         options.challenge_response_authentication = 0;  
                 }  
                 if (options.challenge_response_authentication) {  
                         error("Challenge/response authentication is disabled"  
                             " to avoid man-in-the-middle attacks.");  
                         options.challenge_response_authentication = 0;  
                 }  
                 if (options.forward_agent) {                  if (options.forward_agent) {
                         error("Agent forwarding is disabled to avoid "                          error("Agent forwarding is disabled to avoid "
                             "man-in-the-middle attacks.");                              "man-in-the-middle attacks.");
Line 859 
Line 766 
                             host_file, host_line);                              host_file, host_line);
                 }                  }
                 if (options.strict_host_key_checking == 1) {                  if (options.strict_host_key_checking == 1) {
                         logit("%s", msg);                          logit(msg);
                         error("Exiting, you have requested strict checking.");                          error("Exiting, you have requested strict checking.");
                         goto fail;                          goto fail;
                 } else if (options.strict_host_key_checking == 2) {                  } else if (options.strict_host_key_checking == 2) {
Line 868 
Line 775 
                         if (!confirm(msg))                          if (!confirm(msg))
                                 goto fail;                                  goto fail;
                 } else {                  } else {
                         logit("%s", msg);                          logit(msg);
                 }                  }
         }          }
   
Line 880 
Line 787 
         return -1;          return -1;
 }  }
   
 /* returns 0 if key verifies or -1 if key does NOT verify */  
 int  int
 verify_host_key(char *host, struct sockaddr *hostaddr, Key *host_key)  verify_host_key(char *host, struct sockaddr *hostaddr, Key *host_key)
 {  {
         struct stat st;          struct stat st;
         int flags = 0;  
   
         if (options.verify_host_key_dns &&  
             verify_host_key_dns(host, hostaddr, host_key, &flags) == 0) {  
   
                 if (flags & DNS_VERIFY_FOUND) {  
   
                         if (options.verify_host_key_dns == 1 &&  
                             flags & DNS_VERIFY_MATCH &&  
                             flags & DNS_VERIFY_SECURE)  
                                 return 0;  
   
                         if (flags & DNS_VERIFY_MATCH) {  
                                 matching_host_key_dns = 1;  
                         } else {  
                                 warn_changed_key(host_key);  
                                 error("Update the SSHFP RR in DNS with the new "  
                                     "host key to get rid of this message.");  
                         }  
                 }  
         }  
   
         /* return ok if the key can be found in an old keyfile */          /* return ok if the key can be found in an old keyfile */
         if (stat(options.system_hostfile2, &st) == 0 ||          if (stat(options.system_hostfile2, &st) == 0 ||
             stat(options.user_hostfile2, &st) == 0) {              stat(options.user_hostfile2, &st) == 0) {
Line 1030 
Line 915 
                 debug2("no key of type %d for host %s", type[i], host);                  debug2("no key of type %d for host %s", type[i], host);
         }          }
         return (found);          return (found);
 }  
   
 static void  
 warn_changed_key(Key *host_key)  
 {  
         char *fp;  
         const char *type = key_type(host_key);  
   
         fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX);  
   
         error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");  
         error("@    WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!     @");  
         error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");  
         error("IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!");  
         error("Someone could be eavesdropping on you right now (man-in-the-middle attack)!");  
         error("It is also possible that the %s host key has just been changed.", type);  
         error("The fingerprint for the %s key sent by the remote host is\n%s.",  
             type, fp);  
         error("Please contact your system administrator.");  
   
         xfree(fp);  
 }  }

Legend:
Removed from v.1.137.2.2  
changed lines
  Added in v.1.138