TestHttpFuzzing.cpp (9773B)
1 #include "mozilla/LoadInfo.h" 2 #include "mozilla/Preferences.h" 3 #include "mozilla/SpinEventLoopUntil.h" 4 5 #include "nsCOMPtr.h" 6 #include "nsNetCID.h" 7 #include "nsString.h" 8 #include "nsComponentManagerUtils.h" 9 #include "nsContentUtils.h" 10 #include "nsIChannel.h" 11 #include "nsIHttpChannel.h" 12 #include "nsILoadInfo.h" 13 #include "nsIProxiedProtocolHandler.h" 14 #include "nsIOService.h" 15 #include "nsProtocolProxyService.h" 16 #include "nsScriptSecurityManager.h" 17 #include "nsServiceManagerUtils.h" 18 #include "nsNetUtil.h" 19 #include "NullPrincipal.h" 20 #include "nsCycleCollector.h" 21 #include "RequestContextService.h" 22 #include "nsSandboxFlags.h" 23 24 #include "FuzzingInterface.h" 25 #include "FuzzingStreamListener.h" 26 #include "FuzzyLayer.h" 27 28 namespace mozilla { 29 namespace net { 30 31 // Target spec and optional proxy type to use, set by the respective 32 // initialization function so we can cover all combinations. 33 MOZ_RUNINIT static nsAutoCString httpSpec; 34 MOZ_RUNINIT static nsAutoCString proxyType; 35 static size_t minSize; 36 37 static int FuzzingInitNetworkHttp(int* argc, char*** argv) { 38 Preferences::SetBool("network.dns.native-is-localhost", true); 39 Preferences::SetBool("fuzzing.necko.enabled", true); 40 Preferences::SetInt("network.http.speculative-parallel-limit", 0); 41 Preferences::SetInt("network.http.http2.default-concurrent", 1); 42 43 if (httpSpec.IsEmpty()) { 44 httpSpec = "http://127.0.0.1/"; 45 } 46 47 net_EnsurePSMInit(); 48 49 return 0; 50 } 51 52 static int FuzzingInitNetworkHttp2(int* argc, char*** argv) { 53 httpSpec = "https://127.0.0.1/"; 54 return FuzzingInitNetworkHttp(argc, argv); 55 } 56 57 static int FuzzingInitNetworkHttp3(int* argc, char*** argv) { 58 Preferences::SetBool("fuzzing.necko.http3", true); 59 Preferences::SetBool("network.http.http3.enable", true); 60 Preferences::SetCString("network.http.http3.alt-svc-mapping-for-testing", 61 "fuzz.bad.tld;h3=:443"); 62 httpSpec = "https://fuzz.bad.tld/"; 63 minSize = 1200; 64 return FuzzingInitNetworkHttp(argc, argv); 65 } 66 67 static int FuzzingInitNetworkHttpProxyHttp2(int* argc, char*** argv) { 68 // This is http over an https proxy 69 proxyType = "https"; 70 71 return FuzzingInitNetworkHttp(argc, argv); 72 } 73 74 static int FuzzingInitNetworkHttp2ProxyHttp2(int* argc, char*** argv) { 75 // This is https over an https proxy 76 proxyType = "https"; 77 78 return FuzzingInitNetworkHttp2(argc, argv); 79 } 80 81 static int FuzzingInitNetworkHttpProxyPlain(int* argc, char*** argv) { 82 // This is http over an http proxy 83 proxyType = "http"; 84 85 return FuzzingInitNetworkHttp(argc, argv); 86 } 87 88 static int FuzzingInitNetworkHttp2ProxyPlain(int* argc, char*** argv) { 89 // This is https over an http proxy 90 proxyType = "http"; 91 92 return FuzzingInitNetworkHttp2(argc, argv); 93 } 94 95 static int FuzzingRunNetworkHttp(const uint8_t* data, size_t size) { 96 if (size < minSize) { 97 return 0; 98 } 99 100 // Set the data to be processed 101 addNetworkFuzzingBuffer(data, size); 102 103 nsWeakPtr channelRef; 104 105 nsCOMPtr<nsIRequestContextService> rcsvc = 106 mozilla::net::RequestContextService::GetOrCreate(); 107 uint64_t rcID; 108 109 { 110 nsCOMPtr<nsIURI> url; 111 nsresult rv; 112 113 if (NS_NewURI(getter_AddRefs(url), httpSpec) != NS_OK) { 114 MOZ_CRASH("Call to NS_NewURI failed."); 115 } 116 117 nsLoadFlags loadFlags; 118 loadFlags = nsIRequest::LOAD_BACKGROUND | nsIRequest::LOAD_BYPASS_CACHE | 119 nsIRequest::INHIBIT_CACHING | 120 nsIRequest::LOAD_FRESH_CONNECTION | 121 nsIChannel::LOAD_INITIAL_DOCUMENT_URI; 122 nsSecurityFlags secFlags; 123 secFlags = nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_SEC_CONTEXT_IS_NULL; 124 uint32_t sandboxFlags = SANDBOXED_ORIGIN; 125 126 nsCOMPtr<nsIChannel> channel; 127 nsCOMPtr<nsILoadInfo> loadInfo; 128 129 if (!proxyType.IsEmpty()) { 130 nsAutoCString proxyHost("127.0.0.2"); 131 132 nsCOMPtr<nsIProtocolProxyService2> ps = 133 do_GetService(NS_PROTOCOLPROXYSERVICE_CID); 134 if (!ps) { 135 MOZ_CRASH("Failed to create nsIProtocolProxyService2"); 136 } 137 138 mozilla::net::nsProtocolProxyService* pps = 139 static_cast<mozilla::net::nsProtocolProxyService*>(ps.get()); 140 141 nsCOMPtr<nsIProxyInfo> proxyInfo; 142 rv = pps->NewProxyInfo(proxyType, proxyHost, 443, 143 ""_ns, // aProxyAuthorizationHeader 144 ""_ns, // aConnectionIsolationKey 145 0, // aFlags 146 UINT32_MAX, // aFailoverTimeout 147 nullptr, // aFailoverProxy 148 getter_AddRefs(proxyInfo)); 149 150 if (NS_FAILED(rv)) { 151 MOZ_CRASH("Call to NewProxyInfo failed."); 152 } 153 154 nsCOMPtr<nsIIOService> ioService = do_GetIOService(&rv); 155 if (NS_FAILED(rv)) { 156 MOZ_CRASH("do_GetIOService failed."); 157 } 158 159 nsCOMPtr<nsIProtocolHandler> handler; 160 rv = ioService->GetProtocolHandler("http", getter_AddRefs(handler)); 161 if (NS_FAILED(rv)) { 162 MOZ_CRASH("GetProtocolHandler failed."); 163 } 164 165 nsCOMPtr<nsIProxiedProtocolHandler> pph = do_QueryInterface(handler, &rv); 166 if (NS_FAILED(rv)) { 167 MOZ_CRASH("do_QueryInterface failed."); 168 } 169 170 loadInfo = 171 LoadInfo::Create( 172 nsContentUtils::GetSystemPrincipal(), // loading principal 173 nsContentUtils::GetSystemPrincipal(), // triggering principal 174 nullptr, // Context 175 secFlags, nsIContentPolicy::TYPE_INTERNAL_XMLHTTPREQUEST_ASYNC, 176 Maybe<mozilla::dom::ClientInfo>(), 177 Maybe<mozilla::dom::ServiceWorkerDescriptor>(), sandboxFlags) 178 .unwrap(); 179 180 rv = pph->NewProxiedChannel(url, proxyInfo, 181 0, // aProxyResolveFlags 182 nullptr, // aProxyURI 183 loadInfo, getter_AddRefs(channel)); 184 185 if (NS_FAILED(rv)) { 186 MOZ_CRASH("Call to newProxiedChannel failed."); 187 } 188 } else { 189 rv = NS_NewChannel(getter_AddRefs(channel), url, 190 nsContentUtils::GetSystemPrincipal(), secFlags, 191 nsIContentPolicy::TYPE_INTERNAL_XMLHTTPREQUEST_ASYNC, 192 nullptr, // aCookieJarSettings 193 nullptr, // aPerformanceStorage 194 nullptr, // loadGroup 195 nullptr, // aCallbacks 196 loadFlags, // aLoadFlags 197 nullptr, // aIoService 198 sandboxFlags); 199 200 if (NS_FAILED(rv)) { 201 MOZ_CRASH("Call to NS_NewChannel failed."); 202 } 203 204 loadInfo = channel->LoadInfo(); 205 } 206 207 if (NS_FAILED(loadInfo->SetSkipContentSniffing(true))) { 208 MOZ_CRASH("Failed to call SetSkipContentSniffing"); 209 } 210 211 RefPtr<FuzzingStreamListener> gStreamListener; 212 nsCOMPtr<nsIHttpChannel> gHttpChannel; 213 214 gHttpChannel = do_QueryInterface(channel); 215 rv = gHttpChannel->SetRequestMethod("GET"_ns); 216 if (NS_FAILED(rv)) { 217 MOZ_CRASH("SetRequestMethod on gHttpChannel failed."); 218 } 219 220 nsCOMPtr<nsIRequestContext> rc; 221 rv = rcsvc->NewRequestContext(getter_AddRefs(rc)); 222 if (NS_FAILED(rv)) { 223 MOZ_CRASH("NewRequestContext failed."); 224 } 225 rcID = rc->GetID(); 226 227 rv = gHttpChannel->SetRequestContextID(rcID); 228 if (NS_FAILED(rv)) { 229 MOZ_CRASH("SetRequestContextID on gHttpChannel failed."); 230 } 231 232 if (!proxyType.IsEmpty()) { 233 // NewProxiedChannel doesn't allow us to pass loadFlags directly 234 rv = gHttpChannel->SetLoadFlags(loadFlags); 235 if (rv != NS_OK) { 236 MOZ_CRASH("SetRequestMethod on gHttpChannel failed."); 237 } 238 } 239 240 gStreamListener = new FuzzingStreamListener(); 241 gHttpChannel->AsyncOpen(gStreamListener); 242 243 // Wait for StopRequest 244 gStreamListener->waitUntilDone(); 245 246 bool mainPingBack = false; 247 248 NS_DispatchBackgroundTask(NS_NewRunnableFunction("Dummy", [&]() { 249 NS_DispatchToMainThread( 250 NS_NewRunnableFunction("Dummy", [&]() { mainPingBack = true; })); 251 })); 252 253 SpinEventLoopUntil("FuzzingRunNetworkHttp(mainPingBack)"_ns, 254 [&]() -> bool { return mainPingBack; }); 255 256 channelRef = do_GetWeakReference(gHttpChannel); 257 } 258 259 // Wait for the channel to be destroyed 260 SpinEventLoopUntil( 261 "FuzzingRunNetworkHttp(channel == nullptr)"_ns, [&]() -> bool { 262 nsCycleCollector_collect(CCReason::API, nullptr); 263 nsCOMPtr<nsIHttpChannel> channel = do_QueryReferent(channelRef); 264 return channel == nullptr; 265 }); 266 267 if (!signalNetworkFuzzingDone()) { 268 // Wait for the connection to indicate closed 269 SpinEventLoopUntil("FuzzingRunNetworkHttp(gFuzzingConnClosed)"_ns, 270 [&]() -> bool { return gFuzzingConnClosed; }); 271 } 272 273 rcsvc->RemoveRequestContext(rcID); 274 return 0; 275 } 276 277 MOZ_FUZZING_INTERFACE_RAW(FuzzingInitNetworkHttp, FuzzingRunNetworkHttp, 278 NetworkHttp); 279 280 MOZ_FUZZING_INTERFACE_RAW(FuzzingInitNetworkHttp2, FuzzingRunNetworkHttp, 281 NetworkHttp2); 282 283 MOZ_FUZZING_INTERFACE_RAW(FuzzingInitNetworkHttp3, FuzzingRunNetworkHttp, 284 NetworkHttp3); 285 286 MOZ_FUZZING_INTERFACE_RAW(FuzzingInitNetworkHttp2ProxyHttp2, 287 FuzzingRunNetworkHttp, NetworkHttp2ProxyHttp2); 288 289 MOZ_FUZZING_INTERFACE_RAW(FuzzingInitNetworkHttpProxyHttp2, 290 FuzzingRunNetworkHttp, NetworkHttpProxyHttp2); 291 292 MOZ_FUZZING_INTERFACE_RAW(FuzzingInitNetworkHttpProxyPlain, 293 FuzzingRunNetworkHttp, NetworkHttpProxyPlain); 294 295 MOZ_FUZZING_INTERFACE_RAW(FuzzingInitNetworkHttp2ProxyPlain, 296 FuzzingRunNetworkHttp, NetworkHttp2ProxyPlain); 297 298 } // namespace net 299 } // namespace mozilla