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

Side by Side Diff: chrome/browser/ssl/chrome_expect_ct_reporter.cc

Issue 2957063005: Reland of Update SCT serialization format in Expect-CT reports (Closed)
Patch Set: fix reinterpret_cast Created 3 years, 5 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
« no previous file with comments | « no previous file | chrome/browser/ssl/chrome_expect_ct_reporter_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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"
11 #include "base/feature_list.h" 11 #include "base/feature_list.h"
12 #include "base/json/json_writer.h" 12 #include "base/json/json_writer.h"
13 #include "base/memory/ptr_util.h" 13 #include "base/memory/ptr_util.h"
14 #include "base/metrics/histogram_macros.h" 14 #include "base/metrics/histogram_macros.h"
15 #include "base/metrics/sparse_histogram.h" 15 #include "base/metrics/sparse_histogram.h"
16 #include "base/strings/string_number_conversions.h" 16 #include "base/strings/string_number_conversions.h"
17 #include "base/strings/stringprintf.h" 17 #include "base/strings/stringprintf.h"
18 #include "base/values.h" 18 #include "base/values.h"
19 #include "chrome/common/chrome_features.h" 19 #include "chrome/common/chrome_features.h"
20 #include "net/cert/ct_serialization.h"
20 #include "net/traffic_annotation/network_traffic_annotation.h" 21 #include "net/traffic_annotation/network_traffic_annotation.h"
21 #include "net/url_request/report_sender.h" 22 #include "net/url_request/report_sender.h"
22 23
23 namespace { 24 namespace {
24 25
25 std::string TimeToISO8601(const base::Time& t) { 26 std::string TimeToISO8601(const base::Time& t) {
26 base::Time::Exploded exploded; 27 base::Time::Exploded exploded;
27 t.UTCExplode(&exploded); 28 t.UTCExplode(&exploded);
28 return base::StringPrintf( 29 return base::StringPrintf(
29 "%04d-%02d-%02dT%02d:%02d:%02d.%03dZ", exploded.year, exploded.month, 30 "%04d-%02d-%02dT%02d:%02d:%02d.%03dZ", exploded.year, exploded.month,
(...skipping 14 matching lines...) Expand all
44 45
45 return result; 46 return result;
46 } 47 }
47 48
48 std::string SCTOriginToString( 49 std::string SCTOriginToString(
49 net::ct::SignedCertificateTimestamp::Origin origin) { 50 net::ct::SignedCertificateTimestamp::Origin origin) {
50 switch (origin) { 51 switch (origin) {
51 case net::ct::SignedCertificateTimestamp::SCT_EMBEDDED: 52 case net::ct::SignedCertificateTimestamp::SCT_EMBEDDED:
52 return "embedded"; 53 return "embedded";
53 case net::ct::SignedCertificateTimestamp::SCT_FROM_TLS_EXTENSION: 54 case net::ct::SignedCertificateTimestamp::SCT_FROM_TLS_EXTENSION:
54 return "from-tls-extension"; 55 return "tls-extension";
55 case net::ct::SignedCertificateTimestamp::SCT_FROM_OCSP_RESPONSE: 56 case net::ct::SignedCertificateTimestamp::SCT_FROM_OCSP_RESPONSE:
56 return "from-ocsp-response"; 57 return "ocsp";
57 default: 58 case net::ct::SignedCertificateTimestamp::SCT_ORIGIN_MAX:
58 NOTREACHED(); 59 NOTREACHED();
59 } 60 }
60 return ""; 61 return "";
61 } 62 }
62 63
63 void AddUnknownSCT( 64 void AddSCT(const net::SignedCertificateTimestampAndStatus& sct,
64 const net::SignedCertificateTimestampAndStatus& sct_and_status, 65 base::ListValue* list) {
65 base::ListValue* list) {
66 std::unique_ptr<base::DictionaryValue> list_item(new base::DictionaryValue()); 66 std::unique_ptr<base::DictionaryValue> list_item(new base::DictionaryValue());
67 list_item->SetString("origin", SCTOriginToString(sct_and_status.sct->origin)); 67 // Chrome implements RFC6962, not 6962-bis, so the reports contain v1 SCTs.
68 list_item->SetInteger("version", 1);
69 std::string status;
70 switch (sct.status) {
71 case net::ct::SCT_STATUS_LOG_UNKNOWN:
72 status = "unknown";
73 break;
74 case net::ct::SCT_STATUS_INVALID_SIGNATURE:
75 case net::ct::SCT_STATUS_INVALID_TIMESTAMP:
76 status = "invalid";
77 break;
78 case net::ct::SCT_STATUS_OK:
79 status = "valid";
80 break;
81 case net::ct::SCT_STATUS_NONE:
82 NOTREACHED();
83 }
84 list_item->SetString("status", status);
85 list_item->SetString("source", SCTOriginToString(sct.sct->origin));
86 std::string serialized_sct;
87 net::ct::EncodeSignedCertificateTimestamp(sct.sct, &serialized_sct);
88 std::string encoded_serialized_sct;
89 base::Base64Encode(serialized_sct, &encoded_serialized_sct);
90 list_item->SetString("serialized_sct", encoded_serialized_sct);
68 list->Append(std::move(list_item)); 91 list->Append(std::move(list_item));
69 } 92 }
70 93
71 void AddInvalidSCT(
72 const net::SignedCertificateTimestampAndStatus& sct_and_status,
73 base::ListValue* list) {
74 std::unique_ptr<base::DictionaryValue> list_item(new base::DictionaryValue());
75 list_item->SetString("origin", SCTOriginToString(sct_and_status.sct->origin));
76 std::string log_id;
77 base::Base64Encode(sct_and_status.sct->log_id, &log_id);
78 list_item->SetString("id", log_id);
79 list->Append(std::move(list_item));
80 }
81
82 void AddValidSCT(const net::SignedCertificateTimestampAndStatus& sct_and_status,
83 base::ListValue* list) {
84 std::unique_ptr<base::DictionaryValue> list_item(new base::DictionaryValue());
85 list_item->SetString("origin", SCTOriginToString(sct_and_status.sct->origin));
86
87 // The structure of the SCT object is defined in
88 // http://tools.ietf.org/html/rfc6962#section-4.1.
89 std::unique_ptr<base::DictionaryValue> sct(new base::DictionaryValue());
90 sct->SetInteger("sct_version", sct_and_status.sct->version);
91 std::string log_id;
92 base::Base64Encode(sct_and_status.sct->log_id, &log_id);
93 sct->SetString("id", log_id);
94 base::TimeDelta timestamp =
95 sct_and_status.sct->timestamp - base::Time::UnixEpoch();
96 sct->SetString("timestamp", base::Int64ToString(timestamp.InMilliseconds()));
97 std::string extensions;
98 base::Base64Encode(sct_and_status.sct->extensions, &extensions);
99 sct->SetString("extensions", extensions);
100 std::string signature;
101 base::Base64Encode(sct_and_status.sct->signature.signature_data, &signature);
102 sct->SetString("signature", signature);
103
104 list_item->Set("sct", std::move(sct));
105 list->Append(std::move(list_item));
106 }
107
108 // Records an UMA histogram of the net errors when Expect CT reports 94 // Records an UMA histogram of the net errors when Expect CT reports
109 // fail to send. 95 // fail to send.
110 void RecordUMAOnFailure(const GURL& report_uri, 96 void RecordUMAOnFailure(const GURL& report_uri,
111 int net_error, 97 int net_error,
112 int http_response_code) { 98 int http_response_code) {
113 UMA_HISTOGRAM_SPARSE_SLOWLY("SSL.ExpectCTReportFailure2", -net_error); 99 UMA_HISTOGRAM_SPARSE_SLOWLY("SSL.ExpectCTReportFailure2", -net_error);
114 } 100 }
115 101
116 constexpr net::NetworkTrafficAnnotationTag kTrafficAnnotation = 102 constexpr net::NetworkTrafficAnnotationTag kTrafficAnnotation =
117 net::DefineNetworkTrafficAnnotation("chrome_expect_ct_reporter", R"( 103 net::DefineNetworkTrafficAnnotation("chrome_expect_ct_reporter", R"(
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
154 const net::X509Certificate* validated_certificate_chain, 140 const net::X509Certificate* validated_certificate_chain,
155 const net::X509Certificate* served_certificate_chain, 141 const net::X509Certificate* served_certificate_chain,
156 const net::SignedCertificateTimestampAndStatusList& 142 const net::SignedCertificateTimestampAndStatusList&
157 signed_certificate_timestamps) { 143 signed_certificate_timestamps) {
158 if (report_uri.is_empty()) 144 if (report_uri.is_empty())
159 return; 145 return;
160 146
161 if (!base::FeatureList::IsEnabled(features::kExpectCTReporting)) 147 if (!base::FeatureList::IsEnabled(features::kExpectCTReporting))
162 return; 148 return;
163 149
164 base::DictionaryValue report; 150 base::DictionaryValue outer_report;
165 report.SetString("hostname", host_port_pair.host()); 151 base::DictionaryValue* report = outer_report.SetDictionary(
166 report.SetInteger("port", host_port_pair.port()); 152 "expect-ct-report", base::MakeUnique<base::DictionaryValue>());
167 report.SetString("date-time", TimeToISO8601(base::Time::Now())); 153 report->SetString("hostname", host_port_pair.host());
168 report.SetString("effective-expiration-date", TimeToISO8601(expiration)); 154 report->SetInteger("port", host_port_pair.port());
169 report.Set("served-certificate-chain", 155 report->SetString("date-time", TimeToISO8601(base::Time::Now()));
170 GetPEMEncodedChainAsList(served_certificate_chain)); 156 report->SetString("effective-expiration-date", TimeToISO8601(expiration));
171 report.Set("validated-certificate-chain", 157 report->Set("served-certificate-chain",
172 GetPEMEncodedChainAsList(validated_certificate_chain)); 158 GetPEMEncodedChainAsList(served_certificate_chain));
159 report->Set("validated-certificate-chain",
160 GetPEMEncodedChainAsList(validated_certificate_chain));
173 161
174 std::unique_ptr<base::ListValue> unknown_scts(new base::ListValue()); 162 std::unique_ptr<base::ListValue> scts(new base::ListValue());
175 std::unique_ptr<base::ListValue> invalid_scts(new base::ListValue());
176 std::unique_ptr<base::ListValue> valid_scts(new base::ListValue());
177
178 for (const auto& sct_and_status : signed_certificate_timestamps) { 163 for (const auto& sct_and_status : signed_certificate_timestamps) {
179 switch (sct_and_status.status) { 164 AddSCT(sct_and_status, scts.get());
180 case net::ct::SCT_STATUS_LOG_UNKNOWN:
181 AddUnknownSCT(sct_and_status, unknown_scts.get());
182 break;
183 case net::ct::SCT_STATUS_INVALID_SIGNATURE:
184 case net::ct::SCT_STATUS_INVALID_TIMESTAMP:
185 AddInvalidSCT(sct_and_status, invalid_scts.get());
186 break;
187 case net::ct::SCT_STATUS_OK:
188 AddValidSCT(sct_and_status, valid_scts.get());
189 break;
190 default:
191 NOTREACHED();
192 }
193 } 165 }
194 166 report->Set("scts", std::move(scts));
195 report.Set("unknown-scts", std::move(unknown_scts));
196 report.Set("invalid-scts", std::move(invalid_scts));
197 report.Set("valid-scts", std::move(valid_scts));
198 167
199 std::string serialized_report; 168 std::string serialized_report;
200 if (!base::JSONWriter::Write(report, &serialized_report)) { 169 if (!base::JSONWriter::Write(outer_report, &serialized_report)) {
201 LOG(ERROR) << "Failed to serialize Expect CT report"; 170 LOG(ERROR) << "Failed to serialize Expect CT report";
202 return; 171 return;
203 } 172 }
204 173
205 UMA_HISTOGRAM_BOOLEAN("SSL.ExpectCTReportSendingAttempt", true); 174 UMA_HISTOGRAM_BOOLEAN("SSL.ExpectCTReportSendingAttempt", true);
206 175
207 report_sender_->Send(report_uri, "application/json; charset=utf-8", 176 report_sender_->Send(report_uri, "application/json; charset=utf-8",
208 serialized_report, base::Callback<void()>(), 177 serialized_report, base::Callback<void()>(),
209 base::Bind(RecordUMAOnFailure)); 178 base::Bind(RecordUMAOnFailure));
210 } 179 }
OLDNEW
« no previous file with comments | « no previous file | chrome/browser/ssl/chrome_expect_ct_reporter_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698