Home | History | Annotate | Download | only in net
      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_dns_cert_provenance_checker.h"
      6 
      7 #include "base/memory/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 
     12 namespace {
     13 
     14 class 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 net::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 
    111 net::DnsCertProvenanceChecker* CreateChromeDnsCertProvenanceChecker(
    112     net::DnsRRResolver* dnsrr_resolver,
    113     ChromeURLRequestContext* url_req_context) {
    114   return new ChromeDnsCertProvenanceChecker(dnsrr_resolver, url_req_context);
    115 }
    116