Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(80)

Side by Side Diff: net/socket/ssl_client_socket_openssl.cc

Issue 280853002: Preserve transport errors for OpenSSL sockets. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rephrase a lot of comments. Created 6 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « net/socket/ssl_client_socket_openssl.h ('k') | net/socket/ssl_client_socket_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 // OpenSSL binding for SSLClientSocket. The class layout and general principle 5 // OpenSSL binding for SSLClientSocket. The class layout and general principle
6 // of operation is derived from SSLClientSocketNSS. 6 // of operation is derived from SSLClientSocketNSS.
7 7
8 #include "net/socket/ssl_client_socket_openssl.h" 8 #include "net/socket/ssl_client_socket_openssl.h"
9 9
10 #include <openssl/err.h> 10 #include <openssl/err.h>
(...skipping 321 matching lines...) Expand 10 before | Expand all | Expand 10 after
332 #endif 332 #endif
333 } 333 }
334 334
335 SSLClientSocketOpenSSL::SSLClientSocketOpenSSL( 335 SSLClientSocketOpenSSL::SSLClientSocketOpenSSL(
336 scoped_ptr<ClientSocketHandle> transport_socket, 336 scoped_ptr<ClientSocketHandle> transport_socket,
337 const HostPortPair& host_and_port, 337 const HostPortPair& host_and_port,
338 const SSLConfig& ssl_config, 338 const SSLConfig& ssl_config,
339 const SSLClientSocketContext& context) 339 const SSLClientSocketContext& context)
340 : transport_send_busy_(false), 340 : transport_send_busy_(false),
341 transport_recv_busy_(false), 341 transport_recv_busy_(false),
342 transport_recv_eof_(false),
343 weak_factory_(this), 342 weak_factory_(this),
344 pending_read_error_(kNoPendingReadResult), 343 pending_read_error_(kNoPendingReadResult),
345 transport_write_error_(OK), 344 transport_read_error_(0),
345 transport_write_error_(0),
346 server_cert_chain_(new PeerCertificateChain(NULL)), 346 server_cert_chain_(new PeerCertificateChain(NULL)),
347 completed_handshake_(false), 347 completed_handshake_(false),
348 was_ever_used_(false), 348 was_ever_used_(false),
349 client_auth_cert_needed_(false), 349 client_auth_cert_needed_(false),
350 cert_verifier_(context.cert_verifier), 350 cert_verifier_(context.cert_verifier),
351 server_bound_cert_service_(context.server_bound_cert_service), 351 server_bound_cert_service_(context.server_bound_cert_service),
352 ssl_(NULL), 352 ssl_(NULL),
353 transport_bio_(NULL), 353 transport_bio_(NULL),
354 transport_(transport_socket.Pass()), 354 transport_(transport_socket.Pass()),
355 host_and_port_(host_and_port), 355 host_and_port_(host_and_port),
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
394 int rv = SSL_export_keying_material( 394 int rv = SSL_export_keying_material(
395 ssl_, out, outlen, label.data(), label.size(), 395 ssl_, out, outlen, label.data(), label.size(),
396 reinterpret_cast<const unsigned char*>(context.data()), 396 reinterpret_cast<const unsigned char*>(context.data()),
397 context.length(), context.length() > 0); 397 context.length(), context.length() > 0);
398 398
399 if (rv != 1) { 399 if (rv != 1) {
400 int ssl_error = SSL_get_error(ssl_, rv); 400 int ssl_error = SSL_get_error(ssl_, rv);
401 LOG(ERROR) << "Failed to export keying material;" 401 LOG(ERROR) << "Failed to export keying material;"
402 << " returned " << rv 402 << " returned " << rv
403 << ", SSL error code " << ssl_error; 403 << ", SSL error code " << ssl_error;
404 return MapOpenSSLError(ssl_error, err_tracer); 404 return HandleOpenSSLError(ssl_error, err_tracer);
405 } 405 }
406 return OK; 406 return OK;
407 } 407 }
408 408
409 int SSLClientSocketOpenSSL::GetTLSUniqueChannelBinding(std::string* out) { 409 int SSLClientSocketOpenSSL::GetTLSUniqueChannelBinding(std::string* out) {
410 NOTIMPLEMENTED(); 410 NOTIMPLEMENTED();
411 return ERR_NOT_IMPLEMENTED; 411 return ERR_NOT_IMPLEMENTED;
412 } 412 }
413 413
414 int SSLClientSocketOpenSSL::Connect(const CompletionCallback& callback) { 414 int SSLClientSocketOpenSSL::Connect(const CompletionCallback& callback) {
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
449 } 449 }
450 450
451 // Shut down anything that may call us back. 451 // Shut down anything that may call us back.
452 verifier_.reset(); 452 verifier_.reset();
453 transport_->socket()->Disconnect(); 453 transport_->socket()->Disconnect();
454 454
455 // Null all callbacks, delete all buffers. 455 // Null all callbacks, delete all buffers.
456 transport_send_busy_ = false; 456 transport_send_busy_ = false;
457 send_buffer_ = NULL; 457 send_buffer_ = NULL;
458 transport_recv_busy_ = false; 458 transport_recv_busy_ = false;
459 transport_recv_eof_ = false;
460 recv_buffer_ = NULL; 459 recv_buffer_ = NULL;
461 460
462 user_connect_callback_.Reset(); 461 user_connect_callback_.Reset();
463 user_read_callback_.Reset(); 462 user_read_callback_.Reset();
464 user_write_callback_.Reset(); 463 user_write_callback_.Reset();
465 user_read_buf_ = NULL; 464 user_read_buf_ = NULL;
466 user_read_buf_len_ = 0; 465 user_read_buf_len_ = 0;
467 user_write_buf_ = NULL; 466 user_write_buf_ = NULL;
468 user_write_buf_len_ = 0; 467 user_write_buf_len_ = 0;
469 468
470 pending_read_error_ = kNoPendingReadResult; 469 pending_read_error_ = kNoPendingReadResult;
471 transport_write_error_ = OK; 470 transport_read_error_ = 0;
471 transport_write_error_ = 0;
472 472
473 server_cert_verify_result_.Reset(); 473 server_cert_verify_result_.Reset();
474 completed_handshake_ = false; 474 completed_handshake_ = false;
475 475
476 cert_authorities_.clear(); 476 cert_authorities_.clear();
477 cert_key_types_.clear(); 477 cert_key_types_.clear();
478 client_auth_cert_needed_ = false; 478 client_auth_cert_needed_ = false;
479 } 479 }
480 480
481 bool SSLClientSocketOpenSSL::IsConnected() const { 481 bool SSLClientSocketOpenSSL::IsConnected() const {
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
594 << SSLConnectionStatusToVersion(ssl_info->connection_status); 594 << SSLConnectionStatusToVersion(ssl_info->connection_status);
595 return true; 595 return true;
596 } 596 }
597 597
598 int SSLClientSocketOpenSSL::Read(IOBuffer* buf, 598 int SSLClientSocketOpenSSL::Read(IOBuffer* buf,
599 int buf_len, 599 int buf_len,
600 const CompletionCallback& callback) { 600 const CompletionCallback& callback) {
601 user_read_buf_ = buf; 601 user_read_buf_ = buf;
602 user_read_buf_len_ = buf_len; 602 user_read_buf_len_ = buf_len;
603 603
604 int rv = DoReadLoop(OK); 604 int rv = DoReadLoop();
605 605
606 if (rv == ERR_IO_PENDING) { 606 if (rv == ERR_IO_PENDING) {
607 user_read_callback_ = callback; 607 user_read_callback_ = callback;
608 } else { 608 } else {
609 if (rv > 0) 609 if (rv > 0)
610 was_ever_used_ = true; 610 was_ever_used_ = true;
611 user_read_buf_ = NULL; 611 user_read_buf_ = NULL;
612 user_read_buf_len_ = 0; 612 user_read_buf_len_ = 0;
613 } 613 }
614 614
615 return rv; 615 return rv;
616 } 616 }
617 617
618 int SSLClientSocketOpenSSL::Write(IOBuffer* buf, 618 int SSLClientSocketOpenSSL::Write(IOBuffer* buf,
619 int buf_len, 619 int buf_len,
620 const CompletionCallback& callback) { 620 const CompletionCallback& callback) {
621 user_write_buf_ = buf; 621 user_write_buf_ = buf;
622 user_write_buf_len_ = buf_len; 622 user_write_buf_len_ = buf_len;
623 623
624 int rv = DoWriteLoop(OK); 624 int rv = DoWriteLoop();
625 625
626 if (rv == ERR_IO_PENDING) { 626 if (rv == ERR_IO_PENDING) {
627 user_write_callback_ = callback; 627 user_write_callback_ = callback;
628 } else { 628 } else {
629 if (rv > 0) 629 if (rv > 0)
630 was_ever_used_ = true; 630 was_ever_used_ = true;
631 user_write_buf_ = NULL; 631 user_write_buf_ = NULL;
632 user_write_buf_len_ = 0; 632 user_write_buf_len_ = 0;
633 } 633 }
634 634
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after
778 bool SSLClientSocketOpenSSL::DoTransportIO() { 778 bool SSLClientSocketOpenSSL::DoTransportIO() {
779 bool network_moved = false; 779 bool network_moved = false;
780 int rv; 780 int rv;
781 // Read and write as much data as possible. The loop is necessary because 781 // Read and write as much data as possible. The loop is necessary because
782 // Write() may return synchronously. 782 // Write() may return synchronously.
783 do { 783 do {
784 rv = BufferSend(); 784 rv = BufferSend();
785 if (rv != ERR_IO_PENDING && rv != 0) 785 if (rv != ERR_IO_PENDING && rv != 0)
786 network_moved = true; 786 network_moved = true;
787 } while (rv > 0); 787 } while (rv > 0);
788 if (!transport_recv_eof_ && BufferRecv() != ERR_IO_PENDING) 788 if (transport_read_error_ == 0 && BufferRecv() != ERR_IO_PENDING)
789 network_moved = true; 789 network_moved = true;
790 return network_moved; 790 return network_moved;
791 } 791 }
792 792
793 int SSLClientSocketOpenSSL::DoHandshake() { 793 int SSLClientSocketOpenSSL::DoHandshake() {
794 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); 794 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
795 int net_error = OK; 795 int net_error = OK;
796 int rv = SSL_do_handshake(ssl_); 796 int rv = SSL_do_handshake(ssl_);
797 797
798 if (client_auth_cert_needed_) { 798 if (client_auth_cert_needed_) {
(...skipping 25 matching lines...) Expand all
824 base::Unretained(server_cert_.get()))); 824 base::Unretained(server_cert_.get())));
825 GotoState(STATE_VERIFY_CERT); 825 GotoState(STATE_VERIFY_CERT);
826 } else { 826 } else {
827 int ssl_error = SSL_get_error(ssl_, rv); 827 int ssl_error = SSL_get_error(ssl_, rv);
828 828
829 if (ssl_error == SSL_ERROR_WANT_CHANNEL_ID_LOOKUP) { 829 if (ssl_error == SSL_ERROR_WANT_CHANNEL_ID_LOOKUP) {
830 // The server supports TLS channel id and the lookup is asynchronous. 830 // The server supports TLS channel id and the lookup is asynchronous.
831 // Retrieve the error from the call to |server_bound_cert_service_|. 831 // Retrieve the error from the call to |server_bound_cert_service_|.
832 net_error = channel_id_request_return_value_; 832 net_error = channel_id_request_return_value_;
833 } else { 833 } else {
834 net_error = MapOpenSSLError(ssl_error, err_tracer); 834 net_error = HandleOpenSSLError(ssl_error, err_tracer);
835 } 835 }
836 836
837 // If not done, stay in this state 837 // If not done, stay in this state
838 if (net_error == ERR_IO_PENDING) { 838 if (net_error == ERR_IO_PENDING) {
839 GotoState(STATE_HANDSHAKE); 839 GotoState(STATE_HANDSHAKE);
840 } else { 840 } else {
841 LOG(ERROR) << "handshake failed; returned " << rv 841 LOG(ERROR) << "handshake failed; returned " << rv
842 << ", SSL error code " << ssl_error 842 << ", SSL error code " << ssl_error
843 << ", net_error " << net_error; 843 << ", net_error " << net_error;
844 net_log_.AddEvent( 844 net_log_.AddEvent(
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
967 // In handshake phase. 967 // In handshake phase.
968 OnHandshakeIOComplete(result); 968 OnHandshakeIOComplete(result);
969 return; 969 return;
970 } 970 }
971 971
972 // Network layer received some data, check if client requested to read 972 // Network layer received some data, check if client requested to read
973 // decrypted data. 973 // decrypted data.
974 if (!user_read_buf_.get()) 974 if (!user_read_buf_.get())
975 return; 975 return;
976 976
977 int rv = DoReadLoop(result); 977 int rv = DoReadLoop();
978 if (rv != ERR_IO_PENDING) 978 if (rv != ERR_IO_PENDING)
979 DoReadCallback(rv); 979 DoReadCallback(rv);
980 } 980 }
981 981
982 int SSLClientSocketOpenSSL::DoHandshakeLoop(int last_io_result) { 982 int SSLClientSocketOpenSSL::DoHandshakeLoop(int last_io_result) {
983 int rv = last_io_result; 983 int rv = last_io_result;
984 do { 984 do {
985 // Default to STATE_NONE for next state. 985 // Default to STATE_NONE for next state.
986 // (This is a quirk carried over from the windows 986 // (This is a quirk carried over from the windows
987 // implementation. It makes reading the logs a bit harder.) 987 // implementation. It makes reading the logs a bit harder.)
(...skipping 23 matching lines...) Expand all
1011 if (network_moved && next_handshake_state_ == STATE_HANDSHAKE) { 1011 if (network_moved && next_handshake_state_ == STATE_HANDSHAKE) {
1012 // In general we exit the loop if rv is ERR_IO_PENDING. In this 1012 // In general we exit the loop if rv is ERR_IO_PENDING. In this
1013 // special case we keep looping even if rv is ERR_IO_PENDING because 1013 // special case we keep looping even if rv is ERR_IO_PENDING because
1014 // the transport IO may allow DoHandshake to make progress. 1014 // the transport IO may allow DoHandshake to make progress.
1015 rv = OK; // This causes us to stay in the loop. 1015 rv = OK; // This causes us to stay in the loop.
1016 } 1016 }
1017 } while (rv != ERR_IO_PENDING && next_handshake_state_ != STATE_NONE); 1017 } while (rv != ERR_IO_PENDING && next_handshake_state_ != STATE_NONE);
1018 return rv; 1018 return rv;
1019 } 1019 }
1020 1020
1021 int SSLClientSocketOpenSSL::DoReadLoop(int result) { 1021 int SSLClientSocketOpenSSL::DoReadLoop() {
1022 if (result < 0)
1023 return result;
1024
1025 bool network_moved; 1022 bool network_moved;
1026 int rv; 1023 int rv;
1027 do { 1024 do {
1028 rv = DoPayloadRead(); 1025 rv = DoPayloadRead();
1029 network_moved = DoTransportIO(); 1026 network_moved = DoTransportIO();
1030 } while (rv == ERR_IO_PENDING && network_moved); 1027 } while (rv == ERR_IO_PENDING && network_moved);
1031 1028
1032 return rv; 1029 return rv;
1033 } 1030 }
1034 1031
1035 int SSLClientSocketOpenSSL::DoWriteLoop(int result) { 1032 int SSLClientSocketOpenSSL::DoWriteLoop() {
1036 if (result < 0)
1037 return result;
1038
1039 bool network_moved; 1033 bool network_moved;
1040 int rv; 1034 int rv;
1041 do { 1035 do {
1042 rv = DoPayloadWrite(); 1036 rv = DoPayloadWrite();
1043 network_moved = DoTransportIO(); 1037 network_moved = DoTransportIO();
1044 } while (rv == ERR_IO_PENDING && network_moved); 1038 } while (rv == ERR_IO_PENDING && network_moved);
1045 1039
1046 return rv; 1040 return rv;
1047 } 1041 }
1048 1042
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
1085 if (total_bytes_read > 0) { 1079 if (total_bytes_read > 0) {
1086 pending_read_error_ = rv; 1080 pending_read_error_ = rv;
1087 rv = total_bytes_read; 1081 rv = total_bytes_read;
1088 next_result = &pending_read_error_; 1082 next_result = &pending_read_error_;
1089 } 1083 }
1090 1084
1091 if (client_auth_cert_needed_) { 1085 if (client_auth_cert_needed_) {
1092 *next_result = ERR_SSL_CLIENT_AUTH_CERT_NEEDED; 1086 *next_result = ERR_SSL_CLIENT_AUTH_CERT_NEEDED;
1093 } else if (*next_result < 0) { 1087 } else if (*next_result < 0) {
1094 int err = SSL_get_error(ssl_, *next_result); 1088 int err = SSL_get_error(ssl_, *next_result);
1095 *next_result = MapOpenSSLError(err, err_tracer); 1089 *next_result = HandleOpenSSLError(err, err_tracer);
1096 if (rv > 0 && *next_result == ERR_IO_PENDING) { 1090 if (rv > 0 && *next_result == ERR_IO_PENDING) {
1097 // If at least some data was read from SSL_read(), do not treat 1091 // If at least some data was read from SSL_read(), do not treat
1098 // insufficient data as an error to return in the next call to 1092 // insufficient data as an error to return in the next call to
1099 // DoPayloadRead() - instead, let the call fall through to check 1093 // DoPayloadRead() - instead, let the call fall through to check
1100 // SSL_read() again. This is because DoTransportIO() may complete 1094 // SSL_read() again. This is because DoTransportIO() may complete
1101 // in between the next call to DoPayloadRead(), and thus it is 1095 // in between the next call to DoPayloadRead(), and thus it is
1102 // important to check SSL_read() on subsequent invocations to see 1096 // important to check SSL_read() on subsequent invocations to see
1103 // if a complete record may now be read. 1097 // if a complete record may now be read.
1104 *next_result = kNoPendingReadResult; 1098 *next_result = kNoPendingReadResult;
1105 } 1099 }
1106 } 1100 }
1107 } 1101 }
1108 1102
1109 if (rv >= 0) { 1103 if (rv >= 0) {
1110 net_log_.AddByteTransferEvent(NetLog::TYPE_SSL_SOCKET_BYTES_RECEIVED, rv, 1104 net_log_.AddByteTransferEvent(NetLog::TYPE_SSL_SOCKET_BYTES_RECEIVED, rv,
1111 user_read_buf_->data()); 1105 user_read_buf_->data());
1112 } 1106 }
1113 return rv; 1107 return rv;
1114 } 1108 }
1115 1109
1116 int SSLClientSocketOpenSSL::DoPayloadWrite() { 1110 int SSLClientSocketOpenSSL::DoPayloadWrite() {
1117 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); 1111 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
1118 int rv = SSL_write(ssl_, user_write_buf_->data(), user_write_buf_len_); 1112 int rv = SSL_write(ssl_, user_write_buf_->data(), user_write_buf_len_);
1119 1113
1120 if (rv >= 0) { 1114 if (rv >= 0) {
1121 net_log_.AddByteTransferEvent(NetLog::TYPE_SSL_SOCKET_BYTES_SENT, rv, 1115 net_log_.AddByteTransferEvent(NetLog::TYPE_SSL_SOCKET_BYTES_SENT, rv,
1122 user_write_buf_->data()); 1116 user_write_buf_->data());
1123 return rv; 1117 return rv;
1124 } 1118 }
1125 1119
1126 int err = SSL_get_error(ssl_, rv); 1120 int err = SSL_get_error(ssl_, rv);
1127 return MapOpenSSLError(err, err_tracer); 1121 return HandleOpenSSLError(err, err_tracer);
1128 } 1122 }
1129 1123
1130 int SSLClientSocketOpenSSL::BufferSend(void) { 1124 int SSLClientSocketOpenSSL::BufferSend(void) {
1131 if (transport_send_busy_) 1125 if (transport_send_busy_)
1132 return ERR_IO_PENDING; 1126 return ERR_IO_PENDING;
1133 1127
1134 if (!send_buffer_.get()) { 1128 if (!send_buffer_.get()) {
1135 // Get a fresh send buffer out of the send BIO. 1129 // Get a fresh send buffer out of the send BIO.
1136 size_t max_read = BIO_ctrl_pending(transport_bio_); 1130 size_t max_read = BIO_ctrl_pending(transport_bio_);
1137 if (!max_read) 1131 if (!max_read)
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
1203 1197
1204 void SSLClientSocketOpenSSL::BufferRecvComplete(int result) { 1198 void SSLClientSocketOpenSSL::BufferRecvComplete(int result) {
1205 result = TransportReadComplete(result); 1199 result = TransportReadComplete(result);
1206 OnRecvComplete(result); 1200 OnRecvComplete(result);
1207 } 1201 }
1208 1202
1209 void SSLClientSocketOpenSSL::TransportWriteComplete(int result) { 1203 void SSLClientSocketOpenSSL::TransportWriteComplete(int result) {
1210 DCHECK(ERR_IO_PENDING != result); 1204 DCHECK(ERR_IO_PENDING != result);
1211 if (result < 0) { 1205 if (result < 0) {
1212 // Got a socket write error; close the BIO to indicate this upward. 1206 // Got a socket write error; close the BIO to indicate this upward.
1213 //
1214 // TODO(davidben): The value of |result| gets lost. Feed the error back into
1215 // the BIO so it gets (re-)detected in OnSendComplete. Perhaps with
1216 // BIO_set_callback.
1217 DVLOG(1) << "TransportWriteComplete error " << result; 1207 DVLOG(1) << "TransportWriteComplete error " << result;
1218 (void)BIO_shutdown_wr(SSL_get_wbio(ssl_)); 1208 (void)BIO_shutdown_wr(SSL_get_wbio(ssl_));
1219 1209
1220 // Match the fix for http://crbug.com/249848 in NSS by erroring future reads 1210 // Record the error. Save it to be reported in a future read or write on
1221 // from the socket after a write error. 1211 // transport_bio_'s peer.
1222 //
1223 // TODO(davidben): Avoid having read and write ends interact this way.
1224 transport_write_error_ = result; 1212 transport_write_error_ = result;
1225 (void)BIO_shutdown_wr(transport_bio_);
1226 send_buffer_ = NULL; 1213 send_buffer_ = NULL;
1227 } else { 1214 } else {
1228 DCHECK(send_buffer_.get()); 1215 DCHECK(send_buffer_.get());
1229 send_buffer_->DidConsume(result); 1216 send_buffer_->DidConsume(result);
1230 DCHECK_GE(send_buffer_->BytesRemaining(), 0); 1217 DCHECK_GE(send_buffer_->BytesRemaining(), 0);
1231 if (send_buffer_->BytesRemaining() <= 0) 1218 if (send_buffer_->BytesRemaining() <= 0)
1232 send_buffer_ = NULL; 1219 send_buffer_ = NULL;
1233 } 1220 }
1234 } 1221 }
1235 1222
1236 int SSLClientSocketOpenSSL::TransportReadComplete(int result) { 1223 int SSLClientSocketOpenSSL::TransportReadComplete(int result) {
1237 DCHECK(ERR_IO_PENDING != result); 1224 DCHECK(ERR_IO_PENDING != result);
1238 if (result <= 0) { 1225 // If an EOF, canonicalize to ERR_CONNECTION_CLOSED here so HandleOpenSSLError
1226 // does not report success.
1227 if (result == 0)
1228 result = ERR_CONNECTION_CLOSED;
1229 if (result < 0) {
1239 DVLOG(1) << "TransportReadComplete result " << result; 1230 DVLOG(1) << "TransportReadComplete result " << result;
1240 // Received 0 (end of file) or an error. Either way, bubble it up to the 1231 // Received 0 (end of file) or an error. Save it to be reported in a future
1241 // SSL layer via the BIO. TODO(joth): consider stashing the error code, to 1232 // read on transport_bio_'s peer.
1242 // relay up to the SSL socket client (i.e. via DoReadCallback). 1233 transport_read_error_ = result;
1243 if (result == 0)
1244 transport_recv_eof_ = true;
1245 (void)BIO_shutdown_wr(transport_bio_);
1246 } else if (transport_write_error_ < 0) {
1247 // Mirror transport write errors as read failures; transport_bio_ has been
1248 // shut down by TransportWriteComplete, so the BIO_write will fail, failing
1249 // the CHECK. http://crbug.com/335557.
1250 result = transport_write_error_;
1251 } else { 1234 } else {
1252 DCHECK(recv_buffer_.get()); 1235 DCHECK(recv_buffer_.get());
1253 int ret = BIO_write(transport_bio_, recv_buffer_->data(), result); 1236 int ret = BIO_write(transport_bio_, recv_buffer_->data(), result);
1254 // A write into a memory BIO should always succeed. 1237 // A write into a memory BIO should always succeed.
1255 DCHECK_EQ(result, ret); 1238 DCHECK_EQ(result, ret);
1256 } 1239 }
1257 recv_buffer_ = NULL; 1240 recv_buffer_ = NULL;
1258 transport_recv_busy_ = false; 1241 transport_recv_busy_ = false;
1259 return result; 1242 return result;
1260 } 1243 }
1261 1244
1245 int SSLClientSocketOpenSSL::HandleOpenSSLError(
1246 int ssl_error,
1247 const crypto::OpenSSLErrStackTracer& tracer) {
1248 // Normal OpenSSL error-handling requires handling |ssl_error| being
1249 // SSL_ERROR_SYSCALL by, after checking the error queue, etc., checking
1250 // |errno|, or the equivalent, for the underlying transport error. This would
Ryan Sleevi 2014/06/19 00:27:06 Having trouble parsing one bit of this // Normal
1251 // require hooking into BIO_read and BIO_write calls to OpenSSL's end of
Ryan Sleevi 2014/06/19 00:27:06 Ok, let's use "SSL*" rather than "OpenSSL" for por
1252 // |transport_bio_| to determine which of |transport_read_error_| or
1253 // |transport_write_error_| to extract.
1254 //
1255 // Instead, determine if the OpenSSL operation failed because a BIO_read or
1256 // BIO_write failed. Report the appropriate saved transport error code in that
1257 // case.
1258 if (ssl_error == SSL_ERROR_WANT_READ) {
1259 // On transport read failure, the |transport_bio_| is intentionally not
1260 // closed, so OpenSSL will continue to report SSL_ERROR_WANT_READ once
1261 // exhausting the read buffer. Report any pending errors that were
1262 // observed. Note that both |transport_read_error_| and
1263 // |transport_write_error_| are checked, since the application may have
1264 // encountered a socket error while writing that would otherwise not be
1265 // reported until the application attempted to write again - which it may
1266 // never do. This matches the fix for https://crbug.com/249848 in NSS.
1267 if (transport_read_error_ != 0)
1268 return transport_read_error_;
1269 if (transport_write_error_ != 0)
1270 return transport_write_error_;
1271 } else if (ssl_error == SSL_ERROR_SSL) {
1272 // On transport write failure, OpenSSL's end of |transport_bio_| is shutdown
1273 // for future writes. If OpenSSL then attempts again to BIO_write, it will
1274 // fail with BIO_R_BROKEN_PIPE. Map this to the saved transport write error.
1275 //
1276 // Note that, because of the write buffer, this reports a failure from
1277 // OpenSSL's previous BIO_write call. BIO_write on OpenSSL's end of
1278 // |transport_bio_| returns successfully as soon as data is committed to the
1279 // write buffer. If it then fails to be written to the network, the error is
1280 // not reported until OpenSSL's next BIO_write or BIO_read call. From there,
1281 // it bubbles up to SSLClientSocketOpenSSL's caller through this function.
1282 unsigned long error = ERR_peek_error();
1283 if (error &&
1284 ERR_GET_LIB(error) == ERR_LIB_BIO &&
1285 ERR_GET_REASON(error) == BIO_R_BROKEN_PIPE) {
1286 DCHECK_NE(0, transport_write_error_);
1287 return transport_write_error_;
1288 }
1289 }
1290
1291 // Otherwise, map the error code.
1292 return MapOpenSSLError(ssl_error, tracer);
1293 }
1294
1262 int SSLClientSocketOpenSSL::ClientCertRequestCallback(SSL* ssl, 1295 int SSLClientSocketOpenSSL::ClientCertRequestCallback(SSL* ssl,
1263 X509** x509, 1296 X509** x509,
1264 EVP_PKEY** pkey) { 1297 EVP_PKEY** pkey) {
1265 DVLOG(3) << "OpenSSL ClientCertRequestCallback called"; 1298 DVLOG(3) << "OpenSSL ClientCertRequestCallback called";
1266 DCHECK(ssl == ssl_); 1299 DCHECK(ssl == ssl_);
1267 DCHECK(*x509 == NULL); 1300 DCHECK(*x509 == NULL);
1268 DCHECK(*pkey == NULL); 1301 DCHECK(*pkey == NULL);
1269 if (!ssl_config_.send_client_cert) { 1302 if (!ssl_config_.send_client_cert) {
1270 // First pass: we know that a client certificate is needed, but we do not 1303 // First pass: we know that a client certificate is needed, but we do not
1271 // have one at hand. 1304 // have one at hand.
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after
1430 DVLOG(2) << "next protocol: '" << npn_proto_ << "' status: " << npn_status_; 1463 DVLOG(2) << "next protocol: '" << npn_proto_ << "' status: " << npn_status_;
1431 return SSL_TLSEXT_ERR_OK; 1464 return SSL_TLSEXT_ERR_OK;
1432 } 1465 }
1433 1466
1434 scoped_refptr<X509Certificate> 1467 scoped_refptr<X509Certificate>
1435 SSLClientSocketOpenSSL::GetUnverifiedServerCertificateChain() const { 1468 SSLClientSocketOpenSSL::GetUnverifiedServerCertificateChain() const {
1436 return server_cert_; 1469 return server_cert_;
1437 } 1470 }
1438 1471
1439 } // namespace net 1472 } // namespace net
OLDNEW
« no previous file with comments | « net/socket/ssl_client_socket_openssl.h ('k') | net/socket/ssl_client_socket_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698