Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 23 Jul 1997 16:49:14 -0700 (PDT)
From:      leres@ee.lbl.gov (Craig Leres)
To:        FreeBSD-gnats-submit@FreeBSD.ORG
Cc:        leres@ee.lbl.gov, vern@ee.lbl.gov
Subject:   kern/4153: New tcp initial send sequence number code
Message-ID:  <199707232349.QAA19124@fun.ee.lbl.gov>
Resent-Message-ID: <199707232350.QAA23797@hub.freebsd.org>

next in thread | raw e-mail | index | archive | help

>Number:         4153
>Category:       kern
>Synopsis:       New tcp initial send sequence number code
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Wed Jul 23 16:50:01 PDT 1997
>Last-Modified:
>Originator:     Craig Leres
>Organization:
Lawrence Berkeley National Laboratory
>Release:        FreeBSD 2.2.2-RELEASE i386
>Environment:

	

>Description:

	The tcp iss number chosen by the 2.2.2-RELEASE kernel while
	an improvement over the constant increment version, it is
	still guessable. Although random() is used, the seed is
	not updated and so the pseudo random number sequence is
	essentially published.

>How-To-Repeat:

	While we haven't actually written the test program that
	guesses the next iss, given access to the kernel source it
	is only an exercise.

>Fix:
	
	The following context diffs use a 32 bit random number that
	is based on a seed that is not externally visible. (See
	the comments in tcp_new_iss() for a more detailed explaination.)
	While this version does technically violate the spec, it
	doesn't do so in a manner that will impact any current or
	future implementation. (We've been running a version of
	this code on our SunOS 4 systems since the early days of
	ip spoofing.)

+ rcsdiff -c tcp_input.c
RCS file: RCS/tcp_input.c,v
retrieving revision 1.2
diff -c -r1.2 tcp_input.c
*** /tmp/,RCSt1019028	Wed Jul 23 16:46:16 1997
--- tcp_input.c	Fri Jul 11 23:14:33 1997
***************
*** 272,278 ****
--- 272,280 ----
  	int todrop, acked, ourfinisacked, needoutput = 0;
  	struct in_addr laddr;
  	int dropsocket = 0;
+ #ifndef LBL
  	int iss = 0;
+ #endif
  	u_long tiwin;
  	struct tcpopt to;		/* options in this segment */
  	struct rmxp_tao *taop;		/* pointer to our TAO cache entry */
***************
*** 669,679 ****
--- 671,685 ----
  			bzero(taop, sizeof(*taop));
  		}
  		tcp_dooptions(tp, optp, optlen, ti, &to);
+ #ifdef LBL
+ 		tp->iss = tcp_new_iss();
+ #else
  		if (iss)
  			tp->iss = iss;
  		else
  			tp->iss = tcp_iss;
  		tcp_iss += TCP_ISSINCR/4;
+ #endif
  		tp->irs = ti->ti_seq;
  		tcp_sendseqinit(tp);
  		tcp_rcvseqinit(tp);
***************
*** 1070,1076 ****
--- 1076,1084 ----
  			if (tiflags & TH_SYN &&
  			    tp->t_state == TCPS_TIME_WAIT &&
  			    SEQ_GT(ti->ti_seq, tp->rcv_nxt)) {
+ #ifndef LBL
  				iss = tp->rcv_nxt + TCP_ISSINCR;
+ #endif
  				tp = tcp_close(tp);
  				goto findpcb;
  			}
+ rcsdiff -c tcp_seq.h
RCS file: RCS/tcp_seq.h,v
retrieving revision 1.1
diff -c -r1.1 tcp_seq.h
*** /tmp/,RCSt1019033	Wed Jul 23 16:46:16 1997
--- tcp_seq.h	Fri Jul 11 22:54:06 1997
***************
*** 90,101 ****
--- 90,104 ----
   * If defined, the tcp_random18() macro should produce a
   * number in the range [0-0x3ffff] that is hard to predict.
   */
+ #ifndef LBL
+ /* XXX See tcp_new_iss() in netniet/tcp_subr.c */
  #ifndef tcp_random18
  #define	tcp_random18()	((random() >> 14) & 0x3ffff)
  #endif
  #define	TCP_ISSINCR	(122*1024 + tcp_random18())
  
  extern tcp_seq	tcp_iss;		/* tcp initial send seq # */
+ #endif
  #else
  #define	TCP_ISSINCR	(250*1024)	/* increment for tcp_iss each second */
  #endif /* KERNEL */
+ rcsdiff -c tcp_subr.c
RCS file: RCS/tcp_subr.c,v
retrieving revision 1.1
diff -c -r1.1 tcp_subr.c
*** /tmp/,RCSt1019038	Wed Jul 23 16:46:16 1997
--- tcp_subr.c	Fri Jul 11 23:07:54 1997
***************
*** 46,51 ****
--- 46,54 ----
  #include <sys/socketvar.h>
  #include <sys/protosw.h>
  #include <sys/errno.h>
