Chromium Code Reviews| Index: net/third_party/nss/ssl/ssl3con.c |
| =================================================================== |
| --- net/third_party/nss/ssl/ssl3con.c (revision 151171) |
| +++ net/third_party/nss/ssl/ssl3con.c (working copy) |
| @@ -786,7 +786,7 @@ |
| } |
| ss->version = PR_MIN(peerVersion, ss->vrange.max); |
| - PORT_Assert(ssl3_VersionIsSupported(ssl_variant_stream, ss->version)); |
| + PORT_Assert(ssl3_VersionIsSupported(ss->protocolVariant, ss->version)); |
|
Ryan Sleevi
2012/08/15 03:39:07
This is related to your change to ekr's patch, rig
wtc
2012/08/15 16:16:59
Yes, this fixes an unrelated bug that I discovered
|
| return SECSuccess; |
| } |
| @@ -2286,8 +2286,9 @@ |
| if (capRecordVersion) { |
| /* ssl_SEND_FLAG_CAP_RECORD_VERSION can only be used with |
| - * TLS ClientHello. */ |
| + * TLS initial ClientHello. */ |
|
agl
2012/08/15 04:02:23
(nit: I think there should be a 'the' in this comm
|
| PORT_Assert(!IS_DTLS(ss)); |
| + PORT_Assert(!ss->firstHsDone); |
| PORT_Assert(type == content_handshake); |
| PORT_Assert(ss->ssl3.hs.ws == wait_server_hello); |
| } |
| @@ -4010,7 +4011,7 @@ |
| int num_suites; |
| int actual_count = 0; |
| PRBool isTLS = PR_FALSE; |
| - PRBool serverVersionKnown = PR_FALSE; |
| + PRBool requestingResume = PR_FALSE; |
| PRInt32 total_exten_len = 0; |
| unsigned numCompressionMethods; |
| PRInt32 flags; |
| @@ -4087,9 +4088,33 @@ |
| sidOK = PR_FALSE; |
| } |
| - if (sidOK && ssl3_NegotiateVersion(ss, sid->version, |
| - PR_FALSE) != SECSuccess) { |
| - sidOK = PR_FALSE; |
| + /* TLS 1.0 (RFC 2246) Appendix E says: |
| + * Whenever a client already knows the highest protocol known to |
| + * a server (for example, when resuming a session), it should |
| + * initiate the connection in that native protocol. |
| + * So we pass sid->version to ssl3_NegotiateVersion() here, except |
| + * when renegotiating. |
| + * |
| + * Windows SChannel compares the client_version inside the RSA |
| + * EncryptedPreMasterSecret of a renegotiation with the |
| + * client_version of the initial ClientHello rather than the |
| + * ClientHello in the renegotiation. To work around this bug, we |
| + * continue to use the client_version used in the initial |
| + * ClientHello when renegotiating. |
| + */ |
| + if (sidOK) { |
| + if (ss->firstHsDone) { |
|
Ryan Sleevi
2012/08/15 03:39:07
if (sidOK), isn't a guarantee that firstHsDone is
agl
2012/08/15 04:02:23
I'm not quite sure that I understand your question
Ryan Sleevi
2012/08/15 04:09:44
If we have a session to attempt a resumption with,
wtc
2012/08/15 16:16:59
If ss->firstHsDone is true, it means the first han
wtc
2012/08/16 01:40:06
I found that my reply has a typo. It should read (
|
| + if (sid->version <= ss->clientHelloVersion) { |
| + ss->version = ss->clientHelloVersion; |
|
Ryan Sleevi
2012/08/15 03:39:07
It seems implicit in this is the assumption that s
wtc
2012/08/15 16:16:59
In this case, the SChannel bug requires us to set
|
| + } else { |
| + sidOK = PR_FALSE; |
|
agl
2012/08/15 04:02:23
Is this case ok? If we reject sid because it's ver
wtc
2012/08/15 16:16:59
This case will be handled correctly on lines 4152-
|
| + } |
| + } else { |
| + if (ssl3_NegotiateVersion(ss, sid->version, |
| + PR_FALSE) != SECSuccess) { |
|
Ryan Sleevi
2012/08/15 03:39:07
nit: Shouldn't it be two tabs, then 4 spaces (matc
wtc
2012/08/15 16:16:59
The original code also uses the maximum number of
|
| + sidOK = PR_FALSE; |
| + } |
| + } |
| } |
| if (!sidOK) { |
| @@ -4101,7 +4126,7 @@ |
| } |
| if (sid) { |
| - serverVersionKnown = PR_TRUE; |
| + requestingResume = PR_TRUE; |
| SSL_AtomicIncrementLong(& ssl3stats.sch_sid_cache_hits ); |
| /* Are we attempting a stateless session resume? */ |
| @@ -4116,10 +4141,22 @@ |
| } else { |
| SSL_AtomicIncrementLong(& ssl3stats.sch_sid_cache_misses ); |
| - rv = ssl3_NegotiateVersion(ss, SSL_LIBRARY_VERSION_MAX_SUPPORTED, |
| - PR_TRUE); |
| - if (rv != SECSuccess) |
| - return rv; /* error code was set */ |
| + /* |
| + * Windows SChannel compares the client_version inside the RSA |
| + * EncryptedPreMasterSecret of a renegotiation with the |
| + * client_version of the initial ClientHello rather than the |
| + * ClientHello in the renegotiation. To work around this bug, we |
| + * continue to use the client_version used in the initial |
| + * ClientHello when renegotiating. |
| + */ |
| + if (ss->firstHsDone) { |
| + ss->version = ss->clientHelloVersion; |
| + } else { |
| + rv = ssl3_NegotiateVersion(ss, SSL_LIBRARY_VERSION_MAX_SUPPORTED, |
| + PR_TRUE); |
| + if (rv != SECSuccess) |
| + return rv; /* error code was set */ |
| + } |
| sid = ssl3_NewSessionID(ss, PR_FALSE); |
| if (!sid) { |
| @@ -4219,6 +4256,10 @@ |
| return rv; /* err set by ssl3_AppendHandshake* */ |
| } |
| + if (ss->firstHsDone) { |
| + /* Work around the Windows SChannel bug described above. */ |
| + PORT_Assert(ss->version == ss->clientHelloVersion); |
| + } |
| ss->clientHelloVersion = ss->version; |
| if (IS_DTLS(ss)) { |
| PRUint16 version; |
| @@ -4337,8 +4378,9 @@ |
| ssl_renegotiation_info_xtn; |
| } |
| + ss->ssl3.hs.ws = wait_server_hello; |
|
Ryan Sleevi
2012/08/15 03:39:07
Did you mean to move this? It doesn't seem related
wtc
2012/08/15 16:16:59
Yes, this line needs to be moved here to support t
|
| flags = 0; |
| - if (!serverVersionKnown && !IS_DTLS(ss)) { |
| + if (!ss->firstHsDone && !requestingResume && !IS_DTLS(ss)) { |
| flags |= ssl_SEND_FLAG_CAP_RECORD_VERSION; |
| } |
| rv = ssl3_FlushHandshake(ss, flags); |
| @@ -4346,7 +4388,6 @@ |
| return rv; /* error code set by ssl3_FlushHandshake */ |
| } |
| - ss->ssl3.hs.ws = wait_server_hello; |
| return rv; |
| } |