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

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: Make use of has_dynamic. Created 6 years, 10 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 130 matching lines...) Expand 10 before | Expand all | Expand 10 after
141 base::DictionaryValue toplevel; 141 base::DictionaryValue toplevel;
142 base::Time now = base::Time::Now(); 142 base::Time now = base::Time::Now();
143 TransportSecurityState::Iterator state(*transport_security_state_); 143 TransportSecurityState::Iterator state(*transport_security_state_);
144 for (; state.HasNext(); state.Advance()) { 144 for (; state.HasNext(); state.Advance()) {
145 const std::string& hostname = state.hostname(); 145 const std::string& hostname = state.hostname();
146 const TransportSecurityState::DomainState& domain_state = 146 const TransportSecurityState::DomainState& domain_state =
147 state.domain_state(); 147 state.domain_state();
148 148
149 base::DictionaryValue* serialized = new base::DictionaryValue; 149 base::DictionaryValue* serialized = new base::DictionaryValue;
150 serialized->SetBoolean(kStsIncludeSubdomains, 150 serialized->SetBoolean(kStsIncludeSubdomains,
151 domain_state.sts_include_subdomains); 151 domain_state.dynamic_sts.include_subdomains);
152 serialized->SetBoolean(kPkpIncludeSubdomains, 152 serialized->SetBoolean(kPkpIncludeSubdomains,
153 domain_state.pkp_include_subdomains); 153 domain_state.dynamic_pkp.include_subdomains);
154 serialized->SetDouble(kStsObserved, domain_state.sts_observed.ToDoubleT()); 154 serialized->SetDouble(kStsObserved,
155 serialized->SetDouble(kPkpObserved, domain_state.pkp_observed.ToDoubleT()); 155 domain_state.dynamic_sts.last_observed.ToDoubleT());
156 serialized->SetDouble(kExpiry, domain_state.upgrade_expiry.ToDoubleT()); 156 serialized->SetDouble(kPkpObserved,
157 domain_state.dynamic_pkp.last_observed.ToDoubleT());
158 serialized->SetDouble(kExpiry, domain_state.dynamic_sts.expiry.ToDoubleT());
157 serialized->SetDouble(kDynamicSPKIHashesExpiry, 159 serialized->SetDouble(kDynamicSPKIHashesExpiry,
158 domain_state.dynamic_spki_hashes_expiry.ToDoubleT()); 160 domain_state.dynamic_pkp.expiry.ToDoubleT());
159 161
160 switch (domain_state.upgrade_mode) { 162 switch (domain_state.dynamic_sts.upgrade_mode) {
161 case TransportSecurityState::DomainState::MODE_FORCE_HTTPS: 163 case TransportSecurityState::DomainState::MODE_FORCE_HTTPS:
162 serialized->SetString(kMode, kForceHTTPS); 164 serialized->SetString(kMode, kForceHTTPS);
163 break; 165 break;
164 case TransportSecurityState::DomainState::MODE_DEFAULT: 166 case TransportSecurityState::DomainState::MODE_DEFAULT:
165 serialized->SetString(kMode, kDefault); 167 serialized->SetString(kMode, kDefault);
166 break; 168 break;
167 default: 169 default:
168 NOTREACHED() << "DomainState with unknown mode"; 170 NOTREACHED() << "DomainState with unknown mode";
169 delete serialized; 171 delete serialized;
170 continue; 172 continue;
171 } 173 }
172 174
173 serialized->Set(kStaticSPKIHashes, 175 serialized->Set(kStaticSPKIHashes,
174 SPKIHashesToListValue(domain_state.static_spki_hashes)); 176 SPKIHashesToListValue(domain_state.static_pkp.spki_hashes));
175 177
176 if (now < domain_state.dynamic_spki_hashes_expiry) { 178 if (now < domain_state.dynamic_pkp.expiry) {
177 serialized->Set(kDynamicSPKIHashes, 179 serialized->Set(kDynamicSPKIHashes,
178 SPKIHashesToListValue(domain_state.dynamic_spki_hashes)); 180 SPKIHashesToListValue(domain_state.dynamic_pkp.spki_hashes));
179 } 181 }
180 182
181 toplevel.Set(HashedDomainToExternalString(hostname), serialized); 183 toplevel.Set(HashedDomainToExternalString(hostname), serialized);
182 } 184 }
183 185
184 base::JSONWriter::WriteWithOptions(&toplevel, 186 base::JSONWriter::WriteWithOptions(&toplevel,
185 base::JSONWriter::OPTIONS_PRETTY_PRINT, 187 base::JSONWriter::OPTIONS_PRETTY_PRINT,
186 output); 188 output);
187 return true; 189 return true;
188 } 190 }
(...skipping 30 matching lines...) Expand all
219 double expiry; 221 double expiry;
220 double dynamic_spki_hashes_expiry = 0.0; 222 double dynamic_spki_hashes_expiry = 0.0;
221 TransportSecurityState::DomainState domain_state; 223 TransportSecurityState::DomainState domain_state;
222 224
223 // kIncludeSubdomains is a legacy synonym for kStsIncludeSubdomains and 225 // kIncludeSubdomains is a legacy synonym for kStsIncludeSubdomains and
224 // kPkpIncludeSubdomains. Parse at least one of these properties, 226 // kPkpIncludeSubdomains. Parse at least one of these properties,
225 // preferably the new ones. 227 // preferably the new ones.
226 bool include_subdomains = false; 228 bool include_subdomains = false;
227 bool parsed_include_subdomains = parsed->GetBoolean(kIncludeSubdomains, 229 bool parsed_include_subdomains = parsed->GetBoolean(kIncludeSubdomains,
228 &include_subdomains); 230 &include_subdomains);
229 domain_state.sts_include_subdomains = include_subdomains; 231 domain_state.dynamic_sts.include_subdomains = include_subdomains;
230 domain_state.pkp_include_subdomains = include_subdomains; 232 domain_state.dynamic_pkp.include_subdomains = include_subdomains;
231 if (parsed->GetBoolean(kStsIncludeSubdomains, &include_subdomains)) { 233 if (parsed->GetBoolean(kStsIncludeSubdomains, &include_subdomains)) {
232 domain_state.sts_include_subdomains = include_subdomains; 234 domain_state.dynamic_sts.include_subdomains = include_subdomains;
233 parsed_include_subdomains = true; 235 parsed_include_subdomains = true;
234 } 236 }
235 if (parsed->GetBoolean(kPkpIncludeSubdomains, &include_subdomains)) { 237 if (parsed->GetBoolean(kPkpIncludeSubdomains, &include_subdomains)) {
236 domain_state.pkp_include_subdomains = include_subdomains; 238 domain_state.dynamic_pkp.include_subdomains = include_subdomains;
237 parsed_include_subdomains = true; 239 parsed_include_subdomains = true;
238 } 240 }
239 241
240 if (!parsed_include_subdomains || 242 if (!parsed_include_subdomains ||
241 !parsed->GetString(kMode, &mode_string) || 243 !parsed->GetString(kMode, &mode_string) ||
242 !parsed->GetDouble(kExpiry, &expiry)) { 244 !parsed->GetDouble(kExpiry, &expiry)) {
243 LOG(WARNING) << "Could not parse some elements of entry " << i.key() 245 LOG(WARNING) << "Could not parse some elements of entry " << i.key()
244 << "; skipping entry"; 246 << "; skipping entry";
245 continue; 247 continue;
246 } 248 }
247 249
248 // Don't fail if this key is not present. 250 // Don't fail if this key is not present.
249 parsed->GetDouble(kDynamicSPKIHashesExpiry, 251 parsed->GetDouble(kDynamicSPKIHashesExpiry,
250 &dynamic_spki_hashes_expiry); 252 &dynamic_spki_hashes_expiry);
251 253
252 const base::ListValue* pins_list = NULL; 254 const base::ListValue* pins_list = NULL;
253 // preloaded_spki_hashes is a legacy synonym for static_spki_hashes. 255 // preloaded_spki_hashes is a legacy synonym for static_spki_hashes.
254 if (parsed->GetList(kStaticSPKIHashes, &pins_list)) 256 if (parsed->GetList(kStaticSPKIHashes, &pins_list))
255 SPKIHashesFromListValue(*pins_list, &domain_state.static_spki_hashes); 257 SPKIHashesFromListValue(*pins_list, &domain_state.static_pkp.spki_hashes);
256 else if (parsed->GetList(kPreloadedSPKIHashes, &pins_list)) 258 else if (parsed->GetList(kPreloadedSPKIHashes, &pins_list))
257 SPKIHashesFromListValue(*pins_list, &domain_state.static_spki_hashes); 259 SPKIHashesFromListValue(*pins_list, &domain_state.static_pkp.spki_hashes);
Ryan Sleevi 2014/01/31 20:24:43 I'm.. surprised.. we're deserializing this still.
palmer 2014/01/31 22:20:51 I've added a TODO and filed a bug to get rid of it
258 260
259 if (parsed->GetList(kDynamicSPKIHashes, &pins_list)) 261 if (parsed->GetList(kDynamicSPKIHashes, &pins_list)) {
260 SPKIHashesFromListValue(*pins_list, &domain_state.dynamic_spki_hashes); 262 SPKIHashesFromListValue(*pins_list,
263 &domain_state.dynamic_pkp.spki_hashes);
264 }
261 265
262 if (mode_string == kForceHTTPS || mode_string == kStrict) { 266 if (mode_string == kForceHTTPS || mode_string == kStrict) {
263 domain_state.upgrade_mode = 267 domain_state.dynamic_sts.upgrade_mode =
264 TransportSecurityState::DomainState::MODE_FORCE_HTTPS; 268 TransportSecurityState::DomainState::MODE_FORCE_HTTPS;
265 } else if (mode_string == kDefault || mode_string == kPinningOnly) { 269 } else if (mode_string == kDefault || mode_string == kPinningOnly) {
266 domain_state.upgrade_mode = 270 domain_state.dynamic_sts.upgrade_mode =
267 TransportSecurityState::DomainState::MODE_DEFAULT; 271 TransportSecurityState::DomainState::MODE_DEFAULT;
268 } else { 272 } else {
269 LOG(WARNING) << "Unknown TransportSecurityState mode string " 273 LOG(WARNING) << "Unknown TransportSecurityState mode string "
270 << mode_string << " found for entry " << i.key() 274 << mode_string << " found for entry " << i.key()
271 << "; skipping entry"; 275 << "; skipping entry";
272 continue; 276 continue;
273 } 277 }
274 278
275 domain_state.upgrade_expiry = base::Time::FromDoubleT(expiry); 279 domain_state.dynamic_sts.expiry = base::Time::FromDoubleT(expiry);
276 domain_state.dynamic_spki_hashes_expiry = 280 domain_state.dynamic_pkp.expiry =
277 base::Time::FromDoubleT(dynamic_spki_hashes_expiry); 281 base::Time::FromDoubleT(dynamic_spki_hashes_expiry);
278 282
279 double sts_observed; 283 double sts_observed;
280 double pkp_observed; 284 double pkp_observed;
281 if (parsed->GetDouble(kStsObserved, &sts_observed)) { 285 if (parsed->GetDouble(kStsObserved, &sts_observed)) {
282 domain_state.sts_observed = base::Time::FromDoubleT(sts_observed); 286 domain_state.dynamic_sts.last_observed =
287 base::Time::FromDoubleT(sts_observed);
283 } else if (parsed->GetDouble(kCreated, &sts_observed)) { 288 } else if (parsed->GetDouble(kCreated, &sts_observed)) {
284 // kCreated is a legacy synonym for both kStsObserved and kPkpObserved. 289 // kCreated is a legacy synonym for both kStsObserved and kPkpObserved.
285 domain_state.sts_observed = base::Time::FromDoubleT(sts_observed); 290 domain_state.dynamic_sts.last_observed =
291 base::Time::FromDoubleT(sts_observed);
286 } else { 292 } else {
287 // We're migrating an old entry with no observation date. Make sure we 293 // We're migrating an old entry with no observation date. Make sure we
288 // write the new date back in a reasonable time frame. 294 // write the new date back in a reasonable time frame.
289 dirtied = true; 295 dirtied = true;
290 domain_state.sts_observed = base::Time::Now(); 296 domain_state.dynamic_sts.last_observed = base::Time::Now();
291 } 297 }
292 if (parsed->GetDouble(kPkpObserved, &pkp_observed)) { 298 if (parsed->GetDouble(kPkpObserved, &pkp_observed)) {
293 domain_state.pkp_observed = base::Time::FromDoubleT(pkp_observed); 299 domain_state.dynamic_pkp.last_observed =
300 base::Time::FromDoubleT(pkp_observed);
294 } else if (parsed->GetDouble(kCreated, &pkp_observed)) { 301 } else if (parsed->GetDouble(kCreated, &pkp_observed)) {
295 domain_state.pkp_observed = base::Time::FromDoubleT(pkp_observed); 302 domain_state.dynamic_pkp.last_observed =
303 base::Time::FromDoubleT(pkp_observed);
296 } else { 304 } else {
297 dirtied = true; 305 dirtied = true;
298 domain_state.pkp_observed = base::Time::Now(); 306 domain_state.dynamic_pkp.last_observed = base::Time::Now();
299 } 307 }
300 308
301 if (domain_state.upgrade_expiry <= current_time && 309 if (domain_state.dynamic_sts.expiry <= current_time &&
302 domain_state.dynamic_spki_hashes_expiry <= current_time) { 310 domain_state.dynamic_pkp.expiry <= current_time) {
303 // Make sure we dirty the state if we drop an entry. 311 // Make sure we dirty the state if we drop an entry.
304 dirtied = true; 312 dirtied = true;
305 continue; 313 continue;
306 } 314 }
307 315
308 std::string hashed = ExternalStringToHashedDomain(i.key()); 316 std::string hashed = ExternalStringToHashedDomain(i.key());
309 if (hashed.empty()) { 317 if (hashed.empty()) {
310 dirtied = true; 318 dirtied = true;
311 continue; 319 continue;
312 } 320 }
(...skipping 14 matching lines...) Expand all
327 bool dirty = false; 335 bool dirty = false;
328 if (!LoadEntries(state, &dirty)) { 336 if (!LoadEntries(state, &dirty)) {
329 LOG(ERROR) << "Failed to deserialize state: " << state; 337 LOG(ERROR) << "Failed to deserialize state: " << state;
330 return; 338 return;
331 } 339 }
332 if (dirty) 340 if (dirty)
333 StateIsDirty(transport_security_state_); 341 StateIsDirty(transport_security_state_);
334 } 342 }
335 343
336 } // namespace net 344 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698