| 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 == 5) { |
| 332 sql::Statement select( |
| 333 db_->GetUniqueStatement("SELECT host, private_key FROM channel_id")); |
| 334 sql::Statement update( |
| 335 db_->GetUniqueStatement("UPDATE channel_id SET private_key = ?, " |
| 336 "public_key = \"\" WHERE host = ?")); |
| 337 if (!select.is_valid() || !update.is_valid()) { |
| 338 LOG(WARNING) << "Invalid SQL statements to update Channel ID database to " |
| 339 "version 6."; |
| 340 return false; |
| 341 } |
| 342 |
| 343 while (select.Step()) { |
| 344 std::string host = select.ColumnString(0); |
| 345 std::vector<uint8_t> encrypted_private_key, private_key; |
| 346 select.ColumnBlobAsVector(1, &encrypted_private_key); |
| 347 std::unique_ptr<crypto::ECPrivateKey> key( |
| 348 crypto::ECPrivateKey::CreateFromEncryptedPrivateKeyInfo( |
| 349 encrypted_private_key, std::vector<uint8_t>())); |
| 350 if (!key || !key->ExportPrivateKey(&private_key)) { |
| 351 LOG(WARNING) << "Unable to parse encrypted private key when migrating " |
| 352 "Channel ID database to version 6."; |
| 353 continue; |
| 354 } |
| 355 update.Reset(true); |
| 356 update.BindBlob(0, private_key.data(), |
| 357 static_cast<int>(private_key.size())); |
| 358 update.BindString(1, host); |
| 359 if (!update.Run()) { |
| 360 LOG(WARNING) << "UPDATE statement failed when updating Channel ID " |
| 361 "database to version 6."; |
| 362 return false; |
| 363 } |
| 364 } |
| 333 } | 365 } |
| 334 | 366 |
| 335 if (cur_version < kCurrentVersionNumber) { | 367 if (cur_version < kCurrentVersionNumber) { |
| 336 sql::Statement statement( | 368 if (cur_version <= 4) { |
| 337 db_->GetUniqueStatement("DROP TABLE origin_bound_certs")); | 369 sql::Statement statement( |
| 338 if (!statement.Run()) { | 370 db_->GetUniqueStatement("DROP TABLE origin_bound_certs")); |
| 339 LOG(WARNING) << "Error dropping old origin_bound_certs table"; | 371 if (!statement.Run()) { |
| 340 return false; | 372 LOG(WARNING) << "Error dropping old origin_bound_certs table"; |
| 373 return false; |
| 374 } |
| 341 } | 375 } |
| 342 meta_table_.SetVersionNumber(kCurrentVersionNumber); | 376 meta_table_.SetVersionNumber(kCurrentVersionNumber); |
| 343 meta_table_.SetCompatibleVersionNumber(kCompatibleVersionNumber); | 377 meta_table_.SetCompatibleVersionNumber(kCompatibleVersionNumber); |
| 344 } | 378 } |
| 345 transaction.Commit(); | 379 transaction.Commit(); |
| 346 | 380 |
| 347 // Put future migration cases here. | 381 // Put future migration cases here. |
| 348 | 382 |
| 349 return true; | 383 return true; |
| 350 } | 384 } |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 467 pending_.swap(ops); | 501 pending_.swap(ops); |
| 468 num_pending_ = 0; | 502 num_pending_ = 0; |
| 469 } | 503 } |
| 470 | 504 |
| 471 // Maybe an old timer fired or we are already Close()'ed. | 505 // Maybe an old timer fired or we are already Close()'ed. |
| 472 if (!db_.get() || ops.empty()) | 506 if (!db_.get() || ops.empty()) |
| 473 return; | 507 return; |
| 474 | 508 |
| 475 sql::Statement add_statement(db_->GetCachedStatement( | 509 sql::Statement add_statement(db_->GetCachedStatement( |
| 476 SQL_FROM_HERE, | 510 SQL_FROM_HERE, |
| 477 "INSERT INTO channel_id (host, private_key, public_key, " | 511 "INSERT INTO channel_id (host, private_key, public_key, creation_time) " |
| 478 "creation_time) VALUES (?,?,?,?)")); | 512 "VALUES (?,?,\"\",?)")); |
| 479 if (!add_statement.is_valid()) | 513 if (!add_statement.is_valid()) |
| 480 return; | 514 return; |
| 481 | 515 |
| 482 sql::Statement del_statement(db_->GetCachedStatement( | 516 sql::Statement del_statement(db_->GetCachedStatement( |
| 483 SQL_FROM_HERE, "DELETE FROM channel_id WHERE host=?")); | 517 SQL_FROM_HERE, "DELETE FROM channel_id WHERE host=?")); |
| 484 if (!del_statement.is_valid()) | 518 if (!del_statement.is_valid()) |
| 485 return; | 519 return; |
| 486 | 520 |
| 487 sql::Transaction transaction(db_.get()); | 521 sql::Transaction transaction(db_.get()); |
| 488 if (!transaction.Begin()) | 522 if (!transaction.Begin()) |
| 489 return; | 523 return; |
| 490 | 524 |
| 491 for (PendingOperationsList::iterator it = ops.begin(); it != ops.end(); | 525 for (PendingOperationsList::iterator it = ops.begin(); it != ops.end(); |
| 492 ++it) { | 526 ++it) { |
| 493 // Free the certs as we commit them to the database. | 527 // Free the certs as we commit them to the database. |
| 494 std::unique_ptr<PendingOperation> po(*it); | 528 std::unique_ptr<PendingOperation> po(*it); |
| 495 switch (po->op()) { | 529 switch (po->op()) { |
| 496 case PendingOperation::CHANNEL_ID_ADD: { | 530 case PendingOperation::CHANNEL_ID_ADD: { |
| 497 add_statement.Reset(true); | 531 add_statement.Reset(true); |
| 498 add_statement.BindString(0, po->channel_id().server_identifier()); | 532 add_statement.BindString(0, po->channel_id().server_identifier()); |
| 499 std::vector<uint8_t> private_key, public_key; | 533 std::vector<uint8_t> private_key; |
| 500 if (!po->channel_id().key()->ExportEncryptedPrivateKey(&private_key)) | 534 if (!po->channel_id().key()->ExportPrivateKey(&private_key)) |
| 501 continue; | |
| 502 if (!po->channel_id().key()->ExportPublicKey(&public_key)) | |
| 503 continue; | 535 continue; |
| 504 add_statement.BindBlob( | 536 add_statement.BindBlob( |
| 505 1, private_key.data(), static_cast<int>(private_key.size())); | 537 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( | 538 add_statement.BindInt64( |
| 509 3, po->channel_id().creation_time().ToInternalValue()); | 539 2, po->channel_id().creation_time().ToInternalValue()); |
| 510 if (!add_statement.Run()) | 540 if (!add_statement.Run()) |
| 511 NOTREACHED() << "Could not add a server bound cert to the DB."; | 541 NOTREACHED() << "Could not add a server bound cert to the DB."; |
| 512 break; | 542 break; |
| 513 } | 543 } |
| 514 case PendingOperation::CHANNEL_ID_DELETE: | 544 case PendingOperation::CHANNEL_ID_DELETE: |
| 515 del_statement.Reset(true); | 545 del_statement.Reset(true); |
| 516 del_statement.BindString(0, po->channel_id().server_identifier()); | 546 del_statement.BindString(0, po->channel_id().server_identifier()); |
| 517 if (!del_statement.Run()) | 547 if (!del_statement.Run()) |
| 518 NOTREACHED() << "Could not delete a server bound cert from the DB."; | 548 NOTREACHED() << "Could not delete a server bound cert from the DB."; |
| 519 break; | 549 break; |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 611 backend_->SetForceKeepSessionState(); | 641 backend_->SetForceKeepSessionState(); |
| 612 } | 642 } |
| 613 | 643 |
| 614 SQLiteChannelIDStore::~SQLiteChannelIDStore() { | 644 SQLiteChannelIDStore::~SQLiteChannelIDStore() { |
| 615 backend_->Close(); | 645 backend_->Close(); |
| 616 // We release our reference to the Backend, though it will probably still have | 646 // 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. | 647 // a reference if the background task runner has not run Close() yet. |
| 618 } | 648 } |
| 619 | 649 |
| 620 } // namespace net | 650 } // namespace net |
| OLD | NEW |