1 // Copyright 2015 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 "components/password_manager/content/browser/bad_message.h"
6 
7 #include "base/logging.h"
8 #include "base/metrics/histogram_functions.h"
9 #include "base/syslog_logging.h"
10 #include "components/password_manager/core/browser/password_form.h"
11 #include "content/public/browser/child_process_security_policy.h"
12 #include "content/public/browser/render_frame_host.h"
13 #include "content/public/browser/render_process_host.h"
14 
15 namespace password_manager {
16 namespace bad_message {
17 namespace {
18 
19 // Called when the browser receives a bad IPC message from a renderer process on
20 // the UI thread. Logs the event, records a histogram metric for the |reason|,
21 // and terminates the process for |host|.
ReceivedBadMessage(content::RenderProcessHost * host,BadMessageReason reason)22 void ReceivedBadMessage(content::RenderProcessHost* host,
23                         BadMessageReason reason) {
24   LOG(ERROR)
25       << "Terminating renderer for bad PasswordManager IPC message, reason "
26       << static_cast<int>(reason);
27   base::UmaHistogramSparse("Stability.BadMessageTerminated.PasswordManager",
28                            static_cast<int>(reason));
29   host->ShutdownForBadMessage(
30       content::RenderProcessHost::CrashReportMode::GENERATE_CRASH_DUMP);
31 }
32 
33 }  // namespace
34 
CheckChildProcessSecurityPolicyForURL(content::RenderFrameHost * frame,const GURL & form_url,BadMessageReason reason)35 bool CheckChildProcessSecurityPolicyForURL(content::RenderFrameHost* frame,
36                                            const GURL& form_url,
37                                            BadMessageReason reason) {
38   if (form_url.SchemeIs(url::kAboutScheme) ||
39       form_url.SchemeIs(url::kDataScheme)) {
40     SYSLOG(WARNING) << "Killing renderer: illegal password access from about: "
41                     << "or data: URL. Reason: " << static_cast<int>(reason);
42     bad_message::ReceivedBadMessage(frame->GetProcess(), reason);
43     return false;
44   }
45 
46   content::ChildProcessSecurityPolicy* policy =
47       content::ChildProcessSecurityPolicy::GetInstance();
48   if (!policy->CanAccessDataForOrigin(frame->GetProcess()->GetID(), form_url)) {
49     SYSLOG(WARNING) << "Killing renderer: illegal password access. Reason: "
50                     << static_cast<int>(reason);
51     bad_message::ReceivedBadMessage(frame->GetProcess(), reason);
52     return false;
53   }
54 
55   return true;
56 }
57 
CheckChildProcessSecurityPolicy(content::RenderFrameHost * frame,const PasswordForm & password_form,BadMessageReason reason)58 bool CheckChildProcessSecurityPolicy(content::RenderFrameHost* frame,
59                                      const PasswordForm& password_form,
60                                      BadMessageReason reason) {
61   return CheckChildProcessSecurityPolicyForURL(frame, password_form.url,
62                                                reason) &&
63          CheckChildProcessSecurityPolicyForURL(
64              frame, GURL(password_form.signon_realm), reason) &&
65          CheckChildProcessSecurityPolicyForURL(
66              frame, password_form.form_data.url, reason);
67 }
68 
CheckChildProcessSecurityPolicy(content::RenderFrameHost * frame,const std::vector<PasswordForm> & forms,BadMessageReason reason)69 bool CheckChildProcessSecurityPolicy(content::RenderFrameHost* frame,
70                                      const std::vector<PasswordForm>& forms,
71                                      BadMessageReason reason) {
72   for (const auto& form : forms) {
73     if (!bad_message::CheckChildProcessSecurityPolicy(frame, form, reason))
74       return false;
75   }
76   return true;
77 }
78 
CheckChildProcessSecurityPolicy(content::RenderFrameHost * frame,const std::vector<autofill::FormData> & forms_data,BadMessageReason reason)79 bool CheckChildProcessSecurityPolicy(
80     content::RenderFrameHost* frame,
81     const std::vector<autofill::FormData>& forms_data,
82     BadMessageReason reason) {
83   for (const auto& form_data : forms_data) {
84     if (!bad_message::CheckChildProcessSecurityPolicyForURL(
85             frame, form_data.url, reason)) {
86       return false;
87     }
88   }
89   return true;
90 }
91 
92 }  // namespace bad_message
93 }  // namespace password_manager
94