// Copyright (c) 2011 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "chrome/browser/net/chrome_dns_cert_provenance_checker.h" #include "base/memory/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 : public net::DnsCertProvenanceChecker, public net::DnsCertProvenanceChecker::Delegate { public: ChromeDnsCertProvenanceChecker( net::DnsRRResolver* dnsrr_resolver, ChromeURLRequestContext* url_req_context) : dnsrr_resolver_(dnsrr_resolver), 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 virtual void DoAsyncVerification( const std::string& hostname, const std::vector<base::StringPiece>& der_certs) { net::DnsCertProvenanceChecker::DoAsyncLookup(hostname, der_certs, 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) { const std::string report = BuildEncryptedReport(hostname, der_certs); net::URLRequest* url_request(new net::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(net::URLRequest* request) { std::set<net::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 net::URLRequest::Delegate { public: explicit URLRequestDelegate(ChromeDnsCertProvenanceChecker* checker) : checker_(checker) { } // Delegate implementation void OnResponseStarted(net::URLRequest* request) { const net::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(net::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<net::URLRequest*> inflight_requests_; }; } // namespace net::DnsCertProvenanceChecker* CreateChromeDnsCertProvenanceChecker( net::DnsRRResolver* dnsrr_resolver, ChromeURLRequestContext* url_req_context) { return new ChromeDnsCertProvenanceChecker(dnsrr_resolver, url_req_context); }