Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(3)

Side by Side Diff: chrome/browser/net/chrome_fraudulent_certificate_reporter.cc

Issue 8302019: Recommit fraudulent certificate reporting infrastructure. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 9 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/net/chrome_fraudulent_certificate_reporter.h"
6
7 #include <set>
8
9 #include "base/base64.h"
10 #include "base/logging.h"
11 #include "base/stl_util.h"
12 #include "base/time.h"
13 #include "chrome/browser/net/cert_logger.pb.h"
14 #include "net/base/ssl_info.h"
15 #include "net/base/x509_certificate.h"
16 #include "net/url_request/url_request_context.h"
17
18 namespace chrome_browser_net {
19
20 ChromeFraudulentCertificateReporter::ChromeFraudulentCertificateReporter(
21 net::URLRequestContext* request_context)
22 : request_context_(request_context),
23 upload_url_(FRAUDULENT_CERTIFICATE_UPLOAD_ENDPOINT) {
24 }
25
26 ChromeFraudulentCertificateReporter::~ChromeFraudulentCertificateReporter() {
27 STLDeleteElements(&inflight_requests_);
28 }
29
30 // TODO(palmer): Move this to some globally-visible utility module.
31 static bool DerToPem(const std::string& der_certificate, std::string* output) {
32 std::string b64_encoded;
33 if (!base::Base64Encode(der_certificate, &b64_encoded))
34 return false;
35
36 *output = "-----BEGIN CERTIFICATE-----\r\n";
37
38 size_t size = b64_encoded.size();
39 for (size_t i = 0; i < size; ) {
40 size_t todo = size - i;
41 if (todo > 64)
42 todo = 64;
43 *output += b64_encoded.substr(i, todo);
44 *output += "\r\n";
45 i += todo;
46 }
47
48 *output += "-----END CERTIFICATE-----\r\n";
49 return true;
50 }
51
52 static std::string BuildReport(
53 const std::string& hostname,
54 const net::SSLInfo& ssl_info) {
55 CertLoggerRequest request;
56 base::Time now = base::Time::Now();
57 request.set_time_usec(now.ToInternalValue());
58 request.set_hostname(hostname);
59
60 std::string der_encoded, pem_encoded;
61
62 net::X509Certificate* certificate = ssl_info.cert;
63 if (!certificate->GetDEREncoded(&der_encoded) ||
64 !DerToPem(der_encoded, &pem_encoded)) {
65 LOG(ERROR) << "Could not PEM encode DER certificate";
66 }
67
68 std::string* cert_chain = request.mutable_cert_chain();
69 *cert_chain += pem_encoded;
70
71 const net::X509Certificate::OSCertHandles& intermediates =
72 certificate->GetIntermediateCertificates();
73
74 for (net::X509Certificate::OSCertHandles::const_iterator
75 i = intermediates.begin(); i != intermediates.end(); ++i) {
76 scoped_refptr<net::X509Certificate> cert =
77 net::X509Certificate::CreateFromHandle(*i, intermediates);
78
79 if (!cert->GetDEREncoded(&der_encoded) ||
80 !DerToPem(der_encoded, &pem_encoded)) {
81 LOG(ERROR) << "Could not PEM encode DER certificate";
82 continue;
83 }
84
85 *cert_chain += pem_encoded;
86 }
87
88 std::string out;
89 request.SerializeToString(&out);
90 return out;
91 }
92
93 net::URLRequest* ChromeFraudulentCertificateReporter::CreateURLRequest() {
94 return new net::URLRequest(upload_url_, this);
95 }
96
97 void ChromeFraudulentCertificateReporter::SendReport(
98 const std::string& hostname,
99 const net::SSLInfo& ssl_info,
100 bool sni_available) {
101 // We do silent/automatic reporting ONLY for Google properties. For other
102 // domains (when we start supporting that), we will ask for user permission.
103 if (!net::TransportSecurityState::IsGooglePinnedProperty(hostname,
104 sni_available)) {
105 return;
106 }
107
108 std::string report = BuildReport(hostname, ssl_info);
109
110 net::URLRequest* url_request = CreateURLRequest();
111 url_request->set_context(request_context_);
112 url_request->set_method("POST");
113 url_request->AppendBytesToUpload(report.data(), report.size());
114
115 net::HttpRequestHeaders headers;
116 headers.SetHeader(net::HttpRequestHeaders::kContentType,
117 "x-application/chrome-fraudulent-cert-report");
118 url_request->SetExtraRequestHeaders(headers);
119
120 inflight_requests_.insert(url_request);
121 url_request->Start();
122 }
123
124 void ChromeFraudulentCertificateReporter::RequestComplete(
125 net::URLRequest* request) {
126 std::set<net::URLRequest*>::iterator i = inflight_requests_.find(request);
127 DCHECK(i != inflight_requests_.end());
128 delete *i;
129 inflight_requests_.erase(i);
130 }
131
132 // TODO(palmer): Currently, the upload is fire-and-forget but soon we will
133 // try to recover by retrying, and trying different endpoints, and
134 // appealing to the user.
135 void ChromeFraudulentCertificateReporter::OnResponseStarted(
136 net::URLRequest* request) {
137 const net::URLRequestStatus& status(request->status());
138 if (!status.is_success()) {
139 LOG(WARNING) << "Certificate upload failed"
140 << " status:" << status.status()
141 << " error:" << status.error();
142 } else if (request->GetResponseCode() != 200) {
143 LOG(WARNING) << "Certificate upload HTTP status: "
144 << request->GetResponseCode();
145 }
146 RequestComplete(request);
147 }
148
149 void ChromeFraudulentCertificateReporter::OnReadCompleted(
150 net::URLRequest* request, int bytes_read) {}
151
152 } // namespace chrome_browser_net
153
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698