mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1114816 - Implement TLS intolerance fallback whitelist. r=keeler
This commit is contained in:
parent
984b596986
commit
62c0790149
@ -5,6 +5,14 @@
|
||||
pref("security.tls.version.min", 1);
|
||||
pref("security.tls.version.max", 3);
|
||||
pref("security.tls.version.fallback-limit", 3);
|
||||
# Do not add a site without filing a corresponding evangelism bug.
|
||||
# bug 1095507, www.kredodirect.com.ua
|
||||
# bug 1111354, web3.secureinternetbank.com
|
||||
# bug 1112110, cmypage.kuronekoyamato.co.jp
|
||||
# bug 1115883, www.timewarnercable.com and wayfarer.timewarnercable.com
|
||||
# bug 1126652, www.animate-onlineshop.jp
|
||||
# bug 1126654, www.gamers-onlineshop.jp
|
||||
pref("security.tls.insecure_fallback_hosts", "www.kredodirect.com.ua,web3.secureinternetbank.com,cmypage.kuronekoyamato.co.jp,www.timewarnercable.com,wayfarer.timewarnercable.com,www.animate-onlineshop.jp,www.gamers-onlineshop.jp");
|
||||
|
||||
pref("security.ssl.allow_unrestricted_renego_everywhere__temporarily_available_pref", false);
|
||||
pref("security.ssl.renego_unrestricted_hosts", "");
|
||||
|
@ -676,12 +676,10 @@ nsNSSSocketInfo::SharedState()
|
||||
|
||||
void nsSSLIOLayerHelpers::Cleanup()
|
||||
{
|
||||
MutexAutoLock lock(mutex);
|
||||
mTLSIntoleranceInfo.Clear();
|
||||
|
||||
if (mRenegoUnrestrictedSites) {
|
||||
delete mRenegoUnrestrictedSites;
|
||||
mRenegoUnrestrictedSites = nullptr;
|
||||
}
|
||||
mRenegoUnrestrictedSites.Clear();
|
||||
mInsecureFallbackSites.Clear();
|
||||
}
|
||||
|
||||
static void
|
||||
@ -863,6 +861,17 @@ nsSSLIOLayerHelpers::forgetIntolerance(const nsACString& hostName,
|
||||
return tolerant;
|
||||
}
|
||||
|
||||
bool
|
||||
nsSSLIOLayerHelpers::fallbackLimitReached(const nsACString& hostName,
|
||||
uint16_t intolerant)
|
||||
{
|
||||
MutexAutoLock lock(mutex);
|
||||
if (mInsecureFallbackSites.Contains(hostName)) {
|
||||
return intolerant <= SSL_LIBRARY_VERSION_TLS_1_0;
|
||||
}
|
||||
return intolerant <= mVersionFallbackLimit;
|
||||
}
|
||||
|
||||
// returns true if we should retry the handshake
|
||||
bool
|
||||
nsSSLIOLayerHelpers::rememberIntolerantAtVersion(const nsACString& hostName,
|
||||
@ -871,7 +880,7 @@ nsSSLIOLayerHelpers::rememberIntolerantAtVersion(const nsACString& hostName,
|
||||
uint16_t intolerant,
|
||||
PRErrorCode intoleranceReason)
|
||||
{
|
||||
if (intolerant <= minVersion || intolerant <= mVersionFallbackLimit) {
|
||||
if (intolerant <= minVersion || fallbackLimitReached(hostName, intolerant)) {
|
||||
// We can't fall back any further. Assume that intolerance isn't the issue.
|
||||
uint32_t tolerant = forgetIntolerance(hostName, port);
|
||||
// If we know the server is tolerant at the version, we don't have to
|
||||
@ -1444,8 +1453,7 @@ nsSSLIOLayerPoll(PRFileDesc* fd, int16_t in_flags, int16_t* out_flags)
|
||||
}
|
||||
|
||||
nsSSLIOLayerHelpers::nsSSLIOLayerHelpers()
|
||||
: mRenegoUnrestrictedSites(nullptr)
|
||||
, mTreatUnsafeNegotiationAsBroken(false)
|
||||
: mTreatUnsafeNegotiationAsBroken(false)
|
||||
, mWarnLevelMissingRFC5746(1)
|
||||
, mTLSIntoleranceInfo()
|
||||
, mFalseStartRequireNPN(true)
|
||||
@ -1655,11 +1663,9 @@ PrefObserver::Observe(nsISupports* aSubject, const char* aTopic,
|
||||
NS_ConvertUTF16toUTF8 prefName(someData);
|
||||
|
||||
if (prefName.EqualsLiteral("security.ssl.renego_unrestricted_hosts")) {
|
||||
nsCString unrestricted_hosts;
|
||||
Preferences::GetCString("security.ssl.renego_unrestricted_hosts", &unrestricted_hosts);
|
||||
if (!unrestricted_hosts.IsEmpty()) {
|
||||
mOwner->setRenegoUnrestrictedSites(unrestricted_hosts);
|
||||
}
|
||||
nsCString unrestrictedHosts;
|
||||
Preferences::GetCString("security.ssl.renego_unrestricted_hosts", &unrestrictedHosts);
|
||||
mOwner->setSiteList(mOwner->mRenegoUnrestrictedSites, unrestrictedHosts);
|
||||
} else if (prefName.EqualsLiteral("security.ssl.treat_unsafe_negotiation_as_broken")) {
|
||||
bool enabled;
|
||||
Preferences::GetBool("security.ssl.treat_unsafe_negotiation_as_broken", &enabled);
|
||||
@ -1674,6 +1680,10 @@ PrefObserver::Observe(nsISupports* aSubject, const char* aTopic,
|
||||
FALSE_START_REQUIRE_NPN_DEFAULT);
|
||||
} else if (prefName.EqualsLiteral("security.tls.version.fallback-limit")) {
|
||||
mOwner->loadVersionFallbackLimit();
|
||||
} else if (prefName.EqualsLiteral("security.tls.insecure_fallback_hosts")) {
|
||||
nsCString insecureFallbackHosts;
|
||||
Preferences::GetCString("security.tls.insecure_fallback_hosts", &insecureFallbackHosts);
|
||||
mOwner->setInsecureFallbackSites(insecureFallbackHosts);
|
||||
}
|
||||
}
|
||||
return NS_OK;
|
||||
@ -1710,6 +1720,10 @@ nsSSLIOLayerHelpers::~nsSSLIOLayerHelpers()
|
||||
"security.ssl.warn_missing_rfc5746");
|
||||
Preferences::RemoveObserver(mPrefObserver,
|
||||
"security.ssl.false_start.require-npn");
|
||||
Preferences::RemoveObserver(mPrefObserver,
|
||||
"security.tls.version.fallback-limit");
|
||||
Preferences::RemoveObserver(mPrefObserver,
|
||||
"security.tls.insecure_fallback_hosts");
|
||||
}
|
||||
}
|
||||
|
||||
@ -1758,13 +1772,9 @@ nsSSLIOLayerHelpers::Init()
|
||||
nsSSLPlaintextLayerMethods.recv = PlaintextRecv;
|
||||
}
|
||||
|
||||
mRenegoUnrestrictedSites = new nsTHashtable<nsCStringHashKey>();
|
||||
|
||||
nsCString unrestricted_hosts;
|
||||
Preferences::GetCString("security.ssl.renego_unrestricted_hosts", &unrestricted_hosts);
|
||||
if (!unrestricted_hosts.IsEmpty()) {
|
||||
setRenegoUnrestrictedSites(unrestricted_hosts);
|
||||
}
|
||||
nsCString unrestrictedHosts;
|
||||
Preferences::GetCString("security.ssl.renego_unrestricted_hosts", &unrestrictedHosts);
|
||||
setSiteList(mRenegoUnrestrictedSites, unrestrictedHosts);
|
||||
|
||||
bool enabled = false;
|
||||
Preferences::GetBool("security.ssl.treat_unsafe_negotiation_as_broken", &enabled);
|
||||
@ -1778,6 +1788,9 @@ nsSSLIOLayerHelpers::Init()
|
||||
Preferences::GetBool("security.ssl.false_start.require-npn",
|
||||
FALSE_START_REQUIRE_NPN_DEFAULT);
|
||||
loadVersionFallbackLimit();
|
||||
nsCString insecureFallbackHosts;
|
||||
Preferences::GetCString("security.tls.insecure_fallback_hosts", &insecureFallbackHosts);
|
||||
setInsecureFallbackSites(insecureFallbackHosts);
|
||||
|
||||
mPrefObserver = new PrefObserver(this);
|
||||
Preferences::AddStrongObserver(mPrefObserver,
|
||||
@ -1790,6 +1803,8 @@ nsSSLIOLayerHelpers::Init()
|
||||
"security.ssl.false_start.require-npn");
|
||||
Preferences::AddStrongObserver(mPrefObserver,
|
||||
"security.tls.version.fallback-limit");
|
||||
Preferences::AddStrongObserver(mPrefObserver,
|
||||
"security.tls.insecure_fallback_hosts");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -1810,30 +1825,30 @@ nsSSLIOLayerHelpers::loadVersionFallbackLimit()
|
||||
void
|
||||
nsSSLIOLayerHelpers::clearStoredData()
|
||||
{
|
||||
mRenegoUnrestrictedSites->Clear();
|
||||
MutexAutoLock lock(mutex);
|
||||
mRenegoUnrestrictedSites.Clear();
|
||||
mInsecureFallbackSites.Clear();
|
||||
mTLSIntoleranceInfo.Clear();
|
||||
}
|
||||
|
||||
void
|
||||
nsSSLIOLayerHelpers::setRenegoUnrestrictedSites(const nsCString& str)
|
||||
nsSSLIOLayerHelpers::setSiteList(nsTHashtable<nsCStringHashKey>& sites,
|
||||
const nsCString& str)
|
||||
{
|
||||
MutexAutoLock lock(mutex);
|
||||
|
||||
if (mRenegoUnrestrictedSites) {
|
||||
delete mRenegoUnrestrictedSites;
|
||||
mRenegoUnrestrictedSites = nullptr;
|
||||
}
|
||||
sites.Clear();
|
||||
|
||||
mRenegoUnrestrictedSites = new nsTHashtable<nsCStringHashKey>();
|
||||
if (!mRenegoUnrestrictedSites)
|
||||
if (str.IsEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsCCharSeparatedTokenizer toker(str, ',');
|
||||
|
||||
while (toker.hasMoreTokens()) {
|
||||
const nsCSubstring& host = toker.nextToken();
|
||||
if (!host.IsEmpty()) {
|
||||
mRenegoUnrestrictedSites->PutEntry(host);
|
||||
sites.PutEntry(host);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1842,7 +1857,7 @@ bool
|
||||
nsSSLIOLayerHelpers::isRenegoUnrestrictedSite(const nsCString& str)
|
||||
{
|
||||
MutexAutoLock lock(mutex);
|
||||
return mRenegoUnrestrictedSites->Contains(str);
|
||||
return mRenegoUnrestrictedSites.Contains(str);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -186,7 +186,7 @@ public:
|
||||
static PRIOMethods nsSSLIOLayerMethods;
|
||||
static PRIOMethods nsSSLPlaintextLayerMethods;
|
||||
|
||||
nsTHashtable<nsCStringHashKey>* mRenegoUnrestrictedSites;
|
||||
nsTHashtable<nsCStringHashKey> mRenegoUnrestrictedSites;
|
||||
bool mTreatUnsafeNegotiationAsBroken;
|
||||
int32_t mWarnLevelMissingRFC5746;
|
||||
|
||||
@ -209,9 +209,14 @@ private:
|
||||
}
|
||||
};
|
||||
nsDataHashtable<nsCStringHashKey, IntoleranceEntry> mTLSIntoleranceInfo;
|
||||
// Sites that require insecure fallback to TLS 1.0, set by the pref
|
||||
// security.tls.insecure_fallback_hosts, which is a comma-delimited
|
||||
// list of domain names.
|
||||
nsTHashtable<nsCStringHashKey> mInsecureFallbackSites;
|
||||
public:
|
||||
void rememberTolerantAtVersion(const nsACString& hostname, int16_t port,
|
||||
uint16_t tolerant);
|
||||
bool fallbackLimitReached(const nsACString& hostname, uint16_t intolerant);
|
||||
bool rememberIntolerantAtVersion(const nsACString& hostname, int16_t port,
|
||||
uint16_t intolerant, uint16_t minVersion,
|
||||
PRErrorCode intoleranceReason);
|
||||
@ -225,10 +230,15 @@ public:
|
||||
/*out*/ StrongCipherStatus& strongCipherStatus);
|
||||
PRErrorCode getIntoleranceReason(const nsACString& hostname, int16_t port);
|
||||
|
||||
void setRenegoUnrestrictedSites(const nsCString& str);
|
||||
void setSiteList(nsTHashtable<nsCStringHashKey>& sites,
|
||||
const nsCString& str);
|
||||
bool isRenegoUnrestrictedSite(const nsCString& str);
|
||||
void clearStoredData();
|
||||
void loadVersionFallbackLimit();
|
||||
void setInsecureFallbackSites(const nsCString& str)
|
||||
{
|
||||
setSiteList(mInsecureFallbackSites, str);
|
||||
}
|
||||
|
||||
bool mFalseStartRequireNPN;
|
||||
bool mFalseStartRequireForwardSecrecy;
|
||||
|
@ -517,3 +517,82 @@ TEST_F(TLSIntoleranceTest, TLS_Dont_Forget_Tolerance)
|
||||
ASSERT_EQ(StrongCiphersWorked, strongCipherStatus);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_F(TLSIntoleranceTest, TLS_Per_Site_Fallback_Limit)
|
||||
{
|
||||
NS_NAMED_LITERAL_CSTRING(example_com, "example.com");
|
||||
NS_NAMED_LITERAL_CSTRING(example_net, "example.net");
|
||||
NS_NAMED_LITERAL_CSTRING(example_org, "example.org");
|
||||
|
||||
helpers.mVersionFallbackLimit = SSL_LIBRARY_VERSION_TLS_1_0;
|
||||
|
||||
ASSERT_FALSE(helpers.fallbackLimitReached(example_com, SSL_LIBRARY_VERSION_TLS_1_2));
|
||||
ASSERT_FALSE(helpers.fallbackLimitReached(example_com, SSL_LIBRARY_VERSION_TLS_1_1));
|
||||
ASSERT_TRUE(helpers.fallbackLimitReached(example_com, SSL_LIBRARY_VERSION_TLS_1_0));
|
||||
ASSERT_FALSE(helpers.fallbackLimitReached(example_net, SSL_LIBRARY_VERSION_TLS_1_2));
|
||||
ASSERT_FALSE(helpers.fallbackLimitReached(example_net, SSL_LIBRARY_VERSION_TLS_1_1));
|
||||
ASSERT_TRUE(helpers.fallbackLimitReached(example_net, SSL_LIBRARY_VERSION_TLS_1_0));
|
||||
ASSERT_FALSE(helpers.fallbackLimitReached(example_org, SSL_LIBRARY_VERSION_TLS_1_2));
|
||||
ASSERT_FALSE(helpers.fallbackLimitReached(example_org, SSL_LIBRARY_VERSION_TLS_1_1));
|
||||
ASSERT_TRUE(helpers.fallbackLimitReached(example_org, SSL_LIBRARY_VERSION_TLS_1_0));
|
||||
|
||||
helpers.mVersionFallbackLimit = SSL_LIBRARY_VERSION_TLS_1_2;
|
||||
|
||||
ASSERT_TRUE(helpers.fallbackLimitReached(example_com, SSL_LIBRARY_VERSION_TLS_1_2));
|
||||
ASSERT_TRUE(helpers.fallbackLimitReached(example_com, SSL_LIBRARY_VERSION_TLS_1_1));
|
||||
ASSERT_TRUE(helpers.fallbackLimitReached(example_com, SSL_LIBRARY_VERSION_TLS_1_0));
|
||||
ASSERT_TRUE(helpers.fallbackLimitReached(example_net, SSL_LIBRARY_VERSION_TLS_1_2));
|
||||
ASSERT_TRUE(helpers.fallbackLimitReached(example_net, SSL_LIBRARY_VERSION_TLS_1_1));
|
||||
ASSERT_TRUE(helpers.fallbackLimitReached(example_net, SSL_LIBRARY_VERSION_TLS_1_0));
|
||||
ASSERT_TRUE(helpers.fallbackLimitReached(example_org, SSL_LIBRARY_VERSION_TLS_1_2));
|
||||
ASSERT_TRUE(helpers.fallbackLimitReached(example_org, SSL_LIBRARY_VERSION_TLS_1_1));
|
||||
ASSERT_TRUE(helpers.fallbackLimitReached(example_org, SSL_LIBRARY_VERSION_TLS_1_0));
|
||||
|
||||
helpers.setInsecureFallbackSites(example_com);
|
||||
|
||||
ASSERT_FALSE(helpers.fallbackLimitReached(example_com, SSL_LIBRARY_VERSION_TLS_1_2));
|
||||
ASSERT_FALSE(helpers.fallbackLimitReached(example_com, SSL_LIBRARY_VERSION_TLS_1_1));
|
||||
ASSERT_TRUE(helpers.fallbackLimitReached(example_com, SSL_LIBRARY_VERSION_TLS_1_0));
|
||||
ASSERT_TRUE(helpers.fallbackLimitReached(example_net, SSL_LIBRARY_VERSION_TLS_1_2));
|
||||
ASSERT_TRUE(helpers.fallbackLimitReached(example_net, SSL_LIBRARY_VERSION_TLS_1_1));
|
||||
ASSERT_TRUE(helpers.fallbackLimitReached(example_net, SSL_LIBRARY_VERSION_TLS_1_0));
|
||||
ASSERT_TRUE(helpers.fallbackLimitReached(example_org, SSL_LIBRARY_VERSION_TLS_1_2));
|
||||
ASSERT_TRUE(helpers.fallbackLimitReached(example_org, SSL_LIBRARY_VERSION_TLS_1_1));
|
||||
ASSERT_TRUE(helpers.fallbackLimitReached(example_org, SSL_LIBRARY_VERSION_TLS_1_0));
|
||||
|
||||
helpers.setInsecureFallbackSites(NS_LITERAL_CSTRING("example.com,example.net"));
|
||||
|
||||
ASSERT_FALSE(helpers.fallbackLimitReached(example_com, SSL_LIBRARY_VERSION_TLS_1_2));
|
||||
ASSERT_FALSE(helpers.fallbackLimitReached(example_com, SSL_LIBRARY_VERSION_TLS_1_1));
|
||||
ASSERT_TRUE(helpers.fallbackLimitReached(example_com, SSL_LIBRARY_VERSION_TLS_1_0));
|
||||
ASSERT_FALSE(helpers.fallbackLimitReached(example_net, SSL_LIBRARY_VERSION_TLS_1_2));
|
||||
ASSERT_FALSE(helpers.fallbackLimitReached(example_net, SSL_LIBRARY_VERSION_TLS_1_1));
|
||||
ASSERT_TRUE(helpers.fallbackLimitReached(example_net, SSL_LIBRARY_VERSION_TLS_1_0));
|
||||
ASSERT_TRUE(helpers.fallbackLimitReached(example_org, SSL_LIBRARY_VERSION_TLS_1_2));
|
||||
ASSERT_TRUE(helpers.fallbackLimitReached(example_org, SSL_LIBRARY_VERSION_TLS_1_1));
|
||||
ASSERT_TRUE(helpers.fallbackLimitReached(example_org, SSL_LIBRARY_VERSION_TLS_1_0));
|
||||
|
||||
helpers.setInsecureFallbackSites(example_net);
|
||||
|
||||
ASSERT_TRUE(helpers.fallbackLimitReached(example_com, SSL_LIBRARY_VERSION_TLS_1_2));
|
||||
ASSERT_TRUE(helpers.fallbackLimitReached(example_com, SSL_LIBRARY_VERSION_TLS_1_1));
|
||||
ASSERT_TRUE(helpers.fallbackLimitReached(example_com, SSL_LIBRARY_VERSION_TLS_1_0));
|
||||
ASSERT_FALSE(helpers.fallbackLimitReached(example_net, SSL_LIBRARY_VERSION_TLS_1_2));
|
||||
ASSERT_FALSE(helpers.fallbackLimitReached(example_net, SSL_LIBRARY_VERSION_TLS_1_1));
|
||||
ASSERT_TRUE(helpers.fallbackLimitReached(example_net, SSL_LIBRARY_VERSION_TLS_1_0));
|
||||
ASSERT_TRUE(helpers.fallbackLimitReached(example_org, SSL_LIBRARY_VERSION_TLS_1_2));
|
||||
ASSERT_TRUE(helpers.fallbackLimitReached(example_org, SSL_LIBRARY_VERSION_TLS_1_1));
|
||||
ASSERT_TRUE(helpers.fallbackLimitReached(example_org, SSL_LIBRARY_VERSION_TLS_1_0));
|
||||
|
||||
helpers.setInsecureFallbackSites(EmptyCString());
|
||||
|
||||
ASSERT_TRUE(helpers.fallbackLimitReached(example_com, SSL_LIBRARY_VERSION_TLS_1_2));
|
||||
ASSERT_TRUE(helpers.fallbackLimitReached(example_com, SSL_LIBRARY_VERSION_TLS_1_1));
|
||||
ASSERT_TRUE(helpers.fallbackLimitReached(example_com, SSL_LIBRARY_VERSION_TLS_1_0));
|
||||
ASSERT_TRUE(helpers.fallbackLimitReached(example_net, SSL_LIBRARY_VERSION_TLS_1_2));
|
||||
ASSERT_TRUE(helpers.fallbackLimitReached(example_net, SSL_LIBRARY_VERSION_TLS_1_1));
|
||||
ASSERT_TRUE(helpers.fallbackLimitReached(example_net, SSL_LIBRARY_VERSION_TLS_1_0));
|
||||
ASSERT_TRUE(helpers.fallbackLimitReached(example_org, SSL_LIBRARY_VERSION_TLS_1_2));
|
||||
ASSERT_TRUE(helpers.fallbackLimitReached(example_org, SSL_LIBRARY_VERSION_TLS_1_1));
|
||||
ASSERT_TRUE(helpers.fallbackLimitReached(example_org, SSL_LIBRARY_VERSION_TLS_1_0));
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user