Bug 1578186 - Add fuzzing support for HTTP2 proxy. r=mayhemer

Differential Revision: https://phabricator.services.mozilla.com/D44374

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Christian Holler 2019-09-05 19:26:12 +00:00
parent ccd64f6d10
commit 77a280300f
2 changed files with 169 additions and 30 deletions

View File

@ -29,6 +29,11 @@
#include "mozilla/AutoRestore.h"
#include "mozilla/Mutex.h"
#if defined(FUZZING)
# include "FuzzySecurityInfo.h"
# include "mozilla/StaticPrefs_fuzzing.h"
#endif
namespace mozilla {
namespace net {
@ -84,11 +89,25 @@ TLSFilterTransaction::TLSFilterTransaction(nsAHttpTransaction* aWrapped,
mFD = PR_CreateIOLayerStub(sLayerIdentity, &sLayerMethods);
bool addTLSLayer = true;
#ifdef FUZZING
addTLSLayer = !StaticPrefs::fuzzing_necko_enabled();
if (!addTLSLayer) {
SOCKET_LOG(("Skipping TLS layer in TLSFilterTransaction for fuzzing.\n"));
mSecInfo = static_cast<nsISupports*>(
static_cast<nsISSLSocketControl*>(new FuzzySecurityInfo()));
}
#endif
if (provider && mFD) {
mFD->secret = reinterpret_cast<PRFilePrivate*>(this);
provider->AddToSocket(PR_AF_INET, aTLSHost, aTLSPort, nullptr,
OriginAttributes(), 0, 0, mFD,
getter_AddRefs(mSecInfo));
if (addTLSLayer) {
provider->AddToSocket(PR_AF_INET, aTLSHost, aTLSPort, nullptr,
OriginAttributes(), 0, 0, mFD,
getter_AddRefs(mSecInfo));
}
}
if (mTransaction) {

View File

@ -1,3 +1,4 @@
#include "mozilla/LoadInfo.h"
#include "mozilla/Preferences.h"
#include "nsCOMPtr.h"
@ -5,7 +6,11 @@
#include "nsString.h"
#include "nsComponentManagerUtils.h"
#include "nsContentUtils.h"
#include "nsILoadInfo.h"
#include "nsIPrincipal.h"
#include "nsIProxiedProtocolHandler.h"
#include "nsIOService.h"
#include "nsProtocolProxyService.h"
#include "nsScriptSecurityManager.h"
#include "nsServiceManagerUtils.h"
#include "nsNetUtil.h"
@ -18,8 +23,10 @@
namespace mozilla {
namespace net {
// Used to determine if the fuzzing target should use https:// in spec.
static bool fuzzHttps = false;
// Target spec and optional proxy type to use, set by the respective
// initialization function so we can cover all combinations.
nsAutoCString spec;
nsAutoCString proxyType;
class FuzzingStreamListener final : public nsIStreamListener {
public:
@ -84,15 +91,49 @@ static int FuzzingInitNetworkHttp(int* argc, char*** argv) {
Preferences::SetBool("network.dns.native-is-localhost", true);
Preferences::SetBool("fuzzing.necko.enabled", true);
Preferences::SetInt("network.http.speculative-parallel-limit", 0);
Preferences::SetInt("network.http.spdy.default-concurrent", 1);
if (spec.IsEmpty()) {
spec = "http://127.0.0.1/";
}
return 0;
}
static int FuzzingInitNetworkHttp2(int* argc, char*** argv) {
fuzzHttps = true;
Preferences::SetInt("network.http.spdy.default-concurrent", 1);
spec = "https://127.0.0.1/";
return FuzzingInitNetworkHttp(argc, argv);
}
static int FuzzingInitNetworkHttpProxyHttp2(int* argc, char*** argv) {
// This is http over an https proxy
proxyType = "https";
return FuzzingInitNetworkHttp(argc, argv);
}
static int FuzzingInitNetworkHttp2ProxyHttp2(int* argc, char*** argv) {
// This is https over an https proxy
proxyType = "https";
return FuzzingInitNetworkHttp2(argc, argv);
}
static int FuzzingInitNetworkHttpProxyPlain(int* argc, char*** argv) {
// This is http over an http proxy
proxyType = "http";
return FuzzingInitNetworkHttp(argc, argv);
}
static int FuzzingInitNetworkHttp2ProxyPlain(int* argc, char*** argv) {
// This is https over an http proxy
proxyType = "http";
return FuzzingInitNetworkHttp2(argc, argv);
}
static int FuzzingRunNetworkHttp(const uint8_t* data, size_t size) {
// Set the data to be processed
setNetworkFuzzingBuffer(data, size);
@ -101,15 +142,8 @@ static int FuzzingRunNetworkHttp(const uint8_t* data, size_t size) {
{
nsCOMPtr<nsIURI> url;
nsAutoCString spec;
nsresult rv;
if (fuzzHttps) {
spec = "https://127.0.0.1/";
} else {
spec = "http://127.0.0.1/";
}
if (NS_NewURI(getter_AddRefs(url), spec) != NS_OK) {
MOZ_CRASH("Call to NS_NewURI failed.");
}
@ -122,20 +156,86 @@ static int FuzzingRunNetworkHttp(const uint8_t* data, size_t size) {
nsSecurityFlags secFlags;
secFlags = nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL |
nsILoadInfo::SEC_SANDBOXED;
nsCOMPtr<nsIChannel> channel;
rv = NS_NewChannel(getter_AddRefs(channel), url,
nsContentUtils::GetSystemPrincipal(), secFlags,
nsIContentPolicy::TYPE_INTERNAL_XMLHTTPREQUEST,
nullptr, // aCookieSettings
nullptr, // aPerformanceStorage
nullptr, // loadGroup
nullptr, // aCallbacks
loadFlags, // aLoadFlags
nullptr // aIoService
);
if (rv != NS_OK) {
MOZ_CRASH("Call to NS_NewChannel failed.");
nsCOMPtr<nsIChannel> channel;
nsCOMPtr<nsILoadInfo> loadInfo;
if (!proxyType.IsEmpty()) {
nsAutoCString proxyHost("127.0.0.2");
nsCOMPtr<nsIProtocolProxyService2> ps =
do_GetService(NS_PROTOCOLPROXYSERVICE_CID);
if (!ps) {
MOZ_CRASH("Failed to create nsIProtocolProxyService2");
}
mozilla::net::nsProtocolProxyService* pps =
static_cast<mozilla::net::nsProtocolProxyService*>(ps.get());
nsCOMPtr<nsIProxyInfo> proxyInfo;
rv = pps->NewProxyInfo(proxyType, proxyHost, 443,
EmptyCString(), // aProxyAuthorizationHeader
EmptyCString(), // aConnectionIsolationKey
0, // aFlags
UINT32_MAX, // aFailoverTimeout
nullptr, // aFailoverProxy
getter_AddRefs(proxyInfo));
if (NS_FAILED(rv)) {
MOZ_CRASH("Call to NewProxyInfo failed.");
}
nsCOMPtr<nsIIOService> ioService = do_GetIOService(&rv);
if (NS_FAILED(rv)) {
MOZ_CRASH("do_GetIOService failed.");
}
nsCOMPtr<nsIProtocolHandler> handler;
rv = ioService->GetProtocolHandler("http", getter_AddRefs(handler));
if (NS_FAILED(rv)) {
MOZ_CRASH("GetProtocolHandler failed.");
}
nsCOMPtr<nsIProxiedProtocolHandler> pph = do_QueryInterface(handler, &rv);
if (NS_FAILED(rv)) {
MOZ_CRASH("do_QueryInterface failed.");
}
loadInfo = new LoadInfo(
nsContentUtils::GetSystemPrincipal(), // loading principal
nsContentUtils::GetSystemPrincipal(), // triggering principal
nullptr, // Context
secFlags, nsIContentPolicy::TYPE_INTERNAL_XMLHTTPREQUEST);
rv = pph->NewProxiedChannel(url, proxyInfo,
0, // aProxyResolveFlags
nullptr, // aProxyURI
loadInfo, getter_AddRefs(channel));
if (NS_FAILED(rv)) {
MOZ_CRASH("Call to newProxiedChannel failed.");
}
} else {
rv = NS_NewChannel(getter_AddRefs(channel), url,
nsContentUtils::GetSystemPrincipal(), secFlags,
nsIContentPolicy::TYPE_INTERNAL_XMLHTTPREQUEST,
nullptr, // aCookieSettings
nullptr, // aPerformanceStorage
nullptr, // loadGroup
nullptr, // aCallbacks
loadFlags, // aLoadFlags
nullptr // aIoService
);
if (NS_FAILED(rv)) {
MOZ_CRASH("Call to NS_NewChannel failed.");
}
loadInfo = channel->LoadInfo();
}
if (NS_FAILED(loadInfo->SetSkipContentSniffing(true))) {
MOZ_CRASH("Failed to call SetSkipContentSniffing");
}
RefPtr<FuzzingStreamListener> gStreamListener;
@ -143,7 +243,7 @@ static int FuzzingRunNetworkHttp(const uint8_t* data, size_t size) {
gHttpChannel = do_QueryInterface(channel);
rv = gHttpChannel->SetRequestMethod(NS_LITERAL_CSTRING("GET"));
if (rv != NS_OK) {
if (NS_FAILED(rv)) {
MOZ_CRASH("SetRequestMethod on gHttpChannel failed.");
}
@ -151,15 +251,23 @@ static int FuzzingRunNetworkHttp(const uint8_t* data, size_t size) {
mozilla::net::RequestContextService::GetOrCreate();
nsCOMPtr<nsIRequestContext> rc;
rv = rcsvc->NewRequestContext(getter_AddRefs(rc));
if (rv != NS_OK) {
if (NS_FAILED(rv)) {
MOZ_CRASH("NewRequestContext failed.");
}
rv = gHttpChannel->SetRequestContextID(rc->GetID());
if (rv != NS_OK) {
if (NS_FAILED(rv)) {
MOZ_CRASH("SetRequestContextID on gHttpChannel failed.");
}
if (!proxyType.IsEmpty()) {
// NewProxiedChannel doesn't allow us to pass loadFlags directly
rv = gHttpChannel->SetLoadFlags(loadFlags);
if (rv != NS_OK) {
MOZ_CRASH("SetRequestMethod on gHttpChannel failed.");
}
}
gStreamListener = new FuzzingStreamListener();
gHttpChannel->AsyncOpen(gStreamListener);
@ -188,5 +296,17 @@ MOZ_FUZZING_INTERFACE_RAW(FuzzingInitNetworkHttp, FuzzingRunNetworkHttp,
MOZ_FUZZING_INTERFACE_RAW(FuzzingInitNetworkHttp2, FuzzingRunNetworkHttp,
NetworkHttp2);
MOZ_FUZZING_INTERFACE_RAW(FuzzingInitNetworkHttp2ProxyHttp2, FuzzingRunNetworkHttp,
NetworkHttp2ProxyHttp2);
MOZ_FUZZING_INTERFACE_RAW(FuzzingInitNetworkHttpProxyHttp2, FuzzingRunNetworkHttp,
NetworkHttpProxyHttp2);
MOZ_FUZZING_INTERFACE_RAW(FuzzingInitNetworkHttpProxyPlain, FuzzingRunNetworkHttp,
NetworkHttpProxyPlain);
MOZ_FUZZING_INTERFACE_RAW(FuzzingInitNetworkHttp2ProxyPlain, FuzzingRunNetworkHttp,
NetworkHttp2ProxyPlain);
} // namespace net
} // namespace mozilla