home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / N / TCPIP / NETKIT-A.06 / NETKIT-A / NetKit-A-0.06 / tcp_wrapper-6.3 / socket.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-03-27  |  8.1 KB  |  292 lines

  1.  /*
  2.   * sock_host() determines the type of socket (datagram, stream), the name
  3.   * and address of the host at the other end of a socket, the local socket
  4.   * address and port, and the remote username if username lookups are done
  5.   * irrespective of client. All results are in static memory and will be
  6.   * overwritten upon the next call.
  7.   * 
  8.   * The return status is (-1) if the remote host pretends to have someone elses
  9.   * name, or if the remote host name is available but could not be verified;
  10.   * in either case the hostname will be ignored. The return status is zero in
  11.   * all other cases (the hostname is unavailable, or the host name double
  12.   * check succeeds).
  13.   * 
  14.   * Diagnostics are reported through syslog(3).
  15.   * 
  16.   * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
  17.   */
  18.  
  19. #ifndef lint
  20. static char sccsid[] = "@(#) socket.c 1.9 94/02/01 22:12:16";
  21. #endif
  22.  
  23. /* System libraries. */
  24.  
  25. #include <sys/types.h>
  26. #include <sys/param.h>
  27. #include <sys/socket.h>
  28. #include <netinet/in.h>
  29. #include <netdb.h>
  30. #include <stdio.h>
  31. #include <syslog.h>
  32.  
  33. extern char *inet_ntoa();
  34. extern char *strncpy();
  35. extern char *strcpy();
  36.  
  37.  /*
  38.   * Some AIX versions advertise a too small MAXHOSTNAMELEN value (32).
  39.   * Result: long hostnames would be truncated, and connections would be
  40.   * dropped because of host name verification failures. Adrian van Bloois
  41.   * (A.vanBloois@info.nic.surfnet.nl) figured out what was the problem.
  42.   */
  43.  
  44. #if (MAXHOSTNAMELEN < 64)
  45. #undef MAXHOSTNAMELEN
  46. #endif
  47.  
  48. /* In case not defined in <sys/param.h>. */
  49.  
  50. #ifndef MAXHOSTNAMELEN
  51. #define MAXHOSTNAMELEN    256        /* storage for host name */
  52. #endif
  53.  
  54. /* Local stuff. */
  55.  
  56. #include "log_tcp.h"
  57.  
  58. /* Forward declarations. */
  59.  
  60. static int sock_match_hostname();
  61. static void sock_sink();
  62.  
  63. #ifdef APPEND_DOT
  64.  
  65.  /*
  66.   * Speed up DNS lookups by terminating the host name with a dot. Should be
  67.   * done with care. The speedup can give problems with lookups from sources
  68.   * that lack DNS-style trailing dot magic, such as local files or NIS maps.
  69.   */
  70.  
  71. static struct hostent *gethostbyname_dot(name)
  72. char   *name;
  73. {
  74.     char    dot_name[MAXHOSTNAMELEN + 1];
  75.     char   *strchr();
  76.  
  77.     /*
  78.      * Don't append dots to unqualified names. Such names are likely to come
  79.      * from local hosts files or from NIS.
  80.      */
  81.  
  82.     if (strchr(name, '.') == 0 || strlen(name) >= MAXHOSTNAMELEN - 1) {
  83.     return (gethostbyname(name));
  84.     } else {
  85.     sprintf(dot_name, "%s.", name);
  86.     return (gethostbyname(dot_name));
  87.     }
  88. }
  89.  
  90. #define gethostbyname gethostbyname_dot
  91. #endif
  92.  
  93. /* sock_host - determine endpoint info */
  94.  
  95. int     sock_host(client, fd)
  96. struct client_info *client;
  97. int     fd;
  98. {
  99.     static struct sockaddr rmt_sa;
  100.     static struct sockaddr our_sa;
  101.     int     len;
  102.     char    buf[BUFSIZ];
  103.  
  104.     /*
  105.      * Initialize the result with suitable defaults.
  106.      */
  107.  
  108.     init_client(client);
  109.     client->fd = fd;
  110.  
  111.     /*
  112.      * Look up the remote host address. Hal R. Brand <BRAND@addvax.llnl.gov>
  113.      * suggested how to get the remote host info in case of UDP connections:
  114.      * peek at the first message without actually looking at its contents.
  115.      */
  116.  
  117.     len = sizeof(rmt_sa);
  118.     if (getpeername(client->fd, &rmt_sa, &len) < 0) {
  119.     len = sizeof(rmt_sa);
  120.     if (recvfrom(client->fd, buf, sizeof(buf), MSG_PEEK, &rmt_sa, &len) < 0) {
  121.         syslog(LOG_ERR, "error: can't get client address: %m");
  122.         return (0);                /* address and name unknown */
  123.     }
  124. #ifdef really_paranoid
  125.     memset(buf, 0 sizeof(buf));
  126. #endif
  127.     client->sink = sock_sink;
  128.     }
  129.     client->rmt_sin = (struct sockaddr_in *) & rmt_sa;
  130.  
  131.     /*
  132.      * Determine the local binding. Right now this information is used only
  133.      * for remote username lookups, but it may become useful to map the local
  134.      * port number to an internet service name, so that services handled by
  135.      * the same daemon program (same argv[0] value) can still be
  136.      * distinguished.
  137.      */
  138.  
  139.     len = sizeof(our_sa);
  140.     if (getsockname(client->fd, &our_sa, &len) < 0) {
  141.     syslog(LOG_ERR, "error: getsockname: %m");
  142.     } else {
  143.     client->our_sin = (struct sockaddr_in *) & our_sa;
  144.     }
  145.     return (sock_names(client));
  146. }
  147.  
  148. /* sock_names - map IP address info to readable address and name */
  149.  
  150. int     sock_names(client)
  151. struct client_info *client;
  152. {
  153.     static char addr_buf[MAXHOSTNAMELEN];
  154.     static char name_buf[MAXHOSTNAMELEN];
  155.     struct hostent *hp;
  156.     struct in_addr addr;
  157.  
  158.     /*
  159.      * Some stupid compilers can do struct assignment but cannot do structure
  160.      * initialization.
  161.      */
  162.  
  163.     addr = client->rmt_sin->sin_addr;
  164.  
  165.     /*
  166.      * Do username lookups if we do lookups irrespective of client. In a
  167.      * future release we should perhaps use asynchronous I/O so that the
  168.      * handshake with the rfc931 server can proceed while hostname lookups
  169.      * are going on.
  170.      */
  171.  
  172. #ifdef ALWAYS_RFC931
  173.     if (RFC931_POSSIBLE(client))
  174.     client->user = rfc931(client->rmt_sin, client->our_sin);
  175. #endif
  176.  
  177.     /*
  178.      * Map the address to human-readable form.
  179.      */
  180.  
  181. #define STRNCP(d,s,l) { strncpy((d),(s),(l)); ((d)[(l)-1] = 0); }
  182.  
  183.     STRNCP(addr_buf, inet_ntoa(addr), sizeof(addr_buf));
  184.     client->addr = addr_buf;
  185.  
  186.     /*
  187.      * Look up the remote host name. Verify that the host name does not
  188.      * belong to someone else. Ignore the hostname if verification fails or
  189.      * if verification is not possible.
  190.      */
  191.  
  192.     if ((hp = gethostbyaddr((char *) &addr, sizeof(addr), AF_INET)) == 0)
  193.     return (0);                /* hostname unknown */
  194.     STRNCP(name_buf, hp->h_name, sizeof(name_buf));
  195.     if (sock_match_hostname(name_buf, addr)) {
  196.     client->name = name_buf;
  197.     return (0);                /* hostname verified ok */
  198.     } else {
  199.     return (-1);                /* bad or unverified name */
  200.     }
  201. }
  202.  
  203. /* sock_match_hostname - determine if host name matches IP address */
  204.  
  205. static int sock_match_hostname(remotehost, addr)
  206. char   *remotehost;
  207. struct in_addr addr;
  208. {
  209.     struct hostent *hp;
  210.     int     i;
  211.  
  212.     /*
  213.      * Verify that the client address is a member of the address list
  214.      * returned by gethostbyname(remotehost).
  215.      * 
  216.      * Verify also that gethostbyaddr() and gethostbyname() return the same
  217.      * hostname, or rshd and rlogind may still end up being spoofed.
  218.      * 
  219.      * On some sites, gethostbyname("localhost") returns "localhost.my.domain".
  220.      * This is a DNS artefact. We treat it as a special case. When we can't
  221.      * believe the address list from gethostbyname("localhost") we're in big
  222.      * trouble anyway.
  223.      */
  224.  
  225.     if ((hp = gethostbyname(remotehost)) == 0) {
  226.  
  227.     /*
  228.      * Unable to verify that the host name matches the address. This may
  229.      * be a transient problem or a botched name server setup.
  230.      */
  231.  
  232.     syslog(LOG_ERR,
  233.            "warning: can't verify hostname: gethostbyname(%s) failed",
  234.            remotehost);
  235.     return (FROM_BAD);
  236.  
  237.     } else if (strcasecmp(remotehost, hp->h_name)
  238.            && strcasecmp(remotehost, "localhost")) {
  239.  
  240.     /*
  241.      * The gethostbyaddr() and gethostbyname() calls did not return the
  242.      * same hostname. This could be a nameserver configuration problem.
  243.      * It could also be that someone is trying to spoof us.
  244.      */
  245.  
  246.     syslog(LOG_ERR, "warning: host name/name mismatch: %s != %s",
  247.            remotehost, hp->h_name);
  248.     return (FROM_BAD);
  249.  
  250.     } else {
  251.  
  252.     /*
  253.      * The client address should be a member of the address list returned
  254.      * by gethostbyname(). We should first verify that the h_addrtype
  255.      * field is AF_INET, but this program has already caused too much
  256.      * grief on systems with broken library code.
  257.      */
  258.  
  259.     for (i = 0; hp->h_addr_list[i]; i++) {
  260.         if (memcmp(hp->h_addr_list[i], (caddr_t) & addr, sizeof(addr)) == 0)
  261.         return (FROM_GOOD);
  262.     }
  263.  
  264.     /*
  265.      * The host name does not map to the initial client address. Perhaps
  266.      * someone has messed up. Perhaps someone compromised a name server.
  267.      */
  268.  
  269.     syslog(LOG_ERR, "warning: host name/address mismatch: %s != %s",
  270.            inet_ntoa(addr), hp->h_name);
  271.     return (FROM_BAD);
  272.     }
  273. }
  274.  
  275. /* sock_sink - absorb unreceived IP datagram */
  276.  
  277. static void sock_sink(fd)
  278. int     fd;
  279.  
  280. {
  281.     char    buf[BUFSIZ];
  282.     struct sockaddr sa;
  283.     int     size = sizeof(sa);
  284.  
  285.     /*
  286.      * Eat up the not-yet received datagram. Some systems insist on a
  287.      * non-zero source address argument in the recvfrom() call below.
  288.      */
  289.  
  290.     (void) recvfrom(fd, buf, sizeof(buf), 0, &sa, &size);
  291. }
  292.