[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.168 and 1.168.2.2

version 1.168, 2005/07/17 07:17:55 version 1.168.2.2, 2006/10/06 03:19:33
Line 1 
Line 1 
   /* $OpenBSD$ */
 /*  /*
  * 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
Line 12 
Line 13 
  * called by a name other than "ssh" or "Secure Shell".   * called by a name other than "ssh" or "Secure Shell".
  */   */
   
 #include "includes.h"  #include <sys/types.h>
 RCSID("$OpenBSD$");  #include <sys/wait.h>
   #include <sys/stat.h>
   #include <sys/socket.h>
   #include <sys/time.h>
   
 #include <openssl/bn.h>  #include <netinet/in.h>
   
 #include "ssh.h"  #include <ctype.h>
   #include <errno.h>
   #include <netdb.h>
   #include <paths.h>
   #include <signal.h>
   #include <pwd.h>
   #include <stdio.h>
   #include <stdlib.h>
   #include <string.h>
   #include <unistd.h>
   
 #include "xmalloc.h"  #include "xmalloc.h"
   #include "ssh.h"
 #include "rsa.h"  #include "rsa.h"
 #include "buffer.h"  #include "buffer.h"
 #include "packet.h"  #include "packet.h"
Line 31 
Line 46 
 #include "readconf.h"  #include "readconf.h"
 #include "atomicio.h"  #include "atomicio.h"
 #include "misc.h"  #include "misc.h"
   
 #include "dns.h"  #include "dns.h"
   #include "version.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;  static int matching_host_key_dns = 0;
   
 /* import */  /* import */
 extern Options options;  extern Options options;
Line 59 
Line 74 
         int pin[2], pout[2];          int pin[2], pout[2];
         pid_t pid;          pid_t pid;
         char strport[NI_MAXSERV];          char strport[NI_MAXSERV];
         size_t len;  
   
         /* Convert the port number into a string. */          /* Convert the port number into a string. */
         snprintf(strport, sizeof strport, "%hu", port);          snprintf(strport, sizeof strport, "%hu", port);
Line 71 
Line 85 
          * 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)
          */           */
         len = strlen(proxy_command) + 6;          xasprintf(&tmp, "exec %s", proxy_command);
         tmp = xmalloc(len);  
         strlcpy(tmp, "exec ", len);  
         strlcat(tmp, proxy_command, len);  
         command_string = percent_expand(tmp, "h", host,          command_string = percent_expand(tmp, "h", host,
             "p", strport, (char *)NULL);              "p", strport, (char *)NULL);
         xfree(tmp);          xfree(tmp);
Line 91 
Line 102 
                 char *argv[10];                  char *argv[10];
   
                 /* Child.  Permanently give up superuser privileges. */                  /* Child.  Permanently give up superuser privileges. */
                 seteuid(original_real_uid);                  permanently_drop_suid(original_real_uid);
                 setuid(original_real_uid);  
   
                 /* Redirect stdin and stdout. */                  /* Redirect stdin and stdout. */
                 close(pin[1]);                  close(pin[1]);
Line 202 
Line 212 
         fd_set *fdset;          fd_set *fdset;
         struct timeval tv;          struct timeval tv;
         socklen_t optlen;          socklen_t optlen;
         int fdsetsz, optval, rc, result = -1;          int optval, rc, result = -1;
   
         if (timeout <= 0)          if (timeout <= 0)
                 return (connect(sockfd, serv_addr, addrlen));                  return (connect(sockfd, serv_addr, addrlen));
Line 216 
Line 226 
         if (errno != EINPROGRESS)          if (errno != EINPROGRESS)
                 return (-1);                  return (-1);
   
         fdsetsz = howmany(sockfd + 1, NFDBITS) * sizeof(fd_mask);          fdset = (fd_set *)xcalloc(howmany(sockfd + 1, NFDBITS),
         fdset = (fd_set *)xmalloc(fdsetsz);              sizeof(fd_mask));
   
         memset(fdset, 0, fdsetsz);  
         FD_SET(sockfd, fdset);          FD_SET(sockfd, fdset);
         tv.tv_sec = timeout;          tv.tv_sec = timeout;
         tv.tv_usec = 0;          tv.tv_usec = 0;
