diff options
Diffstat (limited to 'chrome')
-rw-r--r-- | chrome/browser/net/cert_logger.proto | 49 | ||||
-rw-r--r-- | chrome/browser/net/chrome_fraudulent_certificate_reporter.cc | 153 | ||||
-rw-r--r-- | chrome/browser/net/chrome_fraudulent_certificate_reporter.h | 61 | ||||
-rw-r--r-- | chrome/browser/net/chrome_fraudulent_certificate_reporter_unittest.cc | 201 | ||||
-rw-r--r-- | chrome/chrome_browser.gypi | 15 | ||||
-rw-r--r-- | chrome/chrome_tests.gypi | 1 |
6 files changed, 0 insertions, 480 deletions
diff --git a/chrome/browser/net/cert_logger.proto b/chrome/browser/net/cert_logger.proto deleted file mode 100644 index e09ed2a..0000000 --- a/chrome/browser/net/cert_logger.proto +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. -// -// This protobuffer is intended to store reports from Chrome users of -// certificate pinning errors. A report will be sent from Chrome when it gets -// e.g. a certificate for google.com that chains up to a root CA not expected by -// Chrome for that origin, such as DigiNotar (compromised in July 2011), or -// other pinning errors such as a blacklisted cert in the chain. The -// report from the user will include the hostname being accessed, -// the full certificate chain (in PEM format), and the -// timestamp of when the client tried to access the site. A response is -// generated by the frontend and logged, including validation and error checking -// done on the client's input data. - - -syntax = "proto2"; - -package chrome_browser_net; - -// Chrome requires this. -option optimize_for = LITE_RUNTIME; - -// Protocol types -message CertLoggerRequest { - // The hostname being accessed (required as the cert could be valid for - // multiple hosts, e.g. a wildcard or a SubjectAltName. - required string hostname = 1; - // The certificate chain as a series of PEM-encoded certificates, including - // intermediates but not necessarily the root. - required string cert_chain = 2; - // The time (in usec since the epoch) when the client attempted to access the - // site generating the pinning error. - required int64 time_usec = 3; -}; - -// The response sent back to the user. -message CertLoggerResponse { - enum ResponseCode { - OK = 1; - MALFORMED_CERT_DATA = 2; - HOST_CERT_DONT_MATCH = 3; - ROOT_NOT_RECOGNIZED = 4; - ROOT_NOT_UNEXPECTED = 5; - OTHER_ERROR = 6; - }; - required ResponseCode response = 1; -}; - diff --git a/chrome/browser/net/chrome_fraudulent_certificate_reporter.cc b/chrome/browser/net/chrome_fraudulent_certificate_reporter.cc deleted file mode 100644 index bb1b028..0000000 --- a/chrome/browser/net/chrome_fraudulent_certificate_reporter.cc +++ /dev/null @@ -1,153 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/net/chrome_fraudulent_certificate_reporter.h" - -#include <set> - -#include "base/base64.h" -#include "base/logging.h" -#include "base/stl_util.h" -#include "base/time.h" -#include "chrome/browser/net/cert_logger.pb.h" -#include "net/base/ssl_info.h" -#include "net/base/x509_certificate.h" -#include "net/url_request/url_request_context.h" - -namespace chrome_browser_net { - -ChromeFraudulentCertificateReporter::ChromeFraudulentCertificateReporter( - net::URLRequestContext* request_context) - : request_context_(request_context), - upload_url_(FRAUDULENT_CERTIFICATE_UPLOAD_ENDPOINT) { -} - -ChromeFraudulentCertificateReporter::~ChromeFraudulentCertificateReporter() { - STLDeleteElements(&inflight_requests_); -} - -// TODO(palmer): Move this to some globally-visible utility module. -static bool DerToPem(const std::string& der_certificate, std::string* output) { - std::string b64_encoded; - if (!base::Base64Encode(der_certificate, &b64_encoded)) - return false; - - *output = "-----BEGIN CERTIFICATE-----\r\n"; - - size_t size = b64_encoded.size(); - for (size_t i = 0; i < size; ) { - size_t todo = size - i; - if (todo > 64) - todo = 64; - *output += b64_encoded.substr(i, todo); - *output += "\r\n"; - i += todo; - } - - *output += "-----END CERTIFICATE-----\r\n"; - return true; -} - -static std::string BuildReport( - const std::string& hostname, - const net::SSLInfo& ssl_info) { - CertLoggerRequest request; - base::Time now = base::Time::Now(); - request.set_time_usec(now.ToInternalValue()); - request.set_hostname(hostname); - - std::string der_encoded, pem_encoded; - - net::X509Certificate* certificate = ssl_info.cert; - if (!certificate->GetDEREncoded(&der_encoded) || - !DerToPem(der_encoded, &pem_encoded)) { - LOG(ERROR) << "Could not PEM encode DER certificate"; - } - - std::string* cert_chain = request.mutable_cert_chain(); - *cert_chain += pem_encoded; - - const net::X509Certificate::OSCertHandles& intermediates = - certificate->GetIntermediateCertificates(); - - for (net::X509Certificate::OSCertHandles::const_iterator - i = intermediates.begin(); i != intermediates.end(); ++i) { - scoped_refptr<net::X509Certificate> cert = - net::X509Certificate::CreateFromHandle(*i, intermediates); - - if (!cert->GetDEREncoded(&der_encoded) || - !DerToPem(der_encoded, &pem_encoded)) { - LOG(ERROR) << "Could not PEM encode DER certificate"; - continue; - } - - *cert_chain += pem_encoded; - } - - std::string out; - request.SerializeToString(&out); - return out; -} - -net::URLRequest* ChromeFraudulentCertificateReporter::CreateURLRequest() { - return new net::URLRequest(upload_url_, this); -} - -void ChromeFraudulentCertificateReporter::SendReport( - const std::string& hostname, - const net::SSLInfo& ssl_info, - bool sni_available) { - // We do silent/automatic reporting ONLY for Google properties. For other - // domains (when we start supporting that), we will ask for user permission. - if (!net::TransportSecurityState::IsGooglePinnedProperty(hostname, - sni_available)) { - return; - } - - std::string report = BuildReport(hostname, ssl_info); - - net::URLRequest* url_request = CreateURLRequest(); - url_request->set_context(request_context_); - url_request->set_method("POST"); - url_request->AppendBytesToUpload(report.data(), report.size()); - - net::HttpRequestHeaders headers; - headers.SetHeader(net::HttpRequestHeaders::kContentType, - "x-application/chrome-fraudulent-cert-report"); - url_request->SetExtraRequestHeaders(headers); - - inflight_requests_.insert(url_request); - url_request->Start(); -} - -void ChromeFraudulentCertificateReporter::RequestComplete( - net::URLRequest* request) { - std::set<net::URLRequest*>::iterator i = inflight_requests_.find(request); - DCHECK(i != inflight_requests_.end()); - delete *i; - inflight_requests_.erase(i); -} - -// TODO(palmer): Currently, the upload is fire-and-forget but soon we will -// try to recover by retrying, and trying different endpoints, and -// appealing to the user. -void ChromeFraudulentCertificateReporter::OnResponseStarted( - net::URLRequest* request) { - const net::URLRequestStatus& status(request->status()); - if (!status.is_success()) { - LOG(WARNING) << "Certificate upload failed" - << " status:" << status.status() - << " error:" << status.error(); - } else if (request->GetResponseCode() != 200) { - LOG(WARNING) << "Certificate upload HTTP status: " - << request->GetResponseCode(); - } - RequestComplete(request); -} - -void ChromeFraudulentCertificateReporter::OnReadCompleted( - net::URLRequest* request, int bytes_read) {} - -} // namespace chrome_browser_net - diff --git a/chrome/browser/net/chrome_fraudulent_certificate_reporter.h b/chrome/browser/net/chrome_fraudulent_certificate_reporter.h deleted file mode 100644 index 1a78ec2..0000000 --- a/chrome/browser/net/chrome_fraudulent_certificate_reporter.h +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_NET_CHROME_FRAUDULENT_CERTIFICATE_REPORTER_H_ -#define CHROME_BROWSER_NET_CHROME_FRAUDULENT_CERTIFICATE_REPORTER_H_ -#pragma once - -#include <set> -#include <string> - -#include "net/url_request/fraudulent_certificate_reporter.h" -#include "net/url_request/url_request.h" - -namespace chrome_browser_net { - -// TODO(palmer): Switch to HTTPS when the error handling delegate is more -// sophisticated. Ultimately we plan to attempt the report on many transports. -const char FRAUDULENT_CERTIFICATE_UPLOAD_ENDPOINT[] = - "http://clients3.google.com/log_cert_error"; - -class ChromeFraudulentCertificateReporter - : public net::FraudulentCertificateReporter, - public net::URLRequest::Delegate { - public: - explicit ChromeFraudulentCertificateReporter( - net::URLRequestContext* request_context); - - virtual ~ChromeFraudulentCertificateReporter(); - - // Allows users of this class to override this and set their own URLRequest - // type. Used by SendReport. - virtual net::URLRequest* CreateURLRequest(); - - // net::FraudulentCertificateReporter - virtual void SendReport(const std::string& hostname, - const net::SSLInfo& ssl_info, - bool sni_available) OVERRIDE; - - // net::URLRequest::Delegate - virtual void OnResponseStarted(net::URLRequest* request) OVERRIDE; - virtual void OnReadCompleted(net::URLRequest* request, - int bytes_read) OVERRIDE; - - protected: - net::URLRequestContext* const request_context_; - - private: - // Performs post-report cleanup. - void RequestComplete(net::URLRequest* request); - - const GURL upload_url_; - std::set<net::URLRequest*> inflight_requests_; - - DISALLOW_COPY_AND_ASSIGN(ChromeFraudulentCertificateReporter); -}; - -} // namespace chrome_browser_net - -#endif // CHROME_BROWSER_NET_CHROME_FRAUDULENT_CERTIFICATE_REPORTER_H_ - diff --git a/chrome/browser/net/chrome_fraudulent_certificate_reporter_unittest.cc b/chrome/browser/net/chrome_fraudulent_certificate_reporter_unittest.cc deleted file mode 100644 index 06da291..0000000 --- a/chrome/browser/net/chrome_fraudulent_certificate_reporter_unittest.cc +++ /dev/null @@ -1,201 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/net/chrome_fraudulent_certificate_reporter.h" - -#include <string> - -#include "base/bind.h" -#include "base/file_path.h" -#include "base/memory/scoped_ptr.h" -#include "base/message_loop.h" -#include "base/synchronization/waitable_event.h" -#include "base/threading/thread.h" -#include "chrome/browser/net/chrome_url_request_context.h" -#include "content/browser/browser_thread.h" -#include "net/base/cert_test_util.h" -#include "net/base/ssl_info.h" -#include "net/base/transport_security_state.h" -#include "net/base/x509_certificate.h" -#include "net/url_request/fraudulent_certificate_reporter.h" -#include "net/url_request/url_request.h" -#include "testing/gtest/include/gtest/gtest.h" - -using net::SSLInfo; - -namespace chrome_browser_net { - -// Builds an SSLInfo from an invalid cert chain. In this case, the cert is -// expired; what matters is that the cert would not pass even a normal -// sanity check. We test that we DO NOT send a fraudulent certificate report -// in this case. -static SSLInfo GetBadSSLInfo() { - SSLInfo info; - - info.cert = net::ImportCertFromFile(net::GetTestCertsDirectory(), - "expired_cert.pem"); - info.is_issued_by_known_root = false; - - return info; -} - -// Builds an SSLInfo from a "good" cert chain, as defined by IsGoodSSLInfo, -// but which does not pass DomainState::IsChainOfPublicKeysPermitted. In this -// case, the certificate is for mail.google.com, signed by our Chrome test -// CA. During testing, Chrome believes this CA is part of the root system -// store. But, this CA is not in the pin list; we test that we DO send a -// fraudulent certicate report in this case. -static SSLInfo GetGoodSSLInfo() { - SSLInfo info; - - info.cert = net::ImportCertFromFile(net::GetTestCertsDirectory(), - "test_mail_google_com.pem"); - info.is_issued_by_known_root = true; - - return info; -} - -// Checks that |info| is good as required by the SSL checks performed in -// URLRequestHttpJob::OnStartCompleted, which are enough to trigger pin -// checking but not sufficient to pass -// DomainState::IsChainOfPublicKeysPermitted. -static bool IsGoodSSLInfo(const SSLInfo& info) { - return info.is_valid() && info.is_issued_by_known_root; -} - -class TestReporter : public ChromeFraudulentCertificateReporter { - public: - explicit TestReporter(net::URLRequestContext* request_context) - : ChromeFraudulentCertificateReporter(request_context) {} -}; - -class SendingTestReporter : public TestReporter { - public: - explicit SendingTestReporter(net::URLRequestContext* request_context) - : TestReporter(request_context), passed_(false) {} - - // Passes if invoked with a good SSLInfo and for a hostname that is a Google - // pinned property. - virtual void SendReport(const std::string& hostname, - const SSLInfo& ssl_info, - bool sni_available) OVERRIDE { - EXPECT_TRUE(IsGoodSSLInfo(ssl_info)); - EXPECT_TRUE(net::TransportSecurityState::IsGooglePinnedProperty( - hostname, sni_available)); - passed_ = true; - } - - virtual ~SendingTestReporter() { - // If the object is destroyed without having its SendReport method invoked, - // we failed. - EXPECT_TRUE(passed_); - } - - bool passed_; -}; - -class NotSendingTestReporter : public TestReporter { - public: - explicit NotSendingTestReporter(net::URLRequestContext* request_context) - : TestReporter(request_context) {} - - // Passes if invoked with a bad SSLInfo and for a hostname that is not a - // Google pinned property. - virtual void SendReport(const std::string& hostname, - const SSLInfo& ssl_info, - bool sni_available) OVERRIDE { - EXPECT_FALSE(IsGoodSSLInfo(ssl_info)); - EXPECT_FALSE(net::TransportSecurityState::IsGooglePinnedProperty( - hostname, sni_available)); - } -}; - -// For the first version of the feature, sending reports is "fire and forget". -// Therefore, we test only that the Reporter tried to send a request at all. -// In the future, when we have more sophisticated (i.e., any) error handling -// and re-tries, we will need more sopisticated tests as well. -// -// This class doesn't do anything now, but in near future versions it will. -class MockURLRequest : public net::URLRequest { - public: - MockURLRequest() : net::URLRequest(GURL(""), NULL), passed_(false) { - } - - private: - bool passed_; -}; - -// A ChromeFraudulentCertificateReporter that uses a MockURLRequest, but is -// otherwise normal: reports are constructed and sent in the usual way. -class MockReporter : public ChromeFraudulentCertificateReporter { - public: - explicit MockReporter(net::URLRequestContext* request_context) - : ChromeFraudulentCertificateReporter(request_context) {} - - virtual net::URLRequest* CreateURLRequest() OVERRIDE { - return new MockURLRequest(); - } - - virtual void SendReport( - const std::string& hostname, - const net::SSLInfo& ssl_info, - bool sni_available) { - DCHECK(!hostname.empty()); - DCHECK(ssl_info.is_valid()); - ChromeFraudulentCertificateReporter::SendReport(hostname, ssl_info, sni_available); - } -}; - -static void DoReportIsSent() { - scoped_refptr<ChromeURLRequestContext> context = new ChromeURLRequestContext; - SendingTestReporter reporter(context.get()); - SSLInfo info = GetGoodSSLInfo(); - reporter.SendReport("mail.google.com", info, true); -} - -static void DoReportIsNotSent() { - scoped_refptr<ChromeURLRequestContext> context = new ChromeURLRequestContext; - NotSendingTestReporter reporter(context.get()); - SSLInfo info = GetBadSSLInfo(); - reporter.SendReport("127.0.0.1", info, true); -} - -static void DoMockReportIsSent() { - scoped_refptr<ChromeURLRequestContext> context = new ChromeURLRequestContext; - MockReporter reporter(context.get()); - SSLInfo info = GetGoodSSLInfo(); - reporter.SendReport("mail.google.com", info, true); -} - -TEST(ChromeFraudulentCertificateReporterTest, GoodBadInfo) { - SSLInfo good = GetGoodSSLInfo(); - EXPECT_TRUE(IsGoodSSLInfo(good)); - - SSLInfo bad = GetBadSSLInfo(); - EXPECT_FALSE(IsGoodSSLInfo(bad)); -} - -TEST(ChromeFraudulentCertificateReporterTest, ReportIsSent) { - MessageLoop loop(MessageLoop::TYPE_IO); - BrowserThread io_thread(BrowserThread::IO, &loop); - loop.PostTask(FROM_HERE, base::Bind(&DoReportIsSent)); - loop.RunAllPending(); -} - -TEST(ChromeFraudulentCertificateReporterTest, MockReportIsSent) { - MessageLoop loop(MessageLoop::TYPE_IO); - BrowserThread io_thread(BrowserThread::IO, &loop); - loop.PostTask(FROM_HERE, base::Bind(&DoMockReportIsSent)); - loop.RunAllPending(); -} - -TEST(ChromeFraudulentCertificateReporterTest, ReportIsNotSent) { - MessageLoop loop(MessageLoop::TYPE_IO); - BrowserThread io_thread(BrowserThread::IO, &loop); - loop.PostTask(FROM_HERE, base::Bind(&DoReportIsNotSent)); - loop.RunAllPending(); -} - -} // namespace chrome_browser_net - diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi index d5b190e..8a5f5f4 100644 --- a/chrome/chrome_browser.gypi +++ b/chrome/chrome_browser.gypi @@ -10,7 +10,6 @@ 'dependencies': [ 'app/policy/cloud_policy_codegen.gyp:policy', 'browser/sync/protocol/sync_proto.gyp:sync_proto', - 'cert_logger_proto', 'chrome_extra_resources', 'chrome_resources', 'chrome_strings', @@ -1553,8 +1552,6 @@ 'browser/net/chrome_dns_cert_provenance_checker.h', 'browser/net/chrome_dns_cert_provenance_checker_factory.cc', 'browser/net/chrome_dns_cert_provenance_checker_factory.h', - 'browser/net/chrome_fraudulent_certificate_reporter.cc', - 'browser/net/chrome_fraudulent_certificate_reporter.h', 'browser/net/chrome_net_log.cc', 'browser/net/chrome_net_log.h', 'browser/net/chrome_network_delegate.cc', @@ -5124,18 +5121,6 @@ ], }, { - # Protobuf compiler / generator for the fraudulent certificate reporting - # protocol buffer. - 'target_name': 'cert_logger_proto', - 'type': 'static_library', - 'sources': [ 'browser/net/cert_logger.proto', ], - 'variables': { - 'proto_in_dir': 'browser/net', - 'proto_out_dir': 'chrome/browser/net', - }, - 'includes': [ '../build/protoc.gypi', ], - }, - { # Protobuf compiler / generate rule for feedback 'target_name': 'userfeedback_proto', 'type': 'static_library', diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi index f85fdb5..6b6f6f7 100644 --- a/chrome/chrome_tests.gypi +++ b/chrome/chrome_tests.gypi @@ -1374,7 +1374,6 @@ 'browser/metrics/thread_watcher_unittest.cc', 'browser/mock_keychain_mac.cc', 'browser/mock_keychain_mac.h', - 'browser/net/chrome_fraudulent_certificate_reporter_unittest.cc', 'browser/net/chrome_net_log_unittest.cc', 'browser/net/connection_tester_unittest.cc', 'browser/net/gaia/gaia_oauth_fetcher_unittest.cc', |