| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/net/transport_security_persister.h" | 5 #include "chrome/browser/net/transport_security_persister.h" |
| 6 | 6 |
| 7 #include "base/base64.h" | 7 #include "base/base64.h" |
| 8 #include "base/bind.h" | 8 #include "base/bind.h" |
| 9 #include "base/file_util.h" | 9 #include "base/file_util.h" |
| 10 #include "base/files/file_path.h" | 10 #include "base/files/file_path.h" |
| (...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 219 transport_security_state_->ClearDynamicData(); | 219 transport_security_state_->ClearDynamicData(); |
| 220 return Deserialize(serialized, false, dirty, transport_security_state_); | 220 return Deserialize(serialized, false, dirty, transport_security_state_); |
| 221 } | 221 } |
| 222 | 222 |
| 223 // static | 223 // static |
| 224 bool TransportSecurityPersister::Deserialize(const std::string& serialized, | 224 bool TransportSecurityPersister::Deserialize(const std::string& serialized, |
| 225 bool forced, | 225 bool forced, |
| 226 bool* dirty, | 226 bool* dirty, |
| 227 TransportSecurityState* state) { | 227 TransportSecurityState* state) { |
| 228 scoped_ptr<Value> value(base::JSONReader::Read(serialized)); | 228 scoped_ptr<Value> value(base::JSONReader::Read(serialized)); |
| 229 DictionaryValue* dict_value; | 229 DictionaryValue* dict_value = NULL; |
| 230 if (!value.get() || !value->GetAsDictionary(&dict_value)) | 230 if (!value.get() || !value->GetAsDictionary(&dict_value)) |
| 231 return false; | 231 return false; |
| 232 | 232 |
| 233 const base::Time current_time(base::Time::Now()); | 233 const base::Time current_time(base::Time::Now()); |
| 234 bool dirtied = false; | 234 bool dirtied = false; |
| 235 | 235 |
| 236 for (DictionaryValue::key_iterator i = dict_value->begin_keys(); | 236 for (DictionaryValue::Iterator i(*dict_value); !i.IsAtEnd(); i.Advance()) { |
| 237 i != dict_value->end_keys(); ++i) { | 237 const DictionaryValue* parsed = NULL; |
| 238 DictionaryValue* parsed; | 238 if (!i.value().GetAsDictionary(&parsed)) { |
| 239 if (!dict_value->GetDictionaryWithoutPathExpansion(*i, &parsed)) { | 239 LOG(WARNING) << "Could not parse entry " << i.key() << "; skipping entry"; |
| 240 LOG(WARNING) << "Could not parse entry " << *i << "; skipping entry"; | |
| 241 continue; | 240 continue; |
| 242 } | 241 } |
| 243 | 242 |
| 244 std::string mode_string; | 243 std::string mode_string; |
| 245 double created; | 244 double created; |
| 246 double expiry; | 245 double expiry; |
| 247 double dynamic_spki_hashes_expiry = 0.0; | 246 double dynamic_spki_hashes_expiry = 0.0; |
| 248 TransportSecurityState::DomainState domain_state; | 247 TransportSecurityState::DomainState domain_state; |
| 249 | 248 |
| 250 if (!parsed->GetBoolean(kIncludeSubdomains, | 249 if (!parsed->GetBoolean(kIncludeSubdomains, |
| 251 &domain_state.include_subdomains) || | 250 &domain_state.include_subdomains) || |
| 252 !parsed->GetString(kMode, &mode_string) || | 251 !parsed->GetString(kMode, &mode_string) || |
| 253 !parsed->GetDouble(kExpiry, &expiry)) { | 252 !parsed->GetDouble(kExpiry, &expiry)) { |
| 254 LOG(WARNING) << "Could not parse some elements of entry " << *i | 253 LOG(WARNING) << "Could not parse some elements of entry " << i.key() |
| 255 << "; skipping entry"; | 254 << "; skipping entry"; |
| 256 continue; | 255 continue; |
| 257 } | 256 } |
| 258 | 257 |
| 259 // Don't fail if this key is not present. | 258 // Don't fail if this key is not present. |
| 260 parsed->GetDouble(kDynamicSPKIHashesExpiry, | 259 parsed->GetDouble(kDynamicSPKIHashesExpiry, |
| 261 &dynamic_spki_hashes_expiry); | 260 &dynamic_spki_hashes_expiry); |
| 262 | 261 |
| 263 ListValue* pins_list = NULL; | 262 const ListValue* pins_list = NULL; |
| 264 // preloaded_spki_hashes is a legacy synonym for static_spki_hashes. | 263 // preloaded_spki_hashes is a legacy synonym for static_spki_hashes. |
| 265 if (parsed->GetList(kStaticSPKIHashes, &pins_list)) | 264 if (parsed->GetList(kStaticSPKIHashes, &pins_list)) |
| 266 SPKIHashesFromListValue(*pins_list, &domain_state.static_spki_hashes); | 265 SPKIHashesFromListValue(*pins_list, &domain_state.static_spki_hashes); |
| 267 else if (parsed->GetList(kPreloadedSPKIHashes, &pins_list)) | 266 else if (parsed->GetList(kPreloadedSPKIHashes, &pins_list)) |
| 268 SPKIHashesFromListValue(*pins_list, &domain_state.static_spki_hashes); | 267 SPKIHashesFromListValue(*pins_list, &domain_state.static_spki_hashes); |
| 269 | 268 |
| 270 if (parsed->GetList(kDynamicSPKIHashes, &pins_list)) | 269 if (parsed->GetList(kDynamicSPKIHashes, &pins_list)) |
| 271 SPKIHashesFromListValue(*pins_list, &domain_state.dynamic_spki_hashes); | 270 SPKIHashesFromListValue(*pins_list, &domain_state.dynamic_spki_hashes); |
| 272 | 271 |
| 273 if (mode_string == kForceHTTPS || mode_string == kStrict) { | 272 if (mode_string == kForceHTTPS || mode_string == kStrict) { |
| 274 domain_state.upgrade_mode = | 273 domain_state.upgrade_mode = |
| 275 TransportSecurityState::DomainState::MODE_FORCE_HTTPS; | 274 TransportSecurityState::DomainState::MODE_FORCE_HTTPS; |
| 276 } else if (mode_string == kDefault || mode_string == kPinningOnly) { | 275 } else if (mode_string == kDefault || mode_string == kPinningOnly) { |
| 277 domain_state.upgrade_mode = | 276 domain_state.upgrade_mode = |
| 278 TransportSecurityState::DomainState::MODE_DEFAULT; | 277 TransportSecurityState::DomainState::MODE_DEFAULT; |
| 279 } else { | 278 } else { |
| 280 LOG(WARNING) << "Unknown TransportSecurityState mode string " | 279 LOG(WARNING) << "Unknown TransportSecurityState mode string " |
| 281 << mode_string << " found for entry " << *i | 280 << mode_string << " found for entry " << i.key() |
| 282 << "; skipping entry"; | 281 << "; skipping entry"; |
| 283 continue; | 282 continue; |
| 284 } | 283 } |
| 285 | 284 |
| 286 domain_state.upgrade_expiry = base::Time::FromDoubleT(expiry); | 285 domain_state.upgrade_expiry = base::Time::FromDoubleT(expiry); |
| 287 domain_state.dynamic_spki_hashes_expiry = | 286 domain_state.dynamic_spki_hashes_expiry = |
| 288 base::Time::FromDoubleT(dynamic_spki_hashes_expiry); | 287 base::Time::FromDoubleT(dynamic_spki_hashes_expiry); |
| 289 if (parsed->GetDouble(kCreated, &created)) { | 288 if (parsed->GetDouble(kCreated, &created)) { |
| 290 domain_state.created = base::Time::FromDoubleT(created); | 289 domain_state.created = base::Time::FromDoubleT(created); |
| 291 } else { | 290 } else { |
| 292 // We're migrating an old entry with no creation date. Make sure we | 291 // We're migrating an old entry with no creation date. Make sure we |
| 293 // write the new date back in a reasonable time frame. | 292 // write the new date back in a reasonable time frame. |
| 294 dirtied = true; | 293 dirtied = true; |
| 295 domain_state.created = base::Time::Now(); | 294 domain_state.created = base::Time::Now(); |
| 296 } | 295 } |
| 297 | 296 |
| 298 if (domain_state.upgrade_expiry <= current_time && | 297 if (domain_state.upgrade_expiry <= current_time && |
| 299 domain_state.dynamic_spki_hashes_expiry <= current_time) { | 298 domain_state.dynamic_spki_hashes_expiry <= current_time) { |
| 300 // Make sure we dirty the state if we drop an entry. | 299 // Make sure we dirty the state if we drop an entry. |
| 301 dirtied = true; | 300 dirtied = true; |
| 302 continue; | 301 continue; |
| 303 } | 302 } |
| 304 | 303 |
| 305 std::string hashed = ExternalStringToHashedDomain(*i); | 304 std::string hashed = ExternalStringToHashedDomain(i.key()); |
| 306 if (hashed.empty()) { | 305 if (hashed.empty()) { |
| 307 dirtied = true; | 306 dirtied = true; |
| 308 continue; | 307 continue; |
| 309 } | 308 } |
| 310 | 309 |
| 311 if (forced) | 310 if (forced) |
| 312 state->AddOrUpdateForcedHosts(hashed, domain_state); | 311 state->AddOrUpdateForcedHosts(hashed, domain_state); |
| 313 else | 312 else |
| 314 state->AddOrUpdateEnabledHosts(hashed, domain_state); | 313 state->AddOrUpdateEnabledHosts(hashed, domain_state); |
| 315 } | 314 } |
| 316 | 315 |
| 317 *dirty = dirtied; | 316 *dirty = dirtied; |
| 318 return true; | 317 return true; |
| 319 } | 318 } |
| 320 | 319 |
| 321 void TransportSecurityPersister::CompleteLoad(const std::string& state) { | 320 void TransportSecurityPersister::CompleteLoad(const std::string& state) { |
| 322 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 321 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 323 | 322 |
| 324 bool dirty = false; | 323 bool dirty = false; |
| 325 if (!LoadEntries(state, &dirty)) { | 324 if (!LoadEntries(state, &dirty)) { |
| 326 LOG(ERROR) << "Failed to deserialize state: " << state; | 325 LOG(ERROR) << "Failed to deserialize state: " << state; |
| 327 return; | 326 return; |
| 328 } | 327 } |
| 329 if (dirty) | 328 if (dirty) |
| 330 StateIsDirty(transport_security_state_); | 329 StateIsDirty(transport_security_state_); |
| 331 } | 330 } |
| OLD | NEW |