OLD | NEW |
---|---|
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 Loading... | |
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_(ERR_IO_PENDING), |
345 transport_write_error_(ERR_IO_PENDING), | |
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 Loading... | |
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 Loading... | |
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_ = ERR_IO_PENDING; |
471 transport_write_error_ = ERR_IO_PENDING; | |
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 Loading... | |
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 25 matching lines...) Expand all Loading... | |
660 trying_cached_session_ = context->session_cache()->SetSSLSessionWithKey( | 660 trying_cached_session_ = context->session_cache()->SetSSLSessionWithKey( |
661 ssl_, GetSocketSessionCacheKey(*this)); | 661 ssl_, GetSocketSessionCacheKey(*this)); |
662 | 662 |
663 BIO* ssl_bio = NULL; | 663 BIO* ssl_bio = NULL; |
664 // 0 => use default buffer sizes. | 664 // 0 => use default buffer sizes. |
665 if (!BIO_new_bio_pair(&ssl_bio, 0, &transport_bio_, 0)) | 665 if (!BIO_new_bio_pair(&ssl_bio, 0, &transport_bio_, 0)) |
666 return ERR_UNEXPECTED; | 666 return ERR_UNEXPECTED; |
667 DCHECK(ssl_bio); | 667 DCHECK(ssl_bio); |
668 DCHECK(transport_bio_); | 668 DCHECK(transport_bio_); |
669 | 669 |
670 // Install a callback on OpenSSL's end to plumb transport errors through. | |
671 BIO_set_callback(ssl_bio, &SSLClientSocketOpenSSL::BIOCallbackThunk); | |
672 BIO_set_callback_arg(ssl_bio, reinterpret_cast<char*>(this)); | |
673 | |
670 SSL_set_bio(ssl_, ssl_bio, ssl_bio); | 674 SSL_set_bio(ssl_, ssl_bio, ssl_bio); |
671 | 675 |
672 // OpenSSL defaults some options to on, others to off. To avoid ambiguity, | 676 // OpenSSL defaults some options to on, others to off. To avoid ambiguity, |
673 // set everything we care about to an absolute value. | 677 // set everything we care about to an absolute value. |
674 SslSetClearMask options; | 678 SslSetClearMask options; |
675 options.ConfigureFlag(SSL_OP_NO_SSLv2, true); | 679 options.ConfigureFlag(SSL_OP_NO_SSLv2, true); |
676 bool ssl3_enabled = (ssl_config_.version_min == SSL_PROTOCOL_VERSION_SSL3); | 680 bool ssl3_enabled = (ssl_config_.version_min == SSL_PROTOCOL_VERSION_SSL3); |
677 options.ConfigureFlag(SSL_OP_NO_SSLv3, !ssl3_enabled); | 681 options.ConfigureFlag(SSL_OP_NO_SSLv3, !ssl3_enabled); |
678 bool tls1_enabled = (ssl_config_.version_min <= SSL_PROTOCOL_VERSION_TLS1 && | 682 bool tls1_enabled = (ssl_config_.version_min <= SSL_PROTOCOL_VERSION_TLS1 && |
679 ssl_config_.version_max >= SSL_PROTOCOL_VERSION_TLS1); | 683 ssl_config_.version_max >= SSL_PROTOCOL_VERSION_TLS1); |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
778 bool SSLClientSocketOpenSSL::DoTransportIO() { | 782 bool SSLClientSocketOpenSSL::DoTransportIO() { |
779 bool network_moved = false; | 783 bool network_moved = false; |
780 int rv; | 784 int rv; |
781 // Read and write as much data as possible. The loop is necessary because | 785 // Read and write as much data as possible. The loop is necessary because |
782 // Write() may return synchronously. | 786 // Write() may return synchronously. |
783 do { | 787 do { |
784 rv = BufferSend(); | 788 rv = BufferSend(); |
785 if (rv != ERR_IO_PENDING && rv != 0) | 789 if (rv != ERR_IO_PENDING && rv != 0) |
786 network_moved = true; | 790 network_moved = true; |
787 } while (rv > 0); | 791 } while (rv > 0); |
788 if (!transport_recv_eof_ && BufferRecv() != ERR_IO_PENDING) | 792 if (transport_read_error_ == ERR_IO_PENDING && |
793 BufferRecv() != ERR_IO_PENDING) { | |
789 network_moved = true; | 794 network_moved = true; |
795 } | |
790 return network_moved; | 796 return network_moved; |
791 } | 797 } |
792 | 798 |
793 int SSLClientSocketOpenSSL::DoHandshake() { | 799 int SSLClientSocketOpenSSL::DoHandshake() { |
794 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); | 800 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); |
795 int net_error = OK; | 801 int net_error = OK; |
796 int rv = SSL_do_handshake(ssl_); | 802 int rv = SSL_do_handshake(ssl_); |
797 | 803 |
798 if (client_auth_cert_needed_) { | 804 if (client_auth_cert_needed_) { |
799 net_error = ERR_SSL_CLIENT_AUTH_CERT_NEEDED; | 805 net_error = ERR_SSL_CLIENT_AUTH_CERT_NEEDED; |
(...skipping 24 matching lines...) Expand all Loading... | |
824 base::Unretained(server_cert_.get()))); | 830 base::Unretained(server_cert_.get()))); |
825 GotoState(STATE_VERIFY_CERT); | 831 GotoState(STATE_VERIFY_CERT); |
826 } else { | 832 } else { |
827 int ssl_error = SSL_get_error(ssl_, rv); | 833 int ssl_error = SSL_get_error(ssl_, rv); |
828 | 834 |
829 if (ssl_error == SSL_ERROR_WANT_CHANNEL_ID_LOOKUP) { | 835 if (ssl_error == SSL_ERROR_WANT_CHANNEL_ID_LOOKUP) { |
830 // The server supports TLS channel id and the lookup is asynchronous. | 836 // The server supports TLS channel id and the lookup is asynchronous. |
831 // Retrieve the error from the call to |server_bound_cert_service_|. | 837 // Retrieve the error from the call to |server_bound_cert_service_|. |
832 net_error = channel_id_request_return_value_; | 838 net_error = channel_id_request_return_value_; |
833 } else { | 839 } else { |
834 net_error = MapOpenSSLError(ssl_error, err_tracer); | 840 net_error = HandleOpenSSLError(ssl_error, err_tracer); |
835 } | 841 } |
836 | 842 |
837 // If not done, stay in this state | 843 // If not done, stay in this state |
838 if (net_error == ERR_IO_PENDING) { | 844 if (net_error == ERR_IO_PENDING) { |
839 GotoState(STATE_HANDSHAKE); | 845 GotoState(STATE_HANDSHAKE); |
840 } else { | 846 } else { |
841 LOG(ERROR) << "handshake failed; returned " << rv | 847 LOG(ERROR) << "handshake failed; returned " << rv |
842 << ", SSL error code " << ssl_error | 848 << ", SSL error code " << ssl_error |
843 << ", net_error " << net_error; | 849 << ", net_error " << net_error; |
844 net_log_.AddEvent( | 850 net_log_.AddEvent( |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
967 // In handshake phase. | 973 // In handshake phase. |
968 OnHandshakeIOComplete(result); | 974 OnHandshakeIOComplete(result); |
969 return; | 975 return; |
970 } | 976 } |
971 | 977 |
972 // Network layer received some data, check if client requested to read | 978 // Network layer received some data, check if client requested to read |
973 // decrypted data. | 979 // decrypted data. |
974 if (!user_read_buf_.get()) | 980 if (!user_read_buf_.get()) |
975 return; | 981 return; |
976 | 982 |
977 int rv = DoReadLoop(result); | 983 int rv = DoReadLoop(); |
978 if (rv != ERR_IO_PENDING) | 984 if (rv != ERR_IO_PENDING) |
979 DoReadCallback(rv); | 985 DoReadCallback(rv); |
980 } | 986 } |
981 | 987 |
982 int SSLClientSocketOpenSSL::DoHandshakeLoop(int last_io_result) { | 988 int SSLClientSocketOpenSSL::DoHandshakeLoop(int last_io_result) { |
983 int rv = last_io_result; | 989 int rv = last_io_result; |
984 do { | 990 do { |
985 // Default to STATE_NONE for next state. | 991 // Default to STATE_NONE for next state. |
986 // (This is a quirk carried over from the windows | 992 // (This is a quirk carried over from the windows |
987 // implementation. It makes reading the logs a bit harder.) | 993 // implementation. It makes reading the logs a bit harder.) |
(...skipping 23 matching lines...) Expand all Loading... | |
1011 if (network_moved && next_handshake_state_ == STATE_HANDSHAKE) { | 1017 if (network_moved && next_handshake_state_ == STATE_HANDSHAKE) { |
1012 // In general we exit the loop if rv is ERR_IO_PENDING. In this | 1018 // 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 | 1019 // special case we keep looping even if rv is ERR_IO_PENDING because |
1014 // the transport IO may allow DoHandshake to make progress. | 1020 // the transport IO may allow DoHandshake to make progress. |
1015 rv = OK; // This causes us to stay in the loop. | 1021 rv = OK; // This causes us to stay in the loop. |
1016 } | 1022 } |
1017 } while (rv != ERR_IO_PENDING && next_handshake_state_ != STATE_NONE); | 1023 } while (rv != ERR_IO_PENDING && next_handshake_state_ != STATE_NONE); |
1018 return rv; | 1024 return rv; |
1019 } | 1025 } |
1020 | 1026 |
1021 int SSLClientSocketOpenSSL::DoReadLoop(int result) { | 1027 int SSLClientSocketOpenSSL::DoReadLoop() { |
1022 if (result < 0) | |
1023 return result; | |
1024 | |
1025 bool network_moved; | 1028 bool network_moved; |
1026 int rv; | 1029 int rv; |
1027 do { | 1030 do { |
1028 rv = DoPayloadRead(); | 1031 rv = DoPayloadRead(); |
1029 network_moved = DoTransportIO(); | 1032 network_moved = DoTransportIO(); |
1030 } while (rv == ERR_IO_PENDING && network_moved); | 1033 } while (rv == ERR_IO_PENDING && network_moved); |
1031 | 1034 |
1032 return rv; | 1035 return rv; |
1033 } | 1036 } |
1034 | 1037 |
1035 int SSLClientSocketOpenSSL::DoWriteLoop(int result) { | 1038 int SSLClientSocketOpenSSL::DoWriteLoop() { |
1036 if (result < 0) | |
1037 return result; | |
1038 | |
1039 bool network_moved; | 1039 bool network_moved; |
1040 int rv; | 1040 int rv; |
1041 do { | 1041 do { |
1042 rv = DoPayloadWrite(); | 1042 rv = DoPayloadWrite(); |
1043 network_moved = DoTransportIO(); | 1043 network_moved = DoTransportIO(); |
1044 } while (rv == ERR_IO_PENDING && network_moved); | 1044 } while (rv == ERR_IO_PENDING && network_moved); |
1045 | 1045 |
1046 return rv; | 1046 return rv; |
1047 } | 1047 } |
1048 | 1048 |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1085 if (total_bytes_read > 0) { | 1085 if (total_bytes_read > 0) { |
1086 pending_read_error_ = rv; | 1086 pending_read_error_ = rv; |
1087 rv = total_bytes_read; | 1087 rv = total_bytes_read; |
1088 next_result = &pending_read_error_; | 1088 next_result = &pending_read_error_; |
1089 } | 1089 } |
1090 | 1090 |
1091 if (client_auth_cert_needed_) { | 1091 if (client_auth_cert_needed_) { |
1092 *next_result = ERR_SSL_CLIENT_AUTH_CERT_NEEDED; | 1092 *next_result = ERR_SSL_CLIENT_AUTH_CERT_NEEDED; |
1093 } else if (*next_result < 0) { | 1093 } else if (*next_result < 0) { |
1094 int err = SSL_get_error(ssl_, *next_result); | 1094 int err = SSL_get_error(ssl_, *next_result); |
1095 *next_result = MapOpenSSLError(err, err_tracer); | 1095 *next_result = HandleOpenSSLError(err, err_tracer); |
1096 if (rv > 0 && *next_result == ERR_IO_PENDING) { | 1096 if (rv > 0 && *next_result == ERR_IO_PENDING) { |
1097 // If at least some data was read from SSL_read(), do not treat | 1097 // 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 | 1098 // insufficient data as an error to return in the next call to |
1099 // DoPayloadRead() - instead, let the call fall through to check | 1099 // DoPayloadRead() - instead, let the call fall through to check |
1100 // SSL_read() again. This is because DoTransportIO() may complete | 1100 // SSL_read() again. This is because DoTransportIO() may complete |
1101 // in between the next call to DoPayloadRead(), and thus it is | 1101 // in between the next call to DoPayloadRead(), and thus it is |
1102 // important to check SSL_read() on subsequent invocations to see | 1102 // important to check SSL_read() on subsequent invocations to see |
1103 // if a complete record may now be read. | 1103 // if a complete record may now be read. |
1104 *next_result = kNoPendingReadResult; | 1104 *next_result = kNoPendingReadResult; |
1105 } | 1105 } |
1106 } | 1106 } |
1107 } | 1107 } |
1108 | 1108 |
1109 if (rv >= 0) { | 1109 if (rv >= 0) { |
1110 net_log_.AddByteTransferEvent(NetLog::TYPE_SSL_SOCKET_BYTES_RECEIVED, rv, | 1110 net_log_.AddByteTransferEvent(NetLog::TYPE_SSL_SOCKET_BYTES_RECEIVED, rv, |
1111 user_read_buf_->data()); | 1111 user_read_buf_->data()); |
1112 } | 1112 } |
1113 return rv; | 1113 return rv; |
1114 } | 1114 } |
1115 | 1115 |
1116 int SSLClientSocketOpenSSL::DoPayloadWrite() { | 1116 int SSLClientSocketOpenSSL::DoPayloadWrite() { |
1117 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); | 1117 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); |
1118 int rv = SSL_write(ssl_, user_write_buf_->data(), user_write_buf_len_); | 1118 int rv = SSL_write(ssl_, user_write_buf_->data(), user_write_buf_len_); |
1119 | 1119 |
1120 if (rv >= 0) { | 1120 if (rv >= 0) { |
1121 net_log_.AddByteTransferEvent(NetLog::TYPE_SSL_SOCKET_BYTES_SENT, rv, | 1121 net_log_.AddByteTransferEvent(NetLog::TYPE_SSL_SOCKET_BYTES_SENT, rv, |
1122 user_write_buf_->data()); | 1122 user_write_buf_->data()); |
1123 return rv; | 1123 return rv; |
1124 } | 1124 } |
1125 | 1125 |
1126 int err = SSL_get_error(ssl_, rv); | 1126 int err = SSL_get_error(ssl_, rv); |
1127 return MapOpenSSLError(err, err_tracer); | 1127 return HandleOpenSSLError(err, err_tracer); |
1128 } | 1128 } |
1129 | 1129 |
1130 int SSLClientSocketOpenSSL::BufferSend(void) { | 1130 int SSLClientSocketOpenSSL::BufferSend(void) { |
1131 if (transport_send_busy_) | 1131 if (transport_send_busy_) |
1132 return ERR_IO_PENDING; | 1132 return ERR_IO_PENDING; |
1133 | 1133 |
1134 if (!send_buffer_.get()) { | 1134 if (!send_buffer_.get()) { |
1135 // Get a fresh send buffer out of the send BIO. | 1135 // Get a fresh send buffer out of the send BIO. |
1136 size_t max_read = BIO_ctrl_pending(transport_bio_); | 1136 size_t max_read = BIO_ctrl_pending(transport_bio_); |
1137 if (!max_read) | 1137 if (!max_read) |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1202 } | 1202 } |
1203 | 1203 |
1204 void SSLClientSocketOpenSSL::BufferRecvComplete(int result) { | 1204 void SSLClientSocketOpenSSL::BufferRecvComplete(int result) { |
1205 result = TransportReadComplete(result); | 1205 result = TransportReadComplete(result); |
1206 OnRecvComplete(result); | 1206 OnRecvComplete(result); |
1207 } | 1207 } |
1208 | 1208 |
1209 void SSLClientSocketOpenSSL::TransportWriteComplete(int result) { | 1209 void SSLClientSocketOpenSSL::TransportWriteComplete(int result) { |
1210 DCHECK(ERR_IO_PENDING != result); | 1210 DCHECK(ERR_IO_PENDING != result); |
1211 if (result < 0) { | 1211 if (result < 0) { |
1212 // Got a socket write error; close the BIO to indicate this upward. | 1212 // Record the error. Save it to be reported in a future read or write on |
1213 // | 1213 // transport_bio_'s peer. |
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; | |
1218 (void)BIO_shutdown_wr(SSL_get_wbio(ssl_)); | |
1219 | |
1220 // Match the fix for http://crbug.com/249848 in NSS by erroring future reads | |
1221 // from the socket after a write error. | |
1222 // | |
1223 // TODO(davidben): Avoid having read and write ends interact this way. | |
1224 transport_write_error_ = result; | 1214 transport_write_error_ = result; |
1225 (void)BIO_shutdown_wr(transport_bio_); | |
1226 send_buffer_ = NULL; | 1215 send_buffer_ = NULL; |
1227 } else { | 1216 } else { |
1228 DCHECK(send_buffer_.get()); | 1217 DCHECK(send_buffer_.get()); |
1229 send_buffer_->DidConsume(result); | 1218 send_buffer_->DidConsume(result); |
1230 DCHECK_GE(send_buffer_->BytesRemaining(), 0); | 1219 DCHECK_GE(send_buffer_->BytesRemaining(), 0); |
1231 if (send_buffer_->BytesRemaining() <= 0) | 1220 if (send_buffer_->BytesRemaining() <= 0) |
1232 send_buffer_ = NULL; | 1221 send_buffer_ = NULL; |
1233 } | 1222 } |
1234 } | 1223 } |
1235 | 1224 |
1236 int SSLClientSocketOpenSSL::TransportReadComplete(int result) { | 1225 int SSLClientSocketOpenSSL::TransportReadComplete(int result) { |
1237 DCHECK(ERR_IO_PENDING != result); | 1226 DCHECK(ERR_IO_PENDING != result); |
1238 if (result <= 0) { | 1227 if (result <= 0) { |
1239 DVLOG(1) << "TransportReadComplete result " << result; | 1228 DVLOG(1) << "TransportReadComplete result " << result; |
1240 // Received 0 (end of file) or an error. Either way, bubble it up to the | 1229 // 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 | 1230 // read on transport_bio_'s peer. |
1242 // relay up to the SSL socket client (i.e. via DoReadCallback). | 1231 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 { | 1232 } else { |
1252 DCHECK(recv_buffer_.get()); | 1233 DCHECK(recv_buffer_.get()); |
1253 int ret = BIO_write(transport_bio_, recv_buffer_->data(), result); | 1234 int ret = BIO_write(transport_bio_, recv_buffer_->data(), result); |
1254 // A write into a memory BIO should always succeed. | 1235 // A write into a memory BIO should always succeed. |
1255 DCHECK_EQ(result, ret); | 1236 DCHECK_EQ(result, ret); |
1256 } | 1237 } |
1257 recv_buffer_ = NULL; | 1238 recv_buffer_ = NULL; |
1258 transport_recv_busy_ = false; | 1239 transport_recv_busy_ = false; |
1259 return result; | 1240 return result; |
1260 } | 1241 } |
1261 | 1242 |
1243 int SSLClientSocketOpenSSL::HandleOpenSSLError( | |
1244 int ssl_error, | |
1245 const crypto::OpenSSLErrStackTracer& tracer) { | |
1246 // Route transport failures around OpenSSL. Use SSL_ERROR_WANT_READ and | |
1247 // SSL_ERROR_WANT_WRITE to determine whether to use the read or write failure | |
1248 // on the transport. This is done in lieu of routing net errors though | |
1249 // OpenSSL's error system. | |
1250 if (ssl_error == SSL_ERROR_WANT_READ) { | |
1251 // If OpenSSL wanted read data, report any pending errors that were | |
1252 // observed. Note that both |transport_read_error_| and | |
1253 // |transport_write_error_| are checked, since the application may have | |
1254 // encountered a socket error while writing that would otherwise not be | |
1255 // reported until the application attempted to write again - which it may | |
1256 // never do. This matches the fix for https://crbug.com/249848 in NSS. | |
1257 if (transport_read_error_ != ERR_IO_PENDING) | |
1258 return transport_read_error_; | |
1259 if (transport_write_error_ != ERR_IO_PENDING) | |
1260 return transport_write_error_; | |
1261 } else if (ssl_error == SSL_ERROR_WANT_WRITE) { | |
1262 // Because of the write buffer, this reports a failure from the previous | |
1263 // write payload. If the current payload fails to write, the error will be | |
1264 // reported in a future write or read. | |
1265 if (transport_write_error_ != ERR_IO_PENDING) | |
1266 return transport_write_error_; | |
1267 } | |
1268 | |
1269 // Otherwise, map the error code. | |
1270 return MapOpenSSLError(ssl_error, tracer); | |
1271 } | |
1272 | |
1262 int SSLClientSocketOpenSSL::ClientCertRequestCallback(SSL* ssl, | 1273 int SSLClientSocketOpenSSL::ClientCertRequestCallback(SSL* ssl, |
1263 X509** x509, | 1274 X509** x509, |
1264 EVP_PKEY** pkey) { | 1275 EVP_PKEY** pkey) { |
1265 DVLOG(3) << "OpenSSL ClientCertRequestCallback called"; | 1276 DVLOG(3) << "OpenSSL ClientCertRequestCallback called"; |
1266 DCHECK(ssl == ssl_); | 1277 DCHECK(ssl == ssl_); |
1267 DCHECK(*x509 == NULL); | 1278 DCHECK(*x509 == NULL); |
1268 DCHECK(*pkey == NULL); | 1279 DCHECK(*pkey == NULL); |
1269 if (!ssl_config_.send_client_cert) { | 1280 if (!ssl_config_.send_client_cert) { |
1270 // First pass: we know that a client certificate is needed, but we do not | 1281 // First pass: we know that a client certificate is needed, but we do not |
1271 // have one at hand. | 1282 // have one at hand. |
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1424 ssl_config_.next_protos[0].data())); | 1435 ssl_config_.next_protos[0].data())); |
1425 *outlen = ssl_config_.next_protos[0].size(); | 1436 *outlen = ssl_config_.next_protos[0].size(); |
1426 } | 1437 } |
1427 | 1438 |
1428 npn_proto_.assign(reinterpret_cast<const char*>(*out), *outlen); | 1439 npn_proto_.assign(reinterpret_cast<const char*>(*out), *outlen); |
1429 server_protos_.assign(reinterpret_cast<const char*>(in), inlen); | 1440 server_protos_.assign(reinterpret_cast<const char*>(in), inlen); |
1430 DVLOG(2) << "next protocol: '" << npn_proto_ << "' status: " << npn_status_; | 1441 DVLOG(2) << "next protocol: '" << npn_proto_ << "' status: " << npn_status_; |
1431 return SSL_TLSEXT_ERR_OK; | 1442 return SSL_TLSEXT_ERR_OK; |
1432 } | 1443 } |
1433 | 1444 |
1445 long SSLClientSocketOpenSSL::BIOCallback(BIO *bio, | |
1446 int cmd, | |
1447 const char *argp, int argi, long argl, | |
1448 long retvalue) { | |
1449 if (cmd == BIO_CB_WRITE && transport_write_error_ != ERR_IO_PENDING) { | |
1450 // If there is a transport write failure, act as if the buffer is full. This | |
1451 // is necessary so future writes are stopped even if there is room in the | |
1452 // buffer. Although retrying will not be of any use, mark as a retry so | |
1453 // SSL_get_error will return SSL_ERROR_WANT_WRITE if there is no other error | |
1454 // in the error queue. HandleOpenSSLError will consume that and route the | |
1455 // transport error code out of OpenSSL. | |
davidben
2014/06/06 23:31:51
As an alternative, we can BIO_shutdown_wr(SSL_get_
agl
2014/06/09 17:23:34
You mean when the write error is detected in Trans
davidben
2014/06/10 19:16:30
Revised to keep the BIO_shutdown_wr and condition
| |
1456 BIO_set_retry_write(bio); | |
1457 return -1; | |
1458 } | |
1459 return retvalue; | |
1460 } | |
1461 | |
1462 // static | |
1463 long SSLClientSocketOpenSSL::BIOCallbackThunk( | |
1464 BIO *bio, | |
1465 int cmd, | |
1466 const char *argp, int argi, long argl, | |
1467 long retvalue) { | |
1468 SSLClientSocketOpenSSL* socket = reinterpret_cast<SSLClientSocketOpenSSL*>( | |
1469 BIO_get_callback_arg(bio)); | |
1470 return socket->BIOCallback(bio, cmd, argp, argi, argl, retvalue); | |
1471 } | |
1472 | |
1434 scoped_refptr<X509Certificate> | 1473 scoped_refptr<X509Certificate> |
1435 SSLClientSocketOpenSSL::GetUnverifiedServerCertificateChain() const { | 1474 SSLClientSocketOpenSSL::GetUnverifiedServerCertificateChain() const { |
1436 return server_cert_; | 1475 return server_cert_; |
1437 } | 1476 } |
1438 | 1477 |
1439 } // namespace net | 1478 } // namespace net |
OLD | NEW |