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

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: Rebase and refactor. (Not done yet.) Created 6 years, 8 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.sts.include_subdomains);
152 serialized->SetBoolean(kPkpIncludeSubdomains, 152 serialized->SetBoolean(kPkpIncludeSubdomains,
153 domain_state.pkp_include_subdomains); 153 domain_state.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.sts.last_observed.ToDoubleT());
156 serialized->SetDouble(kExpiry, domain_state.upgrade_expiry.ToDoubleT()); 156 serialized->SetDouble(kPkpObserved,
157 domain_state.pkp.last_observed.ToDoubleT());
158 serialized->SetDouble(kExpiry, domain_state.sts.expiry.ToDoubleT());
157 serialized->SetDouble(kDynamicSPKIHashesExpiry, 159 serialized->SetDouble(kDynamicSPKIHashesExpiry,
158 domain_state.dynamic_spki_hashes_expiry.ToDoubleT()); 160 domain_state.pkp.expiry.ToDoubleT());
159 161
160 switch (domain_state.upgrade_mode) { 162 switch (domain_state.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.pkp.spki_hashes));
175 177
176 if (now < domain_state.dynamic_spki_hashes_expiry) { 178 if (now < domain_state.pkp.expiry) {
177 serialized->Set(kDynamicSPKIHashes, 179 serialized->Set(kDynamicSPKIHashes,
178 SPKIHashesToListValue(domain_state.dynamic_spki_hashes)); 180 SPKIHashesToListValue(domain_state.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.sts.include_subdomains = include_subdomains;
230 domain_state.pkp_include_subdomains = include_subdomains; 232 domain_state.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.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.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;
255 // TODO(palmer): crbug.com/339907: Stop deserializing into the static set.
256 //
253 // preloaded_spki_hashes is a legacy synonym for static_spki_hashes. 257 // preloaded_spki_hashes is a legacy synonym for static_spki_hashes.
254 if (parsed->GetList(kStaticSPKIHashes, &pins_list)) 258 if (parsed->GetList(kStaticSPKIHashes, &pins_list))
255 SPKIHashesFromListValue(*pins_list, &domain_state.static_spki_hashes); 259 SPKIHashesFromListValue(*pins_list, &domain_state.pkp.spki_hashes);
256 else if (parsed->GetList(kPreloadedSPKIHashes, &pins_list)) 260 else if (parsed->GetList(kPreloadedSPKIHashes, &pins_list))
257 SPKIHashesFromListValue(*pins_list, &domain_state.static_spki_hashes); 261 SPKIHashesFromListValue(*pins_list, &domain_state.pkp.spki_hashes);
258 262
259 if (parsed->GetList(kDynamicSPKIHashes, &pins_list)) 263 if (parsed->GetList(kDynamicSPKIHashes, &pins_list)) {
260 SPKIHashesFromListValue(*pins_list, &domain_state.dynamic_spki_hashes); 264 SPKIHashesFromListValue(*pins_list,
265 &domain_state.pkp.spki_hashes);
266 }
261 267
262 if (mode_string == kForceHTTPS || mode_string == kStrict) { 268 if (mode_string == kForceHTTPS || mode_string == kStrict) {
263 domain_state.upgrade_mode = 269 domain_state.sts.upgrade_mode =
264 TransportSecurityState::DomainState::MODE_FORCE_HTTPS; 270 TransportSecurityState::DomainState::MODE_FORCE_HTTPS;
265 } else if (mode_string == kDefault || mode_string == kPinningOnly) { 271 } else if (mode_string == kDefault || mode_string == kPinningOnly) {
266 domain_state.upgrade_mode = 272 domain_state.sts.upgrade_mode =
267 TransportSecurityState::DomainState::MODE_DEFAULT; 273 TransportSecurityState::DomainState::MODE_DEFAULT;
268 } else { 274 } else {
269 LOG(WARNING) << "Unknown TransportSecurityState mode string " 275 LOG(WARNING) << "Unknown TransportSecurityState mode string "
270 << mode_string << " found for entry " << i.key() 276 << mode_string << " found for entry " << i.key()
271 << "; skipping entry"; 277 << "; skipping entry";
272 continue; 278 continue;
273 } 279 }
274 280
275 domain_state.upgrade_expiry = base::Time::FromDoubleT(expiry); 281 domain_state.sts.expiry = base::Time::FromDoubleT(expiry);
276 domain_state.dynamic_spki_hashes_expiry = 282 domain_state.pkp.expiry =
277 base::Time::FromDoubleT(dynamic_spki_hashes_expiry); 283 base::Time::FromDoubleT(dynamic_spki_hashes_expiry);
278 284
279 double sts_observed; 285 double sts_observed;
280 double pkp_observed; 286 double pkp_observed;
281 if (parsed->GetDouble(kStsObserved, &sts_observed)) { 287 if (parsed->GetDouble(kStsObserved, &sts_observed)) {
282 domain_state.sts_observed = base::Time::FromDoubleT(sts_observed); 288 domain_state.sts.last_observed =
289 base::Time::FromDoubleT(sts_observed);
283 } else if (parsed->GetDouble(kCreated, &sts_observed)) { 290 } else if (parsed->GetDouble(kCreated, &sts_observed)) {
284 // kCreated is a legacy synonym for both kStsObserved and kPkpObserved. 291 // kCreated is a legacy synonym for both kStsObserved and kPkpObserved.
285 domain_state.sts_observed = base::Time::FromDoubleT(sts_observed); 292 domain_state.sts.last_observed =
293 base::Time::FromDoubleT(sts_observed);
286 } else { 294 } else {
287 // We're migrating an old entry with no observation date. Make sure we 295 // We're migrating an old entry with no observation date. Make sure we
288 // write the new date back in a reasonable time frame. 296 // write the new date back in a reasonable time frame.
289 dirtied = true; 297 dirtied = true;
290 domain_state.sts_observed = base::Time::Now(); 298 domain_state.sts.last_observed = base::Time::Now();
291 } 299 }
292 if (parsed->GetDouble(kPkpObserved, &pkp_observed)) { 300 if (parsed->GetDouble(kPkpObserved, &pkp_observed)) {
293 domain_state.pkp_observed = base::Time::FromDoubleT(pkp_observed); 301 domain_state.pkp.last_observed =
302 base::Time::FromDoubleT(pkp_observed);
294 } else if (parsed->GetDouble(kCreated, &pkp_observed)) { 303 } else if (parsed->GetDouble(kCreated, &pkp_observed)) {
295 domain_state.pkp_observed = base::Time::FromDoubleT(pkp_observed); 304 domain_state.pkp.last_observed =
305 base::Time::FromDoubleT(pkp_observed);
296 } else { 306 } else {
297 dirtied = true; 307 dirtied = true;
298 domain_state.pkp_observed = base::Time::Now(); 308 domain_state.pkp.last_observed = base::Time::Now();
299 } 309 }
300 310
301 if (domain_state.upgrade_expiry <= current_time && 311 if (domain_state.sts.expiry <= current_time &&
302 domain_state.dynamic_spki_hashes_expiry <= current_time) { 312 domain_state.pkp.expiry <= current_time) {
303 // Make sure we dirty the state if we drop an entry. 313 // Make sure we dirty the state if we drop an entry.
304 dirtied = true; 314 dirtied = true;
305 continue; 315 continue;
306 } 316 }
307 317
308 std::string hashed = ExternalStringToHashedDomain(i.key()); 318 std::string hashed = ExternalStringToHashedDomain(i.key());
309 if (hashed.empty()) { 319 if (hashed.empty()) {
310 dirtied = true; 320 dirtied = true;
311 continue; 321 continue;
312 } 322 }
(...skipping 14 matching lines...) Expand all
327 bool dirty = false; 337 bool dirty = false;
328 if (!LoadEntries(state, &dirty)) { 338 if (!LoadEntries(state, &dirty)) {
329 LOG(ERROR) << "Failed to deserialize state: " << state; 339 LOG(ERROR) << "Failed to deserialize state: " << state;
330 return; 340 return;
331 } 341 }
332 if (dirty) 342 if (dirty)
333 StateIsDirty(transport_security_state_); 343 StateIsDirty(transport_security_state_);
334 } 344 }
335 345
336 } // namespace net 346 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698