From 6c728ddf434f114349eb09a43d9b3c47b2bc4303 Mon Sep 17 00:00:00 2001 From: Patrick McManus Date: Thu, 9 Apr 2015 11:31:59 -0400 Subject: [PATCH] bug 1153212 - 2/2 Necko explicitly track origin vs routed host and give psm only origin r=dkeeler r=hurley IGNORE IDL Allow necko to simultaneously track the dual concept of routed host and origin (authenticated host). The origin is given to the socket provider and the routed host is inserted at DNS lookup time as if it were a SRV or CNAME. --HG-- extra : rebase_source : f9cc87b92084025443bc0374b1dd994f01662ebb --- netwerk/base/nsISocketTransport.idl | 7 ++ netwerk/base/nsISocketTransportService.idl | 15 +++ netwerk/base/nsPISocketTransportService.idl | 4 +- netwerk/base/nsSocketTransport2.cpp | 33 ++++- netwerk/base/nsSocketTransport2.h | 3 + netwerk/base/nsSocketTransportService2.cpp | 17 ++- netwerk/base/nsSocketTransportService2.h | 1 + netwerk/build/nsNetCID.h | 11 +- netwerk/protocol/http/AlternateServices.cpp | 8 +- .../protocol/http/ConnectionDiagnostics.cpp | 2 +- netwerk/protocol/http/Http2Stream.cpp | 4 +- netwerk/protocol/http/NullHttpTransaction.cpp | 18 +-- netwerk/protocol/http/SpdyStream31.cpp | 4 +- netwerk/protocol/http/nsHttpChannel.cpp | 4 +- netwerk/protocol/http/nsHttpConnection.cpp | 30 ++--- .../protocol/http/nsHttpConnectionInfo.cpp | 55 ++++---- netwerk/protocol/http/nsHttpConnectionInfo.h | 42 ++++--- netwerk/protocol/http/nsHttpConnectionMgr.cpp | 117 ++++++++++++------ netwerk/protocol/http/nsHttpTransaction.cpp | 2 +- netwerk/socket/nsISSLSocketControl.idl | 14 +-- netwerk/socket/nsISocketProvider.idl | 11 +- netwerk/test/unit/test_http2.js | 2 +- security/manager/ssl/src/nsNSSIOLayer.cpp | 46 +++---- security/manager/ssl/src/nsNSSIOLayer.h | 15 ++- 24 files changed, 266 insertions(+), 199 deletions(-) diff --git a/netwerk/base/nsISocketTransport.idl b/netwerk/base/nsISocketTransport.idl index 31d37779f70a..f7a22ea0a98d 100644 --- a/netwerk/base/nsISocketTransport.idl +++ b/netwerk/base/nsISocketTransport.idl @@ -195,6 +195,13 @@ interface nsISocketTransport : nsITransport */ const unsigned long DISABLE_RFC1918 = (1 << 5); + /** + * This flag is an explicit opt-in that allows a normally secure socket + * provider to use, at its discretion, an insecure algorithm. e.g. + * a TLS socket without authentication. + */ + const unsigned long MITM_OK = (1 << 6); + /** * Socket QoS/ToS markings. Valid values are IPTOS_DSCP_AFxx or * IPTOS_CLASS_CSx (or IPTOS_DSCP_EF, but currently no supported diff --git a/netwerk/base/nsISocketTransportService.idl b/netwerk/base/nsISocketTransportService.idl index f2b24b249595..06350b532f14 100644 --- a/netwerk/base/nsISocketTransportService.idl +++ b/netwerk/base/nsISocketTransportService.idl @@ -118,3 +118,18 @@ interface nsISocketTransportService : nsISupports */ [noscript] void notifyWhenCanAttachSocket(in nsIRunnable aEvent); }; + +[scriptable, uuid(c5204623-5b58-4a16-8b2e-67c34dd02e3f)] +interface nsIRoutedSocketTransportService : nsISocketTransportService +{ + // use this instead of createTransport when you have a transport + // that distinguishes between origin and route (aka connection) + nsISocketTransport createRoutedTransport([array, size_is(aTypeCount)] + in string aSocketTypes, + in unsigned long aTypeCount, + in AUTF8String aHost, // origin + in long aPort, // origin + in AUTF8String aHostRoute, + in long aPortRoute, + in nsIProxyInfo aProxyInfo); +}; diff --git a/netwerk/base/nsPISocketTransportService.idl b/netwerk/base/nsPISocketTransportService.idl index b8ffdb737eb9..75d84bcea479 100644 --- a/netwerk/base/nsPISocketTransportService.idl +++ b/netwerk/base/nsPISocketTransportService.idl @@ -10,9 +10,9 @@ * This is a private interface used by the internals of the networking library. * It will never be frozen. Do not use it in external code. */ -[scriptable, uuid(bc5869e7-53a6-4195-8ab8-32e7116b87dd)] +[scriptable, uuid(18f73bf1-b35b-4b7b-aa9a-11bcbdbc389c)] -interface nsPISocketTransportService : nsISocketTransportService +interface nsPISocketTransportService : nsIRoutedSocketTransportService { /** * init/shutdown routines. diff --git a/netwerk/base/nsSocketTransport2.cpp b/netwerk/base/nsSocketTransport2.cpp index f63326c4f9de..aeebb3a6069c 100644 --- a/netwerk/base/nsSocketTransport2.cpp +++ b/netwerk/base/nsSocketTransport2.cpp @@ -727,6 +727,7 @@ nsSocketTransport::nsSocketTransport() , mTypeCount(0) , mPort(0) , mProxyPort(0) + , mOriginPort(0) , mProxyTransparent(false) , mProxyTransparentResolvesHost(false) , mHttpsProxy(false) @@ -780,6 +781,7 @@ nsSocketTransport::CleanupTypes() nsresult nsSocketTransport::Init(const char **types, uint32_t typeCount, const nsACString &host, uint16_t port, + const nsACString &hostRoute, uint16_t portRoute, nsIProxyInfo *givenProxyInfo) { MOZ_EVENT_TRACER_NAME_OBJECT(this, host.BeginReading()); @@ -792,8 +794,15 @@ nsSocketTransport::Init(const char **types, uint32_t typeCount, // init socket type info - mPort = port; - mHost = host; + mOriginHost = host; + mOriginPort = port; + if (!hostRoute.IsEmpty()) { + mHost = hostRoute; + mPort = portRoute; + } else { + mHost = host; + mPort = port; + } if (proxyInfo) { mHttpsProxy = proxyInfo->IsHTTPS(); @@ -813,8 +822,9 @@ nsSocketTransport::Init(const char **types, uint32_t typeCount, } } - SOCKET_LOG(("nsSocketTransport::Init [this=%p host=%s:%hu proxy=%s:%hu]\n", - this, mHost.get(), mPort, mProxyHost.get(), mProxyPort)); + SOCKET_LOG(("nsSocketTransport::Init [this=%p host=%s:%hu origin=%s:%d proxy=%s:%hu]\n", + this, mHost.get(), mPort, mOriginHost.get(), mOriginPort, + mProxyHost.get(), mProxyPort)); // include proxy type as a socket type if proxy type is not "http" mTypeCount = typeCount + (proxyType != nullptr); @@ -1046,6 +1056,11 @@ nsSocketTransport::ResolveHost() "Setting both RESOLVE_DISABLE_IPV6 and RESOLVE_DISABLE_IPV4"); SendStatus(NS_NET_STATUS_RESOLVING_HOST); + + if (!SocketHost().Equals(mOriginHost)) { + SOCKET_LOG(("nsSocketTransport %p origin %s doing dns for %s\n", + this, mOriginHost.get(), SocketHost().get())); + } rv = dns->AsyncResolveExtended(SocketHost(), dnsFlags, mNetworkInterfaceId, this, nullptr, getter_AddRefs(mDNSRequest)); if (NS_SUCCEEDED(rv)) { @@ -1081,8 +1096,11 @@ nsSocketTransport::BuildSocket(PRFileDesc *&fd, bool &proxyTransparent, bool &us do_GetService(kSocketProviderServiceCID, &rv); if (NS_FAILED(rv)) return rv; - const char *host = mHost.get(); - int32_t port = (int32_t) mPort; + // by setting host to mOriginHost, instead of mHost we send the + // SocketProvider (e.g. PSM) the origin hostname but can still do DNS + // on an explicit alternate service host name + const char *host = mOriginHost.get(); + int32_t port = (int32_t) mOriginPort; const char *proxyHost = mProxyHost.IsEmpty() ? nullptr : mProxyHost.get(); int32_t proxyPort = (int32_t) mProxyPort; uint32_t controlFlags = 0; @@ -1106,6 +1124,9 @@ nsSocketTransport::BuildSocket(PRFileDesc *&fd, bool &proxyTransparent, bool &us if (mConnectionFlags & nsISocketTransport::NO_PERMANENT_STORAGE) controlFlags |= nsISocketProvider::NO_PERMANENT_STORAGE; + if (mConnectionFlags & nsISocketTransport::MITM_OK) + controlFlags |= nsISocketProvider::MITM_OK; + nsCOMPtr secinfo; if (i == 0) { // if this is the first type, we'll want the diff --git a/netwerk/base/nsSocketTransport2.h b/netwerk/base/nsSocketTransport2.h index a17731f977be..3f1b8fd0d345 100644 --- a/netwerk/base/nsSocketTransport2.h +++ b/netwerk/base/nsSocketTransport2.h @@ -127,6 +127,7 @@ public: // given type(s) to the given host or proxy. nsresult Init(const char **socketTypes, uint32_t typeCount, const nsACString &host, uint16_t port, + const nsACString &hostRoute, uint16_t portRoute, nsIProxyInfo *proxyInfo); // this method instructs the socket transport to use an already connected @@ -275,8 +276,10 @@ private: uint32_t mTypeCount; nsCString mHost; nsCString mProxyHost; + nsCString mOriginHost; uint16_t mPort; uint16_t mProxyPort; + uint16_t mOriginPort; bool mProxyTransparent; bool mProxyTransparentResolvesHost; bool mHttpsProxy; diff --git a/netwerk/base/nsSocketTransportService2.cpp b/netwerk/base/nsSocketTransportService2.cpp index 0ff118f6e7d7..0c4d4b9f6853 100644 --- a/netwerk/base/nsSocketTransportService2.cpp +++ b/netwerk/base/nsSocketTransportService2.cpp @@ -443,6 +443,7 @@ nsSocketTransportService::Poll(bool wait, uint32_t *interval, NS_IMPL_ISUPPORTS(nsSocketTransportService, nsISocketTransportService, + nsIRoutedSocketTransportService, nsIEventTarget, nsIThreadObserver, nsIRunnable, @@ -634,6 +635,20 @@ nsSocketTransportService::CreateTransport(const char **types, int32_t port, nsIProxyInfo *proxyInfo, nsISocketTransport **result) +{ + return CreateRoutedTransport(types, typeCount, host, port, NS_LITERAL_CSTRING(""), 0, + proxyInfo, result); +} + +NS_IMETHODIMP +nsSocketTransportService::CreateRoutedTransport(const char **types, + uint32_t typeCount, + const nsACString &host, + int32_t port, + const nsACString &hostRoute, + int32_t portRoute, + nsIProxyInfo *proxyInfo, + nsISocketTransport **result) { #if defined(MOZILLA_XPCOMRT_API) NS_WARNING("nsSocketTransportService::CreateTransport not implemented"); @@ -643,7 +658,7 @@ nsSocketTransportService::CreateTransport(const char **types, NS_ENSURE_TRUE(port >= 0 && port <= 0xFFFF, NS_ERROR_ILLEGAL_VALUE); nsRefPtr trans = new nsSocketTransport(); - nsresult rv = trans->Init(types, typeCount, host, port, proxyInfo); + nsresult rv = trans->Init(types, typeCount, host, port, hostRoute, portRoute, proxyInfo); if (NS_FAILED(rv)) { return rv; } diff --git a/netwerk/base/nsSocketTransportService2.h b/netwerk/base/nsSocketTransportService2.h index 3b8f19790409..a20f669318e2 100644 --- a/netwerk/base/nsSocketTransportService2.h +++ b/netwerk/base/nsSocketTransportService2.h @@ -69,6 +69,7 @@ public: NS_DECL_THREADSAFE_ISUPPORTS NS_DECL_NSPISOCKETTRANSPORTSERVICE NS_DECL_NSISOCKETTRANSPORTSERVICE + NS_DECL_NSIROUTEDSOCKETTRANSPORTSERVICE NS_DECL_NSIEVENTTARGET NS_DECL_NSITHREADOBSERVER NS_DECL_NSIRUNNABLE diff --git a/netwerk/build/nsNetCID.h b/netwerk/build/nsNetCID.h index ac39fb8e816a..90ff3cf60476 100644 --- a/netwerk/build/nsNetCID.h +++ b/netwerk/build/nsNetCID.h @@ -317,13 +317,14 @@ #define NS_SOCKETTRANSPORTSERVICE_CONTRACTID \ "@mozilla.org/network/socket-transport-service;1" #define NS_SOCKETTRANSPORTSERVICE_CID \ -{ /* c07e81e0-ef12-11d2-92b6-00105a1b0d64 */ \ - 0xc07e81e0, \ - 0xef12, \ - 0x11d2, \ - {0x92, 0xb6, 0x00, 0x10, 0x5a, 0x1b, 0x0d, 0x64} \ +{ /* ad56b25f-e6bb-4db3-9f7b-5b7db33fd2b1 */ \ + 0xad56b25f, \ + 0xe6bb, \ + 0x4db3, \ + {0x9f, 0x7b, 0x5b, 0x7d, 0xb3, 0x3f, 0xd2, 0xb1} \ } + // component implementing nsIServerSocket #define NS_SERVERSOCKET_CONTRACTID \ "@mozilla.org/network/server-socket;1" diff --git a/netwerk/protocol/http/AlternateServices.cpp b/netwerk/protocol/http/AlternateServices.cpp index d870b6ae6c63..4d99e0e0ac23 100644 --- a/netwerk/protocol/http/AlternateServices.cpp +++ b/netwerk/protocol/http/AlternateServices.cpp @@ -228,8 +228,8 @@ AltSvcMapping::GetConnectionInfo(nsHttpConnectionInfo **outCI, nsProxyInfo *pi) { nsRefPtr ci = - new nsHttpConnectionInfo(mAlternateHost, mAlternatePort, mNPNToken, - mUsername, pi, mOriginHost, mOriginPort); + new nsHttpConnectionInfo(mOriginHost, mOriginPort, mNPNToken, + mUsername, pi, mAlternateHost, mAlternatePort); ci->SetInsecureScheme(!mHttps); ci->SetPrivate(mPrivate); ci.forget(outCI); @@ -524,8 +524,8 @@ AltSvcCache::ClearHostMapping(const nsACString &host, int32_t port) void AltSvcCache::ClearHostMapping(nsHttpConnectionInfo *ci) { - if (!ci->GetAuthenticationHost().IsEmpty()) { - ClearHostMapping(ci->GetAuthenticationHost(), ci->GetAuthenticationPort()); + if (!ci->GetOrigin().IsEmpty()) { + ClearHostMapping(ci->GetOrigin(), ci->OriginPort()); } } diff --git a/netwerk/protocol/http/ConnectionDiagnostics.cpp b/netwerk/protocol/http/ConnectionDiagnostics.cpp index 174fa3fa25ff..a6d3f0241345 100644 --- a/netwerk/protocol/http/ConnectionDiagnostics.cpp +++ b/netwerk/protocol/http/ConnectionDiagnostics.cpp @@ -57,7 +57,7 @@ nsHttpConnectionMgr::PrintDiagnosticsCB(const nsACString &key, uint32_t i; self->mLogData.AppendPrintf(" ent host = %s hashkey = %s\n", - ent->mConnInfo->Host(), ent->mConnInfo->HashKey().get()); + ent->mConnInfo->Origin(), ent->mConnInfo->HashKey().get()); self->mLogData.AppendPrintf(" AtActiveConnectionLimit = %d\n", self->AtActiveConnectionLimit(ent, NS_HTTP_ALLOW_KEEPALIVE)); self->mLogData.AppendPrintf(" RestrictConnections = %d\n", diff --git a/netwerk/protocol/http/Http2Stream.cpp b/netwerk/protocol/http/Http2Stream.cpp index 38fc025eee45..eab7fee8982b 100644 --- a/netwerk/protocol/http/Http2Stream.cpp +++ b/netwerk/protocol/http/Http2Stream.cpp @@ -464,9 +464,9 @@ Http2Stream::GenerateOpen() return NS_ERROR_UNEXPECTED; } - authorityHeader = ci->GetHost(); + authorityHeader = ci->GetOrigin(); authorityHeader.Append(':'); - authorityHeader.AppendInt(ci->Port()); + authorityHeader.AppendInt(ci->OriginPort()); } mSession->Compressor()->EncodeHeaderBlock(mFlatHttpRequestHeaders, diff --git a/netwerk/protocol/http/NullHttpTransaction.cpp b/netwerk/protocol/http/NullHttpTransaction.cpp index ac1f447175df..4a706992d577 100644 --- a/netwerk/protocol/http/NullHttpTransaction.cpp +++ b/netwerk/protocol/http/NullHttpTransaction.cpp @@ -115,7 +115,7 @@ NullHttpTransaction::NullHttpTransaction(nsHttpConnectionInfo *ci, // There are some observers registered at activity distributor. LOG(("NulHttpTransaction::NullHttpTransaction() " "mActivityDistributor is active " - "[this=%p, %s]", this, ci->GetHost().get())); + "[this=%p, %s]", this, ci->GetOrigin().get())); } else { // There is no observer, so don't use it. mActivityDistributor = nullptr; @@ -163,8 +163,8 @@ NullHttpTransaction::OnTransportStatus(nsITransport* transport, { if (mActivityDistributor) { NS_DispatchToMainThread(new CallObserveActivity(mActivityDistributor, - mConnectionInfo->GetHost(), - mConnectionInfo->Port(), + mConnectionInfo->GetOrigin(), + mConnectionInfo->OriginPort(), mConnectionInfo->EndToEndSSL(), NS_HTTP_ACTIVITY_TYPE_SOCKET_TRANSPORT, static_cast(status), @@ -238,9 +238,9 @@ NullHttpTransaction::RequestHead() mRequestHead = new nsHttpRequestHead(); nsAutoCString hostHeader; - nsCString host(mConnectionInfo->GetHost()); + nsCString host(mConnectionInfo->GetOrigin()); nsresult rv = nsHttpHandler::GenerateHostPort(host, - mConnectionInfo->Port(), + mConnectionInfo->OriginPort(), hostHeader); if (NS_SUCCEEDED(rv)) { mRequestHead->SetHeader(nsHttp::Host, hostHeader); @@ -249,8 +249,8 @@ NullHttpTransaction::RequestHead() nsCString reqHeaderBuf; mRequestHead->Flatten(reqHeaderBuf, false); NS_DispatchToMainThread(new CallObserveActivity(mActivityDistributor, - mConnectionInfo->GetHost(), - mConnectionInfo->Port(), + mConnectionInfo->GetOrigin(), + mConnectionInfo->OriginPort(), mConnectionInfo->EndToEndSSL(), NS_HTTP_ACTIVITY_TYPE_HTTP_TRANSACTION, NS_HTTP_ACTIVITY_SUBTYPE_REQUEST_HEADER, @@ -288,8 +288,8 @@ NullHttpTransaction::Close(nsresult reason) if (mActivityDistributor) { // Report that this transaction is closing. NS_DispatchToMainThread(new CallObserveActivity(mActivityDistributor, - mConnectionInfo->GetHost(), - mConnectionInfo->Port(), + mConnectionInfo->GetOrigin(), + mConnectionInfo->OriginPort(), mConnectionInfo->EndToEndSSL(), NS_HTTP_ACTIVITY_TYPE_HTTP_TRANSACTION, NS_HTTP_ACTIVITY_SUBTYPE_TRANSACTION_CLOSE, diff --git a/netwerk/protocol/http/SpdyStream31.cpp b/netwerk/protocol/http/SpdyStream31.cpp index e1423847d7e6..a8443c670b6b 100644 --- a/netwerk/protocol/http/SpdyStream31.cpp +++ b/netwerk/protocol/http/SpdyStream31.cpp @@ -521,9 +521,9 @@ SpdyStream31::GenerateSynFrame() return NS_ERROR_UNEXPECTED; } nsAutoCString route; - route = ci->GetHost(); + route = ci->GetOrigin(); route.Append(':'); - route.AppendInt(ci->Port()); + route.AppendInt(ci->OriginPort()); CompressToFrame(route); } diff --git a/netwerk/protocol/http/nsHttpChannel.cpp b/netwerk/protocol/http/nsHttpChannel.cpp index eb55de00a058..631829aacf44 100644 --- a/netwerk/protocol/http/nsHttpChannel.cpp +++ b/netwerk/protocol/http/nsHttpChannel.cpp @@ -352,7 +352,7 @@ nsHttpChannel::Connect() } // ensure that we are using a valid hostname - if (!net_IsValidHostName(nsDependentCString(mConnectionInfo->Host()))) + if (!net_IsValidHostName(nsDependentCString(mConnectionInfo->Origin()))) return NS_ERROR_UNKNOWN_HOST; // Finalize ConnectionInfo flags before SpeculativeConnect @@ -923,7 +923,7 @@ nsHttpChannel::CallOnStartRequest() if (!mContentTypeHint.IsEmpty()) mResponseHead->SetContentType(mContentTypeHint); else if (mResponseHead->Version() == NS_HTTP_VERSION_0_9 && - mConnectionInfo->Port() != mConnectionInfo->DefaultPort()) + mConnectionInfo->OriginPort() != mConnectionInfo->DefaultPort()) mResponseHead->SetContentType(NS_LITERAL_CSTRING(TEXT_PLAIN)); else { // Uh-oh. We had better find out what type we are! diff --git a/netwerk/protocol/http/nsHttpConnection.cpp b/netwerk/protocol/http/nsHttpConnection.cpp index a2f6b97e24a9..67a0558d5fed 100644 --- a/netwerk/protocol/http/nsHttpConnection.cpp +++ b/netwerk/protocol/http/nsHttpConnection.cpp @@ -511,22 +511,6 @@ nsHttpConnection::SetupNPNList(nsISSLSocketControl *ssl, uint32_t caps) protocolArray.AppendElement(npnToken); } - nsCString authHost = mConnInfo->GetAuthenticationHost(); - int32_t authPort = mConnInfo->GetAuthenticationPort(); - - if (!authHost.IsEmpty()) { - ssl->SetAuthenticationName(authHost); - ssl->SetAuthenticationPort(authPort); - } - - if (mConnInfo->GetInsecureScheme()) { // http:// over tls - if (authHost.IsEmpty() || authHost.Equals(mConnInfo->GetHost())) { - LOG(("nsHttpConnection::SetupSSL %p TLS-Relaxed " - "with Same Host Auth Bypass", this)); - ssl->SetBypassAuthentication(true); - } - } - nsresult rv = ssl->SetNPNList(protocolArray); LOG(("nsHttpConnection::SetupNPNList %p %x\n",this, rv)); return rv; @@ -720,7 +704,7 @@ nsHttpConnection::CanReuse() NS_SUCCEEDED(mSocketIn->Available(&dataSize)) && dataSize) { LOG(("nsHttpConnection::CanReuse %p %s" "Socket not reusable because read data pending (%llu) on it.\n", - this, mConnInfo->Host(), dataSize)); + this, mConnInfo->Origin(), dataSize)); canReuse = false; } return canReuse; @@ -1023,7 +1007,7 @@ nsHttpConnection::OnHeadersAvailable(nsAHttpTransaction *trans, if (isHttps) { if (mConnInfo->UsingHttpsProxy()) { LOG(("%p new TLSFilterTransaction %s %d\n", - this, mConnInfo->Host(), mConnInfo->Port())); + this, mConnInfo->Origin(), mConnInfo->OriginPort())); SetupSecondaryTLS(); } @@ -1534,7 +1518,7 @@ nsresult nsHttpConnection::OnSocketWritable() { LOG(("nsHttpConnection::OnSocketWritable [this=%p] host=%s\n", - this, mConnInfo->Host())); + this, mConnInfo->Origin())); nsresult rv; uint32_t transactionBytes; @@ -1773,7 +1757,7 @@ nsHttpConnection::SetupSecondaryTLS() MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread); MOZ_ASSERT(!mTLSFilter); LOG(("nsHttpConnection %p SetupSecondaryTLS %s %d\n", - this, mConnInfo->Host(), mConnInfo->Port())); + this, mConnInfo->Origin(), mConnInfo->OriginPort())); nsHttpConnectionInfo *ci = nullptr; if (mTransaction) { @@ -1785,7 +1769,7 @@ nsHttpConnection::SetupSecondaryTLS() MOZ_ASSERT(ci); mTLSFilter = new TLSFilterTransaction(mTransaction, - ci->Host(), ci->Port(), this, this); + ci->Origin(), ci->OriginPort(), this, this); if (mTransaction) { mTransaction = mTLSFilter; @@ -1815,8 +1799,8 @@ nsHttpConnection::MakeConnectString(nsAHttpTransaction *trans, } nsHttpHandler::GenerateHostPort( - nsDependentCString(trans->ConnectionInfo()->Host()), - trans->ConnectionInfo()->Port(), result); + nsDependentCString(trans->ConnectionInfo()->Origin()), + trans->ConnectionInfo()->OriginPort(), result); // CONNECT host:port HTTP/1.1 request->SetMethod(NS_LITERAL_CSTRING("CONNECT")); diff --git a/netwerk/protocol/http/nsHttpConnectionInfo.cpp b/netwerk/protocol/http/nsHttpConnectionInfo.cpp index 66d3e4942668..5a0fef6d7c9c 100644 --- a/netwerk/protocol/http/nsHttpConnectionInfo.cpp +++ b/netwerk/protocol/http/nsHttpConnectionInfo.cpp @@ -20,33 +20,33 @@ namespace mozilla { namespace net { -nsHttpConnectionInfo::nsHttpConnectionInfo(const nsACString &physicalHost, - int32_t physicalPort, +nsHttpConnectionInfo::nsHttpConnectionInfo(const nsACString &originHost, + int32_t originPort, const nsACString &npnToken, const nsACString &username, nsProxyInfo *proxyInfo, bool endToEndSSL) - : mAuthenticationPort(443) + : mRoutedPort(443) { - Init(physicalHost, physicalPort, npnToken, username, proxyInfo, endToEndSSL); + Init(originHost, originPort, npnToken, username, proxyInfo, endToEndSSL); } -nsHttpConnectionInfo::nsHttpConnectionInfo(const nsACString &physicalHost, - int32_t physicalPort, +nsHttpConnectionInfo::nsHttpConnectionInfo(const nsACString &originHost, + int32_t originPort, const nsACString &npnToken, const nsACString &username, nsProxyInfo *proxyInfo, - const nsACString &logicalHost, - int32_t logicalPort) + const nsACString &routedHost, + int32_t routedPort) { mEndToEndSSL = true; // so DefaultPort() works - mAuthenticationPort = logicalPort == -1 ? DefaultPort() : logicalPort; + mRoutedPort = routedPort == -1 ? DefaultPort() : routedPort; - if (!physicalHost.Equals(logicalHost) || (physicalPort != logicalPort)) { - mAuthenticationHost = logicalHost; + if (!originHost.Equals(routedHost) || (originPort != routedPort)) { + mRoutedHost = routedHost; } - Init(physicalHost, physicalPort, npnToken, username, proxyInfo, true); + Init(originHost, originPort, npnToken, username, proxyInfo, true); } void @@ -105,8 +105,8 @@ void nsHttpConnectionInfo::BuildHashKey() keyHost = ProxyHost(); keyPort = ProxyPort(); } else { - keyHost = Host(); - keyPort = Port(); + keyHost = Origin(); + keyPort = OriginPort(); } // The hashkey has 4 fields followed by host connection info @@ -162,11 +162,11 @@ void nsHttpConnectionInfo::BuildHashKey() mHashKey.Append(')'); } - if(!mAuthenticationHost.IsEmpty()) { - mHashKey.AppendLiteral(" '); } @@ -180,8 +180,8 @@ void nsHttpConnectionInfo::BuildHashKey() void nsHttpConnectionInfo::SetOriginServer(const nsACString &host, int32_t port) { - mHost = host; - mPort = port == -1 ? DefaultPort() : port; + mOrigin = host; + mOriginPort = port == -1 ? DefaultPort() : port; BuildHashKey(); } @@ -189,13 +189,12 @@ nsHttpConnectionInfo* nsHttpConnectionInfo::Clone() const { nsHttpConnectionInfo *clone; - if (mAuthenticationHost.IsEmpty()) { - clone = new nsHttpConnectionInfo(mHost, mPort, mNPNToken, mUsername, mProxyInfo, mEndToEndSSL); + if (mRoutedHost.IsEmpty()) { + clone = new nsHttpConnectionInfo(mOrigin, mOriginPort, mNPNToken, mUsername, mProxyInfo, mEndToEndSSL); } else { MOZ_ASSERT(mEndToEndSSL); - clone = new nsHttpConnectionInfo(mHost, mPort, mNPNToken, mUsername, mProxyInfo, - mAuthenticationHost, - mAuthenticationPort); + clone = new nsHttpConnectionInfo(mOrigin, mOriginPort, mNPNToken, mUsername, mProxyInfo, + mRoutedHost, mRoutedPort); } if (!mNetworkInterfaceId.IsEmpty()) { @@ -215,13 +214,13 @@ nsHttpConnectionInfo::Clone() const void nsHttpConnectionInfo::CloneAsDirectRoute(nsHttpConnectionInfo **outCI) { - if (mAuthenticationHost.IsEmpty()) { + if (mRoutedHost.IsEmpty()) { *outCI = Clone(); return; } nsRefPtr clone = - new nsHttpConnectionInfo(mAuthenticationHost, mAuthenticationPort, + new nsHttpConnectionInfo(mOrigin, mOriginPort, EmptyCString(), mUsername, mProxyInfo, mEndToEndSSL); // Make sure the anonymous, insecure-scheme, and private flags are transferred clone->SetAnonymous(GetAnonymous()); @@ -272,7 +271,7 @@ nsHttpConnectionInfo::HostIsLocalIPLiteral() const if (PR_StringToNetAddr(ProxyHost(), &prAddr) != PR_SUCCESS) { return false; } - } else if (PR_StringToNetAddr(Host(), &prAddr) != PR_SUCCESS) { + } else if (PR_StringToNetAddr(Origin(), &prAddr) != PR_SUCCESS) { return false; } NetAddr netAddr; diff --git a/netwerk/protocol/http/nsHttpConnectionInfo.h b/netwerk/protocol/http/nsHttpConnectionInfo.h index 86d9e81f1da5..3f655b6e30ef 100644 --- a/netwerk/protocol/http/nsHttpConnectionInfo.h +++ b/netwerk/protocol/http/nsHttpConnectionInfo.h @@ -32,22 +32,23 @@ namespace mozilla { namespace net { class nsHttpConnectionInfo { public: - nsHttpConnectionInfo(const nsACString &physicalHost, - int32_t physicalPort, + nsHttpConnectionInfo(const nsACString &originHost, + int32_t originPort, const nsACString &npnToken, const nsACString &username, nsProxyInfo *proxyInfo, bool endToEndSSL = false); - // this version must use TLS and you may supply the domain - // information to be validated - nsHttpConnectionInfo(const nsACString &physicalHost, - int32_t physicalPort, + // this version must use TLS and you may supply separate + // connection (aka routing) information than the authenticated + // origin information + nsHttpConnectionInfo(const nsACString &originHost, + int32_t originPort, const nsACString &npnToken, const nsACString &username, nsProxyInfo *proxyInfo, - const nsACString &logicalHost, - int32_t logicalPort); + const nsACString &routedHost, + int32_t routedPort); private: virtual ~nsHttpConnectionInfo() @@ -60,8 +61,13 @@ private: public: const nsAFlatCString &HashKey() const { return mHashKey; } - const nsCString &GetAuthenticationHost() const { return mAuthenticationHost; } - int32_t GetAuthenticationPort() const { return mAuthenticationPort; } + const nsCString &GetOrigin() const { return mOrigin; } + const char *Origin() const { return mOrigin.get(); } + int32_t OriginPort() const { return mOriginPort; } + + const nsCString &GetRoutedHost() const { return mRoutedHost; } + const char *RoutedHost() const { return mRoutedHost.get(); } + int32_t RoutedPort() const { return mRoutedPort; } // With overhead rebuilding the hash key. The initial // network interface is empty. So you can reduce one call @@ -89,10 +95,8 @@ public: return mHashKey.Equals(info->HashKey()); } - const char *Host() const { return mHost.get(); } - int32_t Port() const { return mPort; } const char *Username() const { return mUsername.get(); } - nsProxyInfo *ProxyInfo() { return mProxyInfo; } + nsProxyInfo *ProxyInfo() const { return mProxyInfo; } int32_t DefaultPort() const { return mEndToEndSSL ? NS_HTTPS_DEFAULT_PORT : NS_HTTP_DEFAULT_PORT; } void SetAnonymous(bool anon) { mHashKey.SetCharAt(anon ? 'A' : '.', 2); } @@ -109,7 +113,6 @@ public: const nsCString &GetNetworkInterfaceId() const { return mNetworkInterfaceId; } - const nsCString &GetHost() { return mHost; } const nsCString &GetNPNToken() { return mNPNToken; } const nsCString &GetUsername() { return mUsername; } @@ -131,7 +134,7 @@ public: // Returns true when CONNECT is used to tunnel through the proxy (e.g. https:// or ws://) bool UsingConnect() const { return mUsingConnect; } - // Returns true when mHost is an RFC1918 literal. + // Returns true when origin/proxy is an RFC1918 literal. bool HostIsLocalIPLiteral() const; private: @@ -143,13 +146,14 @@ private: bool EndToEndSSL); void SetOriginServer(const nsACString &host, int32_t port); + nsCString mOrigin; + int32_t mOriginPort; + nsCString mRoutedHost; + int32_t mRoutedPort; + nsCString mHashKey; - nsCString mHost; nsCString mNetworkInterfaceId; - int32_t mPort; nsCString mUsername; - nsCString mAuthenticationHost; - int32_t mAuthenticationPort; nsCOMPtr mProxyInfo; bool mUsingHttpProxy; bool mUsingHttpsProxy; diff --git a/netwerk/protocol/http/nsHttpConnectionMgr.cpp b/netwerk/protocol/http/nsHttpConnectionMgr.cpp index b0663b3dbdc5..9e711d5b130a 100644 --- a/netwerk/protocol/http/nsHttpConnectionMgr.cpp +++ b/netwerk/protocol/http/nsHttpConnectionMgr.cpp @@ -418,7 +418,7 @@ nsHttpConnectionMgr::SpeculativeConnect(nsHttpConnectionInfo *ci, // connected - Bug 853423. if ((!allow1918) && ci && ci->HostIsLocalIPLiteral()) { LOG(("nsHttpConnectionMgr::SpeculativeConnect skipping RFC1918 " - "address [%s]", ci->Host())); + "address [%s]", ci->Origin())); return NS_OK; } @@ -718,8 +718,8 @@ nsHttpConnectionMgr::ReportSpdyConnection(nsHttpConnection *conn, nsConnectionEntry *preferred = LookupPreferredHash(ent); LOG(("ReportSpdyConnection %p,%s prefers %p,%s\n", - ent, ent->mConnInfo->Host(), preferred, - preferred ? preferred->mConnInfo->Host() : "")); + ent, ent->mConnInfo->Origin(), preferred, + preferred ? preferred->mConnInfo->Origin() : "")); if (!preferred) { // this becomes the preferred entry @@ -848,8 +848,8 @@ nsHttpConnectionMgr::GetSpdyPreferredEnt(nsConnectionEntry *aOriginalEntry) RemovePreferredHash(preferred); LOG(("nsHttpConnectionMgr::GetSpdyPreferredConnection " "preferred host mapping %s to %s removed due to inactivity.\n", - aOriginalEntry->mConnInfo->Host(), - preferred->mConnInfo->Host())); + aOriginalEntry->mConnInfo->Origin(), + preferred->mConnInfo->Origin())); return nullptr; } @@ -880,8 +880,8 @@ nsHttpConnectionMgr::GetSpdyPreferredEnt(nsConnectionEntry *aOriginalEntry) NS_SUCCEEDED(rv) && index > 0; --index) { if (info->ProtocolEnabled(index - 1)) { rv = sslSocketControl->JoinConnection(info->VersionString[index - 1], - aOriginalEntry->mConnInfo->GetHost(), - aOriginalEntry->mConnInfo->Port(), + aOriginalEntry->mConnInfo->GetOrigin(), + aOriginalEntry->mConnInfo->OriginPort(), &isJoined); if (NS_SUCCEEDED(rv) && isJoined) { break; @@ -893,7 +893,7 @@ nsHttpConnectionMgr::GetSpdyPreferredEnt(nsConnectionEntry *aOriginalEntry) LOG(("nsHttpConnectionMgr::GetSpdyPreferredConnection " "Host %s cannot be confirmed to be joined " "with %s connections. rv=%x isJoined=%d", - preferred->mConnInfo->Host(), aOriginalEntry->mConnInfo->Host(), + preferred->mConnInfo->Origin(), aOriginalEntry->mConnInfo->Origin(), rv, isJoined)); Telemetry::Accumulate(Telemetry::SPDY_NPN_JOIN, false); return nullptr; @@ -903,8 +903,8 @@ nsHttpConnectionMgr::GetSpdyPreferredEnt(nsConnectionEntry *aOriginalEntry) LOG(("nsHttpConnectionMgr::GetSpdyPreferredConnection " "Host %s has cert valid for %s connections, " "so %s will be coalesced with %s", - preferred->mConnInfo->Host(), aOriginalEntry->mConnInfo->Host(), - aOriginalEntry->mConnInfo->Host(), preferred->mConnInfo->Host())); + preferred->mConnInfo->Origin(), aOriginalEntry->mConnInfo->Origin(), + aOriginalEntry->mConnInfo->Origin(), preferred->mConnInfo->Origin())); Telemetry::Accumulate(Telemetry::SPDY_NPN_JOIN, true); return preferred; } @@ -1476,7 +1476,7 @@ nsHttpConnectionMgr::RestrictConnections(nsConnectionEntry *ent, doRestrict = confirmedRestrict; if (!confirmedRestrict) { LOG(("nsHttpConnectionMgr spdy connection restriction to " - "%s bypassed.\n", ent->mConnInfo->Host())); + "%s bypassed.\n", ent->mConnInfo->Origin())); } } return doRestrict; @@ -1950,8 +1950,8 @@ nsHttpConnectionMgr::DispatchTransaction(nsConnectionEntry *ent, if (conn->UsingSpdy()) { LOG(("Spdy Dispatch Transaction via Activate(). Transaction host = %s, " "Connection host = %s\n", - trans->ConnectionInfo()->Host(), - conn->ConnectionInfo()->Host())); + trans->ConnectionInfo()->Origin(), + conn->ConnectionInfo()->Origin())); rv = conn->Activate(trans, caps, priority); MOZ_ASSERT(NS_SUCCEEDED(rv), "SPDY Cannot Fail Dispatch"); if (NS_SUCCEEDED(rv) && !trans->GetPendingTime().IsNull()) { @@ -2123,7 +2123,7 @@ nsHttpConnectionMgr::ProcessNewTransaction(nsHttpTransaction *trans) if (preferredEntry && (preferredEntry != ent)) { LOG(("nsHttpConnectionMgr::ProcessNewTransaction trans=%p " "redirected via coalescing from %s to %s\n", trans, - ent->mConnInfo->Host(), preferredEntry->mConnInfo->Host())); + ent->mConnInfo->Origin(), preferredEntry->mConnInfo->Origin())); ent = preferredEntry; } @@ -2867,7 +2867,7 @@ nsHttpConnectionMgr::TimeoutTickCB(const nsACString &key, LOG(("nsHttpConnectionMgr::TimeoutTickCB() this=%p host=%s " "idle=%d active=%d half-len=%d pending=%d\n", - self, ent->mConnInfo->Host(), ent->mIdleConns.Length(), + self, ent->mConnInfo->Origin(), ent->mIdleConns.Length(), ent->mActiveConns.Length(), ent->mHalfOpens.Length(), ent->mPendingQ.Length())); @@ -3089,7 +3089,7 @@ nsHalfOpenSocket::nsHalfOpenSocket(nsConnectionEntry *ent, { MOZ_ASSERT(ent && trans, "constructor with null arguments"); LOG(("Creating nsHalfOpenSocket [this=%p trans=%p ent=%s key=%s]\n", - this, trans, ent->mConnInfo->Host(), ent->mConnInfo->HashKey().get())); + this, trans, ent->mConnInfo->Origin(), ent->mConnInfo->HashKey().get())); } nsHttpConnectionMgr::nsHalfOpenSocket::~nsHalfOpenSocket() @@ -3113,8 +3113,19 @@ nsHalfOpenSocket::SetupStreams(nsISocketTransport **transport, nsresult rv; const char *socketTypes[1]; uint32_t typeCount = 0; - if (mEnt->mConnInfo->FirstHopSSL()) { + bool bypassTLSAuth = false; + const nsHttpConnectionInfo *ci = mEnt->mConnInfo; + if (ci->FirstHopSSL()) { socketTypes[typeCount++] = "ssl"; + + if (ci->GetInsecureScheme()) { // http:// over tls + const nsCString &routedHost = ci->GetRoutedHost(); + if (routedHost.Equals(ci->GetOrigin())) { + LOG(("nsHttpConnection::SetupSSL %p TLS-Relaxed " + "with Same Host Auth Bypass", this)); + bypassTLSAuth = true; + } + } } else { socketTypes[typeCount] = gHttpHandler->DefaultSocketType(); if (socketTypes[typeCount]) { @@ -3128,11 +3139,33 @@ nsHalfOpenSocket::SetupStreams(nsISocketTransport **transport, sts = do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID, &rv); NS_ENSURE_SUCCESS(rv, rv); - rv = sts->CreateTransport(socketTypes, typeCount, - nsDependentCString(mEnt->mConnInfo->Host()), - mEnt->mConnInfo->Port(), - mEnt->mConnInfo->ProxyInfo(), - getter_AddRefs(socketTransport)); + LOG(("nsHalfOpenSocket::SetupStreams [this=%p ent=%s] " + "setup routed transport to origin %s:%d via %s:%d\n", + this, ci->HashKey().get(), + ci->Origin(), ci->OriginPort(), ci->RoutedHost(), ci->RoutedPort())); + + nsCOMPtr routedSTS(do_QueryInterface(sts)); + if (routedSTS) { + rv = routedSTS->CreateRoutedTransport( + socketTypes, typeCount, + ci->GetOrigin(), ci->OriginPort(), ci->GetRoutedHost(), ci->RoutedPort(), + ci->ProxyInfo(), getter_AddRefs(socketTransport)); + } else { + if (!ci->GetRoutedHost().IsEmpty()) { + // There is a route requested, but the legacy nsISocketTransportService + // can't handle it. + // Origin should be reachable on origin host name, so this should + // not be a problem - but log it. + LOG(("nsHalfOpenSocket this=%p using legacy nsISocketTransportService " + "means explicit route %s:%d will be ignored.\n", this, + ci->RoutedHost(), ci->RoutedPort())); + } + + rv = sts->CreateTransport(socketTypes, typeCount, + ci->GetOrigin(), ci->OriginPort(), + ci->ProxyInfo(), + getter_AddRefs(socketTransport)); + } NS_ENSURE_SUCCESS(rv, rv); uint32_t tmpFlags = 0; @@ -3142,9 +3175,13 @@ nsHalfOpenSocket::SetupStreams(nsISocketTransport **transport, if (mCaps & NS_HTTP_LOAD_ANONYMOUS) tmpFlags |= nsISocketTransport::ANONYMOUS_CONNECT; - if (mEnt->mConnInfo->GetPrivate()) + if (ci->GetPrivate()) tmpFlags |= nsISocketTransport::NO_PERMANENT_STORAGE; + if (bypassTLSAuth) { + tmpFlags |= nsISocketTransport::MITM_OK; + } + // For backup connections, we disable IPv6. That's because some users have // broken IPv6 connectivity (leading to very long timeouts), and disabling // IPv6 on the backup connection gives them a much better user experience @@ -3166,8 +3203,8 @@ nsHalfOpenSocket::SetupStreams(nsISocketTransport **transport, socketTransport->SetQoSBits(gHttpHandler->GetQoSBits()); - if (!mEnt->mConnInfo->GetNetworkInterfaceId().IsEmpty()) { - socketTransport->SetNetworkInterfaceId(mEnt->mConnInfo->GetNetworkInterfaceId()); + if (!ci->GetNetworkInterfaceId().IsEmpty()) { + socketTransport->SetNetworkInterfaceId(ci->GetNetworkInterfaceId()); } rv = socketTransport->SetEventSink(this, nullptr); @@ -3212,7 +3249,7 @@ nsHttpConnectionMgr::nsHalfOpenSocket::SetupPrimaryStreams() getter_AddRefs(mStreamOut), false); LOG(("nsHalfOpenSocket::SetupPrimaryStream [this=%p ent=%s rv=%x]", - this, mEnt->mConnInfo->Host(), rv)); + this, mEnt->mConnInfo->Origin(), rv)); if (NS_FAILED(rv)) { if (mStreamOut) mStreamOut->AsyncWait(nullptr, 0, 0, nullptr); @@ -3234,7 +3271,7 @@ nsHttpConnectionMgr::nsHalfOpenSocket::SetupBackupStreams() getter_AddRefs(mBackupStreamOut), true); LOG(("nsHalfOpenSocket::SetupBackupStream [this=%p ent=%s rv=%x]", - this, mEnt->mConnInfo->Host(), rv)); + this, mEnt->mConnInfo->Origin(), rv)); if (NS_FAILED(rv)) { if (mBackupStreamOut) mBackupStreamOut->AsyncWait(nullptr, 0, 0, nullptr); @@ -3288,7 +3325,7 @@ void nsHttpConnectionMgr::nsHalfOpenSocket::Abandon() { LOG(("nsHalfOpenSocket::Abandon [this=%p ent=%s]", - this, mEnt->mConnInfo->Host())); + this, mEnt->mConnInfo->Origin())); MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread); @@ -3361,7 +3398,7 @@ nsHalfOpenSocket::OnOutputStreamReady(nsIAsyncOutputStream *out) MOZ_ASSERT(out == mStreamOut || out == mBackupStreamOut, "stream mismatch"); LOG(("nsHalfOpenSocket::OnOutputStreamReady [this=%p ent=%s %s]\n", - this, mEnt->mConnInfo->Host(), + this, mEnt->mConnInfo->Origin(), out == mStreamOut ? "primary" : "backup")); int32_t index; nsresult rv; @@ -3540,10 +3577,10 @@ nsHttpConnectionMgr::nsHalfOpenSocket::OnTransportStatus(nsITransport *trans, } else { newKey->AppendLiteral("~.:"); } - newKey->AppendInt(mEnt->mConnInfo->Port()); + newKey->AppendInt(mEnt->mConnInfo->OriginPort()); LOG(("nsHttpConnectionMgr::nsHalfOpenSocket::OnTransportStatus " "STATUS_CONNECTING_TO Established New Coalescing Key # %d for host " - "%s [%s]", i, mEnt->mConnInfo->Host(), newKey->get())); + "%s [%s]", i, mEnt->mConnInfo->Origin(), newKey->get())); } gHttpHandler->ConnMgr()->ProcessSpdyPendingQ(mEnt); } @@ -3690,7 +3727,7 @@ nsConnectionEntry::OnPipelineFeedbackInfo( if (mPipelineState == PS_GREEN && info == GoodCompletedOK) { int32_t depth = data; LOG(("Transaction completed at pipeline depth of %d. Host = %s\n", - depth, mConnInfo->Host())); + depth, mConnInfo->Origin())); if (depth >= 3) mGreenDepth = kPipelineUnlimited; @@ -3718,7 +3755,7 @@ nsConnectionEntry::OnPipelineFeedbackInfo( else if (info & kPipelineInfoTypeBad) { if ((info & kPipelineInfoTypeRed) && (mPipelineState != PS_RED)) { LOG(("transition to red from %d. Host = %s.\n", - mPipelineState, mConnInfo->Host())); + mPipelineState, mConnInfo->Origin())); mPipelineState = PS_RED; mPipeliningPenalty = 0; } @@ -3773,7 +3810,7 @@ nsConnectionEntry::OnPipelineFeedbackInfo( std::min(mPipeliningClassPenalty[classification], kPenalty); LOG(("Assessing red penalty to %s class %d for event %d. " - "Penalty now %d, throttle[%d] = %d\n", mConnInfo->Host(), + "Penalty now %d, throttle[%d] = %d\n", mConnInfo->Origin(), classification, info, mPipeliningPenalty, classification, mPipeliningClassPenalty[classification])); } @@ -3787,7 +3824,7 @@ nsConnectionEntry::OnPipelineFeedbackInfo( if (mPipelineState == PS_RED && !mPipeliningPenalty) { - LOG(("transition %s to yellow\n", mConnInfo->Host())); + LOG(("transition %s to yellow\n", mConnInfo->Origin())); mPipelineState = PS_YELLOW; mYellowConnection = nullptr; } @@ -3809,7 +3846,7 @@ nsConnectionEntry::OnYellowComplete() { if (mPipelineState == PS_YELLOW) { if (mYellowGoodEvents && !mYellowBadEvents) { - LOG(("transition %s to green\n", mConnInfo->Host())); + LOG(("transition %s to green\n", mConnInfo->Origin())); mPipelineState = PS_GREEN; mGreenDepth = mInitialGreenDepth; } @@ -3819,7 +3856,7 @@ nsConnectionEntry::OnYellowComplete() // kind of negative feedback before opening the flood gates. // If we haven't confirmed that, then transfer back to red. LOG(("transition %s to red from yellow return\n", - mConnInfo->Host())); + mConnInfo->Origin())); mPipelineState = PS_RED; } } @@ -3870,7 +3907,7 @@ nsConnectionEntry::CreditPenalty() if (mPipelineState == PS_RED && !mPipeliningPenalty) { LOG(("transition %s to yellow based on time credit\n", - mConnInfo->Host())); + mConnInfo->Origin())); mPipelineState = PS_YELLOW; mYellowConnection = nullptr; } @@ -3901,8 +3938,8 @@ nsHttpConnectionMgr::ReadConnectionEntry(const nsACString &key, nsTArray *args = static_cast *> (aArg); HttpRetParams data; - data.host = ent->mConnInfo->Host(); - data.port = ent->mConnInfo->Port(); + data.host = ent->mConnInfo->Origin(); + data.port = ent->mConnInfo->OriginPort(); for (uint32_t i = 0; i < ent->mActiveConns.Length(); i++) { HttpConnInfo info; info.ttl = ent->mActiveConns[i]->TimeToLive(); diff --git a/netwerk/protocol/http/nsHttpTransaction.cpp b/netwerk/protocol/http/nsHttpTransaction.cpp index 445da20d13d1..0321ded49ff9 100644 --- a/netwerk/protocol/http/nsHttpTransaction.cpp +++ b/netwerk/protocol/http/nsHttpTransaction.cpp @@ -1181,7 +1181,7 @@ nsHttpTransaction::Restart() mCaps &= ~NS_HTTP_ALLOW_PIPELINING; SetPipelinePosition(0); - if (!mConnInfo->GetAuthenticationHost().IsEmpty()) { + if (!mConnInfo->GetRoutedHost().IsEmpty()) { MutexAutoLock lock(*nsHttp::GetLock()); nsRefPtr ci; mConnInfo->CloneAsDirectRoute(getter_AddRefs(ci)); diff --git a/netwerk/socket/nsISSLSocketControl.idl b/netwerk/socket/nsISSLSocketControl.idl index be06b68280b0..eaf3508145d9 100644 --- a/netwerk/socket/nsISSLSocketControl.idl +++ b/netwerk/socket/nsISSLSocketControl.idl @@ -15,7 +15,7 @@ class nsCString; %} [ref] native nsCStringTArrayRef(nsTArray); -[scriptable, builtinclass, uuid(c6acb521-df47-49aa-b9e8-51c4e984968a)] +[scriptable, builtinclass, uuid(418265c8-654e-4fbb-ba62-4eed27de1f03)] interface nsISSLSocketControl : nsISupports { attribute nsIInterfaceRequestor notificationCallbacks; @@ -108,18 +108,10 @@ interface nsISSLSocketControl : nsISupports { attribute nsIX509Cert clientCert; /** - * If you wish to verify the host certificate using a different name than - * was used for the tcp connection, but without using proxy semantics, you - * can set authenticationName and authenticationPort - */ - attribute ACString authenticationName; - [infallible] attribute long authenticationPort; - - /** - * set bypassAuthentication to true if the server certificate checks should + * bypassAuthentication is true if the server certificate checks are * not be enforced. This is to enable non-secure transport over TLS. */ - [infallible] attribute boolean bypassAuthentication; + [infallible] readonly attribute boolean bypassAuthentication; /* * failedVerification is true if any enforced certificate checks have failed. diff --git a/netwerk/socket/nsISocketProvider.idl b/netwerk/socket/nsISocketProvider.idl index 57f6c4d7060a..ccd97c4805d6 100644 --- a/netwerk/socket/nsISocketProvider.idl +++ b/netwerk/socket/nsISocketProvider.idl @@ -19,9 +19,9 @@ interface nsISocketProvider : nsISupports * @param aFamily * The address family for this socket (PR_AF_INET or PR_AF_INET6). * @param aHost - * The hostname for this connection. + * The origin hostname for this connection. * @param aPort - * The port for this connection. + * The origin port for this connection. * @param aProxyHost * If non-null, the proxy hostname for this connection. * @param aProxyPort @@ -91,6 +91,13 @@ interface nsISocketProvider : nsISupports * connections to share state with each other. */ const unsigned long NO_PERMANENT_STORAGE = 1 << 2; + + /** + * This flag is an explicit opt-in that allows a normally secure socket + * provider to use, at its discretion, an insecure algorithm. e.g. + * a TLS socket without authentication. + */ + const unsigned long MITM_OK = 1 << 3; }; %{C++ diff --git a/netwerk/test/unit/test_http2.js b/netwerk/test/unit/test_http2.js index 6f13b0c619c2..0ef1d3af36d7 100644 --- a/netwerk/test/unit/test_http2.js +++ b/netwerk/test/unit/test_http2.js @@ -769,7 +769,7 @@ var tests = [ test_http2_post_big , test_http2_push2 , test_http2_push3 , test_http2_push4 - // , test_http2_altsvc + , test_http2_altsvc , test_http2_doubleheader , test_http2_xhr , test_http2_header diff --git a/security/manager/ssl/src/nsNSSIOLayer.cpp b/security/manager/ssl/src/nsNSSIOLayer.cpp index 083f97055523..2811b0da972c 100644 --- a/security/manager/ssl/src/nsNSSIOLayer.cpp +++ b/security/manager/ssl/src/nsNSSIOLayer.cpp @@ -191,13 +191,6 @@ nsNSSSocketInfo::GetBypassAuthentication(bool* arg) return NS_OK; } -NS_IMETHODIMP -nsNSSSocketInfo::SetBypassAuthentication(bool arg) -{ - mBypassAuthentication = arg; - return NS_OK; -} - NS_IMETHODIMP nsNSSSocketInfo::GetFailedVerification(bool* arg) { @@ -205,31 +198,6 @@ nsNSSSocketInfo::GetFailedVerification(bool* arg) return NS_OK; } -NS_IMETHODIMP -nsNSSSocketInfo::GetAuthenticationName(nsACString& aAuthenticationName) -{ - aAuthenticationName = GetHostName(); - return NS_OK; -} - -NS_IMETHODIMP -nsNSSSocketInfo::SetAuthenticationName(const nsACString& aAuthenticationName) -{ - return SetHostName(PromiseFlatCString(aAuthenticationName).get()); -} - -NS_IMETHODIMP -nsNSSSocketInfo::GetAuthenticationPort(int32_t* aAuthenticationPort) -{ - return GetPort(aAuthenticationPort); -} - -NS_IMETHODIMP -nsNSSSocketInfo::SetAuthenticationPort(int32_t aAuthenticationPort) -{ - return SetPort(aAuthenticationPort); -} - NS_IMETHODIMP nsNSSSocketInfo::GetRememberClientAuthCertificate(bool* aRemember) { @@ -445,6 +413,12 @@ nsNSSSocketInfo::JoinConnection(const nsACString& npnProtocol, if (!mNPNCompleted || !mNegotiatedNPN.Equals(npnProtocol)) return NS_OK; + if (mBypassAuthentication) { + // An unauthenticated connection does not know whether or not it + // is acceptable for a particular hostname + return NS_OK; + } + IsAcceptableForHost(hostname, _retval); if (*_retval) { @@ -2497,6 +2471,11 @@ nsSSLIOLayerImportFD(PRFileDesc* fd, (SSLGetClientAuthData) nsNSS_SSLGetClientAuthData, infoObject); } + if (flags & nsISocketProvider::MITM_OK) { + PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, + ("[%p] nsSSLIOLayerImportFD: bypass authentication flag\n", fd)); + infoObject->SetBypassAuthentication(true); + } if (SECSuccess != SSL_AuthCertificateHook(sslSock, AuthCertificateHook, infoObject)) { NS_NOTREACHED("failed to configure AuthCertificateHook"); @@ -2586,6 +2565,9 @@ nsSSLIOLayerSetOptions(PRFileDesc* fd, bool forSTARTTLS, if (flags & nsISocketProvider::NO_PERMANENT_STORAGE) { peerId.AppendLiteral("private:"); } + if (flags & nsISocketProvider::MITM_OK) { + peerId.AppendLiteral("bypassAuth:"); + } peerId.Append(host); peerId.Append(':'); peerId.AppendInt(port); diff --git a/security/manager/ssl/src/nsNSSIOLayer.h b/security/manager/ssl/src/nsNSSIOLayer.h index 4eed0afdb1f6..80f691cd15ac 100644 --- a/security/manager/ssl/src/nsNSSIOLayer.h +++ b/security/manager/ssl/src/nsNSSIOLayer.h @@ -97,6 +97,13 @@ public: void SetKEAKeyBits(uint32_t keaBits) { mKEAKeyBits = keaBits; } + void SetBypassAuthentication(bool val) + { + if (!mHandshakeCompleted) { + mBypassAuthentication = val; + } + } + void SetSSLVersionUsed(int16_t version) { mSSLVersionUsed = version; @@ -112,14 +119,6 @@ public: return result; } - inline int32_t GetAuthenticationPort() - { - int32_t result = -1; - mozilla::DebugOnly rv = GetAuthenticationPort(&result); - MOZ_ASSERT(NS_SUCCEEDED(rv)); - return result; - } - protected: virtual ~nsNSSSocketInfo();