summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorwtc@google.com <wtc@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2008-12-19 00:17:48 +0000
committerwtc@google.com <wtc@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2008-12-19 00:17:48 +0000
commit5b62083c99317965244123c031c707d53f0a03f1 (patch)
tree80d8d2b4811aeb65736101fdc88cfdc4a2c28ff3 /net
parent349f6911964be4226312f970d038bdfc3339face (diff)
downloadchromium_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.cc140
-rw-r--r--net/base/cert_verifier.h65
-rw-r--r--net/base/host_resolver.cc6
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_;