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