Line 302 
Line 310 
                 fatal("%s: %.100s: %s", __progname, host,                  fatal("%s: %.100s: %s", __progname, host,
                     gai_strerror(gaierr));                      gai_strerror(gaierr));
   
         /*          for (attempt = 0; attempt < connection_attempts; attempt++) {
          * Try to connect several times.  On some machines, the first time  
          * will sometimes fail.  In general socket code appears to behave  
          * quite magically on many machines.  
                  */  
         for (attempt = 0; ;) {  
                 if (attempt > 0)                  if (attempt > 0)
                         debug("Trying again...");                          debug("Trying again...");
   
                 /* Loop through addresses for this host, and try each one in                  /*
                    sequence until the connection succeeds. */                   * Loop through addresses for this host, and try each one in
                    * sequence until the connection succeeds.
                    */
                 for (ai = aitop; ai; ai = ai->ai_next) {                  for (ai = aitop; ai; ai = ai->ai_next) {
                         if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6)                          if (ai->ai_family != AF_INET && ai->ai_family != AF_INET6)
                                 continue;                                  continue;
Line 339 
Line 344 
                         } else {                          } else {
                                 debug("connect to address %s port %s: %s",                                  debug("connect to address %s port %s: %s",
                                     ntop, strport, strerror(errno));                                      ntop, strport, strerror(errno));
                                 /*  
                                  * Close the failed socket; there appear to  
                                  * be some problems when reusing a socket for  
                                  * which connect() has already returned an  
                                  * error.  
                                  */  
                                 close(sock);                                  close(sock);
                                   sock = -1;
                         }                          }
                 }                  }
                 if (ai)                  if (sock != -1)
                         break;  /* Successful connection. */                          break;  /* Successful connection. */
   
                 attempt++;  
                 if (attempt >= connection_attempts)  
                         break;  
                 /* Sleep a moment before retrying. */                  /* Sleep a moment before retrying. */
                 sleep(1);                  sleep(1);
         }          }
