Bug 853423 - Block speculative connections for local IP addresses r=mcmanus

This commit is contained in:
Steve Workman 2013-11-10 22:59:40 -08:00
parent 0370194b66
commit 531e509b8a
8 changed files with 94 additions and 3 deletions

View File

@ -18,4 +18,4 @@
# Modifying this file will now automatically clobber the buildbot machines \o/ # Modifying this file will now automatically clobber the buildbot machines \o/
# #
Bug 906990 needs a clobber because of bug 928195 Bug 853423 - New code (inc. new function IsIPAddrLocal) is not being included in incremental builds.

View File

@ -176,6 +176,12 @@ interface nsISocketTransport : nsITransport
*/ */
const unsigned long DISABLE_IPV4 = (1 << 4); const unsigned long DISABLE_IPV4 = (1 << 4);
/**
* If set, indicates that the socket should not connect if the hostname
* resolves to an RFC1918 address or IPv6 equivalent.
*/
const unsigned long DISABLE_RFC1918 = (1 << 5);
/** /**
* Socket QoS/ToS markings. Valid values are IPTOS_DSCP_AFxx or * Socket QoS/ToS markings. Valid values are IPTOS_DSCP_AFxx or
* IPTOS_CLASS_CSx (or IPTOS_DSCP_EF, but currently no supported * IPTOS_CLASS_CSx (or IPTOS_DSCP_EF, but currently no supported

View File

@ -1161,6 +1161,28 @@ nsSocketTransport::InitiateSocket()
return NS_ERROR_OFFLINE; return NS_ERROR_OFFLINE;
} }
// Hosts/Proxy Hosts that are Local IP Literals should not be speculatively
// connected - Bug 853423.
if (mConnectionFlags & nsISocketTransport::DISABLE_RFC1918 &&
IsIPAddrLocal(&mNetAddr)) {
#ifdef PR_LOGGING
if (SOCKET_LOG_ENABLED()) {
nsAutoCString netAddrCString;
netAddrCString.SetCapacity(kIPv6CStrBufSize);
if (!NetAddrToString(&mNetAddr,
netAddrCString.BeginWriting(),
kIPv6CStrBufSize))
netAddrCString = NS_LITERAL_CSTRING("<IP-to-string failed>");
SOCKET_LOG(("nsSocketTransport::InitiateSocket skipping "
"speculative connection for host [%s:%d] proxy "
"[%s:%d] with Local IP address [%s]",
mHost.get(), mPort, mProxyHost.get(), mProxyPort,
netAddrCString.get()));
}
#endif
return NS_ERROR_CONNECTION_REFUSED;
}
// //
// find out if it is going to be ok to attach another socket to the STS. // find out if it is going to be ok to attach another socket to the STS.
// if not then we have to wait for the STS to tell us that it is ok. // if not then we have to wait for the STS to tell us that it is ok.

View File

@ -177,6 +177,32 @@ bool IsIPAddrV4Mapped(const NetAddr *addr)
return false; return false;
} }
bool IsIPAddrLocal(const NetAddr *addr)
{
MOZ_ASSERT(addr);
// IPv4 RFC1918 and Link Local Addresses.
if (addr->raw.family == AF_INET) {
uint32_t addr32 = ntohl(addr->inet.ip);
if (addr32 >> 24 == 0x0A || // 10/8 prefix (RFC 1918).
addr32 >> 20 == 0xAC1 || // 172.16/12 prefix (RFC 1918).
addr32 >> 16 == 0xC0A8 || // 192.168/16 prefix (RFC 1918).
addr32 >> 16 == 0xA9FE) { // 169.254/16 prefix (Link Local).
return true;
}
}
// IPv6 Unique and Link Local Addresses.
if (addr->raw.family == AF_INET6) {
uint16_t addr16 = ntohs(addr->inet6.ip.u16[0]);
if (addr16 >> 9 == 0xfc >> 1 || // fc00::/7 Unique Local Address.
addr16 >> 6 == 0xfe80 >> 6) { // fe80::/10 Link Local Address.
return true;
}
}
// Not an IPv4/6 local address.
return false;
}
NetAddrElement::NetAddrElement(const PRNetAddr *prNetAddr) NetAddrElement::NetAddrElement(const PRNetAddr *prNetAddr)
{ {
PRNetAddrToNetAddr(prNetAddr, &mAddress); PRNetAddrToNetAddr(prNetAddr, &mAddress);

View File

@ -160,6 +160,8 @@ bool IsIPAddrAny(const NetAddr *addr);
bool IsIPAddrV4Mapped(const NetAddr *addr); bool IsIPAddrV4Mapped(const NetAddr *addr);
bool IsIPAddrLocal(const NetAddr *addr);
} // namespace net } // namespace net
} // namespace mozilla } // namespace mozilla

View File

@ -8,6 +8,10 @@
#include "HttpLog.h" #include "HttpLog.h"
#include "nsHttpConnectionInfo.h" #include "nsHttpConnectionInfo.h"
#include "mozilla/net/DNS.h"
#include "prnetdb.h"
using namespace mozilla::net;
nsHttpConnectionInfo::nsHttpConnectionInfo(const nsACString &host, int32_t port, nsHttpConnectionInfo::nsHttpConnectionInfo(const nsACString &host, int32_t port,
nsProxyInfo* proxyInfo, nsProxyInfo* proxyInfo,
@ -113,3 +117,19 @@ nsHttpConnectionInfo::UsingProxy()
return !mProxyInfo->IsDirect(); return !mProxyInfo->IsDirect();
} }
bool
nsHttpConnectionInfo::HostIsLocalIPLiteral() const
{
PRNetAddr prAddr;
// If the host/proxy host is not an IP address literal, return false.
if (ProxyHost()) {
if (PR_StringToNetAddr(ProxyHost(), &prAddr) != PR_SUCCESS) {
return false;
}
} else if (PR_StringToNetAddr(Host(), &prAddr) != PR_SUCCESS) {
return false;
}
NetAddr netAddr;
PRNetAddrToNetAddr(&prAddr, &netAddr);
return IsIPAddrLocal(&netAddr);
}

View File

@ -92,6 +92,9 @@ public:
// Returns true for any kind of proxy (http, socks, etc..) // Returns true for any kind of proxy (http, socks, etc..)
bool UsingProxy(); bool UsingProxy();
// Returns true when mHost is an RFC1918 literal.
bool HostIsLocalIPLiteral() const;
private: private:
mozilla::ThreadSafeAutoRefCnt mRef; mozilla::ThreadSafeAutoRefCnt mRef;
nsCString mHashKey; nsCString mHashKey;

View File

@ -357,6 +357,14 @@ nsHttpConnectionMgr::SpeculativeConnect(nsHttpConnectionInfo *ci,
LOG(("nsHttpConnectionMgr::SpeculativeConnect [ci=%s]\n", LOG(("nsHttpConnectionMgr::SpeculativeConnect [ci=%s]\n",
ci->HashKey().get())); ci->HashKey().get()));
// Hosts that are Local IP Literals should not be speculatively
// connected - Bug 853423.
if (ci && ci->HostIsLocalIPLiteral()) {
LOG(("nsHttpConnectionMgr::SpeculativeConnect skipping RFC1918 "
"address [%s]", ci->Host()));
return NS_OK;
}
nsRefPtr<SpeculativeConnectArgs> args = new SpeculativeConnectArgs(); nsRefPtr<SpeculativeConnectArgs> args = new SpeculativeConnectArgs();
// Wrap up the callbacks and the target to ensure they're released on the target // Wrap up the callbacks and the target to ensure they're released on the target
@ -1984,13 +1992,13 @@ nsHttpConnectionMgr::CreateTransport(nsConnectionEntry *ent,
MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread); MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);
nsRefPtr<nsHalfOpenSocket> sock = new nsHalfOpenSocket(ent, trans, caps); nsRefPtr<nsHalfOpenSocket> sock = new nsHalfOpenSocket(ent, trans, caps);
if (speculative)
sock->SetSpeculative(true);
nsresult rv = sock->SetupPrimaryStreams(); nsresult rv = sock->SetupPrimaryStreams();
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
ent->mHalfOpens.AppendElement(sock); ent->mHalfOpens.AppendElement(sock);
mNumHalfOpenConns++; mNumHalfOpenConns++;
if (speculative)
sock->SetSpeculative(true);
return NS_OK; return NS_OK;
} }
@ -2711,6 +2719,10 @@ nsHalfOpenSocket::SetupStreams(nsISocketTransport **transport,
tmpFlags |= nsISocketTransport::DISABLE_IPV6; tmpFlags |= nsISocketTransport::DISABLE_IPV6;
} }
if (IsSpeculative()) {
tmpFlags |= nsISocketTransport::DISABLE_RFC1918;
}
socketTransport->SetConnectionFlags(tmpFlags); socketTransport->SetConnectionFlags(tmpFlags);
socketTransport->SetQoSBits(gHttpHandler->GetQoSBits()); socketTransport->SetQoSBits(gHttpHandler->GetQoSBits());