mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-09 11:25:00 +00:00
Bug 1388925 - Add an opaque flags to have a fine-grained control over TLS configurations. r=mcmanus, r=keeler
This flags is added in the http channel interface by which developers can control the TLS connections from JavaScript code (e.g. Add-ons). Basically, all the changes accounted for plumbing this TLS flags from JavaScript level to C++ code responsible for calling NSS module. We also added a unit test to make sure that separate connections are created if we use different tlsFlags. Basically we used a concrete set of flag values that covers the edge cases and check the hashkey generated in the connection info. --HG-- rename : netwerk/test/unit/test_separate_connections.js => netwerk/test/unit/test_tls_flags_separate_connections.js
This commit is contained in:
parent
9b038447f4
commit
404facfbbc
@ -237,6 +237,13 @@ interface nsISocketTransport : nsITransport
|
||||
*/
|
||||
const unsigned long BE_CONSERVATIVE = (1 << 7);
|
||||
|
||||
/**
|
||||
* An opaque flags for non-standard behavior of the TLS system.
|
||||
* It is unlikely this will need to be set outside of telemetry studies
|
||||
* relating to the TLS implementation.
|
||||
*/
|
||||
attribute unsigned long tlsFlags;
|
||||
|
||||
/**
|
||||
* Socket QoS/ToS markings. Valid values are IPTOS_DSCP_AFxx or
|
||||
* IPTOS_CLASS_CSx (or IPTOS_DSCP_EF, but currently no supported
|
||||
|
@ -775,6 +775,7 @@ nsSocketTransport::nsSocketTransport()
|
||||
, mProxyTransparentResolvesHost(false)
|
||||
, mHttpsProxy(false)
|
||||
, mConnectionFlags(0)
|
||||
, mTlsFlags(0)
|
||||
, mReuseAddrPort(false)
|
||||
, mState(STATE_CLOSED)
|
||||
, mAttached(false)
|
||||
@ -1225,7 +1226,7 @@ nsSocketTransport::BuildSocket(PRFileDesc *&fd, bool &proxyTransparent, bool &us
|
||||
mHttpsProxy ? mProxyHost.get() : host,
|
||||
mHttpsProxy ? mProxyPort : port,
|
||||
proxyInfo, mOriginAttributes,
|
||||
controlFlags, &fd,
|
||||
controlFlags, mTlsFlags, &fd,
|
||||
getter_AddRefs(secinfo));
|
||||
|
||||
if (NS_SUCCEEDED(rv) && !fd) {
|
||||
@ -1239,7 +1240,7 @@ nsSocketTransport::BuildSocket(PRFileDesc *&fd, bool &proxyTransparent, bool &us
|
||||
// to the stack (such as pushing an io layer)
|
||||
rv = provider->AddToSocket(mNetAddr.raw.family,
|
||||
host, port, proxyInfo,
|
||||
mOriginAttributes, controlFlags, fd,
|
||||
mOriginAttributes, controlFlags, mTlsFlags, fd,
|
||||
getter_AddRefs(secinfo));
|
||||
}
|
||||
|
||||
@ -2996,6 +2997,20 @@ nsSocketTransport::SetConnectionFlags(uint32_t value)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSocketTransport::GetTlsFlags(uint32_t *value)
|
||||
{
|
||||
*value = mTlsFlags;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSocketTransport::SetTlsFlags(uint32_t value)
|
||||
{
|
||||
mTlsFlags = value;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsSocketTransport::OnKeepaliveEnabledPrefChange(bool aEnabled)
|
||||
{
|
||||
|
@ -308,6 +308,7 @@ private:
|
||||
bool mProxyTransparentResolvesHost;
|
||||
bool mHttpsProxy;
|
||||
uint32_t mConnectionFlags;
|
||||
uint32_t mTlsFlags;
|
||||
bool mReuseAddrPort;
|
||||
|
||||
// The origin attributes are used to create sockets. The first party domain
|
||||
|
@ -128,6 +128,7 @@ struct HttpChannelOpenArgs
|
||||
bool allowSpdy;
|
||||
bool allowAltSvc;
|
||||
bool beConservative;
|
||||
uint32_t tlsFlags;
|
||||
OptionalLoadInfoArgs loadInfo;
|
||||
OptionalHttpResponseHead synthesizedResponseHead;
|
||||
nsCString synthesizedSecurityInfoSerialization;
|
||||
|
@ -183,6 +183,7 @@ HttpBaseChannel::HttpBaseChannel()
|
||||
, mResponseCouldBeSynthesized(false)
|
||||
, mBlockAuthPrompt(false)
|
||||
, mAllowStaleCacheContent(false)
|
||||
, mTlsFlags(0)
|
||||
, mSuspendCount(0)
|
||||
, mInitialRwin(0)
|
||||
, mProxyResolveFlags(0)
|
||||
@ -2613,6 +2614,22 @@ HttpBaseChannel::SetBeConservative(bool aBeConservative)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
HttpBaseChannel::GetTlsFlags(uint32_t *aTlsFlags)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aTlsFlags);
|
||||
|
||||
*aTlsFlags = mTlsFlags;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
HttpBaseChannel::SetTlsFlags(uint32_t aTlsFlags)
|
||||
{
|
||||
mTlsFlags = aTlsFlags;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
HttpBaseChannel::GetApiRedirectToURI(nsIURI ** aResult)
|
||||
{
|
||||
@ -3420,6 +3437,8 @@ HttpBaseChannel::SetupReplacementChannel(nsIURI *newURI,
|
||||
MOZ_ASSERT(NS_SUCCEEDED(rv));
|
||||
rv = httpInternal->SetBeConservative(mBeConservative);
|
||||
MOZ_ASSERT(NS_SUCCEEDED(rv));
|
||||
rv = httpInternal->SetTlsFlags(mTlsFlags);
|
||||
MOZ_ASSERT(NS_SUCCEEDED(rv));
|
||||
|
||||
RefPtr<nsHttpChannel> realChannel;
|
||||
CallQueryInterface(newChannel, realChannel.StartAssignment());
|
||||
|
@ -235,6 +235,8 @@ public:
|
||||
NS_IMETHOD SetAllowAltSvc(bool aAllowAltSvc) override;
|
||||
NS_IMETHOD GetBeConservative(bool *aBeConservative) override;
|
||||
NS_IMETHOD SetBeConservative(bool aBeConservative) override;
|
||||
NS_IMETHOD GetTlsFlags(uint32_t *aTlsFlags) override;
|
||||
NS_IMETHOD SetTlsFlags(uint32_t aTlsFlags) override;
|
||||
NS_IMETHOD GetApiRedirectToURI(nsIURI * *aApiRedirectToURI) override;
|
||||
virtual MOZ_MUST_USE nsresult AddSecurityMessage(const nsAString &aMessageTag, const nsAString &aMessageCategory);
|
||||
NS_IMETHOD TakeAllSecurityMessages(nsCOMArray<nsISecurityConsoleMessage> &aMessages) override;
|
||||
@ -541,6 +543,11 @@ protected:
|
||||
// Used to enforce that flag's behavior but not expose it externally.
|
||||
uint32_t mAllowStaleCacheContent : 1;
|
||||
|
||||
// An opaque flags for non-standard behavior of the TLS system.
|
||||
// It is unlikely this will need to be set outside of telemetry studies
|
||||
// relating to the TLS implementation.
|
||||
uint32_t mTlsFlags;
|
||||
|
||||
// Current suspension depth for this channel object
|
||||
uint32_t mSuspendCount;
|
||||
|
||||
|
@ -2563,6 +2563,7 @@ HttpChannelChild::ContinueAsyncOpen()
|
||||
openArgs.allowSpdy() = mAllowSpdy;
|
||||
openArgs.allowAltSvc() = mAllowAltSvc;
|
||||
openArgs.beConservative() = mBeConservative;
|
||||
openArgs.tlsFlags() = mTlsFlags;
|
||||
openArgs.initialRwin() = mInitialRwin;
|
||||
|
||||
uint32_t cacheKey = 0;
|
||||
|
@ -136,7 +136,7 @@ HttpChannelParent::Init(const HttpChannelCreationArgs& aArgs)
|
||||
a.thirdPartyFlags(), a.resumeAt(), a.startPos(),
|
||||
a.entityID(), a.chooseApplicationCache(),
|
||||
a.appCacheClientID(), a.allowSpdy(), a.allowAltSvc(), a.beConservative(),
|
||||
a.loadInfo(), a.synthesizedResponseHead(),
|
||||
a.tlsFlags(), a.loadInfo(), a.synthesizedResponseHead(),
|
||||
a.synthesizedSecurityInfoSerialization(),
|
||||
a.cacheKey(), a.requestContextID(), a.preflightArgs(),
|
||||
a.initialRwin(), a.blockAuthPrompt(),
|
||||
@ -457,6 +457,7 @@ HttpChannelParent::DoAsyncOpen( const URIParams& aURI,
|
||||
const bool& allowSpdy,
|
||||
const bool& allowAltSvc,
|
||||
const bool& beConservative,
|
||||
const uint32_t& tlsFlags,
|
||||
const OptionalLoadInfoArgs& aLoadInfoArgs,
|
||||
const OptionalHttpResponseHead& aSynthesizedResponseHead,
|
||||
const nsCString& aSecurityInfoSerialization,
|
||||
@ -683,6 +684,7 @@ HttpChannelParent::DoAsyncOpen( const URIParams& aURI,
|
||||
httpChannel->SetAllowSpdy(allowSpdy);
|
||||
httpChannel->SetAllowAltSvc(allowAltSvc);
|
||||
httpChannel->SetBeConservative(beConservative);
|
||||
httpChannel->SetTlsFlags(tlsFlags);
|
||||
httpChannel->SetInitialRwin(aInitialRwin);
|
||||
httpChannel->SetBlockAuthPrompt(aBlockAuthPrompt);
|
||||
|
||||
|
@ -151,6 +151,7 @@ protected:
|
||||
const bool& allowSpdy,
|
||||
const bool& allowAltSvc,
|
||||
const bool& beConservative,
|
||||
const uint32_t& tlsFlags,
|
||||
const OptionalLoadInfoArgs& aLoadInfoArgs,
|
||||
const OptionalHttpResponseHead& aSynthesizedResponseHead,
|
||||
const nsCString& aSecurityInfoSerialization,
|
||||
|
@ -80,7 +80,7 @@ TLSFilterTransaction::TLSFilterTransaction(nsAHttpTransaction *aWrapped,
|
||||
if (provider && mFD) {
|
||||
mFD->secret = reinterpret_cast<PRFilePrivate *>(this);
|
||||
provider->AddToSocket(PR_AF_INET, aTLSHost, aTLSPort, nullptr,
|
||||
OriginAttributes(), 0, mFD,
|
||||
OriginAttributes(), 0, 0, mFD,
|
||||
getter_AddRefs(mSecInfo));
|
||||
}
|
||||
|
||||
@ -1547,6 +1547,8 @@ FWD_TS_ADDREF(GetSecurityCallbacks, nsIInterfaceRequestor);
|
||||
FWD_TS_PTR(IsAlive, bool);
|
||||
FWD_TS_PTR(GetConnectionFlags, uint32_t);
|
||||
FWD_TS(SetConnectionFlags, uint32_t);
|
||||
FWD_TS_PTR(GetTlsFlags, uint32_t);
|
||||
FWD_TS(SetTlsFlags, uint32_t);
|
||||
FWD_TS_PTR(GetRecvBufferSize, uint32_t);
|
||||
FWD_TS(SetRecvBufferSize, uint32_t);
|
||||
|
||||
|
@ -497,6 +497,7 @@ nsHttpChannel::Connect()
|
||||
mConnectionInfo->SetPrivate(mPrivateBrowsing);
|
||||
mConnectionInfo->SetNoSpdy(mCaps & NS_HTTP_DISALLOW_SPDY);
|
||||
mConnectionInfo->SetBeConservative((mCaps & NS_HTTP_BE_CONSERVATIVE) || mBeConservative);
|
||||
mConnectionInfo->SetTlsFlags(mTlsFlags);
|
||||
|
||||
// Consider opening a TCP connection right away.
|
||||
SpeculativeConnect();
|
||||
|
@ -92,6 +92,7 @@ nsHttpConnectionInfo::Init(const nsACString &host, int32_t port,
|
||||
mUsingConnect = false;
|
||||
mNPNToken = npnToken;
|
||||
mOriginAttributes = originAttributes;
|
||||
mTlsFlags = 0x0;
|
||||
|
||||
mUsingHttpsProxy = (proxyInfo && proxyInfo->IsHTTPS());
|
||||
mUsingHttpProxy = mUsingHttpsProxy || (proxyInfo && proxyInfo->IsHTTP());
|
||||
@ -147,7 +148,8 @@ void nsHttpConnectionInfo::BuildHashKey()
|
||||
// byte 5 is X/. X is for disallow_spdy flag
|
||||
// byte 6 is C/. C is for be Conservative
|
||||
|
||||
mHashKey.AssignLiteral(".......");
|
||||
mHashKey.AssignLiteral(".......[tlsflags0x00000000]");
|
||||
|
||||
mHashKey.Append(keyHost);
|
||||
if (!mNetworkInterfaceId.IsEmpty()) {
|
||||
mHashKey.Append('(');
|
||||
@ -259,6 +261,7 @@ nsHttpConnectionInfo::Clone() const
|
||||
clone->SetInsecureScheme(GetInsecureScheme());
|
||||
clone->SetNoSpdy(GetNoSpdy());
|
||||
clone->SetBeConservative(GetBeConservative());
|
||||
clone->SetTlsFlags(GetTlsFlags());
|
||||
MOZ_ASSERT(clone->Equals(this));
|
||||
|
||||
return clone;
|
||||
@ -282,6 +285,7 @@ nsHttpConnectionInfo::CloneAsDirectRoute(nsHttpConnectionInfo **outCI)
|
||||
clone->SetInsecureScheme(GetInsecureScheme());
|
||||
clone->SetNoSpdy(GetNoSpdy());
|
||||
clone->SetBeConservative(GetBeConservative());
|
||||
clone->SetTlsFlags(GetTlsFlags());
|
||||
if (!mNetworkInterfaceId.IsEmpty()) {
|
||||
clone->SetNetworkInterfaceId(mNetworkInterfaceId);
|
||||
}
|
||||
@ -310,6 +314,13 @@ nsHttpConnectionInfo::CreateWildCard(nsHttpConnectionInfo **outParam)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsHttpConnectionInfo::SetTlsFlags(uint32_t aTlsFlags) {
|
||||
mTlsFlags = aTlsFlags;
|
||||
|
||||
mHashKey.Replace(18, 8, nsPrintfCString("%08x", mTlsFlags));
|
||||
}
|
||||
|
||||
bool
|
||||
nsHttpConnectionInfo::UsingProxy()
|
||||
{
|
||||
|
@ -122,6 +122,9 @@ public:
|
||||
{ mHashKey.SetCharAt(aBeConservative ? 'C' : '.', 6); }
|
||||
bool GetBeConservative() const { return mHashKey.CharAt(6) == 'C'; }
|
||||
|
||||
void SetTlsFlags(uint32_t aTlsFlags);
|
||||
uint32_t GetTlsFlags() const { return mTlsFlags; }
|
||||
|
||||
const nsCString &GetNetworkInterfaceId() const { return mNetworkInterfaceId; }
|
||||
|
||||
const nsCString &GetNPNToken() { return mNPNToken; }
|
||||
@ -176,6 +179,8 @@ private:
|
||||
nsCString mNPNToken;
|
||||
OriginAttributes mOriginAttributes;
|
||||
|
||||
uint32_t mTlsFlags;
|
||||
|
||||
// for RefPtr
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(nsHttpConnectionInfo)
|
||||
};
|
||||
|
@ -3853,6 +3853,7 @@ nsHalfOpenSocket::SetupStreams(nsISocketTransport **transport,
|
||||
}
|
||||
|
||||
socketTransport->SetConnectionFlags(tmpFlags);
|
||||
socketTransport->SetTlsFlags(ci->GetTlsFlags());
|
||||
|
||||
const OriginAttributes& originAttributes = mEnt->mConnInfo->GetOriginAttributes();
|
||||
if (originAttributes != OriginAttributes()) {
|
||||
|
@ -216,6 +216,13 @@ interface nsIHttpChannelInternal : nsISupports
|
||||
*/
|
||||
[must_use] attribute boolean beConservative;
|
||||
|
||||
/**
|
||||
* An opaque flags for non-standard behavior of the TLS system.
|
||||
* It is unlikely this will need to be set outside of telemetry studies
|
||||
* relating to the TLS implementation.
|
||||
*/
|
||||
[must_use] attribute unsigned long tlsFlags;
|
||||
|
||||
[must_use] readonly attribute PRTime lastModifiedTime;
|
||||
|
||||
/**
|
||||
|
@ -102,6 +102,11 @@ interface nsISSLSocketControl : nsISupports {
|
||||
*/
|
||||
readonly attribute uint32_t providerFlags;
|
||||
|
||||
/*
|
||||
* The original TLS flags from the socket provider.
|
||||
*/
|
||||
readonly attribute uint32_t providerTlsFlags;
|
||||
|
||||
/* These values are defined by TLS. */
|
||||
const short SSL_VERSION_3 = 0x0300;
|
||||
const short TLS_VERSION_1 = 0x0301;
|
||||
|
@ -35,6 +35,10 @@ interface nsISocketProvider : nsISupports
|
||||
* The proxy port for this connection.
|
||||
* @param aFlags
|
||||
* Control flags that govern this connection (see below.)
|
||||
* @param aTlsFlags
|
||||
* An opaque flags for non-standard behavior of the TLS system.
|
||||
* It is unlikely this will need to be set outside of telemetry
|
||||
* studies relating to the TLS implementation.
|
||||
* @param aFileDesc
|
||||
* The resulting PRFileDesc.
|
||||
* @param aSecurityInfo
|
||||
@ -48,6 +52,7 @@ interface nsISocketProvider : nsISupports
|
||||
in nsIProxyInfo aProxy,
|
||||
in const_OriginAttributesRef aOriginAttributes,
|
||||
in unsigned long aFlags,
|
||||
in unsigned long aTlsFlags,
|
||||
out PRFileDescStar aFileDesc,
|
||||
out nsISupports aSecurityInfo);
|
||||
|
||||
@ -68,6 +73,7 @@ interface nsISocketProvider : nsISupports
|
||||
in nsIProxyInfo aProxy,
|
||||
in const_OriginAttributesRef aOriginAttributes,
|
||||
in unsigned long aFlags,
|
||||
in unsigned long aTlsFlags,
|
||||
in PRFileDescStar aFileDesc,
|
||||
out nsISupports aSecurityInfo);
|
||||
|
||||
|
@ -78,7 +78,8 @@ public:
|
||||
int32_t family,
|
||||
nsIProxyInfo *proxy,
|
||||
const char *destinationHost,
|
||||
uint32_t flags);
|
||||
uint32_t flags,
|
||||
uint32_t tlsFlags);
|
||||
|
||||
void SetConnectTimeout(PRIntervalTime to);
|
||||
PRStatus DoHandshake(PRFileDesc *fd, int16_t oflags = -1);
|
||||
@ -216,6 +217,7 @@ private:
|
||||
int32_t mVersion; // SOCKS version 4 or 5
|
||||
int32_t mDestinationFamily;
|
||||
uint32_t mFlags;
|
||||
uint32_t mTlsFlags;
|
||||
NetAddr mInternalProxyAddr;
|
||||
NetAddr mExternalProxyAddr;
|
||||
NetAddr mDestinationAddr;
|
||||
@ -232,6 +234,7 @@ nsSOCKSSocketInfo::nsSOCKSSocketInfo()
|
||||
, mVersion(-1)
|
||||
, mDestinationFamily(AF_INET)
|
||||
, mFlags(0)
|
||||
, mTlsFlags(0)
|
||||
, mTimeout(PR_INTERVAL_NO_TIMEOUT)
|
||||
{
|
||||
mData = new uint8_t[BUFFER_SIZE];
|
||||
@ -359,13 +362,14 @@ private:
|
||||
|
||||
|
||||
void
|
||||
nsSOCKSSocketInfo::Init(int32_t version, int32_t family, nsIProxyInfo *proxy, const char *host, uint32_t flags)
|
||||
nsSOCKSSocketInfo::Init(int32_t version, int32_t family, nsIProxyInfo *proxy, const char *host, uint32_t flags, uint32_t tlsFlags)
|
||||
{
|
||||
mVersion = version;
|
||||
mDestinationFamily = family;
|
||||
mProxy = proxy;
|
||||
mDestinationHost = host;
|
||||
mFlags = flags;
|
||||
mTlsFlags = tlsFlags;
|
||||
mProxy->GetUsername(mProxyUsername); // cache
|
||||
}
|
||||
|
||||
@ -1518,6 +1522,7 @@ nsSOCKSIOLayerAddToSocket(int32_t family,
|
||||
nsIProxyInfo *proxy,
|
||||
int32_t socksVersion,
|
||||
uint32_t flags,
|
||||
uint32_t tlsFlags,
|
||||
PRFileDesc *fd,
|
||||
nsISupports** info)
|
||||
{
|
||||
@ -1577,7 +1582,7 @@ nsSOCKSIOLayerAddToSocket(int32_t family,
|
||||
}
|
||||
|
||||
NS_ADDREF(infoObject);
|
||||
infoObject->Init(socksVersion, family, proxy, host, flags);
|
||||
infoObject->Init(socksVersion, family, proxy, host, flags, tlsFlags);
|
||||
layer->secret = (PRFilePrivate*) infoObject;
|
||||
|
||||
PRDescIdentity fdIdentity = PR_GetLayersIdentity(fd);
|
||||
|
@ -17,6 +17,7 @@ nsresult nsSOCKSIOLayerAddToSocket(int32_t family,
|
||||
nsIProxyInfo *proxyInfo,
|
||||
int32_t socksVersion,
|
||||
uint32_t flags,
|
||||
uint32_t tlsFlags,
|
||||
PRFileDesc *fd,
|
||||
nsISupports **info);
|
||||
|
||||
|
@ -50,6 +50,7 @@ nsSOCKSSocketProvider::NewSocket(int32_t family,
|
||||
nsIProxyInfo *proxy,
|
||||
const OriginAttributes &originAttributes,
|
||||
uint32_t flags,
|
||||
uint32_t tlsFlags,
|
||||
PRFileDesc **result,
|
||||
nsISupports **socksInfo)
|
||||
{
|
||||
@ -75,6 +76,7 @@ nsSOCKSSocketProvider::NewSocket(int32_t family,
|
||||
proxy,
|
||||
mVersion,
|
||||
flags,
|
||||
tlsFlags,
|
||||
sock,
|
||||
socksInfo);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
@ -92,6 +94,7 @@ nsSOCKSSocketProvider::AddToSocket(int32_t family,
|
||||
nsIProxyInfo *proxy,
|
||||
const OriginAttributes &originAttributes,
|
||||
uint32_t flags,
|
||||
uint32_t tlsFlags,
|
||||
PRFileDesc *sock,
|
||||
nsISupports **socksInfo)
|
||||
{
|
||||
@ -101,6 +104,7 @@ nsSOCKSSocketProvider::AddToSocket(int32_t family,
|
||||
proxy,
|
||||
mVersion,
|
||||
flags,
|
||||
tlsFlags,
|
||||
sock,
|
||||
socksInfo);
|
||||
|
||||
|
@ -21,6 +21,7 @@ nsUDPSocketProvider::NewSocket(int32_t aFamily,
|
||||
nsIProxyInfo *aProxy,
|
||||
const OriginAttributes &originAttributes,
|
||||
uint32_t aFlags,
|
||||
uint32_t aTlsFlags,
|
||||
PRFileDesc * *aFileDesc,
|
||||
nsISupports **aSecurityInfo)
|
||||
{
|
||||
@ -41,6 +42,7 @@ nsUDPSocketProvider::AddToSocket(int32_t aFamily,
|
||||
nsIProxyInfo *aProxy,
|
||||
const OriginAttributes &originAttributes,
|
||||
uint32_t aFlags,
|
||||
uint32_t aTlsFlags,
|
||||
struct PRFileDesc * aFileDesc,
|
||||
nsISupports **aSecurityInfo)
|
||||
{
|
||||
|
119
netwerk/test/unit/test_tls_flags_separate_connections.js
Normal file
119
netwerk/test/unit/test_tls_flags_separate_connections.js
Normal file
@ -0,0 +1,119 @@
|
||||
Cu.import("resource://testing-common/httpd.js");
|
||||
Cu.import("resource://gre/modules/NetUtil.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "URL", function() {
|
||||
return "http://localhost:" + httpserv.identity.primaryPort;
|
||||
});
|
||||
|
||||
// This unit test ensures connections with different tlsFlags have their own
|
||||
// connection pool. We verify this behavior by opening channels with different
|
||||
// tlsFlags, and their connection info's hash keys should be different.
|
||||
|
||||
// In the first round of this test, we record the hash key for each connection.
|
||||
// In the second round, we check if each connection's hash key is consistent
|
||||
// and different from other connection's hash key.
|
||||
|
||||
let httpserv = null;
|
||||
let gSecondRoundStarted = false;
|
||||
|
||||
let randomFlagValues = [
|
||||
0x00000000,
|
||||
|
||||
0xFFFFFFFF,
|
||||
|
||||
0x12345678,
|
||||
0x12345678,
|
||||
|
||||
0x11111111,
|
||||
0x22222222,
|
||||
|
||||
0xAAAAAAAA,
|
||||
0x77777777,
|
||||
|
||||
0xBBBBBBBB,
|
||||
0xCCCCCCCC
|
||||
];
|
||||
|
||||
function handler(metadata, response) {
|
||||
response.setHeader("Content-Type", "text/plain", false);
|
||||
response.setHeader("Cache-Control", "no-cache", false);
|
||||
response.setStatusLine(metadata.httpVersion, 200, "OK");
|
||||
let body = "0123456789";
|
||||
response.bodyOutputStream.write(body, body.length);
|
||||
}
|
||||
|
||||
function makeChan(url, tlsFlags) {
|
||||
let chan = NetUtil.newChannel({ uri: url, loadUsingSystemPrincipal: true });
|
||||
chan.QueryInterface(Ci.nsIHttpChannelInternal);
|
||||
chan.tlsFlags = tlsFlags;
|
||||
|
||||
return chan;
|
||||
}
|
||||
|
||||
let previousHashKeys = {};
|
||||
|
||||
function Listener(tlsFlags) {
|
||||
this.tlsFlags = tlsFlags;
|
||||
}
|
||||
|
||||
let gTestsRun = 0;
|
||||
Listener.prototype = {
|
||||
onStartRequest: function(request, context) {
|
||||
request.QueryInterface(Ci.nsIHttpChannel)
|
||||
.QueryInterface(Ci.nsIHttpChannelInternal);
|
||||
|
||||
do_check_eq(request.tlsFlags, this.tlsFlags);
|
||||
|
||||
let hashKey = request.connectionInfoHashKey;
|
||||
if (gSecondRoundStarted) {
|
||||
// Compare the hash keys with the previous set ones.
|
||||
// Hash keys should match if and only if their tlsFlags are the same.
|
||||
for (let tlsFlags of randomFlagValues) {
|
||||
if (tlsFlags == this.tlsFlags) {
|
||||
do_check_eq(hashKey, previousHashKeys[tlsFlags]);
|
||||
} else {
|
||||
do_check_neq(hashKey, previousHashKeys[tlsFlags]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Set the hash keys in the first round.
|
||||
previousHashKeys[this.tlsFlags] = hashKey;
|
||||
}
|
||||
},
|
||||
onDataAvailable: function(request, ctx, stream, off, cnt) {
|
||||
read_stream(stream, cnt);
|
||||
},
|
||||
onStopRequest: function() {
|
||||
gTestsRun++;
|
||||
if (gTestsRun == randomFlagValues.length) {
|
||||
gTestsRun = 0;
|
||||
if (gSecondRoundStarted) {
|
||||
// The second round finishes.
|
||||
httpserv.stop(do_test_finished);
|
||||
} else {
|
||||
// The first round finishes. Do the second round.
|
||||
gSecondRoundStarted = true;
|
||||
doTest();
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
function doTest() {
|
||||
for (let tlsFlags of randomFlagValues) {
|
||||
let chan = makeChan(URL, tlsFlags);
|
||||
let listener = new Listener(tlsFlags);
|
||||
chan.asyncOpen2(listener);
|
||||
}
|
||||
}
|
||||
|
||||
function run_test() {
|
||||
do_test_pending();
|
||||
httpserv = new HttpServer();
|
||||
httpserv.registerPathHandler("/", handler);
|
||||
httpserv.start(-1);
|
||||
|
||||
doTest();
|
||||
}
|
||||
|
@ -396,3 +396,4 @@ skip-if = os == "android"
|
||||
[test_bug1312782_http1.js]
|
||||
[test_bug1355539_http1.js]
|
||||
[test_bug1378385_http1.js]
|
||||
[test_tls_flags_separate_connections.js]
|
||||
|
@ -75,7 +75,8 @@ getSiteKey(const nsACString& hostName, uint16_t port,
|
||||
|
||||
extern LazyLogModule gPIPNSSLog;
|
||||
|
||||
nsNSSSocketInfo::nsNSSSocketInfo(SharedSSLState& aState, uint32_t providerFlags)
|
||||
nsNSSSocketInfo::nsNSSSocketInfo(SharedSSLState& aState, uint32_t providerFlags,
|
||||
uint32_t providerTlsFlags)
|
||||
: mFd(nullptr),
|
||||
mCertVerificationState(before_cert_verification),
|
||||
mSharedState(aState),
|
||||
@ -99,6 +100,7 @@ nsNSSSocketInfo::nsNSSSocketInfo(SharedSSLState& aState, uint32_t providerFlags)
|
||||
mMACAlgorithmUsed(nsISSLSocketControl::SSL_MAC_UNKNOWN),
|
||||
mBypassAuthentication(false),
|
||||
mProviderFlags(providerFlags),
|
||||
mProviderTlsFlags(providerTlsFlags),
|
||||
mSocketCreationTimestamp(TimeStamp::Now()),
|
||||
mPlaintextBytesRead(0),
|
||||
mClientCert(nullptr)
|
||||
@ -122,6 +124,13 @@ nsNSSSocketInfo::GetProviderFlags(uint32_t* aProviderFlags)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNSSSocketInfo::GetProviderTlsFlags(uint32_t* aProviderTlsFlags)
|
||||
{
|
||||
*aProviderTlsFlags = mProviderTlsFlags;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsNSSSocketInfo::GetKEAUsed(int16_t* aKea)
|
||||
{
|
||||
@ -1813,7 +1822,8 @@ nsSSLIOLayerNewSocket(int32_t family,
|
||||
PRFileDesc** fd,
|
||||
nsISupports** info,
|
||||
bool forSTARTTLS,
|
||||
uint32_t flags)
|
||||
uint32_t flags,
|
||||
uint32_t tlsFlags)
|
||||
{
|
||||
|
||||
PRFileDesc* sock = PR_OpenTCPSocket(family);
|
||||
@ -1821,7 +1831,7 @@ nsSSLIOLayerNewSocket(int32_t family,
|
||||
|
||||
nsresult rv = nsSSLIOLayerAddToSocket(family, host, port, proxy,
|
||||
originAttributes, sock, info,
|
||||
forSTARTTLS, flags);
|
||||
forSTARTTLS, flags, tlsFlags);
|
||||
if (NS_FAILED(rv)) {
|
||||
PR_Close(sock);
|
||||
return rv;
|
||||
@ -2425,6 +2435,8 @@ nsSSLIOLayerSetOptions(PRFileDesc* fd, bool forSTARTTLS,
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// Use infoObject->GetProviderTlsFlags() to get the TLS flags
|
||||
|
||||
if ((infoObject->GetProviderFlags() & nsISocketProvider::BE_CONSERVATIVE) &&
|
||||
(range.max > SSL_LIBRARY_VERSION_TLS_1_2)) {
|
||||
MOZ_LOG(gPIPNSSLog, LogLevel::Debug,
|
||||
@ -2522,6 +2534,9 @@ nsSSLIOLayerSetOptions(PRFileDesc* fd, bool forSTARTTLS,
|
||||
if (flags & nsISocketProvider::BE_CONSERVATIVE) {
|
||||
peerId.AppendLiteral("beConservative:");
|
||||
}
|
||||
|
||||
peerId.AppendPrintf("tlsflags0x%08x:", infoObject->GetProviderTlsFlags());
|
||||
|
||||
peerId.Append(host);
|
||||
peerId.Append(':');
|
||||
peerId.AppendInt(port);
|
||||
@ -2544,7 +2559,8 @@ nsSSLIOLayerAddToSocket(int32_t family,
|
||||
PRFileDesc* fd,
|
||||
nsISupports** info,
|
||||
bool forSTARTTLS,
|
||||
uint32_t providerFlags)
|
||||
uint32_t providerFlags,
|
||||
uint32_t providerTlsFlags)
|
||||
{
|
||||
nsNSSShutDownPreventionLock locker;
|
||||
PRFileDesc* layer = nullptr;
|
||||
@ -2554,7 +2570,7 @@ nsSSLIOLayerAddToSocket(int32_t family,
|
||||
|
||||
SharedSSLState* sharedState =
|
||||
providerFlags & nsISocketProvider::NO_PERMANENT_STORAGE ? PrivateSSLState() : PublicSSLState();
|
||||
nsNSSSocketInfo* infoObject = new nsNSSSocketInfo(*sharedState, providerFlags);
|
||||
nsNSSSocketInfo* infoObject = new nsNSSSocketInfo(*sharedState, providerFlags, providerTlsFlags);
|
||||
if (!infoObject) return NS_ERROR_FAILURE;
|
||||
|
||||
NS_ADDREF(infoObject);
|
||||
|
@ -35,7 +35,8 @@ class nsNSSSocketInfo final : public mozilla::psm::TransportSecurityInfo,
|
||||
public nsIClientAuthUserDecision
|
||||
{
|
||||
public:
|
||||
nsNSSSocketInfo(mozilla::psm::SharedSSLState& aState, uint32_t providerFlags);
|
||||
nsNSSSocketInfo(mozilla::psm::SharedSSLState& aState, uint32_t providerFlags,
|
||||
uint32_t providerTlsFlags);
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_NSISSLSOCKETCONTROL
|
||||
@ -75,6 +76,7 @@ public:
|
||||
void SetSentClientCert() { mSentClientCert = true; }
|
||||
|
||||
uint32_t GetProviderFlags() const { return mProviderFlags; }
|
||||
uint32_t GetProviderTlsFlags() const { return mProviderTlsFlags; }
|
||||
|
||||
mozilla::psm::SharedSSLState& SharedState();
|
||||
|
||||
@ -156,6 +158,7 @@ private:
|
||||
bool mBypassAuthentication;
|
||||
|
||||
uint32_t mProviderFlags;
|
||||
uint32_t mProviderTlsFlags;
|
||||
mozilla::TimeStamp mSocketCreationTimestamp;
|
||||
uint64_t mPlaintextBytesRead;
|
||||
|
||||
@ -233,7 +236,8 @@ nsresult nsSSLIOLayerNewSocket(int32_t family,
|
||||
PRFileDesc** fd,
|
||||
nsISupports** securityInfo,
|
||||
bool forSTARTTLS,
|
||||
uint32_t flags);
|
||||
uint32_t flags,
|
||||
uint32_t tlsFlags);
|
||||
|
||||
nsresult nsSSLIOLayerAddToSocket(int32_t family,
|
||||
const char* host,
|
||||
@ -243,7 +247,8 @@ nsresult nsSSLIOLayerAddToSocket(int32_t family,
|
||||
PRFileDesc* fd,
|
||||
nsISupports** securityInfo,
|
||||
bool forSTARTTLS,
|
||||
uint32_t flags);
|
||||
uint32_t flags,
|
||||
uint32_t tlsFlags);
|
||||
|
||||
nsresult nsSSLIOLayerFreeTLSIntolerantSites();
|
||||
nsresult displayUnknownCertErrorAlert(nsNSSSocketInfo* infoObject, int error);
|
||||
|
@ -28,6 +28,7 @@ nsSSLSocketProvider::NewSocket(int32_t family,
|
||||
nsIProxyInfo *proxy,
|
||||
const OriginAttributes &originAttributes,
|
||||
uint32_t flags,
|
||||
uint32_t tlsFlags,
|
||||
PRFileDesc **_result,
|
||||
nsISupports **securityInfo)
|
||||
{
|
||||
@ -39,7 +40,8 @@ nsSSLSocketProvider::NewSocket(int32_t family,
|
||||
_result,
|
||||
securityInfo,
|
||||
false,
|
||||
flags);
|
||||
flags,
|
||||
tlsFlags);
|
||||
return (NS_FAILED(rv)) ? NS_ERROR_SOCKET_CREATE_FAILED : NS_OK;
|
||||
}
|
||||
|
||||
@ -51,6 +53,7 @@ nsSSLSocketProvider::AddToSocket(int32_t family,
|
||||
nsIProxyInfo *proxy,
|
||||
const OriginAttributes &originAttributes,
|
||||
uint32_t flags,
|
||||
uint32_t tlsFlags,
|
||||
PRFileDesc *aSocket,
|
||||
nsISupports **securityInfo)
|
||||
{
|
||||
@ -62,7 +65,8 @@ nsSSLSocketProvider::AddToSocket(int32_t family,
|
||||
aSocket,
|
||||
securityInfo,
|
||||
false,
|
||||
flags);
|
||||
flags,
|
||||
tlsFlags);
|
||||
|
||||
return (NS_FAILED(rv)) ? NS_ERROR_SOCKET_CREATE_FAILED : NS_OK;
|
||||
}
|
||||
|
@ -28,6 +28,7 @@ nsTLSSocketProvider::NewSocket(int32_t family,
|
||||
nsIProxyInfo *proxy,
|
||||
const OriginAttributes &originAttributes,
|
||||
uint32_t flags,
|
||||
uint32_t tlsFlags,
|
||||
PRFileDesc **_result,
|
||||
nsISupports **securityInfo)
|
||||
{
|
||||
@ -39,7 +40,8 @@ nsTLSSocketProvider::NewSocket(int32_t family,
|
||||
_result,
|
||||
securityInfo,
|
||||
true,
|
||||
flags);
|
||||
flags,
|
||||
tlsFlags);
|
||||
|
||||
return (NS_FAILED(rv)) ? NS_ERROR_SOCKET_CREATE_FAILED : NS_OK;
|
||||
}
|
||||
@ -52,6 +54,7 @@ nsTLSSocketProvider::AddToSocket(int32_t family,
|
||||
nsIProxyInfo *proxy,
|
||||
const OriginAttributes &originAttributes,
|
||||
uint32_t flags,
|
||||
uint32_t tlsFlags,
|
||||
PRFileDesc *aSocket,
|
||||
nsISupports **securityInfo)
|
||||
{
|
||||
@ -63,7 +66,8 @@ nsTLSSocketProvider::AddToSocket(int32_t family,
|
||||
aSocket,
|
||||
securityInfo,
|
||||
true,
|
||||
flags);
|
||||
flags,
|
||||
tlsFlags);
|
||||
|
||||
return (NS_FAILED(rv)) ? NS_ERROR_SOCKET_CREATE_FAILED : NS_OK;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user