1:  /*
   2:   * This module determines the type of socket (datagram, stream), the client
   3:   * socket address and port, the server socket address and port. In addition,
   4:   * it provides methods to map a transport address to a printable host name
   5:   * or address. Socket address information results are in static memory.
   6:   *
   7:   * The result from the hostname lookup method is STRING_PARANOID when a host
   8:   * pretends to have someone elses name, or when a host name is available but
   9:   * could not be verified.
  10:   *
  11:   * When lookup or conversion fails the result is set to STRING_UNKNOWN.
  12:   *
  13:   * Diagnostics are reported through syslog(3).
  14:   *
  15:   * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
  16:   */
  17: 
  18: #ifndef lint
  19: static char sccsid[] = "@(#) socket.c 1.14 95/01/30 19:51:50";
  20: #endif
  21: 
  22: /* System libraries. */
  23: 
  24: #include <sys/types.h>
  25: #include <sys/param.h>
  26: #include <sys/socket.h>
  27: #include <netinet/in.h>
  28: #include <netdb.h>
  29: #include <stdio.h>
  30: #include <syslog.h>
  31: #include <string.h>
  32: 
  33: extern char *inet_ntoa();
  34: 
  35: /* Local stuff. */
  36: 
  37: #include "tcpd.h"
  38: 
  39: /* Forward declarations. */
  40: 
  41: static void sock_sink();
  42: 
  43: #ifdef APPEND_DOT
  44: 
  45:  /*
  46:   * Speed up DNS lookups by terminating the host name with a dot. Should be
  47:   * done with care. The speedup can give problems with lookups from sources
  48:   * that lack DNS-style trailing dot magic, such as local files or NIS maps.
  49:   */
  50: 
  51: static struct hostent *gethostbyname_dot(name)
  52: char   *name;
  53: {
  54:     char    dot_name[MAXHOSTNAMELEN + 1];
  55: 
  56:     /*
  57:      * Don't append dots to unqualified names. Such names are likely to come
  58:      * from local hosts files or from NIS.
  59:      */
  60: 
  61:     if (strchr(name, '.') == 0 || strlen(name) >= MAXHOSTNAMELEN - 1) {
  62:     return (gethostbyname(name));
  63:     } else {
  64:     sprintf(dot_name, "%s.", name);
  65:     return (gethostbyname(dot_name));
  66:     }
  67: }
  68: 
  69: #define gethostbyname gethostbyname_dot
  70: #endif
  71: 
  72: /* sock_host - look up endpoint addresses and install conversion methods */
  73: 
  74: void    sock_host(request)
  75: struct request_info *request;
  76: {
  77:     static struct sockaddr_in client;
  78:     static struct sockaddr_in server;
  79:     int     len;
  80:     char    buf[BUFSIZ];
  81:     int     fd = request->fd;
  82: 
  83:     sock_methods(request);
  84: 
  85:     /*
  86:      * Look up the client host address. Hal R. Brand <BRAND@addvax.llnl.gov>
  87:      * suggested how to get the client host info in case of UDP connections:
  88:      * peek at the first message without actually looking at its contents. We
  89:      * really should verify that client.sin_family gets the value AF_INET,
  90:      * but this program has already caused too much grief on systems with
  91:      * broken library code.
  92:      */
  93: 
  94:     len = sizeof(client);
  95:     if (getpeername(fd, (struct sockaddr *) & client, &len) < 0) {
  96:     request->sink = sock_sink;
  97:     len = sizeof(client);
  98:     if (recvfrom(fd, buf, sizeof(buf), MSG_PEEK,
  99:              (struct sockaddr *) & client, &len) < 0) {
 100:         tcpd_warn("can't get client address: %m");
 101:         return;             /* give up */
 102:     }
 103: #ifdef really_paranoid
 104:     memset(buf, 0 sizeof(buf));
 105: #endif
 106:     }
 107:     request->client->sin = &client;
 108: 
 109:     /*
 110:      * Determine the server binding. This is used for client username
 111:      * lookups, and for access control rules that trigger on the server
 112:      * address or name.
 113:      */
 114: 
 115:     len = sizeof(server);
 116:     if (getsockname(fd, (struct sockaddr *) & server, &len) < 0) {
 117:     tcpd_warn("getsockname: %m");
 118:     return;
 119:     }
 120:     request->server->sin = &server;
 121: }
 122: 
 123: /* sock_hostaddr - map endpoint address to printable form */
 124: 
 125: void    sock_hostaddr(host)
 126: struct host_info *host;
 127: {
 128:     struct sockaddr_in *sin = host->sin;
 129: 
 130:     if (sin != 0)
 131:     STRN_CPY(host->addr, inet_ntoa(sin->sin_addr), sizeof(host->addr));
 132: }
 133: 
 134: /* sock_hostname - map endpoint address to host name */
 135: 
 136: void    sock_hostname(host)
 137: struct host_info *host;
 138: {
 139:     struct sockaddr_in *sin = host->sin;
 140:     struct hostent *hp;
 141:     int     i;
 142: 
 143:     /*
 144:      * On some systems, for example Solaris 2.3, gethostbyaddr(0.0.0.0) does
 145:      * not fail. Instead it returns "INADDR_ANY". Unfortunately, this does
 146:      * not work the other way around: gethostbyname("INADDR_ANY") fails. We
 147:      * have to special-case 0.0.0.0, in order to avoid false alerts from the
 148:      * host name/address checking code below.
 149:      */
 150:     if (sin != 0 && sin->sin_addr.s_addr != 0
 151:     && (hp = gethostbyaddr((char *) &(sin->sin_addr),
 152:                    sizeof(sin->sin_addr), AF_INET)) != 0) {
 153: 
 154:     STRN_CPY(host->name, hp->h_name, sizeof(host->name));
 155: 
 156:     /*
 157: 	 * Verify that the address is a member of the address list returned
 158: 	 * by gethostbyname(hostname).
 159: 	 *
 160: 	 * Verify also that gethostbyaddr() and gethostbyname() return the same
 161: 	 * hostname, or rshd and rlogind may still end up being spoofed.
 162: 	 *
 163: 	 * On some sites, gethostbyname("localhost") returns "localhost.domain".
 164: 	 * This is a DNS artefact. We treat it as a special case. When we
 165: 	 * can't believe the address list from gethostbyname("localhost")
 166: 	 * we're in big trouble anyway.
 167: 	 */
 168: 
 169:     if ((hp = gethostbyname(host->name)) == 0) {
 170: 
 171:         /*
 172: 	     * Unable to verify that the host name matches the address. This
 173: 	     * may be a transient problem or a botched name server setup.
 174: 	     */
 175: 
 176:         tcpd_warn("can't verify hostname: gethostbyname(%s) failed",
 177:               host->name);
 178: 
 179:     } else if (STR_NE(host->name, hp->h_name)
 180:            && STR_NE(host->name, "localhost")) {
 181: 
 182:         /*
 183: 	     * The gethostbyaddr() and gethostbyname() calls did not return
 184: 	     * the same hostname. This could be a nameserver configuration
 185: 	     * problem. It could also be that someone is trying to spoof us.
 186: 	     */
 187: 
 188:         tcpd_warn("host name/name mismatch: %s != %s",
 189:               host->name, hp->h_name);
 190: 
 191:     } else {
 192: 
 193:         /*
 194: 	     * The address should be a member of the address list returned by
 195: 	     * gethostbyname(). We should first verify that the h_addrtype
 196: 	     * field is AF_INET, but this program has already caused too much
 197: 	     * grief on systems with broken library code.
 198: 	     */
 199: 
 200:         for (i = 0; hp->h_addr_list[i]; i++) {
 201:         if (memcmp(hp->h_addr_list[i],
 202:                (char *) &sin->sin_addr,
 203:                sizeof(sin->sin_addr)) == 0)
 204:             return;         /* name is good, keep it */
 205:         }
 206: 
 207:         /*
 208: 	     * The host name does not map to the initial address. Perhaps
 209: 	     * someone has messed up. Perhaps someone compromised a name
 210: 	     * server.
 211: 	     */
 212: 
 213:         tcpd_warn("host name/address mismatch: %s != %s",
 214:               inet_ntoa(sin->sin_addr), hp->h_name);
 215:     }
 216:     strcpy(host->name, paranoid);       /* name is bad, clobber it */
 217:     }
 218: }
 219: 
 220: /* sock_sink - absorb unreceived IP datagram */
 221: 
 222: static void sock_sink(fd)
 223: int     fd;
 224: {
 225:     char    buf[BUFSIZ];
 226:     struct sockaddr_in sin;
 227:     int     size = sizeof(sin);
 228: 
 229:     /*
 230:      * Eat up the not-yet received datagram. Some systems insist on a
 231:      * non-zero source address argument in the recvfrom() call below.
 232:      */
 233: 
 234:     (void) recvfrom(fd, buf, sizeof(buf), 0, (struct sockaddr *) & sin, &size);
 235: }

Defined functions

gethostbyname_dot defined in line 51; used 1 times
  • in line 69
sock_hostaddr defined in line 125; used 2 times
sock_hostname defined in line 136; used 2 times
sock_sink defined in line 222; used 2 times

Defined variables

sccsid defined in line 19; never used

Defined macros

gethostbyname defined in line 69; used 3 times
Last modified: 1995-01-30
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 3212
Valid CSS Valid XHTML 1.0 Strict