OLD | NEW |
---|---|
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/ssl/chrome_ssl_host_state_delegate.h" | 5 #include "chrome/browser/ssl/chrome_ssl_host_state_delegate.h" |
6 | 6 |
7 #include "base/base64.h" | 7 #include "base/base64.h" |
8 #include "base/command_line.h" | 8 #include "base/command_line.h" |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "base/metrics/field_trial.h" | 10 #include "base/metrics/field_trial.h" |
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
121 // argument dict that is passed in. | 121 // argument dict that is passed in. |
122 // | 122 // |
123 // If create_entries is set to |DoNotCreateDictionaryEntries|, | 123 // If create_entries is set to |DoNotCreateDictionaryEntries|, |
124 // GetValidCertDecisionsDict will return NULL if there is anything invalid about | 124 // GetValidCertDecisionsDict will return NULL if there is anything invalid about |
125 // the setting, such as an invalid version or invalid value types (in addition | 125 // the setting, such as an invalid version or invalid value types (in addition |
126 // to there not be any values in the dictionary). If create_entries is set to | 126 // to there not be any values in the dictionary). If create_entries is set to |
127 // |CreateDictionaryEntries|, if no dictionary is found or the decisions are | 127 // |CreateDictionaryEntries|, if no dictionary is found or the decisions are |
128 // expired, a new dictionary will be created | 128 // expired, a new dictionary will be created |
129 base::DictionaryValue* ChromeSSLHostStateDelegate::GetValidCertDecisionsDict( | 129 base::DictionaryValue* ChromeSSLHostStateDelegate::GetValidCertDecisionsDict( |
130 base::DictionaryValue* dict, | 130 base::DictionaryValue* dict, |
131 CreateDictionaryEntriesDisposition create_entries) { | 131 CreateDictionaryEntriesDisposition create_entries, |
132 bool* expired_previous_decision) { | |
133 // This needs to be done first in case the method is short circuited by an | |
134 // early failure. | |
135 *expired_previous_decision = false; | |
136 | |
132 // Extract the version of the certificate decision structure from the content | 137 // Extract the version of the certificate decision structure from the content |
133 // setting. | 138 // setting. |
134 int version; | 139 int version; |
135 bool success = dict->GetInteger(kSSLCertDecisionVersionKey, &version); | 140 bool success = dict->GetInteger(kSSLCertDecisionVersionKey, &version); |
136 if (!success) { | 141 if (!success) { |
137 if (create_entries == DoNotCreateDictionaryEntries) | 142 if (create_entries == DoNotCreateDictionaryEntries) |
138 return NULL; | 143 return NULL; |
139 | 144 |
140 dict->SetInteger(kSSLCertDecisionVersionKey, | 145 dict->SetInteger(kSSLCertDecisionVersionKey, |
141 kDefaultSSLCertDecisionVersion); | 146 kDefaultSSLCertDecisionVersion); |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
176 } | 181 } |
177 | 182 |
178 // Check to see if the user's certificate decision has expired. | 183 // Check to see if the user's certificate decision has expired. |
179 // - Expired and |create_entries| is DoNotCreateDictionaryEntries, return | 184 // - Expired and |create_entries| is DoNotCreateDictionaryEntries, return |
180 // NULL. | 185 // NULL. |
181 // - Expired and |create_entries| is CreateDictionaryEntries, update the | 186 // - Expired and |create_entries| is CreateDictionaryEntries, update the |
182 // expiration time. | 187 // expiration time. |
183 if (should_remember_ssl_decisions_ != | 188 if (should_remember_ssl_decisions_ != |
184 ForgetSSLExceptionDecisionsAtSessionEnd && | 189 ForgetSSLExceptionDecisionsAtSessionEnd && |
185 decision_expiration.ToInternalValue() <= now.ToInternalValue()) { | 190 decision_expiration.ToInternalValue() <= now.ToInternalValue()) { |
191 expired = true; | |
sky
2014/08/12 16:47:31
Why did you move this AFAICT if it's only needed a
jww
2014/08/12 19:23:42
It seemed cleaner to set expired and expired_previ
| |
192 *expired_previous_decision = true; | |
193 | |
186 if (create_entries == DoNotCreateDictionaryEntries) | 194 if (create_entries == DoNotCreateDictionaryEntries) |
187 return NULL; | 195 return NULL; |
188 | 196 |
189 expired = true; | |
190 | |
191 base::Time expiration_time = | 197 base::Time expiration_time = |
192 now + default_ssl_cert_decision_expiration_delta_; | 198 now + default_ssl_cert_decision_expiration_delta_; |
193 // Unfortunately, JSON (and thus content settings) doesn't support int64 | 199 // Unfortunately, JSON (and thus content settings) doesn't support int64 |
194 // values, only doubles. Since this mildly depends on precision, it is | 200 // values, only doubles. Since this mildly depends on precision, it is |
195 // better to store the value as a string. | 201 // better to store the value as a string. |
196 dict->SetString(kSSLCertDecisionExpirationTimeKey, | 202 dict->SetString(kSSLCertDecisionExpirationTimeKey, |
197 base::Int64ToString(expiration_time.ToInternalValue())); | 203 base::Int64ToString(expiration_time.ToInternalValue())); |
198 } | 204 } |
199 | 205 |
200 // Extract the map of certificate fingerprints to errors from the setting. | 206 // Extract the map of certificate fingerprints to errors from the setting. |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
250 } | 256 } |
251 | 257 |
252 void ChromeSSLHostStateDelegate::Clear() { | 258 void ChromeSSLHostStateDelegate::Clear() { |
253 profile_->GetHostContentSettingsMap()->ClearSettingsForOneType( | 259 profile_->GetHostContentSettingsMap()->ClearSettingsForOneType( |
254 CONTENT_SETTINGS_TYPE_SSL_CERT_DECISIONS); | 260 CONTENT_SETTINGS_TYPE_SSL_CERT_DECISIONS); |
255 } | 261 } |
256 | 262 |
257 net::CertPolicy::Judgment ChromeSSLHostStateDelegate::QueryPolicy( | 263 net::CertPolicy::Judgment ChromeSSLHostStateDelegate::QueryPolicy( |
258 const std::string& host, | 264 const std::string& host, |
259 net::X509Certificate* cert, | 265 net::X509Certificate* cert, |
260 net::CertStatus error) { | 266 net::CertStatus error, |
267 bool* expired_previous_decision) { | |
261 HostContentSettingsMap* map = profile_->GetHostContentSettingsMap(); | 268 HostContentSettingsMap* map = profile_->GetHostContentSettingsMap(); |
262 GURL url = GetSecureGURLForHost(host); | 269 GURL url = GetSecureGURLForHost(host); |
263 scoped_ptr<base::Value> value(map->GetWebsiteSetting( | 270 scoped_ptr<base::Value> value(map->GetWebsiteSetting( |
264 url, url, CONTENT_SETTINGS_TYPE_SSL_CERT_DECISIONS, std::string(), NULL)); | 271 url, url, CONTENT_SETTINGS_TYPE_SSL_CERT_DECISIONS, std::string(), NULL)); |
265 | 272 |
273 // Set a default value in case this method is short circuited and doesn't do a | |
274 // full query. | |
275 *expired_previous_decision = false; | |
266 if (!value.get() || !value->IsType(base::Value::TYPE_DICTIONARY)) | 276 if (!value.get() || !value->IsType(base::Value::TYPE_DICTIONARY)) |
267 return net::CertPolicy::UNKNOWN; | 277 return net::CertPolicy::UNKNOWN; |
268 | 278 |
269 base::DictionaryValue* dict; // Owned by value | 279 base::DictionaryValue* dict; // Owned by value |
270 int policy_decision; | 280 int policy_decision; |
271 bool success = value->GetAsDictionary(&dict); | 281 bool success = value->GetAsDictionary(&dict); |
272 DCHECK(success); | 282 DCHECK(success); |
273 | 283 |
274 base::DictionaryValue* cert_error_dict; // Owned by value | 284 base::DictionaryValue* cert_error_dict; // Owned by value |
275 cert_error_dict = | 285 cert_error_dict = GetValidCertDecisionsDict( |
276 GetValidCertDecisionsDict(dict, DoNotCreateDictionaryEntries); | 286 dict, DoNotCreateDictionaryEntries, expired_previous_decision); |
277 if (!cert_error_dict) | 287 if (!cert_error_dict) { |
288 // This revoke is necessary to clear any old expired setting that may | |
289 // lingering in the case that an old decision expried. | |
290 RevokeAllowAndDenyPreferences(host); | |
278 return net::CertPolicy::UNKNOWN; | 291 return net::CertPolicy::UNKNOWN; |
292 } | |
279 | 293 |
280 success = cert_error_dict->GetIntegerWithoutPathExpansion(GetKey(cert, error), | 294 success = cert_error_dict->GetIntegerWithoutPathExpansion(GetKey(cert, error), |
281 &policy_decision); | 295 &policy_decision); |
282 | 296 |
283 // If a policy decision was successfully retrieved and it's a valid value of | 297 // If a policy decision was successfully retrieved and it's a valid value of |
284 // ALLOWED or DENIED, return the valid value. Otherwise, return UNKNOWN. | 298 // ALLOWED or DENIED, return the valid value. Otherwise, return UNKNOWN. |
285 if (success && policy_decision == net::CertPolicy::Judgment::ALLOWED) | 299 if (success && policy_decision == net::CertPolicy::Judgment::ALLOWED) |
286 return net::CertPolicy::Judgment::ALLOWED; | 300 return net::CertPolicy::Judgment::ALLOWED; |
287 else if (success && policy_decision == net::CertPolicy::Judgment::DENIED) | 301 else if (success && policy_decision == net::CertPolicy::Judgment::DENIED) |
288 return net::CertPolicy::Judgment::DENIED; | 302 return net::CertPolicy::Judgment::DENIED; |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
348 scoped_ptr<base::Value> value(map->GetWebsiteSetting( | 362 scoped_ptr<base::Value> value(map->GetWebsiteSetting( |
349 url, url, CONTENT_SETTINGS_TYPE_SSL_CERT_DECISIONS, std::string(), NULL)); | 363 url, url, CONTENT_SETTINGS_TYPE_SSL_CERT_DECISIONS, std::string(), NULL)); |
350 | 364 |
351 if (!value.get() || !value->IsType(base::Value::TYPE_DICTIONARY)) | 365 if (!value.get() || !value->IsType(base::Value::TYPE_DICTIONARY)) |
352 value.reset(new base::DictionaryValue()); | 366 value.reset(new base::DictionaryValue()); |
353 | 367 |
354 base::DictionaryValue* dict; | 368 base::DictionaryValue* dict; |
355 bool success = value->GetAsDictionary(&dict); | 369 bool success = value->GetAsDictionary(&dict); |
356 DCHECK(success); | 370 DCHECK(success); |
357 | 371 |
358 base::DictionaryValue* cert_dict = | 372 bool expired_previous_decision; // unused value in this function |
359 GetValidCertDecisionsDict(dict, CreateDictionaryEntries); | 373 base::DictionaryValue* cert_dict = GetValidCertDecisionsDict( |
374 dict, CreateDictionaryEntries, &expired_previous_decision); | |
360 // If a a valid certificate dictionary cannot be extracted from the content | 375 // If a a valid certificate dictionary cannot be extracted from the content |
361 // setting, that means it's in an unknown format. Unfortunately, there's | 376 // setting, that means it's in an unknown format. Unfortunately, there's |
362 // nothing to be done in that case, so a silent fail is the only option. | 377 // nothing to be done in that case, so a silent fail is the only option. |
363 if (!cert_dict) | 378 if (!cert_dict) |
364 return; | 379 return; |
365 | 380 |
366 dict->SetIntegerWithoutPathExpansion(kSSLCertDecisionVersionKey, | 381 dict->SetIntegerWithoutPathExpansion(kSSLCertDecisionVersionKey, |
367 kDefaultSSLCertDecisionVersion); | 382 kDefaultSSLCertDecisionVersion); |
368 cert_dict->SetIntegerWithoutPathExpansion(GetKey(cert, error), judgment); | 383 cert_dict->SetIntegerWithoutPathExpansion(GetKey(cert, error), judgment); |
369 | 384 |
370 // The map takes ownership of the value, so it is released in the call to | 385 // The map takes ownership of the value, so it is released in the call to |
371 // SetWebsiteSetting. | 386 // SetWebsiteSetting. |
372 map->SetWebsiteSetting(pattern, | 387 map->SetWebsiteSetting(pattern, |
373 pattern, | 388 pattern, |
374 CONTENT_SETTINGS_TYPE_SSL_CERT_DECISIONS, | 389 CONTENT_SETTINGS_TYPE_SSL_CERT_DECISIONS, |
375 std::string(), | 390 std::string(), |
376 value.release()); | 391 value.release()); |
377 } | 392 } |
OLD | NEW |