Line 361 
Line 358 
         freeaddrinfo(aitop);          freeaddrinfo(aitop);
   
         /* Return failure if we didn't get a successful connection. */          /* Return failure if we didn't get a successful connection. */
         if (attempt >= connection_attempts) {          if (sock == -1) {
                 error("ssh: connect to host %s port %s: %s",                  error("ssh: connect to host %s port %s: %s",
                     host, strport, strerror(errno));                      host, strport, strerror(errno));
                 return (-1);                  return (-1);
Line 393 
Line 390 
         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;          int minor1 = PROTOCOL_MINOR_1;
         u_int i;          u_int i, n;
   
         /* Read other side's version identification. */          /* Read other side's version identification. */
         for (;;) {          for (n = 0;;) {
                 for (i = 0; i < sizeof(buf) - 1; i++) {                  for (i = 0; i < sizeof(buf) - 1; i++) {
                         size_t len = atomicio(read, connection_in, &buf[i], 1);                          size_t len = atomicio(read, connection_in, &buf[i], 1);
   
Line 413 
Line 410 
                                 buf[i + 1] = 0;                                  buf[i + 1] = 0;
                                 break;                                  break;
                         }                          }
                           if (++n > 65536)
                                   fatal("ssh_exchange_identification: No banner received");
                 }                  }
                 buf[sizeof(buf) - 1] = 0;                  buf[sizeof(buf) - 1] = 0;
                 if (strncmp(buf, "SSH-", 4) == 0)                  if (strncmp(buf, "SSH-", 4) == 0)
Line 514 
Line 513 
  * check whether the supplied host key is valid, return -1 if the key   * check whether the supplied host key is valid, return -1 if the key
  * is not valid. the user_hostfile will not be updated if 'readonly' is true.   * is not valid. the user_hostfile will not be updated if 'readonly' is true.
  */   */
   #define RDRW    0
   #define RDONLY  1
   #define ROQUIET 2
 static int  static int
 check_host_key(char *host, struct sockaddr *hostaddr, Key *host_key,  check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port,
     int readonly, const char *user_hostfile, const char *system_hostfile)      Key *host_key, int readonly, const char *user_hostfile,
       const char *system_hostfile)
 {  {
         Key *file_key;          Key *file_key;
         const char *type = key_type(host_key);          const char *type = key_type(host_key);
         char *ip = NULL;          char *ip = NULL, *host = NULL;
         char hostline[1000], *hostp, *fp;          char hostline[1000], *hostp, *fp;
         HostStatus host_status;          HostStatus host_status;
         HostStatus ip_status;          HostStatus ip_status;
Line 567 
Line 570 
                 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 = put_host_port(ntop, port);
         } else {          } else {
                 ip = xstrdup("<no hostip for proxy command>");                  ip = xstrdup("<no hostip for proxy command>");
         }          }
Line 575 
Line 578 
          * Turn off check_host_ip if the connection is to localhost, via proxy           * 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           * command or if we don't have a hostname to compare with
          */           */
         if (options.check_host_ip &&          if (options.check_host_ip && (local ||
             (local || strcmp(host, ip) == 0 || options.proxy_command != NULL))              strcmp(hostname, ip) == 0 || options.proxy_command != NULL))
                 options.check_host_ip = 0;                  options.check_host_ip = 0;
   
         /*          /*
          * Allow the user to record the key under a different name. This is           * Allow the user to record the key under a different name or
          * useful for ssh tunneling over forwarded connections or if you run           * differentiate a non-standard port.  This is useful for ssh
          * multiple sshd's on different ports on the same machine.           * tunneling over forwarded connections or if you run multiple
            * sshd's on different ports on the same machine.
          */           */
         if (options.host_key_alias != NULL) {          if (options.host_key_alias != NULL) {
                 host = options.host_key_alias;                  host = xstrdup(options.host_key_alias);
                 debug("using hostkeyalias: %s", host);                  debug("using hostkeyalias: %s", host);
           } else {
                   host = put_host_port(hostname, port);
         }          }
   
         /*          /*
Line 596 
Line 602 
         file_key = key_new(host_key->type);          file_key = key_new(host_key->type);
   
         /*          /*
          * 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_file = user_hostfile;          host_file = user_hostfile;
Line 655 
Line 661 
                 }                  }
                 break;                  break;
         case HOST_NEW:          case HOST_NEW:
                   if (options.host_key_alias == NULL && port != 0 &&
                       port != SSH_DEFAULT_PORT) {
                           debug("checking without port identifier");
                           if (check_host_key(hostname, hostaddr, 0, host_key, 2,
                               user_hostfile, system_hostfile) == 0) {
                                   debug("found matching key w/out port");
                                   break;
                           }
                   }
                 if (readonly)                  if (readonly)
                         goto fail;                          goto fail;
                 /* The host is new. */                  /* The host is new. */
Line 734 
Line 749 
                             "list of known hosts.", hostp, type);                              "list of known hosts.", hostp, type);
                 break;                  break;
         case HOST_CHANGED:          case HOST_CHANGED:
                   if (readonly == ROQUIET)
                           goto fail;
                 if (options.check_host_ip && host_ip_differ) {                  if (options.check_host_ip && host_ip_differ) {
                         char *key_msg;                          char *key_msg;
                         if (ip_status == HOST_NEW)                          if (ip_status == HOST_NEW)
Line 772 
Line 789 
                 /*                  /*
                  * 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 MITM-able authentication or
                  * agent forwarding.                   * forwarding.
                  */                   */
                 if (options.password_authentication) {                  if (options.password_authentication) {
                         error("Password authentication is disabled to avoid "                          error("Password authentication is disabled to avoid "
Line 807 
Line 824 
                         options.num_local_forwards =                          options.num_local_forwards =
                             options.num_remote_forwards = 0;                              options.num_remote_forwards = 0;
                 }                  }
                   if (options.tun_open != SSH_TUNMODE_NO) {
                           error("Tunnel forwarding is disabled to avoid "
                               "man-in-the-middle attacks.");
                           options.tun_open = SSH_TUNMODE_NO;
                   }
                 /*                  /*
                  * 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 848 
Line 870 
         }          }
   
         xfree(ip);          xfree(ip);
           xfree(host);
         return 0;          return 0;
   
 fail:  fail:
         xfree(ip);          xfree(ip);
           xfree(host);
         return -1;          return -1;
 }  }
   
Line 885 
Line 909 
         /* 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) {
                 if (check_host_key(host, hostaddr, host_key, /*readonly*/ 1,                  if (check_host_key(host, hostaddr, options.port, host_key,
                     options.user_hostfile2, options.system_hostfile2) == 0)                      RDONLY, options.user_hostfile2,
                       options.system_hostfile2) == 0)
                         return 0;                          return 0;
         }          }
         return check_host_key(host, hostaddr, host_key, /*readonly*/ 0,          return check_host_key(host, hostaddr, options.port, host_key,
             options.user_hostfile, options.system_hostfile);              RDRW, options.user_hostfile, options.system_hostfile);
 }  }
   
 /*  /*
Line 914 
Line 939 
         host = xstrdup(orighost);          host = xstrdup(orighost);
         for (cp = host; *cp; cp++)          for (cp = host; *cp; cp++)
                 if (isupper(*cp))                  if (isupper(*cp))
                         *cp = tolower(*cp);                          *cp = (char)tolower(*cp);
   
         /* Exchange protocol version identification strings with the server. */          /* Exchange protocol version identification strings with the server. */
         ssh_exchange_identification();          ssh_exchange_identification();
