[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.9 and 1.10

version 1.9, 1999/12/09 00:00:52 version 1.10, 2000/01/04 00:07:58
Line 28 
Line 28 
 char *  char *
 get_remote_hostname(int socket)  get_remote_hostname(int socket)
 {  {
         struct sockaddr_in from;          struct sockaddr_storage from;
         int fromlen, i;          int i;
         struct hostent *hp;          socklen_t fromlen;
           struct addrinfo hints, *ai, *aitop;
         char name[MAXHOSTNAMELEN];          char name[MAXHOSTNAMELEN];
           char ntop[NI_MAXHOST], ntop2[NI_MAXHOST];
   
         /* Get IP address of client. */          /* Get IP address of client. */
         fromlen = sizeof(from);          fromlen = sizeof(from);
Line 40 
Line 42 
                 debug("getpeername failed: %.100s", strerror(errno));                  debug("getpeername failed: %.100s", strerror(errno));
                 fatal_cleanup();                  fatal_cleanup();
         }          }
         /* Map the IP address to a host name. */          if (getnameinfo((struct sockaddr *)&from, fromlen, ntop, sizeof(ntop),
         hp = gethostbyaddr((char *) &from.sin_addr, sizeof(struct in_addr),               NULL, 0, NI_NUMERICHOST) != 0)
                            from.sin_family);                  fatal("get_remote_hostname: getnameinfo NI_NUMERICHOST failed");
         if (hp) {  
                 /* Got host name, find canonic host name. */  
                 if (strchr(hp->h_name, '.') != 0)  
                         strlcpy(name, hp->h_name, sizeof(name));  
                 else if (hp->h_aliases != 0  
                          && hp->h_aliases[0] != 0  
                          && strchr(hp->h_aliases[0], '.') != 0)  
                         strlcpy(name, hp->h_aliases[0], sizeof(name));  
                 else  
                         strlcpy(name, hp->h_name, sizeof(name));  
   
           /* Map the IP address to a host name. */
           if (getnameinfo((struct sockaddr *)&from, fromlen, name, sizeof(name),
                NULL, 0, NI_NAMEREQD) == 0) {
                   /* Got host name. */
                   name[sizeof(name) - 1] = '\0';
                 /*                  /*
                  * Convert it to all lowercase (which is expected by the rest                   * Convert it to all lowercase (which is expected by the rest
                  * of this software).                   * of this software).
Line 71 
Line 68 
                  * fooled if the intruder has access to the name server of                   * fooled if the intruder has access to the name server of
                  * the domain).                   * the domain).
                  */                   */
                 hp = gethostbyname(name);                  memset(&hints, 0, sizeof(hints));
                 if (!hp) {                  hints.ai_family = from.ss_family;
                         log("reverse mapping checking gethostbyname for %.700s failed - POSSIBLE BREAKIN ATTEMPT!", name);                  if (getaddrinfo(name, NULL, &hints, &aitop) != 0) {
                         strlcpy(name, inet_ntoa(from.sin_addr), sizeof name);                          log("reverse mapping checking getaddrinfo for %.700s failed - POSSIBLE BREAKIN ATTEMPT!", name);
                           strlcpy(name, ntop, sizeof name);
                         goto check_ip_options;                          goto check_ip_options;
                 }                  }
                 /* Look for the address from the list of addresses. */                  /* Look for the address from the list of addresses. */
                 for (i = 0; hp->h_addr_list[i]; i++)                  for (ai = aitop; ai; ai = ai->ai_next) {
                         if (memcmp(hp->h_addr_list[i], &from.sin_addr, sizeof(from.sin_addr))                          if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop2,
                             == 0)                              sizeof(ntop2), NULL, 0, NI_NUMERICHOST) == 0 &&
                                 break;                              (strcmp(ntop, ntop2) == 0))
                 /*                                          break;
                  * If we reached the end of the list, the address was not                  }
                  * there.                  freeaddrinfo(aitop);
                  */                  /* If we reached the end of the list, the address was not there. */
                 if (!hp->h_addr_list[i]) {                  if (!ai) {
                         /* Address not found for the host name. */                          /* 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!",                          log("Address %.100s maps to %.600s, but this does not map back to the address - POSSIBLE BREAKIN ATTEMPT!",
                             inet_ntoa(from.sin_addr), name);                              ntop, name);
                         strlcpy(name, inet_ntoa(from.sin_addr), sizeof name);                          strlcpy(name, ntop, sizeof name);
                         goto check_ip_options;                          goto check_ip_options;
                 }                  }
                 /* Address was found for the host name.  We accept the host name. */                  /* Address was found for the host name.  We accept the host name. */
         } else {          } else {
                 /* Host name not found.  Use ascii representation of the address. */                  /* Host name not found.  Use ascii representation of the address. */
                 strlcpy(name, inet_ntoa(from.sin_addr), sizeof name);                  strlcpy(name, ntop, sizeof name);
                 log("Could not reverse map address %.100s.", name);                  log("Could not reverse map address %.100s.", name);
         }          }
   
Line 113 
Line 111 
          * rest of the interaction and could still bypass security.  So we           * rest of the interaction and could still bypass security.  So we
          * exit here if we detect any IP options.           * exit here if we detect any IP options.
          */           */
         {          /* IP options -- IPv4 only */
           if (from.ss_family == AF_INET) {
                 unsigned char options[200], *ucp;                  unsigned char options[200], *ucp;
                 char text[1024], *cp;                  char text[1024], *cp;
                 int option_size, ipproto;                  socklen_t option_size;
                   int ipproto;
                 struct protoent *ip;                  struct protoent *ip;
   
                 if ((ip = getprotobyname("ip")) != NULL)                  if ((ip = getprotobyname("ip")) != NULL)
Line 125 
Line 125 
                         ipproto = IPPROTO_IP;                          ipproto = IPPROTO_IP;
                 option_size = sizeof(options);                  option_size = sizeof(options);
                 if (getsockopt(0, ipproto, IP_OPTIONS, (char *) options,                  if (getsockopt(0, ipproto, IP_OPTIONS, (char *) options,
                                &option_size) >= 0 && option_size != 0) {                      &option_size) >= 0 && option_size != 0) {
                         cp = text;                          cp = text;
                         /* Note: "text" buffer must be at least 3x as big as options. */                          /* Note: "text" buffer must be at least 3x as big as options. */
                         for (ucp = options; option_size > 0; ucp++, option_size--, cp += 3)                          for (ucp = options; option_size > 0; ucp++, option_size--, cp += 3)
                                 sprintf(cp, " %2.2x", *ucp);                                  sprintf(cp, " %2.2x", *ucp);
                         log("Connection from %.100s with IP options:%.800s",                          log("Connection from %.100s with IP options:%.800s",
                             inet_ntoa(from.sin_addr), text);                              ntop, text);
                         packet_disconnect("Connection from %.100s with IP options:%.800s",                          packet_disconnect("Connection from %.100s with IP options:%.800s",
                                           inet_ntoa(from.sin_addr), text);                                            ntop, text);
                 }                  }
         }          }
   
         return xstrdup(name);          return xstrdup(name);
 }  }
   
 static char *canonical_host_name = NULL;  
 static char *canonical_host_ip = NULL;  
   
 /* Returns 1 if remote host is connected via socket, 0 if not. */  
   
 int  
 peer_connection_is_on_socket()  
 {  
         struct sockaddr_in from;  
         int fromlen;  
         int in = packet_get_connection_in();  
         int out = packet_get_connection_out();  
   
         /* filedescriptors in and out are the same, so it's a socket */  
         if (in == out)  
                 return 1;  
         fromlen = sizeof(from);  
         memset(&from, 0, sizeof(from));  
         if (getpeername(in, (struct sockaddr *) & from, &fromlen) < 0)  
                 return 0;  
         if (from.sin_family != AF_INET && from.sin_family != AF_INET6)  
                 return 0;  
         return 1;  
 }  
   
 /*  /*
  * 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
Line 174 
Line 149 
 const char *  const char *
 get_canonical_hostname()  get_canonical_hostname()
 {  {
           static char *canonical_host_name = NULL;
   
         /* Check if we have previously retrieved this same name. */          /* Check if we have previously retrieved this same name. */
         if (canonical_host_name != NULL)          if (canonical_host_name != NULL)
                 return canonical_host_name;                  return canonical_host_name;
   
         /* Get the real hostname if socket; otherwise return UNKNOWN. */          /* Get the real hostname if socket; otherwise return UNKNOWN. */
         if (peer_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());
         else          else
                 canonical_host_name = xstrdup("UNKNOWN");                  canonical_host_name = xstrdup("UNKNOWN");
