ssh: set rekeying thresholds on construction 

The normal handshake kicks off with a waitSession(), which guarantees
that we never attempt to send data before the first kex is completed,
but ensuring readPacketsLeft > 0 and writePacketsLeft > 0 helps
understand that thresholds can never cause spurious rekeying at the
start of a connection.

Change-Id: If5bcafcda0c7d16fd21f22c664101ac5f5b487d7
Reviewed-on: https://go-review.googlesource.com/38696
Reviewed-by: Adam Langley <agl@golang.org>
Run-TryBot: Adam Langley <agl@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
diff --git a/ssh/handshake.go b/ssh/handshake.go
index b9a2071..85b4013 100644
--- a/ssh/handshake.go
+++ b/ssh/handshake.go
@@ -107,6 +107,8 @@
 
 		config: config,
 	}
+	t.resetReadThresholds()
+	t.resetWriteThresholds()
 
 	// We always start with a mandatory key exchange.
 	t.requestKex <- struct{}{}
@@ -237,6 +239,15 @@
 	}
 }
 
+func (t *handshakeTransport) resetWriteThresholds() {
+	t.writePacketsLeft = packetRekeyThreshold
+	if t.config.RekeyThreshold > 0 {
+		t.writeBytesLeft = int64(t.config.RekeyThreshold)
+	} else if t.algorithms != nil {
+		t.writeBytesLeft = t.algorithms.w.rekeyBytes()
+	}
+}
+
 func (t *handshakeTransport) kexLoop() {
 
 write:
@@ -285,12 +296,8 @@
 		t.writeError = err
 		t.sentInitPacket = nil
 		t.sentInitMsg = nil
-		t.writePacketsLeft = packetRekeyThreshold
-		if t.config.RekeyThreshold > 0 {
-			t.writeBytesLeft = int64(t.config.RekeyThreshold)
-		} else if t.algorithms != nil {
-			t.writeBytesLeft = t.algorithms.w.rekeyBytes()
-		}
+
+		t.resetWriteThresholds()
 
 		// we have completed the key exchange. Since the
 		// reader is still blocked, it is safe to clear out
@@ -344,6 +351,15 @@
 // key exchange itself.
 const packetRekeyThreshold = (1 << 31)
 
+func (t *handshakeTransport) resetReadThresholds() {
+	t.readPacketsLeft = packetRekeyThreshold
+	if t.config.RekeyThreshold > 0 {
+		t.readBytesLeft = int64(t.config.RekeyThreshold)
+	} else {
+		t.readBytesLeft = t.algorithms.r.rekeyBytes()
+	}
+}
+
 func (t *handshakeTransport) readOnePacket(first bool) ([]byte, error) {
 	p, err := t.conn.readPacket()
 	if err != nil {
@@ -391,12 +407,7 @@
 		return nil, err
 	}
 
-	t.readPacketsLeft = packetRekeyThreshold
-	if t.config.RekeyThreshold > 0 {
-		t.readBytesLeft = int64(t.config.RekeyThreshold)
-	} else {
-		t.readBytesLeft = t.algorithms.r.rekeyBytes()
-	}
+	t.resetReadThresholds()
 
 	// By default, a key exchange is hidden from higher layers by
 	// translating it into msgIgnore.