Bug 1168635 - Add an XPCOM interface to allow RC4. r=keeler
This commit is contained in:
62
security/manager/ssl/WeakCryptoOverride.cpp
Normal file
62
security/manager/ssl/WeakCryptoOverride.cpp
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||||
|
/* 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/. */
|
||||||
|
|
||||||
|
#include "WeakCryptoOverride.h"
|
||||||
|
|
||||||
|
#include "MainThreadUtils.h"
|
||||||
|
#include "SharedSSLState.h"
|
||||||
|
|
||||||
|
using namespace mozilla;
|
||||||
|
using namespace mozilla::psm;
|
||||||
|
|
||||||
|
NS_IMPL_ISUPPORTS(WeakCryptoOverride,
|
||||||
|
nsIWeakCryptoOverride)
|
||||||
|
|
||||||
|
WeakCryptoOverride::WeakCryptoOverride()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
WeakCryptoOverride::~WeakCryptoOverride()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
WeakCryptoOverride::AddWeakCryptoOverride(const nsACString& aHostName,
|
||||||
|
bool aPrivate, bool aTemporary)
|
||||||
|
{
|
||||||
|
if (!NS_IsMainThread()) {
|
||||||
|
return NS_ERROR_NOT_SAME_THREAD;
|
||||||
|
}
|
||||||
|
|
||||||
|
SharedSSLState* sharedState = aPrivate ? PrivateSSLState()
|
||||||
|
: PublicSSLState();
|
||||||
|
if (!sharedState) {
|
||||||
|
return NS_ERROR_NOT_AVAILABLE;
|
||||||
|
}
|
||||||
|
const nsPromiseFlatCString& host = PromiseFlatCString(aHostName);
|
||||||
|
sharedState->IOLayerHelpers().addInsecureFallbackSite(host, aTemporary);
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
WeakCryptoOverride::RemoveWeakCryptoOverride(const nsACString& aHostName,
|
||||||
|
int32_t aPort, bool aPrivate)
|
||||||
|
{
|
||||||
|
if (!NS_IsMainThread()) {
|
||||||
|
return NS_ERROR_NOT_SAME_THREAD;
|
||||||
|
}
|
||||||
|
|
||||||
|
SharedSSLState* sharedState = aPrivate ? PrivateSSLState()
|
||||||
|
: PublicSSLState();
|
||||||
|
if (!sharedState) {
|
||||||
|
return NS_ERROR_NOT_AVAILABLE;
|
||||||
|
}
|
||||||
|
const nsPromiseFlatCString& host = PromiseFlatCString(aHostName);
|
||||||
|
sharedState->IOLayerHelpers().removeInsecureFallbackSite(host, aPort);
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
35
security/manager/ssl/WeakCryptoOverride.h
Normal file
35
security/manager/ssl/WeakCryptoOverride.h
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||||
|
*
|
||||||
|
* 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/. */
|
||||||
|
|
||||||
|
#ifndef WEAKCRYPTOOVERRIDE_H
|
||||||
|
#define WEAKCRYPTOOVERRIDE_H
|
||||||
|
|
||||||
|
#include "nsIWeakCryptoOverride.h"
|
||||||
|
#include "nsWeakReference.h"
|
||||||
|
|
||||||
|
namespace mozilla {
|
||||||
|
namespace psm {
|
||||||
|
|
||||||
|
class WeakCryptoOverride final : public nsIWeakCryptoOverride
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
NS_DECL_ISUPPORTS
|
||||||
|
NS_DECL_NSIWEAKCRYPTOOVERRIDE
|
||||||
|
|
||||||
|
WeakCryptoOverride();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
~WeakCryptoOverride();
|
||||||
|
};
|
||||||
|
|
||||||
|
} // psm
|
||||||
|
} // mozilla
|
||||||
|
|
||||||
|
#define NS_WEAKCRYPTOOVERRIDE_CID /* ffb06724-3c20-447c-8328-ae71513dd618 */ \
|
||||||
|
{ 0xffb06724, 0x3c20, 0x447c, \
|
||||||
|
{ 0x83, 0x28, 0xae, 0x71, 0x51, 0x3d, 0xd6, 0x18 } }
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -37,6 +37,7 @@ XPIDL_SOURCES += [
|
|||||||
'nsITokenDialogs.idl',
|
'nsITokenDialogs.idl',
|
||||||
'nsITokenPasswordDialogs.idl',
|
'nsITokenPasswordDialogs.idl',
|
||||||
'nsIUserCertPicker.idl',
|
'nsIUserCertPicker.idl',
|
||||||
|
'nsIWeakCryptoOverride.idl',
|
||||||
'nsIX509Cert.idl',
|
'nsIX509Cert.idl',
|
||||||
'nsIX509CertDB.idl',
|
'nsIX509CertDB.idl',
|
||||||
'nsIX509CertList.idl',
|
'nsIX509CertList.idl',
|
||||||
@@ -126,6 +127,7 @@ UNIFIED_SOURCES += [
|
|||||||
'SharedSSLState.cpp',
|
'SharedSSLState.cpp',
|
||||||
'SSLServerCertVerification.cpp',
|
'SSLServerCertVerification.cpp',
|
||||||
'TransportSecurityInfo.cpp',
|
'TransportSecurityInfo.cpp',
|
||||||
|
'WeakCryptoOverride.cpp',
|
||||||
]
|
]
|
||||||
|
|
||||||
# nsNSSCertificateDB.cpp needs to include nscert.h before everything else.
|
# nsNSSCertificateDB.cpp needs to include nscert.h before everything else.
|
||||||
|
|||||||
45
security/manager/ssl/nsIWeakCryptoOverride.idl
Normal file
45
security/manager/ssl/nsIWeakCryptoOverride.idl
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||||
|
*
|
||||||
|
* 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/. */
|
||||||
|
|
||||||
|
#include "nsISupports.idl"
|
||||||
|
|
||||||
|
%{C++
|
||||||
|
#define NS_WEAKCRYPTOOVERRIDE_CONTRACTID "@mozilla.org/security/weakcryptooverride;1"
|
||||||
|
%}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This represents the fallback whitelist for
|
||||||
|
* weak crypto servers such as RC4-only.
|
||||||
|
*/
|
||||||
|
[scriptable, uuid(27b4d3df-8f15-4eb4-a35f-474e911b61e7)]
|
||||||
|
interface nsIWeakCryptoOverride : nsISupports {
|
||||||
|
/**
|
||||||
|
* Add a weak crypto override for the given hostname:port.
|
||||||
|
* Main thread only.
|
||||||
|
*
|
||||||
|
* @param aHostName The host (punycode) this mapping belongs to
|
||||||
|
* @param aPrivate The override info will used for the private browsing
|
||||||
|
* session and no information will be written to the disk.
|
||||||
|
* @param aTemporary The override info will not persist between sessions.
|
||||||
|
* Ignored if aPrivate is true.
|
||||||
|
*/
|
||||||
|
void addWeakCryptoOverride(in ACString aHostName,
|
||||||
|
in boolean aPrivate,
|
||||||
|
[optional] in boolean aTemporary);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove a weak crypto override for the given hostname:port.
|
||||||
|
* Main thread only.
|
||||||
|
*
|
||||||
|
* @param aHostName The host (punycode) whose entry should be cleared.
|
||||||
|
* @param aPort The port whose entry should be cleared.
|
||||||
|
* @param aPrivate The override info will used for the private browsing
|
||||||
|
* session.
|
||||||
|
*/
|
||||||
|
void removeWeakCryptoOverride(in ACString aHostName,
|
||||||
|
in int32_t aPort,
|
||||||
|
in boolean aPrivate);
|
||||||
|
};
|
||||||
@@ -1239,6 +1239,9 @@ void HandshakeCallback(PRFileDesc* fd, void* client_data) {
|
|||||||
} else {
|
} else {
|
||||||
state = nsIWebProgressListener::STATE_IS_SECURE |
|
state = nsIWebProgressListener::STATE_IS_SECURE |
|
||||||
nsIWebProgressListener::STATE_SECURE_HIGH;
|
nsIWebProgressListener::STATE_SECURE_HIGH;
|
||||||
|
// we know this site no longer requires a weak cipher
|
||||||
|
ioLayerHelpers.removeInsecureFallbackSite(infoObject->GetHostName(),
|
||||||
|
infoObject->GetPort());
|
||||||
}
|
}
|
||||||
infoObject->SetSecurityState(state);
|
infoObject->SetSecurityState(state);
|
||||||
|
|
||||||
|
|||||||
@@ -1539,9 +1539,11 @@ PrefObserver::Observe(nsISupports* aSubject, const char* aTopic,
|
|||||||
} else if (prefName.EqualsLiteral("security.tls.version.fallback-limit")) {
|
} else if (prefName.EqualsLiteral("security.tls.version.fallback-limit")) {
|
||||||
mOwner->loadVersionFallbackLimit();
|
mOwner->loadVersionFallbackLimit();
|
||||||
} else if (prefName.EqualsLiteral("security.tls.insecure_fallback_hosts")) {
|
} else if (prefName.EqualsLiteral("security.tls.insecure_fallback_hosts")) {
|
||||||
nsCString insecureFallbackHosts;
|
// Changes to the whitelist on the public side will update the pref.
|
||||||
Preferences::GetCString("security.tls.insecure_fallback_hosts", &insecureFallbackHosts);
|
// Don't propagate the changes to the private side.
|
||||||
mOwner->setInsecureFallbackSites(insecureFallbackHosts);
|
if (mOwner->isPublic()) {
|
||||||
|
mOwner->initInsecureFallbackSites();
|
||||||
|
}
|
||||||
} else if (prefName.EqualsLiteral("security.tls.insecure_fallback_hosts.use_static_list")) {
|
} else if (prefName.EqualsLiteral("security.tls.insecure_fallback_hosts.use_static_list")) {
|
||||||
mOwner->mUseStaticFallbackList =
|
mOwner->mUseStaticFallbackList =
|
||||||
Preferences::GetBool("security.tls.insecure_fallback_hosts.use_static_list", true);
|
Preferences::GetBool("security.tls.insecure_fallback_hosts.use_static_list", true);
|
||||||
@@ -1642,9 +1644,7 @@ nsSSLIOLayerHelpers::Init()
|
|||||||
Preferences::GetBool("security.ssl.false_start.require-npn",
|
Preferences::GetBool("security.ssl.false_start.require-npn",
|
||||||
FALSE_START_REQUIRE_NPN_DEFAULT);
|
FALSE_START_REQUIRE_NPN_DEFAULT);
|
||||||
loadVersionFallbackLimit();
|
loadVersionFallbackLimit();
|
||||||
nsCString insecureFallbackHosts;
|
initInsecureFallbackSites();
|
||||||
Preferences::GetCString("security.tls.insecure_fallback_hosts", &insecureFallbackHosts);
|
|
||||||
setInsecureFallbackSites(insecureFallbackHosts);
|
|
||||||
mUseStaticFallbackList =
|
mUseStaticFallbackList =
|
||||||
Preferences::GetBool("security.tls.insecure_fallback_hosts.use_static_list", true);
|
Preferences::GetBool("security.tls.insecure_fallback_hosts.use_static_list", true);
|
||||||
mUnrestrictedRC4Fallback =
|
mUnrestrictedRC4Fallback =
|
||||||
@@ -1707,6 +1707,102 @@ nsSSLIOLayerHelpers::setInsecureFallbackSites(const nsCString& str)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsSSLIOLayerHelpers::initInsecureFallbackSites()
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
nsCString insecureFallbackHosts;
|
||||||
|
Preferences::GetCString("security.tls.insecure_fallback_hosts",
|
||||||
|
&insecureFallbackHosts);
|
||||||
|
setInsecureFallbackSites(insecureFallbackHosts);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
nsSSLIOLayerHelpers::isPublic() const
|
||||||
|
{
|
||||||
|
return this == &PublicSSLState()->IOLayerHelpers();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsSSLIOLayerHelpers::addInsecureFallbackSite(const nsCString& hostname,
|
||||||
|
bool temporary)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
{
|
||||||
|
MutexAutoLock lock(mutex);
|
||||||
|
if (mInsecureFallbackSites.Contains(hostname)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mInsecureFallbackSites.PutEntry(hostname);
|
||||||
|
}
|
||||||
|
if (!isPublic() || temporary) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
nsCString value;
|
||||||
|
Preferences::GetCString("security.tls.insecure_fallback_hosts", &value);
|
||||||
|
if (!value.IsEmpty()) {
|
||||||
|
value.Append(',');
|
||||||
|
}
|
||||||
|
value.Append(hostname);
|
||||||
|
Preferences::SetCString("security.tls.insecure_fallback_hosts", value);
|
||||||
|
}
|
||||||
|
|
||||||
|
class FallbackPrefRemover final : public nsRunnable
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit FallbackPrefRemover(const nsACString& aHost)
|
||||||
|
: mHost(aHost)
|
||||||
|
{}
|
||||||
|
NS_IMETHOD Run() override;
|
||||||
|
private:
|
||||||
|
nsCString mHost;
|
||||||
|
};
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
FallbackPrefRemover::Run()
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
|
nsCString oldValue;
|
||||||
|
Preferences::GetCString("security.tls.insecure_fallback_hosts", &oldValue);
|
||||||
|
nsCCharSeparatedTokenizer toker(oldValue, ',');
|
||||||
|
nsCString newValue;
|
||||||
|
while (toker.hasMoreTokens()) {
|
||||||
|
const nsCSubstring& host = toker.nextToken();
|
||||||
|
if (host.Equals(mHost)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!newValue.IsEmpty()) {
|
||||||
|
newValue.Append(',');
|
||||||
|
}
|
||||||
|
newValue.Append(host);
|
||||||
|
}
|
||||||
|
Preferences::SetCString("security.tls.insecure_fallback_hosts", newValue);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsSSLIOLayerHelpers::removeInsecureFallbackSite(const nsACString& hostname,
|
||||||
|
uint16_t port)
|
||||||
|
{
|
||||||
|
forgetIntolerance(hostname, port);
|
||||||
|
{
|
||||||
|
MutexAutoLock lock(mutex);
|
||||||
|
if (!mInsecureFallbackSites.Contains(hostname)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mInsecureFallbackSites.RemoveEntry(hostname);
|
||||||
|
}
|
||||||
|
if (!isPublic()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
RefPtr<nsRunnable> runnable = new FallbackPrefRemover(hostname);
|
||||||
|
if (NS_IsMainThread()) {
|
||||||
|
runnable->Run();
|
||||||
|
} else {
|
||||||
|
NS_DispatchToMainThread(runnable);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct FallbackListComparator
|
struct FallbackListComparator
|
||||||
{
|
{
|
||||||
explicit FallbackListComparator(const char* aTarget)
|
explicit FallbackListComparator(const char* aTarget)
|
||||||
|
|||||||
@@ -226,6 +226,10 @@ public:
|
|||||||
void clearStoredData();
|
void clearStoredData();
|
||||||
void loadVersionFallbackLimit();
|
void loadVersionFallbackLimit();
|
||||||
void setInsecureFallbackSites(const nsCString& str);
|
void setInsecureFallbackSites(const nsCString& str);
|
||||||
|
void initInsecureFallbackSites();
|
||||||
|
bool isPublic() const;
|
||||||
|
void addInsecureFallbackSite(const nsCString& hostname, bool temporary);
|
||||||
|
void removeInsecureFallbackSite(const nsACString& hostname, uint16_t port);
|
||||||
bool isInsecureFallbackSite(const nsACString& hostname);
|
bool isInsecureFallbackSite(const nsACString& hostname);
|
||||||
|
|
||||||
bool mFalseStartRequireNPN;
|
bool mFalseStartRequireNPN;
|
||||||
|
|||||||
@@ -4,48 +4,44 @@
|
|||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* 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/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
#include "mozilla/ModuleUtils.h"
|
#include "CertBlocklist.h"
|
||||||
|
#include "nsCertOverrideService.h"
|
||||||
#include "nsNSSComponent.h"
|
#include "nsCertPicker.h"
|
||||||
#include "nsSSLSocketProvider.h"
|
#include "nsCrypto.h"
|
||||||
#include "nsTLSSocketProvider.h"
|
#include "nsCryptoHash.h"
|
||||||
|
#include "nsCURILoader.h"
|
||||||
|
#include "nsDataSignatureVerifier.h"
|
||||||
|
#include "nsDOMCID.h" //For the NS_CRYPTO_CONTRACTID define
|
||||||
|
#include "nsEntropyCollector.h"
|
||||||
|
#include "nsICategoryManager.h"
|
||||||
#include "nsKeygenHandler.h"
|
#include "nsKeygenHandler.h"
|
||||||
|
#include "nsKeyModule.h"
|
||||||
#include "nsSDR.h"
|
#include "mozilla/ModuleUtils.h"
|
||||||
|
#include "nsNetCID.h"
|
||||||
|
#include "nsNSSCertificate.h"
|
||||||
|
#include "nsNSSCertificateDB.h"
|
||||||
|
#include "nsNSSCertificateFakeTransport.h"
|
||||||
|
#include "nsNSSComponent.h"
|
||||||
|
#include "NSSErrorsService.h"
|
||||||
|
#include "nsNSSVersion.h"
|
||||||
|
#include "nsNTLMAuthModule.h"
|
||||||
#include "nsPK11TokenDB.h"
|
#include "nsPK11TokenDB.h"
|
||||||
#include "nsPKCS11Slot.h"
|
#include "nsPKCS11Slot.h"
|
||||||
#include "nsNSSCertificate.h"
|
#include "PSMContentListener.h"
|
||||||
#include "nsNSSCertificateFakeTransport.h"
|
#include "nsRandomGenerator.h"
|
||||||
#include "nsNSSCertificateDB.h"
|
#include "nsSDR.h"
|
||||||
|
#include "nsSecureBrowserUIImpl.h"
|
||||||
|
#include "nsSiteSecurityService.h"
|
||||||
|
#include "nsSSLSocketProvider.h"
|
||||||
|
#include "nsSSLStatus.h"
|
||||||
|
#include "nsTLSSocketProvider.h"
|
||||||
|
#include "TransportSecurityInfo.h"
|
||||||
|
#include "WeakCryptoOverride.h"
|
||||||
|
#include "nsXULAppAPI.h"
|
||||||
|
|
||||||
#ifdef MOZ_XUL
|
#ifdef MOZ_XUL
|
||||||
#include "nsCertTree.h"
|
#include "nsCertTree.h"
|
||||||
#endif
|
#endif
|
||||||
#include "nsCrypto.h"
|
|
||||||
#include "nsCryptoHash.h"
|
|
||||||
//For the NS_CRYPTO_CONTRACTID define
|
|
||||||
#include "nsDOMCID.h"
|
|
||||||
#include "nsNetCID.h"
|
|
||||||
#include "nsCertPicker.h"
|
|
||||||
#include "nsCURILoader.h"
|
|
||||||
#include "nsICategoryManager.h"
|
|
||||||
#include "nsNTLMAuthModule.h"
|
|
||||||
#include "nsKeyModule.h"
|
|
||||||
#include "nsDataSignatureVerifier.h"
|
|
||||||
#include "nsCertOverrideService.h"
|
|
||||||
#include "nsRandomGenerator.h"
|
|
||||||
#include "nsSSLStatus.h"
|
|
||||||
#include "TransportSecurityInfo.h"
|
|
||||||
#include "NSSErrorsService.h"
|
|
||||||
#include "nsNSSVersion.h"
|
|
||||||
#include "CertBlocklist.h"
|
|
||||||
#include "nsEntropyCollector.h"
|
|
||||||
#include "nsSecureBrowserUIImpl.h"
|
|
||||||
#include "nsSiteSecurityService.h"
|
|
||||||
|
|
||||||
#include "nsXULAppAPI.h"
|
|
||||||
|
|
||||||
#include "PSMContentListener.h"
|
|
||||||
|
|
||||||
#define NS_IS_PROCESS_DEFAULT \
|
#define NS_IS_PROCESS_DEFAULT \
|
||||||
(GeckoProcessType_Default == XRE_GetProcessType())
|
(GeckoProcessType_Default == XRE_GetProcessType())
|
||||||
@@ -223,6 +219,7 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsEntropyCollector)
|
|||||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsSecureBrowserUIImpl)
|
NS_GENERIC_FACTORY_CONSTRUCTOR(nsSecureBrowserUIImpl)
|
||||||
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(CertBlocklist, Init)
|
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(CertBlocklist, Init)
|
||||||
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsSiteSecurityService, Init)
|
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsSiteSecurityService, Init)
|
||||||
|
NS_GENERIC_FACTORY_CONSTRUCTOR(WeakCryptoOverride)
|
||||||
|
|
||||||
NS_DEFINE_NAMED_CID(NS_NSSCOMPONENT_CID);
|
NS_DEFINE_NAMED_CID(NS_NSSCOMPONENT_CID);
|
||||||
NS_DEFINE_NAMED_CID(NS_SSLSOCKETPROVIDER_CID);
|
NS_DEFINE_NAMED_CID(NS_SSLSOCKETPROVIDER_CID);
|
||||||
@@ -256,6 +253,7 @@ NS_DEFINE_NAMED_CID(NS_ENTROPYCOLLECTOR_CID);
|
|||||||
NS_DEFINE_NAMED_CID(NS_SECURE_BROWSER_UI_CID);
|
NS_DEFINE_NAMED_CID(NS_SECURE_BROWSER_UI_CID);
|
||||||
NS_DEFINE_NAMED_CID(NS_SITE_SECURITY_SERVICE_CID);
|
NS_DEFINE_NAMED_CID(NS_SITE_SECURITY_SERVICE_CID);
|
||||||
NS_DEFINE_NAMED_CID(NS_CERT_BLOCKLIST_CID);
|
NS_DEFINE_NAMED_CID(NS_CERT_BLOCKLIST_CID);
|
||||||
|
NS_DEFINE_NAMED_CID(NS_WEAKCRYPTOOVERRIDE_CID);
|
||||||
|
|
||||||
static const mozilla::Module::CIDEntry kNSSCIDs[] = {
|
static const mozilla::Module::CIDEntry kNSSCIDs[] = {
|
||||||
{ &kNS_NSSCOMPONENT_CID, false, nullptr, nsNSSComponentConstructor },
|
{ &kNS_NSSCOMPONENT_CID, false, nullptr, nsNSSComponentConstructor },
|
||||||
@@ -290,6 +288,7 @@ static const mozilla::Module::CIDEntry kNSSCIDs[] = {
|
|||||||
{ &kNS_SECURE_BROWSER_UI_CID, false, nullptr, nsSecureBrowserUIImplConstructor },
|
{ &kNS_SECURE_BROWSER_UI_CID, false, nullptr, nsSecureBrowserUIImplConstructor },
|
||||||
{ &kNS_SITE_SECURITY_SERVICE_CID, false, nullptr, nsSiteSecurityServiceConstructor },
|
{ &kNS_SITE_SECURITY_SERVICE_CID, false, nullptr, nsSiteSecurityServiceConstructor },
|
||||||
{ &kNS_CERT_BLOCKLIST_CID, false, nullptr, CertBlocklistConstructor},
|
{ &kNS_CERT_BLOCKLIST_CID, false, nullptr, CertBlocklistConstructor},
|
||||||
|
{ &kNS_WEAKCRYPTOOVERRIDE_CID, false, nullptr, WeakCryptoOverrideConstructor },
|
||||||
{ nullptr }
|
{ nullptr }
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -325,6 +324,7 @@ static const mozilla::Module::ContractIDEntry kNSSContracts[] = {
|
|||||||
{ NS_SECURE_BROWSER_UI_CONTRACTID, &kNS_SECURE_BROWSER_UI_CID },
|
{ NS_SECURE_BROWSER_UI_CONTRACTID, &kNS_SECURE_BROWSER_UI_CID },
|
||||||
{ NS_SSSERVICE_CONTRACTID, &kNS_SITE_SECURITY_SERVICE_CID },
|
{ NS_SSSERVICE_CONTRACTID, &kNS_SITE_SECURITY_SERVICE_CID },
|
||||||
{ NS_CERTBLOCKLIST_CONTRACTID, &kNS_CERT_BLOCKLIST_CID },
|
{ NS_CERTBLOCKLIST_CONTRACTID, &kNS_CERT_BLOCKLIST_CID },
|
||||||
|
{ NS_WEAKCRYPTOOVERRIDE_CONTRACTID, &kNS_WEAKCRYPTOOVERRIDE_CID },
|
||||||
{ nullptr }
|
{ nullptr }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -31,6 +31,7 @@
|
|||||||
#include "imgIRequest.h"
|
#include "imgIRequest.h"
|
||||||
#include "nsThreadUtils.h"
|
#include "nsThreadUtils.h"
|
||||||
#include "nsNetCID.h"
|
#include "nsNetCID.h"
|
||||||
|
#include "nsNetUtil.h"
|
||||||
#include "nsCRT.h"
|
#include "nsCRT.h"
|
||||||
#include "nsIInterfaceRequestorUtils.h"
|
#include "nsIInterfaceRequestorUtils.h"
|
||||||
#include "nsIProtocolHandler.h"
|
#include "nsIProtocolHandler.h"
|
||||||
|
|||||||
@@ -63,6 +63,7 @@ const SEC_ERROR_POLICY_VALIDATION_FAILED = SEC_ERROR_BASE + 160;
|
|||||||
const SEC_ERROR_OCSP_BAD_SIGNATURE = SEC_ERROR_BASE + 157;
|
const SEC_ERROR_OCSP_BAD_SIGNATURE = SEC_ERROR_BASE + 157;
|
||||||
const SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED = SEC_ERROR_BASE + 176;
|
const SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED = SEC_ERROR_BASE + 176;
|
||||||
|
|
||||||
|
const SSL_ERROR_NO_CYPHER_OVERLAP = SSL_ERROR_BASE + 2;
|
||||||
const SSL_ERROR_BAD_CERT_DOMAIN = SSL_ERROR_BASE + 12;
|
const SSL_ERROR_BAD_CERT_DOMAIN = SSL_ERROR_BASE + 12;
|
||||||
const SSL_ERROR_BAD_CERT_ALERT = SSL_ERROR_BASE + 17;
|
const SSL_ERROR_BAD_CERT_ALERT = SSL_ERROR_BASE + 17;
|
||||||
const SSL_ERROR_WEAK_SERVER_CERT_KEY = SSL_ERROR_BASE + 132;
|
const SSL_ERROR_WEAK_SERVER_CERT_KEY = SSL_ERROR_BASE + 132;
|
||||||
|
|||||||
262
security/manager/ssl/tests/unit/test_weak_crypto.js
Normal file
262
security/manager/ssl/tests/unit/test_weak_crypto.js
Normal file
@@ -0,0 +1,262 @@
|
|||||||
|
/* Any copyright is dedicated to the Public Domain.
|
||||||
|
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
// Tests the weak crypto override
|
||||||
|
|
||||||
|
const TLS_RSA_WITH_RC4_128_MD5 = 0x0004;
|
||||||
|
const TLS_RSA_WITH_RC4_128_SHA = 0x0005;
|
||||||
|
const TLS_ECDHE_ECDSA_WITH_RC4_128_SHA = 0xC007;
|
||||||
|
const TLS_ECDHE_RSA_WITH_RC4_128_SHA = 0xC011;
|
||||||
|
|
||||||
|
// Need profile dir to store the key / cert
|
||||||
|
do_get_profile();
|
||||||
|
// Ensure PSM is initialized
|
||||||
|
Cc["@mozilla.org/psm;1"].getService(Ci.nsISupports);
|
||||||
|
|
||||||
|
const certService = Cc["@mozilla.org/security/local-cert-service;1"]
|
||||||
|
.getService(Ci.nsILocalCertService);
|
||||||
|
const certOverrideService = Cc["@mozilla.org/security/certoverride;1"]
|
||||||
|
.getService(Ci.nsICertOverrideService);
|
||||||
|
const weakCryptoOverride = Cc["@mozilla.org/security/weakcryptooverride;1"]
|
||||||
|
.getService(Ci.nsIWeakCryptoOverride);
|
||||||
|
const socketTransportService =
|
||||||
|
Cc["@mozilla.org/network/socket-transport-service;1"]
|
||||||
|
.getService(Ci.nsISocketTransportService);
|
||||||
|
|
||||||
|
function getCert() {
|
||||||
|
let deferred = Promise.defer();
|
||||||
|
certService.getOrCreateCert("tls-test", {
|
||||||
|
handleCert: function(c, rv) {
|
||||||
|
if (rv) {
|
||||||
|
deferred.reject(rv);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
deferred.resolve(c);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return deferred.promise;
|
||||||
|
}
|
||||||
|
|
||||||
|
function startServer(cert, rc4only) {
|
||||||
|
let tlsServer = Cc["@mozilla.org/network/tls-server-socket;1"]
|
||||||
|
.createInstance(Ci.nsITLSServerSocket);
|
||||||
|
tlsServer.init(-1, true, -1);
|
||||||
|
tlsServer.serverCert = cert;
|
||||||
|
|
||||||
|
let input, output;
|
||||||
|
|
||||||
|
let listener = {
|
||||||
|
onSocketAccepted: function(socket, transport) {
|
||||||
|
do_print("Accept TLS client connection");
|
||||||
|
let connectionInfo = transport.securityInfo
|
||||||
|
.QueryInterface(Ci.nsITLSServerConnectionInfo);
|
||||||
|
connectionInfo.setSecurityObserver(listener);
|
||||||
|
input = transport.openInputStream(0, 0, 0);
|
||||||
|
output = transport.openOutputStream(0, 0, 0);
|
||||||
|
},
|
||||||
|
onHandshakeDone: function(socket, status) {
|
||||||
|
do_print("TLS handshake done");
|
||||||
|
|
||||||
|
equal(status.tlsVersionUsed, Ci.nsITLSClientStatus.TLS_VERSION_1_2,
|
||||||
|
"Using TLS 1.2");
|
||||||
|
let expectedCipher = rc4only ? "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA"
|
||||||
|
: "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256";
|
||||||
|
equal(status.cipherName, expectedCipher,
|
||||||
|
"Using expected cipher");
|
||||||
|
equal(status.keyLength, 128, "Using 128-bit key");
|
||||||
|
equal(status.macLength, rc4only ? 160 : 128, "Using MAC of expected length");
|
||||||
|
|
||||||
|
input.asyncWait({
|
||||||
|
onInputStreamReady: function(input) {
|
||||||
|
NetUtil.asyncCopy(input, output);
|
||||||
|
}
|
||||||
|
}, 0, 0, Services.tm.currentThread);
|
||||||
|
},
|
||||||
|
onStopListening: function() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
tlsServer.setSessionCache(false);
|
||||||
|
tlsServer.setSessionTickets(false);
|
||||||
|
tlsServer.setRequestClientCertificate(Ci.nsITLSServerSocket.REQUEST_NEVER);
|
||||||
|
if (rc4only) {
|
||||||
|
let cipherSuites = [
|
||||||
|
TLS_ECDHE_RSA_WITH_RC4_128_SHA,
|
||||||
|
TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
|
||||||
|
TLS_RSA_WITH_RC4_128_SHA,
|
||||||
|
TLS_RSA_WITH_RC4_128_MD5
|
||||||
|
];
|
||||||
|
tlsServer.setCipherSuites(cipherSuites, cipherSuites.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
tlsServer.asyncListen(listener);
|
||||||
|
|
||||||
|
return tlsServer.port;
|
||||||
|
}
|
||||||
|
|
||||||
|
function storeCertOverride(port, cert) {
|
||||||
|
let overrideBits = Ci.nsICertOverrideService.ERROR_UNTRUSTED |
|
||||||
|
Ci.nsICertOverrideService.ERROR_MISMATCH;
|
||||||
|
certOverrideService.rememberValidityOverride("127.0.0.1", port, cert,
|
||||||
|
overrideBits, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
function startClient(port, expectedResult, options = {}) {
|
||||||
|
let SSL_ERROR_BASE = Ci.nsINSSErrorsService.NSS_SSL_ERROR_BASE;
|
||||||
|
let SSL_ERROR_BAD_CERT_ALERT = SSL_ERROR_BASE + 17;
|
||||||
|
let transport =
|
||||||
|
socketTransportService.createTransport(["ssl"], 1, "127.0.0.1", port, null);
|
||||||
|
if (options.isPrivate) {
|
||||||
|
transport.connectionFlags |= Ci.nsISocketTransport.NO_PERMANENT_STORAGE;
|
||||||
|
}
|
||||||
|
let input;
|
||||||
|
let output;
|
||||||
|
|
||||||
|
let inputDeferred = Promise.defer();
|
||||||
|
let outputDeferred = Promise.defer();
|
||||||
|
|
||||||
|
let handler = {
|
||||||
|
|
||||||
|
onTransportStatus: function(transport, status) {
|
||||||
|
if (status === Ci.nsISocketTransport.STATUS_CONNECTED_TO) {
|
||||||
|
output.asyncWait(handler, 0, 0, Services.tm.currentThread);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
onInputStreamReady: function(input) {
|
||||||
|
let errorCode = Cr.NS_OK;
|
||||||
|
try {
|
||||||
|
let data = NetUtil.readInputStreamToString(input, input.available());
|
||||||
|
equal(data, "HELLO", "Echoed data received");
|
||||||
|
input.close();
|
||||||
|
output.close();
|
||||||
|
} catch (e) {
|
||||||
|
errorCode = e.result;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
equal(errorCode, expectedResult,
|
||||||
|
"Actual and expected connection result should match");
|
||||||
|
inputDeferred.resolve();
|
||||||
|
} catch (e) {
|
||||||
|
inputDeferred.reject(e);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
onOutputStreamReady: function(output) {
|
||||||
|
try {
|
||||||
|
output.write("HELLO", 5);
|
||||||
|
do_print("Output to server written");
|
||||||
|
outputDeferred.resolve();
|
||||||
|
input = transport.openInputStream(0, 0, 0);
|
||||||
|
input.asyncWait(handler, 0, 0, Services.tm.currentThread);
|
||||||
|
} catch (e) {
|
||||||
|
let errorCode = -1 * (e.result & 0xFFFF);
|
||||||
|
if (errorCode == SSL_ERROR_BAD_CERT_ALERT) {
|
||||||
|
do_print("Server doesn't like client cert");
|
||||||
|
}
|
||||||
|
outputDeferred.reject(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
transport.setEventSink(handler, Services.tm.currentThread);
|
||||||
|
output = transport.openOutputStream(0, 0, 0);
|
||||||
|
|
||||||
|
return Promise.all([inputDeferred.promise, outputDeferred.promise]);
|
||||||
|
}
|
||||||
|
|
||||||
|
function run_test() {
|
||||||
|
Services.prefs.setBoolPref("security.tls.unrestricted_rc4_fallback", false);
|
||||||
|
run_next_test();
|
||||||
|
}
|
||||||
|
|
||||||
|
// for sanity check
|
||||||
|
add_task(function*() {
|
||||||
|
let cert = yield getCert();
|
||||||
|
ok(!!cert, "Got self-signed cert");
|
||||||
|
let port = startServer(cert, false);
|
||||||
|
storeCertOverride(port, cert);
|
||||||
|
yield startClient(port, Cr.NS_OK);
|
||||||
|
yield startClient(port, Cr.NS_OK, {isPrivate: true});
|
||||||
|
});
|
||||||
|
|
||||||
|
add_task(function*() {
|
||||||
|
let cert = yield getCert();
|
||||||
|
ok(!!cert, "Got self-signed cert");
|
||||||
|
let port = startServer(cert, true);
|
||||||
|
storeCertOverride(port, cert);
|
||||||
|
yield startClient(port, getXPCOMStatusFromNSS(SSL_ERROR_NO_CYPHER_OVERLAP));
|
||||||
|
yield startClient(port, getXPCOMStatusFromNSS(SSL_ERROR_NO_CYPHER_OVERLAP),
|
||||||
|
{isPrivate: true});
|
||||||
|
|
||||||
|
weakCryptoOverride.addWeakCryptoOverride("127.0.0.1", true);
|
||||||
|
// private browsing should not affect the permanent storage.
|
||||||
|
equal(Services.prefs.getCharPref("security.tls.insecure_fallback_hosts"),
|
||||||
|
"");
|
||||||
|
yield startClient(port, getXPCOMStatusFromNSS(SSL_ERROR_NO_CYPHER_OVERLAP));
|
||||||
|
// The auto-retry on connection reset is implemented in our HTTP layer.
|
||||||
|
// So we will see the crafted NS_ERROR_NET_RESET when we use
|
||||||
|
// nsISocketTransport directly.
|
||||||
|
yield startClient(port, Cr.NS_ERROR_NET_RESET, {isPrivate: true});
|
||||||
|
// retry manually to simulate the HTTP layer
|
||||||
|
yield startClient(port, Cr.NS_OK, {isPrivate: true});
|
||||||
|
|
||||||
|
weakCryptoOverride.removeWeakCryptoOverride("127.0.0.1", port, true);
|
||||||
|
equal(Services.prefs.getCharPref("security.tls.insecure_fallback_hosts"),
|
||||||
|
"");
|
||||||
|
yield startClient(port, getXPCOMStatusFromNSS(SSL_ERROR_NO_CYPHER_OVERLAP));
|
||||||
|
yield startClient(port, getXPCOMStatusFromNSS(SSL_ERROR_NO_CYPHER_OVERLAP),
|
||||||
|
{isPrivate: true});
|
||||||
|
|
||||||
|
weakCryptoOverride.addWeakCryptoOverride("127.0.0.1", false, true);
|
||||||
|
// temporary override should not change the pref.
|
||||||
|
equal(Services.prefs.getCharPref("security.tls.insecure_fallback_hosts"),
|
||||||
|
"");
|
||||||
|
yield startClient(port, Cr.NS_ERROR_NET_RESET);
|
||||||
|
yield startClient(port, Cr.NS_OK);
|
||||||
|
yield startClient(port, getXPCOMStatusFromNSS(SSL_ERROR_NO_CYPHER_OVERLAP),
|
||||||
|
{isPrivate: true});
|
||||||
|
|
||||||
|
weakCryptoOverride.removeWeakCryptoOverride("127.0.0.1", port, false);
|
||||||
|
equal(Services.prefs.getCharPref("security.tls.insecure_fallback_hosts"),
|
||||||
|
"");
|
||||||
|
yield startClient(port, getXPCOMStatusFromNSS(SSL_ERROR_NO_CYPHER_OVERLAP));
|
||||||
|
yield startClient(port, getXPCOMStatusFromNSS(SSL_ERROR_NO_CYPHER_OVERLAP),
|
||||||
|
{isPrivate: true});
|
||||||
|
|
||||||
|
weakCryptoOverride.addWeakCryptoOverride("127.0.0.1", false);
|
||||||
|
// permanent override should change the pref.
|
||||||
|
equal(Services.prefs.getCharPref("security.tls.insecure_fallback_hosts"),
|
||||||
|
"127.0.0.1");
|
||||||
|
yield startClient(port, Cr.NS_ERROR_NET_RESET);
|
||||||
|
yield startClient(port, Cr.NS_OK);
|
||||||
|
yield startClient(port, getXPCOMStatusFromNSS(SSL_ERROR_NO_CYPHER_OVERLAP),
|
||||||
|
{isPrivate: true});
|
||||||
|
|
||||||
|
weakCryptoOverride.removeWeakCryptoOverride("127.0.0.1", port, false);
|
||||||
|
equal(Services.prefs.getCharPref("security.tls.insecure_fallback_hosts"),
|
||||||
|
"");
|
||||||
|
yield startClient(port, getXPCOMStatusFromNSS(SSL_ERROR_NO_CYPHER_OVERLAP));
|
||||||
|
yield startClient(port, getXPCOMStatusFromNSS(SSL_ERROR_NO_CYPHER_OVERLAP),
|
||||||
|
{isPrivate: true});
|
||||||
|
|
||||||
|
// add a host to the pref to prepare the next test
|
||||||
|
weakCryptoOverride.addWeakCryptoOverride("127.0.0.1", false);
|
||||||
|
yield startClient(port, Cr.NS_ERROR_NET_RESET);
|
||||||
|
yield startClient(port, Cr.NS_OK);
|
||||||
|
equal(Services.prefs.getCharPref("security.tls.insecure_fallback_hosts"),
|
||||||
|
"127.0.0.1");
|
||||||
|
});
|
||||||
|
|
||||||
|
add_task(function*() {
|
||||||
|
let cert = yield getCert();
|
||||||
|
ok(!!cert, "Got self-signed cert");
|
||||||
|
let port = startServer(cert, false);
|
||||||
|
storeCertOverride(port, cert);
|
||||||
|
yield startClient(port, Cr.NS_OK);
|
||||||
|
// Successful strong cipher will remove the host from the pref.
|
||||||
|
equal(Services.prefs.getCharPref("security.tls.insecure_fallback_hosts"),
|
||||||
|
"");
|
||||||
|
});
|
||||||
@@ -149,3 +149,6 @@ run-sequentially = hardcoded ports
|
|||||||
run-sequentially = hardcoded ports
|
run-sequentially = hardcoded ports
|
||||||
[test_certviewer_invalid_oids.js]
|
[test_certviewer_invalid_oids.js]
|
||||||
skip-if = toolkit == 'android' || buildapp == 'b2g'
|
skip-if = toolkit == 'android' || buildapp == 'b2g'
|
||||||
|
|
||||||
|
[test_weak_crypto.js]
|
||||||
|
skip-if = toolkit == 'android'
|
||||||
|
|||||||
Reference in New Issue
Block a user