OLD | NEW |
---|---|
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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/extras/sqlite/sqlite_channel_id_store.h" | 5 #include "net/extras/sqlite/sqlite_channel_id_store.h" |
6 | 6 |
7 #include <memory> | 7 #include <memory> |
8 #include <set> | 8 #include <set> |
9 #include <utility> | 9 #include <utility> |
10 #include <vector> | 10 #include <vector> |
(...skipping 15 matching lines...) Expand all Loading... | |
26 #include "net/ssl/ssl_client_cert_type.h" | 26 #include "net/ssl/ssl_client_cert_type.h" |
27 #include "sql/error_delegate_util.h" | 27 #include "sql/error_delegate_util.h" |
28 #include "sql/meta_table.h" | 28 #include "sql/meta_table.h" |
29 #include "sql/statement.h" | 29 #include "sql/statement.h" |
30 #include "sql/transaction.h" | 30 #include "sql/transaction.h" |
31 #include "url/gurl.h" | 31 #include "url/gurl.h" |
32 | 32 |
33 namespace { | 33 namespace { |
34 | 34 |
35 // Version number of the database. | 35 // Version number of the database. |
36 const int kCurrentVersionNumber = 5; | 36 const int kCurrentVersionNumber = 6; |
37 const int kCompatibleVersionNumber = 5; | 37 const int kCompatibleVersionNumber = 6; |
38 | 38 |
39 } // namespace | 39 } // namespace |
40 | 40 |
41 namespace net { | 41 namespace net { |
42 | 42 |
43 // This class is designed to be shared between any calling threads and the | 43 // This class is designed to be shared between any calling threads and the |
44 // background task runner. It batches operations and commits them on a timer. | 44 // background task runner. It batches operations and commits them on a timer. |
45 class SQLiteChannelIDStore::Backend | 45 class SQLiteChannelIDStore::Backend |
46 : public base::RefCountedThreadSafe<SQLiteChannelIDStore::Backend> { | 46 : public base::RefCountedThreadSafe<SQLiteChannelIDStore::Backend> { |
47 public: | 47 public: |
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
205 KillDatabase(); | 205 KillDatabase(); |
206 meta_table_.Reset(); | 206 meta_table_.Reset(); |
207 db_.reset(); | 207 db_.reset(); |
208 return; | 208 return; |
209 } | 209 } |
210 | 210 |
211 db_->Preload(); | 211 db_->Preload(); |
212 | 212 |
213 // Slurp all the certs into the out-vector. | 213 // Slurp all the certs into the out-vector. |
214 sql::Statement smt(db_->GetUniqueStatement( | 214 sql::Statement smt(db_->GetUniqueStatement( |
215 "SELECT host, private_key, public_key, creation_time FROM channel_id")); | 215 "SELECT host, private_key, creation_time FROM channel_id")); |
216 if (!smt.is_valid()) { | 216 if (!smt.is_valid()) { |
217 if (corruption_detected_) | 217 if (corruption_detected_) |
218 KillDatabase(); | 218 KillDatabase(); |
219 meta_table_.Reset(); | 219 meta_table_.Reset(); |
220 db_.reset(); | 220 db_.reset(); |
221 return; | 221 return; |
222 } | 222 } |
223 | 223 |
224 while (smt.Step()) { | 224 while (smt.Step()) { |
225 std::vector<uint8_t> private_key_from_db, public_key_from_db; | 225 std::vector<uint8_t> private_key_from_db; |
226 smt.ColumnBlobAsVector(1, &private_key_from_db); | 226 smt.ColumnBlobAsVector(1, &private_key_from_db); |
227 smt.ColumnBlobAsVector(2, &public_key_from_db); | |
228 std::unique_ptr<crypto::ECPrivateKey> key( | 227 std::unique_ptr<crypto::ECPrivateKey> key( |
229 crypto::ECPrivateKey::CreateFromEncryptedPrivateKeyInfo( | 228 crypto::ECPrivateKey::CreateFromPrivateKeyInfo(private_key_from_db)); |
230 private_key_from_db, public_key_from_db)); | |
231 if (!key) | 229 if (!key) |
232 continue; | 230 continue; |
233 std::unique_ptr<DefaultChannelIDStore::ChannelID> channel_id( | 231 std::unique_ptr<DefaultChannelIDStore::ChannelID> channel_id( |
234 new DefaultChannelIDStore::ChannelID( | 232 new DefaultChannelIDStore::ChannelID( |
235 smt.ColumnString(0), // host | 233 smt.ColumnString(0), // host |
236 base::Time::FromInternalValue(smt.ColumnInt64(3)), std::move(key))); | 234 base::Time::FromInternalValue(smt.ColumnInt64(2)), std::move(key))); |
237 channel_ids->push_back(std::move(channel_id)); | 235 channel_ids->push_back(std::move(channel_id)); |
238 } | 236 } |
239 | 237 |
240 UMA_HISTOGRAM_COUNTS_10000( | 238 UMA_HISTOGRAM_COUNTS_10000( |
241 "DomainBoundCerts.DBLoadedCount", | 239 "DomainBoundCerts.DBLoadedCount", |
242 static_cast<base::HistogramBase::Sample>(channel_ids->size())); | 240 static_cast<base::HistogramBase::Sample>(channel_ids->size())); |
243 base::TimeDelta load_time = base::TimeTicks::Now() - start; | 241 base::TimeDelta load_time = base::TimeTicks::Now() - start; |
244 UMA_HISTOGRAM_CUSTOM_TIMES("DomainBoundCerts.DBLoadTime", | 242 UMA_HISTOGRAM_CUSTOM_TIMES("DomainBoundCerts.DBLoadTime", |
245 load_time, | 243 load_time, |
246 base::TimeDelta::FromMilliseconds(1), | 244 base::TimeDelta::FromMilliseconds(1), |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
279 return false; | 277 return false; |
280 } | 278 } |
281 } | 279 } |
282 | 280 |
283 // Migrate from previous versions to new version if possible | 281 // Migrate from previous versions to new version if possible |
284 if (cur_version >= 2 && cur_version <= 4) { | 282 if (cur_version >= 2 && cur_version <= 4) { |
285 sql::Statement statement(db_->GetUniqueStatement( | 283 sql::Statement statement(db_->GetUniqueStatement( |
286 "SELECT origin, cert, private_key, cert_type FROM origin_bound_certs")); | 284 "SELECT origin, cert, private_key, cert_type FROM origin_bound_certs")); |
287 sql::Statement insert_statement(db_->GetUniqueStatement( | 285 sql::Statement insert_statement(db_->GetUniqueStatement( |
288 "INSERT INTO channel_id (host, private_key, public_key, creation_time) " | 286 "INSERT INTO channel_id (host, private_key, public_key, creation_time) " |
289 "VALUES (?, ?, ?, ?)")); | 287 "VALUES (?, ?, \"\", ?)")); |
290 if (!statement.is_valid() || !insert_statement.is_valid()) { | 288 if (!statement.is_valid() || !insert_statement.is_valid()) { |
291 LOG(WARNING) << "Unable to update server bound cert database to " | 289 LOG(WARNING) << "Unable to update server bound cert database to " |
292 << "version 5."; | 290 << "version 6."; |
293 return false; | 291 return false; |
294 } | 292 } |
295 | 293 |
296 while (statement.Step()) { | 294 while (statement.Step()) { |
297 if (statement.ColumnInt64(3) != CLIENT_CERT_ECDSA_SIGN) | 295 if (statement.ColumnInt64(3) != CLIENT_CERT_ECDSA_SIGN) |
298 continue; | 296 continue; |
299 std::string origin = statement.ColumnString(0); | 297 std::string origin = statement.ColumnString(0); |
300 std::string cert_from_db; | 298 std::string cert_from_db; |
301 statement.ColumnBlobAsString(1, &cert_from_db); | 299 statement.ColumnBlobAsString(1, &cert_from_db); |
302 std::string private_key; | 300 std::vector<uint8_t> encrypted_private_key, private_key; |
303 statement.ColumnBlobAsString(2, &private_key); | 301 statement.ColumnBlobAsVector(2, &encrypted_private_key); |
302 std::unique_ptr<crypto::ECPrivateKey> key( | |
303 crypto::ECPrivateKey::CreateFromEncryptedPrivateKeyInfo( | |
304 encrypted_private_key, std::vector<uint8_t>())); | |
305 if (!key || !key->ExportPrivateKey(&private_key)) { | |
306 LOG(WARNING) << "Unable to parse encrypted private key when migrating " | |
307 "Channel ID database to version 6."; | |
308 continue; | |
309 } | |
304 // Parse the cert and extract the real value and then update the DB. | 310 // Parse the cert and extract the real value and then update the DB. |
305 scoped_refptr<X509Certificate> cert(X509Certificate::CreateFromBytes( | 311 scoped_refptr<X509Certificate> cert(X509Certificate::CreateFromBytes( |
306 cert_from_db.data(), static_cast<int>(cert_from_db.size()))); | 312 cert_from_db.data(), static_cast<int>(cert_from_db.size()))); |
307 if (cert.get()) { | 313 if (cert.get()) { |
308 insert_statement.Reset(true); | 314 insert_statement.Reset(true); |
309 insert_statement.BindString(0, origin); | 315 insert_statement.BindString(0, origin); |
310 insert_statement.BindBlob(1, private_key.data(), | 316 insert_statement.BindBlob(1, private_key.data(), |
311 static_cast<int>(private_key.size())); | 317 static_cast<int>(private_key.size())); |
312 base::StringPiece spki; | 318 insert_statement.BindInt64(2, cert->valid_start().ToInternalValue()); |
313 if (!asn1::ExtractSPKIFromDERCert(cert_from_db, &spki)) { | |
314 LOG(WARNING) << "Unable to extract SPKI from cert when migrating " | |
315 "channel id database to version 5."; | |
316 return false; | |
317 } | |
318 insert_statement.BindBlob(2, spki.data(), | |
319 static_cast<int>(spki.size())); | |
320 insert_statement.BindInt64(3, cert->valid_start().ToInternalValue()); | |
321 if (!insert_statement.Run()) { | 319 if (!insert_statement.Run()) { |
322 LOG(WARNING) << "Unable to update channel id database to " | 320 LOG(WARNING) << "Unable to update channel id database to " |
323 << "version 5."; | 321 << "version 6."; |
324 return false; | 322 return false; |
325 } | 323 } |
326 } else { | 324 } else { |
327 // If there's a cert we can't parse, just leave it. It'll get replaced | 325 // If there's a cert we can't parse, just leave it. It'll get replaced |
328 // with a new one if we ever try to use it. | 326 // with a new one if we ever try to use it. |
329 LOG(WARNING) << "Error parsing cert for database upgrade for origin " | 327 LOG(WARNING) << "Error parsing cert for database upgrade for origin " |
330 << statement.ColumnString(0); | 328 << statement.ColumnString(0); |
331 } | 329 } |
332 } | 330 } |
331 } else if (cur_version >= 2 && cur_version <= 5) { | |
mattm
2017/04/04 22:44:24
Should be cur_version == 5? or maybe (cur_version
nharper
2017/04/04 23:01:31
Done.
| |
332 sql::Statement select( | |
333 db_->GetUniqueStatement("SELECT host, private_key FROM channel_id")); | |
334 sql::Statement update(db_->GetUniqueStatement( | |
335 "UPDATE channel_id SET private_key = ? WHERE host = ?")); | |
mattm
2017/04/04 22:44:24
Also set public_key to "" here?
nharper
2017/04/04 23:01:31
Done.
| |
336 if (!select.is_valid() || !update.is_valid()) { | |
337 LOG(WARNING) << "Invalid SQL statements to update Channel ID database to " | |
338 "version 6."; | |
339 return false; | |
340 } | |
341 | |
342 while (select.Step()) { | |
343 std::string host = select.ColumnString(0); | |
344 std::vector<uint8_t> encrypted_private_key, private_key; | |
345 select.ColumnBlobAsVector(1, &encrypted_private_key); | |
346 std::unique_ptr<crypto::ECPrivateKey> key( | |
347 crypto::ECPrivateKey::CreateFromEncryptedPrivateKeyInfo( | |
348 encrypted_private_key, std::vector<uint8_t>())); | |
349 if (!key || !key->ExportPrivateKey(&private_key)) { | |
350 LOG(WARNING) << "Unable to parse encrypted private key when migrating " | |
351 "Channel ID database to version 6."; | |
352 continue; | |
353 } | |
354 update.Reset(true); | |
355 update.BindBlob(0, private_key.data(), | |
356 static_cast<int>(private_key.size())); | |
357 update.BindString(1, host); | |
358 if (!update.Run()) { | |
359 LOG(WARNING) << "UPDATE statement failed when updating Channel ID " | |
360 "database to version 6."; | |
361 return false; | |
362 } | |
363 } | |
333 } | 364 } |
334 | 365 |
335 if (cur_version < kCurrentVersionNumber) { | 366 if (cur_version < kCurrentVersionNumber) { |
336 sql::Statement statement( | 367 if (cur_version <= 4) { |
337 db_->GetUniqueStatement("DROP TABLE origin_bound_certs")); | 368 sql::Statement statement( |
338 if (!statement.Run()) { | 369 db_->GetUniqueStatement("DROP TABLE origin_bound_certs")); |
339 LOG(WARNING) << "Error dropping old origin_bound_certs table"; | 370 if (!statement.Run()) { |
340 return false; | 371 LOG(WARNING) << "Error dropping old origin_bound_certs table"; |
372 return false; | |
373 } | |
341 } | 374 } |
342 meta_table_.SetVersionNumber(kCurrentVersionNumber); | 375 meta_table_.SetVersionNumber(kCurrentVersionNumber); |
343 meta_table_.SetCompatibleVersionNumber(kCompatibleVersionNumber); | 376 meta_table_.SetCompatibleVersionNumber(kCompatibleVersionNumber); |
344 } | 377 } |
345 transaction.Commit(); | 378 transaction.Commit(); |
346 | 379 |
347 // Put future migration cases here. | 380 // Put future migration cases here. |
348 | 381 |
349 return true; | 382 return true; |
350 } | 383 } |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
467 pending_.swap(ops); | 500 pending_.swap(ops); |
468 num_pending_ = 0; | 501 num_pending_ = 0; |
469 } | 502 } |
470 | 503 |
471 // Maybe an old timer fired or we are already Close()'ed. | 504 // Maybe an old timer fired or we are already Close()'ed. |
472 if (!db_.get() || ops.empty()) | 505 if (!db_.get() || ops.empty()) |
473 return; | 506 return; |
474 | 507 |
475 sql::Statement add_statement(db_->GetCachedStatement( | 508 sql::Statement add_statement(db_->GetCachedStatement( |
476 SQL_FROM_HERE, | 509 SQL_FROM_HERE, |
477 "INSERT INTO channel_id (host, private_key, public_key, " | 510 "INSERT INTO channel_id (host, private_key, public_key, creation_time) " |
478 "creation_time) VALUES (?,?,?,?)")); | 511 "VALUES (?,?,\"\",?)")); |
479 if (!add_statement.is_valid()) | 512 if (!add_statement.is_valid()) |
480 return; | 513 return; |
481 | 514 |
482 sql::Statement del_statement(db_->GetCachedStatement( | 515 sql::Statement del_statement(db_->GetCachedStatement( |
483 SQL_FROM_HERE, "DELETE FROM channel_id WHERE host=?")); | 516 SQL_FROM_HERE, "DELETE FROM channel_id WHERE host=?")); |
484 if (!del_statement.is_valid()) | 517 if (!del_statement.is_valid()) |
485 return; | 518 return; |
486 | 519 |
487 sql::Transaction transaction(db_.get()); | 520 sql::Transaction transaction(db_.get()); |
488 if (!transaction.Begin()) | 521 if (!transaction.Begin()) |
489 return; | 522 return; |
490 | 523 |
491 for (PendingOperationsList::iterator it = ops.begin(); it != ops.end(); | 524 for (PendingOperationsList::iterator it = ops.begin(); it != ops.end(); |
492 ++it) { | 525 ++it) { |
493 // Free the certs as we commit them to the database. | 526 // Free the certs as we commit them to the database. |
494 std::unique_ptr<PendingOperation> po(*it); | 527 std::unique_ptr<PendingOperation> po(*it); |
495 switch (po->op()) { | 528 switch (po->op()) { |
496 case PendingOperation::CHANNEL_ID_ADD: { | 529 case PendingOperation::CHANNEL_ID_ADD: { |
497 add_statement.Reset(true); | 530 add_statement.Reset(true); |
498 add_statement.BindString(0, po->channel_id().server_identifier()); | 531 add_statement.BindString(0, po->channel_id().server_identifier()); |
499 std::vector<uint8_t> private_key, public_key; | 532 std::vector<uint8_t> private_key; |
500 if (!po->channel_id().key()->ExportEncryptedPrivateKey(&private_key)) | 533 if (!po->channel_id().key()->ExportPrivateKey(&private_key)) |
501 continue; | |
502 if (!po->channel_id().key()->ExportPublicKey(&public_key)) | |
503 continue; | 534 continue; |
504 add_statement.BindBlob( | 535 add_statement.BindBlob( |
505 1, private_key.data(), static_cast<int>(private_key.size())); | 536 1, private_key.data(), static_cast<int>(private_key.size())); |
506 add_statement.BindBlob(2, public_key.data(), | |
507 static_cast<int>(public_key.size())); | |
508 add_statement.BindInt64( | 537 add_statement.BindInt64( |
509 3, po->channel_id().creation_time().ToInternalValue()); | 538 2, po->channel_id().creation_time().ToInternalValue()); |
510 if (!add_statement.Run()) | 539 if (!add_statement.Run()) |
511 NOTREACHED() << "Could not add a server bound cert to the DB."; | 540 NOTREACHED() << "Could not add a server bound cert to the DB."; |
512 break; | 541 break; |
513 } | 542 } |
514 case PendingOperation::CHANNEL_ID_DELETE: | 543 case PendingOperation::CHANNEL_ID_DELETE: |
515 del_statement.Reset(true); | 544 del_statement.Reset(true); |
516 del_statement.BindString(0, po->channel_id().server_identifier()); | 545 del_statement.BindString(0, po->channel_id().server_identifier()); |
517 if (!del_statement.Run()) | 546 if (!del_statement.Run()) |
518 NOTREACHED() << "Could not delete a server bound cert from the DB."; | 547 NOTREACHED() << "Could not delete a server bound cert from the DB."; |
519 break; | 548 break; |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
611 backend_->SetForceKeepSessionState(); | 640 backend_->SetForceKeepSessionState(); |
612 } | 641 } |
613 | 642 |
614 SQLiteChannelIDStore::~SQLiteChannelIDStore() { | 643 SQLiteChannelIDStore::~SQLiteChannelIDStore() { |
615 backend_->Close(); | 644 backend_->Close(); |
616 // We release our reference to the Backend, though it will probably still have | 645 // We release our reference to the Backend, though it will probably still have |
617 // a reference if the background task runner has not run Close() yet. | 646 // a reference if the background task runner has not run Close() yet. |
618 } | 647 } |
619 | 648 |
620 } // namespace net | 649 } // namespace net |
OLD | NEW |