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

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

Issue 1000813002: Tidy up SSL_read error handling. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@openssl-alert
Patch Set: Created 5 years, 9 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
« no previous file with comments | « no previous file | no next file » | 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 <errno.h> 10 #include <errno.h>
(...skipping 1516 matching lines...) Expand 10 before | Expand all | Expand 10 after
1527 NetLog::TYPE_SSL_READ_ERROR, 1527 NetLog::TYPE_SSL_READ_ERROR,
1528 CreateNetLogOpenSSLErrorCallback(rv, pending_read_ssl_error_, 1528 CreateNetLogOpenSSLErrorCallback(rv, pending_read_ssl_error_,
1529 pending_read_error_info_)); 1529 pending_read_error_info_));
1530 } 1530 }
1531 pending_read_ssl_error_ = SSL_ERROR_NONE; 1531 pending_read_ssl_error_ = SSL_ERROR_NONE;
1532 pending_read_error_info_ = OpenSSLErrorInfo(); 1532 pending_read_error_info_ = OpenSSLErrorInfo();
1533 return rv; 1533 return rv;
1534 } 1534 }
1535 1535
1536 int total_bytes_read = 0; 1536 int total_bytes_read = 0;
1537 int ssl_ret;
1537 do { 1538 do {
1538 rv = SSL_read(ssl_, user_read_buf_->data() + total_bytes_read, 1539 ssl_ret = SSL_read(ssl_, user_read_buf_->data() + total_bytes_read,
1539 user_read_buf_len_ - total_bytes_read); 1540 user_read_buf_len_ - total_bytes_read);
1540 if (rv > 0) 1541 if (ssl_ret > 0)
1541 total_bytes_read += rv; 1542 total_bytes_read += ssl_ret;
1542 } while (total_bytes_read < user_read_buf_len_ && rv > 0); 1543 } while (total_bytes_read < user_read_buf_len_ && ssl_ret > 0);
1543 1544
1544 if (total_bytes_read == user_read_buf_len_) { 1545 // Although only the final SSL_read call may have failed, the failure needs to
1545 rv = total_bytes_read; 1546 // processed immediately, while the information still available in OpenSSL's
1546 } else { 1547 // error queue.
1547 // Otherwise, an error occurred (rv <= 0). The error needs to be handled 1548 if (client_auth_cert_needed_) {
1548 // immediately, while the OpenSSL errors are still available in 1549 pending_read_error_ = ERR_SSL_CLIENT_AUTH_CERT_NEEDED;
1549 // thread-local storage. However, the handled/remapped error code should 1550 } else if (ssl_ret <= 0) {
Ryan Sleevi 2015/03/17 00:33:14 Why is this change correct? Previously, this code
davidben 2015/03/20 20:46:04 Claim: Exactly one of ssl_ret <= 0 and total_bytes
1550 // only be returned if no application data was already read; if it was, the 1551 // A zero return from SSL_read may mean any of:
1551 // error code should be deferred until the next call of DoPayloadRead. 1552 // - The underlying BIO_read returned 0.
1553 // - The peer sent a close_notify.
1554 // - Any arbitrary error. https://crbug.com/466303
1552 // 1555 //
1553 // If no data was read, |*next_result| will point to the return value of 1556 // TransportReadComplete converts the first to an ERR_CONNECTION_CLOSED
1554 // this function. If at least some data was read, |*next_result| will point 1557 // error, so it does not occur. The second and third are distinguished by
1555 // to |pending_read_error_|, to be returned in a future call to 1558 // SSL_ERROR_ZERO_RETURN.
1556 // DoPayloadRead() (e.g.: after the current data is handled). 1559 pending_read_ssl_error_ = SSL_get_error(ssl_, ssl_ret);
1557 int *next_result = &rv; 1560 if (pending_read_ssl_error_ == SSL_ERROR_ZERO_RETURN) {
1558 if (total_bytes_read > 0) { 1561 pending_read_error_ = 0;
1559 pending_read_error_ = rv; 1562 } else {
1560 rv = total_bytes_read; 1563 pending_read_error_ = MapOpenSSLErrorWithDetails(
1561 next_result = &pending_read_error_; 1564 pending_read_ssl_error_, err_tracer, &pending_read_error_info_);
1562 } 1565 }
1563 1566
1564 if (client_auth_cert_needed_) { 1567 // Many servers do not reliably send a close_notify alert when shutting down
1565 *next_result = ERR_SSL_CLIENT_AUTH_CERT_NEEDED; 1568 // a connection, and instead terminate the TCP connection. This is reported
1566 } else if (*next_result <= 0) { 1569 // as ERR_CONNECTION_CLOSED. Because of this, map the unclean shutdown to a
1567 // A zero return from SSL_read may mean any of: 1570 // graceful EOF, instead of treating it as an error as it should be.
1568 // - The underlying BIO_read returned 0. 1571 if (pending_read_error_ == ERR_CONNECTION_CLOSED)
1569 // - The peer sent a close_notify. 1572 pending_read_error_ = 0;
1570 // - Any arbitrary error. https://crbug.com/466303 1573 }
1571 //
1572 // TransportReadComplete converts the first to an ERR_CONNECTION_CLOSED
1573 // error, so it does not occur. The second and third are distinguished by
1574 // SSL_ERROR_ZERO_RETURN.
1575 pending_read_ssl_error_ = SSL_get_error(ssl_, *next_result);
1576 if (pending_read_ssl_error_ == SSL_ERROR_ZERO_RETURN) {
1577 *next_result = 0;
1578 } else {
1579 *next_result = MapOpenSSLErrorWithDetails(
1580 pending_read_ssl_error_, err_tracer, &pending_read_error_info_);
1581 }
1582 1574
1583 // Many servers do not reliably send a close_notify alert when shutting 1575 if (total_bytes_read > 0 || user_read_buf_len_ == 0) {
Ryan Sleevi 2015/03/17 00:33:14 How is it possible for user_read_buf_len to equal
davidben 2015/03/20 20:46:04 I noticed that we don't actually have any checks t
1584 // down a connection, and instead terminate the TCP connection. This is 1576 // Return any bytes read to the caller. The error will be deferred to the
1585 // reported as ERR_CONNECTION_CLOSED. Because of this, map the unclean 1577 // next call of DoPayloadRead.
1586 // shutdown to a graceful EOF, instead of treating it as an error as it 1578 rv = total_bytes_read;
1587 // should be.
1588 if (*next_result == ERR_CONNECTION_CLOSED)
1589 *next_result = 0;
1590 1579
1591 if (rv > 0 && *next_result == ERR_IO_PENDING) { 1580 // Do not treat insufficient data as an error to return in the next call to
1592 // If at least some data was read from SSL_read(), do not treat 1581 // DoPayloadRead() - instead, let the call fall through to check SSL_read()
1593 // insufficient data as an error to return in the next call to 1582 // again. This is because DoTransportIO() may complete in between the next
1594 // DoPayloadRead() - instead, let the call fall through to check 1583 // call to DoPayloadRead(), and thus it is important to check SSL_read() on
1595 // SSL_read() again. This is because DoTransportIO() may complete 1584 // subsequent invocations to see if a complete record may now be read.
1596 // in between the next call to DoPayloadRead(), and thus it is 1585 if (pending_read_error_ == ERR_IO_PENDING)
1597 // important to check SSL_read() on subsequent invocations to see 1586 pending_read_error_ = kNoPendingReadResult;
1598 // if a complete record may now be read. 1587 } else {
1599 *next_result = kNoPendingReadResult; 1588 // No bytes were returned. Return the pending read error immediately.
1600 } 1589 DCHECK_NE(kNoPendingReadResult, pending_read_error_);
1601 } 1590 rv = pending_read_error_;
1591 pending_read_error_ = kNoPendingReadResult;
1602 } 1592 }
1603 1593
1604 if (rv >= 0) { 1594 if (rv >= 0) {
1605 net_log_.AddByteTransferEvent(NetLog::TYPE_SSL_SOCKET_BYTES_RECEIVED, rv, 1595 net_log_.AddByteTransferEvent(NetLog::TYPE_SSL_SOCKET_BYTES_RECEIVED, rv,
1606 user_read_buf_->data()); 1596 user_read_buf_->data());
1607 } else if (rv != ERR_IO_PENDING) { 1597 } else if (rv != ERR_IO_PENDING) {
1608 net_log_.AddEvent( 1598 net_log_.AddEvent(
1609 NetLog::TYPE_SSL_READ_ERROR, 1599 NetLog::TYPE_SSL_READ_ERROR,
1610 CreateNetLogOpenSSLErrorCallback(rv, pending_read_ssl_error_, 1600 CreateNetLogOpenSSLErrorCallback(rv, pending_read_ssl_error_,
1611 pending_read_error_info_)); 1601 pending_read_error_info_));
(...skipping 442 matching lines...) Expand 10 before | Expand all | Expand 10 after
2054 ct::SCT_STATUS_LOG_UNKNOWN)); 2044 ct::SCT_STATUS_LOG_UNKNOWN));
2055 } 2045 }
2056 } 2046 }
2057 2047
2058 scoped_refptr<X509Certificate> 2048 scoped_refptr<X509Certificate>
2059 SSLClientSocketOpenSSL::GetUnverifiedServerCertificateChain() const { 2049 SSLClientSocketOpenSSL::GetUnverifiedServerCertificateChain() const {
2060 return server_cert_; 2050 return server_cert_;
2061 } 2051 }
2062 2052
2063 } // namespace net 2053 } // namespace net
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698