| 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 "net/http/transport_security_persister.h" | 5 #include "net/http/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 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 84 std::string LoadState(const base::FilePath& path) { | 84 std::string LoadState(const base::FilePath& path) { |
| 85 std::string result; | 85 std::string result; |
| 86 if (!base::ReadFileToString(path, &result)) { | 86 if (!base::ReadFileToString(path, &result)) { |
| 87 return ""; | 87 return ""; |
| 88 } | 88 } |
| 89 return result; | 89 return result; |
| 90 } | 90 } |
| 91 | 91 |
| 92 } // namespace | 92 } // namespace |
| 93 | 93 |
| 94 | |
| 95 namespace net { | 94 namespace net { |
| 96 | 95 |
| 97 TransportSecurityPersister::TransportSecurityPersister( | 96 TransportSecurityPersister::TransportSecurityPersister( |
| 98 TransportSecurityState* state, | 97 TransportSecurityState* state, |
| 99 const base::FilePath& profile_path, | 98 const base::FilePath& profile_path, |
| 100 base::SequencedTaskRunner* background_runner, | 99 base::SequencedTaskRunner* background_runner, |
| 101 bool readonly) | 100 bool readonly) |
| 102 : transport_security_state_(state), | 101 : transport_security_state_(state), |
| 103 writer_(profile_path.AppendASCII("TransportSecurity"), background_runner), | 102 writer_(profile_path.AppendASCII("TransportSecurity"), background_runner), |
| 104 foreground_runner_(base::MessageLoop::current()->message_loop_proxy()), | 103 foreground_runner_(base::MessageLoop::current()->message_loop_proxy()), |
| (...skipping 12 matching lines...) Expand all Loading... |
| 117 | 116 |
| 118 TransportSecurityPersister::~TransportSecurityPersister() { | 117 TransportSecurityPersister::~TransportSecurityPersister() { |
| 119 DCHECK(foreground_runner_->RunsTasksOnCurrentThread()); | 118 DCHECK(foreground_runner_->RunsTasksOnCurrentThread()); |
| 120 | 119 |
| 121 if (writer_.HasPendingWrite()) | 120 if (writer_.HasPendingWrite()) |
| 122 writer_.DoScheduledWrite(); | 121 writer_.DoScheduledWrite(); |
| 123 | 122 |
| 124 transport_security_state_->SetDelegate(NULL); | 123 transport_security_state_->SetDelegate(NULL); |
| 125 } | 124 } |
| 126 | 125 |
| 127 void TransportSecurityPersister::StateIsDirty( | 126 void TransportSecurityPersister::StateIsDirty(TransportSecurityState* state) { |
| 128 TransportSecurityState* state) { | |
| 129 DCHECK(foreground_runner_->RunsTasksOnCurrentThread()); | 127 DCHECK(foreground_runner_->RunsTasksOnCurrentThread()); |
| 130 DCHECK_EQ(transport_security_state_, state); | 128 DCHECK_EQ(transport_security_state_, state); |
| 131 | 129 |
| 132 if (!readonly_) | 130 if (!readonly_) |
| 133 writer_.ScheduleWrite(this); | 131 writer_.ScheduleWrite(this); |
| 134 } | 132 } |
| 135 | 133 |
| 136 bool TransportSecurityPersister::SerializeData(std::string* output) { | 134 bool TransportSecurityPersister::SerializeData(std::string* output) { |
| 137 DCHECK(foreground_runner_->RunsTasksOnCurrentThread()); | 135 DCHECK(foreground_runner_->RunsTasksOnCurrentThread()); |
| 138 | 136 |
| (...skipping 30 matching lines...) Expand all Loading... |
| 169 } | 167 } |
| 170 | 168 |
| 171 if (now < domain_state.dynamic_spki_hashes_expiry) { | 169 if (now < domain_state.dynamic_spki_hashes_expiry) { |
| 172 serialized->Set(kDynamicSPKIHashes, | 170 serialized->Set(kDynamicSPKIHashes, |
| 173 SPKIHashesToListValue(domain_state.dynamic_spki_hashes)); | 171 SPKIHashesToListValue(domain_state.dynamic_spki_hashes)); |
| 174 } | 172 } |
| 175 | 173 |
| 176 toplevel.Set(HashedDomainToExternalString(hostname), serialized); | 174 toplevel.Set(HashedDomainToExternalString(hostname), serialized); |
| 177 } | 175 } |
| 178 | 176 |
| 179 base::JSONWriter::WriteWithOptions(&toplevel, | 177 base::JSONWriter::WriteWithOptions( |
| 180 base::JSONWriter::OPTIONS_PRETTY_PRINT, | 178 &toplevel, base::JSONWriter::OPTIONS_PRETTY_PRINT, output); |
| 181 output); | |
| 182 return true; | 179 return true; |
| 183 } | 180 } |
| 184 | 181 |
| 185 bool TransportSecurityPersister::LoadEntries(const std::string& serialized, | 182 bool TransportSecurityPersister::LoadEntries(const std::string& serialized, |
| 186 bool* dirty) { | 183 bool* dirty) { |
| 187 DCHECK(foreground_runner_->RunsTasksOnCurrentThread()); | 184 DCHECK(foreground_runner_->RunsTasksOnCurrentThread()); |
| 188 | 185 |
| 189 transport_security_state_->ClearDynamicData(); | 186 transport_security_state_->ClearDynamicData(); |
| 190 return Deserialize(serialized, dirty, transport_security_state_); | 187 return Deserialize(serialized, dirty, transport_security_state_); |
| 191 } | 188 } |
| 192 | 189 |
| 193 // static | 190 // static |
| 194 bool TransportSecurityPersister::Deserialize(const std::string& serialized, | 191 bool TransportSecurityPersister::Deserialize(const std::string& serialized, |
| 195 bool* dirty, | 192 bool* dirty, |
| 196 TransportSecurityState* state) { | 193 TransportSecurityState* state) { |
| 197 scoped_ptr<base::Value> value(base::JSONReader::Read(serialized)); | 194 scoped_ptr<base::Value> value(base::JSONReader::Read(serialized)); |
| 198 base::DictionaryValue* dict_value = NULL; | 195 base::DictionaryValue* dict_value = NULL; |
| 199 if (!value.get() || !value->GetAsDictionary(&dict_value)) | 196 if (!value.get() || !value->GetAsDictionary(&dict_value)) |
| 200 return false; | 197 return false; |
| 201 | 198 |
| 202 const base::Time current_time(base::Time::Now()); | 199 const base::Time current_time(base::Time::Now()); |
| 203 bool dirtied = false; | 200 bool dirtied = false; |
| 204 | 201 |
| 205 for (base::DictionaryValue::Iterator i(*dict_value); | 202 for (base::DictionaryValue::Iterator i(*dict_value); !i.IsAtEnd(); |
| 206 !i.IsAtEnd(); i.Advance()) { | 203 i.Advance()) { |
| 207 const base::DictionaryValue* parsed = NULL; | 204 const base::DictionaryValue* parsed = NULL; |
| 208 if (!i.value().GetAsDictionary(&parsed)) { | 205 if (!i.value().GetAsDictionary(&parsed)) { |
| 209 LOG(WARNING) << "Could not parse entry " << i.key() << "; skipping entry"; | 206 LOG(WARNING) << "Could not parse entry " << i.key() << "; skipping entry"; |
| 210 continue; | 207 continue; |
| 211 } | 208 } |
| 212 | 209 |
| 213 std::string mode_string; | 210 std::string mode_string; |
| 214 double expiry; | 211 double expiry; |
| 215 double dynamic_spki_hashes_expiry = 0.0; | 212 double dynamic_spki_hashes_expiry = 0.0; |
| 216 TransportSecurityState::DomainState domain_state; | 213 TransportSecurityState::DomainState domain_state; |
| 217 | 214 |
| 218 // kIncludeSubdomains is a legacy synonym for kStsIncludeSubdomains and | 215 // kIncludeSubdomains is a legacy synonym for kStsIncludeSubdomains and |
| 219 // kPkpIncludeSubdomains. Parse at least one of these properties, | 216 // kPkpIncludeSubdomains. Parse at least one of these properties, |
| 220 // preferably the new ones. | 217 // preferably the new ones. |
| 221 bool include_subdomains = false; | 218 bool include_subdomains = false; |
| 222 bool parsed_include_subdomains = parsed->GetBoolean(kIncludeSubdomains, | 219 bool parsed_include_subdomains = |
| 223 &include_subdomains); | 220 parsed->GetBoolean(kIncludeSubdomains, &include_subdomains); |
| 224 domain_state.sts_include_subdomains = include_subdomains; | 221 domain_state.sts_include_subdomains = include_subdomains; |
| 225 domain_state.pkp_include_subdomains = include_subdomains; | 222 domain_state.pkp_include_subdomains = include_subdomains; |
| 226 if (parsed->GetBoolean(kStsIncludeSubdomains, &include_subdomains)) { | 223 if (parsed->GetBoolean(kStsIncludeSubdomains, &include_subdomains)) { |
| 227 domain_state.sts_include_subdomains = include_subdomains; | 224 domain_state.sts_include_subdomains = include_subdomains; |
| 228 parsed_include_subdomains = true; | 225 parsed_include_subdomains = true; |
| 229 } | 226 } |
| 230 if (parsed->GetBoolean(kPkpIncludeSubdomains, &include_subdomains)) { | 227 if (parsed->GetBoolean(kPkpIncludeSubdomains, &include_subdomains)) { |
| 231 domain_state.pkp_include_subdomains = include_subdomains; | 228 domain_state.pkp_include_subdomains = include_subdomains; |
| 232 parsed_include_subdomains = true; | 229 parsed_include_subdomains = true; |
| 233 } | 230 } |
| 234 | 231 |
| 235 if (!parsed_include_subdomains || | 232 if (!parsed_include_subdomains || !parsed->GetString(kMode, &mode_string) || |
| 236 !parsed->GetString(kMode, &mode_string) || | |
| 237 !parsed->GetDouble(kExpiry, &expiry)) { | 233 !parsed->GetDouble(kExpiry, &expiry)) { |
| 238 LOG(WARNING) << "Could not parse some elements of entry " << i.key() | 234 LOG(WARNING) << "Could not parse some elements of entry " << i.key() |
| 239 << "; skipping entry"; | 235 << "; skipping entry"; |
| 240 continue; | 236 continue; |
| 241 } | 237 } |
| 242 | 238 |
| 243 // Don't fail if this key is not present. | 239 // Don't fail if this key is not present. |
| 244 parsed->GetDouble(kDynamicSPKIHashesExpiry, | 240 parsed->GetDouble(kDynamicSPKIHashesExpiry, &dynamic_spki_hashes_expiry); |
| 245 &dynamic_spki_hashes_expiry); | |
| 246 | 241 |
| 247 const base::ListValue* pins_list = NULL; | 242 const base::ListValue* pins_list = NULL; |
| 248 if (parsed->GetList(kDynamicSPKIHashes, &pins_list)) | 243 if (parsed->GetList(kDynamicSPKIHashes, &pins_list)) |
| 249 SPKIHashesFromListValue(*pins_list, &domain_state.dynamic_spki_hashes); | 244 SPKIHashesFromListValue(*pins_list, &domain_state.dynamic_spki_hashes); |
| 250 | 245 |
| 251 if (mode_string == kForceHTTPS || mode_string == kStrict) { | 246 if (mode_string == kForceHTTPS || mode_string == kStrict) { |
| 252 domain_state.upgrade_mode = | 247 domain_state.upgrade_mode = |
| 253 TransportSecurityState::DomainState::MODE_FORCE_HTTPS; | 248 TransportSecurityState::DomainState::MODE_FORCE_HTTPS; |
| 254 } else if (mode_string == kDefault || mode_string == kPinningOnly) { | 249 } else if (mode_string == kDefault || mode_string == kPinningOnly) { |
| 255 domain_state.upgrade_mode = | 250 domain_state.upgrade_mode = |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 316 bool dirty = false; | 311 bool dirty = false; |
| 317 if (!LoadEntries(state, &dirty)) { | 312 if (!LoadEntries(state, &dirty)) { |
| 318 LOG(ERROR) << "Failed to deserialize state: " << state; | 313 LOG(ERROR) << "Failed to deserialize state: " << state; |
| 319 return; | 314 return; |
| 320 } | 315 } |
| 321 if (dirty) | 316 if (dirty) |
| 322 StateIsDirty(transport_security_state_); | 317 StateIsDirty(transport_security_state_); |
| 323 } | 318 } |
| 324 | 319 |
| 325 } // namespace net | 320 } // namespace net |
| OLD | NEW |