wok annotate linux/stuff/linux-tcp_stealth.u @ rev 25000

updated nms (0.3.3 -> 1.0.1)
author Hans-G?nter Theisgen
date Mon May 16 13:53:18 2022 +0100 (2022-05-16)
parents
children
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)