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

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

Powered by Google App Engine
This is Rietveld 408576698