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

Side by Side Diff: net/http/transport_security_persister.cc

Issue 103803012: Make HSTS headers not clobber preloaded pins. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Respond to comments and fix compilation errors. Created 6 years, 7 months 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 | Annotate | Revision Log
OLDNEW
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 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
139 base::DictionaryValue toplevel; 139 base::DictionaryValue toplevel;
140 base::Time now = base::Time::Now(); 140 base::Time now = base::Time::Now();
141 TransportSecurityState::Iterator state(*transport_security_state_); 141 TransportSecurityState::Iterator state(*transport_security_state_);
142 for (; state.HasNext(); state.Advance()) { 142 for (; state.HasNext(); state.Advance()) {
143 const std::string& hostname = state.hostname(); 143 const std::string& hostname = state.hostname();
144 const TransportSecurityState::DomainState& domain_state = 144 const TransportSecurityState::DomainState& domain_state =
145 state.domain_state(); 145 state.domain_state();
146 146
147 base::DictionaryValue* serialized = new base::DictionaryValue; 147 base::DictionaryValue* serialized = new base::DictionaryValue;
148 serialized->SetBoolean(kStsIncludeSubdomains, 148 serialized->SetBoolean(kStsIncludeSubdomains,
149 domain_state.sts_include_subdomains); 149 domain_state.sts.include_subdomains);
150 serialized->SetBoolean(kPkpIncludeSubdomains, 150 serialized->SetBoolean(kPkpIncludeSubdomains,
151 domain_state.pkp_include_subdomains); 151 domain_state.pkp.include_subdomains);
152 serialized->SetDouble(kStsObserved, domain_state.sts_observed.ToDoubleT()); 152 serialized->SetDouble(kStsObserved,
153 serialized->SetDouble(kPkpObserved, domain_state.pkp_observed.ToDoubleT()); 153 domain_state.sts.last_observed.ToDoubleT());
154 serialized->SetDouble(kExpiry, domain_state.upgrade_expiry.ToDoubleT()); 154 serialized->SetDouble(kPkpObserved,
155 domain_state.pkp.last_observed.ToDoubleT());
156 serialized->SetDouble(kExpiry, domain_state.sts.expiry.ToDoubleT());
155 serialized->SetDouble(kDynamicSPKIHashesExpiry, 157 serialized->SetDouble(kDynamicSPKIHashesExpiry,
156 domain_state.dynamic_spki_hashes_expiry.ToDoubleT()); 158 domain_state.pkp.expiry.ToDoubleT());
157 159
158 switch (domain_state.upgrade_mode) { 160 switch (domain_state.sts.upgrade_mode) {
159 case TransportSecurityState::DomainState::MODE_FORCE_HTTPS: 161 case TransportSecurityState::DomainState::MODE_FORCE_HTTPS:
160 serialized->SetString(kMode, kForceHTTPS); 162 serialized->SetString(kMode, kForceHTTPS);
161 break; 163 break;
162 case TransportSecurityState::DomainState::MODE_DEFAULT: 164 case TransportSecurityState::DomainState::MODE_DEFAULT:
163 serialized->SetString(kMode, kDefault); 165 serialized->SetString(kMode, kDefault);
164 break; 166 break;
165 default: 167 default:
166 NOTREACHED() << "DomainState with unknown mode"; 168 NOTREACHED() << "DomainState with unknown mode";
167 delete serialized; 169 delete serialized;
168 continue; 170 continue;
169 } 171 }
170 172
171 if (now < domain_state.dynamic_spki_hashes_expiry) { 173 if (now < domain_state.pkp.expiry) {
172 serialized->Set(kDynamicSPKIHashes, 174 serialized->Set(kDynamicSPKIHashes,
173 SPKIHashesToListValue(domain_state.dynamic_spki_hashes)); 175 SPKIHashesToListValue(domain_state.pkp.spki_hashes));
174 } 176 }
175 177
176 toplevel.Set(HashedDomainToExternalString(hostname), serialized); 178 toplevel.Set(HashedDomainToExternalString(hostname), serialized);
177 } 179 }
178 180
179 base::JSONWriter::WriteWithOptions(&toplevel, 181 base::JSONWriter::WriteWithOptions(&toplevel,
180 base::JSONWriter::OPTIONS_PRETTY_PRINT, 182 base::JSONWriter::OPTIONS_PRETTY_PRINT,
181 output); 183 output);
182 return true; 184 return true;
183 } 185 }
(...skipping 30 matching lines...) Expand all
214 double expiry; 216 double expiry;
215 double dynamic_spki_hashes_expiry = 0.0; 217 double dynamic_spki_hashes_expiry = 0.0;
216 TransportSecurityState::DomainState domain_state; 218 TransportSecurityState::DomainState domain_state;
217 219
218 // kIncludeSubdomains is a legacy synonym for kStsIncludeSubdomains and 220 // kIncludeSubdomains is a legacy synonym for kStsIncludeSubdomains and
219 // kPkpIncludeSubdomains. Parse at least one of these properties, 221 // kPkpIncludeSubdomains. Parse at least one of these properties,
220 // preferably the new ones. 222 // preferably the new ones.
221 bool include_subdomains = false; 223 bool include_subdomains = false;
222 bool parsed_include_subdomains = parsed->GetBoolean(kIncludeSubdomains, 224 bool parsed_include_subdomains = parsed->GetBoolean(kIncludeSubdomains,
223 &include_subdomains); 225 &include_subdomains);
224 domain_state.sts_include_subdomains = include_subdomains; 226 domain_state.sts.include_subdomains = include_subdomains;
225 domain_state.pkp_include_subdomains = include_subdomains; 227 domain_state.pkp.include_subdomains = include_subdomains;
226 if (parsed->GetBoolean(kStsIncludeSubdomains, &include_subdomains)) { 228 if (parsed->GetBoolean(kStsIncludeSubdomains, &include_subdomains)) {
227 domain_state.sts_include_subdomains = include_subdomains; 229 domain_state.sts.include_subdomains = include_subdomains;
228 parsed_include_subdomains = true; 230 parsed_include_subdomains = true;
229 } 231 }
230 if (parsed->GetBoolean(kPkpIncludeSubdomains, &include_subdomains)) { 232 if (parsed->GetBoolean(kPkpIncludeSubdomains, &include_subdomains)) {
231 domain_state.pkp_include_subdomains = include_subdomains; 233 domain_state.pkp.include_subdomains = include_subdomains;
232 parsed_include_subdomains = true; 234 parsed_include_subdomains = true;
233 } 235 }
234 236
235 if (!parsed_include_subdomains || 237 if (!parsed_include_subdomains ||
236 !parsed->GetString(kMode, &mode_string) || 238 !parsed->GetString(kMode, &mode_string) ||
237 !parsed->GetDouble(kExpiry, &expiry)) { 239 !parsed->GetDouble(kExpiry, &expiry)) {
238 LOG(WARNING) << "Could not parse some elements of entry " << i.key() 240 LOG(WARNING) << "Could not parse some elements of entry " << i.key()
239 << "; skipping entry"; 241 << "; skipping entry";
240 continue; 242 continue;
241 } 243 }
242 244
243 // Don't fail if this key is not present. 245 // Don't fail if this key is not present.
244 parsed->GetDouble(kDynamicSPKIHashesExpiry, 246 parsed->GetDouble(kDynamicSPKIHashesExpiry,
245 &dynamic_spki_hashes_expiry); 247 &dynamic_spki_hashes_expiry);
246 248
247 const base::ListValue* pins_list = NULL; 249 const base::ListValue* pins_list = NULL;
248 if (parsed->GetList(kDynamicSPKIHashes, &pins_list)) 250 if (parsed->GetList(kDynamicSPKIHashes, &pins_list)) {
249 SPKIHashesFromListValue(*pins_list, &domain_state.dynamic_spki_hashes); 251 SPKIHashesFromListValue(*pins_list, &domain_state.pkp.spki_hashes);
252 }
250 253
251 if (mode_string == kForceHTTPS || mode_string == kStrict) { 254 if (mode_string == kForceHTTPS || mode_string == kStrict) {
252 domain_state.upgrade_mode = 255 domain_state.sts.upgrade_mode =
253 TransportSecurityState::DomainState::MODE_FORCE_HTTPS; 256 TransportSecurityState::DomainState::MODE_FORCE_HTTPS;
254 } else if (mode_string == kDefault || mode_string == kPinningOnly) { 257 } else if (mode_string == kDefault || mode_string == kPinningOnly) {
255 domain_state.upgrade_mode = 258 domain_state.sts.upgrade_mode =
256 TransportSecurityState::DomainState::MODE_DEFAULT; 259 TransportSecurityState::DomainState::MODE_DEFAULT;
257 } else { 260 } else {
258 LOG(WARNING) << "Unknown TransportSecurityState mode string " 261 LOG(WARNING) << "Unknown TransportSecurityState mode string "
259 << mode_string << " found for entry " << i.key() 262 << mode_string << " found for entry " << i.key()
260 << "; skipping entry"; 263 << "; skipping entry";
261 continue; 264 continue;
262 } 265 }
263 266
264 domain_state.upgrade_expiry = base::Time::FromDoubleT(expiry); 267 domain_state.sts.expiry = base::Time::FromDoubleT(expiry);
265 domain_state.dynamic_spki_hashes_expiry = 268 domain_state.pkp.expiry =
266 base::Time::FromDoubleT(dynamic_spki_hashes_expiry); 269 base::Time::FromDoubleT(dynamic_spki_hashes_expiry);
267 270
268 double sts_observed; 271 double sts_observed;
269 double pkp_observed; 272 double pkp_observed;
270 if (parsed->GetDouble(kStsObserved, &sts_observed)) { 273 if (parsed->GetDouble(kStsObserved, &sts_observed)) {
271 domain_state.sts_observed = base::Time::FromDoubleT(sts_observed); 274 domain_state.sts.last_observed = base::Time::FromDoubleT(sts_observed);
272 } else if (parsed->GetDouble(kCreated, &sts_observed)) { 275 } else if (parsed->GetDouble(kCreated, &sts_observed)) {
273 // kCreated is a legacy synonym for both kStsObserved and kPkpObserved. 276 // kCreated is a legacy synonym for both kStsObserved and kPkpObserved.
274 domain_state.sts_observed = base::Time::FromDoubleT(sts_observed); 277 domain_state.sts.last_observed = base::Time::FromDoubleT(sts_observed);
275 } else { 278 } else {
276 // We're migrating an old entry with no observation date. Make sure we 279 // We're migrating an old entry with no observation date. Make sure we
277 // write the new date back in a reasonable time frame. 280 // write the new date back in a reasonable time frame.
278 dirtied = true; 281 dirtied = true;
279 domain_state.sts_observed = base::Time::Now(); 282 domain_state.sts.last_observed = base::Time::Now();
280 } 283 }
281 if (parsed->GetDouble(kPkpObserved, &pkp_observed)) { 284 if (parsed->GetDouble(kPkpObserved, &pkp_observed)) {
282 domain_state.pkp_observed = base::Time::FromDoubleT(pkp_observed); 285 domain_state.pkp.last_observed = base::Time::FromDoubleT(pkp_observed);
283 } else if (parsed->GetDouble(kCreated, &pkp_observed)) { 286 } else if (parsed->GetDouble(kCreated, &pkp_observed)) {
284 domain_state.pkp_observed = base::Time::FromDoubleT(pkp_observed); 287 domain_state.pkp.last_observed = base::Time::FromDoubleT(pkp_observed);
285 } else { 288 } else {
286 dirtied = true; 289 dirtied = true;
287 domain_state.pkp_observed = base::Time::Now(); 290 domain_state.pkp.last_observed = base::Time::Now();
288 } 291 }
289 292
290 if (domain_state.upgrade_expiry <= current_time && 293 if (domain_state.sts.expiry <= current_time &&
291 domain_state.dynamic_spki_hashes_expiry <= current_time) { 294 domain_state.pkp.expiry <= current_time) {
292 // Make sure we dirty the state if we drop an entry. 295 // Make sure we dirty the state if we drop an entry.
293 dirtied = true; 296 dirtied = true;
294 continue; 297 continue;
295 } 298 }
296 299
297 std::string hashed = ExternalStringToHashedDomain(i.key()); 300 std::string hashed = ExternalStringToHashedDomain(i.key());
298 if (hashed.empty()) { 301 if (hashed.empty()) {
299 dirtied = true; 302 dirtied = true;
300 continue; 303 continue;
301 } 304 }
(...skipping 14 matching lines...) Expand all
316 bool dirty = false; 319 bool dirty = false;
317 if (!LoadEntries(state, &dirty)) { 320 if (!LoadEntries(state, &dirty)) {
318 LOG(ERROR) << "Failed to deserialize state: " << state; 321 LOG(ERROR) << "Failed to deserialize state: " << state;
319 return; 322 return;
320 } 323 }
321 if (dirty) 324 if (dirty)
322 StateIsDirty(transport_security_state_); 325 StateIsDirty(transport_security_state_);
323 } 326 }
324 327
325 } // namespace net 328 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698