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

This commit is contained in:
Steve Workman 2013-09-28 14:59:56 -07:00
parent 419addc4d6
commit 68ae0b0e0a
7 changed files with 91 additions and 0 deletions

View File

@ -176,6 +176,12 @@ interface nsISocketTransport : nsITransport
*/
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
* IPTOS_CLASS_CSx (or IPTOS_DSCP_EF, but currently no supported

View File

@ -1161,6 +1161,28 @@ nsSocketTransport::InitiateSocket()
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.
// 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;
}
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)
{
PRNetAddrToNetAddr(prNetAddr, &mAddress);

View File

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

View File

@ -8,6 +8,10 @@
#include "HttpLog.h"
#include "nsHttpConnectionInfo.h"
#include "mozilla/net/DNS.h"
#include "prnetdb.h"
using namespace mozilla::net;
nsHttpConnectionInfo::nsHttpConnectionInfo(const nsACString &host, int32_t port,
nsProxyInfo* proxyInfo,
@ -113,3 +117,19 @@ nsHttpConnectionInfo::UsingProxy()
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..)
bool UsingProxy();
// Returns true when mHost is an RFC1918 literal.
bool HostIsLocalIPLiteral() const;
private:
mozilla::ThreadSafeAutoRefCnt mRef;
nsCString mHashKey;

View File

@ -326,6 +326,14 @@ nsHttpConnectionMgr::SpeculativeConnect(nsHttpConnectionInfo *ci,
LOG(("nsHttpConnectionMgr::SpeculativeConnect [ci=%s]\n",
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;
}
// Wrap up the callbacks and the target to ensure they're released on the target
// thread properly.
nsCOMPtr<nsIInterfaceRequestor> wrappedCallbacks;
@ -2654,6 +2662,10 @@ nsHalfOpenSocket::SetupStreams(nsISocketTransport **transport,
tmpFlags |= nsISocketTransport::DISABLE_IPV6;
}
if (IsSpeculative()) {
tmpFlags |= nsISocketTransport::DISABLE_RFC1918;
}
socketTransport->SetConnectionFlags(tmpFlags);
socketTransport->SetQoSBits(gHttpHandler->GetQoSBits());