1// Copyright (c) 2013 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/chromeos/policy/policy_cert_verifier.h"
6
7#include "base/logging.h"
8#include "chrome/browser/browser_process.h"
9#include "content/public/browser/browser_thread.h"
10#include "net/base/net_errors.h"
11#include "net/cert/cert_verify_proc.h"
12#include "net/cert/multi_threaded_cert_verifier.h"
13
14namespace policy {
15
16namespace {
17
18void MaybeSignalAnchorUse(int error,
19                          const base::Closure& anchor_used_callback,
20                          const net::CertVerifyResult& verify_result) {
21  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
22  if (error != net::OK || !verify_result.is_issued_by_additional_trust_anchor ||
23      anchor_used_callback.is_null()) {
24    return;
25  }
26  anchor_used_callback.Run();
27}
28
29void CompleteAndSignalAnchorUse(
30    const base::Closure& anchor_used_callback,
31    const net::CompletionCallback& completion_callback,
32    const net::CertVerifyResult* verify_result,
33    int error) {
34  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
35  MaybeSignalAnchorUse(error, anchor_used_callback, *verify_result);
36  if (!completion_callback.is_null())
37    completion_callback.Run(error);
38}
39
40}  // namespace
41
42PolicyCertVerifier::PolicyCertVerifier(
43    const base::Closure& anchor_used_callback)
44    : anchor_used_callback_(anchor_used_callback) {
45  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
46}
47
48PolicyCertVerifier::~PolicyCertVerifier() {
49  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
50}
51
52void PolicyCertVerifier::InitializeOnIOThread(
53    const scoped_refptr<net::CertVerifyProc>& verify_proc) {
54  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
55  if (!verify_proc->SupportsAdditionalTrustAnchors()) {
56    LOG(WARNING)
57        << "Additional trust anchors not supported on the current platform!";
58  }
59  net::MultiThreadedCertVerifier* verifier =
60      new net::MultiThreadedCertVerifier(verify_proc.get());
61  verifier->SetCertTrustAnchorProvider(this);
62  delegate_.reset(verifier);
63}
64
65void PolicyCertVerifier::SetTrustAnchors(
66    const net::CertificateList& trust_anchors) {
67  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
68  trust_anchors_ = trust_anchors;
69}
70
71int PolicyCertVerifier::Verify(
72    net::X509Certificate* cert,
73    const std::string& hostname,
74    int flags,
75    net::CRLSet* crl_set,
76    net::CertVerifyResult* verify_result,
77    const net::CompletionCallback& completion_callback,
78    RequestHandle* out_req,
79    const net::BoundNetLog& net_log) {
80  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
81  DCHECK(delegate_);
82  net::CompletionCallback wrapped_callback =
83      base::Bind(&CompleteAndSignalAnchorUse,
84                 anchor_used_callback_,
85                 completion_callback,
86                 verify_result);
87  int error = delegate_->Verify(cert, hostname, flags, crl_set, verify_result,
88                                wrapped_callback, out_req, net_log);
89  MaybeSignalAnchorUse(error, anchor_used_callback_, *verify_result);
90  return error;
91}
92
93void PolicyCertVerifier::CancelRequest(RequestHandle req) {
94  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
95  delegate_->CancelRequest(req);
96}
97
98const net::CertificateList& PolicyCertVerifier::GetAdditionalTrustAnchors() {
99  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
100  return trust_anchors_;
101}
102
103}  // namespace policy
104