commit 8a68f975ee5faa39efa26a79062476ab50dd18ab Author: Patrick McManus mcmanus@ducksong.com Date: Tue May 22 13:50:56 2018 -0400
Bug 1463509 - SOCKS support for Alternative Services r=valentin
MozReview-Commit-ID: 1oXnQuzOqsC
--HG-- extra : rebase_source : 84bfaec48c5fc216da6586e7f06f118292d3fb17 --- netwerk/base/nsSocketTransport2.cpp | 32 +++++++++++++++++++++-------- netwerk/protocol/http/AlternateServices.cpp | 8 +++++++- netwerk/protocol/http/AlternateServices.h | 4 ++++ netwerk/protocol/http/nsHttpChannel.cpp | 5 ++--- 4 files changed, 37 insertions(+), 12 deletions(-)
diff --git a/netwerk/base/nsSocketTransport2.cpp b/netwerk/base/nsSocketTransport2.cpp index df01e62f55d3..aa9232f4698c 100644 --- a/netwerk/base/nsSocketTransport2.cpp +++ b/netwerk/base/nsSocketTransport2.cpp @@ -1170,7 +1170,7 @@ nsSocketTransport::BuildSocket(PRFileDesc *&fd, bool &proxyTransparent, bool &us uint32_t controlFlags = 0;
uint32_t i; - for (i=0; i<mTypeCount; ++i) { + for (i = 0; i < mTypeCount; ++i) { nsCOMPtr<nsISocketProvider> provider;
SOCKET_LOG((" pushing io layer [%u:%s]\n", i, mTypes[i])); @@ -1199,12 +1199,30 @@ nsSocketTransport::BuildSocket(PRFileDesc *&fd, bool &proxyTransparent, bool &us // if this is the first type, we'll want the // service to allocate a new socket
+ // Most layers _ESPECIALLY_ PSM want the origin name here as they + // will use it for secure checks, etc.. and any connection management + // differences between the origin name and the routed name can be + // taken care of via DNS. However, SOCKS is a special case as there is + // no DNS. in the case of SOCKS and PSM the PSM is a separate layer + // and receives the origin name. + const char *socketProviderHost = host; + int32_t socketProviderPort = port; + if (mProxyTransparentResolvesHost && + (!strcmp(mTypes[0], "socks") || !strcmp(mTypes[0], "socks4"))) { + SOCKET_LOG(("SOCKS %d Host/Route override: %s:%d -> %s:%d\n", + mHttpsProxy, + socketProviderHost, socketProviderPort, + mHost.get(), mPort)); + socketProviderHost = mHost.get(); + socketProviderPort = mPort; + } + // when https proxying we want to just connect to the proxy as if // it were the end host (i.e. expect the proxy's cert)
rv = provider->NewSocket(mNetAddr.raw.family, - mHttpsProxy ? mProxyHost.get() : host, - mHttpsProxy ? mProxyPort : port, + mHttpsProxy ? mProxyHost.get() : socketProviderHost, + mHttpsProxy ? mProxyPort : socketProviderPort, proxyInfo, mOriginAttributes, controlFlags, mTlsFlags, &fd, getter_AddRefs(secinfo)); @@ -1213,8 +1231,7 @@ nsSocketTransport::BuildSocket(PRFileDesc *&fd, bool &proxyTransparent, bool &us NS_NOTREACHED("NewSocket succeeded but failed to create a PRFileDesc"); rv = NS_ERROR_UNEXPECTED; } - } - else { + } else { // the socket has already been allocated, // so we just want the service to add itself // to the stack (such as pushing an io layer) @@ -1245,9 +1262,8 @@ nsSocketTransport::BuildSocket(PRFileDesc *&fd, bool &proxyTransparent, bool &us secCtrl->SetNotificationCallbacks(callbacks); // remember if socket type is SSL so we can ProxyStartSSL if need be. usingSSL = isSSL; - } - else if ((strcmp(mTypes[i], "socks") == 0) || - (strcmp(mTypes[i], "socks4") == 0)) { + } else if ((strcmp(mTypes[i], "socks") == 0) || + (strcmp(mTypes[i], "socks4") == 0)) { // since socks is transparent, any layers above // it do not have to worry about proxy stuff proxyInfo = nullptr; diff --git a/netwerk/protocol/http/AlternateServices.cpp b/netwerk/protocol/http/AlternateServices.cpp index 2ce3d333d60d..f4cfa800715b 100644 --- a/netwerk/protocol/http/AlternateServices.cpp +++ b/netwerk/protocol/http/AlternateServices.cpp @@ -46,6 +46,12 @@ SchemeIsHTTPS(const nsACString &originScheme, bool &outIsHTTPS) return NS_OK; }
+bool +AltSvcMapping::AcceptableProxy(nsProxyInfo *proxyInfo) +{ + return !proxyInfo || proxyInfo->IsDirect() || proxyInfo->IsSOCKS(); +} + void AltSvcMapping::ProcessHeader(const nsCString &buf, const nsCString &originScheme, const nsCString &originHost, int32_t originPort, @@ -59,7 +65,7 @@ AltSvcMapping::ProcessHeader(const nsCString &buf, const nsCString &originScheme return; }
- if (proxyInfo && !proxyInfo->IsDirect()) { + if (!AcceptableProxy(proxyInfo)) { LOG(("AltSvcMapping::ProcessHeader ignoring due to proxy\n")); return; } diff --git a/netwerk/protocol/http/AlternateServices.h b/netwerk/protocol/http/AlternateServices.h index 051f010801b4..688586ba5b89 100644 --- a/netwerk/protocol/http/AlternateServices.h +++ b/netwerk/protocol/http/AlternateServices.h @@ -66,6 +66,10 @@ public: nsIInterfaceRequestor *callbacks, nsProxyInfo *proxyInfo, uint32_t caps, const OriginAttributes &originAttributes);
+ // AcceptableProxy() decides whether a particular proxy configuration (pi) is suitable + // for use with Alt-Svc. No proxy (including a null pi) is suitable. + static bool AcceptableProxy(nsProxyInfo *pi); + const nsCString &AlternateHost() const { return mAlternateHost; } const nsCString &OriginHost() const { return mOriginHost; } uint32_t OriginPort() const { return mOriginPort; } diff --git a/netwerk/protocol/http/nsHttpChannel.cpp b/netwerk/protocol/http/nsHttpChannel.cpp index 28ff7709863e..35b4b4dfeb1e 100644 --- a/netwerk/protocol/http/nsHttpChannel.cpp +++ b/netwerk/protocol/http/nsHttpChannel.cpp @@ -6163,9 +6163,8 @@ nsHttpChannel::BeginConnect() RefPtr<AltSvcMapping> mapping; if (!mConnectionInfo && mAllowAltSvc && // per channel !(mLoadFlags & LOAD_FRESH_CONNECTION) && - (scheme.EqualsLiteral("http") || - scheme.EqualsLiteral("https")) && - (!proxyInfo || proxyInfo->IsDirect()) && + AltSvcMapping::AcceptableProxy(proxyInfo) && + (scheme.EqualsLiteral("http") || scheme.EqualsLiteral("https")) && (mapping = gHttpHandler->GetAltServiceMapping(scheme, host, port, mPrivateBrowsing,