summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoragl@chromium.org <agl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-11-24 17:20:49 +0000
committeragl@chromium.org <agl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-11-24 17:20:49 +0000
commit361fe8abbf9d24b4f7d6dfe011034205b8a57c01 (patch)
treea820073fa20ebb5a9d8288e1444e27c9d4c39553
parent97b37f0dfa7883a1457534d9c2e3702361bad3ce (diff)
downloadchromium_src-361fe8abbf9d24b4f7d6dfe011034205b8a57c01.zip
chromium_src-361fe8abbf9d24b4f7d6dfe011034205b8a57c01.tar.gz
chromium_src-361fe8abbf9d24b4f7d6dfe011034205b8a57c01.tar.bz2
net: Implement DNS certificate provenance check uploads.
BUG=none TEST=none http://codereview.chromium.org/4830001 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@67275 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/io_thread.cc5
-rw-r--r--chrome/browser/net/chrome_dns_cert_provenance_checker.cc73
-rw-r--r--net/socket/dns_cert_provenance_checker.cc44
-rw-r--r--net/socket/dns_cert_provenance_checker.h2
-rw-r--r--net/url_request/url_request.h6
5 files changed, 123 insertions, 7 deletions
diff --git a/chrome/browser/io_thread.cc b/chrome/browser/io_thread.cc
index a623019..1067bf8 100644
--- a/chrome/browser/io_thread.cc
+++ b/chrome/browser/io_thread.cc
@@ -380,6 +380,11 @@ void IOThread::CleanUp() {
url_request_context_getters.begin();
it != url_request_context_getters.end(); ++it) {
ChromeURLRequestContextGetter* getter = *it;
+ // Stop all pending certificate provenance check uploads
+ net::DnsCertProvenanceChecker* checker =
+ getter->GetURLRequestContext()->dns_cert_checker();
+ if (checker)
+ checker->Shutdown();
getter->ReleaseURLRequestContext();
}
diff --git a/chrome/browser/net/chrome_dns_cert_provenance_checker.cc b/chrome/browser/net/chrome_dns_cert_provenance_checker.cc
index 2f6ebc5..e9bcf2f 100644
--- a/chrome/browser/net/chrome_dns_cert_provenance_checker.cc
+++ b/chrome/browser/net/chrome_dns_cert_provenance_checker.cc
@@ -4,6 +4,11 @@
#include "chrome/browser/net/chrome_dns_cert_provenance_checker.h"
+#include "base/scoped_ptr.h"
+#include "base/stl_util-inl.h"
+#include "chrome/browser/net/chrome_url_request_context.h"
+#include "net/url_request/url_request.h"
+
namespace {
class ChromeDnsCertProvenanceChecker :
@@ -14,7 +19,13 @@ class ChromeDnsCertProvenanceChecker :
net::DnsRRResolver* dnsrr_resolver,
ChromeURLRequestContext* url_req_context)
: dnsrr_resolver_(dnsrr_resolver),
- url_req_context_(url_req_context) {
+ url_req_context_(url_req_context),
+ upload_url_("http://chromecertcheck.appspot.com/upload"),
+ delegate_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
+ }
+
+ ~ChromeDnsCertProvenanceChecker() {
+ DCHECK(inflight_requests_.empty());
}
// DnsCertProvenanceChecker interface
@@ -25,16 +36,74 @@ class ChromeDnsCertProvenanceChecker :
dnsrr_resolver_, this);
}
+ virtual void Shutdown() {
+ STLDeleteContainerPointers(inflight_requests_.begin(),
+ inflight_requests_.end());
+ inflight_requests_.clear();
+ }
+
// DnsCertProvenanceChecker::Delegate interface
virtual void OnDnsCertLookupFailed(
const std::string& hostname,
const std::vector<std::string>& der_certs) {
- // Currently unimplemented.
+ const std::string report = BuildEncryptedReport(hostname, der_certs);
+
+ URLRequest* url_request(new URLRequest(upload_url_, &delegate_));
+ url_request->set_context(url_req_context_);
+ url_request->set_method("POST");
+ url_request->AppendBytesToUpload(report.data(), report.size());
+ net::HttpRequestHeaders headers;
+ headers.SetHeader(net::HttpRequestHeaders::kContentType,
+ "x-application/chrome-cert-provenance-report");
+ url_request->SetExtraRequestHeaders(headers);
+ inflight_requests_.insert(url_request);
+ url_request->Start();
}
private:
+ void RequestComplete(URLRequest* request) {
+ std::set<URLRequest*>::iterator i = inflight_requests_.find(request);
+ DCHECK(i != inflight_requests_.end());
+ delete *i;
+ inflight_requests_.erase(i);
+ }
+
+ // URLRequestDelegate is the delegate for the upload. Since this is a
+ // fire-and-forget operation, we don't care if there are any errors in the
+ // upload.
+ class URLRequestDelegate : public URLRequest::Delegate {
+ public:
+ explicit URLRequestDelegate(ChromeDnsCertProvenanceChecker* checker)
+ : checker_(checker) {
+ }
+
+ // Delegate implementation
+ void OnResponseStarted(URLRequest* request) {
+ const URLRequestStatus& status(request->status());
+ if (!status.is_success()) {
+ LOG(WARNING) << "Certificate upload failed"
+ << " status:" << status.status()
+ << " os_error:" << status.os_error();
+ } else if (request->GetResponseCode() != 200) {
+ LOG(WARNING) << "Certificate upload HTTP status: "
+ << request->GetResponseCode();
+ }
+ checker_->RequestComplete(request);
+ }
+
+ void OnReadCompleted(URLRequest* request, int bytes_read) {
+ NOTREACHED();
+ }
+
+ private:
+ ChromeDnsCertProvenanceChecker* const checker_;
+ };
+
net::DnsRRResolver* const dnsrr_resolver_;
ChromeURLRequestContext* const url_req_context_;
+ const GURL upload_url_;
+ URLRequestDelegate delegate_;
+ std::set<URLRequest*> inflight_requests_;
};
} // namespace
diff --git a/net/socket/dns_cert_provenance_checker.cc b/net/socket/dns_cert_provenance_checker.cc
index 97265f1..27c4982 100644
--- a/net/socket/dns_cert_provenance_checker.cc
+++ b/net/socket/dns_cert_provenance_checker.cc
@@ -13,6 +13,7 @@
#include <pk11pub.h>
#include <sechash.h>
+#include <set>
#include <string>
#include "base/basictypes.h"
@@ -21,6 +22,7 @@
#include "base/non_thread_safe.h"
#include "base/pickle.h"
#include "base/scoped_ptr.h"
+#include "base/singleton.h"
#include "net/base/completion_callback.h"
#include "net/base/dns_util.h"
#include "net/base/dnsrr_resolver.h"
@@ -43,6 +45,40 @@ const uint8 kServerPublicKey[] = {
0x6c, 0x2e, 0xfb, 0x32, 0x42, 0x27, 0xe4, 0x23, 0xea, 0xcd, 0x81, 0x62, 0xc1,
};
+const unsigned kMaxUploadsPerSession = 10;
+
+// DnsCertLimits is a singleton class which keeps track of which hosts we have
+// uploaded reports for in this session. Since some users will be behind MITM
+// proxies, they would otherwise upload for every host and we don't wish to
+// spam the upload server.
+class DnsCertLimits {
+ public:
+ DnsCertLimits() { }
+
+ // HaveReachedMaxUploads returns true iff we have uploaded the maximum number
+ // of DNS certificate reports for this session.
+ bool HaveReachedMaxUploads() {
+ return uploaded_hostnames_.size() >= kMaxUploadsPerSession;
+ }
+
+ // HaveReachedMaxUploads returns true iff we have already uploaded a report
+ // about the given hostname in this session.
+ bool HaveUploadedForHostname(const std::string& hostname) {
+ return uploaded_hostnames_.count(hostname) > 0;
+ }
+
+ void DidUpload(const std::string& hostname) {
+ uploaded_hostnames_.insert(hostname);
+ }
+
+ private:
+ friend struct DefaultSingletonTraits<DnsCertLimits>;
+
+ std::set<std::string> uploaded_hostnames_;
+
+ DISALLOW_COPY_AND_ASSIGN(DnsCertLimits);
+};
+
// DnsCertProvenanceCheck performs the DNS lookup of the certificate. This
// class is self-deleting.
class DnsCertProvenanceCheck : public NonThreadSafe {
@@ -69,6 +105,12 @@ class DnsCertProvenanceCheck : public NonThreadSafe {
if (der_certs_.empty())
return;
+ DnsCertLimits* const limits = Singleton<DnsCertLimits>::get();
+ if (limits->HaveReachedMaxUploads() ||
+ limits->HaveUploadedForHostname(hostname_)) {
+ return;
+ }
+
uint8 fingerprint[SHA1_LENGTH];
SECStatus rv = HASH_HashBuf(
HASH_AlgSHA1, fingerprint, (uint8*) der_certs_[0].data(),
@@ -104,6 +146,7 @@ class DnsCertProvenanceCheck : public NonThreadSafe {
LOG(ERROR) << "FAILED"
<< " hostname:" << hostname_
<< " domain:" << domain_;
+ Singleton<DnsCertLimits>::get()->DidUpload(hostname_);
delegate_->OnDnsCertLookupFailed(hostname_, der_certs_);
} else if (status == OK) {
LOG(ERROR) << "GOOD"
@@ -116,7 +159,6 @@ class DnsCertProvenanceCheck : public NonThreadSafe {
delete this;
}
-
const std::string hostname_;
std::string domain_;
DnsRRResolver* dnsrr_resolver_;
diff --git a/net/socket/dns_cert_provenance_checker.h b/net/socket/dns_cert_provenance_checker.h
index 8fef60f..810e272 100644
--- a/net/socket/dns_cert_provenance_checker.h
+++ b/net/socket/dns_cert_provenance_checker.h
@@ -27,6 +27,8 @@ class DnsCertProvenanceChecker {
const std::vector<std::string>& der_certs) = 0;
};
+ virtual void Shutdown() = 0;
+
virtual ~DnsCertProvenanceChecker();
// DoAsyncVerification starts an asynchronous check for the given certificate
diff --git a/net/url_request/url_request.h b/net/url_request/url_request.h
index 01f5984..66c0aa9 100644
--- a/net/url_request/url_request.h
+++ b/net/url_request/url_request.h
@@ -302,7 +302,7 @@ class URLRequest : public NonThreadSafe {
// expected modification time is provided (non-zero), it will be used to
// check if the underlying file has been changed or not. The granularity of
// the time comparison is 1 second since time_t precision is used in WebKit.
- void AppendBytesToUpload(const char* bytes, int bytes_len);
+ void AppendBytesToUpload(const char* bytes, int bytes_len); // takes a copy
void AppendFileRangeToUpload(const FilePath& file_path,
uint64 offset, uint64 length,
const base::Time& expected_modification_time);
@@ -431,9 +431,7 @@ class URLRequest : public NonThreadSafe {
// and the response has not yet been called).
bool is_pending() const { return is_pending_; }
- // Returns the error status of the request. This value is 0 if there is no
- // error. Otherwise, it is a value defined by the operating system (e.g., an
- // error code returned by GetLastError() on windows).
+ // Returns the error status of the request.
const URLRequestStatus& status() const { return status_; }
// This method is called to start the request. The delegate will receive