+ #ifdef LBL
+ #include <sys/vmmeter.h>	/* source of randomness for tcp_new_iss() */
+ #endif
  
  #include <net/route.h>
  #include <net/if.h>
***************
*** 102,108 ****
--- 105,113 ----
  tcp_init()
  {
  
+ #ifndef LBL
  	tcp_iss = random();	/* wrong, but better than a constant */
+ #endif
  	tcp_ccgen = 1;
  	tcp_cleartaocache();
  	LIST_INIT(&tcb);
***************
*** 113,118 ****
--- 118,154 ----
  	if (max_linkhdr + sizeof(struct tcpiphdr) > MHLEN)
  		panic("tcp_init");
  }
+ 
+ #ifdef LBL
+ tcp_seq
+ tcp_new_iss()
+ {
+         struct timeval now;
+ 
+         /*
+          * choose a 'random' initial send sequence number that
+          * a) is unlikely to conflict with any other that we've
+          * recently used and (b) is hard for an adversary to
+          * guess.  We use the low bits of the high res clock to
+          * gain some entropy then stick in some system counters
+          * that change rapidly & change on non-network activity
+          * to get some more then run the whole thing through kernrand
+          * so an attacker has to invert a non-linear function to start
+          * analyzing the pattern.  Note that we're running this on
+          * a machine with at least microsecond clock resolution so
+          * the now.tv_usec term provides short term (<1s) variation &
+          * the v_swtch & v_syscall terms provide longer term variation.
+          * On a machine with a poor clock (10ms or worse resolution)
+          * the now.tv_usec should be replaced with something that
+          * varies substantially on a ~1ms (i.e., 1 packet time) scale.
+          * Also note that v_swtch & v_syscall are monotone increasing
+          * which is used to help with property (a) above.
+          */
+         microtime(&now);
+ 	srandom((now.tv_usec << 10) ^ cnt.v_swtch ^ cnt.v_syscall);
+         return (random());
+ }
+ #endif
  
  /*
   * Create template to be used to send tcp packets on a connection.
+ rcsdiff -c tcp_timer.c
RCS file: RCS/tcp_timer.c,v
retrieving revision 1.1
diff -c -r1.1 tcp_timer.c
*** /tmp/,RCSt1019043	Wed Jul 23 16:46:16 1997
--- tcp_timer.c	Fri Jul 11 23:18:45 1997
***************
*** 174,180 ****
--- 174,182 ----
  tpgone:
  		;
  	}
+ #ifndef LBL
  	tcp_iss += TCP_ISSINCR/PR_SLOWHZ;		/* increment iss */
+ #endif
  #ifdef TCP_COMPAT_42
  	if ((int)tcp_iss < 0)
  		tcp_iss = TCP_ISSINCR;			/* XXX */
+ rcsdiff -c tcp_usrreq.c
RCS file: RCS/tcp_usrreq.c,v
retrieving revision 1.2
diff -c -r1.2 tcp_usrreq.c
*** /tmp/,RCSt1019048	Wed Jul 23 16:46:16 1997
--- tcp_usrreq.c	Fri Jul 11 23:17:45 1997
***************
*** 591,597 ****
--- 591,601 ----
  	tcpstat.tcps_connattempt++;
  	tp->t_state = TCPS_SYN_SENT;
  	tp->t_timer[TCPT_KEEP] = tcp_keepinit;
+ #ifdef LBL
+ 	tp->iss = tcp_new_iss();
+ #else
  	tp->iss = tcp_iss; tcp_iss += TCP_ISSINCR/2;
+ #endif
  	tcp_sendseqinit(tp);
  
  	/*
+ rcsdiff -c tcp_var.h
RCS file: RCS/tcp_var.h,v
retrieving revision 1.1
diff -c -r1.1 tcp_var.h
*** /tmp/,RCSt1019053	Wed Jul 23 16:46:16 1997
--- tcp_var.h	Fri Jul 11 22:53:56 1997
***************
*** 345,350 ****
--- 345,353 ----
  struct rmxp_tao *
  	 tcp_gettaocache __P((struct inpcb *));
  void	 tcp_init __P((void));
+ #ifdef LBL
+ tcp_seq	 tcp_new_iss __P((void));
+ #endif
  void	 tcp_input __P((struct mbuf *, int));
  void	 tcp_mss __P((struct tcpcb *, int));
  int	 tcp_mssopt __P((struct tcpcb *));

>Audit-Trail:
>Unformatted:



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199707232349.QAA19124>