Chromium Code Reviews| 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_(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 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_ = 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 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 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |