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

Diff for /src/usr.bin/ssh/canohost.c between version 1.19 and 1.20

version 1.19, 2001/01/29 19:42:33 version 1.20, 2001/02/03 10:08:37
Line 18 
Line 18 
 #include "xmalloc.h"  #include "xmalloc.h"
 #include "log.h"  #include "log.h"
   
   void    check_ip_options(int socket, char *ipaddr);
   
 /*  /*
  * Return the canonical name of the host at the other end of the socket. The   * Return the canonical name of the host at the other end of the socket. The
  * caller should free the returned string with xfree.   * caller should free the returned string with xfree.
  */   */
   
 char *  char *
 get_remote_hostname(int socket)  get_remote_hostname(int socket, int reverse_mapping_check)
 {  {
         struct sockaddr_storage from;          struct sockaddr_storage from;
         int i;          int i;
         socklen_t fromlen;          socklen_t fromlen;
         struct addrinfo hints, *ai, *aitop;          struct addrinfo hints, *ai, *aitop;
         char name[MAXHOSTNAMELEN];          char name[NI_MAXHOST], ntop[NI_MAXHOST], ntop2[NI_MAXHOST];
         char ntop[NI_MAXHOST], ntop2[NI_MAXHOST];  
   
         /* Get IP address of client. */          /* Get IP address of client. */
         fromlen = sizeof(from);          fromlen = sizeof(from);
         memset(&from, 0, sizeof(from));          memset(&from, 0, sizeof(from));
         if (getpeername(socket, (struct sockaddr *) & from, &fromlen) < 0) {          if (getpeername(socket, (struct sockaddr *) &from, &fromlen) < 0) {
                 debug("getpeername failed: %.100s", strerror(errno));                  debug("getpeername failed: %.100s", strerror(errno));
                 fatal_cleanup();                  fatal_cleanup();
         }          }
           if (from.ss_family == AF_INET)
                   check_ip_options(socket, ntop);
   
         if (getnameinfo((struct sockaddr *)&from, fromlen, ntop, sizeof(ntop),          if (getnameinfo((struct sockaddr *)&from, fromlen, ntop, sizeof(ntop),
              NULL, 0, NI_NUMERICHOST) != 0)               NULL, 0, NI_NUMERICHOST) != 0)
                 fatal("get_remote_hostname: getnameinfo NI_NUMERICHOST failed");                  fatal("get_remote_hostname: getnameinfo NI_NUMERICHOST failed");
   
         /* Map the IP address to a host name. */          /* Map the IP address to a host name. */
         if (getnameinfo((struct sockaddr *)&from, fromlen, name, sizeof(name),          if (getnameinfo((struct sockaddr *)&from, fromlen, name, sizeof(name),
              NULL, 0, NI_NAMEREQD) == 0) {               NULL, 0, NI_NAMEREQD) != 0) {
                 /* Got host name. */                  /* Host name not found.  Use ip address. */
                 name[sizeof(name) - 1] = '\0';                  log("Could not reverse map address %.100s.", ntop);
                 /*                  return xstrdup(ntop);
                  * Convert it to all lowercase (which is expected by the rest  
                  * of this software).  
                  */  
                 for (i = 0; name[i]; i++)  
                         if (isupper(name[i]))  
                                 name[i] = tolower(name[i]);  
   
                 /*  
                  * Map it back to an IP address and check that the given  
                  * address actually is an address of this host.  This is  
                  * necessary because anyone with access to a name server can  
                  * define arbitrary names for an IP address. Mapping from  
                  * name to IP address can be trusted better (but can still be  
                  * fooled if the intruder has access to the name server of  
                  * the domain).  
                  */  
                 memset(&hints, 0, sizeof(hints));  
                 hints.ai_family = from.ss_family;  
                 hints.ai_socktype = SOCK_STREAM;  
                 if (getaddrinfo(name, NULL, &hints, &aitop) != 0) {  
                         log("reverse mapping checking getaddrinfo for %.700s failed - POSSIBLE BREAKIN ATTEMPT!", name);  
                         strlcpy(name, ntop, sizeof name);  
                         goto check_ip_options;  
                 }  
                 /* Look for the address from the list of addresses. */  
                 for (ai = aitop; ai; ai = ai->ai_next) {  
                         if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop2,  
                             sizeof(ntop2), NULL, 0, NI_NUMERICHOST) == 0 &&  
                             (strcmp(ntop, ntop2) == 0))  
                                         break;  
                 }  
                 freeaddrinfo(aitop);  
                 /* If we reached the end of the list, the address was not there. */  
                 if (!ai) {  
                         /* Address not found for the host name. */  
                         log("Address %.100s maps to %.600s, but this does not map back to the address - POSSIBLE BREAKIN ATTEMPT!",  
                             ntop, name);  
                         strlcpy(name, ntop, sizeof name);  
                         goto check_ip_options;  
                 }  
                 /* Address was found for the host name.  We accept the host name. */  
         } else {  
                 /* Host name not found.  Use ascii representation of the address. */  
                 strlcpy(name, ntop, sizeof name);  
                 log("Could not reverse map address %.100s.", name);  
         }          }
   
 check_ip_options:          /* Got host name. */
           name[sizeof(name) - 1] = '\0';
         /*          /*
          * If IP options are supported, make sure there are none (log and           * Convert it to all lowercase (which is expected by the rest
          * disconnect them if any are found).  Basically we are worried about           * of this software).
          * source routing; it can be used to pretend you are somebody  
          * (ip-address) you are not. That itself may be "almost acceptable"  
          * under certain circumstances, but rhosts autentication is useless  
          * if source routing is accepted. Notice also that if we just dropped  
          * source routing here, the other side could use IP spoofing to do  
          * rest of the interaction and could still bypass security.  So we  
          * exit here if we detect any IP options.  
          */           */
         /* IP options -- IPv4 only */          for (i = 0; name[i]; i++)
         if (from.ss_family == AF_INET) {                  if (isupper(name[i]))
                 u_char options[200], *ucp;                          name[i] = tolower(name[i]);
                 char text[1024], *cp;  
                 socklen_t option_size;  
                 int ipproto;  
                 struct protoent *ip;  
   
                 if ((ip = getprotobyname("ip")) != NULL)          if (!reverse_mapping_check)
                         ipproto = ip->p_proto;                  return xstrdup(name);
                 else          /*
                         ipproto = IPPROTO_IP;           * Map it back to an IP address and check that the given
                 option_size = sizeof(options);           * address actually is an address of this host.  This is
                 if (getsockopt(socket, ipproto, IP_OPTIONS, (char *) options,           * necessary because anyone with access to a name server can
                     &option_size) >= 0 && option_size != 0) {           * define arbitrary names for an IP address. Mapping from
                         cp = text;           * name to IP address can be trusted better (but can still be
                         /* Note: "text" buffer must be at least 3x as big as options. */           * fooled if the intruder has access to the name server of
                         for (ucp = options; option_size > 0; ucp++, option_size--, cp += 3)           * the domain).
                                 sprintf(cp, " %2.2x", *ucp);           */
                         log("Connection from %.100s with IP options:%.800s",          memset(&hints, 0, sizeof(hints));
                             ntop, text);          hints.ai_family = from.ss_family;
                         packet_disconnect("Connection from %.100s with IP options:%.800s",          hints.ai_socktype = SOCK_STREAM;
                                           ntop, text);          if (getaddrinfo(name, NULL, &hints, &aitop) != 0) {
                 }                  log("reverse mapping checking getaddrinfo for %.700s "
                       "failed - POSSIBLE BREAKIN ATTEMPT!", name);
                   return xstrdup(ntop);
         }          }
           /* Look for the address from the list of addresses. */
           for (ai = aitop; ai; ai = ai->ai_next) {
                   if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop2,
                       sizeof(ntop2), NULL, 0, NI_NUMERICHOST) == 0 &&
                       (strcmp(ntop, ntop2) == 0))
                                   break;
           }
           freeaddrinfo(aitop);
           /* If we reached the end of the list, the address was not there. */
           if (!ai) {
                   /* Address not found for the host name. */
                   log("Address %.100s maps to %.600s, but this does not "
                       "map back to the address - POSSIBLE BREAKIN ATTEMPT!",
                       ntop, name);
                   return xstrdup(ntop);
           }
         return xstrdup(name);          return xstrdup(name);
 }  }
   
 /*  /*
    * If IP options are supported, make sure there are none (log and
    * disconnect them if any are found).  Basically we are worried about
    * source routing; it can be used to pretend you are somebody
    * (ip-address) you are not. That itself may be "almost acceptable"
    * under certain circumstances, but rhosts autentication is useless
    * if source routing is accepted. Notice also that if we just dropped
    * source routing here, the other side could use IP spoofing to do
    * rest of the interaction and could still bypass security.  So we
    * exit here if we detect any IP options.
    */
   /* IPv4 only */
   void
   check_ip_options(int socket, char *ipaddr)
   {
           u_char options[200], *ucp;
           char text[1024], *cp;
           socklen_t option_size;
           int ipproto;
           struct protoent *ip;
   
           if ((ip = getprotobyname("ip")) != NULL)
                   ipproto = ip->p_proto;
           else
                   ipproto = IPPROTO_IP;
           option_size = sizeof(options);
           if (getsockopt(socket, ipproto, IP_OPTIONS, (void *)options,
               &option_size) >= 0 && option_size != 0) {
                   cp = text;
                   /* Note: "text" buffer must be at least 3x as big as options. */
                   for (ucp = options; option_size > 0; ucp++, option_size--, cp += 3)
                           sprintf(cp, " %2.2x", *ucp);
                   log("Connection from %.100s with IP options:%.800s",
                       ipaddr, text);
                   packet_disconnect("Connection from %.100s with IP options:%.800s",
                       ipaddr, text);
           }
   }
   
   /*
  * Return the canonical name of the host in the other side of the current   * Return the canonical name of the host in the other side of the current
  * connection.  The host name is cached, so it is efficient to call this   * connection.  The host name is cached, so it is efficient to call this
  * several times.   * several times.
  */   */
   
 const char *  const char *
 get_canonical_hostname()  get_canonical_hostname(int reverse_mapping_check)
 {  {
         static char *canonical_host_name = NULL;          static char *canonical_host_name = NULL;
           static int reverse_mapping_checked = 0;
   
         /* Check if we have previously retrieved this same name. */          /* Check if we have previously retrieved name with same option. */
         if (canonical_host_name != NULL)          if (canonical_host_name != NULL) {
                 return canonical_host_name;                  if (reverse_mapping_checked != reverse_mapping_check)
                           xfree(canonical_host_name);
                   else
                           return canonical_host_name;
           }
   
         /* Get the real hostname if socket; otherwise return UNKNOWN. */          /* Get the real hostname if socket; otherwise return UNKNOWN. */
         if (packet_connection_is_on_socket())          if (packet_connection_is_on_socket())
                 canonical_host_name = get_remote_hostname(packet_get_connection_in());                  canonical_host_name = get_remote_hostname(
                       packet_get_connection_in(), reverse_mapping_check);
         else          else
                 canonical_host_name = xstrdup("UNKNOWN");                  canonical_host_name = xstrdup("UNKNOWN");
   
           reverse_mapping_checked = reverse_mapping_check;
         return canonical_host_name;          return canonical_host_name;
 }  }
   

Legend:
Removed from v.1.19  
changed lines
  Added in v.1.20