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

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

Issue 1539043002: Pull SecurityStateModel out into a component (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: rebase Created 4 years, 11 months 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 <stdint.h>
8
9 #include "base/command_line.h"
10 #include "base/metrics/field_trial.h"
11 #include "base/metrics/histogram_macros.h"
12 #include "chrome/browser/ssl/security_state_model_client.h"
13 #include "chrome/common/chrome_switches.h"
14 #include "net/ssl/ssl_cipher_suite_names.h"
15 #include "net/ssl/ssl_connection_status_flags.h"
16
17 namespace {
18
19 SecurityStateModel::SecurityLevel GetSecurityLevelForNonSecureFieldTrial() {
20 // TODO(estark): componentize switches::kMarkNonSecureAs.
21 // https://crbug.com/515071
22 std::string choice =
23 base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
24 switches::kMarkNonSecureAs);
25 std::string group = base::FieldTrialList::FindFullName("MarkNonSecureAs");
26
27 // Do not change this enum. It is used in the histogram.
28 enum MarkNonSecureStatus { NEUTRAL, DUBIOUS, NON_SECURE, LAST_STATUS };
29 const char kEnumeration[] = "MarkNonSecureAs";
30
31 SecurityStateModel::SecurityLevel level = SecurityStateModel::NONE;
32 MarkNonSecureStatus status;
33
34 if (choice == switches::kMarkNonSecureAsNeutral) {
35 status = NEUTRAL;
36 level = SecurityStateModel::NONE;
37 } else if (choice == switches::kMarkNonSecureAsNonSecure) {
38 status = NON_SECURE;
39 level = SecurityStateModel::SECURITY_ERROR;
40 } else if (group == switches::kMarkNonSecureAsNeutral) {
41 status = NEUTRAL;
42 level = SecurityStateModel::NONE;
43 } else if (group == switches::kMarkNonSecureAsNonSecure) {
44 status = NON_SECURE;
45 level = SecurityStateModel::SECURITY_ERROR;
46 } else {
47 status = NEUTRAL;
48 level = SecurityStateModel::NONE;
49 }
50
51 UMA_HISTOGRAM_ENUMERATION(kEnumeration, status, LAST_STATUS);
52 return level;
53 }
54
55 SecurityStateModel::SHA1DeprecationStatus GetSHA1DeprecationStatus(
56 scoped_refptr<net::X509Certificate> cert,
57 const SecurityStateModel::VisibleSecurityState& visible_security_state) {
58 if (!cert ||
59 !(visible_security_state.cert_status &
60 net::CERT_STATUS_SHA1_SIGNATURE_PRESENT))
61 return SecurityStateModel::NO_DEPRECATED_SHA1;
62
63 // The internal representation of the dates for UI treatment of SHA-1.
64 // See http://crbug.com/401365 for details.
65 static const int64_t kJanuary2017 = INT64_C(13127702400000000);
66 if (cert->valid_expiry() >= base::Time::FromInternalValue(kJanuary2017))
67 return SecurityStateModel::DEPRECATED_SHA1_MAJOR;
68 static const int64_t kJanuary2016 = INT64_C(13096080000000000);
69 if (cert->valid_expiry() >= base::Time::FromInternalValue(kJanuary2016))
70 return SecurityStateModel::DEPRECATED_SHA1_MINOR;
71
72 return SecurityStateModel::NO_DEPRECATED_SHA1;
73 }
74
75 SecurityStateModel::MixedContentStatus GetMixedContentStatus(
76 const SecurityStateModel::VisibleSecurityState& visible_security_state) {
77 bool ran_insecure_content = visible_security_state.ran_mixed_content;
78 bool displayed_insecure_content =
79 visible_security_state.displayed_mixed_content;
80 if (ran_insecure_content && displayed_insecure_content)
81 return SecurityStateModel::RAN_AND_DISPLAYED_MIXED_CONTENT;
82 if (ran_insecure_content)
83 return SecurityStateModel::RAN_MIXED_CONTENT;
84 if (displayed_insecure_content)
85 return SecurityStateModel::DISPLAYED_MIXED_CONTENT;
86
87 return SecurityStateModel::NO_MIXED_CONTENT;
88 }
89
90 SecurityStateModel::SecurityLevel GetSecurityLevelForRequest(
91 const SecurityStateModel::VisibleSecurityState& visible_security_state,
92 SecurityStateModelClient* client,
93 const scoped_refptr<net::X509Certificate>& cert,
94 SecurityStateModel::SHA1DeprecationStatus sha1_status,
95 SecurityStateModel::MixedContentStatus mixed_content_status) {
96 DCHECK(visible_security_state.initialized);
97 GURL url = visible_security_state.url;
98 switch (visible_security_state.initial_security_level) {
99 case SecurityStateModel::NONE: {
100 if (!client->IsOriginSecure(url) && url.IsStandard())
101 return GetSecurityLevelForNonSecureFieldTrial();
102 return SecurityStateModel::NONE;
103 }
104
105 case SecurityStateModel::SECURITY_ERROR:
106 return SecurityStateModel::SECURITY_ERROR;
107
108 case SecurityStateModel::SECURITY_WARNING:
109 case SecurityStateModel::SECURITY_POLICY_WARNING:
110 return visible_security_state.initial_security_level;
111
112 case SecurityStateModel::SECURE:
113 case SecurityStateModel::EV_SECURE: {
114 // Major cert errors and active mixed content will generally be
115 // downgraded by the embedder to SECURITY_ERROR and handled above,
116 // but downgrade here just in case.
117 net::CertStatus cert_status = visible_security_state.cert_status;
118 if (net::IsCertStatusError(cert_status) &&
119 !net::IsCertStatusMinorError(cert_status)) {
120 return SecurityStateModel::SECURITY_ERROR;
121 }
122 if (mixed_content_status == SecurityStateModel::RAN_MIXED_CONTENT ||
123 mixed_content_status ==
124 SecurityStateModel::RAN_AND_DISPLAYED_MIXED_CONTENT) {
125 return SecurityStateModel::kRanInsecureContentLevel;
126 }
127
128 // Report if there is a policy cert first, before reporting any other
129 // authenticated-but-with-errors cases. A policy cert is a strong
130 // indicator of a MITM being present (the enterprise), while the
131 // other authenticated-but-with-errors indicate something may
132 // be wrong, or may be wrong in the future, but is unclear now.
133 if (client->UsedPolicyInstalledCertificate())
134 return SecurityStateModel::SECURITY_POLICY_WARNING;
135
136 if (sha1_status == SecurityStateModel::DEPRECATED_SHA1_MAJOR)
137 return SecurityStateModel::SECURITY_ERROR;
138 if (sha1_status == SecurityStateModel::DEPRECATED_SHA1_MINOR)
139 return SecurityStateModel::NONE;
140
141 // Active mixed content is handled above.
142 DCHECK_NE(SecurityStateModel::RAN_MIXED_CONTENT, mixed_content_status);
143 DCHECK_NE(SecurityStateModel::RAN_AND_DISPLAYED_MIXED_CONTENT,
144 mixed_content_status);
145 if (mixed_content_status == SecurityStateModel::DISPLAYED_MIXED_CONTENT)
146 return SecurityStateModel::kDisplayedInsecureContentLevel;
147
148 if (net::IsCertStatusError(cert_status)) {
149 // Major cert errors are handled above.
150 DCHECK(net::IsCertStatusMinorError(cert_status));
151 return SecurityStateModel::NONE;
152 }
153 if (net::SSLConnectionStatusToVersion(
154 visible_security_state.connection_status) ==
155 net::SSL_CONNECTION_VERSION_SSL3) {
156 // SSLv3 will be removed in the future.
157 return SecurityStateModel::SECURITY_WARNING;
158 }
159 if ((cert_status & net::CERT_STATUS_IS_EV) && cert)
160 return SecurityStateModel::EV_SECURE;
161 return SecurityStateModel::SECURE;
162 }
163 }
164
165 return SecurityStateModel::NONE;
166 }
167
168 void SecurityInfoForRequest(
169 SecurityStateModelClient* client,
170 const SecurityStateModel::VisibleSecurityState& visible_security_state,
171 const scoped_refptr<net::X509Certificate>& cert,
172 SecurityStateModel::SecurityInfo* security_info) {
173 if (!visible_security_state.initialized) {
174 *security_info = SecurityStateModel::SecurityInfo();
175 return;
176 }
177 security_info->cert_id = visible_security_state.cert_id;
178 security_info->sha1_deprecation_status =
179 GetSHA1DeprecationStatus(cert, visible_security_state);
180 security_info->mixed_content_status =
181 GetMixedContentStatus(visible_security_state);
182 security_info->security_bits = visible_security_state.security_bits;
183 security_info->connection_status = visible_security_state.connection_status;
184 security_info->cert_status = visible_security_state.cert_status;
185 security_info->scheme_is_cryptographic =
186 visible_security_state.url.SchemeIsCryptographic();
187 security_info->is_secure_protocol_and_ciphersuite =
188 (net::SSLConnectionStatusToVersion(security_info->connection_status) >=
189 net::SSL_CONNECTION_VERSION_TLS1_2 &&
190 net::IsSecureTLSCipherSuite(net::SSLConnectionStatusToCipherSuite(
191 security_info->connection_status)));
192
193 security_info->sct_verify_statuses =
194 visible_security_state.sct_verify_statuses;
195
196 security_info->security_level =
197 GetSecurityLevelForRequest(visible_security_state, client, cert,
198 security_info->sha1_deprecation_status,
199 security_info->mixed_content_status);
200 }
201
202 } // namespace
203
204 const SecurityStateModel::SecurityLevel
205 SecurityStateModel::kDisplayedInsecureContentLevel =
206 SecurityStateModel::NONE;
207 const SecurityStateModel::SecurityLevel
208 SecurityStateModel::kRanInsecureContentLevel =
209 SecurityStateModel::SECURITY_ERROR;
210
211 SecurityStateModel::SecurityInfo::SecurityInfo()
212 : security_level(SecurityStateModel::NONE),
213 sha1_deprecation_status(SecurityStateModel::NO_DEPRECATED_SHA1),
214 mixed_content_status(SecurityStateModel::NO_MIXED_CONTENT),
215 scheme_is_cryptographic(false),
216 cert_status(0),
217 cert_id(0),
218 security_bits(-1),
219 connection_status(0),
220 is_secure_protocol_and_ciphersuite(false) {}
221
222 SecurityStateModel::SecurityInfo::~SecurityInfo() {}
223
224 SecurityStateModel::SecurityStateModel() {}
225
226 SecurityStateModel::~SecurityStateModel() {}
227
228 const SecurityStateModel::SecurityInfo& SecurityStateModel::GetSecurityInfo()
229 const {
230 scoped_refptr<net::X509Certificate> cert = nullptr;
231 client_->RetrieveCert(&cert);
232
233 // Check if the cached |security_info_| must be recomputed.
234 VisibleSecurityState new_visible_state;
235 client_->GetVisibleSecurityState(&new_visible_state);
236 bool visible_security_state_changed =
237 !(visible_security_state_ == new_visible_state);
238 if (!visible_security_state_changed) {
239 // A cert must be present in order for the site to be considered
240 // EV_SECURE, and the cert might have been removed since the
241 // security level was last computed.
242 if (security_info_.security_level == EV_SECURE && !cert) {
243 security_info_.security_level = SECURE;
244 }
245 return security_info_;
246 }
247
248 visible_security_state_ = new_visible_state;
249 SecurityInfoForRequest(client_, visible_security_state_, cert,
250 &security_info_);
251 return security_info_;
252 }
253
254 void SecurityStateModel::SetClient(SecurityStateModelClient* client) {
255 client_ = client;
256 }
257
258 SecurityStateModel::VisibleSecurityState::VisibleSecurityState()
259 : initialized(false),
260 initial_security_level(SecurityStateModel::NONE),
261 cert_id(0),
262 cert_status(0),
263 connection_status(0),
264 security_bits(-1),
265 displayed_mixed_content(false),
266 ran_mixed_content(false) {}
267
268 SecurityStateModel::VisibleSecurityState::~VisibleSecurityState() {}
269
270 bool SecurityStateModel::VisibleSecurityState::operator==(
271 const SecurityStateModel::VisibleSecurityState& other) const {
272 return (url == other.url &&
273 initial_security_level == other.initial_security_level &&
274 cert_id == other.cert_id && cert_status == other.cert_status &&
275 connection_status == other.connection_status &&
276 security_bits == other.security_bits &&
277 sct_verify_statuses == other.sct_verify_statuses &&
278 displayed_mixed_content == other.displayed_mixed_content &&
279 ran_mixed_content == other.ran_mixed_content);
280 }
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