| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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 "chrome/browser/ssl/chrome_expect_ct_reporter.h" | 5 #include "chrome/browser/ssl/chrome_expect_ct_reporter.h" |
| 6 | 6 |
| 7 #include <string> | 7 #include <string> |
| 8 | 8 |
| 9 #include "base/base64.h" | 9 #include "base/base64.h" |
| 10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
| (...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 229 } | 229 } |
| 230 } | 230 } |
| 231 } | 231 } |
| 232 | 232 |
| 233 // Checks that the |serialized_report| deserializes properly and | 233 // Checks that the |serialized_report| deserializes properly and |
| 234 // contains the correct information (hostname, port, served and | 234 // contains the correct information (hostname, port, served and |
| 235 // validated certificate chains, SCTs) for the given |host_port| and | 235 // validated certificate chains, SCTs) for the given |host_port| and |
| 236 // |ssl_info|. | 236 // |ssl_info|. |
| 237 void CheckExpectCTReport(const std::string& serialized_report, | 237 void CheckExpectCTReport(const std::string& serialized_report, |
| 238 const net::HostPortPair& host_port, | 238 const net::HostPortPair& host_port, |
| 239 const std::string& expiration, |
| 239 const net::SSLInfo& ssl_info) { | 240 const net::SSLInfo& ssl_info) { |
| 240 std::unique_ptr<base::Value> value(base::JSONReader::Read(serialized_report)); | 241 std::unique_ptr<base::Value> value(base::JSONReader::Read(serialized_report)); |
| 241 ASSERT_TRUE(value); | 242 ASSERT_TRUE(value); |
| 242 ASSERT_TRUE(value->IsType(base::Value::Type::DICTIONARY)); | 243 ASSERT_TRUE(value->IsType(base::Value::Type::DICTIONARY)); |
| 243 | 244 |
| 244 base::DictionaryValue* report_dict; | 245 base::DictionaryValue* report_dict; |
| 245 ASSERT_TRUE(value->GetAsDictionary(&report_dict)); | 246 ASSERT_TRUE(value->GetAsDictionary(&report_dict)); |
| 246 | 247 |
| 247 std::string report_hostname; | 248 std::string report_hostname; |
| 248 EXPECT_TRUE(report_dict->GetString("hostname", &report_hostname)); | 249 EXPECT_TRUE(report_dict->GetString("hostname", &report_hostname)); |
| 249 EXPECT_EQ(host_port.host(), report_hostname); | 250 EXPECT_EQ(host_port.host(), report_hostname); |
| 250 int report_port; | 251 int report_port; |
| 251 EXPECT_TRUE(report_dict->GetInteger("port", &report_port)); | 252 EXPECT_TRUE(report_dict->GetInteger("port", &report_port)); |
| 252 EXPECT_EQ(host_port.port(), report_port); | 253 EXPECT_EQ(host_port.port(), report_port); |
| 253 | 254 |
| 255 std::string report_expiration; |
| 256 EXPECT_TRUE( |
| 257 report_dict->GetString("effective-expiration-date", &report_expiration)); |
| 258 EXPECT_EQ(expiration, report_expiration); |
| 259 |
| 254 const base::ListValue* report_served_certificate_chain = nullptr; | 260 const base::ListValue* report_served_certificate_chain = nullptr; |
| 255 ASSERT_TRUE(report_dict->GetList("served-certificate-chain", | 261 ASSERT_TRUE(report_dict->GetList("served-certificate-chain", |
| 256 &report_served_certificate_chain)); | 262 &report_served_certificate_chain)); |
| 257 ASSERT_NO_FATAL_FAILURE(CheckReportCertificateChain( | 263 ASSERT_NO_FATAL_FAILURE(CheckReportCertificateChain( |
| 258 ssl_info.unverified_cert, *report_served_certificate_chain)); | 264 ssl_info.unverified_cert, *report_served_certificate_chain)); |
| 259 | 265 |
| 260 const base::ListValue* report_validated_certificate_chain = nullptr; | 266 const base::ListValue* report_validated_certificate_chain = nullptr; |
| 261 ASSERT_TRUE(report_dict->GetList("validated-certificate-chain", | 267 ASSERT_TRUE(report_dict->GetList("validated-certificate-chain", |
| 262 &report_validated_certificate_chain)); | 268 &report_validated_certificate_chain)); |
| 263 ASSERT_NO_FATAL_FAILURE(CheckReportCertificateChain( | 269 ASSERT_NO_FATAL_FAILURE(CheckReportCertificateChain( |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 315 void TearDown() override { | 321 void TearDown() override { |
| 316 net::URLRequestFilter::GetInstance()->ClearHandlers(); | 322 net::URLRequestFilter::GetInstance()->ClearHandlers(); |
| 317 } | 323 } |
| 318 | 324 |
| 319 net::TestURLRequestContext* context() { return context_.get(); } | 325 net::TestURLRequestContext* context() { return context_.get(); } |
| 320 | 326 |
| 321 protected: | 327 protected: |
| 322 void SendReport(ChromeExpectCTReporter* reporter, | 328 void SendReport(ChromeExpectCTReporter* reporter, |
| 323 const net::HostPortPair& host_port, | 329 const net::HostPortPair& host_port, |
| 324 const GURL& report_uri, | 330 const GURL& report_uri, |
| 331 base::Time expiration, |
| 325 const net::SSLInfo& ssl_info) { | 332 const net::SSLInfo& ssl_info) { |
| 326 base::RunLoop run_loop; | 333 base::RunLoop run_loop; |
| 327 network_delegate_.set_url_request_destroyed_callback( | 334 network_delegate_.set_url_request_destroyed_callback( |
| 328 run_loop.QuitClosure()); | 335 run_loop.QuitClosure()); |
| 329 reporter->OnExpectCTFailed(host_port, report_uri, ssl_info.cert.get(), | 336 reporter->OnExpectCTFailed( |
| 330 ssl_info.unverified_cert.get(), | 337 host_port, report_uri, expiration, ssl_info.cert.get(), |
| 331 ssl_info.signed_certificate_timestamps); | 338 ssl_info.unverified_cert.get(), ssl_info.signed_certificate_timestamps); |
| 332 run_loop.Run(); | 339 run_loop.Run(); |
| 333 } | 340 } |
| 334 | 341 |
| 335 private: | 342 private: |
| 336 TestExpectCTNetworkDelegate network_delegate_; | 343 TestExpectCTNetworkDelegate network_delegate_; |
| 337 std::unique_ptr<net::TestURLRequestContext> context_; | 344 std::unique_ptr<net::TestURLRequestContext> context_; |
| 338 content::TestBrowserThreadBundle thread_bundle_; | 345 content::TestBrowserThreadBundle thread_bundle_; |
| 339 | 346 |
| 340 DISALLOW_COPY_AND_ASSIGN(ChromeExpectCTReporterWaitTest); | 347 DISALLOW_COPY_AND_ASSIGN(ChromeExpectCTReporterWaitTest); |
| 341 }; | 348 }; |
| (...skipping 18 matching lines...) Expand all Loading... |
| 360 | 367 |
| 361 net::SSLInfo ssl_info; | 368 net::SSLInfo ssl_info; |
| 362 ssl_info.cert = | 369 ssl_info.cert = |
| 363 net::ImportCertFromFile(net::GetTestCertsDirectory(), "ok_cert.pem"); | 370 net::ImportCertFromFile(net::GetTestCertsDirectory(), "ok_cert.pem"); |
| 364 ssl_info.unverified_cert = net::ImportCertFromFile( | 371 ssl_info.unverified_cert = net::ImportCertFromFile( |
| 365 net::GetTestCertsDirectory(), "localhost_cert.pem"); | 372 net::GetTestCertsDirectory(), "localhost_cert.pem"); |
| 366 | 373 |
| 367 net::HostPortPair host_port("example.test", 443); | 374 net::HostPortPair host_port("example.test", 443); |
| 368 GURL report_uri("http://example-report.test"); | 375 GURL report_uri("http://example-report.test"); |
| 369 | 376 |
| 370 reporter.OnExpectCTFailed(host_port, report_uri, ssl_info.cert.get(), | 377 reporter.OnExpectCTFailed(host_port, report_uri, base::Time(), |
| 371 ssl_info.unverified_cert.get(), | 378 ssl_info.cert.get(), ssl_info.unverified_cert.get(), |
| 372 ssl_info.signed_certificate_timestamps); | 379 ssl_info.signed_certificate_timestamps); |
| 373 EXPECT_TRUE(sender->latest_report_uri().is_empty()); | 380 EXPECT_TRUE(sender->latest_report_uri().is_empty()); |
| 374 EXPECT_TRUE(sender->latest_serialized_report().empty()); | 381 EXPECT_TRUE(sender->latest_serialized_report().empty()); |
| 375 | 382 |
| 376 histograms.ExpectTotalCount(kSendHistogramName, 0); | 383 histograms.ExpectTotalCount(kSendHistogramName, 0); |
| 377 } | 384 } |
| 378 | 385 |
| 379 // Test that no report is sent if the report URI is empty. | 386 // Test that no report is sent if the report URI is empty. |
| 380 TEST(ChromeExpectCTReporterTest, EmptyReportURI) { | 387 TEST(ChromeExpectCTReporterTest, EmptyReportURI) { |
| 381 base::MessageLoop message_loop; | 388 base::MessageLoop message_loop; |
| 382 base::HistogramTester histograms; | 389 base::HistogramTester histograms; |
| 383 histograms.ExpectTotalCount(kSendHistogramName, 0); | 390 histograms.ExpectTotalCount(kSendHistogramName, 0); |
| 384 | 391 |
| 385 TestCertificateReportSender* sender = new TestCertificateReportSender(); | 392 TestCertificateReportSender* sender = new TestCertificateReportSender(); |
| 386 net::TestURLRequestContext context; | 393 net::TestURLRequestContext context; |
| 387 ChromeExpectCTReporter reporter(&context); | 394 ChromeExpectCTReporter reporter(&context); |
| 388 reporter.report_sender_.reset(sender); | 395 reporter.report_sender_.reset(sender); |
| 389 EXPECT_TRUE(sender->latest_report_uri().is_empty()); | 396 EXPECT_TRUE(sender->latest_report_uri().is_empty()); |
| 390 EXPECT_TRUE(sender->latest_serialized_report().empty()); | 397 EXPECT_TRUE(sender->latest_serialized_report().empty()); |
| 391 | 398 |
| 392 reporter.OnExpectCTFailed(net::HostPortPair(), GURL(), nullptr, nullptr, | 399 reporter.OnExpectCTFailed(net::HostPortPair(), GURL(), base::Time(), nullptr, |
| 400 nullptr, |
| 393 net::SignedCertificateTimestampAndStatusList()); | 401 net::SignedCertificateTimestampAndStatusList()); |
| 394 EXPECT_TRUE(sender->latest_report_uri().is_empty()); | 402 EXPECT_TRUE(sender->latest_report_uri().is_empty()); |
| 395 EXPECT_TRUE(sender->latest_serialized_report().empty()); | 403 EXPECT_TRUE(sender->latest_serialized_report().empty()); |
| 396 | 404 |
| 397 histograms.ExpectTotalCount(kSendHistogramName, 0); | 405 histograms.ExpectTotalCount(kSendHistogramName, 0); |
| 398 } | 406 } |
| 399 | 407 |
| 400 // Test that if a report fails to send, the UMA metric is recorded. | 408 // Test that if a report fails to send, the UMA metric is recorded. |
| 401 TEST_F(ChromeExpectCTReporterWaitTest, SendReportFailure) { | 409 TEST_F(ChromeExpectCTReporterWaitTest, SendReportFailure) { |
| 402 base::HistogramTester histograms; | 410 base::HistogramTester histograms; |
| 403 histograms.ExpectTotalCount(kFailureHistogramName, 0); | 411 histograms.ExpectTotalCount(kFailureHistogramName, 0); |
| 404 histograms.ExpectTotalCount(kSendHistogramName, 0); | 412 histograms.ExpectTotalCount(kSendHistogramName, 0); |
| 405 | 413 |
| 406 ChromeExpectCTReporter reporter(context()); | 414 ChromeExpectCTReporter reporter(context()); |
| 407 | 415 |
| 408 net::SSLInfo ssl_info; | 416 net::SSLInfo ssl_info; |
| 409 ssl_info.cert = | 417 ssl_info.cert = |
| 410 net::ImportCertFromFile(net::GetTestCertsDirectory(), "ok_cert.pem"); | 418 net::ImportCertFromFile(net::GetTestCertsDirectory(), "ok_cert.pem"); |
| 411 ssl_info.unverified_cert = net::ImportCertFromFile( | 419 ssl_info.unverified_cert = net::ImportCertFromFile( |
| 412 net::GetTestCertsDirectory(), "localhost_cert.pem"); | 420 net::GetTestCertsDirectory(), "localhost_cert.pem"); |
| 413 | 421 |
| 414 net::HostPortPair host_port("example.test", 443); | 422 net::HostPortPair host_port("example.test", 443); |
| 415 GURL report_uri( | 423 GURL report_uri( |
| 416 net::URLRequestFailedJob::GetMockHttpUrl(net::ERR_CONNECTION_FAILED)); | 424 net::URLRequestFailedJob::GetMockHttpUrl(net::ERR_CONNECTION_FAILED)); |
| 417 | 425 |
| 418 SendReport(&reporter, host_port, report_uri, ssl_info); | 426 SendReport(&reporter, host_port, report_uri, base::Time(), ssl_info); |
| 419 | 427 |
| 420 histograms.ExpectTotalCount(kFailureHistogramName, 1); | 428 histograms.ExpectTotalCount(kFailureHistogramName, 1); |
| 421 histograms.ExpectBucketCount(kFailureHistogramName, | 429 histograms.ExpectBucketCount(kFailureHistogramName, |
| 422 -net::ERR_CONNECTION_FAILED, 1); | 430 -net::ERR_CONNECTION_FAILED, 1); |
| 423 histograms.ExpectTotalCount(kSendHistogramName, 1); | 431 histograms.ExpectTotalCount(kSendHistogramName, 1); |
| 424 histograms.ExpectBucketCount(kSendHistogramName, true, 1); | 432 histograms.ExpectBucketCount(kSendHistogramName, true, 1); |
| 425 } | 433 } |
| 426 | 434 |
| 427 // Test that a sent report has the right format. | 435 // Test that a sent report has the right format. |
| 428 TEST(ChromeExpectCTReporterTest, SendReport) { | 436 TEST(ChromeExpectCTReporterTest, SendReport) { |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 480 "valid_log_id1", "extensions1", "signature1", now, net::ct::SCT_STATUS_OK, | 488 "valid_log_id1", "extensions1", "signature1", now, net::ct::SCT_STATUS_OK, |
| 481 &ssl_info.signed_certificate_timestamps); | 489 &ssl_info.signed_certificate_timestamps); |
| 482 MakeTestSCTAndStatus(net::ct::SignedCertificateTimestamp::SCT_EMBEDDED, | 490 MakeTestSCTAndStatus(net::ct::SignedCertificateTimestamp::SCT_EMBEDDED, |
| 483 "valid_log_id2", "extensions2", "signature2", now, | 491 "valid_log_id2", "extensions2", "signature2", now, |
| 484 net::ct::SCT_STATUS_OK, | 492 net::ct::SCT_STATUS_OK, |
| 485 &ssl_info.signed_certificate_timestamps); | 493 &ssl_info.signed_certificate_timestamps); |
| 486 | 494 |
| 487 net::HostPortPair host_port("example.test", 443); | 495 net::HostPortPair host_port("example.test", 443); |
| 488 GURL report_uri("http://example-report.test"); | 496 GURL report_uri("http://example-report.test"); |
| 489 | 497 |
| 498 const char kExpirationTimeStr[] = "2017-01-01T00:00:00.000Z"; |
| 499 base::Time expiration; |
| 500 ASSERT_TRUE( |
| 501 base::Time::FromUTCExploded({2017, 1, 0, 1, 0, 0, 0, 0}, &expiration)); |
| 502 |
| 490 // Check that the report is sent and contains the correct information. | 503 // Check that the report is sent and contains the correct information. |
| 491 reporter.OnExpectCTFailed(host_port, report_uri, ssl_info.cert.get(), | 504 reporter.OnExpectCTFailed(host_port, report_uri, expiration, |
| 492 ssl_info.unverified_cert.get(), | 505 ssl_info.cert.get(), ssl_info.unverified_cert.get(), |
| 493 ssl_info.signed_certificate_timestamps); | 506 ssl_info.signed_certificate_timestamps); |
| 494 EXPECT_EQ(report_uri, sender->latest_report_uri()); | 507 EXPECT_EQ(report_uri, sender->latest_report_uri()); |
| 495 EXPECT_FALSE(sender->latest_serialized_report().empty()); | 508 EXPECT_FALSE(sender->latest_serialized_report().empty()); |
| 496 EXPECT_EQ("application/json; charset=utf-8", sender->latest_content_type()); | 509 EXPECT_EQ("application/json; charset=utf-8", sender->latest_content_type()); |
| 497 ASSERT_NO_FATAL_FAILURE(CheckExpectCTReport( | 510 ASSERT_NO_FATAL_FAILURE( |
| 498 sender->latest_serialized_report(), host_port, ssl_info)); | 511 CheckExpectCTReport(sender->latest_serialized_report(), host_port, |
| 512 kExpirationTimeStr, ssl_info)); |
| 499 | 513 |
| 500 histograms.ExpectTotalCount(kFailureHistogramName, 0); | 514 histograms.ExpectTotalCount(kFailureHistogramName, 0); |
| 501 histograms.ExpectTotalCount(kSendHistogramName, 1); | 515 histograms.ExpectTotalCount(kSendHistogramName, 1); |
| 502 histograms.ExpectBucketCount(kSendHistogramName, true, 1); | 516 histograms.ExpectBucketCount(kSendHistogramName, true, 1); |
| 503 } | 517 } |
| OLD | NEW |