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

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: sleevi comments 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 1416 matching lines...) Expand 10 before | Expand all | Expand 10 after
1427 rv = DoPayloadWrite(); 1427 rv = DoPayloadWrite();
1428 network_moved = DoTransportIO(); 1428 network_moved = DoTransportIO();
1429 } while (rv == ERR_IO_PENDING && network_moved); 1429 } while (rv == ERR_IO_PENDING && network_moved);
1430 1430
1431 return rv; 1431 return rv;
1432 } 1432 }
1433 1433
1434 int SSLClientSocketOpenSSL::DoPayloadRead() { 1434 int SSLClientSocketOpenSSL::DoPayloadRead() {
1435 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); 1435 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
1436 1436
1437 DCHECK_LT(0, user_read_buf_len_);
1438 DCHECK(user_read_buf_.get());
1439
1437 int rv; 1440 int rv;
1438 if (pending_read_error_ != kNoPendingReadResult) { 1441 if (pending_read_error_ != kNoPendingReadResult) {
1439 rv = pending_read_error_; 1442 rv = pending_read_error_;
1440 pending_read_error_ = kNoPendingReadResult; 1443 pending_read_error_ = kNoPendingReadResult;
1441 if (rv == 0) { 1444 if (rv == 0) {
1442 net_log_.AddByteTransferEvent(NetLog::TYPE_SSL_SOCKET_BYTES_RECEIVED, 1445 net_log_.AddByteTransferEvent(NetLog::TYPE_SSL_SOCKET_BYTES_RECEIVED,
1443 rv, user_read_buf_->data()); 1446 rv, user_read_buf_->data());
1444 } else { 1447 } else {
1445 net_log_.AddEvent( 1448 net_log_.AddEvent(
1446 NetLog::TYPE_SSL_READ_ERROR, 1449 NetLog::TYPE_SSL_READ_ERROR,
1447 CreateNetLogOpenSSLErrorCallback(rv, pending_read_ssl_error_, 1450 CreateNetLogOpenSSLErrorCallback(rv, pending_read_ssl_error_,
1448 pending_read_error_info_)); 1451 pending_read_error_info_));
1449 } 1452 }
1450 pending_read_ssl_error_ = SSL_ERROR_NONE; 1453 pending_read_ssl_error_ = SSL_ERROR_NONE;
1451 pending_read_error_info_ = OpenSSLErrorInfo(); 1454 pending_read_error_info_ = OpenSSLErrorInfo();
1452 return rv; 1455 return rv;
1453 } 1456 }
1454 1457
1455 int total_bytes_read = 0; 1458 int total_bytes_read = 0;
1459 int ssl_ret;
1456 do { 1460 do {
1457 rv = SSL_read(ssl_, user_read_buf_->data() + total_bytes_read, 1461 ssl_ret = SSL_read(ssl_, user_read_buf_->data() + total_bytes_read,
1458 user_read_buf_len_ - total_bytes_read); 1462 user_read_buf_len_ - total_bytes_read);
1459 if (rv > 0) 1463 if (ssl_ret > 0)
1460 total_bytes_read += rv; 1464 total_bytes_read += ssl_ret;
1461 } while (total_bytes_read < user_read_buf_len_ && rv > 0); 1465 } while (total_bytes_read < user_read_buf_len_ && ssl_ret > 0);
1462 1466
1463 if (total_bytes_read == user_read_buf_len_) { 1467 // Although only the final SSL_read call may have failed, the failure needs to
1464 rv = total_bytes_read; 1468 // processed immediately, while the information still available in OpenSSL's
1465 } else { 1469 // error queue.
1466 // Otherwise, an error occurred (rv <= 0). The error needs to be handled 1470 if (client_auth_cert_needed_) {
1467 // immediately, while the OpenSSL errors are still available in 1471 pending_read_error_ = ERR_SSL_CLIENT_AUTH_CERT_NEEDED;
1468 // thread-local storage. However, the handled/remapped error code should 1472 } else if (ssl_ret <= 0) {
1469 // only be returned if no application data was already read; if it was, the 1473 // A zero return from SSL_read may mean any of:
1470 // error code should be deferred until the next call of DoPayloadRead. 1474 // - The underlying BIO_read returned 0.
1475 // - The peer sent a close_notify.
1476 // - Any arbitrary error. https://crbug.com/466303
1471 // 1477 //
1472 // If no data was read, |*next_result| will point to the return value of 1478 // TransportReadComplete converts the first to an ERR_CONNECTION_CLOSED
1473 // this function. If at least some data was read, |*next_result| will point 1479 // error, so it does not occur. The second and third are distinguished by
1474 // to |pending_read_error_|, to be returned in a future call to 1480 // SSL_ERROR_ZERO_RETURN.
1475 // DoPayloadRead() (e.g.: after the current data is handled). 1481 pending_read_ssl_error_ = SSL_get_error(ssl_, ssl_ret);
1476 int *next_result = &rv; 1482 if (pending_read_ssl_error_ == SSL_ERROR_ZERO_RETURN) {
1477 if (total_bytes_read > 0) { 1483 pending_read_error_ = 0;
1478 pending_read_error_ = rv; 1484 } else {
1479 rv = total_bytes_read; 1485 pending_read_error_ = MapOpenSSLErrorWithDetails(
1480 next_result = &pending_read_error_; 1486 pending_read_ssl_error_, err_tracer, &pending_read_error_info_);
1481 } 1487 }
1482 1488
1483 if (client_auth_cert_needed_) { 1489 // Many servers do not reliably send a close_notify alert when shutting down
1484 *next_result = ERR_SSL_CLIENT_AUTH_CERT_NEEDED; 1490 // a connection, and instead terminate the TCP connection. This is reported
1485 } else if (*next_result <= 0) { 1491 // as ERR_CONNECTION_CLOSED. Because of this, map the unclean shutdown to a
1486 // A zero return from SSL_read may mean any of: 1492 // graceful EOF, instead of treating it as an error as it should be.
1487 // - The underlying BIO_read returned 0. 1493 if (pending_read_error_ == ERR_CONNECTION_CLOSED)
1488 // - The peer sent a close_notify. 1494 pending_read_error_ = 0;
1489 // - Any arbitrary error. https://crbug.com/466303 1495 }
1490 //
1491 // TransportReadComplete converts the first to an ERR_CONNECTION_CLOSED
1492 // error, so it does not occur. The second and third are distinguished by
1493 // SSL_ERROR_ZERO_RETURN.
1494 pending_read_ssl_error_ = SSL_get_error(ssl_, *next_result);
1495 if (pending_read_ssl_error_ == SSL_ERROR_ZERO_RETURN) {
1496 *next_result = 0;
1497 } else {
1498 *next_result = MapOpenSSLErrorWithDetails(
1499 pending_read_ssl_error_, err_tracer, &pending_read_error_info_);
1500 }
1501 1496
1502 // Many servers do not reliably send a close_notify alert when shutting 1497 if (total_bytes_read > 0) {
1503 // down a connection, and instead terminate the TCP connection. This is 1498 // Return any bytes read to the caller. The error will be deferred to the
1504 // reported as ERR_CONNECTION_CLOSED. Because of this, map the unclean 1499 // next call of DoPayloadRead.
1505 // shutdown to a graceful EOF, instead of treating it as an error as it 1500 rv = total_bytes_read;
1506 // should be.
1507 if (*next_result == ERR_CONNECTION_CLOSED)
1508 *next_result = 0;
1509 1501
1510 if (rv > 0 && *next_result == ERR_IO_PENDING) { 1502 // Do not treat insufficient data as an error to return in the next call to
1511 // If at least some data was read from SSL_read(), do not treat 1503 // DoPayloadRead() - instead, let the call fall through to check SSL_read()
1512 // insufficient data as an error to return in the next call to 1504 // again. This is because DoTransportIO() may complete in between the next
1513 // DoPayloadRead() - instead, let the call fall through to check 1505 // call to DoPayloadRead(), and thus it is important to check SSL_read() on
1514 // SSL_read() again. This is because DoTransportIO() may complete 1506 // subsequent invocations to see if a complete record may now be read.
1515 // in between the next call to DoPayloadRead(), and thus it is 1507 if (pending_read_error_ == ERR_IO_PENDING)
1516 // important to check SSL_read() on subsequent invocations to see 1508 pending_read_error_ = kNoPendingReadResult;
1517 // if a complete record may now be read. 1509 } else {
1518 *next_result = kNoPendingReadResult; 1510 // No bytes were returned. Return the pending read error immediately.
1519 } 1511 DCHECK_NE(kNoPendingReadResult, pending_read_error_);
1520 } 1512 rv = pending_read_error_;
1513 pending_read_error_ = kNoPendingReadResult;
1521 } 1514 }
1522 1515
1523 if (rv >= 0) { 1516 if (rv >= 0) {
1524 net_log_.AddByteTransferEvent(NetLog::TYPE_SSL_SOCKET_BYTES_RECEIVED, rv, 1517 net_log_.AddByteTransferEvent(NetLog::TYPE_SSL_SOCKET_BYTES_RECEIVED, rv,
1525 user_read_buf_->data()); 1518 user_read_buf_->data());
1526 } else if (rv != ERR_IO_PENDING) { 1519 } else if (rv != ERR_IO_PENDING) {
1527 net_log_.AddEvent( 1520 net_log_.AddEvent(
1528 NetLog::TYPE_SSL_READ_ERROR, 1521 NetLog::TYPE_SSL_READ_ERROR,
1529 CreateNetLogOpenSSLErrorCallback(rv, pending_read_ssl_error_, 1522 CreateNetLogOpenSSLErrorCallback(rv, pending_read_ssl_error_,
1530 pending_read_error_info_)); 1523 pending_read_error_info_));
(...skipping 440 matching lines...) Expand 10 before | Expand all | Expand 10 after
1971 1964
1972 return result; 1965 return result;
1973 } 1966 }
1974 1967
1975 scoped_refptr<X509Certificate> 1968 scoped_refptr<X509Certificate>
1976 SSLClientSocketOpenSSL::GetUnverifiedServerCertificateChain() const { 1969 SSLClientSocketOpenSSL::GetUnverifiedServerCertificateChain() const {
1977 return server_cert_; 1970 return server_cert_;
1978 } 1971 }
1979 1972
1980 } // namespace net 1973 } // 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