]>
Commit | Line | Data |
---|---|---|
befa9345 | 1 | --- linux/net/ipv4/ip_masq_irc.c.dist Sun Mar 25 13:31:12 2001 |
2 | +++ linux/net/ipv4/ip_masq_irc.c Mon Jul 30 13:29:49 2001 | |
3 | @@ -22,6 +22,7 @@ | |
4 | * <sshore@escape.ca> | |
5 | * Scottie Shore : added support for mIRC DCC resume negotiation | |
6 | * <sshore@escape.ca> | |
7 | + * Juan Jose Ciarlante : src addr/port checking for better security (spotted by Michal Zalewski) | |
8 | * | |
9 | * This program is free software; you can redistribute it and/or | |
10 | * modify it under the terms of the GNU General Public License | |
11 | @@ -38,7 +39,12 @@ | |
12 | * /etc/conf.modules (or /etc/modules.conf depending on your config) | |
13 | * where modload will pick it up should you use modload to load your | |
14 | * modules. | |
15 | - * | |
16 | + * | |
17 | + * Insecure "back" data channel opening | |
18 | + * The helper does some trivial checks when opening a new DCC data | |
19 | + * channel. Use module parameter | |
20 | + * insecure=1 | |
21 | + * ... to avoid this and get previous (pre 2.2.20) behaviour. | |
22 | */ | |
23 | ||
24 | #include <linux/config.h> | |
25 | @@ -72,6 +78,9 @@ | |
26 | ||
27 | MODULE_PARM(ports, "1-" __MODULE_STRING(MAX_MASQ_APP_PORTS) "i"); | |
28 | ||
29 | +static int insecure=0; | |
30 | +MODULE_PARM(insecure, "i"); | |
31 | + | |
32 | ||
33 | /* | |
34 | * List of supported DCC protocols | |
35 | @@ -110,6 +119,30 @@ | |
36 | return 0; | |
37 | } | |
38 | ||
39 | + | |
40 | +/* | |
41 | + * Ugly workaround [TM] --mummy ... why does this protocol sucks? | |
42 | + * | |
43 | + * The <1024 check and same source address just raise the | |
44 | + * security "feeling" => they don't prevent a redirector listening | |
45 | + * in same src address at a higher port; you should protect | |
46 | + * your internal network with ipchains output rules anyway | |
47 | + */ | |
48 | + | |
49 | +static inline int masq_irc_out_check(const struct ip_masq *ms, __u32 data_saddr, __u16 data_sport) { | |
50 | + int allow=1; | |
51 | + | |
52 | + IP_MASQ_DEBUG(1-debug, "masq_irc_out_check( s_addr=%d.%d.%d.%d, data_saddr=%d.%d.%d.%d, data_sport=%d", | |
53 | + NIPQUAD(ms->saddr), NIPQUAD(data_saddr), ntohs(data_sport)); | |
54 | + | |
55 | + /* | |
56 | + * Ignore data channel back to other src addr, nor to port < 1024 | |
57 | + */ | |
58 | + if (ms->saddr != data_saddr || ntohs(data_sport) < 1024) | |
59 | + allow=0; | |
60 | + | |
61 | + return allow; | |
62 | +} | |
63 | int | |
64 | masq_irc_out (struct ip_masq_app *mapp, struct ip_masq *ms, struct sk_buff **skb_p, __u32 maddr) | |
65 | { | |
66 | @@ -118,7 +151,7 @@ | |
67 | struct tcphdr *th; | |
68 | char *data, *data_limit; | |
69 | __u32 s_addr; | |
70 | - __u16 s_port; | |
71 | + __u32 s_port; /* larger to allow strtoul() return value validation */ | |
72 | struct ip_masq *n_ms; | |
73 | char buf[20]; /* "m_addr m_port" (dec base)*/ | |
74 | unsigned buf_len; | |
75 | @@ -199,12 +232,25 @@ | |
76 | s_port = simple_strtoul(data,&data,10); | |
77 | addr_end_p = data; | |
78 | ||
79 | + /* Sanity checks */ | |
80 | + if (!s_addr || !s_port || s_port > 65535) | |
81 | + continue; | |
82 | + | |
83 | + /* Prefer net order from now on */ | |
84 | + s_addr = htonl(s_addr); | |
85 | + s_port = htons(s_port); | |
86 | + | |
87 | + /* Simple validation */ | |
88 | + if (!insecure && !masq_irc_out_check(ms, s_addr, s_port)) | |
89 | + /* We may just: return 0; */ | |
90 | + continue; | |
91 | + | |
92 | /* Do we already have a port open for this client? | |
93 | * If so, use it (for DCC ACCEPT) | |
94 | */ | |
95 | ||
96 | n_ms = ip_masq_out_get(IPPROTO_TCP, | |
97 | - htonl(s_addr),htons(s_port), | |
98 | + s_addr, s_port, | |
99 | 0, 0); | |
100 | ||
101 | /* | |
102 | @@ -216,7 +262,7 @@ | |
103 | if (n_ms==NULL) | |
104 | n_ms = ip_masq_new(IPPROTO_TCP, | |
105 | maddr, 0, | |
106 | - htonl(s_addr),htons(s_port), | |
107 | + s_addr, s_port, | |
108 | 0, 0, | |
109 | IP_MASQ_F_NO_DPORT|IP_MASQ_F_NO_DADDR); | |
110 | if (n_ms==NULL) | |
111 | @@ -236,7 +282,10 @@ | |
112 | diff = buf_len - (addr_end_p-addr_beg_p); | |
113 | ||
114 | *addr_beg_p = '\0'; | |
115 | - IP_MASQ_DEBUG(1-debug, "masq_irc_out(): '%s' %X:%X detected (diff=%d)\n", dcc_p, s_addr,s_port, diff); | |
116 | + IP_MASQ_DEBUG(1-debug, "masq_irc_out(): '%s' %d.%d.%d.%d:%d -> %d.%d.%d.%d:%d detected (diff=%d)\n", dcc_p, | |
117 | + NIPQUAD(s_addr), htons(s_port), | |
118 | + NIPQUAD(n_ms->maddr), htons(n_ms->mport), | |
119 | + diff); | |
120 | ||
121 | /* | |
122 | * No shift. |