Line 931 
Line 956 
                 ssh_kex(host, hostaddr);                  ssh_kex(host, hostaddr);
                 ssh_userauth1(local_user, server_user, host, sensitive);                  ssh_userauth1(local_user, server_user, host, sensitive);
         }          }
           xfree(local_user);
 }  }
   
 void  void
Line 944 
Line 970 
                 return;                  return;
         }          }
         size = roundup(strlen(password) + 1, 32);          size = roundup(strlen(password) + 1, 32);
         padded = xmalloc(size);          padded = xcalloc(1, size);
         memset(padded, 0, size);  
         strlcpy(padded, password, size);          strlcpy(padded, password, size);
         packet_put_string(padded, size);          packet_put_string(padded, size);
         memset(padded, 0, size);          memset(padded, 0, size);
Line 1026 
Line 1051 
         error("Please contact your system administrator.");          error("Please contact your system administrator.");
   
         xfree(fp);          xfree(fp);
   }
   
   /*
    * Execute a local command
    */
   int
   ssh_local_cmd(const char *args)
   {
           char *shell;
           pid_t pid;
           int status;
   
           if (!options.permit_local_command ||
               args == NULL || !*args)
                   return (1);
   
           if ((shell = getenv("SHELL")) == NULL)
                   shell = _PATH_BSHELL;
   
           pid = fork();
           if (pid == 0) {
                   debug3("Executing %s -c \"%s\"", shell, args);
                   execl(shell, shell, "-c", args, (char *)NULL);
                   error("Couldn't execute %s -c \"%s\": %s",
                       shell, args, strerror(errno));
                   _exit(1);
           } else if (pid == -1)
                   fatal("fork failed: %.100s", strerror(errno));
           while (waitpid(pid, &status, 0) == -1)
                   if (errno != EINTR)
                           fatal("Couldn't wait for child: %s", strerror(errno));
   
           if (!WIFEXITED(status))
                   return (1);
   
           return (WEXITSTATUS(status));
 }  }

Legend:
Removed from v.1.168  
changed lines
  Added in v.1.168.2.2