Line 189 
Line 166 
   
 /*  /*
  * Returns the IP-address of the remote host as a string.  The returned   * Returns the IP-address of the remote host as a string.  The returned
  * string need not be freed.   * string must not be freed.
  */   */
   
 const char *  const char *
 get_remote_ipaddr()  get_remote_ipaddr()
 {  {
         struct sockaddr_in from;          static char *canonical_host_ip = NULL;
         int fromlen, socket;          struct sockaddr_storage from;
           socklen_t fromlen;
           int socket;
           char ntop[NI_MAXHOST];
   
         /* Check whether we have chached the name. */          /* Check whether we have chached the name. */
         if (canonical_host_ip != NULL)          if (canonical_host_ip != NULL)
                 return canonical_host_ip;                  return canonical_host_ip;
   
         /* If not a socket, return UNKNOWN. */          /* If not a socket, return UNKNOWN. */
         if (!peer_connection_is_on_socket()) {          if (!packet_connection_is_on_socket()) {
                 canonical_host_ip = xstrdup("UNKNOWN");                  canonical_host_ip = xstrdup("UNKNOWN");
                 return canonical_host_ip;                  return canonical_host_ip;
         }          }
Line 218 
Line 198 
                 fatal_cleanup();                  fatal_cleanup();
         }          }
         /* Get the IP address in ascii. */          /* Get the IP address in ascii. */
         canonical_host_ip = xstrdup(inet_ntoa(from.sin_addr));          if (getnameinfo((struct sockaddr *)&from, fromlen, ntop, sizeof(ntop),
                NULL, 0, NI_NUMERICHOST) != 0)
                   fatal("get_remote_hostname: getnameinfo NI_NUMERICHOST failed");
   
           canonical_host_ip = xstrdup(ntop);
   
         /* Return ip address string. */          /* Return ip address string. */
         return canonical_host_ip;          return canonical_host_ip;
 }  }
   
 /* Returns the port of the peer of the socket. */  /* Returns the local/remote port for the socket. */
   
 int  int
 get_peer_port(int sock)  get_sock_port(int sock, int local)
 {  {
         struct sockaddr_in from;          struct sockaddr_storage from;
         int fromlen;          socklen_t fromlen;
           char strport[NI_MAXSERV];
   
         /* 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(sock, (struct sockaddr *) & from, &fromlen) < 0) {          if (local) {
                 debug("getpeername failed: %.100s", strerror(errno));                  if (getsockname(sock, (struct sockaddr *)&from, &fromlen) < 0) {
                 fatal_cleanup();                          error("getsockname failed: %.100s", strerror(errno));
                           return 0;
                   }
           } else {
                   if (getpeername(sock, (struct sockaddr *) & from, &fromlen) < 0) {
                           debug("getpeername failed: %.100s", strerror(errno));
                           fatal_cleanup();
                   }
         }          }
         /* Return port number. */          /* Return port number. */
         return ntohs(from.sin_port);          if (getnameinfo((struct sockaddr *)&from, fromlen, NULL, 0,
                strport, sizeof(strport), NI_NUMERICSERV) != 0)
                   fatal("get_sock_port: getnameinfo NI_NUMERICSERV failed");
           return atoi(strport);
 }  }
   
 /* Returns the port number of the remote host.  */  /* Returns remote/local port number for the current connection. */
   
 int  int
 get_remote_port()  get_port(int local)
 {  {
         int socket;  
   
         /*          /*
          * If the connection is not a socket, return 65535.  This is           * If the connection is not a socket, return 65535.  This is
          * intentionally chosen to be an unprivileged port number.           * intentionally chosen to be an unprivileged port number.
          */           */
         if (!peer_connection_is_on_socket())          if (!packet_connection_is_on_socket())
                 return 65535;                  return 65535;
   
         /* Get client socket. */          /* Get socket and return the port number. */
         socket = packet_get_connection_in();          return get_sock_port(packet_get_connection_in(), local);
   }
   
         /* Get and return the peer port number. */  int
         return get_peer_port(socket);  get_peer_port(int sock)
   {
           return get_sock_port(sock, 0);
   }
   
   int
   get_remote_port()
   {
           return get_port(0);
   }
   
   int
   get_local_port()
   {
           return get_port(1);
 }  }

Legend:
Removed from v.1.9  
changed lines
  Added in v.1.10