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 |