home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume20 / log_tcp / part01 / fromhost.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-05-22  |  3.9 KB  |  139 lines

  1.  /*
  2.   * fromhost() returns the name of the host at the other end of standard
  3.   * input, the host address if name lookup fails, "stdin" if it is connected
  4.   * to a terminal, or a null pointer in all other cases.
  5.   * 
  6.   * Protection against spoofing of naive rsh and rlogind implementations:
  7.   * 
  8.   * Initially, all we have is the remote host address. If the host address->name
  9.   * mapping is available, fromhost() verifies that the host name->address
  10.   * mapping yields the original host address. The idea is that it is much
  11.   * easier to compromise some random address->name map (because there is one
  12.   * for almost every network), than to compromise the name->address map that
  13.   * is unique for your internet domain.
  14.   * 
  15.   * Anyway, if the test fails, fromhost() either drops the connection (when
  16.   * compiled with -DPARANOID) or just returns the remote host address instead
  17.   * of the bad remote host name (not compiled with -DPARANOID).
  18.   * 
  19.   * Diagnostics are reported through syslog(3).
  20.   * 
  21.   * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
  22.   */
  23.  
  24. #ifndef lint
  25. static char sccsid[] = "@(#) fromhost.c 1.2 91/05/20 13:28:01";
  26. #endif
  27.  
  28. #include <stdio.h>
  29. #include <sys/types.h>
  30. #include <sys/param.h>
  31. #include <sys/socket.h>
  32. #include <syslog.h>
  33. #include <netinet/in.h>
  34. #include <netdb.h>
  35.  
  36. #ifndef MAXHOSTNAMELEN
  37. #define MAXHOSTNAMELEN    BUFSIZ
  38. #endif
  39.  
  40. /* The following are to be used in assignment context, not in comparisons */
  41.  
  42. #define    GOOD    1
  43. #define    BAD    0
  44.  
  45. /* fromhost - find out what is at the other end of standard input */
  46.  
  47. char   *fromhost()
  48. {
  49.     struct sockaddr sa;
  50.     struct sockaddr_in *sin = (struct sockaddr_in *) (&sa);
  51.     struct hostent *hp;
  52.     int     sockt = fileno(stdin);
  53.     int     length = sizeof(sa);
  54.     static char remotehost[MAXHOSTNAMELEN + 1];
  55.     char   *inet_ntoa();
  56.     char   *strncpy();
  57.  
  58.     /* Try to be smart if standard input is not connected to a socket. */
  59.  
  60.     if (getpeername(sockt, &sa, &length) < 0) {
  61.     if (isatty(sockt)) {
  62.         return ("stdin");
  63.     } else {
  64.         syslog(LOG_ERR, "getpeername: %m");
  65.         return (0);
  66.     }
  67.     }
  68.     if (sa.sa_family != AF_INET) {
  69.     syslog(LOG_ERR, "unknown address family %ld", (long) sa.sa_family);
  70.     return (0);
  71.     }
  72.     /* Look up the remote host name. Use its address if name lookup fails. */
  73.  
  74.     if ((hp = gethostbyaddr((char *) &sin->sin_addr.s_addr,
  75.                 sizeof(sin->sin_addr.s_addr),
  76.                 AF_INET)) == 0) {
  77.     return (inet_ntoa(sin->sin_addr));
  78.     }
  79.     /* Save the host name before the gethostbyxxx() routines clobber it. */
  80.  
  81.     (void) strncpy(remotehost, hp->h_name, sizeof(remotehost) - 1);
  82.     remotehost[sizeof(remotehost) - 1] = 0;
  83.  
  84.     /*
  85.      * Decide what to do if the host name does not match the address or if we
  86.      * are unable to verify that the host name matches the address.
  87.      */
  88.  
  89.     if (matchname(remotehost, sin)) {
  90.     return (remotehost);
  91.     } else {
  92. #ifdef    PARANOID
  93.     exit(0);
  94. #else
  95.     return (inet_ntoa(sin->sin_addr));
  96. #endif
  97.     }
  98. }
  99.  
  100. /* matchname - determine if host name matches address */
  101.  
  102. static int matchname(remotehost, sin)
  103. char   *remotehost;
  104. struct sockaddr_in *sin;
  105. {
  106.     struct hostent *hp;
  107.     int     i;
  108.  
  109.     if ((hp = gethostbyname(remotehost)) == 0) {
  110.  
  111.     /*
  112.      * Unable to verify that the host name matches the address. This may be
  113.      * a transient problem or a botched name server setup.
  114.      */
  115.  
  116.     syslog(LOG_ERR, "gethostbyname(%s): lookup failure", remotehost);
  117.     return (BAD);
  118.     } else {
  119.  
  120.     /* Look up the host address in the address list we just got. */
  121.  
  122.     for (i = 0; hp->h_addr_list[i]; i++) {
  123.         if (memcmp(hp->h_addr_list[i], (caddr_t) & sin->sin_addr,
  124.                sizeof(sin->sin_addr)) == 0)
  125.         return (GOOD);
  126.     }
  127.  
  128.     /*
  129.      * The host name does not map to the host address. Perhaps someone
  130.      * has compromised a name server. More likely someone botched it, but
  131.      * that could be dangerous, too.
  132.      */
  133.  
  134.     syslog(LOG_ERR, "host name/address mismatch: %s != %s",
  135.            inet_ntoa(sin->sin_addr), hp->h_name);
  136.     return (BAD);
  137.     }
  138. }
  139.