blob: 9aaca41d0864af671b33bd907dbc58bb6433768a [file] [log] [blame]
[email protected]d518cd92010-09-29 12:27:441// Copyright (c) 2010 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// OpenSSL binding for SSLClientSocket. The class layout and general principle
6// of operation is derived from SSLClientSocketNSS.
7
8#include "net/socket/ssl_client_socket_openssl.h"
9
10#include <openssl/ssl.h>
11#include <openssl/err.h>
12
[email protected]fbef13932010-11-23 12:38:5313#include "base/lock.h"
[email protected]835d7c82010-10-14 04:38:3814#include "base/metrics/histogram.h"
[email protected]313834722010-11-17 09:57:1815#include "base/openssl_util.h"
[email protected]fbef13932010-11-23 12:38:5316#include "base/singleton.h"
[email protected]313834722010-11-17 09:57:1817#include "net/base/cert_verifier.h"
[email protected]d518cd92010-09-29 12:27:4418#include "net/base/net_errors.h"
19#include "net/base/ssl_connection_status_flags.h"
20#include "net/base/ssl_info.h"
[email protected]d518cd92010-09-29 12:27:4421
22namespace net {
23
24namespace {
25
26// Enable this to see logging for state machine state transitions.
27#if 0
[email protected]3b112772010-10-04 10:54:4928#define GotoState(s) do { DVLOG(2) << (void *)this << " " << __FUNCTION__ << \
[email protected]d518cd92010-09-29 12:27:4429 " jump to state " << s; \
30 next_handshake_state_ = s; } while (0)
31#else
32#define GotoState(s) next_handshake_state_ = s
33#endif
34
35const size_t kMaxRecvBufferSize = 4096;
[email protected]fbef13932010-11-23 12:38:5336const int kSessionCacheTimeoutSeconds = 60 * 60;
37const size_t kSessionCacheMaxEntires = 1024;
[email protected]d518cd92010-09-29 12:27:4438
39int MapOpenSSLError(int err) {
40 switch (err) {
41 case SSL_ERROR_WANT_READ:
42 case SSL_ERROR_WANT_WRITE:
43 return ERR_IO_PENDING;
[email protected]170e76c2010-10-04 15:04:2044 case SSL_ERROR_SYSCALL:
[email protected]abc7e06d2010-10-06 15:40:3545 DVLOG(1) << "OpenSSL SYSCALL error, errno " << errno;
[email protected]170e76c2010-10-04 15:04:2046 return ERR_SSL_PROTOCOL_ERROR;
[email protected]d518cd92010-09-29 12:27:4447 default:
48 // TODO(joth): Implement full mapping.
49 LOG(WARNING) << "Unknown OpenSSL error " << err;
[email protected]d518cd92010-09-29 12:27:4450 return ERR_SSL_PROTOCOL_ERROR;
51 }
52}
53
[email protected]313834722010-11-17 09:57:1854// We do certificate verification after handshake, so we disable the default
55// by registering a no-op verify function.
56int NoOpVerifyCallback(X509_STORE_CTX*, void *) {
57 DVLOG(3) << "skipping cert verify";
58 return 1;
59}
60
[email protected]fbef13932010-11-23 12:38:5361// OpenSSL manages a cache of SSL_SESSION, this class provides the application
62// side policy for that cache about session re-use: we retain one session per
63// unique HostPortPair.
64class SSLSessionCache {
65 public:
66 SSLSessionCache() {}
67
68 void OnSessionAdded(const HostPortPair& host_and_port, SSL_SESSION* session) {
69 // Declare the session cleaner-upper before the lock, so any call into
70 // OpenSSL to free the session will happen after the lock is released.
71 base::ScopedOpenSSL<SSL_SESSION, SSL_SESSION_free> session_to_free;
72 AutoLock lock(lock_);
73
74 DCHECK_EQ(0U, session_map_.count(session));
75 std::pair<HostPortMap::iterator, bool> res =
76 host_port_map_.insert(std::make_pair(host_and_port, session));
77 if (!res.second) { // Already exists: replace old entry.
78 session_to_free.reset(res.first->second);
79 session_map_.erase(session_to_free.get());
80 res.first->second = session;
81 }
82 DVLOG(2) << "Adding session " << session << " => "
83 << host_and_port.ToString() << ", new entry = " << res.second;
84 DCHECK(host_port_map_[host_and_port] == session);
85 session_map_[session] = res.first;
86 DCHECK_EQ(host_port_map_.size(), session_map_.size());
87 DCHECK_LE(host_port_map_.size(), kSessionCacheMaxEntires);
[email protected]313834722010-11-17 09:57:1888 }
[email protected]fbef13932010-11-23 12:38:5389
90 void OnSessionRemoved(SSL_SESSION* session) {
91 // Declare the session cleaner-upper before the lock, so any call into
92 // OpenSSL to free the session will happen after the lock is released.
93 base::ScopedOpenSSL<SSL_SESSION, SSL_SESSION_free> session_to_free;
94 AutoLock lock(lock_);
95
96 SessionMap::iterator it = session_map_.find(session);
97 if (it == session_map_.end())
98 return;
99 DVLOG(2) << "Remove session " << session << " => "
100 << it->second->first.ToString();
101 DCHECK(it->second->second == session);
102 host_port_map_.erase(it->second);
103 session_map_.erase(it);
104 session_to_free.reset(session);
105 DCHECK_EQ(host_port_map_.size(), session_map_.size());
[email protected]313834722010-11-17 09:57:18106 }
[email protected]fbef13932010-11-23 12:38:53107
108 // Looks up the host:port in the cache, and if a session is found it is added
109 // to |ssl|, returning true on success.
110 bool SetSSLSession(SSL* ssl, const HostPortPair& host_and_port) {
111 AutoLock lock(lock_);
112 HostPortMap::iterator it = host_port_map_.find(host_and_port);
113 if (it == host_port_map_.end())
114 return false;
115 DVLOG(2) << "Lookup session: " << it->second << " => "
116 << host_and_port.ToString();
117 SSL_SESSION* session = it->second;
118 DCHECK(session);
119 DCHECK(session_map_[session] == it);
120 // Ideally we'd release |lock_| before calling into OpenSSL here, however
121 // that opens a small risk |session| will go out of scope before it is used.
122 // Alternatively we would take a temporary local refcount on |session|,
123 // except OpenSSL does not provide a public API for adding a ref (c.f.
124 // SSL_SESSION_free which decrements the ref).
125 return SSL_set_session(ssl, session) == 1;
126 }
127
128 private:
129 // A pair of maps to allow bi-directional lookups between host:port and an
130 // associated seesion.
131 // TODO(joth): When client certificates are implemented we should key the
132 // cache on the client certificate used in addition to the host-port pair.
133 typedef std::map<HostPortPair, SSL_SESSION*> HostPortMap;
134 typedef std::map<SSL_SESSION*, HostPortMap::iterator> SessionMap;
135 HostPortMap host_port_map_;
136 SessionMap session_map_;
137
138 // Protects access to both the above maps.
139 Lock lock_;
140
141 DISALLOW_COPY_AND_ASSIGN(SSLSessionCache);
[email protected]313834722010-11-17 09:57:18142};
143
[email protected]fbef13932010-11-23 12:38:53144class SSLContext {
145 public:
146 static SSLContext* Get() { return Singleton<SSLContext>::get(); }
147 SSL_CTX* ssl_ctx() { return ssl_ctx_.get(); }
148 SSLSessionCache* session_cache() { return &session_cache_; }
149
150 SSLClientSocketOpenSSL* GetClientSocketFromSSL(SSL* ssl) {
151 DCHECK(ssl);
152 SSLClientSocketOpenSSL* socket = static_cast<SSLClientSocketOpenSSL*>(
153 SSL_get_ex_data(ssl, ssl_socket_data_index_));
154 DCHECK(socket);
155 return socket;
156 }
157
158 bool SetClientSocketForSSL(SSL* ssl, SSLClientSocketOpenSSL* socket) {
159 return SSL_set_ex_data(ssl, ssl_socket_data_index_, socket) != 0;
160 }
161
162 private:
163 friend struct DefaultSingletonTraits<SSLContext>;
164
165 SSLContext() {
166 base::EnsureOpenSSLInit();
167 ssl_socket_data_index_ = SSL_get_ex_new_index(0, 0, 0, 0, 0);
168 DCHECK_NE(ssl_socket_data_index_, -1);
169 ssl_ctx_.reset(SSL_CTX_new(SSLv23_client_method()));
170 SSL_CTX_set_cert_verify_callback(ssl_ctx_.get(), NoOpVerifyCallback, NULL);
171 SSL_CTX_set_session_cache_mode(ssl_ctx_.get(), SSL_SESS_CACHE_CLIENT);
172 SSL_CTX_sess_set_new_cb(ssl_ctx_.get(), NewSessionCallbackStatic);
173 SSL_CTX_sess_set_remove_cb(ssl_ctx_.get(), RemoveSessionCallbackStatic);
174 SSL_CTX_set_timeout(ssl_ctx_.get(), kSessionCacheTimeoutSeconds);
175 SSL_CTX_sess_set_cache_size(ssl_ctx_.get(), kSessionCacheMaxEntires);
176 }
177
178 static int NewSessionCallbackStatic(SSL* ssl, SSL_SESSION* session) {
179 return Get()->NewSessionCallback(ssl, session);
180 }
181
182 int NewSessionCallback(SSL* ssl, SSL_SESSION* session) {
183 SSLClientSocketOpenSSL* socket = GetClientSocketFromSSL(ssl);
184 session_cache_.OnSessionAdded(socket->host_and_port(), session);
185 return 1; // 1 => We took ownership of |session|.
186 }
187
188 static void RemoveSessionCallbackStatic(SSL_CTX* ctx, SSL_SESSION* session) {
189 return Get()->RemoveSessionCallback(ctx, session);
190 }
191
192 void RemoveSessionCallback(SSL_CTX* ctx, SSL_SESSION* session) {
193 DCHECK(ctx == ssl_ctx());
194 session_cache_.OnSessionRemoved(session);
195 }
196
197 // This is the index used with SSL_get_ex_data to retrieve the owner
198 // SSLClientSocketOpenSSL object from an SSL instance.
199 int ssl_socket_data_index_;
200
201 base::ScopedOpenSSL<SSL_CTX, SSL_CTX_free> ssl_ctx_;
202 SSLSessionCache session_cache_;
203};
[email protected]313834722010-11-17 09:57:18204
[email protected]3b112772010-10-04 10:54:49205} // namespace
[email protected]d518cd92010-09-29 12:27:44206
207SSLClientSocketOpenSSL::SSLClientSocketOpenSSL(
208 ClientSocketHandle* transport_socket,
[email protected]055d7f22010-11-15 12:03:12209 const HostPortPair& host_and_port,
[email protected]d518cd92010-09-29 12:27:44210 const SSLConfig& ssl_config)
211 : ALLOW_THIS_IN_INITIALIZER_LIST(buffer_send_callback_(
212 this, &SSLClientSocketOpenSSL::BufferSendComplete)),
213 ALLOW_THIS_IN_INITIALIZER_LIST(buffer_recv_callback_(
214 this, &SSLClientSocketOpenSSL::BufferRecvComplete)),
215 transport_send_busy_(false),
216 transport_recv_busy_(false),
217 user_connect_callback_(NULL),
218 user_read_callback_(NULL),
219 user_write_callback_(NULL),
[email protected]fbef13932010-11-23 12:38:53220 completed_handshake_(false),
[email protected]d518cd92010-09-29 12:27:44221 client_auth_cert_needed_(false),
[email protected]170e76c2010-10-04 15:04:20222 ALLOW_THIS_IN_INITIALIZER_LIST(handshake_io_callback_(
223 this, &SSLClientSocketOpenSSL::OnHandshakeIOComplete)),
[email protected]d518cd92010-09-29 12:27:44224 ssl_(NULL),
225 transport_bio_(NULL),
226 transport_(transport_socket),
[email protected]055d7f22010-11-15 12:03:12227 host_and_port_(host_and_port),
[email protected]d518cd92010-09-29 12:27:44228 ssl_config_(ssl_config),
[email protected]fbef13932010-11-23 12:38:53229 trying_cached_session_(false),
[email protected]d518cd92010-09-29 12:27:44230 net_log_(transport_socket->socket()->NetLog()) {
231}
232
233SSLClientSocketOpenSSL::~SSLClientSocketOpenSSL() {
234 Disconnect();
235}
236
[email protected]d518cd92010-09-29 12:27:44237bool SSLClientSocketOpenSSL::Init() {
[email protected]9e733f32010-10-04 18:19:08238 DCHECK(!ssl_);
239 DCHECK(!transport_bio_);
240
[email protected]fbef13932010-11-23 12:38:53241 SSLContext* context = SSLContext::Get();
242 base::OpenSSLErrStackTracer err_tracer(FROM_HERE);
[email protected]d518cd92010-09-29 12:27:44243
[email protected]fbef13932010-11-23 12:38:53244 ssl_ = SSL_new(context->ssl_ctx());
245 if (!ssl_ || !context->SetClientSocketForSSL(ssl_, this))
[email protected]d518cd92010-09-29 12:27:44246 return false;
[email protected]fbef13932010-11-23 12:38:53247
248 if (!SSL_set_tlsext_host_name(ssl_, host_and_port_.host().c_str()))
249 return false;
250
251 trying_cached_session_ =
252 context->session_cache()->SetSSLSession(ssl_, host_and_port_);
[email protected]d518cd92010-09-29 12:27:44253
254 BIO* ssl_bio = NULL;
[email protected]fbef13932010-11-23 12:38:53255 // 0 => use default buffer sizes.
256 if (!BIO_new_bio_pair(&ssl_bio, 0, &transport_bio_, 0))
[email protected]d518cd92010-09-29 12:27:44257 return false;
[email protected]d518cd92010-09-29 12:27:44258 DCHECK(ssl_bio);
259 DCHECK(transport_bio_);
260
261 SSL_set_bio(ssl_, ssl_bio, ssl_bio);
262
[email protected]9e733f32010-10-04 18:19:08263#define SET_SSL_CONFIG_OPTION(option, value) \
264 (((value) ? set_mask : clear_mask) |= (option))
265
266 // OpenSSL defaults some options to on, others to off. To avoid ambiguity,
267 // set everything we care about to an absolute value.
268 long set_mask = 0;
269 long clear_mask = 0;
270 SET_SSL_CONFIG_OPTION(SSL_OP_NO_SSLv2, !ssl_config_.ssl2_enabled);
271 SET_SSL_CONFIG_OPTION(SSL_OP_NO_SSLv3, !ssl_config_.ssl3_enabled);
272 SET_SSL_CONFIG_OPTION(SSL_OP_NO_TLSv1, !ssl_config_.tls1_enabled);
273
274 // TODO(joth): Set this conditionally, see http://crbug.com/55410
275 SET_SSL_CONFIG_OPTION(SSL_OP_LEGACY_SERVER_CONNECT, true);
276
277 // Make sure we haven't got any intersection in the set & clear options.
278 DCHECK_EQ(0, set_mask & clear_mask);
279
280 SSL_set_options(ssl_, set_mask);
281 SSL_clear_options(ssl_, clear_mask);
282#undef SET_SSL_CONFIG_OPTION
283
[email protected]d518cd92010-09-29 12:27:44284 return true;
285}
286
[email protected]d518cd92010-09-29 12:27:44287// SSLClientSocket methods
288
289void SSLClientSocketOpenSSL::GetSSLInfo(SSLInfo* ssl_info) {
[email protected]170e76c2010-10-04 15:04:20290 ssl_info->Reset();
291 if (!server_cert_)
292 return;
293
[email protected]170e76c2010-10-04 15:04:20294 ssl_info->cert = server_cert_;
295 ssl_info->cert_status = server_cert_verify_result_.cert_status;
[email protected]2907525c2010-10-08 15:53:52296
297 const SSL_CIPHER* cipher = SSL_get_current_cipher(ssl_);
298 CHECK(cipher);
299 ssl_info->security_bits = SSL_CIPHER_get_bits(cipher, NULL);
300 ssl_info->connection_status |= (cipher->id & SSL_CONNECTION_CIPHERSUITE_MASK)
301 << SSL_CONNECTION_CIPHERSUITE_SHIFT;
302 DVLOG(2) << SSL_CIPHER_get_name(cipher) << ": cipher ID " << cipher->id
303 << " security bits " << ssl_info->security_bits;
304
305 // Experimenting suggests the compression object is optional, whereas the
306 // cipher (above) is always present.
307 const COMP_METHOD* compression = SSL_get_current_compression(ssl_);
308 if (compression) {
309 ssl_info->connection_status |=
310 (compression->type & SSL_CONNECTION_COMPRESSION_MASK)
311 << SSL_CONNECTION_COMPRESSION_SHIFT;
312 DVLOG(2) << SSL_COMP_get_name(compression)
313 << ": compression ID " << compression->type;
314 }
[email protected]9e733f32010-10-04 18:19:08315
316 bool peer_supports_renego_ext = !!SSL_get_secure_renegotiation_support(ssl_);
317 if (!peer_supports_renego_ext)
318 ssl_info->connection_status |= SSL_CONNECTION_NO_RENEGOTIATION_EXTENSION;
319 UMA_HISTOGRAM_ENUMERATION("Net.RenegotiationExtensionSupported",
320 (int)peer_supports_renego_ext, 2);
321
322 if (ssl_config_.ssl3_fallback)
323 ssl_info->connection_status |= SSL_CONNECTION_SSL3_FALLBACK;
[email protected]d518cd92010-09-29 12:27:44324}
325
326void SSLClientSocketOpenSSL::GetSSLCertRequestInfo(
327 SSLCertRequestInfo* cert_request_info) {
328 NOTREACHED();
329}
330
331SSLClientSocket::NextProtoStatus SSLClientSocketOpenSSL::GetNextProto(
332 std::string* proto) {
333 proto->clear();
334 return kNextProtoUnsupported;
335}
336
337void SSLClientSocketOpenSSL::DoReadCallback(int rv) {
338 // Since Run may result in Read being called, clear |user_read_callback_|
339 // up front.
340 CompletionCallback* c = user_read_callback_;
341 user_read_callback_ = NULL;
342 user_read_buf_ = NULL;
343 user_read_buf_len_ = 0;
344 c->Run(rv);
345}
346
347void SSLClientSocketOpenSSL::DoWriteCallback(int rv) {
348 // Since Run may result in Write being called, clear |user_write_callback_|
349 // up front.
350 CompletionCallback* c = user_write_callback_;
351 user_write_callback_ = NULL;
352 user_write_buf_ = NULL;
353 user_write_buf_len_ = 0;
354 c->Run(rv);
355}
356
357// ClientSocket methods
358
359int SSLClientSocketOpenSSL::Connect(CompletionCallback* callback) {
360 net_log_.BeginEvent(NetLog::TYPE_SSL_CONNECT, NULL);
361
[email protected]d518cd92010-09-29 12:27:44362 // Set up new ssl object.
363 if (!Init()) {
364 net_log_.EndEvent(NetLog::TYPE_SSL_CONNECT, NULL);
365 return ERR_UNEXPECTED;
366 }
367
368 // Set SSL to client mode. Handshake happens in the loop below.
369 SSL_set_connect_state(ssl_);
370
371 GotoState(STATE_HANDSHAKE);
372 int rv = DoHandshakeLoop(net::OK);
373 if (rv == ERR_IO_PENDING) {
374 user_connect_callback_ = callback;
375 } else {
376 net_log_.EndEvent(NetLog::TYPE_SSL_CONNECT, NULL);
377 }
378
379 return rv > OK ? OK : rv;
380}
381
382void SSLClientSocketOpenSSL::Disconnect() {
[email protected]170e76c2010-10-04 15:04:20383 if (ssl_) {
384 SSL_free(ssl_);
385 ssl_ = NULL;
386 }
387 if (transport_bio_) {
388 BIO_free_all(transport_bio_);
389 transport_bio_ = NULL;
390 }
391
392 // Shut down anything that may call us back (through buffer_send_callback_,
393 // buffer_recv_callback, or handshake_io_callback_).
394 verifier_.reset();
395 transport_->socket()->Disconnect();
396
[email protected]d518cd92010-09-29 12:27:44397 // Null all callbacks, delete all buffers.
398 transport_send_busy_ = false;
399 send_buffer_ = NULL;
400 transport_recv_busy_ = false;
401 recv_buffer_ = NULL;
402
403 user_connect_callback_ = NULL;
404 user_read_callback_ = NULL;
405 user_write_callback_ = NULL;
406 user_read_buf_ = NULL;
407 user_read_buf_len_ = 0;
408 user_write_buf_ = NULL;
409 user_write_buf_len_ = 0;
410
[email protected]170e76c2010-10-04 15:04:20411 server_cert_verify_result_.Reset();
[email protected]d518cd92010-09-29 12:27:44412 completed_handshake_ = false;
[email protected]fbef13932010-11-23 12:38:53413
414 client_certs_.clear();
415 client_auth_cert_needed_ = false;
[email protected]d518cd92010-09-29 12:27:44416}
417
418int SSLClientSocketOpenSSL::DoHandshakeLoop(int last_io_result) {
419 bool network_moved;
420 int rv = last_io_result;
421 do {
422 // Default to STATE_NONE for next state.
423 // (This is a quirk carried over from the windows
424 // implementation. It makes reading the logs a bit harder.)
425 // State handlers can and often do call GotoState just
426 // to stay in the current state.
427 State state = next_handshake_state_;
428 GotoState(STATE_NONE);
429 switch (state) {
430 case STATE_NONE:
431 // we're just pumping data between the buffer and the network
432 break;
433 case STATE_HANDSHAKE:
434 rv = DoHandshake();
435 break;
[email protected]d518cd92010-09-29 12:27:44436 case STATE_VERIFY_CERT:
437 DCHECK(rv == OK);
438 rv = DoVerifyCert(rv);
439 break;
440 case STATE_VERIFY_CERT_COMPLETE:
441 rv = DoVerifyCertComplete(rv);
442 break;
[email protected]d518cd92010-09-29 12:27:44443 default:
444 rv = ERR_UNEXPECTED;
445 NOTREACHED() << "unexpected state" << state;
446 break;
447 }
448
449 // To avoid getting an ERR_IO_PENDING here after handshake complete.
450 if (next_handshake_state_ == STATE_NONE)
451 break;
452
453 // Do the actual network I/O.
454 network_moved = DoTransportIO();
455 } while ((rv != ERR_IO_PENDING || network_moved) &&
456 next_handshake_state_ != STATE_NONE);
457 return rv;
458}
459
460int SSLClientSocketOpenSSL::DoHandshake() {
[email protected]fbef13932010-11-23 12:38:53461 base::OpenSSLErrStackTracer err_tracer(FROM_HERE);
[email protected]d518cd92010-09-29 12:27:44462 int net_error = net::OK;
463 int rv = SSL_do_handshake(ssl_);
464
465 if (rv == 1) {
[email protected]fbef13932010-11-23 12:38:53466 if (trying_cached_session_ && logging::DEBUG_MODE) {
467 DVLOG(2) << "Result of session reuse for " << host_and_port_.ToString()
468 << " is: " << (SSL_session_reused(ssl_) ? "Success" : "Fail");
469 }
470
[email protected]d518cd92010-09-29 12:27:44471 // SSL handshake is completed. Let's verify the certificate.
[email protected]abc7e06d2010-10-06 15:40:35472 const bool got_cert = !!UpdateServerCert();
473 DCHECK(got_cert);
474 GotoState(STATE_VERIFY_CERT);
[email protected]d518cd92010-09-29 12:27:44475 } else {
476 int ssl_error = SSL_get_error(ssl_, rv);
[email protected]170e76c2010-10-04 15:04:20477 net_error = MapOpenSSLError(ssl_error);
[email protected]d518cd92010-09-29 12:27:44478
479 // If not done, stay in this state
[email protected]170e76c2010-10-04 15:04:20480 if (net_error == ERR_IO_PENDING) {
481 GotoState(STATE_HANDSHAKE);
482 } else {
483 LOG(ERROR) << "handshake failed; returned " << rv
484 << ", SSL error code " << ssl_error
485 << ", net_error " << net_error;
[email protected]170e76c2010-10-04 15:04:20486 }
487 }
488 return net_error;
489}
490
491int SSLClientSocketOpenSSL::DoVerifyCert(int result) {
492 DCHECK(server_cert_);
493 GotoState(STATE_VERIFY_CERT_COMPLETE);
494 int flags = 0;
495
496 if (ssl_config_.rev_checking_enabled)
497 flags |= X509Certificate::VERIFY_REV_CHECKING_ENABLED;
498 if (ssl_config_.verify_ev_cert)
499 flags |= X509Certificate::VERIFY_EV_CERT;
500 verifier_.reset(new CertVerifier);
[email protected]055d7f22010-11-15 12:03:12501 return verifier_->Verify(server_cert_, host_and_port_.host(), flags,
[email protected]170e76c2010-10-04 15:04:20502 &server_cert_verify_result_,
503 &handshake_io_callback_);
504}
505
506int SSLClientSocketOpenSSL::DoVerifyCertComplete(int result) {
507 verifier_.reset();
508
509 if (result == OK) {
510 // TODO(joth): Work out if we need to remember the intermediate CA certs
511 // when the server sends them to us, and do so here.
[email protected]2907525c2010-10-08 15:53:52512 } else {
513 DVLOG(1) << "DoVerifyCertComplete error " << ErrorToString(result)
514 << " (" << result << ")";
[email protected]d518cd92010-09-29 12:27:44515 }
516
[email protected]170e76c2010-10-04 15:04:20517 // If we have been explicitly told to accept this certificate, override the
518 // result of verifier_.Verify.
519 // Eventually, we should cache the cert verification results so that we don't
520 // need to call verifier_.Verify repeatedly. But for now we need to do this.
521 // Alternatively, we could use the cert's status that we stored along with
522 // the cert in the allowed_bad_certs vector.
523 if (IsCertificateError(result) &&
524 ssl_config_.IsAllowedBadCert(server_cert_)) {
[email protected]b30a3f52010-10-16 01:05:46525 VLOG(1) << "accepting bad SSL certificate, as user told us to";
[email protected]170e76c2010-10-04 15:04:20526 result = OK;
527 }
528
529 completed_handshake_ = true;
[email protected]170e76c2010-10-04 15:04:20530 // Exit DoHandshakeLoop and return the result to the caller to Connect.
531 DCHECK_EQ(STATE_NONE, next_handshake_state_);
532 return result;
533}
534
[email protected]170e76c2010-10-04 15:04:20535X509Certificate* SSLClientSocketOpenSSL::UpdateServerCert() {
536 if (server_cert_)
537 return server_cert_;
538
[email protected]313834722010-11-17 09:57:18539 base::ScopedOpenSSL<X509, X509_free> cert(SSL_get_peer_certificate(ssl_));
[email protected]2907525c2010-10-08 15:53:52540 if (!cert.get()) {
[email protected]170e76c2010-10-04 15:04:20541 LOG(WARNING) << "SSL_get_peer_certificate returned NULL";
542 return NULL;
543 }
544
[email protected]2907525c2010-10-08 15:53:52545 // Unlike SSL_get_peer_certificate, SSL_get_peer_cert_chain does not
546 // increment the reference so sk_X509_free does not need to be called.
547 STACK_OF(X509)* chain = SSL_get_peer_cert_chain(ssl_);
548 X509Certificate::OSCertHandles intermediates;
549 if (chain) {
550 for (int i = 0; i < sk_X509_num(chain); ++i)
551 intermediates.push_back(sk_X509_value(chain, i));
552 }
553 server_cert_ = X509Certificate::CreateFromHandle(
554 cert.get(), X509Certificate::SOURCE_FROM_NETWORK, intermediates);
[email protected]170e76c2010-10-04 15:04:20555 DCHECK(server_cert_);
[email protected]170e76c2010-10-04 15:04:20556
557 return server_cert_;
[email protected]d518cd92010-09-29 12:27:44558}
559
560bool SSLClientSocketOpenSSL::DoTransportIO() {
561 bool network_moved = false;
562 int nsent = BufferSend();
563 int nreceived = BufferRecv();
564 network_moved = (nsent > 0 || nreceived >= 0);
565 return network_moved;
566}
567
568int SSLClientSocketOpenSSL::BufferSend(void) {
569 if (transport_send_busy_)
570 return ERR_IO_PENDING;
571
572 if (!send_buffer_) {
573 // Get a fresh send buffer out of the send BIO.
574 size_t max_read = BIO_ctrl_pending(transport_bio_);
575 if (max_read > 0) {
576 send_buffer_ = new DrainableIOBuffer(new IOBuffer(max_read), max_read);
577 int read_bytes = BIO_read(transport_bio_, send_buffer_->data(), max_read);
578 DCHECK_GT(read_bytes, 0);
579 CHECK_EQ(static_cast<int>(max_read), read_bytes);
580 }
581 }
582
583 int rv = 0;
584 while (send_buffer_) {
585 rv = transport_->socket()->Write(send_buffer_,
586 send_buffer_->BytesRemaining(),
587 &buffer_send_callback_);
588 if (rv == ERR_IO_PENDING) {
589 transport_send_busy_ = true;
590 return rv;
591 }
592 TransportWriteComplete(rv);
593 }
594 return rv;
595}
596
597void SSLClientSocketOpenSSL::BufferSendComplete(int result) {
598 transport_send_busy_ = false;
599 TransportWriteComplete(result);
600 OnSendComplete(result);
601}
602
603void SSLClientSocketOpenSSL::TransportWriteComplete(int result) {
[email protected]abc7e06d2010-10-06 15:40:35604 DCHECK(ERR_IO_PENDING != result);
[email protected]d518cd92010-09-29 12:27:44605 if (result < 0) {
606 // Got a socket write error; close the BIO to indicate this upward.
[email protected]abc7e06d2010-10-06 15:40:35607 DVLOG(1) << "TransportWriteComplete error " << result;
[email protected]d518cd92010-09-29 12:27:44608 (void)BIO_shutdown_wr(transport_bio_);
609 send_buffer_ = NULL;
610 } else {
611 DCHECK(send_buffer_);
612 send_buffer_->DidConsume(result);
613 DCHECK_GE(send_buffer_->BytesRemaining(), 0);
614 if (send_buffer_->BytesRemaining() <= 0)
615 send_buffer_ = NULL;
616 }
617}
618
619int SSLClientSocketOpenSSL::BufferRecv(void) {
620 if (transport_recv_busy_)
621 return ERR_IO_PENDING;
622
623 size_t max_write = BIO_ctrl_get_write_guarantee(transport_bio_);
624 if (max_write > kMaxRecvBufferSize)
625 max_write = kMaxRecvBufferSize;
626
627 if (!max_write)
628 return ERR_IO_PENDING;
629
630 recv_buffer_ = new IOBuffer(max_write);
631 int rv = transport_->socket()->Read(recv_buffer_, max_write,
632 &buffer_recv_callback_);
633 if (rv == ERR_IO_PENDING) {
634 transport_recv_busy_ = true;
635 } else {
636 TransportReadComplete(rv);
637 }
638 return rv;
639}
640
641void SSLClientSocketOpenSSL::BufferRecvComplete(int result) {
642 TransportReadComplete(result);
643 OnRecvComplete(result);
644}
645
646void SSLClientSocketOpenSSL::TransportReadComplete(int result) {
[email protected]abc7e06d2010-10-06 15:40:35647 DCHECK(ERR_IO_PENDING != result);
648 if (result <= 0) {
649 DVLOG(1) << "TransportReadComplete result " << result;
650 // Received 0 (end of file) or an error. Either way, bubble it up to the
651 // SSL layer via the BIO. TODO(joth): consider stashing the error code, to
652 // relay up to the SSL socket client (i.e. via DoReadCallback).
653 BIO_set_mem_eof_return(transport_bio_, 0);
654 (void)BIO_shutdown_wr(transport_bio_);
655 } else {
656 DCHECK(recv_buffer_);
[email protected]d518cd92010-09-29 12:27:44657 int ret = BIO_write(transport_bio_, recv_buffer_->data(), result);
658 // A write into a memory BIO should always succeed.
659 CHECK_EQ(result, ret);
[email protected]d518cd92010-09-29 12:27:44660 }
661 recv_buffer_ = NULL;
662 transport_recv_busy_ = false;
663}
664
665void SSLClientSocketOpenSSL::DoConnectCallback(int rv) {
666 CompletionCallback* c = user_connect_callback_;
667 user_connect_callback_ = NULL;
668 c->Run(rv > OK ? OK : rv);
669}
670
671void SSLClientSocketOpenSSL::OnHandshakeIOComplete(int result) {
672 int rv = DoHandshakeLoop(result);
673 if (rv != ERR_IO_PENDING) {
674 net_log_.EndEvent(NetLog::TYPE_SSL_CONNECT, NULL);
675 DoConnectCallback(rv);
676 }
677}
678
679void SSLClientSocketOpenSSL::OnSendComplete(int result) {
680 if (next_handshake_state_ != STATE_NONE) {
681 // In handshake phase.
682 OnHandshakeIOComplete(result);
683 return;
684 }
685
686 // OnSendComplete may need to call DoPayloadRead while the renegotiation
687 // handshake is in progress.
688 int rv_read = ERR_IO_PENDING;
689 int rv_write = ERR_IO_PENDING;
690 bool network_moved;
691 do {
692 if (user_read_buf_)
693 rv_read = DoPayloadRead();
694 if (user_write_buf_)
695 rv_write = DoPayloadWrite();
696 network_moved = DoTransportIO();
697 } while (rv_read == ERR_IO_PENDING &&
698 rv_write == ERR_IO_PENDING &&
699 network_moved);
700
701 if (user_read_buf_ && rv_read != ERR_IO_PENDING)
702 DoReadCallback(rv_read);
703 if (user_write_buf_ && rv_write != ERR_IO_PENDING)
704 DoWriteCallback(rv_write);
705}
706
707void SSLClientSocketOpenSSL::OnRecvComplete(int result) {
708 if (next_handshake_state_ != STATE_NONE) {
709 // In handshake phase.
710 OnHandshakeIOComplete(result);
711 return;
712 }
713
714 // Network layer received some data, check if client requested to read
715 // decrypted data.
716 if (!user_read_buf_)
717 return;
718
719 int rv = DoReadLoop(result);
720 if (rv != ERR_IO_PENDING)
721 DoReadCallback(rv);
722}
723
724bool SSLClientSocketOpenSSL::IsConnected() const {
725 bool ret = completed_handshake_ && transport_->socket()->IsConnected();
726 return ret;
727}
728
729bool SSLClientSocketOpenSSL::IsConnectedAndIdle() const {
730 bool ret = completed_handshake_ && transport_->socket()->IsConnectedAndIdle();
731 return ret;
732}
733
734int SSLClientSocketOpenSSL::GetPeerAddress(AddressList* addressList) const {
735 return transport_->socket()->GetPeerAddress(addressList);
736}
737
738const BoundNetLog& SSLClientSocketOpenSSL::NetLog() const {
739 return net_log_;
740}
741
742void SSLClientSocketOpenSSL::SetSubresourceSpeculation() {
743 if (transport_.get() && transport_->socket()) {
744 transport_->socket()->SetSubresourceSpeculation();
745 } else {
746 NOTREACHED();
747 }
748}
749
750void SSLClientSocketOpenSSL::SetOmniboxSpeculation() {
751 if (transport_.get() && transport_->socket()) {
752 transport_->socket()->SetOmniboxSpeculation();
753 } else {
754 NOTREACHED();
755 }
756}
757
758bool SSLClientSocketOpenSSL::WasEverUsed() const {
759 if (transport_.get() && transport_->socket())
760 return transport_->socket()->WasEverUsed();
761
762 NOTREACHED();
763 return false;
764}
765
[email protected]7f7e92392010-10-26 18:29:29766bool SSLClientSocketOpenSSL::UsingTCPFastOpen() const {
767 if (transport_.get() && transport_->socket())
768 return transport_->socket()->UsingTCPFastOpen();
769
770 NOTREACHED();
771 return false;
772}
773
[email protected]d518cd92010-09-29 12:27:44774// Socket methods
775
776int SSLClientSocketOpenSSL::Read(IOBuffer* buf,
777 int buf_len,
778 CompletionCallback* callback) {
779 user_read_buf_ = buf;
780 user_read_buf_len_ = buf_len;
781
782 int rv = DoReadLoop(OK);
783
784 if (rv == ERR_IO_PENDING) {
785 user_read_callback_ = callback;
786 } else {
787 user_read_buf_ = NULL;
788 user_read_buf_len_ = 0;
789 }
790
791 return rv;
792}
793
794int SSLClientSocketOpenSSL::DoReadLoop(int result) {
795 if (result < 0)
796 return result;
797
798 bool network_moved;
799 int rv;
800 do {
801 rv = DoPayloadRead();
802 network_moved = DoTransportIO();
803 } while (rv == ERR_IO_PENDING && network_moved);
804
805 return rv;
806}
807
808int SSLClientSocketOpenSSL::Write(IOBuffer* buf,
809 int buf_len,
810 CompletionCallback* callback) {
811 user_write_buf_ = buf;
812 user_write_buf_len_ = buf_len;
813
814 int rv = DoWriteLoop(OK);
815
816 if (rv == ERR_IO_PENDING) {
817 user_write_callback_ = callback;
818 } else {
819 user_write_buf_ = NULL;
820 user_write_buf_len_ = 0;
821 }
822
823 return rv;
824}
825
826int SSLClientSocketOpenSSL::DoWriteLoop(int result) {
827 if (result < 0)
828 return result;
829
830 bool network_moved;
831 int rv;
832 do {
833 rv = DoPayloadWrite();
834 network_moved = DoTransportIO();
835 } while (rv == ERR_IO_PENDING && network_moved);
836
837 return rv;
838}
839
840bool SSLClientSocketOpenSSL::SetReceiveBufferSize(int32 size) {
841 return transport_->socket()->SetReceiveBufferSize(size);
842}
843
844bool SSLClientSocketOpenSSL::SetSendBufferSize(int32 size) {
845 return transport_->socket()->SetSendBufferSize(size);
846}
847
848int SSLClientSocketOpenSSL::DoPayloadRead() {
[email protected]fbef13932010-11-23 12:38:53849 base::OpenSSLErrStackTracer err_tracer(FROM_HERE);
[email protected]d518cd92010-09-29 12:27:44850 int rv = SSL_read(ssl_, user_read_buf_->data(), user_read_buf_len_);
851 // We don't need to invalidate the non-client-authenticated SSL session
852 // because the server will renegotiate anyway.
853 if (client_auth_cert_needed_)
854 return ERR_SSL_CLIENT_AUTH_CERT_NEEDED;
855
856 if (rv >= 0)
857 return rv;
858
859 int err = SSL_get_error(ssl_, rv);
860 return MapOpenSSLError(err);
861}
862
863int SSLClientSocketOpenSSL::DoPayloadWrite() {
[email protected]fbef13932010-11-23 12:38:53864 base::OpenSSLErrStackTracer err_tracer(FROM_HERE);
[email protected]d518cd92010-09-29 12:27:44865 int rv = SSL_write(ssl_, user_write_buf_->data(), user_write_buf_len_);
866
867 if (rv >= 0)
868 return rv;
869
870 int err = SSL_get_error(ssl_, rv);
871 return MapOpenSSLError(err);
872}
873
874} // namespace net