Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(56)

Side by Side Diff: chrome/browser/ssl/security_state_model.cc

Issue 1440303002: Componentize SecurityStateModel (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: android/cros fixes Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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 "chrome/browser/ssl/security_state_model.h"
6
7 #include "base/command_line.h"
8 #include "base/metrics/field_trial.h"
9 #include "base/metrics/histogram_macros.h"
10 #include "base/prefs/pref_service.h"
11 #include "chrome/browser/profiles/profile.h"
12 #include "chrome/common/chrome_constants.h"
13 #include "chrome/common/chrome_switches.h"
14 #include "chrome/common/pref_names.h"
15 #include "chrome/common/pref_names.h"
16 #include "content/public/browser/cert_store.h"
17 #include "content/public/browser/navigation_entry.h"
18 #include "content/public/browser/navigation_handle.h"
19 #include "content/public/browser/web_contents.h"
20 #include "content/public/common/origin_util.h"
21 #include "net/ssl/ssl_cipher_suite_names.h"
22 #include "net/ssl/ssl_connection_status_flags.h"
23
24 #if defined(OS_CHROMEOS)
25 #include "chrome/browser/chromeos/policy/policy_cert_service.h"
26 #include "chrome/browser/chromeos/policy/policy_cert_service_factory.h"
27 #endif
28
29 DEFINE_WEB_CONTENTS_USER_DATA_KEY(SecurityStateModel);
30
31 namespace {
32
33 SecurityStateModel::SecurityLevel GetSecurityLevelForNonSecureFieldTrial() {
34 std::string choice =
35 base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
36 switches::kMarkNonSecureAs);
37 std::string group = base::FieldTrialList::FindFullName("MarkNonSecureAs");
38
39 // Do not change this enum. It is used in the histogram.
40 enum MarkNonSecureStatus { NEUTRAL, DUBIOUS, NON_SECURE, LAST_STATUS };
41 const char kEnumeration[] = "MarkNonSecureAs";
42
43 SecurityStateModel::SecurityLevel level = SecurityStateModel::NONE;
44 MarkNonSecureStatus status;
45
46 if (choice == switches::kMarkNonSecureAsNeutral) {
47 status = NEUTRAL;
48 level = SecurityStateModel::NONE;
49 } else if (choice == switches::kMarkNonSecureAsNonSecure) {
50 status = NON_SECURE;
51 level = SecurityStateModel::SECURITY_ERROR;
52 } else if (group == switches::kMarkNonSecureAsNeutral) {
53 status = NEUTRAL;
54 level = SecurityStateModel::NONE;
55 } else if (group == switches::kMarkNonSecureAsNonSecure) {
56 status = NON_SECURE;
57 level = SecurityStateModel::SECURITY_ERROR;
58 } else {
59 status = NEUTRAL;
60 level = SecurityStateModel::NONE;
61 }
62
63 UMA_HISTOGRAM_ENUMERATION(kEnumeration, status, LAST_STATUS);
64 return level;
65 }
66
67 scoped_refptr<net::X509Certificate> GetCertForSSLStatus(
68 const content::SSLStatus& ssl) {
69 scoped_refptr<net::X509Certificate> cert;
70 return content::CertStore::GetInstance()->RetrieveCert(ssl.cert_id, &cert)
71 ? cert
72 : nullptr;
73 }
74
75 SecurityStateModel::SHA1DeprecationStatus GetSHA1DeprecationStatus(
76 scoped_refptr<net::X509Certificate> cert,
77 const content::SSLStatus& ssl) {
78 if (!cert || !(ssl.cert_status & net::CERT_STATUS_SHA1_SIGNATURE_PRESENT))
79 return SecurityStateModel::NO_DEPRECATED_SHA1;
80
81 // The internal representation of the dates for UI treatment of SHA-1.
82 // See http://crbug.com/401365 for details.
83 static const int64_t kJanuary2017 = INT64_C(13127702400000000);
84 if (cert->valid_expiry() >= base::Time::FromInternalValue(kJanuary2017))
85 return SecurityStateModel::DEPRECATED_SHA1_MAJOR;
86 static const int64_t kJanuary2016 = INT64_C(13096080000000000);
87 if (cert->valid_expiry() >= base::Time::FromInternalValue(kJanuary2016))
88 return SecurityStateModel::DEPRECATED_SHA1_MINOR;
89
90 return SecurityStateModel::NO_DEPRECATED_SHA1;
91 }
92
93 SecurityStateModel::MixedContentStatus GetMixedContentStatus(
94 const content::SSLStatus& ssl) {
95 bool ran_insecure_content = false;
96 bool displayed_insecure_content = false;
97 if (ssl.content_status & content::SSLStatus::RAN_INSECURE_CONTENT)
98 ran_insecure_content = true;
99 if (ssl.content_status & content::SSLStatus::DISPLAYED_INSECURE_CONTENT)
100 displayed_insecure_content = true;
101
102 if (ran_insecure_content && displayed_insecure_content)
103 return SecurityStateModel::RAN_AND_DISPLAYED_MIXED_CONTENT;
104 if (ran_insecure_content)
105 return SecurityStateModel::RAN_MIXED_CONTENT;
106 if (displayed_insecure_content)
107 return SecurityStateModel::DISPLAYED_MIXED_CONTENT;
108
109 return SecurityStateModel::NO_MIXED_CONTENT;
110 }
111
112 SecurityStateModel::SecurityLevel GetSecurityLevelForRequest(
113 const GURL& url,
114 const content::SSLStatus& ssl,
115 Profile* profile,
116 scoped_refptr<net::X509Certificate> cert,
117 SecurityStateModel::SHA1DeprecationStatus sha1_status,
118 SecurityStateModel::MixedContentStatus mixed_content_status) {
119 switch (ssl.security_style) {
120 case content::SECURITY_STYLE_UNKNOWN:
121 return SecurityStateModel::NONE;
122
123 case content::SECURITY_STYLE_UNAUTHENTICATED: {
124 if (!content::IsOriginSecure(url) && url.IsStandard())
125 return GetSecurityLevelForNonSecureFieldTrial();
126 return SecurityStateModel::NONE;
127 }
128
129 case content::SECURITY_STYLE_AUTHENTICATION_BROKEN:
130 return SecurityStateModel::SECURITY_ERROR;
131
132 case content::SECURITY_STYLE_WARNING:
133 NOTREACHED();
134 return SecurityStateModel::SECURITY_WARNING;
135
136 case content::SECURITY_STYLE_AUTHENTICATED: {
137 #if defined(OS_CHROMEOS)
138 // Report if there is a policy cert first, before reporting any other
139 // authenticated-but-with-errors cases. A policy cert is a strong
140 // indicator of a MITM being present (the enterprise), while the
141 // other authenticated-but-with-errors indicate something may
142 // be wrong, or may be wrong in the future, but is unclear now.
143 policy::PolicyCertService* service =
144 policy::PolicyCertServiceFactory::GetForProfile(profile);
145 if (service && service->UsedPolicyCertificates())
146 return SecurityStateModel::SECURITY_POLICY_WARNING;
147 #endif
148
149 if (sha1_status == SecurityStateModel::DEPRECATED_SHA1_MAJOR)
150 return SecurityStateModel::SECURITY_ERROR;
151 if (sha1_status == SecurityStateModel::DEPRECATED_SHA1_MINOR)
152 return SecurityStateModel::NONE;
153
154 // Active mixed content is downgraded to the BROKEN style and
155 // handled above.
156 DCHECK_NE(SecurityStateModel::RAN_MIXED_CONTENT, mixed_content_status);
157 DCHECK_NE(SecurityStateModel::RAN_AND_DISPLAYED_MIXED_CONTENT,
158 mixed_content_status);
159 // This should be kept in sync with
160 // |kDisplayedInsecureContentStyle|. That is: the treatment
161 // given to passive mixed content here should be expressed by
162 // |kDisplayedInsecureContentStyle|, which is used to coordinate
163 // the treatment of passive mixed content with other security UI
164 // elements outside of //chrome.
165 if (mixed_content_status == SecurityStateModel::DISPLAYED_MIXED_CONTENT)
166 return SecurityStateModel::NONE;
167
168 if (net::IsCertStatusError(ssl.cert_status)) {
169 DCHECK(net::IsCertStatusMinorError(ssl.cert_status));
170 return SecurityStateModel::NONE;
171 }
172 if (net::SSLConnectionStatusToVersion(ssl.connection_status) ==
173 net::SSL_CONNECTION_VERSION_SSL3) {
174 // SSLv3 will be removed in the future.
175 return SecurityStateModel::SECURITY_WARNING;
176 }
177 if ((ssl.cert_status & net::CERT_STATUS_IS_EV) && cert)
178 return SecurityStateModel::EV_SECURE;
179 return SecurityStateModel::SECURE;
180 }
181 }
182
183 return SecurityStateModel::NONE;
184 }
185
186 } // namespace
187
188 const content::SecurityStyle
189 SecurityStateModel::kDisplayedInsecureContentStyle =
190 content::SECURITY_STYLE_UNAUTHENTICATED;
191 const content::SecurityStyle SecurityStateModel::kRanInsecureContentStyle =
192 content::SECURITY_STYLE_AUTHENTICATION_BROKEN;
193
194 SecurityStateModel::SecurityInfo::SecurityInfo()
195 : security_level(SecurityStateModel::NONE),
196 sha1_deprecation_status(SecurityStateModel::NO_DEPRECATED_SHA1),
197 mixed_content_status(SecurityStateModel::NO_MIXED_CONTENT),
198 scheme_is_cryptographic(false),
199 cert_status(0),
200 cert_id(0),
201 security_bits(-1),
202 connection_status(0),
203 is_secure_protocol_and_ciphersuite(false) {}
204
205 SecurityStateModel::SecurityInfo::~SecurityInfo() {}
206
207 SecurityStateModel::~SecurityStateModel() {}
208
209 const SecurityStateModel::SecurityInfo& SecurityStateModel::GetSecurityInfo()
210 const {
211 content::NavigationEntry* entry =
212 web_contents_->GetController().GetVisibleEntry();
213 if (!entry) {
214 security_info_ = SecurityInfo();
215 visible_url_ = GURL();
216 visible_ssl_status_ = content::SSLStatus();
217 return security_info_;
218 }
219
220 if (entry->GetURL() == visible_url_ &&
221 entry->GetSSL().Equals(visible_ssl_status_)) {
222 // A cert must be present in the CertStore in order for the site to
223 // be considered EV_SECURE, and the cert might have been removed
224 // since the security level was last computed.
225 if (security_info_.security_level == EV_SECURE &&
226 !GetCertForSSLStatus(visible_ssl_status_)) {
227 security_info_.security_level = SECURE;
228 }
229 return security_info_;
230 }
231
232 SecurityInfoForRequest(
233 entry->GetURL(), entry->GetSSL(),
234 Profile::FromBrowserContext(web_contents_->GetBrowserContext()),
235 &security_info_);
236 visible_url_ = entry->GetURL();
237 visible_ssl_status_ = entry->GetSSL();
238 return security_info_;
239 }
240
241 // static
242 void SecurityStateModel::SecurityInfoForRequest(const GURL& url,
243 const content::SSLStatus& ssl,
244 Profile* profile,
245 SecurityInfo* security_info) {
246 scoped_refptr<net::X509Certificate> cert = GetCertForSSLStatus(ssl);
247 security_info->cert_id = ssl.cert_id;
248 security_info->sha1_deprecation_status = GetSHA1DeprecationStatus(cert, ssl);
249 security_info->mixed_content_status = GetMixedContentStatus(ssl);
250 security_info->security_bits = ssl.security_bits;
251 security_info->connection_status = ssl.connection_status;
252 security_info->cert_status = ssl.cert_status;
253 security_info->scheme_is_cryptographic = url.SchemeIsCryptographic();
254 security_info->is_secure_protocol_and_ciphersuite =
255 (net::SSLConnectionStatusToVersion(ssl.connection_status) >=
256 net::SSL_CONNECTION_VERSION_TLS1_2 &&
257 net::IsSecureTLSCipherSuite(
258 net::SSLConnectionStatusToCipherSuite(ssl.connection_status)));
259
260 security_info->sct_verify_statuses.clear();
261 for (const auto& sct : ssl.signed_certificate_timestamp_ids) {
262 security_info->sct_verify_statuses.push_back(sct.status);
263 }
264
265 security_info->security_level = GetSecurityLevelForRequest(
266 url, ssl, profile, cert, security_info->sha1_deprecation_status,
267 security_info->mixed_content_status);
268 }
269
270 SecurityStateModel::SecurityStateModel(content::WebContents* web_contents)
271 : web_contents_(web_contents) {}
OLDNEW
« no previous file with comments | « chrome/browser/ssl/security_state_model.h ('k') | chrome/browser/ssl/security_state_model_android.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698