summaryrefslogtreecommitdiffstats
path: root/net/third_party/nss/patches/recordlayerversion.patch
blob: 68135c74027e2153c0985910fda475e158193b12 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
Index: mozilla/security/nss/lib/ssl/sslimpl.h
===================================================================
RCS file: /cvsroot/mozilla/security/nss/lib/ssl/sslimpl.h,v
retrieving revision 1.106
diff -u -p -r1.106 sslimpl.h
--- mozilla/security/nss/lib/ssl/sslimpl.h	14 Jun 2012 19:03:29 -0000	1.106
+++ mozilla/security/nss/lib/ssl/sslimpl.h	17 Aug 2012 02:10:02 -0000
@@ -251,6 +251,8 @@ struct sslSocketOpsStr {
 #define ssl_SEND_FLAG_NO_BUFFER		0x20000000
 #define ssl_SEND_FLAG_USE_EPOCH		0x10000000 /* DTLS only */
 #define ssl_SEND_FLAG_NO_RETRANSMIT	0x08000000 /* DTLS only */
+#define ssl_SEND_FLAG_CAP_RECORD_VERSION \
+					0x04000000 /* TLS only */
 #define ssl_SEND_FLAG_MASK		0x7f000000
 
 /*
@@ -1327,6 +1329,7 @@ extern SECStatus
 ssl3_CompressMACEncryptRecord(ssl3CipherSpec *   cwSpec,
 		              PRBool             isServer,
 			      PRBool             isDTLS,
+			      PRBool             capRecordVersion,
                               SSL3ContentType    type,
 		              const SSL3Opaque * pIn,
 		              PRUint32           contentLen,
Index: mozilla/security/nss/lib/ssl/ssl3con.c
===================================================================
RCS file: /cvsroot/mozilla/security/nss/lib/ssl/ssl3con.c,v
retrieving revision 1.186
diff -u -p -r1.186 ssl3con.c
--- mozilla/security/nss/lib/ssl/ssl3con.c	30 Jul 2012 00:47:36 -0000	1.186
+++ mozilla/security/nss/lib/ssl/ssl3con.c	17 Aug 2012 02:10:02 -0000
@@ -2060,6 +2060,7 @@ SECStatus
 ssl3_CompressMACEncryptRecord(ssl3CipherSpec *   cwSpec,
 		              PRBool             isServer,
 			      PRBool             isDTLS,
+			      PRBool             capRecordVersion,
                               SSL3ContentType    type,
 		              const SSL3Opaque * pIn,
 		              PRUint32           contentLen,
@@ -2219,8 +2220,13 @@ ssl3_CompressMACEncryptRecord(ssl3Cipher
 	wrBuf->buf[11] = MSB(cipherBytes);
 	wrBuf->buf[12] = LSB(cipherBytes);
     } else {
-	wrBuf->buf[1] = MSB(cwSpec->version);
-	wrBuf->buf[2] = LSB(cwSpec->version);
+	SSL3ProtocolVersion version = cwSpec->version;
+
+	if (capRecordVersion) {
+	    version = PR_MIN(SSL_LIBRARY_VERSION_TLS_1_0, version);
+	}
+	wrBuf->buf[1] = MSB(version);
+	wrBuf->buf[2] = LSB(version);
 	wrBuf->buf[3] = MSB(cipherBytes);
 	wrBuf->buf[4] = LSB(cipherBytes);
     }
@@ -2250,7 +2256,14 @@ ssl3_CompressMACEncryptRecord(ssl3Cipher
  *    all ciphertext into the pending ciphertext buffer.
  * ssl_SEND_FLAG_USE_EPOCH (for DTLS)
  *    Forces the use of the provided epoch
- *
+ * ssl_SEND_FLAG_CAP_RECORD_VERSION
+ *    Caps the record layer version number of TLS ClientHello to { 3, 1 }
+ *    (TLS 1.0). Some TLS 1.0 servers (which seem to use F5 BIG-IP) ignore 
+ *    ClientHello.client_version and use the record layer version number
+ *    (TLSPlaintext.version) instead when negotiating protocol versions. In
+ *    addition, if the record layer version number of ClientHello is { 3, 2 }
+ *    (TLS 1.1) or higher, these servers reset the TCP connections. Set this
+ *    flag to work around such servers.
  */
 PRInt32
 ssl3_SendRecord(   sslSocket *        ss,
@@ -2263,6 +2276,7 @@ ssl3_SendRecord(   sslSocket *        ss
     sslBuffer      *          wrBuf 	  = &ss->sec.writeBuf;
     SECStatus                 rv;
     PRInt32                   totalSent   = 0;
+    PRBool                    capRecordVersion;
 
     SSL_TRC(3, ("%d: SSL3[%d] SendRecord type: %s nIn=%d",
 		SSL_GETPID(), ss->fd, ssl3_DecodeContentType(type),
@@ -2271,6 +2285,17 @@ ssl3_SendRecord(   sslSocket *        ss
 
     PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss) );
 
+    capRecordVersion = ((flags & ssl_SEND_FLAG_CAP_RECORD_VERSION) != 0);
+
+    if (capRecordVersion) {
+	/* ssl_SEND_FLAG_CAP_RECORD_VERSION can only be used with the
+	 * TLS initial ClientHello. */
+	PORT_Assert(!IS_DTLS(ss));
+	PORT_Assert(!ss->firstHsDone);
+	PORT_Assert(type == content_handshake);
+	PORT_Assert(ss->ssl3.hs.ws == wait_server_hello);
+    }
+
     if (ss->ssl3.initialized == PR_FALSE) {
 	/* This can happen on a server if the very first incoming record
 	** looks like a defective ssl3 record (e.g. too long), and we're
@@ -2327,7 +2352,8 @@ ssl3_SendRecord(   sslSocket *        ss
 
 	    rv = ssl3_CompressMACEncryptRecord(ss->ssl3.cwSpec,
 					       ss->sec.isServer, IS_DTLS(ss),
-					       type, pIn, 1, wrBuf);
+					       capRecordVersion, type, pIn,
+					       1, wrBuf);
 	    if (rv != SECSuccess)
 	        goto spec_locked_loser;
 
@@ -2340,7 +2366,8 @@ ssl3_SendRecord(   sslSocket *        ss
 
 	    rv = ssl3_CompressMACEncryptRecord(ss->ssl3.cwSpec,
 	                                       ss->sec.isServer, IS_DTLS(ss),
-					       type, pIn + 1, contentLen - 1,
+					       capRecordVersion, type,
+					       pIn + 1, contentLen - 1,
 	                                       &secondRecord);
 	    if (rv == SECSuccess) {
 	        PRINT_BUF(50, (ss, "send (encrypted) record data [2/2]:",
@@ -2352,6 +2379,7 @@ ssl3_SendRecord(   sslSocket *        ss
 		rv = ssl3_CompressMACEncryptRecord(ss->ssl3.cwSpec,
 						   ss->sec.isServer,
 						   IS_DTLS(ss),
+						   capRecordVersion,
 						   type, pIn,
 						   contentLen, wrBuf);
 	    } else {
@@ -2563,6 +2591,8 @@ ssl3_FlushHandshake(sslSocket *ss, PRInt
 static SECStatus
 ssl3_FlushHandshakeMessages(sslSocket *ss, PRInt32 flags)
 {
+    static const PRInt32 allowedFlags = ssl_SEND_FLAG_FORCE_INTO_BUFFER |
+                                        ssl_SEND_FLAG_CAP_RECORD_VERSION;
     PRInt32 rv = SECSuccess;
 
     PORT_Assert( ss->opt.noLocks || ssl_HaveSSL3HandshakeLock(ss));
@@ -2571,9 +2601,9 @@ ssl3_FlushHandshakeMessages(sslSocket *s
     if (!ss->sec.ci.sendBuf.buf || !ss->sec.ci.sendBuf.len)
 	return rv;
 
-    /* only this flag is allowed */
-    PORT_Assert(!(flags & ~ssl_SEND_FLAG_FORCE_INTO_BUFFER));
-    if ((flags & ~ssl_SEND_FLAG_FORCE_INTO_BUFFER) != 0) {
+    /* only these flags are allowed */
+    PORT_Assert(!(flags & ~allowedFlags));
+    if ((flags & ~allowedFlags) != 0) {
 	PORT_SetError(SEC_ERROR_INVALID_ARGS);
 	rv = SECFailure;
     } else {
@@ -4000,8 +4030,10 @@ ssl3_SendClientHello(sslSocket *ss, PRBo
     int              num_suites;
     int              actual_count = 0;
     PRBool           isTLS = PR_FALSE;
+    PRBool           requestingResume = PR_FALSE;
     PRInt32          total_exten_len = 0;
     unsigned         numCompressionMethods;
+    PRInt32          flags;
 
     SSL_TRC(3, ("%d: SSL3[%d]: send client_hello handshake", SSL_GETPID(),
 		ss->fd));
@@ -4090,6 +4122,7 @@ ssl3_SendClientHello(sslSocket *ss, PRBo
     }
 
     if (sid) {
+	requestingResume = PR_TRUE;
 	SSL_AtomicIncrementLong(& ssl3stats.sch_sid_cache_hits );
 
 	/* Are we attempting a stateless session resume? */
@@ -4325,7 +4358,11 @@ ssl3_SendClientHello(sslSocket *ss, PRBo
 	    ssl_renegotiation_info_xtn;
     }
 
-    rv = ssl3_FlushHandshake(ss, 0);
+    flags = 0;
+    if (!ss->firstHsDone && !requestingResume && !IS_DTLS(ss)) {
+	flags |= ssl_SEND_FLAG_CAP_RECORD_VERSION;
+    }
+    rv = ssl3_FlushHandshake(ss, flags);
     if (rv != SECSuccess) {
 	return rv;	/* error code set by ssl3_FlushHandshake */
     }
Index: mozilla/security/nss/lib/ssl/dtlscon.c
===================================================================
RCS file: /cvsroot/mozilla/security/nss/lib/ssl/dtlscon.c,v
retrieving revision 1.3
diff -u -p -r1.3 dtlscon.c
--- mozilla/security/nss/lib/ssl/dtlscon.c	4 Jul 2012 15:21:47 -0000	1.3
+++ mozilla/security/nss/lib/ssl/dtlscon.c	17 Aug 2012 02:10:02 -0000
@@ -802,7 +802,8 @@ dtls_CompressMACEncryptRecord(sslSocket 
 
     if (cwSpec) {
         rv = ssl3_CompressMACEncryptRecord(cwSpec, ss->sec.isServer, PR_TRUE,
-					   type, pIn, contentLen, wrBuf);
+					   PR_FALSE, type, pIn, contentLen,
+					   wrBuf);
     } else {
         PR_NOT_REACHED("Couldn't find a cipher spec matching epoch");
 	PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);