1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3  * License, v. 2.0. If a copy of the MPL was not distributed with this
4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 
6 #include "SocketProcessParent.h"
7 #include "SocketProcessLogging.h"
8 
9 #include "AltServiceParent.h"
10 #include "CachePushChecker.h"
11 #include "HttpTransactionParent.h"
12 #include "SocketProcessHost.h"
13 #include "mozilla/Components.h"
14 #include "mozilla/dom/MemoryReportRequest.h"
15 #include "mozilla/ipc/FileDescriptorSetParent.h"
16 #include "mozilla/ipc/IPCStreamAlloc.h"
17 #include "mozilla/ipc/PChildToParentStreamParent.h"
18 #include "mozilla/ipc/PParentToChildStreamParent.h"
19 #include "mozilla/net/DNSRequestParent.h"
20 #include "mozilla/net/ProxyConfigLookupParent.h"
21 #include "mozilla/RemoteLazyInputStreamParent.h"
22 #include "mozilla/Telemetry.h"
23 #include "mozilla/TelemetryIPC.h"
24 #include "nsIAppStartup.h"
25 #include "nsIHttpActivityObserver.h"
26 #include "nsIObserverService.h"
27 #include "nsNSSIOLayer.h"
28 #include "PSMIPCCommon.h"
29 #include "secerr.h"
30 #ifdef MOZ_WEBRTC
31 #  include "mozilla/dom/ContentProcessManager.h"
32 #  include "mozilla/dom/BrowserParent.h"
33 #  include "mozilla/net/WebrtcTCPSocketParent.h"
34 #endif
35 #if defined(MOZ_WIDGET_ANDROID)
36 #  include "mozilla/java/GeckoProcessManagerWrappers.h"
37 #  include "mozilla/java/GeckoProcessTypeWrappers.h"
38 #endif  // defined(MOZ_WIDGET_ANDROID)
39 
40 namespace mozilla {
41 namespace net {
42 
43 static SocketProcessParent* sSocketProcessParent;
44 
SocketProcessParent(SocketProcessHost * aHost)45 SocketProcessParent::SocketProcessParent(SocketProcessHost* aHost)
46     : mHost(aHost) {
47   MOZ_ASSERT(NS_IsMainThread());
48   MOZ_ASSERT(mHost);
49 
50   MOZ_COUNT_CTOR(SocketProcessParent);
51   sSocketProcessParent = this;
52 }
53 
~SocketProcessParent()54 SocketProcessParent::~SocketProcessParent() {
55   MOZ_ASSERT(NS_IsMainThread());
56 
57   MOZ_COUNT_DTOR(SocketProcessParent);
58   sSocketProcessParent = nullptr;
59 }
60 
61 /* static */
GetSingleton()62 SocketProcessParent* SocketProcessParent::GetSingleton() {
63   MOZ_ASSERT(NS_IsMainThread());
64 
65   return sSocketProcessParent;
66 }
67 
ActorDestroy(ActorDestroyReason aWhy)68 void SocketProcessParent::ActorDestroy(ActorDestroyReason aWhy) {
69 #if defined(MOZ_WIDGET_ANDROID)
70   nsCOMPtr<nsIEventTarget> launcherThread(ipc::GetIPCLauncher());
71   MOZ_ASSERT(launcherThread);
72 
73   auto procType = java::GeckoProcessType::SOCKET();
74   auto selector =
75       java::GeckoProcessManager::Selector::New(procType, OtherPid());
76 
77   launcherThread->Dispatch(NS_NewRunnableFunction(
78       "SocketProcessParent::ActorDestroy",
79       [selector = java::GeckoProcessManager::Selector::GlobalRef(selector)]() {
80         java::GeckoProcessManager::ShutdownProcess(selector);
81       }));
82 #endif  // defined(MOZ_WIDGET_ANDROID)
83 
84   if (aWhy == AbnormalShutdown) {
85     GenerateCrashReport(OtherPid());
86 
87     if (PR_GetEnv("MOZ_CRASHREPORTER_SHUTDOWN")) {
88       printf_stderr("Shutting down due to socket process crash.\n");
89       nsCOMPtr<nsIAppStartup> appService =
90           do_GetService("@mozilla.org/toolkit/app-startup;1");
91       if (appService) {
92         bool userAllowedQuit = true;
93         appService->Quit(nsIAppStartup::eForceQuit, 1, &userAllowedQuit);
94       }
95     }
96   }
97 
98   if (mHost) {
99     mHost->OnChannelClosed();
100   }
101 }
102 
SendRequestMemoryReport(const uint32_t & aGeneration,const bool & aAnonymize,const bool & aMinimizeMemoryUsage,const Maybe<ipc::FileDescriptor> & aDMDFile)103 bool SocketProcessParent::SendRequestMemoryReport(
104     const uint32_t& aGeneration, const bool& aAnonymize,
105     const bool& aMinimizeMemoryUsage,
106     const Maybe<ipc::FileDescriptor>& aDMDFile) {
107   mMemoryReportRequest = MakeUnique<dom::MemoryReportRequestHost>(aGeneration);
108 
109   PSocketProcessParent::SendRequestMemoryReport(
110       aGeneration, aAnonymize, aMinimizeMemoryUsage, aDMDFile,
111       [&](const uint32_t& aGeneration2) {
112         MOZ_ASSERT(gIOService);
113         if (!gIOService->SocketProcess()) {
114           return;
115         }
116         SocketProcessParent* actor = gIOService->SocketProcess()->GetActor();
117         if (!actor) {
118           return;
119         }
120         if (actor->mMemoryReportRequest) {
121           actor->mMemoryReportRequest->Finish(aGeneration2);
122           actor->mMemoryReportRequest = nullptr;
123         }
124       },
125       [&](mozilla::ipc::ResponseRejectReason) {
126         MOZ_ASSERT(gIOService);
127         if (!gIOService->SocketProcess()) {
128           return;
129         }
130         SocketProcessParent* actor = gIOService->SocketProcess()->GetActor();
131         if (!actor) {
132           return;
133         }
134         actor->mMemoryReportRequest = nullptr;
135       });
136 
137   return true;
138 }
139 
RecvAddMemoryReport(const MemoryReport & aReport)140 mozilla::ipc::IPCResult SocketProcessParent::RecvAddMemoryReport(
141     const MemoryReport& aReport) {
142   if (mMemoryReportRequest) {
143     mMemoryReportRequest->RecvReport(aReport);
144   }
145   return IPC_OK();
146 }
147 
RecvAccumulateChildHistograms(nsTArray<HistogramAccumulation> && aAccumulations)148 mozilla::ipc::IPCResult SocketProcessParent::RecvAccumulateChildHistograms(
149     nsTArray<HistogramAccumulation>&& aAccumulations) {
150   TelemetryIPC::AccumulateChildHistograms(Telemetry::ProcessID::Socket,
151                                           aAccumulations);
152   return IPC_OK();
153 }
154 
RecvAccumulateChildKeyedHistograms(nsTArray<KeyedHistogramAccumulation> && aAccumulations)155 mozilla::ipc::IPCResult SocketProcessParent::RecvAccumulateChildKeyedHistograms(
156     nsTArray<KeyedHistogramAccumulation>&& aAccumulations) {
157   TelemetryIPC::AccumulateChildKeyedHistograms(Telemetry::ProcessID::Socket,
158                                                aAccumulations);
159   return IPC_OK();
160 }
161 
RecvUpdateChildScalars(nsTArray<ScalarAction> && aScalarActions)162 mozilla::ipc::IPCResult SocketProcessParent::RecvUpdateChildScalars(
163     nsTArray<ScalarAction>&& aScalarActions) {
164   TelemetryIPC::UpdateChildScalars(Telemetry::ProcessID::Socket,
165                                    aScalarActions);
166   return IPC_OK();
167 }
168 
RecvUpdateChildKeyedScalars(nsTArray<KeyedScalarAction> && aScalarActions)169 mozilla::ipc::IPCResult SocketProcessParent::RecvUpdateChildKeyedScalars(
170     nsTArray<KeyedScalarAction>&& aScalarActions) {
171   TelemetryIPC::UpdateChildKeyedScalars(Telemetry::ProcessID::Socket,
172                                         aScalarActions);
173   return IPC_OK();
174 }
175 
RecvRecordChildEvents(nsTArray<mozilla::Telemetry::ChildEventData> && aEvents)176 mozilla::ipc::IPCResult SocketProcessParent::RecvRecordChildEvents(
177     nsTArray<mozilla::Telemetry::ChildEventData>&& aEvents) {
178   TelemetryIPC::RecordChildEvents(Telemetry::ProcessID::Socket, aEvents);
179   return IPC_OK();
180 }
181 
RecvRecordDiscardedData(const mozilla::Telemetry::DiscardedData & aDiscardedData)182 mozilla::ipc::IPCResult SocketProcessParent::RecvRecordDiscardedData(
183     const mozilla::Telemetry::DiscardedData& aDiscardedData) {
184   TelemetryIPC::RecordDiscardedData(Telemetry::ProcessID::Socket,
185                                     aDiscardedData);
186   return IPC_OK();
187 }
188 
AllocPWebrtcTCPSocketParent(const Maybe<TabId> & aTabId)189 PWebrtcTCPSocketParent* SocketProcessParent::AllocPWebrtcTCPSocketParent(
190     const Maybe<TabId>& aTabId) {
191 #ifdef MOZ_WEBRTC
192   WebrtcTCPSocketParent* parent = new WebrtcTCPSocketParent(aTabId);
193   parent->AddRef();
194   return parent;
195 #else
196   return nullptr;
197 #endif
198 }
199 
DeallocPWebrtcTCPSocketParent(PWebrtcTCPSocketParent * aActor)200 bool SocketProcessParent::DeallocPWebrtcTCPSocketParent(
201     PWebrtcTCPSocketParent* aActor) {
202 #ifdef MOZ_WEBRTC
203   WebrtcTCPSocketParent* parent = static_cast<WebrtcTCPSocketParent*>(aActor);
204   parent->Release();
205 #endif
206   return true;
207 }
208 
AllocPDNSRequestParent(const nsCString & aHost,const nsCString & aTrrServer,const uint16_t & aType,const OriginAttributes & aOriginAttributes,const uint32_t & aFlags)209 already_AddRefed<PDNSRequestParent> SocketProcessParent::AllocPDNSRequestParent(
210     const nsCString& aHost, const nsCString& aTrrServer, const uint16_t& aType,
211     const OriginAttributes& aOriginAttributes, const uint32_t& aFlags) {
212   RefPtr<DNSRequestHandler> handler = new DNSRequestHandler();
213   RefPtr<DNSRequestParent> actor = new DNSRequestParent(handler);
214   return actor.forget();
215 }
216 
RecvPDNSRequestConstructor(PDNSRequestParent * aActor,const nsCString & aHost,const nsCString & aTrrServer,const uint16_t & aType,const OriginAttributes & aOriginAttributes,const uint32_t & aFlags)217 mozilla::ipc::IPCResult SocketProcessParent::RecvPDNSRequestConstructor(
218     PDNSRequestParent* aActor, const nsCString& aHost,
219     const nsCString& aTrrServer, const uint16_t& aType,
220     const OriginAttributes& aOriginAttributes, const uint32_t& aFlags) {
221   RefPtr<DNSRequestParent> actor = static_cast<DNSRequestParent*>(aActor);
222   RefPtr<DNSRequestHandler> handler =
223       actor->GetDNSRequest()->AsDNSRequestHandler();
224   handler->DoAsyncResolve(aHost, aTrrServer, aType, aOriginAttributes, aFlags);
225   return IPC_OK();
226 }
227 
228 mozilla::ipc::PFileDescriptorSetParent*
AllocPFileDescriptorSetParent(const FileDescriptor & aFD)229 SocketProcessParent::AllocPFileDescriptorSetParent(const FileDescriptor& aFD) {
230   return new mozilla::ipc::FileDescriptorSetParent(aFD);
231 }
232 
DeallocPFileDescriptorSetParent(PFileDescriptorSetParent * aActor)233 bool SocketProcessParent::DeallocPFileDescriptorSetParent(
234     PFileDescriptorSetParent* aActor) {
235   delete static_cast<mozilla::ipc::FileDescriptorSetParent*>(aActor);
236   return true;
237 }
238 
239 mozilla::ipc::PChildToParentStreamParent*
AllocPChildToParentStreamParent()240 SocketProcessParent::AllocPChildToParentStreamParent() {
241   return mozilla::ipc::AllocPChildToParentStreamParent();
242 }
243 
DeallocPChildToParentStreamParent(PChildToParentStreamParent * aActor)244 bool SocketProcessParent::DeallocPChildToParentStreamParent(
245     PChildToParentStreamParent* aActor) {
246   delete aActor;
247   return true;
248 }
249 
250 mozilla::ipc::PParentToChildStreamParent*
AllocPParentToChildStreamParent()251 SocketProcessParent::AllocPParentToChildStreamParent() {
252   MOZ_CRASH("PParentToChildStreamChild actors should be manually constructed!");
253 }
254 
DeallocPParentToChildStreamParent(PParentToChildStreamParent * aActor)255 bool SocketProcessParent::DeallocPParentToChildStreamParent(
256     PParentToChildStreamParent* aActor) {
257   delete aActor;
258   return true;
259 }
260 
261 mozilla::ipc::PParentToChildStreamParent*
SendPParentToChildStreamConstructor(PParentToChildStreamParent * aActor)262 SocketProcessParent::SendPParentToChildStreamConstructor(
263     PParentToChildStreamParent* aActor) {
264   MOZ_ASSERT(NS_IsMainThread());
265   return PSocketProcessParent::SendPParentToChildStreamConstructor(aActor);
266 }
267 
268 mozilla::ipc::PFileDescriptorSetParent*
SendPFileDescriptorSetConstructor(const FileDescriptor & aFD)269 SocketProcessParent::SendPFileDescriptorSetConstructor(
270     const FileDescriptor& aFD) {
271   MOZ_ASSERT(NS_IsMainThread());
272   return PSocketProcessParent::SendPFileDescriptorSetConstructor(aFD);
273 }
274 
RecvObserveHttpActivity(const HttpActivityArgs & aArgs,const uint32_t & aActivityType,const uint32_t & aActivitySubtype,const PRTime & aTimestamp,const uint64_t & aExtraSizeData,const nsCString & aExtraStringData)275 mozilla::ipc::IPCResult SocketProcessParent::RecvObserveHttpActivity(
276     const HttpActivityArgs& aArgs, const uint32_t& aActivityType,
277     const uint32_t& aActivitySubtype, const PRTime& aTimestamp,
278     const uint64_t& aExtraSizeData, const nsCString& aExtraStringData) {
279   nsCOMPtr<nsIHttpActivityDistributor> activityDistributor =
280       components::HttpActivityDistributor::Service();
281   MOZ_ASSERT(activityDistributor);
282 
283   Unused << activityDistributor->ObserveActivityWithArgs(
284       aArgs, aActivityType, aActivitySubtype, aTimestamp, aExtraSizeData,
285       aExtraStringData);
286   return IPC_OK();
287 }
288 
RecvInitBackground(Endpoint<PBackgroundParent> && aEndpoint)289 mozilla::ipc::IPCResult SocketProcessParent::RecvInitBackground(
290     Endpoint<PBackgroundParent>&& aEndpoint) {
291   LOG(("SocketProcessParent::RecvInitBackground\n"));
292   if (!ipc::BackgroundParent::Alloc(nullptr, std::move(aEndpoint))) {
293     return IPC_FAIL(this, "BackgroundParent::Alloc failed");
294   }
295 
296   return IPC_OK();
297 }
298 
299 already_AddRefed<PAltServiceParent>
AllocPAltServiceParent()300 SocketProcessParent::AllocPAltServiceParent() {
301   RefPtr<AltServiceParent> actor = new AltServiceParent();
302   return actor.forget();
303 }
304 
RecvGetTLSClientCert(const nsCString & aHostName,const OriginAttributes & aOriginAttributes,const int32_t & aPort,const uint32_t & aProviderFlags,const uint32_t & aProviderTlsFlags,const ByteArray & aServerCert,Maybe<ByteArray> && aClientCert,nsTArray<ByteArray> && aCollectedCANames,bool * aSucceeded,ByteArray * aOutCert,ByteArray * aOutKey,nsTArray<ByteArray> * aBuiltChain)305 mozilla::ipc::IPCResult SocketProcessParent::RecvGetTLSClientCert(
306     const nsCString& aHostName, const OriginAttributes& aOriginAttributes,
307     const int32_t& aPort, const uint32_t& aProviderFlags,
308     const uint32_t& aProviderTlsFlags, const ByteArray& aServerCert,
309     Maybe<ByteArray>&& aClientCert, nsTArray<ByteArray>&& aCollectedCANames,
310     bool* aSucceeded, ByteArray* aOutCert, ByteArray* aOutKey,
311     nsTArray<ByteArray>* aBuiltChain) {
312   *aSucceeded = false;
313 
314   SECItem serverCertItem = {
315       siBuffer, const_cast<uint8_t*>(aServerCert.data().Elements()),
316       static_cast<unsigned int>(aServerCert.data().Length())};
317   UniqueCERTCertificate serverCert(CERT_NewTempCertificate(
318       CERT_GetDefaultCertDB(), &serverCertItem, nullptr, false, true));
319   if (!serverCert) {
320     return IPC_OK();
321   }
322 
323   RefPtr<nsIX509Cert> clientCert;
324   if (aClientCert) {
325     clientCert = nsNSSCertificate::ConstructFromDER(
326         BitwiseCast<char*, uint8_t*>(aClientCert->data().Elements()),
327         aClientCert->data().Length());
328     if (!clientCert) {
329       return IPC_OK();
330     }
331   }
332 
333   ClientAuthInfo info(aHostName, aOriginAttributes, aPort, aProviderFlags,
334                       aProviderTlsFlags, clientCert);
335   nsTArray<nsTArray<uint8_t>> collectedCANames;
336   for (auto& name : aCollectedCANames) {
337     collectedCANames.AppendElement(std::move(name.data()));
338   }
339 
340   UniqueCERTCertificate cert;
341   UniqueSECKEYPrivateKey key;
342   UniqueCERTCertList builtChain;
343   SECStatus status =
344       DoGetClientAuthData(std::move(info), serverCert,
345                           std::move(collectedCANames), cert, key, builtChain);
346   if (status != SECSuccess) {
347     return IPC_OK();
348   }
349 
350   SerializeClientCertAndKey(cert, key, *aOutCert, *aOutKey);
351 
352   if (builtChain) {
353     for (CERTCertListNode* n = CERT_LIST_HEAD(builtChain);
354          !CERT_LIST_END(n, builtChain); n = CERT_LIST_NEXT(n)) {
355       ByteArray array;
356       array.data().AppendElements(n->cert->derCert.data, n->cert->derCert.len);
357       aBuiltChain->AppendElement(std::move(array));
358     }
359   }
360 
361   *aSucceeded = true;
362   return IPC_OK();
363 }
364 
365 already_AddRefed<PProxyConfigLookupParent>
AllocPProxyConfigLookupParent(nsIURI * aURI,const uint32_t & aProxyResolveFlags)366 SocketProcessParent::AllocPProxyConfigLookupParent(
367     nsIURI* aURI, const uint32_t& aProxyResolveFlags) {
368   RefPtr<ProxyConfigLookupParent> actor =
369       new ProxyConfigLookupParent(aURI, aProxyResolveFlags);
370   return actor.forget();
371 }
372 
RecvPProxyConfigLookupConstructor(PProxyConfigLookupParent * aActor,nsIURI * aURI,const uint32_t & aProxyResolveFlags)373 mozilla::ipc::IPCResult SocketProcessParent::RecvPProxyConfigLookupConstructor(
374     PProxyConfigLookupParent* aActor, nsIURI* aURI,
375     const uint32_t& aProxyResolveFlags) {
376   static_cast<ProxyConfigLookupParent*>(aActor)->DoProxyLookup();
377   return IPC_OK();
378 }
379 
RecvCachePushCheck(nsIURI * aPushedURL,OriginAttributes && aOriginAttributes,nsCString && aRequestString,CachePushCheckResolver && aResolver)380 mozilla::ipc::IPCResult SocketProcessParent::RecvCachePushCheck(
381     nsIURI* aPushedURL, OriginAttributes&& aOriginAttributes,
382     nsCString&& aRequestString, CachePushCheckResolver&& aResolver) {
383   RefPtr<CachePushChecker> checker = new CachePushChecker(
384       aPushedURL, aOriginAttributes, aRequestString, aResolver);
385   if (NS_FAILED(checker->DoCheck())) {
386     aResolver(false);
387   }
388   return IPC_OK();
389 }
390 
391 // To ensure that IPDL is finished before SocketParent gets deleted.
392 class DeferredDeleteSocketProcessParent : public Runnable {
393  public:
DeferredDeleteSocketProcessParent(UniquePtr<SocketProcessParent> && aParent)394   explicit DeferredDeleteSocketProcessParent(
395       UniquePtr<SocketProcessParent>&& aParent)
396       : Runnable("net::DeferredDeleteSocketProcessParent"),
397         mParent(std::move(aParent)) {}
398 
Run()399   NS_IMETHODIMP Run() override { return NS_OK; }
400 
401  private:
402   UniquePtr<SocketProcessParent> mParent;
403 };
404 
405 /* static */
Destroy(UniquePtr<SocketProcessParent> && aParent)406 void SocketProcessParent::Destroy(UniquePtr<SocketProcessParent>&& aParent) {
407   NS_DispatchToMainThread(
408       new DeferredDeleteSocketProcessParent(std::move(aParent)));
409 }
410 
411 already_AddRefed<PRemoteLazyInputStreamParent>
AllocPRemoteLazyInputStreamParent(const nsID & aID,const uint64_t & aSize)412 SocketProcessParent::AllocPRemoteLazyInputStreamParent(const nsID& aID,
413                                                        const uint64_t& aSize) {
414   RefPtr<RemoteLazyInputStreamParent> actor =
415       RemoteLazyInputStreamParent::Create(aID, aSize, this);
416   return actor.forget();
417 }
418 
419 mozilla::ipc::IPCResult
RecvPRemoteLazyInputStreamConstructor(PRemoteLazyInputStreamParent * aActor,const nsID & aID,const uint64_t & aSize)420 SocketProcessParent::RecvPRemoteLazyInputStreamConstructor(
421     PRemoteLazyInputStreamParent* aActor, const nsID& aID,
422     const uint64_t& aSize) {
423   if (!static_cast<RemoteLazyInputStreamParent*>(aActor)->HasValidStream()) {
424     return IPC_FAIL_NO_REASON(this);
425   }
426 
427   return IPC_OK();
428 }
429 
RecvODoHServiceActivated(const bool & aActivated)430 mozilla::ipc::IPCResult SocketProcessParent::RecvODoHServiceActivated(
431     const bool& aActivated) {
432   nsCOMPtr<nsIObserverService> observerService =
433       mozilla::services::GetObserverService();
434 
435   if (observerService) {
436     observerService->NotifyObservers(nullptr, "odoh-service-activated",
437                                      aActivated ? u"true" : u"false");
438   }
439   return IPC_OK();
440 }
441 
442 }  // namespace net
443 }  // namespace mozilla
444