summaryrefslogtreecommitdiffstats
path: root/net/base/multi_threaded_cert_verifier.h
blob: 10c9421ccc74f24d2e7d14fd559496b987448080 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
// Copyright (c) 2012 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.

#ifndef NET_BASE_MULTI_THREADED_CERT_VERIFIER_H_
#define NET_BASE_MULTI_THREADED_CERT_VERIFIER_H_
#pragma once

#include <map>
#include <string>

#include "base/basictypes.h"
#include "base/gtest_prod_util.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/threading/non_thread_safe.h"
#include "net/base/cert_database.h"
#include "net/base/cert_verifier.h"
#include "net/base/cert_verify_result.h"
#include "net/base/completion_callback.h"
#include "net/base/expiring_cache.h"
#include "net/base/net_export.h"
#include "net/base/x509_cert_types.h"

namespace net {

class CertVerifierJob;
class CertVerifierRequest;
class CertVerifierWorker;
class CertVerifyProc;

// MultiThreadedCertVerifier is a CertVerifier implementation that runs
// synchronous CertVerifier implementations on worker threads.
class NET_EXPORT_PRIVATE MultiThreadedCertVerifier :
    public CertVerifier,
    NON_EXPORTED_BASE(public base::NonThreadSafe),
    public CertDatabase::Observer {
 public:
  MultiThreadedCertVerifier();

  // When the verifier is destroyed, all certificate verifications requests are
  // canceled, and their completion callbacks will not be called.
  virtual ~MultiThreadedCertVerifier();

  // CertVerifier implementation
  virtual int Verify(X509Certificate* cert,
                     const std::string& hostname,
                     int flags,
                     CRLSet* crl_set,
                     CertVerifyResult* verify_result,
                     const CompletionCallback& callback,
                     CertVerifier::RequestHandle* out_req,
                     const BoundNetLog& net_log) OVERRIDE;

  virtual void CancelRequest(CertVerifier::RequestHandle req) OVERRIDE;

 private:
  friend class CertVerifierWorker;  // Calls HandleResult.
  friend class CertVerifierRequest;
  friend class CertVerifierJob;
  friend class MultiThreadedCertVerifierTest;
  FRIEND_TEST_ALL_PREFIXES(MultiThreadedCertVerifierTest, CacheHit);
  FRIEND_TEST_ALL_PREFIXES(MultiThreadedCertVerifierTest, DifferentCACerts);
  FRIEND_TEST_ALL_PREFIXES(MultiThreadedCertVerifierTest, InflightJoin);
  FRIEND_TEST_ALL_PREFIXES(MultiThreadedCertVerifierTest, CancelRequest);
  FRIEND_TEST_ALL_PREFIXES(MultiThreadedCertVerifierTest,
                           RequestParamsComparators);

  // Input parameters of a certificate verification request.
  struct RequestParams {
    RequestParams(const SHA1Fingerprint& cert_fingerprint_arg,
                  const SHA1Fingerprint& ca_fingerprint_arg,
                  const std::string& hostname_arg,
                  int flags_arg)
        : cert_fingerprint(cert_fingerprint_arg),
          ca_fingerprint(ca_fingerprint_arg),
          hostname(hostname_arg),
          flags(flags_arg) {}

    bool operator<(const RequestParams& other) const {
      // |flags| is compared before |cert_fingerprint|, |ca_fingerprint|, and
      // |hostname| under assumption that integer comparisons are faster than
      // memory and string comparisons.
      if (flags != other.flags)
        return flags < other.flags;
      int rv = memcmp(cert_fingerprint.data, other.cert_fingerprint.data,
                      sizeof(cert_fingerprint.data));
      if (rv != 0)
        return rv < 0;
      rv = memcmp(ca_fingerprint.data, other.ca_fingerprint.data,
                  sizeof(ca_fingerprint.data));
      if (rv != 0)
        return rv < 0;
      return hostname < other.hostname;
    }

    SHA1Fingerprint cert_fingerprint;
    SHA1Fingerprint ca_fingerprint;
    std::string hostname;
    int flags;
  };

  // CachedResult contains the result of a certificate verification.
  struct CachedResult {
    CachedResult();
    ~CachedResult();

    int error;  // The return value of CertVerifier::Verify.
    CertVerifyResult result;  // The output of CertVerifier::Verify.
  };

  void HandleResult(X509Certificate* cert,
                    const std::string& hostname,
                    int flags,
                    int error,
                    const CertVerifyResult& verify_result);

  // CertDatabase::Observer methods:
  virtual void OnCertTrustChanged(const X509Certificate* cert) OVERRIDE;

  // For unit testing.
  void ClearCache() { cache_.Clear(); }
  size_t GetCacheSize() const { return cache_.size(); }
  uint64 cache_hits() const { return cache_hits_; }
  uint64 requests() const { return requests_; }
  uint64 inflight_joins() const { return inflight_joins_; }
  void SetCertVerifyProc(CertVerifyProc* verify_proc);

  // cache_ maps from a request to a cached result.
  typedef ExpiringCache<RequestParams, CachedResult> CertVerifierCache;
  CertVerifierCache cache_;

  // inflight_ maps from a request to an active verification which is taking
  // place.
  std::map<RequestParams, CertVerifierJob*> inflight_;

  uint64 requests_;
  uint64 cache_hits_;
  uint64 inflight_joins_;

  scoped_refptr<CertVerifyProc> verify_proc_;

  DISALLOW_COPY_AND_ASSIGN(MultiThreadedCertVerifier);
};

}  // namespace net

#endif  // NET_BASE_MULTI_THREADED_CERT_VERIFIER_H_