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