Bug 1168635 - Add an XPCOM interface to allow RC4. r=keeler

This commit is contained in:
Masatoshi Kimura
2015-10-15 05:48:27 +09:00
parent 3d596d21af
commit 2bc320d8ca
12 changed files with 556 additions and 42 deletions

View 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;
}

View 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

View File

@@ -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.

View 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);
};

View File

@@ -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);

View File

@@ -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)

View File

@@ -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;

View File

@@ -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 }
}; };

View File

@@ -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"

View File

@@ -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;

View 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"),
"");
});

View File

@@ -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'