source: trunk/third/tcp_wrappers/fix_options.c @ 11717

Revision 11717, 3.3 KB checked in by danw, 26 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r11716, which included commits to RCS files with non-trunk default branches.
Line 
1 /*
2  * Routine to disable IP-level socket options. This code was taken from 4.4BSD
3  * rlogind and kernel source, but all mistakes in it are my fault.
4  *
5  * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
6  */
7
8#ifndef lint
9static char sccsid[] = "@(#) fix_options.c 1.6 97/04/08 02:29:19";
10#endif
11
12#include <sys/types.h>
13#include <sys/param.h>
14#include <netinet/in.h>
15#include <netinet/in_systm.h>
16#include <netinet/ip.h>
17#include <netdb.h>
18#include <stdio.h>
19#include <syslog.h>
20
21#ifndef IPOPT_OPTVAL
22#define IPOPT_OPTVAL    0
23#define IPOPT_OLEN      1
24#endif
25
26#include "tcpd.h"
27
28#define BUFFER_SIZE     512             /* Was: BUFSIZ */
29
30/* fix_options - get rid of IP-level socket options */
31
32fix_options(request)
33struct request_info *request;
34{
35#ifdef IP_OPTIONS
36    unsigned char optbuf[BUFFER_SIZE / 3], *cp;
37    char    lbuf[BUFFER_SIZE], *lp;
38    int     optsize = sizeof(optbuf), ipproto;
39    struct protoent *ip;
40    int     fd = request->fd;
41    unsigned int opt;
42    int     optlen;
43    struct in_addr dummy;
44
45    if ((ip = getprotobyname("ip")) != 0)
46        ipproto = ip->p_proto;
47    else
48        ipproto = IPPROTO_IP;
49
50    if (getsockopt(fd, ipproto, IP_OPTIONS, (char *) optbuf, &optsize) == 0
51        && optsize != 0) {
52
53        /*
54         * Horror! 4.[34] BSD getsockopt() prepends the first-hop destination
55         * address to the result IP options list when source routing options
56         * are present (see <netinet/ip_var.h>), but produces no output for
57         * other IP options. Solaris 2.x getsockopt() does produce output for
58         * non-routing IP options, and uses the same format as BSD even when
59         * the space for the destination address is unused. The code below
60         * does the right thing with 4.[34]BSD derivatives and Solaris 2, but
61         * may occasionally miss source routing options on incompatible
62         * systems such as Linux. Their choice.
63         *
64         * Look for source routing options. Drop the connection when one is
65         * found. Just wiping the IP options is insufficient: we would still
66         * help the attacker by providing a real TCP sequence number, and the
67         * attacker would still be able to send packets (blind spoofing). I
68         * discussed this attack with Niels Provos, half a year before the
69         * attack was described in open mailing lists.
70         *
71         * It would be cleaner to just return a yes/no reply and let the caller
72         * decide how to deal with it. Resident servers should not terminate.
73         * However I am not prepared to make changes to internal interfaces
74         * on short notice.
75         */
76#define ADDR_LEN sizeof(dummy.s_addr)
77
78        for (cp = optbuf + ADDR_LEN; cp < optbuf + optsize; cp += optlen) {
79            opt = cp[IPOPT_OPTVAL];
80            if (opt == IPOPT_LSRR || opt == IPOPT_SSRR) {
81                syslog(LOG_WARNING,
82                   "refused connect from %s with IP source routing options",
83                       eval_client(request));
84                shutdown(fd, 2);
85                return;
86            }
87            if (opt == IPOPT_EOL)
88                break;
89            if (opt == IPOPT_NOP) {
90                optlen = 1;
91            } else {
92                optlen = cp[IPOPT_OLEN];
93                if (optlen <= 0)                /* Do not loop! */
94                    break;
95            }
96        }
97        lp = lbuf;
98        for (cp = optbuf; optsize > 0; cp++, optsize--, lp += 3)
99            sprintf(lp, " %2.2x", *cp);
100        syslog(LOG_NOTICE,
101               "connect from %s with IP options (ignored):%s",
102               eval_client(request), lbuf);
103        if (setsockopt(fd, ipproto, IP_OPTIONS, (char *) 0, optsize) != 0) {
104            syslog(LOG_ERR, "setsockopt IP_OPTIONS NULL: %m");
105            shutdown(fd, 2);
106        }
107    }
108#endif
109}
Note: See TracBrowser for help on using the repository browser.