diff options
author | wtc@google.com <wtc@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-12-19 00:17:48 +0000 |
---|---|---|
committer | wtc@google.com <wtc@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-12-19 00:17:48 +0000 |
commit | 5b62083c99317965244123c031c707d53f0a03f1 (patch) | |
tree | 80d8d2b4811aeb65736101fdc88cfdc4a2c28ff3 /net | |
parent | 349f6911964be4226312f970d038bdfc3339face (diff) | |
download | chromium_src-5b62083c99317965244123c031c707d53f0a03f1.zip chromium_src-5b62083c99317965244123c031c707d53f0a03f1.tar.gz chromium_src-5b62083c99317965244123c031c707d53f0a03f1.tar.bz2 |
Add the CertVerifier class. It is based on the
HostResolver class. It's not being compiled yet.
R=eroman
BUG=3592
Review URL: http://codereview.chromium.org/14868
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@7280 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net')
-rw-r--r-- | net/base/cert_verifier.cc | 140 | ||||
-rw-r--r-- | net/base/cert_verifier.h | 65 | ||||
-rw-r--r-- | net/base/host_resolver.cc | 6 |
3 files changed, 208 insertions, 3 deletions
diff --git a/net/base/cert_verifier.cc b/net/base/cert_verifier.cc new file mode 100644 index 0000000..8163690 --- /dev/null +++ b/net/base/cert_verifier.cc @@ -0,0 +1,140 @@ +// Copyright (c) 2008 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 "net/base/cert_verifier.h" + +#include "base/message_loop.h" +#include "base/worker_pool.h" +#include "net/base/net_errors.h" +#include "net/base/x509_certificate.h" + +namespace net { + +class CertVerifier::Request : + public base::RefCountedThreadSafe<CertVerifier::Request> { + public: + Request(CertVerifier* verifier, + X509Certificate* cert, + const std::string& hostname, + bool rev_checking_enabled, + int* cert_status, + CompletionCallback* callback) + : cert_(cert), + hostname_(hostname), + rev_checking_enabled_(rev_checking_enabled), + verifier_(verifier), + cert_status_(cert_status), + callback_(callback), + origin_loop_(MessageLoop::current()), + error_(OK), + result_(0) { + } + + ~Request() {} + + void DoVerify() { + // Running on the worker thread + error_ = cert_->Verify(hostname_, rev_checking_enabled_, &result_); + + Task* reply = NewRunnableMethod(this, &Request::DoCallback); + + // The origin loop could go away while we are trying to post to it, so we + // need to call its PostTask method inside a lock. See ~CertVerifier. + { + AutoLock locked(origin_loop_lock_); + if (origin_loop_) { + origin_loop_->PostTask(FROM_HERE, reply); + reply = NULL; + } + } + + // Does nothing if it got posted. + delete reply; + } + + void DoCallback() { + // Running on the origin thread. + DCHECK(error_ || result_); + + // We may have been cancelled! + if (!verifier_) + return; + + *cert_status_ = result_; + + // Drop the verifier's reference to us. Do this before running the + // callback since the callback might result in the verifier being + // destroyed. + verifier_->request_ = NULL; + + callback_->Run(error_); + } + + void Cancel() { + verifier_ = NULL; + + AutoLock locked(origin_loop_lock_); + origin_loop_ = NULL; + } + + private: + // Set on the origin thread, read on the worker thread. + scoped_refptr<X509Certificate> cert_; + std::string hostname_; + bool rev_checking_enabled_; + + // Only used on the origin thread (where Verify was called). + CertVerifier* verifier_; + int* cert_status_; + CompletionCallback* callback_; + + // Used to post ourselves onto the origin thread. + Lock origin_loop_lock_; + MessageLoop* origin_loop_; + + // Assigned on the worker thread, read on the origin thread. + int error_; + int result_; +}; + +//----------------------------------------------------------------------------- + +CertVerifier::CertVerifier() { +} + +CertVerifier::~CertVerifier() { + if (request_) + request_->Cancel(); +} + +int CertVerifier::Verify(X509Certificate* cert, + const std::string& hostname, + bool rev_checking_enabled, + int* cert_status, + CompletionCallback* callback) { + DCHECK(!request_) << "verifier already in use"; + + // Do a synchronous verification. + if (!callback) { + int result; + int rv = cert->Verify(hostname, rev_checking_enabled, &result); + *cert_status = result; + return rv; + } + + request_ = new Request(this, cert, hostname, rev_checking_enabled, + cert_status, callback); + + // Dispatch to worker thread... + if (!WorkerPool::PostTask(FROM_HERE, + NewRunnableMethod(request_.get(), &Request::DoVerify), true)) { + NOTREACHED(); + request_ = NULL; + return ERR_FAILED; + } + + return ERR_IO_PENDING; +} + +} // namespace net diff --git a/net/base/cert_verifier.h b/net/base/cert_verifier.h new file mode 100644 index 0000000..06f7cef --- /dev/null +++ b/net/base/cert_verifier.h @@ -0,0 +1,65 @@ +// Copyright (c) 2008 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_CERT_VERIFIER_H_ +#define NET_BASE_CERT_VERIFIER_H_ + +#include <string> + +#include "base/basictypes.h" +#include "base/ref_counted.h" +#include "net/base/completion_callback.h" + +namespace net { + +class X509Certificate; + +// This class represents the task of verifying a certificate. It can only +// verify a single certificate at a time, so if you need to verify multiple +// certificates at the same time, you will need to allocate a CertVerifier +// object for each certificate. +// +// TODO(wtc): This class is based on HostResolver. We should create a base +// class for the common code between the two classes. +// +class CertVerifier { + public: + CertVerifier(); + + // If a completion callback is pending when the verifier is destroyed, the + // certificate verification is cancelled, and the completion callback will + // not be called. + ~CertVerifier(); + + // Verifies the given certificate against the given hostname. Returns OK if + // successful or an error code upon failure. + // + // The |cert_status| bitmask is always filled out regardless of the return + // value. If the certificate has multiple errors, the corresponding status + // flags are set in |cert_status|, and the error code for the most serious + // error is returned. + // + // If |rev_checking_enabled| is true, certificate revocation checking is + // performed. + // + // When callback is null, the operation completes synchronously. + // + // When callback is non-null, ERR_IO_PENDING is returned if the operation + // could not be completed synchronously, in which case the result code will + // be passed to the callback when available. + // + int Verify(X509Certificate* cert, const std::string& hostname, + bool rev_checking_enabled, int* cert_status, + CompletionCallback* callback); + + private: + class Request; + friend class Request; + scoped_refptr<Request> request_; + DISALLOW_COPY_AND_ASSIGN(CertVerifier); +}; + +} // namespace net + +#endif // NET_BASE_CERT_VERIFIER_H_ diff --git a/net/base/host_resolver.cc b/net/base/host_resolver.cc index f575fc7..bf5d3c2 100644 --- a/net/base/host_resolver.cc +++ b/net/base/host_resolver.cc @@ -76,7 +76,7 @@ class HostResolver::Request : error_(OK), results_(NULL) { } - + ~Request() { if (results_) freeaddrinfo(results_); @@ -97,7 +97,7 @@ class HostResolver::Request : reply = NULL; } } - + // Does nothing if it got posted. delete reply; } @@ -129,7 +129,7 @@ class HostResolver::Request : AutoLock locked(origin_loop_lock_); origin_loop_ = NULL; } - + private: // Set on the origin thread, read on the worker thread. std::string host_; |