1*1da177e4SLinus Torvalds /* 2*1da177e4SLinus Torvalds * Syncookies implementation for the Linux kernel 3*1da177e4SLinus Torvalds * 4*1da177e4SLinus Torvalds * Copyright (C) 1997 Andi Kleen 5*1da177e4SLinus Torvalds * Based on ideas by D.J.Bernstein and Eric Schenk. 6*1da177e4SLinus Torvalds * 7*1da177e4SLinus Torvalds * This program is free software; you can redistribute it and/or 8*1da177e4SLinus Torvalds * modify it under the terms of the GNU General Public License 9*1da177e4SLinus Torvalds * as published by the Free Software Foundation; either version 10*1da177e4SLinus Torvalds * 2 of the License, or (at your option) any later version. 11*1da177e4SLinus Torvalds * 12*1da177e4SLinus Torvalds * $Id: syncookies.c,v 1.18 2002/02/01 22:01:04 davem Exp $ 13*1da177e4SLinus Torvalds * 14*1da177e4SLinus Torvalds * Missing: IPv6 support. 15*1da177e4SLinus Torvalds */ 16*1da177e4SLinus Torvalds 17*1da177e4SLinus Torvalds #include <linux/tcp.h> 18*1da177e4SLinus Torvalds #include <linux/slab.h> 19*1da177e4SLinus Torvalds #include <linux/random.h> 20*1da177e4SLinus Torvalds #include <linux/cryptohash.h> 21*1da177e4SLinus Torvalds #include <linux/kernel.h> 22*1da177e4SLinus Torvalds #include <net/tcp.h> 23*1da177e4SLinus Torvalds 24*1da177e4SLinus Torvalds extern int sysctl_tcp_syncookies; 25*1da177e4SLinus Torvalds 26*1da177e4SLinus Torvalds static __u32 syncookie_secret[2][16-3+SHA_DIGEST_WORDS]; 27*1da177e4SLinus Torvalds 28*1da177e4SLinus Torvalds static __init int init_syncookies(void) 29*1da177e4SLinus Torvalds { 30*1da177e4SLinus Torvalds get_random_bytes(syncookie_secret, sizeof(syncookie_secret)); 31*1da177e4SLinus Torvalds return 0; 32*1da177e4SLinus Torvalds } 33*1da177e4SLinus Torvalds module_init(init_syncookies); 34*1da177e4SLinus Torvalds 35*1da177e4SLinus Torvalds #define COOKIEBITS 24 /* Upper bits store count */ 36*1da177e4SLinus Torvalds #define COOKIEMASK (((__u32)1 << COOKIEBITS) - 1) 37*1da177e4SLinus Torvalds 38*1da177e4SLinus Torvalds static u32 cookie_hash(u32 saddr, u32 daddr, u32 sport, u32 dport, 39*1da177e4SLinus Torvalds u32 count, int c) 40*1da177e4SLinus Torvalds { 41*1da177e4SLinus Torvalds __u32 tmp[16 + 5 + SHA_WORKSPACE_WORDS]; 42*1da177e4SLinus Torvalds 43*1da177e4SLinus Torvalds memcpy(tmp + 3, syncookie_secret[c], sizeof(syncookie_secret[c])); 44*1da177e4SLinus Torvalds tmp[0] = saddr; 45*1da177e4SLinus Torvalds tmp[1] = daddr; 46*1da177e4SLinus Torvalds tmp[2] = (sport << 16) + dport; 47*1da177e4SLinus Torvalds tmp[3] = count; 48*1da177e4SLinus Torvalds sha_transform(tmp + 16, (__u8 *)tmp, tmp + 16 + 5); 49*1da177e4SLinus Torvalds 50*1da177e4SLinus Torvalds return tmp[17]; 51*1da177e4SLinus Torvalds } 52*1da177e4SLinus Torvalds 53*1da177e4SLinus Torvalds static __u32 secure_tcp_syn_cookie(__u32 saddr, __u32 daddr, __u16 sport, 54*1da177e4SLinus Torvalds __u16 dport, __u32 sseq, __u32 count, 55*1da177e4SLinus Torvalds __u32 data) 56*1da177e4SLinus Torvalds { 57*1da177e4SLinus Torvalds /* 58*1da177e4SLinus Torvalds * Compute the secure sequence number. 59*1da177e4SLinus Torvalds * The output should be: 60*1da177e4SLinus Torvalds * HASH(sec1,saddr,sport,daddr,dport,sec1) + sseq + (count * 2^24) 61*1da177e4SLinus Torvalds * + (HASH(sec2,saddr,sport,daddr,dport,count,sec2) % 2^24). 62*1da177e4SLinus Torvalds * Where sseq is their sequence number and count increases every 63*1da177e4SLinus Torvalds * minute by 1. 64*1da177e4SLinus Torvalds * As an extra hack, we add a small "data" value that encodes the 65*1da177e4SLinus Torvalds * MSS into the second hash value. 66*1da177e4SLinus Torvalds */ 67*1da177e4SLinus Torvalds 68*1da177e4SLinus Torvalds return (cookie_hash(saddr, daddr, sport, dport, 0, 0) + 69*1da177e4SLinus Torvalds sseq + (count << COOKIEBITS) + 70*1da177e4SLinus Torvalds ((cookie_hash(saddr, daddr, sport, dport, count, 1) + data) 71*1da177e4SLinus Torvalds & COOKIEMASK)); 72*1da177e4SLinus Torvalds } 73*1da177e4SLinus Torvalds 74*1da177e4SLinus Torvalds /* 75*1da177e4SLinus Torvalds * This retrieves the small "data" value from the syncookie. 76*1da177e4SLinus Torvalds * If the syncookie is bad, the data returned will be out of 77*1da177e4SLinus Torvalds * range. This must be checked by the caller. 78*1da177e4SLinus Torvalds * 79*1da177e4SLinus Torvalds * The count value used to generate the cookie must be within 80*1da177e4SLinus Torvalds * "maxdiff" if the current (passed-in) "count". The return value 81*1da177e4SLinus Torvalds * is (__u32)-1 if this test fails. 82*1da177e4SLinus Torvalds */ 83*1da177e4SLinus Torvalds static __u32 check_tcp_syn_cookie(__u32 cookie, __u32 saddr, __u32 daddr, 84*1da177e4SLinus Torvalds __u16 sport, __u16 dport, __u32 sseq, 85*1da177e4SLinus Torvalds __u32 count, __u32 maxdiff) 86*1da177e4SLinus Torvalds { 87*1da177e4SLinus Torvalds __u32 diff; 88*1da177e4SLinus Torvalds 89*1da177e4SLinus Torvalds /* Strip away the layers from the cookie */ 90*1da177e4SLinus Torvalds cookie -= cookie_hash(saddr, daddr, sport, dport, 0, 0) + sseq; 91*1da177e4SLinus Torvalds 92*1da177e4SLinus Torvalds /* Cookie is now reduced to (count * 2^24) ^ (hash % 2^24) */ 93*1da177e4SLinus Torvalds diff = (count - (cookie >> COOKIEBITS)) & ((__u32) - 1 >> COOKIEBITS); 94*1da177e4SLinus Torvalds if (diff >= maxdiff) 95*1da177e4SLinus Torvalds return (__u32)-1; 96*1da177e4SLinus Torvalds 97*1da177e4SLinus Torvalds return (cookie - 98*1da177e4SLinus Torvalds cookie_hash(saddr, daddr, sport, dport, count - diff, 1)) 99*1da177e4SLinus Torvalds & COOKIEMASK; /* Leaving the data behind */ 100*1da177e4SLinus Torvalds } 101*1da177e4SLinus Torvalds 102*1da177e4SLinus Torvalds /* 103*1da177e4SLinus Torvalds * This table has to be sorted and terminated with (__u16)-1. 104*1da177e4SLinus Torvalds * XXX generate a better table. 105*1da177e4SLinus Torvalds * Unresolved Issues: HIPPI with a 64k MSS is not well supported. 106*1da177e4SLinus Torvalds */ 107*1da177e4SLinus Torvalds static __u16 const msstab[] = { 108*1da177e4SLinus Torvalds 64 - 1, 109*1da177e4SLinus Torvalds 256 - 1, 110*1da177e4SLinus Torvalds 512 - 1, 111*1da177e4SLinus Torvalds 536 - 1, 112*1da177e4SLinus Torvalds 1024 - 1, 113*1da177e4SLinus Torvalds 1440 - 1, 114*1da177e4SLinus Torvalds 1460 - 1, 115*1da177e4SLinus Torvalds 4312 - 1, 116*1da177e4SLinus Torvalds (__u16)-1 117*1da177e4SLinus Torvalds }; 118*1da177e4SLinus Torvalds /* The number doesn't include the -1 terminator */ 119*1da177e4SLinus Torvalds #define NUM_MSS (ARRAY_SIZE(msstab) - 1) 120*1da177e4SLinus Torvalds 121*1da177e4SLinus Torvalds /* 122*1da177e4SLinus Torvalds * Generate a syncookie. mssp points to the mss, which is returned 123*1da177e4SLinus Torvalds * rounded down to the value encoded in the cookie. 124*1da177e4SLinus Torvalds */ 125*1da177e4SLinus Torvalds __u32 cookie_v4_init_sequence(struct sock *sk, struct sk_buff *skb, __u16 *mssp) 126*1da177e4SLinus Torvalds { 127*1da177e4SLinus Torvalds struct tcp_sock *tp = tcp_sk(sk); 128*1da177e4SLinus Torvalds int mssind; 129*1da177e4SLinus Torvalds const __u16 mss = *mssp; 130*1da177e4SLinus Torvalds 131*1da177e4SLinus Torvalds 132*1da177e4SLinus Torvalds tp->last_synq_overflow = jiffies; 133*1da177e4SLinus Torvalds 134*1da177e4SLinus Torvalds /* XXX sort msstab[] by probability? Binary search? */ 135*1da177e4SLinus Torvalds for (mssind = 0; mss > msstab[mssind + 1]; mssind++) 136*1da177e4SLinus Torvalds ; 137*1da177e4SLinus Torvalds *mssp = msstab[mssind] + 1; 138*1da177e4SLinus Torvalds 139*1da177e4SLinus Torvalds NET_INC_STATS_BH(LINUX_MIB_SYNCOOKIESSENT); 140*1da177e4SLinus Torvalds 141*1da177e4SLinus Torvalds return secure_tcp_syn_cookie(skb->nh.iph->saddr, skb->nh.iph->daddr, 142*1da177e4SLinus Torvalds skb->h.th->source, skb->h.th->dest, 143*1da177e4SLinus Torvalds ntohl(skb->h.th->seq), 144*1da177e4SLinus Torvalds jiffies / (HZ * 60), mssind); 145*1da177e4SLinus Torvalds } 146*1da177e4SLinus Torvalds 147*1da177e4SLinus Torvalds /* 148*1da177e4SLinus Torvalds * This (misnamed) value is the age of syncookie which is permitted. 149*1da177e4SLinus Torvalds * Its ideal value should be dependent on TCP_TIMEOUT_INIT and 150*1da177e4SLinus Torvalds * sysctl_tcp_retries1. It's a rather complicated formula (exponential 151*1da177e4SLinus Torvalds * backoff) to compute at runtime so it's currently hardcoded here. 152*1da177e4SLinus Torvalds */ 153*1da177e4SLinus Torvalds #define COUNTER_TRIES 4 154*1da177e4SLinus Torvalds /* 155*1da177e4SLinus Torvalds * Check if a ack sequence number is a valid syncookie. 156*1da177e4SLinus Torvalds * Return the decoded mss if it is, or 0 if not. 157*1da177e4SLinus Torvalds */ 158*1da177e4SLinus Torvalds static inline int cookie_check(struct sk_buff *skb, __u32 cookie) 159*1da177e4SLinus Torvalds { 160*1da177e4SLinus Torvalds __u32 seq; 161*1da177e4SLinus Torvalds __u32 mssind; 162*1da177e4SLinus Torvalds 163*1da177e4SLinus Torvalds seq = ntohl(skb->h.th->seq)-1; 164*1da177e4SLinus Torvalds mssind = check_tcp_syn_cookie(cookie, 165*1da177e4SLinus Torvalds skb->nh.iph->saddr, skb->nh.iph->daddr, 166*1da177e4SLinus Torvalds skb->h.th->source, skb->h.th->dest, 167*1da177e4SLinus Torvalds seq, jiffies / (HZ * 60), COUNTER_TRIES); 168*1da177e4SLinus Torvalds 169*1da177e4SLinus Torvalds return mssind < NUM_MSS ? msstab[mssind] + 1 : 0; 170*1da177e4SLinus Torvalds } 171*1da177e4SLinus Torvalds 172*1da177e4SLinus Torvalds extern struct or_calltable or_ipv4; 173*1da177e4SLinus Torvalds 174*1da177e4SLinus Torvalds static inline struct sock *get_cookie_sock(struct sock *sk, struct sk_buff *skb, 175*1da177e4SLinus Torvalds struct open_request *req, 176*1da177e4SLinus Torvalds struct dst_entry *dst) 177*1da177e4SLinus Torvalds { 178*1da177e4SLinus Torvalds struct tcp_sock *tp = tcp_sk(sk); 179*1da177e4SLinus Torvalds struct sock *child; 180*1da177e4SLinus Torvalds 181*1da177e4SLinus Torvalds child = tp->af_specific->syn_recv_sock(sk, skb, req, dst); 182*1da177e4SLinus Torvalds if (child) 183*1da177e4SLinus Torvalds tcp_acceptq_queue(sk, req, child); 184*1da177e4SLinus Torvalds else 185*1da177e4SLinus Torvalds tcp_openreq_free(req); 186*1da177e4SLinus Torvalds 187*1da177e4SLinus Torvalds return child; 188*1da177e4SLinus Torvalds } 189*1da177e4SLinus Torvalds 190*1da177e4SLinus Torvalds struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb, 191*1da177e4SLinus Torvalds struct ip_options *opt) 192*1da177e4SLinus Torvalds { 193*1da177e4SLinus Torvalds struct tcp_sock *tp = tcp_sk(sk); 194*1da177e4SLinus Torvalds __u32 cookie = ntohl(skb->h.th->ack_seq) - 1; 195*1da177e4SLinus Torvalds struct sock *ret = sk; 196*1da177e4SLinus Torvalds struct open_request *req; 197*1da177e4SLinus Torvalds int mss; 198*1da177e4SLinus Torvalds struct rtable *rt; 199*1da177e4SLinus Torvalds __u8 rcv_wscale; 200*1da177e4SLinus Torvalds 201*1da177e4SLinus Torvalds if (!sysctl_tcp_syncookies || !skb->h.th->ack) 202*1da177e4SLinus Torvalds goto out; 203*1da177e4SLinus Torvalds 204*1da177e4SLinus Torvalds if (time_after(jiffies, tp->last_synq_overflow + TCP_TIMEOUT_INIT) || 205*1da177e4SLinus Torvalds (mss = cookie_check(skb, cookie)) == 0) { 206*1da177e4SLinus Torvalds NET_INC_STATS_BH(LINUX_MIB_SYNCOOKIESFAILED); 207*1da177e4SLinus Torvalds goto out; 208*1da177e4SLinus Torvalds } 209*1da177e4SLinus Torvalds 210*1da177e4SLinus Torvalds NET_INC_STATS_BH(LINUX_MIB_SYNCOOKIESRECV); 211*1da177e4SLinus Torvalds 212*1da177e4SLinus Torvalds req = tcp_openreq_alloc(); 213*1da177e4SLinus Torvalds ret = NULL; 214*1da177e4SLinus Torvalds if (!req) 215*1da177e4SLinus Torvalds goto out; 216*1da177e4SLinus Torvalds 217*1da177e4SLinus Torvalds req->rcv_isn = htonl(skb->h.th->seq) - 1; 218*1da177e4SLinus Torvalds req->snt_isn = cookie; 219*1da177e4SLinus Torvalds req->mss = mss; 220*1da177e4SLinus Torvalds req->rmt_port = skb->h.th->source; 221*1da177e4SLinus Torvalds req->af.v4_req.loc_addr = skb->nh.iph->daddr; 222*1da177e4SLinus Torvalds req->af.v4_req.rmt_addr = skb->nh.iph->saddr; 223*1da177e4SLinus Torvalds req->class = &or_ipv4; /* for savety */ 224*1da177e4SLinus Torvalds req->af.v4_req.opt = NULL; 225*1da177e4SLinus Torvalds 226*1da177e4SLinus Torvalds /* We throwed the options of the initial SYN away, so we hope 227*1da177e4SLinus Torvalds * the ACK carries the same options again (see RFC1122 4.2.3.8) 228*1da177e4SLinus Torvalds */ 229*1da177e4SLinus Torvalds if (opt && opt->optlen) { 230*1da177e4SLinus Torvalds int opt_size = sizeof(struct ip_options) + opt->optlen; 231*1da177e4SLinus Torvalds 232*1da177e4SLinus Torvalds req->af.v4_req.opt = kmalloc(opt_size, GFP_ATOMIC); 233*1da177e4SLinus Torvalds if (req->af.v4_req.opt) { 234*1da177e4SLinus Torvalds if (ip_options_echo(req->af.v4_req.opt, skb)) { 235*1da177e4SLinus Torvalds kfree(req->af.v4_req.opt); 236*1da177e4SLinus Torvalds req->af.v4_req.opt = NULL; 237*1da177e4SLinus Torvalds } 238*1da177e4SLinus Torvalds } 239*1da177e4SLinus Torvalds } 240*1da177e4SLinus Torvalds 241*1da177e4SLinus Torvalds req->snd_wscale = req->rcv_wscale = req->tstamp_ok = 0; 242*1da177e4SLinus Torvalds req->wscale_ok = req->sack_ok = 0; 243*1da177e4SLinus Torvalds req->expires = 0UL; 244*1da177e4SLinus Torvalds req->retrans = 0; 245*1da177e4SLinus Torvalds 246*1da177e4SLinus Torvalds /* 247*1da177e4SLinus Torvalds * We need to lookup the route here to get at the correct 248*1da177e4SLinus Torvalds * window size. We should better make sure that the window size 249*1da177e4SLinus Torvalds * hasn't changed since we received the original syn, but I see 250*1da177e4SLinus Torvalds * no easy way to do this. 251*1da177e4SLinus Torvalds */ 252*1da177e4SLinus Torvalds { 253*1da177e4SLinus Torvalds struct flowi fl = { .nl_u = { .ip4_u = 254*1da177e4SLinus Torvalds { .daddr = ((opt && opt->srr) ? 255*1da177e4SLinus Torvalds opt->faddr : 256*1da177e4SLinus Torvalds req->af.v4_req.rmt_addr), 257*1da177e4SLinus Torvalds .saddr = req->af.v4_req.loc_addr, 258*1da177e4SLinus Torvalds .tos = RT_CONN_FLAGS(sk) } }, 259*1da177e4SLinus Torvalds .proto = IPPROTO_TCP, 260*1da177e4SLinus Torvalds .uli_u = { .ports = 261*1da177e4SLinus Torvalds { .sport = skb->h.th->dest, 262*1da177e4SLinus Torvalds .dport = skb->h.th->source } } }; 263*1da177e4SLinus Torvalds if (ip_route_output_key(&rt, &fl)) { 264*1da177e4SLinus Torvalds tcp_openreq_free(req); 265*1da177e4SLinus Torvalds goto out; 266*1da177e4SLinus Torvalds } 267*1da177e4SLinus Torvalds } 268*1da177e4SLinus Torvalds 269*1da177e4SLinus Torvalds /* Try to redo what tcp_v4_send_synack did. */ 270*1da177e4SLinus Torvalds req->window_clamp = dst_metric(&rt->u.dst, RTAX_WINDOW); 271*1da177e4SLinus Torvalds tcp_select_initial_window(tcp_full_space(sk), req->mss, 272*1da177e4SLinus Torvalds &req->rcv_wnd, &req->window_clamp, 273*1da177e4SLinus Torvalds 0, &rcv_wscale); 274*1da177e4SLinus Torvalds /* BTW win scale with syncookies is 0 by definition */ 275*1da177e4SLinus Torvalds req->rcv_wscale = rcv_wscale; 276*1da177e4SLinus Torvalds 277*1da177e4SLinus Torvalds ret = get_cookie_sock(sk, skb, req, &rt->u.dst); 278*1da177e4SLinus Torvalds out: return ret; 279*1da177e4SLinus Torvalds } 280