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 |