| OLD | NEW |
| 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2008 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "net/base/host_resolver.h" | 5 #include "net/base/cert_verifier.h" |
| 6 | |
| 7 #if defined(OS_WIN) | |
| 8 #include <ws2tcpip.h> | |
| 9 #include <wspiapi.h> // Needed for Win2k compat. | |
| 10 #elif defined(OS_POSIX) | |
| 11 #include <netdb.h> | |
| 12 #include <sys/socket.h> | |
| 13 #endif | |
| 14 | 6 |
| 15 #include "base/message_loop.h" | 7 #include "base/message_loop.h" |
| 16 #include "base/string_util.h" | |
| 17 #include "base/worker_pool.h" | 8 #include "base/worker_pool.h" |
| 18 #include "net/base/address_list.h" | |
| 19 #include "net/base/net_errors.h" | 9 #include "net/base/net_errors.h" |
| 20 | 10 #include "net/base/x509_certificate.h" |
| 21 #if defined(OS_WIN) | |
| 22 #include "net/base/winsock_init.h" | |
| 23 #endif | |
| 24 | 11 |
| 25 namespace net { | 12 namespace net { |
| 26 | 13 |
| 27 //----------------------------------------------------------------------------- | 14 class CertVerifier::Request : |
| 28 | 15 public base::RefCountedThreadSafe<CertVerifier::Request> { |
| 29 static HostMapper* host_mapper; | |
| 30 | |
| 31 HostMapper* SetHostMapper(HostMapper* value) { | |
| 32 std::swap(host_mapper, value); | |
| 33 return value; | |
| 34 } | |
| 35 | |
| 36 static int HostResolverProc( | |
| 37 const std::string& host, const std::string& port, struct addrinfo** out) { | |
| 38 struct addrinfo hints = {0}; | |
| 39 hints.ai_family = PF_UNSPEC; | |
| 40 hints.ai_flags = AI_ADDRCONFIG; | |
| 41 | |
| 42 // Restrict result set to only this socket type to avoid duplicates. | |
| 43 hints.ai_socktype = SOCK_STREAM; | |
| 44 | |
| 45 int err = getaddrinfo(host.c_str(), port.c_str(), &hints, out); | |
| 46 return err ? ERR_NAME_NOT_RESOLVED : OK; | |
| 47 } | |
| 48 | |
| 49 static int ResolveAddrInfo( | |
| 50 const std::string& host, const std::string& port, struct addrinfo** out) { | |
| 51 int rv; | |
| 52 if (host_mapper) { | |
| 53 rv = HostResolverProc(host_mapper->Map(host), port, out); | |
| 54 } else { | |
| 55 rv = HostResolverProc(host, port, out); | |
| 56 } | |
| 57 return rv; | |
| 58 } | |
| 59 | |
| 60 //----------------------------------------------------------------------------- | |
| 61 | |
| 62 class HostResolver::Request : | |
| 63 public base::RefCountedThreadSafe<HostResolver::Request> { | |
| 64 public: | 16 public: |
| 65 Request(HostResolver* resolver, | 17 Request(CertVerifier* verifier, |
| 66 const std::string& host, | 18 X509Certificate* cert, |
| 67 const std::string& port, | 19 const std::string& hostname, |
| 68 AddressList* addresses, | 20 bool rev_checking_enabled, |
| 21 int* cert_status, |
| 69 CompletionCallback* callback) | 22 CompletionCallback* callback) |
| 70 : host_(host), | 23 : cert_(cert), |
| 71 port_(port), | 24 hostname_(hostname), |
| 72 resolver_(resolver), | 25 rev_checking_enabled_(rev_checking_enabled), |
| 73 addresses_(addresses), | 26 verifier_(verifier), |
| 27 cert_status_(cert_status), |
| 74 callback_(callback), | 28 callback_(callback), |
| 75 origin_loop_(MessageLoop::current()), | 29 origin_loop_(MessageLoop::current()), |
| 76 error_(OK), | 30 error_(OK), |
| 77 results_(NULL) { | 31 result_(0) { |
| 78 } | |
| 79 | |
| 80 ~Request() { | |
| 81 if (results_) | |
| 82 freeaddrinfo(results_); | |
| 83 } | 32 } |
| 84 | 33 |
| 85 void DoLookup() { | 34 ~Request() {} |
| 35 |
| 36 void DoVerify() { |
| 86 // Running on the worker thread | 37 // Running on the worker thread |
| 87 error_ = ResolveAddrInfo(host_, port_, &results_); | 38 error_ = cert_->Verify(hostname_, rev_checking_enabled_, &result_); |
| 88 | 39 |
| 89 Task* reply = NewRunnableMethod(this, &Request::DoCallback); | 40 Task* reply = NewRunnableMethod(this, &Request::DoCallback); |
| 90 | 41 |
| 91 // The origin loop could go away while we are trying to post to it, so we | 42 // The origin loop could go away while we are trying to post to it, so we |
| 92 // need to call its PostTask method inside a lock. See ~HostResolver. | 43 // need to call its PostTask method inside a lock. See ~CertVerifier. |
| 93 { | 44 { |
| 94 AutoLock locked(origin_loop_lock_); | 45 AutoLock locked(origin_loop_lock_); |
| 95 if (origin_loop_) { | 46 if (origin_loop_) { |
| 96 origin_loop_->PostTask(FROM_HERE, reply); | 47 origin_loop_->PostTask(FROM_HERE, reply); |
| 97 reply = NULL; | 48 reply = NULL; |
| 98 } | 49 } |
| 99 } | 50 } |
| 100 | 51 |
| 101 // Does nothing if it got posted. | 52 // Does nothing if it got posted. |
| 102 delete reply; | 53 delete reply; |
| 103 } | 54 } |
| 104 | 55 |
| 105 void DoCallback() { | 56 void DoCallback() { |
| 106 // Running on the origin thread. | 57 // Running on the origin thread. |
| 107 DCHECK(error_ || results_); | 58 DCHECK(error_ || result_); |
| 108 | 59 |
| 109 // We may have been cancelled! | 60 // We may have been cancelled! |
| 110 if (!resolver_) | 61 if (!verifier_) |
| 111 return; | 62 return; |
| 112 | 63 |
| 113 if (!error_) { | 64 *cert_status_ = result_; |
| 114 addresses_->Adopt(results_); | |
| 115 results_ = NULL; | |
| 116 } | |
| 117 | 65 |
| 118 // Drop the resolver's reference to us. Do this before running the | 66 // Drop the verifier's reference to us. Do this before running the |
| 119 // callback since the callback might result in the resolver being | 67 // callback since the callback might result in the verifier being |
| 120 // destroyed. | 68 // destroyed. |
| 121 resolver_->request_ = NULL; | 69 verifier_->request_ = NULL; |
| 122 | 70 |
| 123 callback_->Run(error_); | 71 callback_->Run(error_); |
| 124 } | 72 } |
| 125 | 73 |
| 126 void Cancel() { | 74 void Cancel() { |
| 127 resolver_ = NULL; | 75 verifier_ = NULL; |
| 128 | 76 |
| 129 AutoLock locked(origin_loop_lock_); | 77 AutoLock locked(origin_loop_lock_); |
| 130 origin_loop_ = NULL; | 78 origin_loop_ = NULL; |
| 131 } | 79 } |
| 132 | 80 |
| 133 private: | 81 private: |
| 134 // Set on the origin thread, read on the worker thread. | 82 // Set on the origin thread, read on the worker thread. |
| 135 std::string host_; | 83 scoped_refptr<X509Certificate> cert_; |
| 136 std::string port_; | 84 std::string hostname_; |
| 85 bool rev_checking_enabled_; |
| 137 | 86 |
| 138 // Only used on the origin thread (where Resolve was called). | 87 // Only used on the origin thread (where Verify was called). |
| 139 HostResolver* resolver_; | 88 CertVerifier* verifier_; |
| 140 AddressList* addresses_; | 89 int* cert_status_; |
| 141 CompletionCallback* callback_; | 90 CompletionCallback* callback_; |
| 142 | 91 |
| 143 // Used to post ourselves onto the origin thread. | 92 // Used to post ourselves onto the origin thread. |
| 144 Lock origin_loop_lock_; | 93 Lock origin_loop_lock_; |
| 145 MessageLoop* origin_loop_; | 94 MessageLoop* origin_loop_; |
| 146 | 95 |
| 147 // Assigned on the worker thread, read on the origin thread. | 96 // Assigned on the worker thread, read on the origin thread. |
| 148 int error_; | 97 int error_; |
| 149 struct addrinfo* results_; | 98 int result_; |
| 150 }; | 99 }; |
| 151 | 100 |
| 152 //----------------------------------------------------------------------------- | 101 //----------------------------------------------------------------------------- |
| 153 | 102 |
| 154 HostResolver::HostResolver() { | 103 CertVerifier::CertVerifier() { |
| 155 #if defined(OS_WIN) | |
| 156 EnsureWinsockInit(); | |
| 157 #endif | |
| 158 } | 104 } |
| 159 | 105 |
| 160 HostResolver::~HostResolver() { | 106 CertVerifier::~CertVerifier() { |
| 161 if (request_) | 107 if (request_) |
| 162 request_->Cancel(); | 108 request_->Cancel(); |
| 163 } | 109 } |
| 164 | 110 |
| 165 int HostResolver::Resolve(const std::string& hostname, int port, | 111 int CertVerifier::Verify(X509Certificate* cert, |
| 166 AddressList* addresses, | 112 const std::string& hostname, |
| 167 CompletionCallback* callback) { | 113 bool rev_checking_enabled, |
| 168 DCHECK(!request_) << "resolver already in use"; | 114 int* cert_status, |
| 115 CompletionCallback* callback) { |
| 116 DCHECK(!request_) << "verifier already in use"; |
| 169 | 117 |
| 170 const std::string& port_str = IntToString(port); | 118 // Do a synchronous verification. |
| 171 | |
| 172 // Do a synchronous resolution. | |
| 173 if (!callback) { | 119 if (!callback) { |
| 174 struct addrinfo* results; | 120 int result; |
| 175 int rv = ResolveAddrInfo(hostname, port_str, &results); | 121 int rv = cert->Verify(hostname, rev_checking_enabled, &result); |
| 176 if (rv == OK) | 122 *cert_status = result; |
| 177 addresses->Adopt(results); | |
| 178 return rv; | 123 return rv; |
| 179 } | 124 } |
| 180 | 125 |
| 181 request_ = new Request(this, hostname, port_str, addresses, callback); | 126 request_ = new Request(this, cert, hostname, rev_checking_enabled, |
| 127 cert_status, callback); |
| 182 | 128 |
| 183 // Dispatch to worker thread... | 129 // Dispatch to worker thread... |
| 184 if (!WorkerPool::PostTask(FROM_HERE, | 130 if (!WorkerPool::PostTask(FROM_HERE, |
| 185 NewRunnableMethod(request_.get(), &Request::DoLookup), true)) { | 131 NewRunnableMethod(request_.get(), &Request::DoVerify), true)) { |
| 186 NOTREACHED(); | 132 NOTREACHED(); |
| 187 request_ = NULL; | 133 request_ = NULL; |
| 188 return ERR_FAILED; | 134 return ERR_FAILED; |
| 189 } | 135 } |
| 190 | 136 |
| 191 return ERR_IO_PENDING; | 137 return ERR_IO_PENDING; |
| 192 } | 138 } |
| 193 | 139 |
| 194 } // namespace net | 140 } // namespace net |
| OLD | NEW |