1c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved.
2c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// found in the LICENSE file.
4c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/chromeos/policy/policy_cert_verifier.h"
6c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
7c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/logging.h"
8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/browser_process.h"
9c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "content/public/browser/browser_thread.h"
10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/base/net_errors.h"
11c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/cert/cert_verify_proc.h"
12c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/cert/multi_threaded_cert_verifier.h"
13c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
14c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace policy {
15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace {
17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
18424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)void MaybeSignalAnchorUse(int error,
19424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                          const base::Closure& anchor_used_callback,
20424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                          const net::CertVerifyResult& verify_result) {
21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
22424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (error != net::OK || !verify_result.is_issued_by_additional_trust_anchor ||
23424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      anchor_used_callback.is_null()) {
24424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return;
25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
26424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  anchor_used_callback.Run();
27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
29424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)void CompleteAndSignalAnchorUse(
30424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const base::Closure& anchor_used_callback,
31424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const net::CompletionCallback& completion_callback,
32424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const net::CertVerifyResult* verify_result,
33424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    int error) {
34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
35424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  MaybeSignalAnchorUse(error, anchor_used_callback, *verify_result);
36424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (!completion_callback.is_null())
37424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    completion_callback.Run(error);
38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}  // namespace
41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)PolicyCertVerifier::PolicyCertVerifier(
43424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const base::Closure& anchor_used_callback)
44424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    : anchor_used_callback_(anchor_used_callback) {
45424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
46424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
47424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
48424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)PolicyCertVerifier::~PolicyCertVerifier() {
49424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
50424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
51424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void PolicyCertVerifier::InitializeOnIOThread(
535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const scoped_refptr<net::CertVerifyProc>& verify_proc) {
54c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
55c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!verify_proc->SupportsAdditionalTrustAnchors()) {
56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    LOG(WARNING)
57f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        << "Additional trust anchors not supported on the current platform!";
58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
59c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  net::MultiThreadedCertVerifier* verifier =
601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      new net::MultiThreadedCertVerifier(verify_proc.get());
61424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  verifier->SetCertTrustAnchorProvider(this);
62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  delegate_.reset(verifier);
63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
64c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
65424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)void PolicyCertVerifier::SetTrustAnchors(
66424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const net::CertificateList& trust_anchors) {
67c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
68424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  trust_anchors_ = trust_anchors;
69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
71424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)int PolicyCertVerifier::Verify(
72424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    net::X509Certificate* cert,
73424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const std::string& hostname,
74424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    int flags,
75424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    net::CRLSet* crl_set,
76424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    net::CertVerifyResult* verify_result,
77424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const net::CompletionCallback& completion_callback,
78424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    RequestHandle* out_req,
79424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const net::BoundNetLog& net_log) {
80c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
81424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  DCHECK(delegate_);
82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  net::CompletionCallback wrapped_callback =
83424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      base::Bind(&CompleteAndSignalAnchorUse,
84424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                 anchor_used_callback_,
85424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                 completion_callback,
86424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                 verify_result);
87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int error = delegate_->Verify(cert, hostname, flags, crl_set, verify_result,
88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                wrapped_callback, out_req, net_log);
89424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  MaybeSignalAnchorUse(error, anchor_used_callback_, *verify_result);
90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return error;
91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void PolicyCertVerifier::CancelRequest(RequestHandle req) {
94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  delegate_->CancelRequest(req);
96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
98424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)const net::CertificateList& PolicyCertVerifier::GetAdditionalTrustAnchors() {
99424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
100424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  return trust_anchors_;
101424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
102424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}  // namespace policy
104