Bug 783448: When renegotiating, continue to use the client_version used in
the initial ClientHello to work around a Windows SChannel bug. r=ryan.sleevi,bsmith. git-svn-id: svn://10.0.0.236/trunk@264269 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
@@ -5,7 +5,7 @@
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
/* $Id: ssl3con.c,v 1.190 2012-09-28 01:46:45 wtc%google.com Exp $ */
|
||||
/* $Id: ssl3con.c,v 1.191 2012-09-28 04:51:22 wtc%google.com Exp $ */
|
||||
|
||||
/* TODO(ekr): Implement HelloVerifyRequest on server side. OK for now. */
|
||||
|
||||
@@ -4060,6 +4060,23 @@ ssl3_SendClientHello(sslSocket *ss, PRBool resending)
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*
|
||||
* During a renegotiation, ss->clientHelloVersion will be used again to
|
||||
* work around a Windows SChannel bug. Ensure that it is still enabled.
|
||||
*/
|
||||
if (ss->firstHsDone) {
|
||||
if (SSL3_ALL_VERSIONS_DISABLED(&ss->vrange)) {
|
||||
PORT_SetError(SSL_ERROR_SSL_DISABLED);
|
||||
return SECFailure;
|
||||
}
|
||||
|
||||
if (ss->clientHelloVersion < ss->vrange.min ||
|
||||
ss->clientHelloVersion > ss->vrange.max) {
|
||||
PORT_SetError(SSL_ERROR_NO_CYPHER_OVERLAP);
|
||||
return SECFailure;
|
||||
}
|
||||
}
|
||||
|
||||
/* We ignore ss->sec.ci.sid here, and use ssl_Lookup because Lookup
|
||||
* handles expired entries and other details.
|
||||
* XXX If we've been called from ssl2_BeginClientHandshake, then
|
||||
@@ -4107,9 +4124,41 @@ ssl3_SendClientHello(sslSocket *ss, PRBool resending)
|
||||
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) {
|
||||
/*
|
||||
* The client_version of the initial ClientHello is still
|
||||
* available in ss->clientHelloVersion. Ensure that
|
||||
* sid->version is bounded within
|
||||
* [ss->vrange.min, ss->clientHelloVersion], otherwise we
|
||||
* can't use sid.
|
||||
*/
|
||||
if (sid->version >= ss->vrange.min &&
|
||||
sid->version <= ss->clientHelloVersion) {
|
||||
ss->version = ss->clientHelloVersion;
|
||||
} else {
|
||||
sidOK = PR_FALSE;
|
||||
}
|
||||
} else {
|
||||
if (ssl3_NegotiateVersion(ss, sid->version,
|
||||
PR_FALSE) != SECSuccess) {
|
||||
sidOK = PR_FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!sidOK) {
|
||||
@@ -4137,10 +4186,22 @@ ssl3_SendClientHello(sslSocket *ss, PRBool resending)
|
||||
} 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) {
|
||||
@@ -4240,6 +4301,11 @@ ssl3_SendClientHello(sslSocket *ss, PRBool resending)
|
||||
return rv; /* err set by ssl3_AppendHandshake* */
|
||||
}
|
||||
|
||||
if (ss->firstHsDone) {
|
||||
/* The client hello version must stay unchanged to work around
|
||||
* the Windows SChannel bug described above. */
|
||||
PORT_Assert(ss->version == ss->clientHelloVersion);
|
||||
}
|
||||
ss->clientHelloVersion = ss->version;
|
||||
if (IS_DTLS(ss)) {
|
||||
PRUint16 version;
|
||||
|
||||
Reference in New Issue
Block a user