chrome_dns_cert_provenance_checker.cc revision 21d179b334e59e9a3bfcaed4c4430bef1bc5759d
1// Copyright (c) 2010 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_dns_cert_provenance_checker.h"
6
7#include "base/scoped_ptr.h"
8#include "base/stl_util-inl.h"
9#include "chrome/browser/net/chrome_url_request_context.h"
10#include "net/url_request/url_request.h"
11
12namespace {
13
14class ChromeDnsCertProvenanceChecker :
15    public net::DnsCertProvenanceChecker,
16    public net::DnsCertProvenanceChecker::Delegate {
17 public:
18  ChromeDnsCertProvenanceChecker(
19      net::DnsRRResolver* dnsrr_resolver,
20      ChromeURLRequestContext* url_req_context)
21      : dnsrr_resolver_(dnsrr_resolver),
22        url_req_context_(url_req_context),
23        upload_url_("http://chromecertcheck.appspot.com/upload"),
24        delegate_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
25  }
26
27  ~ChromeDnsCertProvenanceChecker() {
28    DCHECK(inflight_requests_.empty());
29  }
30
31  // DnsCertProvenanceChecker interface
32  virtual void DoAsyncVerification(
33      const std::string& hostname,
34      const std::vector<base::StringPiece>& der_certs) {
35    net::DnsCertProvenanceChecker::DoAsyncLookup(hostname, der_certs,
36                                                 dnsrr_resolver_, this);
37  }
38
39  virtual void Shutdown() {
40    STLDeleteContainerPointers(inflight_requests_.begin(),
41                               inflight_requests_.end());
42    inflight_requests_.clear();
43  }
44
45  // DnsCertProvenanceChecker::Delegate interface
46  virtual void OnDnsCertLookupFailed(
47      const std::string& hostname,
48      const std::vector<std::string>& der_certs) {
49    const std::string report = BuildEncryptedReport(hostname, der_certs);
50
51    net::URLRequest* url_request(new net::URLRequest(upload_url_, &delegate_));
52    url_request->set_context(url_req_context_);
53    url_request->set_method("POST");
54    url_request->AppendBytesToUpload(report.data(), report.size());
55    net::HttpRequestHeaders headers;
56    headers.SetHeader(net::HttpRequestHeaders::kContentType,
57                      "x-application/chrome-cert-provenance-report");
58    url_request->SetExtraRequestHeaders(headers);
59    inflight_requests_.insert(url_request);
60    url_request->Start();
61  }
62
63 private:
64  void RequestComplete(net::URLRequest* request) {
65    std::set<net::URLRequest*>::iterator i = inflight_requests_.find(request);
66    DCHECK(i != inflight_requests_.end());
67    delete *i;
68    inflight_requests_.erase(i);
69  }
70
71  // URLRequestDelegate is the delegate for the upload. Since this is a
72  // fire-and-forget operation, we don't care if there are any errors in the
73  // upload.
74  class URLRequestDelegate : public net::URLRequest::Delegate {
75   public:
76    explicit URLRequestDelegate(ChromeDnsCertProvenanceChecker* checker)
77        : checker_(checker) {
78    }
79
80    // Delegate implementation
81    void OnResponseStarted(net::URLRequest* request) {
82      const URLRequestStatus& status(request->status());
83      if (!status.is_success()) {
84        LOG(WARNING) << "Certificate upload failed"
85                     << " status:" << status.status()
86                     << " os_error:" << status.os_error();
87      } else if (request->GetResponseCode() != 200) {
88        LOG(WARNING) << "Certificate upload HTTP status: "
89                     << request->GetResponseCode();
90      }
91      checker_->RequestComplete(request);
92    }
93
94    void OnReadCompleted(net::URLRequest* request, int bytes_read) {
95      NOTREACHED();
96    }
97
98   private:
99    ChromeDnsCertProvenanceChecker* const checker_;
100  };
101
102  net::DnsRRResolver* const dnsrr_resolver_;
103  ChromeURLRequestContext* const url_req_context_;
104  const GURL upload_url_;
105  URLRequestDelegate delegate_;
106  std::set<net::URLRequest*> inflight_requests_;
107};
108
109}  // namespace
110
111net::DnsCertProvenanceChecker* CreateChromeDnsCertProvenanceChecker(
112    net::DnsRRResolver* dnsrr_resolver,
113    ChromeURLRequestContext* url_req_context) {
114  return new ChromeDnsCertProvenanceChecker(dnsrr_resolver, url_req_context);
115}
116