[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.79 and 1.79.2.3

version 1.79, 2000/09/17 15:52:51 version 1.79.2.3, 2001/03/21 19:46:30
Line 16 
Line 16 
 RCSID("$OpenBSD$");  RCSID("$OpenBSD$");
   
 #include <openssl/bn.h>  #include <openssl/bn.h>
 #include <openssl/dsa.h>  
 #include <openssl/rsa.h>  
   
   #include "ssh.h"
 #include "xmalloc.h"  #include "xmalloc.h"
 #include "rsa.h"  #include "rsa.h"
 #include "ssh.h"  
 #include "buffer.h"  #include "buffer.h"
 #include "packet.h"  #include "packet.h"
 #include "uidswap.h"  #include "uidswap.h"
 #include "compat.h"  #include "compat.h"
 #include "readconf.h"  
 #include "key.h"  #include "key.h"
 #include "sshconnect.h"  #include "sshconnect.h"
 #include "hostfile.h"  #include "hostfile.h"
   #include "log.h"
   #include "readconf.h"
   #include "atomicio.h"
   #include "misc.h"
   
 char *client_version_string = NULL;  char *client_version_string = NULL;
 char *server_version_string = NULL;  char *server_version_string = NULL;
Line 37 
Line 38 
 extern Options options;  extern Options options;
 extern char *__progname;  extern char *__progname;
   
   /* AF_UNSPEC or AF_INET or AF_INET6 */
   extern int IPv4or6;
   
 /*  /*
  * Connect to the given ssh server using a proxy command.   * Connect to the given ssh server using a proxy command.
  */   */
Line 109 
Line 113 
   
                 /* Stderr is left as it is so that error messages get                  /* Stderr is left as it is so that error messages get
                    printed on the user's terminal. */                     printed on the user's terminal. */
                 argv[0] = "/bin/sh";                  argv[0] = _PATH_BSHELL;
                 argv[1] = "-c";                  argv[1] = "-c";
                 argv[2] = command_string;                  argv[2] = command_string;
                 argv[3] = NULL;                  argv[3] = NULL;
   
                 /* Execute the proxy command.  Note that we gave up any                  /* Execute the proxy command.  Note that we gave up any
                    extra privileges above. */                     extra privileges above. */
                 execv("/bin/sh", argv);                  execv(argv[0], argv);
                 perror("/bin/sh");                  perror(argv[0]);
                 exit(1);                  exit(1);
         }          }
         /* Parent. */          /* Parent. */
