Bug 1463509 - SOCKS support for Alternative Services r=valentin
MozReview-Commit-ID: 1oXnQuzOqsC
--- a/netwerk/base/nsSocketTransport2.cpp
+++ b/netwerk/base/nsSocketTransport2.cpp
@@ -1156,17 +1156,17 @@ nsSocketTransport::BuildSocket(PRFileDes
// 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;
nsCOMPtr<nsIProxyInfo> proxyInfo = mProxyInfo;
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]));
rv = spserv->GetSocketProvider(mTypes[i], getter_AddRefs(provider));
if (NS_FAILED(rv))
break;
@@ -1185,32 +1185,49 @@ nsSocketTransport::BuildSocket(PRFileDes
if (mConnectionFlags & nsISocketTransport::BE_CONSERVATIVE)
controlFlags |= nsISocketProvider::BE_CONSERVATIVE;
nsCOMPtr<nsISupports> secinfo;
if (i == 0) {
// 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));
if (NS_SUCCEEDED(rv) && !fd) {
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)
rv = provider->AddToSocket(mNetAddr.raw.family,
host, port, proxyInfo,
mOriginAttributes, controlFlags, mTlsFlags, fd,
getter_AddRefs(secinfo));
}
@@ -1231,19 +1248,18 @@ nsSocketTransport::BuildSocket(PRFileDes
SOCKET_LOG((" [secinfo=%p callbacks=%p]\n", mSecInfo.get(), mCallbacks.get()));
}
// don't call into PSM while holding mLock!!
nsCOMPtr<nsISSLSocketControl> secCtrl(do_QueryInterface(secinfo));
if (secCtrl)
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;
proxyTransparent = true;
}
}
if (NS_FAILED(rv)) {
--- a/netwerk/protocol/http/AlternateServices.cpp
+++ b/netwerk/protocol/http/AlternateServices.cpp
@@ -41,30 +41,36 @@ SchemeIsHTTPS(const nsACString &originSc
if (!outIsHTTPS && !originScheme.EqualsLiteral("http")) {
MOZ_ASSERT(false, "unexpected scheme");
return NS_ERROR_UNEXPECTED;
}
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,
const nsACString &username, bool privateBrowsing,
nsIInterfaceRequestor *callbacks, nsProxyInfo *proxyInfo,
uint32_t caps, const OriginAttributes &originAttributes)
{
MOZ_ASSERT(NS_IsMainThread());
LOG(("AltSvcMapping::ProcessHeader: %s\n", buf.get()));
if (!callbacks) {
return;
}
- if (proxyInfo && !proxyInfo->IsDirect()) {
+ if (!AcceptableProxy(proxyInfo)) {
LOG(("AltSvcMapping::ProcessHeader ignoring due to proxy\n"));
return;
}
bool isHTTPS;
if (NS_FAILED(SchemeIsHTTPS(originScheme, isHTTPS))) {
return;
}
--- a/netwerk/protocol/http/AlternateServices.h
+++ b/netwerk/protocol/http/AlternateServices.h
@@ -61,16 +61,20 @@ public:
AltSvcMapping(DataStorage *storage, int32_t storageEpoch, const nsCString &serialized);
static void ProcessHeader(const nsCString &buf, const nsCString &originScheme,
const nsCString &originHost, int32_t originPort,
const nsACString &username, bool privateBrowsing,
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; }
const nsCString &HashKey() const { return mHashKey; }
uint32_t AlternatePort() const { return mAlternatePort; }
bool Validated() { return mValidated; }
int32_t GetExpiresAt() { return mExpiresAt; }
bool RouteEquals(AltSvcMapping *map);
--- a/netwerk/protocol/http/nsHttpChannel.cpp
+++ b/netwerk/protocol/http/nsHttpChannel.cpp
@@ -6177,19 +6177,18 @@ nsHttpChannel::BeginConnect()
SetDoNotTrack();
OriginAttributes originAttributes;
NS_GetOriginAttributes(this, originAttributes);
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,
originAttributes))) {
LOG(("nsHttpChannel %p Alt Service Mapping Found %s://%s:%d [%s]\n",
this, scheme.get(), mapping->AlternateHost().get(),
mapping->AlternatePort(), mapping->HashKey().get()));