rev |
line source |
pascal@20313
|
1 From https://gnunet.org/knock :
|
pascal@20313
|
2 https://gnunet.org/sites/default/files/tcp_stealth_3.16_1.diff
|
pascal@20313
|
3 Signed-off-by: Julian Kirsch <kirschju@sec.in.tum.de>
|
pascal@20313
|
4 ---
|
pascal@20313
|
5 diff -Nurp linux-3.16/include/linux/tcp.h linux-3.16-knock/include/linux/tcp.h
|
pascal@20313
|
6 --- linux-3.16/include/linux/tcp.h 2014-08-03 18:25:02.000000000 -0400
|
pascal@20313
|
7 +++ linux-3.16-knock/include/linux/tcp.h 2014-08-19 06:15:42.329509665 -0400
|
pascal@20313
|
8 @@ -20,6 +20,7 @@
|
pascal@20313
|
9
|
pascal@20313
|
10 #include <linux/skbuff.h>
|
pascal@20313
|
11 #include <linux/dmaengine.h>
|
pascal@20313
|
12 +#include <linux/cryptohash.h>
|
pascal@20313
|
13 #include <net/sock.h>
|
pascal@20313
|
14 #include <net/inet_connection_sock.h>
|
pascal@20313
|
15 #include <net/inet_timewait_sock.h>
|
pascal@20313
|
16 @@ -325,6 +326,21 @@ struct tcp_sock {
|
pascal@20313
|
17 struct tcp_md5sig_info __rcu *md5sig_info;
|
pascal@20313
|
18 #endif
|
pascal@20313
|
19
|
pascal@20313
|
20 +#ifdef CONFIG_TCP_STEALTH
|
pascal@20313
|
21 +/* Stealth TCP socket configuration */
|
pascal@20313
|
22 + struct {
|
pascal@20313
|
23 + #define TCP_STEALTH_MODE_AUTH BIT(0)
|
pascal@20313
|
24 + #define TCP_STEALTH_MODE_INTEGRITY BIT(1)
|
pascal@20313
|
25 + #define TCP_STEALTH_MODE_INTEGRITY_LEN BIT(2)
|
pascal@20313
|
26 + int mode;
|
pascal@20313
|
27 + u8 secret[MD5_MESSAGE_BYTES];
|
pascal@20313
|
28 + int integrity_len;
|
pascal@20313
|
29 + u16 integrity_hash;
|
pascal@20313
|
30 + u32 tsval;
|
pascal@20313
|
31 + bool saw_tsval;
|
pascal@20313
|
32 + } stealth;
|
pascal@20313
|
33 +#endif
|
pascal@20313
|
34 +
|
pascal@20313
|
35 /* TCP fastopen related information */
|
pascal@20313
|
36 struct tcp_fastopen_request *fastopen_req;
|
pascal@20313
|
37 /* fastopen_rsk points to request_sock that resulted in this big
|
pascal@20313
|
38 diff -Nurp linux-3.16/include/net/secure_seq.h linux-3.16-knock/include/net/secure_seq.h
|
pascal@20313
|
39 --- linux-3.16/include/net/secure_seq.h 2014-08-03 18:25:02.000000000 -0400
|
pascal@20313
|
40 +++ linux-3.16-knock/include/net/secure_seq.h 2014-08-19 05:52:22.389447048 -0400
|
pascal@20313
|
41 @@ -14,5 +14,10 @@ u64 secure_dccp_sequence_number(__be32 s
|
pascal@20313
|
42 __be16 sport, __be16 dport);
|
pascal@20313
|
43 u64 secure_dccpv6_sequence_number(__be32 *saddr, __be32 *daddr,
|
pascal@20313
|
44 __be16 sport, __be16 dport);
|
pascal@20313
|
45 +#ifdef CONFIG_TCP_STEALTH
|
pascal@20313
|
46 +u32 tcp_stealth_do_auth(struct sock *sk, struct sk_buff *skb);
|
pascal@20313
|
47 +u32 tcp_stealth_sequence_number(struct sock *sk, __be32 *daddr,
|
pascal@20313
|
48 + u32 daddr_size, __be16 dport);
|
pascal@20313
|
49 +#endif
|
pascal@20313
|
50
|
pascal@20313
|
51 #endif /* _NET_SECURE_SEQ */
|
pascal@20313
|
52 diff -Nurp linux-3.16/include/net/tcp.h linux-3.16-knock/include/net/tcp.h
|
pascal@20313
|
53 --- linux-3.16/include/net/tcp.h 2014-08-03 18:25:02.000000000 -0400
|
pascal@20313
|
54 +++ linux-3.16-knock/include/net/tcp.h 2014-08-11 07:16:15.968418122 -0400
|
pascal@20313
|
55 @@ -442,6 +442,12 @@ void tcp_parse_options(const struct sk_b
|
pascal@20313
|
56 struct tcp_options_received *opt_rx,
|
pascal@20313
|
57 int estab, struct tcp_fastopen_cookie *foc);
|
pascal@20313
|
58 const u8 *tcp_parse_md5sig_option(const struct tcphdr *th);
|
pascal@20313
|
59 +#ifdef CONFIG_TCP_STEALTH
|
pascal@20313
|
60 +const bool tcp_parse_tsval_option(u32 *tsval, const struct tcphdr *th);
|
pascal@20313
|
61 +int tcp_stealth_integrity(u16 *hash, u8 *secret, u8 *payload, int len);
|
pascal@20313
|
62 +#define be32_isn_to_be16_av(x) (((__be16 *)&x)[0])
|
pascal@20313
|
63 +#define be32_isn_to_be16_ih(x) (((__be16 *)&x)[1])
|
pascal@20313
|
64 +#endif
|
pascal@20313
|
65
|
pascal@20313
|
66 /*
|
pascal@20313
|
67 * TCP v4 functions exported for the inet6 API
|
pascal@20313
|
68 diff -Nurp linux-3.16/include/uapi/linux/tcp.h linux-3.16-knock/include/uapi/linux/tcp.h
|
pascal@20313
|
69 --- linux-3.16/include/uapi/linux/tcp.h 2014-08-03 18:25:02.000000000 -0400
|
pascal@20313
|
70 +++ linux-3.16-knock/include/uapi/linux/tcp.h 2014-08-11 07:16:15.968418122 -0400
|
pascal@20313
|
71 @@ -112,6 +112,9 @@ enum {
|
pascal@20313
|
72 #define TCP_FASTOPEN 23 /* Enable FastOpen on listeners */
|
pascal@20313
|
73 #define TCP_TIMESTAMP 24
|
pascal@20313
|
74 #define TCP_NOTSENT_LOWAT 25 /* limit number of unsent bytes in write queue */
|
pascal@20313
|
75 +#define TCP_STEALTH 26
|
pascal@20313
|
76 +#define TCP_STEALTH_INTEGRITY 27
|
pascal@20313
|
77 +#define TCP_STEALTH_INTEGRITY_LEN 28
|
pascal@20313
|
78
|
pascal@20313
|
79 struct tcp_repair_opt {
|
pascal@20313
|
80 __u32 opt_code;
|
pascal@20313
|
81 diff -Nurp linux-3.16/net/core/secure_seq.c linux-3.16-knock/net/core/secure_seq.c
|
pascal@20313
|
82 --- linux-3.16/net/core/secure_seq.c 2014-08-03 18:25:02.000000000 -0400
|
pascal@20313
|
83 +++ linux-3.16-knock/net/core/secure_seq.c 2014-08-19 06:19:31.241519904 -0400
|
pascal@20313
|
84 @@ -8,7 +8,11 @@
|
pascal@20313
|
85 #include <linux/ktime.h>
|
pascal@20313
|
86 #include <linux/string.h>
|
pascal@20313
|
87 #include <linux/net.h>
|
pascal@20313
|
88 +#include <linux/socket.h>
|
pascal@20313
|
89 +#include <linux/ip.h>
|
pascal@20313
|
90 +#include <linux/ipv6.h>
|
pascal@20313
|
91
|
pascal@20313
|
92 +#include <net/tcp.h>
|
pascal@20313
|
93 #include <net/secure_seq.h>
|
pascal@20313
|
94
|
pascal@20313
|
95 #if IS_ENABLED(CONFIG_IPV6) || IS_ENABLED(CONFIG_INET)
|
pascal@20313
|
96 @@ -39,6 +43,102 @@ static u32 seq_scale(u32 seq)
|
pascal@20313
|
97 }
|
pascal@20313
|
98 #endif
|
pascal@20313
|
99
|
pascal@20313
|
100 +#ifdef CONFIG_TCP_STEALTH
|
pascal@20313
|
101 +u32 tcp_stealth_sequence_number(struct sock *sk, __be32 *daddr,
|
pascal@20313
|
102 + u32 daddr_size, __be16 dport)
|
pascal@20313
|
103 +{
|
pascal@20313
|
104 + struct tcp_sock *tp = tcp_sk(sk);
|
pascal@20313
|
105 + struct tcp_md5sig_key *md5;
|
pascal@20313
|
106 +
|
pascal@20313
|
107 + __u32 sec[MD5_MESSAGE_BYTES / sizeof(__u32)];
|
pascal@20313
|
108 + __u32 i;
|
pascal@20313
|
109 + __u32 tsval = 0;
|
pascal@20313
|
110 +
|
pascal@20313
|
111 + __be32 iv[MD5_DIGEST_WORDS] = { 0 };
|
pascal@20313
|
112 + __be32 isn;
|
pascal@20313
|
113 +
|
pascal@20313
|
114 + memcpy(iv, (const __u8 *)daddr,
|
pascal@20313
|
115 + (daddr_size > sizeof(iv)) ? sizeof(iv) : daddr_size);
|
pascal@20313
|
116 +
|
pascal@20313
|
117 +#ifdef CONFIG_TCP_MD5SIG
|
pascal@20313
|
118 + md5 = tp->af_specific->md5_lookup(sk, sk);
|
pascal@20313
|
119 +#else
|
pascal@20313
|
120 + md5 = NULL;
|
pascal@20313
|
121 +#endif
|
pascal@20313
|
122 + if (likely(sysctl_tcp_timestamps && !md5) || tp->stealth.saw_tsval)
|
pascal@20313
|
123 + tsval = tp->stealth.tsval;
|
pascal@20313
|
124 +
|
pascal@20313
|
125 + ((__be16 *)iv)[2] ^= cpu_to_be16(tp->stealth.integrity_hash);
|
pascal@20313
|
126 + iv[2] ^= cpu_to_be32(tsval);
|
pascal@20313
|
127 + ((__be16 *)iv)[6] ^= dport;
|
pascal@20313
|
128 +
|
pascal@20313
|
129 + for (i = 0; i < MD5_DIGEST_WORDS; i++)
|
pascal@20313
|
130 + iv[i] = le32_to_cpu(iv[i]);
|
pascal@20313
|
131 + for (i = 0; i < MD5_MESSAGE_BYTES / sizeof(__le32); i++)
|
pascal@20313
|
132 + sec[i] = le32_to_cpu(((__le32 *)tp->stealth.secret)[i]);
|
pascal@20313
|
133 +
|
pascal@20313
|
134 + md5_transform(iv, sec);
|
pascal@20313
|
135 +
|
pascal@20313
|
136 + isn = cpu_to_be32(iv[0]) ^ cpu_to_be32(iv[1]) ^
|
pascal@20313
|
137 + cpu_to_be32(iv[2]) ^ cpu_to_be32(iv[3]);
|
pascal@20313
|
138 +
|
pascal@20313
|
139 + if (tp->stealth.mode & TCP_STEALTH_MODE_INTEGRITY)
|
pascal@20313
|
140 + be32_isn_to_be16_ih(isn) =
|
pascal@20313
|
141 + cpu_to_be16(tp->stealth.integrity_hash);
|
pascal@20313
|
142 +
|
pascal@20313
|
143 + return be32_to_cpu(isn);
|
pascal@20313
|
144 +}
|
pascal@20313
|
145 +EXPORT_SYMBOL(tcp_stealth_sequence_number);
|
pascal@20313
|
146 +
|
pascal@20313
|
147 +u32 tcp_stealth_do_auth(struct sock *sk, struct sk_buff *skb)
|
pascal@20313
|
148 +{
|
pascal@20313
|
149 + struct tcp_sock *tp = tcp_sk(sk);
|
pascal@20313
|
150 + struct tcphdr *th = tcp_hdr(skb);
|
pascal@20313
|
151 + __be32 isn = th->seq;
|
pascal@20313
|
152 + __be32 hash;
|
pascal@20313
|
153 + __be32 *daddr;
|
pascal@20313
|
154 + u32 daddr_size;
|
pascal@20313
|
155 +
|
pascal@20313
|
156 + tp->stealth.saw_tsval = tcp_parse_tsval_option(&tp->stealth.tsval, th);
|
pascal@20313
|
157 +
|
pascal@20313
|
158 + if (tp->stealth.mode & TCP_STEALTH_MODE_INTEGRITY_LEN)
|
pascal@20313
|
159 + tp->stealth.integrity_hash =
|
pascal@20313
|
160 + be16_to_cpu(be32_isn_to_be16_ih(isn));
|
pascal@20313
|
161 +
|
pascal@20313
|
162 + switch (tp->inet_conn.icsk_inet.sk.sk_family) {
|
pascal@20313
|
163 +#if IS_ENABLED(CONFIG_IPV6)
|
pascal@20313
|
164 + case PF_INET6:
|
pascal@20313
|
165 + daddr_size = sizeof(ipv6_hdr(skb)->daddr.s6_addr32);
|
pascal@20313
|
166 + daddr = ipv6_hdr(skb)->daddr.s6_addr32;
|
pascal@20313
|
167 + break;
|
pascal@20313
|
168 +#endif
|
pascal@20313
|
169 + case PF_INET:
|
pascal@20313
|
170 + daddr_size = sizeof(ip_hdr(skb)->daddr);
|
pascal@20313
|
171 + daddr = &ip_hdr(skb)->daddr;
|
pascal@20313
|
172 + break;
|
pascal@20313
|
173 + default:
|
pascal@20313
|
174 + pr_err("TCP Stealth: Unknown network layer protocol, stop!\n");
|
pascal@20313
|
175 + return 1;
|
pascal@20313
|
176 + }
|
pascal@20313
|
177 +
|
pascal@20313
|
178 + hash = tcp_stealth_sequence_number(sk, daddr, daddr_size, th->dest);
|
pascal@20313
|
179 + cpu_to_be32s(&hash);
|
pascal@20313
|
180 +
|
pascal@20313
|
181 + if (tp->stealth.mode & TCP_STEALTH_MODE_AUTH &&
|
pascal@20313
|
182 + tp->stealth.mode & TCP_STEALTH_MODE_INTEGRITY_LEN &&
|
pascal@20313
|
183 + be32_isn_to_be16_av(isn) == be32_isn_to_be16_av(hash))
|
pascal@20313
|
184 + return 0;
|
pascal@20313
|
185 +
|
pascal@20313
|
186 + if (tp->stealth.mode & TCP_STEALTH_MODE_AUTH &&
|
pascal@20313
|
187 + !(tp->stealth.mode & TCP_STEALTH_MODE_INTEGRITY_LEN) &&
|
pascal@20313
|
188 + isn == hash)
|
pascal@20313
|
189 + return 0;
|
pascal@20313
|
190 +
|
pascal@20313
|
191 + return 1;
|
pascal@20313
|
192 +}
|
pascal@20313
|
193 +EXPORT_SYMBOL(tcp_stealth_do_auth);
|
pascal@20313
|
194 +#endif
|
pascal@20313
|
195 +
|
pascal@20313
|
196 #if IS_ENABLED(CONFIG_IPV6)
|
pascal@20313
|
197 __u32 secure_tcpv6_sequence_number(const __be32 *saddr, const __be32 *daddr,
|
pascal@20313
|
198 __be16 sport, __be16 dport)
|
pascal@20313
|
199 diff -Nurp linux-3.16/net/ipv4/Kconfig linux-3.16-knock/net/ipv4/Kconfig
|
pascal@20313
|
200 --- linux-3.16/net/ipv4/Kconfig 2014-08-03 18:25:02.000000000 -0400
|
pascal@20313
|
201 +++ linux-3.16-knock/net/ipv4/Kconfig 2014-08-11 07:16:15.968418122 -0400
|
pascal@20313
|
202 @@ -618,3 +618,13 @@ config TCP_MD5SIG
|
pascal@20313
|
203 on the Internet.
|
pascal@20313
|
204
|
pascal@20313
|
205 If unsure, say N.
|
pascal@20313
|
206 +
|
pascal@20313
|
207 +config TCP_STEALTH
|
pascal@20313
|
208 + bool "TCP: Stealth TCP socket support"
|
pascal@20313
|
209 + default n
|
pascal@20313
|
210 + ---help---
|
pascal@20313
|
211 + This option enables support for stealth TCP sockets. If you do not
|
pascal@20313
|
212 + know what this means, you do not need it.
|
pascal@20313
|
213 +
|
pascal@20313
|
214 + If unsure, say N.
|
pascal@20313
|
215 +
|
pascal@20313
|
216 diff -Nurp linux-3.16/net/ipv4/tcp.c linux-3.16-knock/net/ipv4/tcp.c
|
pascal@20313
|
217 --- linux-3.16/net/ipv4/tcp.c 2014-08-03 18:25:02.000000000 -0400
|
pascal@20313
|
218 +++ linux-3.16-knock/net/ipv4/tcp.c 2014-08-19 06:17:19.497514011 -0400
|
pascal@20313
|
219 @@ -2443,6 +2443,43 @@ static int tcp_repair_options_est(struct
|
pascal@20313
|
220 return 0;
|
pascal@20313
|
221 }
|
pascal@20313
|
222
|
pascal@20313
|
223 +#ifdef CONFIG_TCP_STEALTH
|
pascal@20313
|
224 +int tcp_stealth_integrity(__be16 *hash, u8 *secret, u8 *payload, int len)
|
pascal@20313
|
225 +{
|
pascal@20313
|
226 + struct scatterlist sg[2];
|
pascal@20313
|
227 + struct crypto_hash *tfm;
|
pascal@20313
|
228 + struct hash_desc desc;
|
pascal@20313
|
229 + __be16 h[MD5_DIGEST_WORDS * 2];
|
pascal@20313
|
230 + int i;
|
pascal@20313
|
231 + int err = 0;
|
pascal@20313
|
232 +
|
pascal@20313
|
233 + tfm = crypto_alloc_hash("md5", 0, CRYPTO_ALG_ASYNC);
|
pascal@20313
|
234 + if (IS_ERR(tfm)) {
|
pascal@20313
|
235 + err = -PTR_ERR(tfm);
|
pascal@20313
|
236 + goto out;
|
pascal@20313
|
237 + }
|
pascal@20313
|
238 + desc.tfm = tfm;
|
pascal@20313
|
239 + desc.flags = 0;
|
pascal@20313
|
240 +
|
pascal@20313
|
241 + sg_init_table(sg, 2);
|
pascal@20313
|
242 + sg_set_buf(&sg[0], secret, MD5_MESSAGE_BYTES);
|
pascal@20313
|
243 + sg_set_buf(&sg[1], payload, len);
|
pascal@20313
|
244 +
|
pascal@20313
|
245 + if (crypto_hash_digest(&desc, sg, MD5_MESSAGE_BYTES + len, (u8 *)h)) {
|
pascal@20313
|
246 + err = -EFAULT;
|
pascal@20313
|
247 + goto out;
|
pascal@20313
|
248 + }
|
pascal@20313
|
249 +
|
pascal@20313
|
250 + *hash = be16_to_cpu(h[0]);
|
pascal@20313
|
251 + for (i = 1; i < MD5_DIGEST_WORDS * 2; i++)
|
pascal@20313
|
252 + *hash ^= be16_to_cpu(h[i]);
|
pascal@20313
|
253 +
|
pascal@20313
|
254 +out:
|
pascal@20313
|
255 + crypto_free_hash(tfm);
|
pascal@20313
|
256 + return err;
|
pascal@20313
|
257 +}
|
pascal@20313
|
258 +#endif
|
pascal@20313
|
259 +
|
pascal@20313
|
260 /*
|
pascal@20313
|
261 * Socket option code for TCP.
|
pascal@20313
|
262 */
|
pascal@20313
|
263 @@ -2473,6 +2510,67 @@ static int do_tcp_setsockopt(struct sock
|
pascal@20313
|
264 release_sock(sk);
|
pascal@20313
|
265 return err;
|
pascal@20313
|
266 }
|
pascal@20313
|
267 +#ifdef CONFIG_TCP_STEALTH
|
pascal@20313
|
268 + case TCP_STEALTH: {
|
pascal@20313
|
269 + u8 secret[MD5_MESSAGE_BYTES];
|
pascal@20313
|
270 +
|
pascal@20313
|
271 + if (optlen < MD5_MESSAGE_BYTES)
|
pascal@20313
|
272 + return -EINVAL;
|
pascal@20313
|
273 +
|
pascal@20313
|
274 + val = copy_from_user(secret, optval, MD5_MESSAGE_BYTES);
|
pascal@20313
|
275 + if (val != 0)
|
pascal@20313
|
276 + return -EFAULT;
|
pascal@20313
|
277 +
|
pascal@20313
|
278 + lock_sock(sk);
|
pascal@20313
|
279 + memcpy(tp->stealth.secret, secret, MD5_MESSAGE_BYTES);
|
pascal@20313
|
280 + tp->stealth.mode = TCP_STEALTH_MODE_AUTH;
|
pascal@20313
|
281 + tp->stealth.tsval = 0;
|
pascal@20313
|
282 + tp->stealth.saw_tsval = false;
|
pascal@20313
|
283 + release_sock(sk);
|
pascal@20313
|
284 + return err;
|
pascal@20313
|
285 + }
|
pascal@20313
|
286 + case TCP_STEALTH_INTEGRITY: {
|
pascal@20313
|
287 + u8 *payload;
|
pascal@20313
|
288 +
|
pascal@20313
|
289 + lock_sock(sk);
|
pascal@20313
|
290 +
|
pascal@20313
|
291 + if (!(tp->stealth.mode & TCP_STEALTH_MODE_AUTH)) {
|
pascal@20313
|
292 + err = -EOPNOTSUPP;
|
pascal@20313
|
293 + goto stealth_integrity_out_1;
|
pascal@20313
|
294 + }
|
pascal@20313
|
295 +
|
pascal@20313
|
296 + if (optlen < 1 || optlen > USHRT_MAX) {
|
pascal@20313
|
297 + err = -EINVAL;
|
pascal@20313
|
298 + goto stealth_integrity_out_1;
|
pascal@20313
|
299 + }
|
pascal@20313
|
300 +
|
pascal@20313
|
301 + payload = vmalloc(optlen);
|
pascal@20313
|
302 + if (!payload) {
|
pascal@20313
|
303 + err = -ENOMEM;
|
pascal@20313
|
304 + goto stealth_integrity_out_1;
|
pascal@20313
|
305 + }
|
pascal@20313
|
306 +
|
pascal@20313
|
307 + val = copy_from_user(payload, optval, optlen);
|
pascal@20313
|
308 + if (val != 0) {
|
pascal@20313
|
309 + err = -EFAULT;
|
pascal@20313
|
310 + goto stealth_integrity_out_2;
|
pascal@20313
|
311 + }
|
pascal@20313
|
312 +
|
pascal@20313
|
313 + err = tcp_stealth_integrity(&tp->stealth.integrity_hash,
|
pascal@20313
|
314 + tp->stealth.secret, payload,
|
pascal@20313
|
315 + optlen);
|
pascal@20313
|
316 + if (err)
|
pascal@20313
|
317 + goto stealth_integrity_out_2;
|
pascal@20313
|
318 +
|
pascal@20313
|
319 + tp->stealth.mode |= TCP_STEALTH_MODE_INTEGRITY;
|
pascal@20313
|
320 +
|
pascal@20313
|
321 +stealth_integrity_out_2:
|
pascal@20313
|
322 + vfree(payload);
|
pascal@20313
|
323 +stealth_integrity_out_1:
|
pascal@20313
|
324 + release_sock(sk);
|
pascal@20313
|
325 + return err;
|
pascal@20313
|
326 + }
|
pascal@20313
|
327 +#endif
|
pascal@20313
|
328 default:
|
pascal@20313
|
329 /* fallthru */
|
pascal@20313
|
330 break;
|
pascal@20313
|
331 @@ -2717,6 +2815,18 @@ static int do_tcp_setsockopt(struct sock
|
pascal@20313
|
332 tp->notsent_lowat = val;
|
pascal@20313
|
333 sk->sk_write_space(sk);
|
pascal@20313
|
334 break;
|
pascal@20313
|
335 +#ifdef CONFIG_TCP_STEALTH
|
pascal@20313
|
336 + case TCP_STEALTH_INTEGRITY_LEN:
|
pascal@20313
|
337 + if (!(tp->stealth.mode & TCP_STEALTH_MODE_AUTH)) {
|
pascal@20313
|
338 + err = -EOPNOTSUPP;
|
pascal@20313
|
339 + } else if (val < 1 || val > USHRT_MAX) {
|
pascal@20313
|
340 + err = -EINVAL;
|
pascal@20313
|
341 + } else {
|
pascal@20313
|
342 + tp->stealth.integrity_len = val;
|
pascal@20313
|
343 + tp->stealth.mode |= TCP_STEALTH_MODE_INTEGRITY_LEN;
|
pascal@20313
|
344 + }
|
pascal@20313
|
345 + break;
|
pascal@20313
|
346 +#endif
|
pascal@20313
|
347 default:
|
pascal@20313
|
348 err = -ENOPROTOOPT;
|
pascal@20313
|
349 break;
|
pascal@20313
|
350 diff -Nurp linux-3.16/net/ipv4/tcp_input.c linux-3.16-knock/net/ipv4/tcp_input.c
|
pascal@20313
|
351 --- linux-3.16/net/ipv4/tcp_input.c 2014-08-03 18:25:02.000000000 -0400
|
pascal@20313
|
352 +++ linux-3.16-knock/net/ipv4/tcp_input.c 2014-08-18 13:08:23.956054243 -0400
|
pascal@20313
|
353 @@ -76,6 +76,9 @@
|
pascal@20313
|
354 #include <net/netdma.h>
|
pascal@20313
|
355
|
pascal@20313
|
356 int sysctl_tcp_timestamps __read_mostly = 1;
|
pascal@20313
|
357 +#ifdef CONFIG_TCP_STEALTH
|
pascal@20313
|
358 +EXPORT_SYMBOL(sysctl_tcp_timestamps);
|
pascal@20313
|
359 +#endif
|
pascal@20313
|
360 int sysctl_tcp_window_scaling __read_mostly = 1;
|
pascal@20313
|
361 int sysctl_tcp_sack __read_mostly = 1;
|
pascal@20313
|
362 int sysctl_tcp_fack __read_mostly = 1;
|
pascal@20313
|
363 @@ -3666,6 +3669,47 @@ static bool tcp_fast_parse_options(const
|
pascal@20313
|
364 return true;
|
pascal@20313
|
365 }
|
pascal@20313
|
366
|
pascal@20313
|
367 +#ifdef CONFIG_TCP_STEALTH
|
pascal@20313
|
368 +/* Parse only the TSVal field of the TCP Timestamp option header.
|
pascal@20313
|
369 + */
|
pascal@20313
|
370 +const bool tcp_parse_tsval_option(u32 *tsval, const struct tcphdr *th)
|
pascal@20313
|
371 +{
|
pascal@20313
|
372 + int length = (th->doff << 2) - sizeof(*th);
|
pascal@20313
|
373 + const u8 *ptr = (const u8 *)(th + 1);
|
pascal@20313
|
374 +
|
pascal@20313
|
375 + /* If the TCP option is too short, we can short cut */
|
pascal@20313
|
376 + if (length < TCPOLEN_TIMESTAMP)
|
pascal@20313
|
377 + return false;
|
pascal@20313
|
378 +
|
pascal@20313
|
379 + while (length > 0) {
|
pascal@20313
|
380 + int opcode = *ptr++;
|
pascal@20313
|
381 + int opsize;
|
pascal@20313
|
382 +
|
pascal@20313
|
383 + switch (opcode) {
|
pascal@20313
|
384 + case TCPOPT_EOL:
|
pascal@20313
|
385 + return false;
|
pascal@20313
|
386 + case TCPOPT_NOP:
|
pascal@20313
|
387 + length--;
|
pascal@20313
|
388 + continue;
|
pascal@20313
|
389 + case TCPOPT_TIMESTAMP:
|
pascal@20313
|
390 + opsize = *ptr++;
|
pascal@20313
|
391 + if (opsize != TCPOLEN_TIMESTAMP || opsize > length)
|
pascal@20313
|
392 + return false;
|
pascal@20313
|
393 + *tsval = get_unaligned_be32(ptr);
|
pascal@20313
|
394 + return true;
|
pascal@20313
|
395 + default:
|
pascal@20313
|
396 + opsize = *ptr++;
|
pascal@20313
|
397 + if (opsize < 2 || opsize > length)
|
pascal@20313
|
398 + return false;
|
pascal@20313
|
399 + }
|
pascal@20313
|
400 + ptr += opsize - 2;
|
pascal@20313
|
401 + length -= opsize;
|
pascal@20313
|
402 + }
|
pascal@20313
|
403 + return false;
|
pascal@20313
|
404 +}
|
pascal@20313
|
405 +EXPORT_SYMBOL(tcp_parse_tsval_option);
|
pascal@20313
|
406 +#endif
|
pascal@20313
|
407 +
|
pascal@20313
|
408 #ifdef CONFIG_TCP_MD5SIG
|
pascal@20313
|
409 /*
|
pascal@20313
|
410 * Parse MD5 Signature option
|
pascal@20313
|
411 @@ -4337,6 +4381,31 @@ err:
|
pascal@20313
|
412 return -ENOMEM;
|
pascal@20313
|
413 }
|
pascal@20313
|
414
|
pascal@20313
|
415 +#ifdef CONFIG_TCP_STEALTH
|
pascal@20313
|
416 +static int __tcp_stealth_integrity_check(struct sock *sk, struct sk_buff *skb)
|
pascal@20313
|
417 +{
|
pascal@20313
|
418 + struct tcphdr *th = tcp_hdr(skb);
|
pascal@20313
|
419 + struct tcp_sock *tp = tcp_sk(sk);
|
pascal@20313
|
420 + u16 hash;
|
pascal@20313
|
421 + __be32 seq = cpu_to_be32(TCP_SKB_CB(skb)->seq - 1);
|
pascal@20313
|
422 + char *data = skb->data + th->doff * 4;
|
pascal@20313
|
423 + int len = skb->len - th->doff * 4;
|
pascal@20313
|
424 +
|
pascal@20313
|
425 + if (len < tp->stealth.integrity_len)
|
pascal@20313
|
426 + return 1;
|
pascal@20313
|
427 +
|
pascal@20313
|
428 + if (tcp_stealth_integrity(&hash, tp->stealth.secret, data,
|
pascal@20313
|
429 + tp->stealth.integrity_len))
|
pascal@20313
|
430 + return 1;
|
pascal@20313
|
431 +
|
pascal@20313
|
432 + if (be32_isn_to_be16_ih(seq) != cpu_to_be16(hash))
|
pascal@20313
|
433 + return 1;
|
pascal@20313
|
434 +
|
pascal@20313
|
435 + tp->stealth.mode &= ~TCP_STEALTH_MODE_INTEGRITY_LEN;
|
pascal@20313
|
436 + return 0;
|
pascal@20313
|
437 +}
|
pascal@20313
|
438 +#endif
|
pascal@20313
|
439 +
|
pascal@20313
|
440 static void tcp_data_queue(struct sock *sk, struct sk_buff *skb)
|
pascal@20313
|
441 {
|
pascal@20313
|
442 const struct tcphdr *th = tcp_hdr(skb);
|
pascal@20313
|
443 @@ -4347,6 +4416,14 @@ static void tcp_data_queue(struct sock *
|
pascal@20313
|
444 if (TCP_SKB_CB(skb)->seq == TCP_SKB_CB(skb)->end_seq)
|
pascal@20313
|
445 goto drop;
|
pascal@20313
|
446
|
pascal@20313
|
447 +#ifdef CONFIG_TCP_STEALTH
|
pascal@20313
|
448 + if (unlikely(tp->stealth.mode & TCP_STEALTH_MODE_INTEGRITY_LEN) &&
|
pascal@20313
|
449 + __tcp_stealth_integrity_check(sk, skb)) {
|
pascal@20313
|
450 + tcp_reset(sk);
|
pascal@20313
|
451 + goto drop;
|
pascal@20313
|
452 + }
|
pascal@20313
|
453 +#endif
|
pascal@20313
|
454 +
|
pascal@20313
|
455 skb_dst_drop(skb);
|
pascal@20313
|
456 __skb_pull(skb, th->doff * 4);
|
pascal@20313
|
457
|
pascal@20313
|
458 @@ -5171,6 +5248,15 @@ void tcp_rcv_established(struct sock *sk
|
pascal@20313
|
459 int copied_early = 0;
|
pascal@20313
|
460 bool fragstolen = false;
|
pascal@20313
|
461
|
pascal@20313
|
462 +#ifdef CONFIG_TCP_STEALTH
|
pascal@20313
|
463 + if (unlikely(tp->stealth.mode &
|
pascal@20313
|
464 + TCP_STEALTH_MODE_INTEGRITY_LEN) &&
|
pascal@20313
|
465 + __tcp_stealth_integrity_check(sk, skb)) {
|
pascal@20313
|
466 + tcp_reset(sk);
|
pascal@20313
|
467 + goto discard;
|
pascal@20313
|
468 + }
|
pascal@20313
|
469 +#endif
|
pascal@20313
|
470 +
|
pascal@20313
|
471 if (tp->copied_seq == tp->rcv_nxt &&
|
pascal@20313
|
472 len - tcp_header_len <= tp->ucopy.len) {
|
pascal@20313
|
473 #ifdef CONFIG_NET_DMA
|
pascal@20313
|
474 diff -Nurp linux-3.16/net/ipv4/tcp_ipv4.c linux-3.16-knock/net/ipv4/tcp_ipv4.c
|
pascal@20313
|
475 --- linux-3.16/net/ipv4/tcp_ipv4.c 2014-08-03 18:25:02.000000000 -0400
|
pascal@20313
|
476 +++ linux-3.16-knock/net/ipv4/tcp_ipv4.c 2014-08-19 05:50:27.217441897 -0400
|
pascal@20313
|
477 @@ -76,6 +76,7 @@
|
pascal@20313
|
478 #include <net/secure_seq.h>
|
pascal@20313
|
479 #include <net/tcp_memcontrol.h>
|
pascal@20313
|
480 #include <net/busy_poll.h>
|
pascal@20313
|
481 +#include <net/secure_seq.h>
|
pascal@20313
|
482
|
pascal@20313
|
483 #include <linux/inet.h>
|
pascal@20313
|
484 #include <linux/ipv6.h>
|
pascal@20313
|
485 @@ -235,6 +236,21 @@ int tcp_v4_connect(struct sock *sk, stru
|
pascal@20313
|
486 sk->sk_gso_type = SKB_GSO_TCPV4;
|
pascal@20313
|
487 sk_setup_caps(sk, &rt->dst);
|
pascal@20313
|
488
|
pascal@20313
|
489 +#ifdef CONFIG_TCP_STEALTH
|
pascal@20313
|
490 + /* If CONFIG_TCP_STEALTH is defined, we need to know the timestamp as
|
pascal@20313
|
491 + * early as possible and thus move taking the snapshot of tcp_time_stamp
|
pascal@20313
|
492 + * here.
|
pascal@20313
|
493 + */
|
pascal@20313
|
494 + tp->stealth.tsval = tcp_time_stamp;
|
pascal@20313
|
495 +
|
pascal@20313
|
496 + if (!tp->write_seq && likely(!tp->repair) &&
|
pascal@20313
|
497 + unlikely(tp->stealth.mode & TCP_STEALTH_MODE_AUTH))
|
pascal@20313
|
498 + tp->write_seq = tcp_stealth_sequence_number(sk,
|
pascal@20313
|
499 + &inet->inet_daddr,
|
pascal@20313
|
500 + sizeof(inet->inet_daddr),
|
pascal@20313
|
501 + usin->sin_port);
|
pascal@20313
|
502 +#endif
|
pascal@20313
|
503 +
|
pascal@20313
|
504 if (!tp->write_seq && likely(!tp->repair))
|
pascal@20313
|
505 tp->write_seq = secure_tcp_sequence_number(inet->inet_saddr,
|
pascal@20313
|
506 inet->inet_daddr,
|
pascal@20313
|
507 @@ -1546,6 +1562,8 @@ static struct sock *tcp_v4_hnd_req(struc
|
pascal@20313
|
508 */
|
pascal@20313
|
509 int tcp_v4_do_rcv(struct sock *sk, struct sk_buff *skb)
|
pascal@20313
|
510 {
|
pascal@20313
|
511 + struct tcp_sock *tp = tcp_sk(sk);
|
pascal@20313
|
512 + struct tcphdr *th = tcp_hdr(skb);
|
pascal@20313
|
513 struct sock *rsk;
|
pascal@20313
|
514 #ifdef CONFIG_TCP_MD5SIG
|
pascal@20313
|
515 /*
|
pascal@20313
|
516 @@ -1576,6 +1594,15 @@ int tcp_v4_do_rcv(struct sock *sk, struc
|
pascal@20313
|
517 if (skb->len < tcp_hdrlen(skb) || tcp_checksum_complete(skb))
|
pascal@20313
|
518 goto csum_err;
|
pascal@20313
|
519
|
pascal@20313
|
520 +#ifdef CONFIG_TCP_STEALTH
|
pascal@20313
|
521 + if (sk->sk_state == TCP_LISTEN && th->syn && !th->fin &&
|
pascal@20313
|
522 + unlikely(tp->stealth.mode & TCP_STEALTH_MODE_AUTH) &&
|
pascal@20313
|
523 + tcp_stealth_do_auth(sk, skb)) {
|
pascal@20313
|
524 + rsk = sk;
|
pascal@20313
|
525 + goto reset;
|
pascal@20313
|
526 + }
|
pascal@20313
|
527 +#endif
|
pascal@20313
|
528 +
|
pascal@20313
|
529 if (sk->sk_state == TCP_LISTEN) {
|
pascal@20313
|
530 struct sock *nsk = tcp_v4_hnd_req(sk, skb);
|
pascal@20313
|
531 if (!nsk)
|
pascal@20313
|
532 diff -Nurp linux-3.16/net/ipv4/tcp_output.c linux-3.16-knock/net/ipv4/tcp_output.c
|
pascal@20313
|
533 --- linux-3.16/net/ipv4/tcp_output.c 2014-08-03 18:25:02.000000000 -0400
|
pascal@20313
|
534 +++ linux-3.16-knock/net/ipv4/tcp_output.c 2014-08-11 07:29:32.776405670 -0400
|
pascal@20313
|
535 @@ -2486,10 +2486,22 @@ int __tcp_retransmit_skb(struct sock *sk
|
pascal@20313
|
536
|
pascal@20313
|
537 tcp_retrans_try_collapse(sk, skb, cur_mss);
|
pascal@20313
|
538
|
pascal@20313
|
539 +#ifdef CONFIG_TCP_STEALTH
|
pascal@20313
|
540 + if (unlikely(TCP_SKB_CB(skb)->tcp_flags & TCPHDR_SYN &&
|
pascal@20313
|
541 + tp->stealth.mode & TCP_STEALTH_MODE_AUTH)) {
|
pascal@20313
|
542 + /* If TCP stealth is active, reuse the timestamp from the first
|
pascal@20313
|
543 + * SYN.
|
pascal@20313
|
544 + */
|
pascal@20313
|
545 + TCP_SKB_CB(skb)->when = tp->stealth.tsval;
|
pascal@20313
|
546 + } else {
|
pascal@20313
|
547 + TCP_SKB_CB(skb)->when = tcp_time_stamp;
|
pascal@20313
|
548 + }
|
pascal@20313
|
549 +#else
|
pascal@20313
|
550 /* Make a copy, if the first transmission SKB clone we made
|
pascal@20313
|
551 * is still in somebody's hands, else make a clone.
|
pascal@20313
|
552 */
|
pascal@20313
|
553 TCP_SKB_CB(skb)->when = tcp_time_stamp;
|
pascal@20313
|
554 +#endif
|
pascal@20313
|
555
|
pascal@20313
|
556 /* make sure skb->data is aligned on arches that require it
|
pascal@20313
|
557 * and check if ack-trimming & collapsing extended the headroom
|
pascal@20313
|
558 @@ -3094,7 +3106,15 @@ int tcp_connect(struct sock *sk)
|
pascal@20313
|
559 return -ENOBUFS;
|
pascal@20313
|
560
|
pascal@20313
|
561 tcp_init_nondata_skb(buff, tp->write_seq++, TCPHDR_SYN);
|
pascal@20313
|
562 +#ifdef CONFIG_TCP_STEALTH
|
pascal@20313
|
563 + /* The timetamp was already set at the time the ISN was generated
|
pascal@20313
|
564 + * as we need to know its value in the stealth_tcp_sequence_number()
|
pascal@20313
|
565 + * function.
|
pascal@20313
|
566 + */
|
pascal@20313
|
567 + tp->retrans_stamp = TCP_SKB_CB(buff)->when = tp->stealth.tsval;
|
pascal@20313
|
568 +#else
|
pascal@20313
|
569 tp->retrans_stamp = TCP_SKB_CB(buff)->when = tcp_time_stamp;
|
pascal@20313
|
570 +#endif
|
pascal@20313
|
571 tcp_connect_queue_skb(sk, buff);
|
pascal@20313
|
572 TCP_ECN_send_syn(sk, buff);
|
pascal@20313
|
573
|
pascal@20313
|
574 diff -Nurp linux-3.16/net/ipv6/tcp_ipv6.c linux-3.16-knock/net/ipv6/tcp_ipv6.c
|
pascal@20313
|
575 --- linux-3.16/net/ipv6/tcp_ipv6.c 2014-08-03 18:25:02.000000000 -0400
|
pascal@20313
|
576 +++ linux-3.16-knock/net/ipv6/tcp_ipv6.c 2014-08-19 06:24:12.497532484 -0400
|
pascal@20313
|
577 @@ -64,6 +64,7 @@
|
pascal@20313
|
578 #include <net/secure_seq.h>
|
pascal@20313
|
579 #include <net/tcp_memcontrol.h>
|
pascal@20313
|
580 #include <net/busy_poll.h>
|
pascal@20313
|
581 +#include <net/secure_seq.h>
|
pascal@20313
|
582
|
pascal@20313
|
583 #include <linux/proc_fs.h>
|
pascal@20313
|
584 #include <linux/seq_file.h>
|
pascal@20313
|
585 @@ -294,6 +295,21 @@ static int tcp_v6_connect(struct sock *s
|
pascal@20313
|
586 if (err)
|
pascal@20313
|
587 goto late_failure;
|
pascal@20313
|
588
|
pascal@20313
|
589 +#ifdef CONFIG_TCP_STEALTH
|
pascal@20313
|
590 + /* If CONFIG_TCP_STEALTH is defined, we need to know the timestamp as
|
pascal@20313
|
591 + * early as possible and thus move taking the snapshot of tcp_time_stamp
|
pascal@20313
|
592 + * here.
|
pascal@20313
|
593 + */
|
pascal@20313
|
594 + tp->stealth.tsval = tcp_time_stamp;
|
pascal@20313
|
595 +
|
pascal@20313
|
596 + if (!tp->write_seq && likely(!tp->repair) &&
|
pascal@20313
|
597 + unlikely(tp->stealth.mode & TCP_STEALTH_MODE_AUTH))
|
pascal@20313
|
598 + tp->write_seq = tcp_stealth_sequence_number(sk,
|
pascal@20313
|
599 + sk->sk_v6_daddr.s6_addr32,
|
pascal@20313
|
600 + sizeof(sk->sk_v6_daddr),
|
pascal@20313
|
601 + inet->inet_dport);
|
pascal@20313
|
602 +#endif
|
pascal@20313
|
603 +
|
pascal@20313
|
604 if (!tp->write_seq && likely(!tp->repair))
|
pascal@20313
|
605 tp->write_seq = secure_tcpv6_sequence_number(np->saddr.s6_addr32,
|
pascal@20313
|
606 sk->sk_v6_daddr.s6_addr32,
|
pascal@20313
|
607 @@ -1343,7 +1359,8 @@ out:
|
pascal@20313
|
608 static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb)
|
pascal@20313
|
609 {
|
pascal@20313
|
610 struct ipv6_pinfo *np = inet6_sk(sk);
|
pascal@20313
|
611 - struct tcp_sock *tp;
|
pascal@20313
|
612 + struct tcp_sock *tp = tcp_sk(sk);
|
pascal@20313
|
613 + struct tcphdr *th = tcp_hdr(skb);
|
pascal@20313
|
614 struct sk_buff *opt_skb = NULL;
|
pascal@20313
|
615
|
pascal@20313
|
616 /* Imagine: socket is IPv6. IPv4 packet arrives,
|
pascal@20313
|
617 @@ -1407,6 +1424,13 @@ static int tcp_v6_do_rcv(struct sock *sk
|
pascal@20313
|
618 if (skb->len < tcp_hdrlen(skb) || tcp_checksum_complete(skb))
|
pascal@20313
|
619 goto csum_err;
|
pascal@20313
|
620
|
pascal@20313
|
621 +#ifdef CONFIG_TCP_STEALTH
|
pascal@20313
|
622 + if (sk->sk_state == TCP_LISTEN && th->syn && !th->fin &&
|
pascal@20313
|
623 + tp->stealth.mode & TCP_STEALTH_MODE_AUTH &&
|
pascal@20313
|
624 + tcp_stealth_do_auth(sk, skb))
|
pascal@20313
|
625 + goto reset;
|
pascal@20313
|
626 +#endif
|
pascal@20313
|
627 +
|
pascal@20313
|
628 if (sk->sk_state == TCP_LISTEN) {
|
pascal@20313
|
629 struct sock *nsk = tcp_v6_hnd_req(sk, skb);
|
pascal@20313
|
630 if (!nsk)
|