[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.228 and 1.229

version 1.228, 2010/10/06 21:10:21 version 1.229, 2010/11/29 23:45:51
Line 65 
Line 65 
 extern uid_t original_real_uid;  extern uid_t original_real_uid;
 extern uid_t original_effective_uid;  extern uid_t original_effective_uid;
   
 static int show_other_keys(const char *, Key *);  static int show_other_keys(struct hostkeys *, Key *);
 static void warn_changed_key(Key *);  static void warn_changed_key(Key *);
   
 /*  /*
Line 597 
Line 597 
         return 1;          return 1;
 }  }
   
   static int
   sockaddr_is_local(struct sockaddr *hostaddr)
   {
           switch (hostaddr->sa_family) {
           case AF_INET:
                   return (ntohl(((struct sockaddr_in *)hostaddr)->
                       sin_addr.s_addr) >> 24) == IN_LOOPBACKNET;
           case AF_INET6:
                   return IN6_IS_ADDR_LOOPBACK(
                       &(((struct sockaddr_in6 *)hostaddr)->sin6_addr));
           default:
                   return 0;
           }
   }
   
 /*  /*
    * Prepare the hostname and ip address strings that are used to lookup
    * host keys in known_hosts files. These may have a port number appended.
    */
   void
   get_hostfile_hostname_ipaddr(char *hostname, struct sockaddr *hostaddr,
       u_short port, char **hostfile_hostname, char **hostfile_ipaddr)
   {
           char ntop[NI_MAXHOST];
   
           /*
            * We don't have the remote ip-address for connections
            * using a proxy command
            */
           if (hostfile_ipaddr != NULL) {
                   if (options.proxy_command == NULL) {
                           if (getnameinfo(hostaddr, hostaddr->sa_len,
                               ntop, sizeof(ntop), NULL, 0, NI_NUMERICHOST) != 0)
                           fatal("check_host_key: getnameinfo failed");
                           *hostfile_ipaddr = put_host_port(ntop, port);
                   } else {
                           *hostfile_ipaddr = xstrdup("<no hostip for proxy "
                               "command>");
                   }
           }
   
           /*
            * Allow the user to record the key under a different name or
            * differentiate a non-standard port.  This is useful for ssh
            * tunneling over forwarded connections or if you run multiple
            * sshd's on different ports on the same machine.
            */
           if (hostfile_hostname != NULL) {
                   if (options.host_key_alias != NULL) {
                           *hostfile_hostname = xstrdup(options.host_key_alias);
                           debug("using hostkeyalias: %s", *hostfile_hostname);
                   } else {
                           *hostfile_hostname = put_host_port(hostname, port);
                   }
           }
   }
   
   /*
  * 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.
  */   */
Line 606 
Line 663 
 #define ROQUIET 2  #define ROQUIET 2
 static int  static int
 check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port,  check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port,
     Key *host_key, int readonly, const char *user_hostfile,      Key *host_key, int readonly, char *user_hostfile,
     const char *system_hostfile)      char *system_hostfile)
 {  {
         Key *file_key, *raw_key = NULL;          Key *raw_key = NULL;
         const char *type;          const char *type;
         char *ip = NULL, *host = NULL;          char *ip = NULL, *host = NULL;
         char hostline[1000], *hostp, *fp, *ra;          char hostline[1000], *hostp, *fp, *ra;
         HostStatus host_status;          HostStatus host_status;
         HostStatus ip_status;          HostStatus ip_status;
         int r, want_cert, local = 0, host_ip_differ = 0;          int r, want_cert = key_is_cert(host_key), host_ip_differ = 0;
         char ntop[NI_MAXHOST];          int local = sockaddr_is_local(hostaddr);
         char msg[1024];          char msg[1024];
         int len, host_line, ip_line, cancelled_forwarding = 0;          int len, cancelled_forwarding = 0;
         const char *host_file = NULL, *ip_file = NULL;          struct hostkeys *host_hostkeys, *ip_hostkeys;
           const struct hostkey_entry *host_found, *ip_found;
   
         /*          /*
          * Force accepting of the host key for loopback/localhost. The           * Force accepting of the host key for loopback/localhost. The
Line 629 
Line 687 
          * essentially disables host authentication for localhost; however,           * essentially disables host authentication for localhost; however,
          * this is probably not a real problem.           * this is probably not a real problem.
          */           */
         /**  hostaddr == 0! */  
         switch (hostaddr->sa_family) {  
         case AF_INET:  
                 local = (ntohl(((struct sockaddr_in *)hostaddr)->  
                     sin_addr.s_addr) >> 24) == IN_LOOPBACKNET;  
                 break;  
         case AF_INET6:  
                 local = IN6_IS_ADDR_LOOPBACK(  
                     &(((struct sockaddr_in6 *)hostaddr)->sin6_addr));  
                 break;  
         default:  
                 local = 0;  
                 break;  
         }  
         if (options.no_host_authentication_for_localhost == 1 && local &&          if (options.no_host_authentication_for_localhost == 1 && local &&
             options.host_key_alias == NULL) {              options.host_key_alias == NULL) {
                 debug("Forcing accepting of host key for "                  debug("Forcing accepting of host key for "
Line 651 
Line 695 
         }          }
   
         /*          /*
          * We don't have the remote ip-address for connections           * Prepare the hostname and address strings used for hostkey lookup.
          * using a proxy command           * In some cases, these will have a port number appended.
          */           */
         if (options.proxy_command == NULL) {          get_hostfile_hostname_ipaddr(hostname, hostaddr, port, &host, &ip);
                 if (getnameinfo(hostaddr, hostaddr->sa_len, ntop, sizeof(ntop),  
                     NULL, 0, NI_NUMERICHOST) != 0)  
                         fatal("check_host_key: getnameinfo failed");  
                 ip = put_host_port(ntop, port);  
         } else {  
                 ip = xstrdup("<no hostip for proxy command>");  
         }  
   
         /*          /*
          * 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
Line 671 
Line 708 
             strcmp(hostname, ip) == 0 || options.proxy_command != NULL))              strcmp(hostname, ip) == 0 || options.proxy_command != NULL))
                 options.check_host_ip = 0;                  options.check_host_ip = 0;
   
         /*          host_hostkeys = init_hostkeys();
          * Allow the user to record the key under a different name or          load_hostkeys(host_hostkeys, host, user_hostfile);
          * differentiate a non-standard port.  This is useful for ssh          load_hostkeys(host_hostkeys, host, system_hostfile);
          * tunneling over forwarded connections or if you run multiple  
          * sshd's on different ports on the same machine.          ip_hostkeys = NULL;
          */          if (!want_cert && options.check_host_ip) {
         if (options.host_key_alias != NULL) {                  ip_hostkeys = init_hostkeys();
                 host = xstrdup(options.host_key_alias);                  load_hostkeys(ip_hostkeys, ip, user_hostfile);
                 debug("using hostkeyalias: %s", host);                  load_hostkeys(ip_hostkeys, ip, system_hostfile);
         } else {  
                 host = put_host_port(hostname, port);  
         }          }
   
  retry:   retry:
           /* Reload these as they may have changed on cert->key downgrade */
         want_cert = key_is_cert(host_key);          want_cert = key_is_cert(host_key);
         type = key_type(host_key);          type = key_type(host_key);
   
         /*          /*
          * Store the host key from the known host file in here so that we can  
          * compare it with the key for the IP address.  
          */  
         file_key = key_new(key_is_cert(host_key) ? KEY_UNSPEC : 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_status = check_key_in_hostkeys(host_hostkeys, host_key,
         host_status = check_host_in_hostfile(host_file, host, host_key,              &host_found);
             file_key, &host_line);  
         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, looking for a certificate, or the hostname was an ip           * localhost, looking for a certificate, or the hostname was an ip
          * address to begin with.           * address to begin with.
          */           */
         if (!want_cert && options.check_host_ip) {          if (!want_cert && ip_hostkeys != NULL) {
                 Key *ip_key = key_new(host_key->type);                  ip_status = check_key_in_hostkeys(ip_hostkeys, host_key,
                       &ip_found);
                 ip_file = user_hostfile;  
                 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 ||
                       (ip_found != NULL &&
                       !key_equal(ip_found->key, host_found->key))))
                         host_ip_differ = 1;                          host_ip_differ = 1;
   
                 key_free(ip_key);  
         } else          } else
                 ip_status = host_status;                  ip_status = host_status;
   
         key_free(file_key);  
   
         switch (host_status) {          switch (host_status) {
         case HOST_OK:          case HOST_OK:
                 /* 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 %s.",                  debug("Host '%.200s' is known and matches the %s host %s.",
                     host, type, want_cert ? "certificate" : "key");                      host, type, want_cert ? "certificate" : "key");
                 debug("Found %s in %s:%d",                  debug("Found %s in %s:%lu", want_cert ? "CA key" : "key",
                     want_cert ? "CA key" : "key", host_file, host_line);                      host_found->file, host_found->line);
                 if (want_cert && !check_host_cert(hostname, host_key))                  if (want_cert && !check_host_cert(hostname, host_key))
                         goto fail;                          goto fail;
                 if (options.check_host_ip && ip_status == HOST_NEW) {                  if (options.check_host_ip && ip_status == HOST_NEW) {
Line 789 
Line 804 
                 } else if (options.strict_host_key_checking == 2) {                  } else if (options.strict_host_key_checking == 2) {
                         char msg1[1024], msg2[1024];                          char msg1[1024], msg2[1024];
   
                         if (show_other_keys(host, host_key))                          if (show_other_keys(host_hostkeys, host_key))
                                 snprintf(msg1, sizeof(msg1),                                  snprintf(msg1, sizeof(msg1),
                                     "\nbut keys of different type are already"                                      "\nbut keys of different type are already"
                                     " known for this host.");                                      " known for this host.");
Line 830 
Line 845 
                  * local known_hosts file.                   * local known_hosts file.
                  */                   */
                 if (options.check_host_ip && ip_status == HOST_NEW) {                  if (options.check_host_ip && ip_status == HOST_NEW) {
                         snprintf(hostline, sizeof(hostline), "%s,%s",                          snprintf(hostline, sizeof(hostline), "%s,%s", host, ip);
                             host, ip);  
                         hostp = hostline;                          hostp = hostline;
                         if (options.hash_known_hosts) {                          if (options.hash_known_hosts) {
                                 /* Add hash of host and IP separately */                                  /* Add hash of host and IP separately */
Line 885 
Line 899 
                          * all hosts that one might visit.                           * all hosts that one might visit.
                          */                           */
                         debug("Host certificate authority does not "                          debug("Host certificate authority does not "
                             "match %s in %s:%d", CA_MARKER,                              "match %s in %s:%lu", CA_MARKER,
                             host_file, host_line);                              host_found->file, host_found->line);
                         goto fail;                          goto fail;
                 }                  }
                 if (readonly == ROQUIET)                  if (readonly == ROQUIET)
Line 908 
Line 922 
                         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)                          if (ip_status != HOST_NEW)
                                 error("Offending key for IP in %s:%d", ip_file, ip_line);                                  error("Offending key for IP in %s:%lu",
                                       ip_found->file, ip_found->line);
                 }                  }
                 /* The host key has changed. */                  /* The host key has changed. */
                 warn_changed_key(host_key);                  warn_changed_key(host_key);
                 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 %s key in %s:%lu", key_type(host_found->key),
                       host_found->file, host_found->line);
   
                 /*                  /*
                  * 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 999 
Line 1015 
                 snprintf(msg, sizeof(msg),                  snprintf(msg, sizeof(msg),
                     "Warning: the %s host key for '%.200s' "                      "Warning: the %s host key for '%.200s' "
                     "differs from the key for the IP address '%.128s'"                      "differs from the key for the IP address '%.128s'"
                     "\nOffending key for IP in %s:%d",                      "\nOffending key for IP in %s:%lu",
                     type, host, ip, ip_file, ip_line);                      type, host, ip, ip_found->file, ip_found->line);
                 if (host_status == HOST_OK) {                  if (host_status == HOST_OK) {
                         len = strlen(msg);                          len = strlen(msg);
                         snprintf(msg + len, sizeof(msg) - len,                          snprintf(msg + len, sizeof(msg) - len,
                             "\nMatching host key in %s:%d",                              "\nMatching host key in %s:%lu",
                             host_file, host_line);                              host_found->file, host_found->line);
                 }                  }
                 if (options.strict_host_key_checking == 1) {                  if (options.strict_host_key_checking == 1) {
                         logit("%s", msg);                          logit("%s", msg);
Line 1023 
Line 1039 
   
         xfree(ip);          xfree(ip);
         xfree(host);          xfree(host);
           if (host_hostkeys != NULL)
                   free_hostkeys(host_hostkeys);
           if (ip_hostkeys != NULL)
                   free_hostkeys(ip_hostkeys);
         return 0;          return 0;
   
 fail:  fail:
Line 1042 
Line 1062 
                 key_free(raw_key);                  key_free(raw_key);
         xfree(ip);          xfree(ip);
         xfree(host);          xfree(host);
           if (host_hostkeys != NULL)
                   free_hostkeys(host_hostkeys);
           if (ip_hostkeys != NULL)
                   free_hostkeys(ip_hostkeys);
         return -1;          return -1;
 }  }
   
Line 1051 
Line 1075 
 {  {
         struct stat st;          struct stat st;
         int flags = 0;          int flags = 0;
           char *fp;
   
           fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX);
           debug("Server host key: %s %s", key_type(host_key), fp);
           xfree(fp);
   
         /* XXX certs are not yet supported for DNS */          /* XXX certs are not yet supported for DNS */
         if (!key_is_cert(host_key) && options.verify_host_key_dns &&          if (!key_is_cert(host_key) && options.verify_host_key_dns &&
             verify_host_key_dns(host, hostaddr, host_key, &flags) == 0) {              verify_host_key_dns(host, hostaddr, host_key, &flags) == 0) {
Line 1094 
Line 1123 
  */   */
 void  void
 ssh_login(Sensitive *sensitive, const char *orighost,  ssh_login(Sensitive *sensitive, const char *orighost,
     struct sockaddr *hostaddr, struct passwd *pw, int timeout_ms)      struct sockaddr *hostaddr, u_short port, struct passwd *pw, int timeout_ms)
 {  {
         char *host, *cp;          char *host, *cp;
         char *server_user, *local_user;          char *server_user, *local_user;
Line 1117 
Line 1146 
         /* key exchange */          /* key exchange */
         /* authenticate user */          /* authenticate user */
         if (compat20) {          if (compat20) {
                 ssh_kex2(host, hostaddr);                  ssh_kex2(host, hostaddr, port);
                 ssh_userauth2(local_user, server_user, host, sensitive);                  ssh_userauth2(local_user, server_user, host, sensitive);
         } else {          } else {
                 ssh_kex(host, hostaddr);                  ssh_kex(host, hostaddr);
Line 1144 
Line 1173 
         xfree(padded);          xfree(padded);
 }  }
   
 static int  
 show_key_from_file(const char *file, const char *host, int keytype)  
 {  
         Key *found;  
         char *fp, *ra;  
         int line, ret;  
   
         found = key_new(keytype);  
         if ((ret = lookup_key_in_hostfile_by_type(file, host,  
             keytype, found, &line))) {  
                 fp = key_fingerprint(found, SSH_FP_MD5, SSH_FP_HEX);  
                 ra = key_fingerprint(found, SSH_FP_MD5, SSH_FP_RANDOMART);  
                 logit("WARNING: %s key found for host %s\n"  
                     "in %s:%d\n"  
                     "%s key fingerprint %s.\n%s\n",  
                     key_type(found), host, file, line,  
                     key_type(found), fp, ra);  
                 xfree(ra);  
                 xfree(fp);  
         }  
         key_free(found);  
         return (ret);  
 }  
   
 /* print all known host keys for a given host, but skip keys of given type */  /* print all known host keys for a given host, but skip keys of given type */
 static int  static int
 show_other_keys(const char *host, Key *key)  show_other_keys(struct hostkeys *hostkeys, Key *key)
 {  {
         int type[] = { KEY_RSA1, KEY_RSA, KEY_DSA, KEY_ECDSA, -1};          int type[] = { KEY_RSA1, KEY_RSA, KEY_DSA, KEY_ECDSA, -1};
         int i, found = 0;          int i, ret = 0;
           char *fp, *ra;
           const struct hostkey_entry *found;
   
         for (i = 0; type[i] != -1; i++) {          for (i = 0; type[i] != -1; i++) {
                 if (type[i] == key->type)                  if (type[i] == key->type)
                         continue;                          continue;
                 if (type[i] != KEY_RSA1 &&                  if (!lookup_key_in_hostkeys_by_type(hostkeys, type[i], &found))
                     show_key_from_file(options.user_hostfile2, host, type[i])) {  
                         found = 1;  
                         continue;                          continue;
                 }                  fp = key_fingerprint(found->key, SSH_FP_MD5, SSH_FP_HEX);
                 if (type[i] != KEY_RSA1 &&                  ra = key_fingerprint(found->key, SSH_FP_MD5, SSH_FP_RANDOMART);
                     show_key_from_file(options.system_hostfile2, host, type[i])) {                  logit("WARNING: %s key found for host %s\n"
                         found = 1;                      "in %s:%lu\n"
                         continue;                      "%s key fingerprint %s.",
                 }                      key_type(found->key),
                 if (show_key_from_file(options.user_hostfile, host, type[i])) {                      found->host, found->file, found->line,
                         found = 1;                      key_type(found->key), fp);
                         continue;                  if (options.visual_host_key)
                 }                          logit("%s", ra);
                 if (show_key_from_file(options.system_hostfile, host, type[i])) {                  xfree(ra);
                         found = 1;                  xfree(fp);
                         continue;                  ret = 1;
                 }  
                 debug2("no key of type %d for host %s", type[i], host);  
         }          }
         return (found);          return ret;
 }  }
   
 static void  static void

Legend:
Removed from v.1.228  
changed lines
  Added in v.1.229