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 |