Line 187 
Line 191 
             int anonymous, uid_t original_real_uid,              int anonymous, uid_t original_real_uid,
             const char *proxy_command)              const char *proxy_command)
 {  {
           int gaierr;
           int on = 1;
         int sock = -1, attempt;          int sock = -1, attempt;
         struct servent *sp;  
         struct addrinfo hints, *ai, *aitop;  
         char ntop[NI_MAXHOST], strport[NI_MAXSERV];          char ntop[NI_MAXHOST], strport[NI_MAXSERV];
         int gaierr;          struct addrinfo hints, *ai, *aitop;
         struct linger linger;          struct linger linger;
           struct servent *sp;
   
         debug("ssh_connect: getuid %u geteuid %u anon %d",          debug("ssh_connect: getuid %u geteuid %u anon %d",
               (u_int) getuid(), (u_int) geteuid(), anonymous);                (u_int) getuid(), (u_int) geteuid(), anonymous);
Line 244 
Line 249 
   
                         /* Create a socket for connecting. */                          /* Create a socket for connecting. */
                         sock = ssh_create_socket(original_real_uid,                          sock = ssh_create_socket(original_real_uid,
                             !anonymous && geteuid() == 0 && port < IPPORT_RESERVED,                              !anonymous && geteuid() == 0,
                             ai->ai_family);                              ai->ai_family);
                         if (sock < 0)                          if (sock < 0)
                                 continue;                                  continue;
Line 294 
Line 299 
         /* setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *)&on, sizeof(on)); */          /* setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *)&on, sizeof(on)); */
         linger.l_onoff = 1;          linger.l_onoff = 1;
         linger.l_linger = 5;          linger.l_linger = 5;
         setsockopt(sock, SOL_SOCKET, SO_LINGER, (void *) &linger, sizeof(linger));          setsockopt(sock, SOL_SOCKET, SO_LINGER, (void *)&linger, sizeof(linger));
   
           /* Set keepalives if requested. */
           if (options.keepalives &&
               setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, (void *)&on,
               sizeof(on)) < 0)
                   error("setsockopt SO_KEEPALIVE: %.100s", strerror(errno));
   
         /* Set the connection. */          /* Set the connection. */
         packet_set_connection(sock, sock);          packet_set_connection(sock, sock);
   
Line 307 
Line 318 
  * identification string.   * identification string.
  */   */
 void  void
 ssh_exchange_identification()  ssh_exchange_identification(void)
 {  {
         char buf[256], remote_version[256];     /* must be same size! */          char buf[256], remote_version[256];     /* must be same size! */
         int remote_major, remote_minor, i, mismatch;          int remote_major, remote_minor, i, mismatch;
         int connection_in = packet_get_connection_in();          int connection_in = packet_get_connection_in();
         int connection_out = packet_get_connection_out();          int connection_out = packet_get_connection_out();
           int minor1 = PROTOCOL_MINOR_1;
   
         /* Read other side\'s version identification. */          /* Read other side\'s version identification. */
         for (;;) {          for (;;) {
Line 366 
Line 378 
                 }                  }
                 if (remote_minor < 3) {                  if (remote_minor < 3) {
                         fatal("Remote machine has too old SSH software version.");                          fatal("Remote machine has too old SSH software version.");
                 } else if (remote_minor == 3) {                  } else if (remote_minor == 3 || remote_minor == 4) {
                         /* We speak 1.3, too. */                          /* We speak 1.3, too. */
                         enable_compat13();                          enable_compat13();
                           minor1 = 3;
                         if (options.forward_agent) {                          if (options.forward_agent) {
                                 log("Agent forwarding disabled for protocol 1.3");                                  log("Agent forwarding disabled for protocol 1.3");
                                 options.forward_agent = 0;                                  options.forward_agent = 0;
Line 394 
Line 407 
         /* Send our own protocol version identification. */          /* Send our own protocol version identification. */
         snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s\n",          snprintf(buf, sizeof buf, "SSH-%d.%d-%.100s\n",
             compat20 ? PROTOCOL_MAJOR_2 : PROTOCOL_MAJOR_1,              compat20 ? PROTOCOL_MAJOR_2 : PROTOCOL_MAJOR_1,
             compat20 ? PROTOCOL_MINOR_2 : PROTOCOL_MINOR_1,              compat20 ? PROTOCOL_MINOR_2 : minor1,
             SSH_VERSION);              SSH_VERSION);
         if (atomicio(write, 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));
Line 404 
Line 417 
         debug("Local version string %.100s", client_version_string);          debug("Local version string %.100s", client_version_string);
 }  }
   
   /* defaults to 'no' */
 int  int
 read_yes_or_no(const char *prompt, int defval)  read_yes_or_no(const char *prompt, int defval)
 {  {
Line 411 
Line 425 
         FILE *f;          FILE *f;
         int retval = -1;          int retval = -1;
   
         if (isatty(0))          if (options.batch_mode)
                   return 0;
   
           if (isatty(STDIN_FILENO))
                 f = stdin;                  f = stdin;
         else          else
                 f = fopen("/dev/tty", "rw");                  f = fopen(_PATH_TTY, "rw");
   
         if (f == NULL)          if (f == NULL)
                 return 0;                  return 0;
Line 460 
Line 477 
         Key *file_key;          Key *file_key;
         char *type = key_type(host_key);          char *type = key_type(host_key);
         char *ip = NULL;          char *ip = NULL;
         char hostline[1000], *hostp;          char hostline[1000], *hostp, *fp;
         HostStatus host_status;          HostStatus host_status;
         HostStatus ip_status;          HostStatus ip_status;
         int local = 0, host_ip_differ = 0;          int local = 0, host_ip_differ = 0;
         char ntop[NI_MAXHOST];          char ntop[NI_MAXHOST];
           int host_line, ip_line;
           const char *host_file = NULL, *ip_file = NULL;
   
         /*          /*
          * Force accepting of the host key for loopback/localhost. The           * Force accepting of the host key for loopback/localhost. The
Line 486 
Line 505 
                 local = 0;                  local = 0;
                 break;                  break;
         }          }
         if (local) {          if (local && options.host_key_alias == NULL) {
                 debug("Forcing accepting of host key for loopback/localhost.");                  debug("Forcing accepting of host key for "
                       "loopback/localhost.");
                 return;                  return;
         }          }
   
         /*          /*
          * Turn off check_host_ip for proxy connects, since           * We don't have the remote ip-address for connections
          * we don't have the remote ip-address           * using a proxy command
          */           */
         if (options.proxy_command != NULL && options.check_host_ip)          if (options.proxy_command == NULL) {
                 options.check_host_ip = 0;  
   
         if (options.check_host_ip) {  
                 if (getnameinfo(hostaddr, hostaddr->sa_len, ntop, sizeof(ntop),                  if (getnameinfo(hostaddr, hostaddr->sa_len, ntop, sizeof(ntop),
                     NULL, 0, NI_NUMERICHOST) != 0)                      NULL, 0, NI_NUMERICHOST) != 0)
                         fatal("check_host_key: getnameinfo failed");                          fatal("check_host_key: getnameinfo failed");
                 ip = xstrdup(ntop);                  ip = xstrdup(ntop);
           } else {
                   ip = xstrdup("<no hostip for proxy command>");
         }          }
           /*
            * Turn off check_host_ip if the connection is to localhost, via proxy
            * command or if we don't have a hostname to compare with
            */
           if (options.check_host_ip &&
               (local || strcmp(host, ip) == 0 || options.proxy_command != NULL))
                   options.check_host_ip = 0;
   
         /*          /*
            * Allow the user to record the key under a different name. This is
            * useful for ssh tunneling over forwarded connections or if you run
            * multiple sshd's on different ports on the same machine.
            */
           if (options.host_key_alias != NULL) {
                   host = options.host_key_alias;
                   debug("using hostkeyalias: %s", host);
           }
   
           /*
          * Store the host key from the known host file in here so that we can           * Store the host key from the known host file in here so that we can
          * compare it with the key for the IP address.           * compare it with the key for the IP address.
          */           */
Line 515 
Line 551 
          * Check if the host key is present in the user\'s list of known           * Check if the host key is present in the user\'s list of known
          * hosts or in the systemwide list.           * hosts or in the systemwide list.
          */           */
         host_status = check_host_in_hostfile(user_hostfile, host, host_key, file_key);          host_file = user_hostfile;
         if (host_status == HOST_NEW)          host_status = check_host_in_hostfile(host_file, host, host_key, file_key, &host_line);
                 host_status = check_host_in_hostfile(system_hostfile, host, host_key, file_key);          if (host_status == HOST_NEW) {
                   host_file = system_hostfile;
                   host_status = check_host_in_hostfile(host_file, host, host_key, file_key, &host_line);
           }
         /*          /*
          * Also perform check for the ip address, skip the check if we are           * Also perform check for the ip address, skip the check if we are
          * localhost or the hostname was an ip address to begin with           * localhost or the hostname was an ip address to begin with
          */           */
         if (options.check_host_ip && !local && strcmp(host, ip)) {          if (options.check_host_ip) {
                 Key *ip_key = key_new(host_key->type);                  Key *ip_key = key_new(host_key->type);
                 ip_status = check_host_in_hostfile(user_hostfile, ip, host_key, ip_key);  
   
                 if (ip_status == HOST_NEW)                  ip_file = user_hostfile;
                         ip_status = check_host_in_hostfile(system_hostfile, ip, host_key, ip_key);                  ip_status = check_host_in_hostfile(ip_file, ip, host_key, ip_key, &ip_line);
                   if (ip_status == HOST_NEW) {
                           ip_file = system_hostfile;
                           ip_status = check_host_in_hostfile(ip_file, ip, host_key, ip_key, &ip_line);
                   }
                 if (host_status == HOST_CHANGED &&                  if (host_status == HOST_CHANGED &&
                     (ip_status != HOST_CHANGED || !key_equal(ip_key, file_key)))                      (ip_status != HOST_CHANGED || !key_equal(ip_key, file_key)))
                         host_ip_differ = 1;                          host_ip_differ = 1;
Line 543 
Line 585 
                 /* The host is known and the key matches. */                  /* The host is known and the key matches. */
                 debug("Host '%.200s' is known and matches the %s host key.",                  debug("Host '%.200s' is known and matches the %s host key.",
                     host, type);                      host, type);
                 if (options.check_host_ip) {                  debug("Found key in %s:%d", host_file, host_line);
                         if (ip_status == HOST_NEW) {                  if (options.check_host_ip && ip_status == HOST_NEW) {
                                 if (!add_host_to_hostfile(user_hostfile, ip, host_key))                          if (!add_host_to_hostfile(user_hostfile, ip, host_key))
                                         log("Failed to add the %s host key for IP address '%.30s' to the list of known hosts (%.30s).",                                  log("Failed to add the %s host key for IP address '%.128s' to the list of known hosts (%.30s).",
                                             type, ip, user_hostfile);                                      type, ip, user_hostfile);
                                 else                          else
                                         log("Warning: Permanently added the %s host key for IP address '%.30s' to the list of known hosts.",                                  log("Warning: Permanently added the %s host key for IP address '%.128s' to the list of known hosts.",
                                             type, ip);                                      type, ip);
                         } else if (ip_status != HOST_OK)  
                                 log("Warning: the %s host key for '%.200s' differs from the key for the IP address '%.30s'",  
                                     type, host, ip);  
                 }                  }
                 break;                  break;
         case HOST_NEW:          case HOST_NEW:
Line 565 
Line 604 
                 } else if (options.strict_host_key_checking == 2) {                  } else if (options.strict_host_key_checking == 2) {
                         /* The default */                          /* The default */
                         char prompt[1024];                          char prompt[1024];
                         char *fp = key_fingerprint(host_key);                          fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX);
                         snprintf(prompt, sizeof(prompt),                          snprintf(prompt, sizeof(prompt),
                             "The authenticity of host '%.200s' can't be established.\n"                              "The authenticity of host '%.200s (%s)' can't be established.\n"
                             "%s key fingerprint is %s.\n"                              "%s key fingerprint is %s.\n"
                             "Are you sure you want to continue connecting (yes/no)? ",                              "Are you sure you want to continue connecting (yes/no)? ",
                             host, type, fp);                              host, ip, type, fp);
                           xfree(fp);
                         if (!read_yes_or_no(prompt, -1))                          if (!read_yes_or_no(prompt, -1))
                                 fatal("Aborted by user!\n");                                  fatal("Aborted by user!");
                 }                  }
                 if (options.check_host_ip && ip_status == HOST_NEW && strcmp(host, ip)) {                  if (options.check_host_ip && ip_status == HOST_NEW) {
                         snprintf(hostline, sizeof(hostline), "%s,%s", host, ip);                          snprintf(hostline, sizeof(hostline), "%s,%s", host, ip);
                         hostp = hostline;                          hostp = hostline;
                 } else                  } else
Line 604 
Line 644 
                         error("and the key for the according IP address %s", ip);                          error("and the key for the according IP address %s", ip);
                         error("%s. This could either mean that", msg);                          error("%s. This could either mean that", msg);
                         error("DNS SPOOFING is happening or the IP address for the host");                          error("DNS SPOOFING is happening or the IP address for the host");
                         error("and its host key have changed at the same time");                          error("and its host key have changed at the same time.");
                           if (ip_status != HOST_NEW)
                                   error("Offending key for IP in %s:%d", ip_file, ip_line);
                 }                  }
                 /* The host key has changed. */                  /* The host key has changed. */
                   fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX);
                 error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");                  error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
                 error("@    WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!     @");                  error("@    WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!     @");
                 error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");                  error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
                 error("IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!");                  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("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("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("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);
                   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 637 
Line 684 
                         error("Agent forwarding is disabled to avoid trojan horses.");                          error("Agent forwarding is disabled to avoid trojan horses.");
                         options.forward_agent = 0;                          options.forward_agent = 0;
                 }                  }
                   if (options.forward_x11) {
                           error("X11 forwarding is disabled to avoid trojan horses.");
                           options.forward_x11 = 0;
                   }
                   if (options.num_local_forwards > 0 || options.num_remote_forwards > 0) {
                           error("Port forwarding is disabled to avoid trojan horses.");
                           options.num_local_forwards = options.num_remote_forwards = 0;
                   }
                 /*                  /*
                  * XXX Should permit the user to change to use the new id.                   * XXX Should permit the user to change to use the new id.
                  * This could be done by converting the host key to an                   * This could be done by converting the host key to an
Line 646 
Line 701 
                  */                   */
                 break;                  break;
         }          }
         if (options.check_host_ip)  
                 xfree(ip);          if (options.check_host_ip && host_status != HOST_CHANGED &&
               ip_status == HOST_CHANGED) {
                   log("Warning: the %s host key for '%.200s' "
                       "differs from the key for the IP address '%.128s'",
                       type, host, ip);
                   if (host_status == HOST_OK)
                           log("Matching host key in %s:%d", host_file, host_line);
                   log("Offending key for IP in %s:%d", ip_file, ip_line);
                   if (options.strict_host_key_checking == 1) {
                           fatal("Exiting, you have requested strict checking.");
                   } else if (options.strict_host_key_checking == 2) {
                           if (!read_yes_or_no("Are you sure you want " \
                               "to continue connecting (yes/no)? ", -1))
                                   fatal("Aborted by user!");
                   }
           }
   
           xfree(ip);
 }  }
   
 /*  /*
Line 693 
Line 765 
                 ssh_kex(host, hostaddr);                  ssh_kex(host, hostaddr);
                 ssh_userauth(local_user, server_user, host, host_key_valid, own_host_key);                  ssh_userauth(local_user, server_user, host, host_key_valid, own_host_key);
         }          }
   }
   
   void
   ssh_put_password(char *password)
   {
           int size;
           char *padded;
   
           if (datafellows & SSH_BUG_PASSWORDPAD) {
                   packet_put_string(password, strlen(password));
                   return;
           }
           size = roundup(strlen(password) + 1, 32);
           padded = xmalloc(size);
           memset(padded, 0, size);
           strlcpy(padded, password, size);
           packet_put_string(padded, size);
           memset(padded, 0, size);
           xfree(padded);
 }  }

Legend:
Removed from v.1.79  
changed lines
  Added in v.1.79.2.3