mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1088915 - Stop offering RC4 in the first handshakes. r=keeler
This commit is contained in:
parent
47c59a92a4
commit
72b1c83560
@ -624,6 +624,7 @@ typedef struct {
|
||||
const char* pref;
|
||||
long id;
|
||||
bool enabledByDefault;
|
||||
bool weak;
|
||||
} CipherPref;
|
||||
|
||||
// Update the switch statement in HandshakeCallback in nsNSSCallbacks.cpp when
|
||||
@ -667,9 +668,9 @@ static const CipherPref sCipherPrefs[] = {
|
||||
TLS_DHE_DSS_WITH_AES_256_CBC_SHA, false }, // deprecated (DSS)
|
||||
|
||||
{ "security.ssl3.ecdhe_rsa_rc4_128_sha",
|
||||
TLS_ECDHE_RSA_WITH_RC4_128_SHA, true }, // deprecated (RC4)
|
||||
TLS_ECDHE_RSA_WITH_RC4_128_SHA, true, true }, // deprecated (RC4)
|
||||
{ "security.ssl3.ecdhe_ecdsa_rc4_128_sha",
|
||||
TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, true }, // deprecated (RC4)
|
||||
TLS_ECDHE_ECDSA_WITH_RC4_128_SHA, true, true }, // deprecated (RC4)
|
||||
|
||||
{ "security.ssl3.rsa_aes_128_sha",
|
||||
TLS_RSA_WITH_AES_128_CBC_SHA, true }, // deprecated (RSA key exchange)
|
||||
@ -683,15 +684,40 @@ static const CipherPref sCipherPrefs[] = {
|
||||
TLS_RSA_WITH_3DES_EDE_CBC_SHA, true }, // deprecated (RSA key exchange, 3DES)
|
||||
|
||||
{ "security.ssl3.rsa_rc4_128_sha",
|
||||
TLS_RSA_WITH_RC4_128_SHA, true }, // deprecated (RSA key exchange, RC4)
|
||||
TLS_RSA_WITH_RC4_128_SHA, true, true }, // deprecated (RSA key exchange, RC4)
|
||||
{ "security.ssl3.rsa_rc4_128_md5",
|
||||
TLS_RSA_WITH_RC4_128_MD5, true }, // deprecated (RSA key exchange, RC4, HMAC-MD5)
|
||||
TLS_RSA_WITH_RC4_128_MD5, true, true }, // deprecated (RSA key exchange, RC4, HMAC-MD5)
|
||||
|
||||
// All the rest are disabled by default
|
||||
|
||||
{ nullptr, 0 } // end marker
|
||||
};
|
||||
|
||||
// Bit flags indicating what weak ciphers are enabled.
|
||||
// The bit index will correspond to the index in sCipherPrefs.
|
||||
// Wrtten by the main thread, read from any threads.
|
||||
static Atomic<uint32_t> sEnabledWeakCiphers;
|
||||
static_assert(MOZ_ARRAY_LENGTH(sCipherPrefs) - 1 <= sizeof(uint32_t) * CHAR_BIT,
|
||||
"too many cipher suites");
|
||||
|
||||
/*static*/ bool
|
||||
nsNSSComponent::AreAnyWeakCiphersEnabled()
|
||||
{
|
||||
return !!sEnabledWeakCiphers;
|
||||
}
|
||||
|
||||
/*static*/ void
|
||||
nsNSSComponent::UseWeakCiphersOnSocket(PRFileDesc* fd)
|
||||
{
|
||||
const uint32_t enabledWeakCiphers = sEnabledWeakCiphers;
|
||||
const CipherPref* const cp = sCipherPrefs;
|
||||
for (size_t i = 0; cp[i].pref; ++i) {
|
||||
if (enabledWeakCiphers & ((uint32_t)1 << i)) {
|
||||
SSL_CipherPrefSet(fd, cp[i].id, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static const int32_t OCSP_ENABLED_DEFAULT = 1;
|
||||
static const bool REQUIRE_SAFE_NEGOTIATION_DEFAULT = false;
|
||||
static const bool ALLOW_UNRESTRICTED_RENEGO_DEFAULT = false;
|
||||
@ -773,12 +799,27 @@ CipherSuiteChangeObserver::Observe(nsISupports* aSubject,
|
||||
if (nsCRT::strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID) == 0) {
|
||||
NS_ConvertUTF16toUTF8 prefName(someData);
|
||||
// Look through the cipher table and set according to pref setting
|
||||
for (const CipherPref* cp = sCipherPrefs; cp->pref; ++cp) {
|
||||
if (prefName.Equals(cp->pref)) {
|
||||
bool cipherEnabled = Preferences::GetBool(cp->pref,
|
||||
cp->enabledByDefault);
|
||||
SSL_CipherPrefSetDefault(cp->id, cipherEnabled);
|
||||
SSL_ClearSessionCache();
|
||||
const CipherPref* const cp = sCipherPrefs;
|
||||
for (size_t i = 0; cp[i].pref; ++i) {
|
||||
if (prefName.Equals(cp[i].pref)) {
|
||||
bool cipherEnabled = Preferences::GetBool(cp[i].pref,
|
||||
cp[i].enabledByDefault);
|
||||
if (cp[i].weak) {
|
||||
// Weak ciphers will not be used by default even if they
|
||||
// are enabled in prefs. They are only used on specific
|
||||
// sockets as a part of a fallback mechanism.
|
||||
// Only the main thread will change sEnabledWeakCiphers.
|
||||
uint32_t enabledWeakCiphers = sEnabledWeakCiphers;
|
||||
if (cipherEnabled) {
|
||||
enabledWeakCiphers |= ((uint32_t)1 << i);
|
||||
} else {
|
||||
enabledWeakCiphers &= ~((uint32_t)1 << i);
|
||||
}
|
||||
sEnabledWeakCiphers = enabledWeakCiphers;
|
||||
} else {
|
||||
SSL_CipherPrefSetDefault(cp[i].id, cipherEnabled);
|
||||
SSL_ClearSessionCache();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1646,10 +1687,22 @@ InitializeCipherSuite()
|
||||
}
|
||||
|
||||
// Now only set SSL/TLS ciphers we knew about at compile time
|
||||
for (const CipherPref* cp = sCipherPrefs; cp->pref; ++cp) {
|
||||
bool cipherEnabled = Preferences::GetBool(cp->pref, cp->enabledByDefault);
|
||||
SSL_CipherPrefSetDefault(cp->id, cipherEnabled);
|
||||
uint32_t enabledWeakCiphers = 0;
|
||||
const CipherPref* const cp = sCipherPrefs;
|
||||
for (size_t i = 0; cp[i].pref; ++i) {
|
||||
bool cipherEnabled = Preferences::GetBool(cp[i].pref,
|
||||
cp[i].enabledByDefault);
|
||||
if (cp[i].weak) {
|
||||
// Weak ciphers are not used by default. See the comment
|
||||
// in CipherSuiteChangeObserver::Observe for details.
|
||||
if (cipherEnabled) {
|
||||
enabledWeakCiphers |= ((uint32_t)1 << i);
|
||||
}
|
||||
} else {
|
||||
SSL_CipherPrefSetDefault(cp[i].id, cipherEnabled);
|
||||
}
|
||||
}
|
||||
sEnabledWeakCiphers = enabledWeakCiphers;
|
||||
|
||||
// Enable ciphers for PKCS#12
|
||||
SEC_PKCS12EnableCipher(PKCS12_RC4_40, 1);
|
||||
|
@ -153,6 +153,10 @@ public:
|
||||
::mozilla::TemporaryRef<mozilla::psm::SharedCertVerifier>
|
||||
GetDefaultCertVerifier() MOZ_OVERRIDE;
|
||||
|
||||
// The following two methods are thread-safe.
|
||||
static bool AreAnyWeakCiphersEnabled();
|
||||
static void UseWeakCiphersOnSocket(PRFileDesc* fd);
|
||||
|
||||
protected:
|
||||
virtual ~nsNSSComponent();
|
||||
|
||||
|
@ -855,10 +855,14 @@ nsSSLIOLayerHelpers::rememberTolerantAtVersion(const nsACString& hostName,
|
||||
entry.intolerant = entry.tolerant + 1;
|
||||
entry.intoleranceReason = 0; // lose the reason
|
||||
}
|
||||
if (entry.strongCipherStatus == StrongCipherStatusUnknown) {
|
||||
entry.strongCipherStatus = StrongCiphersWorked;
|
||||
}
|
||||
} else {
|
||||
entry.tolerant = tolerant;
|
||||
entry.intolerant = 0;
|
||||
entry.intoleranceReason = 0;
|
||||
entry.strongCipherStatus = StrongCiphersWorked;
|
||||
}
|
||||
|
||||
entry.AssertInvariant();
|
||||
@ -880,6 +884,9 @@ void nsSSLIOLayerHelpers::forgetIntolerance(const nsACString& hostName,
|
||||
|
||||
entry.intolerant = 0;
|
||||
entry.intoleranceReason = 0;
|
||||
if (entry.strongCipherStatus != StrongCiphersWorked) {
|
||||
entry.strongCipherStatus = StrongCipherStatusUnknown;
|
||||
}
|
||||
|
||||
entry.AssertInvariant();
|
||||
mTLSIntoleranceInfo.Put(key, entry);
|
||||
@ -918,6 +925,7 @@ nsSSLIOLayerHelpers::rememberIntolerantAtVersion(const nsACString& hostName,
|
||||
}
|
||||
} else {
|
||||
entry.tolerant = 0;
|
||||
entry.strongCipherStatus = StrongCipherStatusUnknown;
|
||||
}
|
||||
|
||||
entry.intolerant = intolerant;
|
||||
@ -928,10 +936,41 @@ nsSSLIOLayerHelpers::rememberIntolerantAtVersion(const nsACString& hostName,
|
||||
return true;
|
||||
}
|
||||
|
||||
// returns true if we should retry the handshake
|
||||
bool
|
||||
nsSSLIOLayerHelpers::rememberStrongCiphersFailed(const nsACString& hostName,
|
||||
int16_t port)
|
||||
{
|
||||
nsCString key;
|
||||
getSiteKey(hostName, port, key);
|
||||
|
||||
MutexAutoLock lock(mutex);
|
||||
|
||||
IntoleranceEntry entry;
|
||||
if (mTLSIntoleranceInfo.Get(key, &entry)) {
|
||||
entry.AssertInvariant();
|
||||
if (entry.strongCipherStatus != StrongCipherStatusUnknown) {
|
||||
// We already know if the server supports a strong cipher.
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
entry.tolerant = 0;
|
||||
entry.intolerant = 0;
|
||||
entry.intoleranceReason = SSL_ERROR_NO_CYPHER_OVERLAP;
|
||||
}
|
||||
|
||||
entry.strongCipherStatus = StrongCiphersFailed;
|
||||
entry.AssertInvariant();
|
||||
mTLSIntoleranceInfo.Put(key, entry);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
nsSSLIOLayerHelpers::adjustForTLSIntolerance(const nsACString& hostName,
|
||||
int16_t port,
|
||||
/*in/out*/ SSLVersionRange& range)
|
||||
/*in/out*/ SSLVersionRange& range,
|
||||
/*out*/ StrongCipherStatus& strongCipherStatus)
|
||||
{
|
||||
IntoleranceEntry entry;
|
||||
|
||||
@ -954,6 +993,7 @@ nsSSLIOLayerHelpers::adjustForTLSIntolerance(const nsACString& hostName,
|
||||
range.max = entry.intolerant - 1;
|
||||
}
|
||||
}
|
||||
strongCipherStatus = entry.strongCipherStatus;
|
||||
}
|
||||
|
||||
PRErrorCode
|
||||
@ -1169,6 +1209,15 @@ retryDueToTLSIntolerance(PRErrorCode err, nsNSSSocketInfo* socketInfo)
|
||||
.forgetIntolerance(socketInfo->GetHostName(), socketInfo->GetPort());
|
||||
|
||||
return false;
|
||||
} else if (err == SSL_ERROR_NO_CYPHER_OVERLAP &&
|
||||
nsNSSComponent::AreAnyWeakCiphersEnabled()) {
|
||||
if (socketInfo->SharedState().IOLayerHelpers()
|
||||
.rememberStrongCiphersFailed(socketInfo->GetHostName(),
|
||||
socketInfo->GetPort())) {
|
||||
Telemetry::Accumulate(Telemetry::SSL_WEAK_CIPHERS_FALLBACK, true);
|
||||
return true;
|
||||
}
|
||||
Telemetry::Accumulate(Telemetry::SSL_WEAK_CIPHERS_FALLBACK, false);
|
||||
}
|
||||
|
||||
// When not using a proxy we'll see a connection reset error.
|
||||
@ -2535,21 +2584,26 @@ nsSSLIOLayerSetOptions(PRFileDesc* fd, bool forSTARTTLS,
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
uint16_t maxEnabledVersion = range.max;
|
||||
|
||||
uint16_t maxEnabledVersion = range.max;
|
||||
StrongCipherStatus strongCiphersStatus = StrongCipherStatusUnknown;
|
||||
infoObject->SharedState().IOLayerHelpers()
|
||||
.adjustForTLSIntolerance(infoObject->GetHostName(), infoObject->GetPort(),
|
||||
range);
|
||||
range, strongCiphersStatus);
|
||||
PR_LOG(gPIPNSSLog, PR_LOG_DEBUG,
|
||||
("[%p] nsSSLIOLayerSetOptions: using TLS version range (0x%04x,0x%04x)\n",
|
||||
("[%p] nsSSLIOLayerSetOptions: using TLS version range (0x%04x,0x%04x)%s\n",
|
||||
fd, static_cast<unsigned int>(range.min),
|
||||
static_cast<unsigned int>(range.max)));
|
||||
static_cast<unsigned int>(range.max),
|
||||
strongCiphersStatus == StrongCiphersFailed ? " with weak ciphers" : ""));
|
||||
|
||||
if (SSL_VersionRangeSet(fd, &range) != SECSuccess) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
infoObject->SetTLSVersionRange(range);
|
||||
|
||||
if (strongCiphersStatus == StrongCiphersFailed) {
|
||||
nsNSSComponent::UseWeakCiphersOnSocket(fd);
|
||||
}
|
||||
|
||||
// when adjustForTLSIntolerance tweaks the maximum version downward,
|
||||
// we tell the server using this SCSV so they can detect a downgrade attack
|
||||
if (range.max < maxEnabledVersion) {
|
||||
|
@ -173,6 +173,12 @@ private:
|
||||
nsCOMPtr<nsIX509Cert> mClientCert;
|
||||
};
|
||||
|
||||
enum StrongCipherStatus {
|
||||
StrongCipherStatusUnknown,
|
||||
StrongCiphersWorked,
|
||||
StrongCiphersFailed
|
||||
};
|
||||
|
||||
class nsSSLIOLayerHelpers
|
||||
{
|
||||
public:
|
||||
@ -203,6 +209,7 @@ private:
|
||||
uint16_t tolerant;
|
||||
uint16_t intolerant;
|
||||
PRErrorCode intoleranceReason;
|
||||
StrongCipherStatus strongCipherStatus;
|
||||
|
||||
void AssertInvariant() const
|
||||
{
|
||||
@ -216,9 +223,11 @@ public:
|
||||
bool rememberIntolerantAtVersion(const nsACString& hostname, int16_t port,
|
||||
uint16_t intolerant, uint16_t minVersion,
|
||||
PRErrorCode intoleranceReason);
|
||||
bool rememberStrongCiphersFailed(const nsACString& hostName, int16_t port);
|
||||
void forgetIntolerance(const nsACString& hostname, int16_t port);
|
||||
void adjustForTLSIntolerance(const nsACString& hostname, int16_t port,
|
||||
/*in/out*/ SSLVersionRange& range);
|
||||
/*in/out*/ SSLVersionRange& range,
|
||||
/*out*/ StrongCipherStatus& strongCipherStatus);
|
||||
PRErrorCode getIntoleranceReason(const nsACString& hostname, int16_t port);
|
||||
|
||||
void setRenegoUnrestrictedSites(const nsCString& str);
|
||||
|
@ -19,7 +19,7 @@ protected:
|
||||
nsSSLIOLayerHelpers helpers;
|
||||
};
|
||||
|
||||
TEST_F(TLSIntoleranceTest, Test_1_2_through_3_0)
|
||||
TEST_F(TLSIntoleranceTest, Test_Full_Fallback_Process)
|
||||
{
|
||||
helpers.mVersionFallbackLimit = SSL_LIBRARY_VERSION_3_0;
|
||||
|
||||
@ -27,10 +27,25 @@ TEST_F(TLSIntoleranceTest, Test_1_2_through_3_0)
|
||||
{
|
||||
SSLVersionRange range = { SSL_LIBRARY_VERSION_3_0,
|
||||
SSL_LIBRARY_VERSION_TLS_1_2 };
|
||||
helpers.adjustForTLSIntolerance(HOST, PORT, range);
|
||||
StrongCipherStatus strongCipherStatus = StrongCipherStatusUnknown;
|
||||
helpers.adjustForTLSIntolerance(HOST, PORT, range, strongCipherStatus);
|
||||
ASSERT_EQ(SSL_LIBRARY_VERSION_3_0, range.min);
|
||||
ASSERT_EQ(SSL_LIBRARY_VERSION_TLS_1_2, range.max);
|
||||
ASSERT_EQ(StrongCipherStatusUnknown, strongCipherStatus);
|
||||
|
||||
ASSERT_TRUE(helpers.rememberStrongCiphersFailed(HOST, PORT));
|
||||
}
|
||||
|
||||
{
|
||||
SSLVersionRange range = { SSL_LIBRARY_VERSION_3_0,
|
||||
SSL_LIBRARY_VERSION_TLS_1_2 };
|
||||
StrongCipherStatus strongCipherStatus = StrongCipherStatusUnknown;
|
||||
helpers.adjustForTLSIntolerance(HOST, PORT, range, strongCipherStatus);
|
||||
ASSERT_EQ(SSL_LIBRARY_VERSION_3_0, range.min);
|
||||
ASSERT_EQ(SSL_LIBRARY_VERSION_TLS_1_2, range.max);
|
||||
ASSERT_EQ(StrongCiphersFailed, strongCipherStatus);
|
||||
|
||||
ASSERT_FALSE(helpers.rememberStrongCiphersFailed(HOST, PORT));
|
||||
ASSERT_TRUE(helpers.rememberIntolerantAtVersion(HOST, PORT,
|
||||
range.min, range.max, 0));
|
||||
}
|
||||
@ -38,10 +53,13 @@ TEST_F(TLSIntoleranceTest, Test_1_2_through_3_0)
|
||||
{
|
||||
SSLVersionRange range = { SSL_LIBRARY_VERSION_3_0,
|
||||
SSL_LIBRARY_VERSION_TLS_1_2 };
|
||||
helpers.adjustForTLSIntolerance(HOST, PORT, range);
|
||||
StrongCipherStatus strongCipherStatus = StrongCipherStatusUnknown;
|
||||
helpers.adjustForTLSIntolerance(HOST, PORT, range, strongCipherStatus);
|
||||
ASSERT_EQ(SSL_LIBRARY_VERSION_3_0, range.min);
|
||||
ASSERT_EQ(SSL_LIBRARY_VERSION_TLS_1_1, range.max);
|
||||
ASSERT_EQ(StrongCiphersFailed, strongCipherStatus);
|
||||
|
||||
ASSERT_FALSE(helpers.rememberStrongCiphersFailed(HOST, PORT));
|
||||
ASSERT_TRUE(helpers.rememberIntolerantAtVersion(HOST, PORT,
|
||||
range.min, range.max, 0));
|
||||
}
|
||||
@ -49,10 +67,13 @@ TEST_F(TLSIntoleranceTest, Test_1_2_through_3_0)
|
||||
{
|
||||
SSLVersionRange range = { SSL_LIBRARY_VERSION_3_0,
|
||||
SSL_LIBRARY_VERSION_TLS_1_2 };
|
||||
helpers.adjustForTLSIntolerance(HOST, PORT, range);
|
||||
StrongCipherStatus strongCipherStatus = StrongCipherStatusUnknown;
|
||||
helpers.adjustForTLSIntolerance(HOST, PORT, range, strongCipherStatus);
|
||||
ASSERT_EQ(SSL_LIBRARY_VERSION_3_0, range.min);
|
||||
ASSERT_EQ(SSL_LIBRARY_VERSION_TLS_1_0, range.max);
|
||||
ASSERT_EQ(StrongCiphersFailed, strongCipherStatus);
|
||||
|
||||
ASSERT_FALSE(helpers.rememberStrongCiphersFailed(HOST, PORT));
|
||||
ASSERT_TRUE(helpers.rememberIntolerantAtVersion(HOST, PORT,
|
||||
range.min, range.max, 0));
|
||||
}
|
||||
@ -61,10 +82,13 @@ TEST_F(TLSIntoleranceTest, Test_1_2_through_3_0)
|
||||
SSLVersionRange range = { SSL_LIBRARY_VERSION_3_0,
|
||||
SSL_LIBRARY_VERSION_TLS_1_2 };
|
||||
|
||||
helpers.adjustForTLSIntolerance(HOST, PORT, range);
|
||||
StrongCipherStatus strongCipherStatus = StrongCipherStatusUnknown;
|
||||
helpers.adjustForTLSIntolerance(HOST, PORT, range, strongCipherStatus);
|
||||
ASSERT_EQ(SSL_LIBRARY_VERSION_3_0, range.min);
|
||||
ASSERT_EQ(SSL_LIBRARY_VERSION_3_0, range.max);
|
||||
ASSERT_EQ(StrongCiphersFailed, strongCipherStatus);
|
||||
|
||||
ASSERT_FALSE(helpers.rememberStrongCiphersFailed(HOST, PORT));
|
||||
// false because we reached the floor set by range.min
|
||||
ASSERT_FALSE(helpers.rememberIntolerantAtVersion(HOST, PORT,
|
||||
range.min, range.max, 0));
|
||||
@ -73,11 +97,13 @@ TEST_F(TLSIntoleranceTest, Test_1_2_through_3_0)
|
||||
{
|
||||
SSLVersionRange range = { SSL_LIBRARY_VERSION_3_0,
|
||||
SSL_LIBRARY_VERSION_TLS_1_2 };
|
||||
helpers.adjustForTLSIntolerance(HOST, PORT, range);
|
||||
StrongCipherStatus strongCipherStatus = StrongCipherStatusUnknown;
|
||||
helpers.adjustForTLSIntolerance(HOST, PORT, range, strongCipherStatus);
|
||||
ASSERT_EQ(SSL_LIBRARY_VERSION_3_0, range.min);
|
||||
// When rememberIntolerantAtVersion returns false, it also resets the
|
||||
// intolerance information for the server.
|
||||
ASSERT_EQ(SSL_LIBRARY_VERSION_TLS_1_2, range.max);
|
||||
ASSERT_EQ(StrongCipherStatusUnknown, strongCipherStatus);
|
||||
}
|
||||
}
|
||||
|
||||
@ -125,9 +151,11 @@ TEST_F(TLSIntoleranceTest, Test_Fallback_Limit_Below_Min)
|
||||
{
|
||||
SSLVersionRange range = { SSL_LIBRARY_VERSION_3_0,
|
||||
SSL_LIBRARY_VERSION_TLS_1_2 };
|
||||
helpers.adjustForTLSIntolerance(HOST, PORT, range);
|
||||
StrongCipherStatus strongCipherStatus = StrongCipherStatusUnknown;
|
||||
helpers.adjustForTLSIntolerance(HOST, PORT, range, strongCipherStatus);
|
||||
ASSERT_EQ(SSL_LIBRARY_VERSION_3_0, range.min);
|
||||
ASSERT_EQ(SSL_LIBRARY_VERSION_TLS_1_1, range.max);
|
||||
ASSERT_EQ(StrongCipherStatusUnknown, strongCipherStatus);
|
||||
}
|
||||
|
||||
ASSERT_FALSE(helpers.rememberIntolerantAtVersion(HOST, PORT,
|
||||
@ -145,9 +173,11 @@ TEST_F(TLSIntoleranceTest, Test_Tolerant_Overrides_Intolerant_1)
|
||||
helpers.rememberTolerantAtVersion(HOST, PORT, SSL_LIBRARY_VERSION_TLS_1_1);
|
||||
SSLVersionRange range = { SSL_LIBRARY_VERSION_3_0,
|
||||
SSL_LIBRARY_VERSION_TLS_1_2 };
|
||||
helpers.adjustForTLSIntolerance(HOST, PORT, range);
|
||||
StrongCipherStatus strongCipherStatus = StrongCipherStatusUnknown;
|
||||
helpers.adjustForTLSIntolerance(HOST, PORT, range, strongCipherStatus);
|
||||
ASSERT_EQ(SSL_LIBRARY_VERSION_3_0, range.min);
|
||||
ASSERT_EQ(SSL_LIBRARY_VERSION_TLS_1_1, range.max);
|
||||
ASSERT_EQ(StrongCiphersWorked, strongCipherStatus);
|
||||
}
|
||||
|
||||
TEST_F(TLSIntoleranceTest, Test_Tolerant_Overrides_Intolerant_2)
|
||||
@ -159,9 +189,11 @@ TEST_F(TLSIntoleranceTest, Test_Tolerant_Overrides_Intolerant_2)
|
||||
helpers.rememberTolerantAtVersion(HOST, PORT, SSL_LIBRARY_VERSION_TLS_1_2);
|
||||
SSLVersionRange range = { SSL_LIBRARY_VERSION_3_0,
|
||||
SSL_LIBRARY_VERSION_TLS_1_2 };
|
||||
helpers.adjustForTLSIntolerance(HOST, PORT, range);
|
||||
StrongCipherStatus strongCipherStatus = StrongCipherStatusUnknown;
|
||||
helpers.adjustForTLSIntolerance(HOST, PORT, range, strongCipherStatus);
|
||||
ASSERT_EQ(SSL_LIBRARY_VERSION_3_0, range.min);
|
||||
ASSERT_EQ(SSL_LIBRARY_VERSION_TLS_1_2, range.max);
|
||||
ASSERT_EQ(StrongCiphersWorked, strongCipherStatus);
|
||||
}
|
||||
|
||||
TEST_F(TLSIntoleranceTest, Test_Intolerant_Does_Not_Override_Tolerant)
|
||||
@ -175,9 +207,11 @@ TEST_F(TLSIntoleranceTest, Test_Intolerant_Does_Not_Override_Tolerant)
|
||||
0));
|
||||
SSLVersionRange range = { SSL_LIBRARY_VERSION_3_0,
|
||||
SSL_LIBRARY_VERSION_TLS_1_2 };
|
||||
helpers.adjustForTLSIntolerance(HOST, PORT, range);
|
||||
StrongCipherStatus strongCipherStatus = StrongCipherStatusUnknown;
|
||||
helpers.adjustForTLSIntolerance(HOST, PORT, range, strongCipherStatus);
|
||||
ASSERT_EQ(SSL_LIBRARY_VERSION_3_0, range.min);
|
||||
ASSERT_EQ(SSL_LIBRARY_VERSION_TLS_1_2, range.max);
|
||||
ASSERT_EQ(StrongCiphersWorked, strongCipherStatus);
|
||||
}
|
||||
|
||||
TEST_F(TLSIntoleranceTest, Test_Port_Is_Relevant)
|
||||
@ -195,14 +229,16 @@ TEST_F(TLSIntoleranceTest, Test_Port_Is_Relevant)
|
||||
{
|
||||
SSLVersionRange range = { SSL_LIBRARY_VERSION_3_0,
|
||||
SSL_LIBRARY_VERSION_TLS_1_2 };
|
||||
helpers.adjustForTLSIntolerance(HOST, 1, range);
|
||||
StrongCipherStatus strongCipherStatus = StrongCipherStatusUnknown;
|
||||
helpers.adjustForTLSIntolerance(HOST, 1, range, strongCipherStatus);
|
||||
ASSERT_EQ(SSL_LIBRARY_VERSION_TLS_1_2, range.max);
|
||||
}
|
||||
|
||||
{
|
||||
SSLVersionRange range = { SSL_LIBRARY_VERSION_3_0,
|
||||
SSL_LIBRARY_VERSION_TLS_1_2 };
|
||||
helpers.adjustForTLSIntolerance(HOST, 2, range);
|
||||
StrongCipherStatus strongCipherStatus = StrongCipherStatusUnknown;
|
||||
helpers.adjustForTLSIntolerance(HOST, 2, range, strongCipherStatus);
|
||||
ASSERT_EQ(SSL_LIBRARY_VERSION_TLS_1_1, range.max);
|
||||
}
|
||||
}
|
||||
@ -242,6 +278,147 @@ TEST_F(TLSIntoleranceTest, Test_Intolerance_Reason_Cleared)
|
||||
ASSERT_EQ(0, helpers.getIntoleranceReason(HOST, 1));
|
||||
}
|
||||
|
||||
TEST_F(TLSIntoleranceTest, Test_Strong_Ciphers_Failed)
|
||||
{
|
||||
helpers.mVersionFallbackLimit = SSL_LIBRARY_VERSION_TLS_1_1;
|
||||
|
||||
ASSERT_TRUE(helpers.rememberStrongCiphersFailed(HOST, PORT));
|
||||
|
||||
{
|
||||
SSLVersionRange range = { SSL_LIBRARY_VERSION_3_0,
|
||||
SSL_LIBRARY_VERSION_TLS_1_2 };
|
||||
StrongCipherStatus strongCipherStatus = StrongCipherStatusUnknown;
|
||||
helpers.adjustForTLSIntolerance(HOST, PORT, range, strongCipherStatus);
|
||||
ASSERT_EQ(SSL_LIBRARY_VERSION_3_0, range.min);
|
||||
ASSERT_EQ(SSL_LIBRARY_VERSION_TLS_1_2, range.max);
|
||||
ASSERT_EQ(StrongCiphersFailed, strongCipherStatus);
|
||||
|
||||
ASSERT_TRUE(helpers.rememberIntolerantAtVersion(HOST, PORT,
|
||||
range.min, range.max, 0));
|
||||
}
|
||||
|
||||
{
|
||||
SSLVersionRange range = { SSL_LIBRARY_VERSION_3_0,
|
||||
SSL_LIBRARY_VERSION_TLS_1_2 };
|
||||
StrongCipherStatus strongCipherStatus = StrongCipherStatusUnknown;
|
||||
helpers.adjustForTLSIntolerance(HOST, PORT, range, strongCipherStatus);
|
||||
ASSERT_EQ(SSL_LIBRARY_VERSION_3_0, range.min);
|
||||
ASSERT_EQ(SSL_LIBRARY_VERSION_TLS_1_1, range.max);
|
||||
ASSERT_EQ(StrongCiphersFailed, strongCipherStatus);
|
||||
|
||||
ASSERT_FALSE(helpers.rememberIntolerantAtVersion(HOST, PORT,
|
||||
range.min, range.max, 0));
|
||||
}
|
||||
|
||||
{
|
||||
SSLVersionRange range = { SSL_LIBRARY_VERSION_3_0,
|
||||
SSL_LIBRARY_VERSION_TLS_1_2 };
|
||||
StrongCipherStatus strongCipherStatus = StrongCipherStatusUnknown;
|
||||
helpers.adjustForTLSIntolerance(HOST, PORT, range, strongCipherStatus);
|
||||
ASSERT_EQ(SSL_LIBRARY_VERSION_3_0, range.min);
|
||||
// When rememberIntolerantAtVersion returns false, it also resets the
|
||||
// intolerance information for the server.
|
||||
ASSERT_EQ(SSL_LIBRARY_VERSION_TLS_1_2, range.max);
|
||||
ASSERT_EQ(StrongCipherStatusUnknown, strongCipherStatus);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(TLSIntoleranceTest, Test_Strong_Ciphers_Failed_At_1_1)
|
||||
{
|
||||
helpers.mVersionFallbackLimit = SSL_LIBRARY_VERSION_3_0;
|
||||
|
||||
// No adjustment made when there is no entry for the site.
|
||||
{
|
||||
SSLVersionRange range = { SSL_LIBRARY_VERSION_3_0,
|
||||
SSL_LIBRARY_VERSION_TLS_1_2 };
|
||||
StrongCipherStatus strongCipherStatus = StrongCipherStatusUnknown;
|
||||
helpers.adjustForTLSIntolerance(HOST, PORT, range, strongCipherStatus);
|
||||
ASSERT_TRUE(helpers.rememberIntolerantAtVersion(HOST, PORT,
|
||||
range.min, range.max, 0));
|
||||
}
|
||||
|
||||
{
|
||||
SSLVersionRange range = { SSL_LIBRARY_VERSION_3_0,
|
||||
SSL_LIBRARY_VERSION_TLS_1_2 };
|
||||
StrongCipherStatus strongCipherStatus = StrongCipherStatusUnknown;
|
||||
helpers.adjustForTLSIntolerance(HOST, PORT, range, strongCipherStatus);
|
||||
ASSERT_TRUE(helpers.rememberStrongCiphersFailed(HOST, PORT));
|
||||
}
|
||||
|
||||
{
|
||||
SSLVersionRange range = { SSL_LIBRARY_VERSION_3_0,
|
||||
SSL_LIBRARY_VERSION_TLS_1_2 };
|
||||
StrongCipherStatus strongCipherStatus = StrongCipherStatusUnknown;
|
||||
helpers.adjustForTLSIntolerance(HOST, PORT, range, strongCipherStatus);
|
||||
ASSERT_EQ(SSL_LIBRARY_VERSION_3_0, range.min);
|
||||
ASSERT_EQ(SSL_LIBRARY_VERSION_TLS_1_1, range.max);
|
||||
ASSERT_EQ(StrongCiphersFailed, strongCipherStatus);
|
||||
|
||||
ASSERT_TRUE(helpers.rememberIntolerantAtVersion(HOST, PORT,
|
||||
range.min, range.max, 0));
|
||||
}
|
||||
|
||||
{
|
||||
SSLVersionRange range = { SSL_LIBRARY_VERSION_3_0,
|
||||
SSL_LIBRARY_VERSION_TLS_1_2 };
|
||||
StrongCipherStatus strongCipherStatus = StrongCipherStatusUnknown;
|
||||
helpers.adjustForTLSIntolerance(HOST, PORT, range, strongCipherStatus);
|
||||
ASSERT_EQ(SSL_LIBRARY_VERSION_3_0, range.min);
|
||||
ASSERT_EQ(SSL_LIBRARY_VERSION_TLS_1_0, range.max);
|
||||
ASSERT_EQ(StrongCiphersFailed, strongCipherStatus);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(TLSIntoleranceTest, Test_Strong_Ciphers_Failed_With_High_Limit)
|
||||
{
|
||||
// this value disables version fallback entirely: with this value, all efforts
|
||||
// to mark an origin as version intolerant fail
|
||||
helpers.mVersionFallbackLimit = SSL_LIBRARY_VERSION_TLS_1_2;
|
||||
// ...but weak ciphers fallback will not be disabled
|
||||
ASSERT_TRUE(helpers.rememberStrongCiphersFailed(HOST, PORT));
|
||||
ASSERT_FALSE(helpers.rememberIntolerantAtVersion(HOST, PORT,
|
||||
SSL_LIBRARY_VERSION_3_0,
|
||||
SSL_LIBRARY_VERSION_TLS_1_2,
|
||||
0));
|
||||
ASSERT_FALSE(helpers.rememberIntolerantAtVersion(HOST, PORT,
|
||||
SSL_LIBRARY_VERSION_3_0,
|
||||
SSL_LIBRARY_VERSION_TLS_1_1,
|
||||
0));
|
||||
ASSERT_FALSE(helpers.rememberIntolerantAtVersion(HOST, PORT,
|
||||
SSL_LIBRARY_VERSION_3_0,
|
||||
SSL_LIBRARY_VERSION_TLS_1_0,
|
||||
0));
|
||||
}
|
||||
|
||||
TEST_F(TLSIntoleranceTest, Test_Tolerant_Does_Not_Override_Weak_Ciphers_Fallback)
|
||||
{
|
||||
ASSERT_TRUE(helpers.rememberStrongCiphersFailed(HOST, PORT));
|
||||
// No adjustment made when intolerant is zero.
|
||||
helpers.rememberTolerantAtVersion(HOST, PORT, SSL_LIBRARY_VERSION_TLS_1_1);
|
||||
SSLVersionRange range = { SSL_LIBRARY_VERSION_3_0,
|
||||
SSL_LIBRARY_VERSION_TLS_1_2 };
|
||||
StrongCipherStatus strongCipherStatus = StrongCipherStatusUnknown;
|
||||
helpers.adjustForTLSIntolerance(HOST, PORT, range, strongCipherStatus);
|
||||
ASSERT_EQ(SSL_LIBRARY_VERSION_3_0, range.min);
|
||||
ASSERT_EQ(SSL_LIBRARY_VERSION_TLS_1_2, range.max);
|
||||
ASSERT_EQ(StrongCiphersFailed, strongCipherStatus);
|
||||
}
|
||||
|
||||
TEST_F(TLSIntoleranceTest, Test_Weak_Ciphers_Fallback_Does_Not_Override_Tolerant)
|
||||
{
|
||||
// No adjustment made when there is no entry for the site.
|
||||
helpers.rememberTolerantAtVersion(HOST, PORT, SSL_LIBRARY_VERSION_TLS_1_1);
|
||||
// false because strongCipherWorked is set by rememberTolerantAtVersion.
|
||||
ASSERT_FALSE(helpers.rememberStrongCiphersFailed(HOST, PORT));
|
||||
SSLVersionRange range = { SSL_LIBRARY_VERSION_3_0,
|
||||
SSL_LIBRARY_VERSION_TLS_1_2 };
|
||||
StrongCipherStatus strongCipherStatus = StrongCipherStatusUnknown;
|
||||
helpers.adjustForTLSIntolerance(HOST, PORT, range, strongCipherStatus);
|
||||
ASSERT_EQ(SSL_LIBRARY_VERSION_3_0, range.min);
|
||||
ASSERT_EQ(SSL_LIBRARY_VERSION_TLS_1_2, range.max);
|
||||
ASSERT_EQ(StrongCiphersWorked, strongCipherStatus);
|
||||
}
|
||||
|
||||
TEST_F(TLSIntoleranceTest, TLS_Forget_Intolerance)
|
||||
{
|
||||
{
|
||||
@ -252,9 +429,11 @@ TEST_F(TLSIntoleranceTest, TLS_Forget_Intolerance)
|
||||
|
||||
SSLVersionRange range = { SSL_LIBRARY_VERSION_3_0,
|
||||
SSL_LIBRARY_VERSION_TLS_1_2 };
|
||||
helpers.adjustForTLSIntolerance(HOST, PORT, range);
|
||||
StrongCipherStatus strongCipherStatus = StrongCipherStatusUnknown;
|
||||
helpers.adjustForTLSIntolerance(HOST, PORT, range, strongCipherStatus);
|
||||
ASSERT_EQ(SSL_LIBRARY_VERSION_3_0, range.min);
|
||||
ASSERT_EQ(SSL_LIBRARY_VERSION_TLS_1_1, range.max);
|
||||
ASSERT_EQ(StrongCipherStatusUnknown, strongCipherStatus);
|
||||
}
|
||||
|
||||
{
|
||||
@ -262,22 +441,49 @@ TEST_F(TLSIntoleranceTest, TLS_Forget_Intolerance)
|
||||
|
||||
SSLVersionRange range = { SSL_LIBRARY_VERSION_3_0,
|
||||
SSL_LIBRARY_VERSION_TLS_1_2 };
|
||||
helpers.adjustForTLSIntolerance(HOST, PORT, range);
|
||||
StrongCipherStatus strongCipherStatus = StrongCipherStatusUnknown;
|
||||
helpers.adjustForTLSIntolerance(HOST, PORT, range, strongCipherStatus);
|
||||
ASSERT_EQ(SSL_LIBRARY_VERSION_3_0, range.min);
|
||||
ASSERT_EQ(SSL_LIBRARY_VERSION_TLS_1_2, range.max);
|
||||
ASSERT_EQ(StrongCipherStatusUnknown, strongCipherStatus);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(TLSIntoleranceTest, TLS_Forget_Strong_Cipher_Failed)
|
||||
{
|
||||
{
|
||||
ASSERT_TRUE(helpers.rememberStrongCiphersFailed(HOST, PORT));
|
||||
|
||||
SSLVersionRange range = { SSL_LIBRARY_VERSION_3_0,
|
||||
SSL_LIBRARY_VERSION_TLS_1_2 };
|
||||
StrongCipherStatus strongCipherStatus = StrongCipherStatusUnknown;
|
||||
helpers.adjustForTLSIntolerance(HOST, PORT, range, strongCipherStatus);
|
||||
ASSERT_EQ(StrongCiphersFailed, strongCipherStatus);
|
||||
}
|
||||
|
||||
{
|
||||
helpers.forgetIntolerance(HOST, PORT);
|
||||
|
||||
SSLVersionRange range = { SSL_LIBRARY_VERSION_3_0,
|
||||
SSL_LIBRARY_VERSION_TLS_1_2 };
|
||||
StrongCipherStatus strongCipherStatus = StrongCipherStatusUnknown;
|
||||
helpers.adjustForTLSIntolerance(HOST, PORT, range, strongCipherStatus);
|
||||
ASSERT_EQ(StrongCipherStatusUnknown, strongCipherStatus);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(TLSIntoleranceTest, TLS_Dont_Forget_Tolerance)
|
||||
{
|
||||
{
|
||||
helpers.rememberTolerantAtVersion(HOST, 1, SSL_LIBRARY_VERSION_TLS_1_1);
|
||||
helpers.rememberTolerantAtVersion(HOST, PORT, SSL_LIBRARY_VERSION_TLS_1_1);
|
||||
|
||||
SSLVersionRange range = { SSL_LIBRARY_VERSION_3_0,
|
||||
SSL_LIBRARY_VERSION_TLS_1_2 };
|
||||
helpers.adjustForTLSIntolerance(HOST, PORT, range);
|
||||
StrongCipherStatus strongCipherStatus = StrongCipherStatusUnknown;
|
||||
helpers.adjustForTLSIntolerance(HOST, PORT, range, strongCipherStatus);
|
||||
ASSERT_EQ(SSL_LIBRARY_VERSION_3_0, range.min);
|
||||
ASSERT_EQ(SSL_LIBRARY_VERSION_TLS_1_2, range.max);
|
||||
ASSERT_EQ(StrongCiphersWorked, strongCipherStatus);
|
||||
}
|
||||
|
||||
{
|
||||
@ -288,9 +494,11 @@ TEST_F(TLSIntoleranceTest, TLS_Dont_Forget_Tolerance)
|
||||
|
||||
SSLVersionRange range = { SSL_LIBRARY_VERSION_3_0,
|
||||
SSL_LIBRARY_VERSION_TLS_1_2 };
|
||||
helpers.adjustForTLSIntolerance(HOST, PORT, range);
|
||||
StrongCipherStatus strongCipherStatus = StrongCipherStatusUnknown;
|
||||
helpers.adjustForTLSIntolerance(HOST, PORT, range, strongCipherStatus);
|
||||
ASSERT_EQ(SSL_LIBRARY_VERSION_3_0, range.min);
|
||||
ASSERT_EQ(SSL_LIBRARY_VERSION_TLS_1_1, range.max);
|
||||
ASSERT_EQ(StrongCiphersWorked, strongCipherStatus);
|
||||
}
|
||||
|
||||
{
|
||||
@ -298,8 +506,10 @@ TEST_F(TLSIntoleranceTest, TLS_Dont_Forget_Tolerance)
|
||||
|
||||
SSLVersionRange range = { SSL_LIBRARY_VERSION_3_0,
|
||||
SSL_LIBRARY_VERSION_TLS_1_2 };
|
||||
helpers.adjustForTLSIntolerance(HOST, PORT, range);
|
||||
StrongCipherStatus strongCipherStatus = StrongCipherStatusUnknown;
|
||||
helpers.adjustForTLSIntolerance(HOST, PORT, range, strongCipherStatus);
|
||||
ASSERT_EQ(SSL_LIBRARY_VERSION_3_0, range.min);
|
||||
ASSERT_EQ(SSL_LIBRARY_VERSION_TLS_1_2, range.max);
|
||||
ASSERT_EQ(StrongCiphersWorked, strongCipherStatus);
|
||||
}
|
||||
}
|
||||
|
@ -6382,6 +6382,11 @@
|
||||
"n_values": 64,
|
||||
"description": "TLS/SSL version intolerance was falsely detected, server rejected handshake"
|
||||
},
|
||||
"SSL_WEAK_CIPHERS_FALLBACK": {
|
||||
"expires_in_version": "never",
|
||||
"kind": "boolean",
|
||||
"description": "Fallback attempted when server did not support any strong cipher suites"
|
||||
},
|
||||
"SSL_CIPHER_SUITE_FULL": {
|
||||
"expires_in_version": "never",
|
||||
"kind": "enumerated",
|
||||
|
Loading…
Reference in New Issue
Block a user