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#ifndef NET_BASE_CERT_VERIFIER_H_
6#define NET_BASE_CERT_VERIFIER_H_
7#pragma once
8
9#include <map>
10#include <string>
11
12#include "base/basictypes.h"
13#include "base/memory/scoped_ptr.h"
14#include "base/threading/non_thread_safe.h"
15#include "base/time.h"
16#include "net/base/cert_database.h"
17#include "net/base/cert_verify_result.h"
18#include "net/base/completion_callback.h"
19#include "net/base/net_export.h"
20#include "net/base/x509_cert_types.h"
21
22namespace net {
23
24class CertVerifierJob;
25class CertVerifierWorker;
26class X509Certificate;
27
28// CachedCertVerifyResult contains the result of a certificate verification.
29struct CachedCertVerifyResult {
30  CachedCertVerifyResult();
31  ~CachedCertVerifyResult();
32
33  // Returns true if |current_time| is greater than or equal to |expiry|.
34  bool HasExpired(base::Time current_time) const;
35
36  int error;  // The return value of CertVerifier::Verify.
37  CertVerifyResult result;  // The output of CertVerifier::Verify.
38
39  // The time at which the certificate verification result expires.
40  base::Time expiry;
41};
42
43// CertVerifier represents a service for verifying certificates.
44//
45// CertVerifier can handle multiple requests at a time, so when canceling a
46// request the RequestHandle that was returned by Verify() needs to be
47// given.  A simpler alternative for consumers that only have 1 outstanding
48// request at a time is to create a SingleRequestCertVerifier wrapper around
49// CertVerifier (which will automatically cancel the single request when it
50// goes out of scope).
51class NET_EXPORT CertVerifier : public base::NonThreadSafe,
52                     public CertDatabase::Observer {
53 public:
54  // Opaque type used to cancel a request.
55  typedef void* RequestHandle;
56
57  // CertVerifier must not call base::Time::Now() directly.  It must call
58  // time_service_->Now().  This allows unit tests to mock the current time.
59  class TimeService {
60   public:
61    virtual ~TimeService() {}
62
63    virtual base::Time Now() = 0;
64  };
65
66  CertVerifier();
67
68  // Used by unit tests to mock the current time.  Takes ownership of
69  // |time_service|.
70  explicit CertVerifier(TimeService* time_service);
71
72  // When the verifier is destroyed, all certificate verifications requests are
73  // canceled, and their completion callbacks will not be called.
74  ~CertVerifier();
75
76  // Verifies the given certificate against the given hostname.  Returns OK if
77  // successful or an error code upon failure.
78  //
79  // The |*verify_result| structure, including the |verify_result->cert_status|
80  // bitmask, is always filled out regardless of the return value.  If the
81  // certificate has multiple errors, the corresponding status flags are set in
82  // |verify_result->cert_status|, and the error code for the most serious
83  // error is returned.
84  //
85  // |flags| is bitwise OR'd of X509Certificate::VerifyFlags.
86  // If VERIFY_REV_CHECKING_ENABLED is set in |flags|, certificate revocation
87  // checking is performed.
88  //
89  // If VERIFY_EV_CERT is set in |flags| too, EV certificate verification is
90  // performed.  If |flags| is VERIFY_EV_CERT (that is,
91  // VERIFY_REV_CHECKING_ENABLED is not set), EV certificate verification will
92  // not be performed.
93  //
94  // |callback| must not be null.  ERR_IO_PENDING is returned if the operation
95  // could not be completed synchronously, in which case the result code will
96  // be passed to the callback when available.
97  //
98  // If |out_req| is non-NULL, then |*out_req| will be filled with a handle to
99  // the async request. This handle is not valid after the request has
100  // completed.
101  int Verify(X509Certificate* cert,
102             const std::string& hostname,
103             int flags,
104             CertVerifyResult* verify_result,
105             CompletionCallback* callback,
106             RequestHandle* out_req);
107
108  // Cancels the specified request. |req| is the handle returned by Verify().
109  // After a request is canceled, its completion callback will not be called.
110  void CancelRequest(RequestHandle req);
111
112  // Clears the verification result cache.
113  void ClearCache();
114
115  size_t GetCacheSize() const;
116
117  uint64 requests() const { return requests_; }
118  uint64 cache_hits() const { return cache_hits_; }
119  uint64 inflight_joins() const { return inflight_joins_; }
120
121 private:
122  friend class CertVerifierWorker;  // Calls HandleResult.
123
124  // Input parameters of a certificate verification request.
125  struct RequestParams {
126    bool operator==(const RequestParams& other) const {
127      // |flags| is compared before |cert_fingerprint| and |hostname| under
128      // assumption that integer comparisons are faster than memory and string
129      // comparisons.
130      return (flags == other.flags &&
131              memcmp(cert_fingerprint.data, other.cert_fingerprint.data,
132                     sizeof(cert_fingerprint.data)) == 0 &&
133              hostname == other.hostname);
134    }
135
136    bool operator<(const RequestParams& other) const {
137      // |flags| is compared before |cert_fingerprint| and |hostname| under
138      // assumption that integer comparisons are faster than memory and string
139      // comparisons.
140      if (flags != other.flags)
141        return flags < other.flags;
142      int rv = memcmp(cert_fingerprint.data, other.cert_fingerprint.data,
143                      sizeof(cert_fingerprint.data));
144      if (rv != 0)
145        return rv < 0;
146      return hostname < other.hostname;
147    }
148
149    SHA1Fingerprint cert_fingerprint;
150    std::string hostname;
151    int flags;
152  };
153
154  void HandleResult(X509Certificate* cert,
155                    const std::string& hostname,
156                    int flags,
157                    int error,
158                    const CertVerifyResult& verify_result);
159
160  // CertDatabase::Observer methods:
161  virtual void OnCertTrustChanged(const X509Certificate* cert);
162
163  // cache_ maps from a request to a cached result. The cached result may
164  // have expired and the size of |cache_| must be <= kMaxCacheEntries.
165  std::map<RequestParams, CachedCertVerifyResult> cache_;
166
167  // inflight_ maps from a request to an active verification which is taking
168  // place.
169  std::map<RequestParams, CertVerifierJob*> inflight_;
170
171  scoped_ptr<TimeService> time_service_;
172
173  uint64 requests_;
174  uint64 cache_hits_;
175  uint64 inflight_joins_;
176
177  DISALLOW_COPY_AND_ASSIGN(CertVerifier);
178};
179
180// This class represents the task of verifying a certificate.  It wraps
181// CertVerifier to verify only a single certificate at a time and cancels this
182// request when going out of scope.
183class SingleRequestCertVerifier {
184 public:
185  // |cert_verifier| must remain valid for the lifetime of |this|.
186  explicit SingleRequestCertVerifier(CertVerifier* cert_verifier);
187
188  // If a completion callback is pending when the verifier is destroyed, the
189  // certificate verification is canceled, and the completion callback will
190  // not be called.
191  ~SingleRequestCertVerifier();
192
193  // Verifies the given certificate, filling out the |verify_result| object
194  // upon success. See CertVerifier::Verify() for details.
195  int Verify(X509Certificate* cert,
196             const std::string& hostname,
197             int flags,
198             CertVerifyResult* verify_result,
199             CompletionCallback* callback);
200
201 private:
202  // Callback for when the request to |cert_verifier_| completes, so we
203  // dispatch to the user's callback.
204  void OnVerifyCompletion(int result);
205
206  // The actual certificate verifier that will handle the request.
207  CertVerifier* const cert_verifier_;
208
209  // The current request (if any).
210  CertVerifier::RequestHandle cur_request_;
211  CompletionCallback* cur_request_callback_;
212
213  // Completion callback for when request to |cert_verifier_| completes.
214  CompletionCallbackImpl<SingleRequestCertVerifier> callback_;
215
216  DISALLOW_COPY_AND_ASSIGN(SingleRequestCertVerifier);
217};
218
219}  // namespace net
220
221#endif  // NET_BASE_CERT_VERIFIER_H_
222