blob: 64852f234360b8998b2f74419682e82612e32582 [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]170e76c2010-10-04 15:04:2013#include "net/base/cert_verifier.h"
[email protected]835d7c82010-10-14 04:38:3814#include "base/metrics/histogram.h"
[email protected]d518cd92010-09-29 12:27:4415#include "net/base/net_errors.h"
[email protected]2907525c2010-10-08 15:53:5216#include "net/base/openssl_util.h"
[email protected]d518cd92010-09-29 12:27:4417#include "net/base/ssl_connection_status_flags.h"
18#include "net/base/ssl_info.h"
[email protected]d518cd92010-09-29 12:27:4419
20namespace net {
21
22namespace {
23
24// Enable this to see logging for state machine state transitions.
25#if 0
[email protected]3b112772010-10-04 10:54:4926#define GotoState(s) do { DVLOG(2) << (void *)this << " " << __FUNCTION__ << \
[email protected]d518cd92010-09-29 12:27:4427 " jump to state " << s; \
28 next_handshake_state_ = s; } while (0)
29#else
30#define GotoState(s) next_handshake_state_ = s
31#endif
32
33const size_t kMaxRecvBufferSize = 4096;
34
35void MaybeLogSSLError() {
36 int error_num;
37 while ((error_num = ERR_get_error()) != 0) {
38 char buf[128]; // this buffer must be at least 120 chars long.
39 ERR_error_string_n(error_num, buf, arraysize(buf));
[email protected]3b112772010-10-04 10:54:4940 DVLOG(1) << "SSL error " << error_num << ": " << buf;
[email protected]d518cd92010-09-29 12:27:4441 }
42}
43
44int MapOpenSSLError(int err) {
45 switch (err) {
46 case SSL_ERROR_WANT_READ:
47 case SSL_ERROR_WANT_WRITE:
48 return ERR_IO_PENDING;
[email protected]170e76c2010-10-04 15:04:2049 case SSL_ERROR_SYSCALL:
[email protected]abc7e06d2010-10-06 15:40:3550 DVLOG(1) << "OpenSSL SYSCALL error, errno " << errno;
[email protected]170e76c2010-10-04 15:04:2051 MaybeLogSSLError();
52 return ERR_SSL_PROTOCOL_ERROR;
[email protected]d518cd92010-09-29 12:27:4453 default:
54 // TODO(joth): Implement full mapping.
55 LOG(WARNING) << "Unknown OpenSSL error " << err;
56 MaybeLogSSLError();
57 return ERR_SSL_PROTOCOL_ERROR;
58 }
59}
60
[email protected]3b112772010-10-04 10:54:4961} // namespace
[email protected]d518cd92010-09-29 12:27:4462
63SSLClientSocketOpenSSL::SSLClientSocketOpenSSL(
64 ClientSocketHandle* transport_socket,
65 const std::string& hostname,
66 const SSLConfig& ssl_config)
67 : ALLOW_THIS_IN_INITIALIZER_LIST(buffer_send_callback_(
68 this, &SSLClientSocketOpenSSL::BufferSendComplete)),
69 ALLOW_THIS_IN_INITIALIZER_LIST(buffer_recv_callback_(
70 this, &SSLClientSocketOpenSSL::BufferRecvComplete)),
71 transport_send_busy_(false),
72 transport_recv_busy_(false),
73 user_connect_callback_(NULL),
74 user_read_callback_(NULL),
75 user_write_callback_(NULL),
76 client_auth_cert_needed_(false),
[email protected]170e76c2010-10-04 15:04:2077 ALLOW_THIS_IN_INITIALIZER_LIST(handshake_io_callback_(
78 this, &SSLClientSocketOpenSSL::OnHandshakeIOComplete)),
[email protected]d518cd92010-09-29 12:27:4479 ssl_(NULL),
80 transport_bio_(NULL),
81 transport_(transport_socket),
82 hostname_(hostname),
83 ssl_config_(ssl_config),
84 completed_handshake_(false),
85 net_log_(transport_socket->socket()->NetLog()) {
86}
87
88SSLClientSocketOpenSSL::~SSLClientSocketOpenSSL() {
89 Disconnect();
90}
91
[email protected]d518cd92010-09-29 12:27:4492bool SSLClientSocketOpenSSL::Init() {
[email protected]9e733f32010-10-04 18:19:0893 DCHECK(!ssl_);
94 DCHECK(!transport_bio_);
95
[email protected]2907525c2010-10-08 15:53:5296 ssl_ = SSL_new(GetOpenSSLInitSingleton()->ssl_ctx());
[email protected]d518cd92010-09-29 12:27:4497 if (!ssl_) {
98 MaybeLogSSLError();
99 return false;
100 }
101
102 if (!SSL_set_tlsext_host_name(ssl_, hostname_.c_str())) {
103 MaybeLogSSLError();
104 return false;
105 }
106
107 BIO* ssl_bio = NULL;
108 // TODO(joth): Provide explicit write buffer sizes, rather than use defaults?
109 if (!BIO_new_bio_pair(&ssl_bio, 0, &transport_bio_, 0)) {
110 MaybeLogSSLError();
111 return false;
112 }
113 DCHECK(ssl_bio);
114 DCHECK(transport_bio_);
115
116 SSL_set_bio(ssl_, ssl_bio, ssl_bio);
117
[email protected]9e733f32010-10-04 18:19:08118#define SET_SSL_CONFIG_OPTION(option, value) \
119 (((value) ? set_mask : clear_mask) |= (option))
120
121 // OpenSSL defaults some options to on, others to off. To avoid ambiguity,
122 // set everything we care about to an absolute value.
123 long set_mask = 0;
124 long clear_mask = 0;
125 SET_SSL_CONFIG_OPTION(SSL_OP_NO_SSLv2, !ssl_config_.ssl2_enabled);
126 SET_SSL_CONFIG_OPTION(SSL_OP_NO_SSLv3, !ssl_config_.ssl3_enabled);
127 SET_SSL_CONFIG_OPTION(SSL_OP_NO_TLSv1, !ssl_config_.tls1_enabled);
128
129 // TODO(joth): Set this conditionally, see http://crbug.com/55410
130 SET_SSL_CONFIG_OPTION(SSL_OP_LEGACY_SERVER_CONNECT, true);
131
132 // Make sure we haven't got any intersection in the set & clear options.
133 DCHECK_EQ(0, set_mask & clear_mask);
134
135 SSL_set_options(ssl_, set_mask);
136 SSL_clear_options(ssl_, clear_mask);
137#undef SET_SSL_CONFIG_OPTION
138
[email protected]d518cd92010-09-29 12:27:44139 return true;
140}
141
[email protected]d518cd92010-09-29 12:27:44142// SSLClientSocket methods
143
144void SSLClientSocketOpenSSL::GetSSLInfo(SSLInfo* ssl_info) {
[email protected]170e76c2010-10-04 15:04:20145 ssl_info->Reset();
146 if (!server_cert_)
147 return;
148
[email protected]170e76c2010-10-04 15:04:20149 ssl_info->cert = server_cert_;
150 ssl_info->cert_status = server_cert_verify_result_.cert_status;
[email protected]2907525c2010-10-08 15:53:52151
152 const SSL_CIPHER* cipher = SSL_get_current_cipher(ssl_);
153 CHECK(cipher);
154 ssl_info->security_bits = SSL_CIPHER_get_bits(cipher, NULL);
155 ssl_info->connection_status |= (cipher->id & SSL_CONNECTION_CIPHERSUITE_MASK)
156 << SSL_CONNECTION_CIPHERSUITE_SHIFT;
157 DVLOG(2) << SSL_CIPHER_get_name(cipher) << ": cipher ID " << cipher->id
158 << " security bits " << ssl_info->security_bits;
159
160 // Experimenting suggests the compression object is optional, whereas the
161 // cipher (above) is always present.
162 const COMP_METHOD* compression = SSL_get_current_compression(ssl_);
163 if (compression) {
164 ssl_info->connection_status |=
165 (compression->type & SSL_CONNECTION_COMPRESSION_MASK)
166 << SSL_CONNECTION_COMPRESSION_SHIFT;
167 DVLOG(2) << SSL_COMP_get_name(compression)
168 << ": compression ID " << compression->type;
169 }
[email protected]9e733f32010-10-04 18:19:08170
171 bool peer_supports_renego_ext = !!SSL_get_secure_renegotiation_support(ssl_);
172 if (!peer_supports_renego_ext)
173 ssl_info->connection_status |= SSL_CONNECTION_NO_RENEGOTIATION_EXTENSION;
174 UMA_HISTOGRAM_ENUMERATION("Net.RenegotiationExtensionSupported",
175 (int)peer_supports_renego_ext, 2);
176
177 if (ssl_config_.ssl3_fallback)
178 ssl_info->connection_status |= SSL_CONNECTION_SSL3_FALLBACK;
[email protected]d518cd92010-09-29 12:27:44179}
180
181void SSLClientSocketOpenSSL::GetSSLCertRequestInfo(
182 SSLCertRequestInfo* cert_request_info) {
183 NOTREACHED();
184}
185
186SSLClientSocket::NextProtoStatus SSLClientSocketOpenSSL::GetNextProto(
187 std::string* proto) {
188 proto->clear();
189 return kNextProtoUnsupported;
190}
191
192void SSLClientSocketOpenSSL::DoReadCallback(int rv) {
193 // Since Run may result in Read being called, clear |user_read_callback_|
194 // up front.
195 CompletionCallback* c = user_read_callback_;
196 user_read_callback_ = NULL;
197 user_read_buf_ = NULL;
198 user_read_buf_len_ = 0;
199 c->Run(rv);
200}
201
202void SSLClientSocketOpenSSL::DoWriteCallback(int rv) {
203 // Since Run may result in Write being called, clear |user_write_callback_|
204 // up front.
205 CompletionCallback* c = user_write_callback_;
206 user_write_callback_ = NULL;
207 user_write_buf_ = NULL;
208 user_write_buf_len_ = 0;
209 c->Run(rv);
210}
211
212// ClientSocket methods
213
214int SSLClientSocketOpenSSL::Connect(CompletionCallback* callback) {
215 net_log_.BeginEvent(NetLog::TYPE_SSL_CONNECT, NULL);
216
[email protected]d518cd92010-09-29 12:27:44217 // Set up new ssl object.
218 if (!Init()) {
219 net_log_.EndEvent(NetLog::TYPE_SSL_CONNECT, NULL);
220 return ERR_UNEXPECTED;
221 }
222
223 // Set SSL to client mode. Handshake happens in the loop below.
224 SSL_set_connect_state(ssl_);
225
226 GotoState(STATE_HANDSHAKE);
227 int rv = DoHandshakeLoop(net::OK);
228 if (rv == ERR_IO_PENDING) {
229 user_connect_callback_ = callback;
230 } else {
231 net_log_.EndEvent(NetLog::TYPE_SSL_CONNECT, NULL);
232 }
233
234 return rv > OK ? OK : rv;
235}
236
237void SSLClientSocketOpenSSL::Disconnect() {
[email protected]170e76c2010-10-04 15:04:20238 if (ssl_) {
239 SSL_free(ssl_);
240 ssl_ = NULL;
241 }
242 if (transport_bio_) {
243 BIO_free_all(transport_bio_);
244 transport_bio_ = NULL;
245 }
246
247 // Shut down anything that may call us back (through buffer_send_callback_,
248 // buffer_recv_callback, or handshake_io_callback_).
249 verifier_.reset();
250 transport_->socket()->Disconnect();
251
[email protected]d518cd92010-09-29 12:27:44252 // Null all callbacks, delete all buffers.
253 transport_send_busy_ = false;
254 send_buffer_ = NULL;
255 transport_recv_busy_ = false;
256 recv_buffer_ = NULL;
257
258 user_connect_callback_ = NULL;
259 user_read_callback_ = NULL;
260 user_write_callback_ = NULL;
261 user_read_buf_ = NULL;
262 user_read_buf_len_ = 0;
263 user_write_buf_ = NULL;
264 user_write_buf_len_ = 0;
265
266 client_certs_.clear();
267 client_auth_cert_needed_ = false;
268
[email protected]170e76c2010-10-04 15:04:20269 server_cert_verify_result_.Reset();
[email protected]d518cd92010-09-29 12:27:44270 completed_handshake_ = false;
[email protected]d518cd92010-09-29 12:27:44271}
272
273int SSLClientSocketOpenSSL::DoHandshakeLoop(int last_io_result) {
274 bool network_moved;
275 int rv = last_io_result;
276 do {
277 // Default to STATE_NONE for next state.
278 // (This is a quirk carried over from the windows
279 // implementation. It makes reading the logs a bit harder.)
280 // State handlers can and often do call GotoState just
281 // to stay in the current state.
282 State state = next_handshake_state_;
283 GotoState(STATE_NONE);
284 switch (state) {
285 case STATE_NONE:
286 // we're just pumping data between the buffer and the network
287 break;
288 case STATE_HANDSHAKE:
289 rv = DoHandshake();
290 break;
[email protected]d518cd92010-09-29 12:27:44291 case STATE_VERIFY_CERT:
292 DCHECK(rv == OK);
293 rv = DoVerifyCert(rv);
294 break;
295 case STATE_VERIFY_CERT_COMPLETE:
296 rv = DoVerifyCertComplete(rv);
297 break;
[email protected]d518cd92010-09-29 12:27:44298 default:
299 rv = ERR_UNEXPECTED;
300 NOTREACHED() << "unexpected state" << state;
301 break;
302 }
303
304 // To avoid getting an ERR_IO_PENDING here after handshake complete.
305 if (next_handshake_state_ == STATE_NONE)
306 break;
307
308 // Do the actual network I/O.
309 network_moved = DoTransportIO();
310 } while ((rv != ERR_IO_PENDING || network_moved) &&
311 next_handshake_state_ != STATE_NONE);
312 return rv;
313}
314
315int SSLClientSocketOpenSSL::DoHandshake() {
316 int net_error = net::OK;
317 int rv = SSL_do_handshake(ssl_);
318
319 if (rv == 1) {
320 // SSL handshake is completed. Let's verify the certificate.
[email protected]abc7e06d2010-10-06 15:40:35321 const bool got_cert = !!UpdateServerCert();
322 DCHECK(got_cert);
323 GotoState(STATE_VERIFY_CERT);
[email protected]d518cd92010-09-29 12:27:44324 } else {
325 int ssl_error = SSL_get_error(ssl_, rv);
[email protected]170e76c2010-10-04 15:04:20326 net_error = MapOpenSSLError(ssl_error);
[email protected]d518cd92010-09-29 12:27:44327
328 // If not done, stay in this state
[email protected]170e76c2010-10-04 15:04:20329 if (net_error == ERR_IO_PENDING) {
330 GotoState(STATE_HANDSHAKE);
331 } else {
332 LOG(ERROR) << "handshake failed; returned " << rv
333 << ", SSL error code " << ssl_error
334 << ", net_error " << net_error;
335 MaybeLogSSLError();
336 }
337 }
338 return net_error;
339}
340
341int SSLClientSocketOpenSSL::DoVerifyCert(int result) {
342 DCHECK(server_cert_);
343 GotoState(STATE_VERIFY_CERT_COMPLETE);
344 int flags = 0;
345
346 if (ssl_config_.rev_checking_enabled)
347 flags |= X509Certificate::VERIFY_REV_CHECKING_ENABLED;
348 if (ssl_config_.verify_ev_cert)
349 flags |= X509Certificate::VERIFY_EV_CERT;
350 verifier_.reset(new CertVerifier);
351 return verifier_->Verify(server_cert_, hostname_, flags,
352 &server_cert_verify_result_,
353 &handshake_io_callback_);
354}
355
356int SSLClientSocketOpenSSL::DoVerifyCertComplete(int result) {
357 verifier_.reset();
358
359 if (result == OK) {
360 // TODO(joth): Work out if we need to remember the intermediate CA certs
361 // when the server sends them to us, and do so here.
[email protected]2907525c2010-10-08 15:53:52362 } else {
363 DVLOG(1) << "DoVerifyCertComplete error " << ErrorToString(result)
364 << " (" << result << ")";
[email protected]d518cd92010-09-29 12:27:44365 }
366
[email protected]170e76c2010-10-04 15:04:20367 // If we have been explicitly told to accept this certificate, override the
368 // result of verifier_.Verify.
369 // Eventually, we should cache the cert verification results so that we don't
370 // need to call verifier_.Verify repeatedly. But for now we need to do this.
371 // Alternatively, we could use the cert's status that we stored along with
372 // the cert in the allowed_bad_certs vector.
373 if (IsCertificateError(result) &&
374 ssl_config_.IsAllowedBadCert(server_cert_)) {
375 LOG(INFO) << "accepting bad SSL certificate, as user told us to";
376 result = OK;
377 }
378
379 completed_handshake_ = true;
380 // The NSS version has a comment that we may not need this call because it is
381 // now harmless to have a session with a bad cert.
382 // This may or may not apply here, but let's invalidate it anyway.
383 InvalidateSessionIfBadCertificate();
384 // Exit DoHandshakeLoop and return the result to the caller to Connect.
385 DCHECK_EQ(STATE_NONE, next_handshake_state_);
386 return result;
387}
388
389void SSLClientSocketOpenSSL::InvalidateSessionIfBadCertificate() {
390 if (UpdateServerCert() != NULL &&
391 ssl_config_.IsAllowedBadCert(server_cert_)) {
392 // Remove from session cache but don't clear this connection.
393 // TODO(joth): This should be a no-op until we enable session caching,
394 // see SSL_CTX_set_session_cache_mode(SSL_SESS_CACHE_CLIENT).
395 SSL_SESSION* session = SSL_get_session(ssl_);
396 LOG_IF(ERROR, session) << "Connection has a session?? " << session;
[email protected]2907525c2010-10-08 15:53:52397 int rv = SSL_CTX_remove_session(GetOpenSSLInitSingleton()->ssl_ctx(),
398 session);
[email protected]170e76c2010-10-04 15:04:20399 LOG_IF(ERROR, rv) << "Session was cached?? " << rv;
400 }
401}
402
403X509Certificate* SSLClientSocketOpenSSL::UpdateServerCert() {
404 if (server_cert_)
405 return server_cert_;
406
[email protected]2907525c2010-10-08 15:53:52407 ScopedSSL<X509, X509_free> cert(SSL_get_peer_certificate(ssl_));
408 if (!cert.get()) {
[email protected]170e76c2010-10-04 15:04:20409 LOG(WARNING) << "SSL_get_peer_certificate returned NULL";
410 return NULL;
411 }
412
[email protected]2907525c2010-10-08 15:53:52413 // Unlike SSL_get_peer_certificate, SSL_get_peer_cert_chain does not
414 // increment the reference so sk_X509_free does not need to be called.
415 STACK_OF(X509)* chain = SSL_get_peer_cert_chain(ssl_);
416 X509Certificate::OSCertHandles intermediates;
417 if (chain) {
418 for (int i = 0; i < sk_X509_num(chain); ++i)
419 intermediates.push_back(sk_X509_value(chain, i));
420 }
421 server_cert_ = X509Certificate::CreateFromHandle(
422 cert.get(), X509Certificate::SOURCE_FROM_NETWORK, intermediates);
[email protected]170e76c2010-10-04 15:04:20423 DCHECK(server_cert_);
[email protected]170e76c2010-10-04 15:04:20424
425 return server_cert_;
[email protected]d518cd92010-09-29 12:27:44426}
427
428bool SSLClientSocketOpenSSL::DoTransportIO() {
429 bool network_moved = false;
430 int nsent = BufferSend();
431 int nreceived = BufferRecv();
432 network_moved = (nsent > 0 || nreceived >= 0);
433 return network_moved;
434}
435
436int SSLClientSocketOpenSSL::BufferSend(void) {
437 if (transport_send_busy_)
438 return ERR_IO_PENDING;
439
440 if (!send_buffer_) {
441 // Get a fresh send buffer out of the send BIO.
442 size_t max_read = BIO_ctrl_pending(transport_bio_);
443 if (max_read > 0) {
444 send_buffer_ = new DrainableIOBuffer(new IOBuffer(max_read), max_read);
445 int read_bytes = BIO_read(transport_bio_, send_buffer_->data(), max_read);
446 DCHECK_GT(read_bytes, 0);
447 CHECK_EQ(static_cast<int>(max_read), read_bytes);
448 }
449 }
450
451 int rv = 0;
452 while (send_buffer_) {
453 rv = transport_->socket()->Write(send_buffer_,
454 send_buffer_->BytesRemaining(),
455 &buffer_send_callback_);
456 if (rv == ERR_IO_PENDING) {
457 transport_send_busy_ = true;
458 return rv;
459 }
460 TransportWriteComplete(rv);
461 }
462 return rv;
463}
464
465void SSLClientSocketOpenSSL::BufferSendComplete(int result) {
466 transport_send_busy_ = false;
467 TransportWriteComplete(result);
468 OnSendComplete(result);
469}
470
471void SSLClientSocketOpenSSL::TransportWriteComplete(int result) {
[email protected]abc7e06d2010-10-06 15:40:35472 DCHECK(ERR_IO_PENDING != result);
[email protected]d518cd92010-09-29 12:27:44473 if (result < 0) {
474 // Got a socket write error; close the BIO to indicate this upward.
[email protected]abc7e06d2010-10-06 15:40:35475 DVLOG(1) << "TransportWriteComplete error " << result;
[email protected]d518cd92010-09-29 12:27:44476 (void)BIO_shutdown_wr(transport_bio_);
477 send_buffer_ = NULL;
478 } else {
479 DCHECK(send_buffer_);
480 send_buffer_->DidConsume(result);
481 DCHECK_GE(send_buffer_->BytesRemaining(), 0);
482 if (send_buffer_->BytesRemaining() <= 0)
483 send_buffer_ = NULL;
484 }
485}
486
487int SSLClientSocketOpenSSL::BufferRecv(void) {
488 if (transport_recv_busy_)
489 return ERR_IO_PENDING;
490
491 size_t max_write = BIO_ctrl_get_write_guarantee(transport_bio_);
492 if (max_write > kMaxRecvBufferSize)
493 max_write = kMaxRecvBufferSize;
494
495 if (!max_write)
496 return ERR_IO_PENDING;
497
498 recv_buffer_ = new IOBuffer(max_write);
499 int rv = transport_->socket()->Read(recv_buffer_, max_write,
500 &buffer_recv_callback_);
501 if (rv == ERR_IO_PENDING) {
502 transport_recv_busy_ = true;
503 } else {
504 TransportReadComplete(rv);
505 }
506 return rv;
507}
508
509void SSLClientSocketOpenSSL::BufferRecvComplete(int result) {
510 TransportReadComplete(result);
511 OnRecvComplete(result);
512}
513
514void SSLClientSocketOpenSSL::TransportReadComplete(int result) {
[email protected]abc7e06d2010-10-06 15:40:35515 DCHECK(ERR_IO_PENDING != result);
516 if (result <= 0) {
517 DVLOG(1) << "TransportReadComplete result " << result;
518 // Received 0 (end of file) or an error. Either way, bubble it up to the
519 // SSL layer via the BIO. TODO(joth): consider stashing the error code, to
520 // relay up to the SSL socket client (i.e. via DoReadCallback).
521 BIO_set_mem_eof_return(transport_bio_, 0);
522 (void)BIO_shutdown_wr(transport_bio_);
523 } else {
524 DCHECK(recv_buffer_);
[email protected]d518cd92010-09-29 12:27:44525 int ret = BIO_write(transport_bio_, recv_buffer_->data(), result);
526 // A write into a memory BIO should always succeed.
527 CHECK_EQ(result, ret);
[email protected]d518cd92010-09-29 12:27:44528 }
529 recv_buffer_ = NULL;
530 transport_recv_busy_ = false;
531}
532
533void SSLClientSocketOpenSSL::DoConnectCallback(int rv) {
534 CompletionCallback* c = user_connect_callback_;
535 user_connect_callback_ = NULL;
536 c->Run(rv > OK ? OK : rv);
537}
538
539void SSLClientSocketOpenSSL::OnHandshakeIOComplete(int result) {
540 int rv = DoHandshakeLoop(result);
541 if (rv != ERR_IO_PENDING) {
542 net_log_.EndEvent(NetLog::TYPE_SSL_CONNECT, NULL);
543 DoConnectCallback(rv);
544 }
545}
546
547void SSLClientSocketOpenSSL::OnSendComplete(int result) {
548 if (next_handshake_state_ != STATE_NONE) {
549 // In handshake phase.
550 OnHandshakeIOComplete(result);
551 return;
552 }
553
554 // OnSendComplete may need to call DoPayloadRead while the renegotiation
555 // handshake is in progress.
556 int rv_read = ERR_IO_PENDING;
557 int rv_write = ERR_IO_PENDING;
558 bool network_moved;
559 do {
560 if (user_read_buf_)
561 rv_read = DoPayloadRead();
562 if (user_write_buf_)
563 rv_write = DoPayloadWrite();
564 network_moved = DoTransportIO();
565 } while (rv_read == ERR_IO_PENDING &&
566 rv_write == ERR_IO_PENDING &&
567 network_moved);
568
569 if (user_read_buf_ && rv_read != ERR_IO_PENDING)
570 DoReadCallback(rv_read);
571 if (user_write_buf_ && rv_write != ERR_IO_PENDING)
572 DoWriteCallback(rv_write);
573}
574
575void SSLClientSocketOpenSSL::OnRecvComplete(int result) {
576 if (next_handshake_state_ != STATE_NONE) {
577 // In handshake phase.
578 OnHandshakeIOComplete(result);
579 return;
580 }
581
582 // Network layer received some data, check if client requested to read
583 // decrypted data.
584 if (!user_read_buf_)
585 return;
586
587 int rv = DoReadLoop(result);
588 if (rv != ERR_IO_PENDING)
589 DoReadCallback(rv);
590}
591
592bool SSLClientSocketOpenSSL::IsConnected() const {
593 bool ret = completed_handshake_ && transport_->socket()->IsConnected();
594 return ret;
595}
596
597bool SSLClientSocketOpenSSL::IsConnectedAndIdle() const {
598 bool ret = completed_handshake_ && transport_->socket()->IsConnectedAndIdle();
599 return ret;
600}
601
602int SSLClientSocketOpenSSL::GetPeerAddress(AddressList* addressList) const {
603 return transport_->socket()->GetPeerAddress(addressList);
604}
605
606const BoundNetLog& SSLClientSocketOpenSSL::NetLog() const {
607 return net_log_;
608}
609
610void SSLClientSocketOpenSSL::SetSubresourceSpeculation() {
611 if (transport_.get() && transport_->socket()) {
612 transport_->socket()->SetSubresourceSpeculation();
613 } else {
614 NOTREACHED();
615 }
616}
617
618void SSLClientSocketOpenSSL::SetOmniboxSpeculation() {
619 if (transport_.get() && transport_->socket()) {
620 transport_->socket()->SetOmniboxSpeculation();
621 } else {
622 NOTREACHED();
623 }
624}
625
626bool SSLClientSocketOpenSSL::WasEverUsed() const {
627 if (transport_.get() && transport_->socket())
628 return transport_->socket()->WasEverUsed();
629
630 NOTREACHED();
631 return false;
632}
633
634// Socket methods
635
636int SSLClientSocketOpenSSL::Read(IOBuffer* buf,
637 int buf_len,
638 CompletionCallback* callback) {
639 user_read_buf_ = buf;
640 user_read_buf_len_ = buf_len;
641
642 int rv = DoReadLoop(OK);
643
644 if (rv == ERR_IO_PENDING) {
645 user_read_callback_ = callback;
646 } else {
647 user_read_buf_ = NULL;
648 user_read_buf_len_ = 0;
649 }
650
651 return rv;
652}
653
654int SSLClientSocketOpenSSL::DoReadLoop(int result) {
655 if (result < 0)
656 return result;
657
658 bool network_moved;
659 int rv;
660 do {
661 rv = DoPayloadRead();
662 network_moved = DoTransportIO();
663 } while (rv == ERR_IO_PENDING && network_moved);
664
665 return rv;
666}
667
668int SSLClientSocketOpenSSL::Write(IOBuffer* buf,
669 int buf_len,
670 CompletionCallback* callback) {
671 user_write_buf_ = buf;
672 user_write_buf_len_ = buf_len;
673
674 int rv = DoWriteLoop(OK);
675
676 if (rv == ERR_IO_PENDING) {
677 user_write_callback_ = callback;
678 } else {
679 user_write_buf_ = NULL;
680 user_write_buf_len_ = 0;
681 }
682
683 return rv;
684}
685
686int SSLClientSocketOpenSSL::DoWriteLoop(int result) {
687 if (result < 0)
688 return result;
689
690 bool network_moved;
691 int rv;
692 do {
693 rv = DoPayloadWrite();
694 network_moved = DoTransportIO();
695 } while (rv == ERR_IO_PENDING && network_moved);
696
697 return rv;
698}
699
700bool SSLClientSocketOpenSSL::SetReceiveBufferSize(int32 size) {
701 return transport_->socket()->SetReceiveBufferSize(size);
702}
703
704bool SSLClientSocketOpenSSL::SetSendBufferSize(int32 size) {
705 return transport_->socket()->SetSendBufferSize(size);
706}
707
708int SSLClientSocketOpenSSL::DoPayloadRead() {
709 int rv = SSL_read(ssl_, user_read_buf_->data(), user_read_buf_len_);
710 // We don't need to invalidate the non-client-authenticated SSL session
711 // because the server will renegotiate anyway.
712 if (client_auth_cert_needed_)
713 return ERR_SSL_CLIENT_AUTH_CERT_NEEDED;
714
715 if (rv >= 0)
716 return rv;
717
718 int err = SSL_get_error(ssl_, rv);
719 return MapOpenSSLError(err);
720}
721
722int SSLClientSocketOpenSSL::DoPayloadWrite() {
723 int rv = SSL_write(ssl_, user_write_buf_->data(), user_write_buf_len_);
724
725 if (rv >= 0)
726 return rv;
727
728 int err = SSL_get_error(ssl_, rv);
729 return MapOpenSSLError(err);
730}
731
732} // namespace net