1 // Copyright 2018 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "services/network/network_service_network_delegate.h"
6 
7 #include <string>
8 
9 #include "base/bind.h"
10 #include "base/debug/dump_without_crashing.h"
11 #include "base/strings/utf_string_conversions.h"
12 #include "build/build_config.h"
13 #include "components/domain_reliability/monitor.h"
14 #include "net/base/isolation_info.h"
15 #include "net/base/load_flags.h"
16 #include "net/base/net_errors.h"
17 #include "net/url_request/url_request.h"
18 #include "services/network/cookie_manager.h"
19 #include "services/network/network_context.h"
20 #include "services/network/network_service.h"
21 #include "services/network/network_service_proxy_delegate.h"
22 #include "services/network/pending_callback_chain.h"
23 #include "services/network/public/cpp/features.h"
24 #include "services/network/url_loader.h"
25 #include "url/gurl.h"
26 
27 #if !defined(OS_IOS)
28 #include "services/network/websocket.h"
29 #endif
30 
31 namespace network {
32 
33 namespace {
34 
35 const char kClearSiteDataHeader[] = "Clear-Site-Data";
36 
37 }  // anonymous namespace
38 
NetworkServiceNetworkDelegate(bool enable_referrers,bool validate_referrer_policy_on_initial_request,mojo::PendingRemote<mojom::ProxyErrorClient> proxy_error_client_remote,NetworkContext * network_context)39 NetworkServiceNetworkDelegate::NetworkServiceNetworkDelegate(
40     bool enable_referrers,
41     bool validate_referrer_policy_on_initial_request,
42     mojo::PendingRemote<mojom::ProxyErrorClient> proxy_error_client_remote,
43     NetworkContext* network_context)
44     : enable_referrers_(enable_referrers),
45       validate_referrer_policy_on_initial_request_(
46           validate_referrer_policy_on_initial_request),
47       network_context_(network_context) {
48   if (proxy_error_client_remote)
49     proxy_error_client_.Bind(std::move(proxy_error_client_remote));
50 }
51 
52 NetworkServiceNetworkDelegate::~NetworkServiceNetworkDelegate() = default;
53 
MaybeTruncateReferrer(net::URLRequest * const request,const GURL & effective_url)54 void NetworkServiceNetworkDelegate::MaybeTruncateReferrer(
55     net::URLRequest* const request,
56     const GURL& effective_url) {
57   if (!enable_referrers_) {
58     request->SetReferrer(std::string());
59     request->set_referrer_policy(net::URLRequest::NO_REFERRER);
60     return;
61   }
62 
63   if (base::FeatureList::IsEnabled(
64           features::kCapReferrerToOriginOnCrossOrigin)) {
65     url::Origin destination_origin = url::Origin::Create(effective_url);
66     url::Origin source_origin = url::Origin::Create(GURL(request->referrer()));
67     if (!destination_origin.IsSameOriginWith(source_origin))
68       request->SetReferrer(source_origin.GetURL().spec());
69   }
70 }
71 
OnBeforeURLRequest(net::URLRequest * request,net::CompletionOnceCallback callback,GURL * new_url)72 int NetworkServiceNetworkDelegate::OnBeforeURLRequest(
73     net::URLRequest* request,
74     net::CompletionOnceCallback callback,
75     GURL* new_url) {
76   DCHECK(request);
77 
78   auto* const loader = URLLoader::ForRequest(*request);
79   const GURL* effective_url = nullptr;
80   if (loader && loader->new_redirect_url()) {
81     DCHECK(new_url);
82     *new_url = loader->new_redirect_url().value();
83     effective_url = new_url;
84   } else {
85     effective_url = &request->url();
86   }
87 
88   MaybeTruncateReferrer(request, *effective_url);
89 
90   NetworkService* network_service = network_context_->network_service();
91   if (network_service)
92     network_service->OnBeforeURLRequest();
93 
94   if (!loader)
95     return net::OK;
96 
97   if (network_service) {
98     loader->SetAllowReportingRawHeaders(network_service->HasRawHeadersAccess(
99         loader->GetProcessId(), *effective_url));
100   }
101   return net::OK;
102 }
103 
OnBeforeStartTransaction(net::URLRequest * request,net::CompletionOnceCallback callback,net::HttpRequestHeaders * headers)104 int NetworkServiceNetworkDelegate::OnBeforeStartTransaction(
105     net::URLRequest* request,
106     net::CompletionOnceCallback callback,
107     net::HttpRequestHeaders* headers) {
108   URLLoader* url_loader = URLLoader::ForRequest(*request);
109   if (url_loader)
110     return url_loader->OnBeforeStartTransaction(std::move(callback), headers);
111 
112 #if !defined(OS_IOS)
113   WebSocket* web_socket = WebSocket::ForRequest(*request);
114   if (web_socket)
115     return web_socket->OnBeforeStartTransaction(std::move(callback), headers);
116 #endif  // !defined(OS_IOS)
117 
118   return net::OK;
119 }
120 
OnHeadersReceived(net::URLRequest * request,net::CompletionOnceCallback callback,const net::HttpResponseHeaders * original_response_headers,scoped_refptr<net::HttpResponseHeaders> * override_response_headers,const net::IPEndPoint & endpoint,base::Optional<GURL> * preserve_fragment_on_redirect_url)121 int NetworkServiceNetworkDelegate::OnHeadersReceived(
122     net::URLRequest* request,
123     net::CompletionOnceCallback callback,
124     const net::HttpResponseHeaders* original_response_headers,
125     scoped_refptr<net::HttpResponseHeaders>* override_response_headers,
126     const net::IPEndPoint& endpoint,
127     base::Optional<GURL>* preserve_fragment_on_redirect_url) {
128   auto chain = base::MakeRefCounted<PendingCallbackChain>(std::move(callback));
129   URLLoader* url_loader = URLLoader::ForRequest(*request);
130   if (url_loader) {
131     chain->AddResult(url_loader->OnHeadersReceived(
132         chain->CreateCallback(), original_response_headers,
133         override_response_headers, endpoint,
134         preserve_fragment_on_redirect_url));
135   }
136 
137 #if !defined(OS_IOS)
138   WebSocket* web_socket = WebSocket::ForRequest(*request);
139   if (web_socket) {
140     chain->AddResult(web_socket->OnHeadersReceived(
141         chain->CreateCallback(), original_response_headers,
142         override_response_headers, preserve_fragment_on_redirect_url));
143   }
144 #endif  // !defined(OS_IOS)
145 
146   chain->AddResult(HandleClearSiteDataHeader(request, chain->CreateCallback(),
147                                              original_response_headers));
148 
149   return chain->GetResult();
150 }
151 
OnBeforeRedirect(net::URLRequest * request,const GURL & new_location)152 void NetworkServiceNetworkDelegate::OnBeforeRedirect(net::URLRequest* request,
153                                                      const GURL& new_location) {
154   if (network_context_->domain_reliability_monitor())
155     network_context_->domain_reliability_monitor()->OnBeforeRedirect(request);
156 }
157 
OnResponseStarted(net::URLRequest * request,int net_error)158 void NetworkServiceNetworkDelegate::OnResponseStarted(net::URLRequest* request,
159                                                       int net_error) {
160   ForwardProxyErrors(net_error);
161 }
162 
OnCompleted(net::URLRequest * request,bool started,int net_error)163 void NetworkServiceNetworkDelegate::OnCompleted(net::URLRequest* request,
164                                                 bool started,
165                                                 int net_error) {
166   // TODO(mmenke): Once the network service ships on all platforms, can move
167   // this logic into URLLoader's completion method.
168   DCHECK_NE(net::ERR_IO_PENDING, net_error);
169 
170   if (network_context_->domain_reliability_monitor()) {
171     network_context_->domain_reliability_monitor()->OnCompleted(
172         request, started, net_error);
173   }
174 
175   ForwardProxyErrors(net_error);
176 }
177 
OnPACScriptError(int line_number,const base::string16 & error)178 void NetworkServiceNetworkDelegate::OnPACScriptError(
179     int line_number,
180     const base::string16& error) {
181   if (!proxy_error_client_)
182     return;
183 
184   proxy_error_client_->OnPACScriptError(line_number, base::UTF16ToUTF8(error));
185 }
186 
OnCanGetCookies(const net::URLRequest & request,const net::CookieList & cookie_list,bool allowed_from_caller)187 bool NetworkServiceNetworkDelegate::OnCanGetCookies(
188     const net::URLRequest& request,
189     const net::CookieList& cookie_list,
190     bool allowed_from_caller) {
191   bool allowed =
192       allowed_from_caller &&
193       network_context_->cookie_manager()
194           ->cookie_settings()
195           .IsCookieAccessAllowed(request.url(),
196                                  request.site_for_cookies().RepresentativeUrl(),
197                                  request.isolation_info()
198                                      .network_isolation_key()
199                                      .GetTopFrameOrigin());
200 
201   if (!allowed)
202     return false;
203 
204   URLLoader* url_loader = URLLoader::ForRequest(request);
205   if (url_loader)
206     return url_loader->AllowCookies(request.url(), request.site_for_cookies());
207 #if !defined(OS_IOS)
208   WebSocket* web_socket = WebSocket::ForRequest(request);
209   if (web_socket)
210     return web_socket->AllowCookies(request.url());
211 #endif  // !defined(OS_IOS)
212   return true;
213 }
214 
OnCanSetCookie(const net::URLRequest & request,const net::CanonicalCookie & cookie,net::CookieOptions * options,bool allowed_from_caller)215 bool NetworkServiceNetworkDelegate::OnCanSetCookie(
216     const net::URLRequest& request,
217     const net::CanonicalCookie& cookie,
218     net::CookieOptions* options,
219     bool allowed_from_caller) {
220   bool allowed =
221       allowed_from_caller &&
222       network_context_->cookie_manager()
223           ->cookie_settings()
224           .IsCookieAccessAllowed(request.url(),
225                                  request.site_for_cookies().RepresentativeUrl(),
226                                  request.isolation_info().top_frame_origin());
227   if (!allowed)
228     return false;
229   URLLoader* url_loader = URLLoader::ForRequest(request);
230   if (url_loader)
231     return url_loader->AllowCookies(request.url(), request.site_for_cookies());
232 #if !defined(OS_IOS)
233   WebSocket* web_socket = WebSocket::ForRequest(request);
234   if (web_socket)
235     return web_socket->AllowCookies(request.url());
236 #endif  // !defined(OS_IOS)
237   return true;
238 }
239 
OnForcePrivacyMode(const GURL & url,const net::SiteForCookies & site_for_cookies,const base::Optional<url::Origin> & top_frame_origin) const240 bool NetworkServiceNetworkDelegate::OnForcePrivacyMode(
241     const GURL& url,
242     const net::SiteForCookies& site_for_cookies,
243     const base::Optional<url::Origin>& top_frame_origin) const {
244   return !network_context_->cookie_manager()
245               ->cookie_settings()
246               .IsCookieAccessAllowed(url, site_for_cookies.RepresentativeUrl(),
247                                      top_frame_origin);
248 }
249 
250 bool NetworkServiceNetworkDelegate::
OnCancelURLRequestWithPolicyViolatingReferrerHeader(const net::URLRequest & request,const GURL & target_url,const GURL & referrer_url) const251     OnCancelURLRequestWithPolicyViolatingReferrerHeader(
252         const net::URLRequest& request,
253         const GURL& target_url,
254         const GURL& referrer_url) const {
255   // TODO(mmenke): Once the network service has shipped on all platforms,
256   // consider moving this logic into URLLoader, and removing this method from
257   // NetworkDelegate. Can just have a DCHECK in URLRequest instead.
258   if (!validate_referrer_policy_on_initial_request_)
259     return false;
260 
261   LOG(ERROR) << "Cancelling request to " << target_url
262              << " with invalid referrer " << referrer_url;
263   // Record information to help debug issues like http://crbug.com/422871.
264   if (target_url.SchemeIsHTTPOrHTTPS()) {
265     auto referrer_policy = request.referrer_policy();
266     base::debug::Alias(&referrer_policy);
267     DEBUG_ALIAS_FOR_GURL(target_buf, target_url);
268     DEBUG_ALIAS_FOR_GURL(referrer_buf, referrer_url);
269     base::debug::DumpWithoutCrashing();
270   }
271   return true;
272 }
273 
OnCanQueueReportingReport(const url::Origin & origin) const274 bool NetworkServiceNetworkDelegate::OnCanQueueReportingReport(
275     const url::Origin& origin) const {
276   return network_context_->cookie_manager()
277       ->cookie_settings()
278       .IsCookieAccessAllowed(origin.GetURL(), origin.GetURL());
279 }
280 
OnCanSendReportingReports(std::set<url::Origin> origins,base::OnceCallback<void (std::set<url::Origin>)> result_callback) const281 void NetworkServiceNetworkDelegate::OnCanSendReportingReports(
282     std::set<url::Origin> origins,
283     base::OnceCallback<void(std::set<url::Origin>)> result_callback) const {
284   auto* client = network_context_->client();
285   if (!client) {
286     origins.clear();
287     std::move(result_callback).Run(std::move(origins));
288     return;
289   }
290 
291   if (network_context_->SkipReportingPermissionCheck()) {
292     std::move(result_callback).Run(std::move(origins));
293     return;
294   }
295 
296   std::vector<url::Origin> origin_vector;
297   std::copy(origins.begin(), origins.end(), std::back_inserter(origin_vector));
298   client->OnCanSendReportingReports(
299       origin_vector,
300       base::BindOnce(
301           &NetworkServiceNetworkDelegate::FinishedCanSendReportingReports,
302           weak_ptr_factory_.GetWeakPtr(), std::move(result_callback)));
303 }
304 
OnCanSetReportingClient(const url::Origin & origin,const GURL & endpoint) const305 bool NetworkServiceNetworkDelegate::OnCanSetReportingClient(
306     const url::Origin& origin,
307     const GURL& endpoint) const {
308   return network_context_->cookie_manager()
309       ->cookie_settings()
310       .IsCookieAccessAllowed(origin.GetURL(), origin.GetURL());
311 }
312 
OnCanUseReportingClient(const url::Origin & origin,const GURL & endpoint) const313 bool NetworkServiceNetworkDelegate::OnCanUseReportingClient(
314     const url::Origin& origin,
315     const GURL& endpoint) const {
316   return network_context_->cookie_manager()
317       ->cookie_settings()
318       .IsCookieAccessAllowed(origin.GetURL(), origin.GetURL());
319 }
320 
HandleClearSiteDataHeader(net::URLRequest * request,net::CompletionOnceCallback callback,const net::HttpResponseHeaders * original_response_headers)321 int NetworkServiceNetworkDelegate::HandleClearSiteDataHeader(
322     net::URLRequest* request,
323     net::CompletionOnceCallback callback,
324     const net::HttpResponseHeaders* original_response_headers) {
325   DCHECK(request);
326   if (!original_response_headers || !network_context_->client())
327     return net::OK;
328 
329   URLLoader* url_loader = URLLoader::ForRequest(*request);
330   if (!url_loader)
331     return net::OK;
332 
333   std::string header_value;
334   if (!original_response_headers->GetNormalizedHeader(kClearSiteDataHeader,
335                                                       &header_value)) {
336     return net::OK;
337   }
338 
339   network_context_->client()->OnClearSiteData(
340       url_loader->GetProcessId(), url_loader->GetRenderFrameId(),
341       request->url(), header_value, request->load_flags(),
342       base::BindOnce(&NetworkServiceNetworkDelegate::FinishedClearSiteData,
343                      weak_ptr_factory_.GetWeakPtr(), request->GetWeakPtr(),
344                      std::move(callback)));
345 
346   return net::ERR_IO_PENDING;
347 }
348 
FinishedClearSiteData(base::WeakPtr<net::URLRequest> request,net::CompletionOnceCallback callback)349 void NetworkServiceNetworkDelegate::FinishedClearSiteData(
350     base::WeakPtr<net::URLRequest> request,
351     net::CompletionOnceCallback callback) {
352   if (request)
353     std::move(callback).Run(net::OK);
354 }
355 
FinishedCanSendReportingReports(base::OnceCallback<void (std::set<url::Origin>)> result_callback,const std::vector<url::Origin> & origins)356 void NetworkServiceNetworkDelegate::FinishedCanSendReportingReports(
357     base::OnceCallback<void(std::set<url::Origin>)> result_callback,
358     const std::vector<url::Origin>& origins) {
359   std::set<url::Origin> origin_set(origins.begin(), origins.end());
360   std::move(result_callback).Run(origin_set);
361 }
362 
ForwardProxyErrors(int net_error)363 void NetworkServiceNetworkDelegate::ForwardProxyErrors(int net_error) {
364   if (!proxy_error_client_)
365     return;
366 
367   // TODO(https://crbug.com/876848): Provide justification for the currently
368   // enumerated errors.
369   switch (net_error) {
370     case net::ERR_PROXY_AUTH_UNSUPPORTED:
371     case net::ERR_PROXY_CONNECTION_FAILED:
372     case net::ERR_TUNNEL_CONNECTION_FAILED:
373       proxy_error_client_->OnRequestMaybeFailedDueToProxySettings(net_error);
374       break;
375   }
376 }
377 
378 }  // namespace network
379