15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// OpenSSL binding for SSLClientSocket. The class layout and general principle 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// of operation is derived from SSLClientSocketNSS. 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/socket/ssl_client_socket_openssl.h" 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <openssl/err.h> 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <openssl/opensslv.h> 122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <openssl/ssl.h> 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h" 152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/callback_helpers.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/singleton.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/metrics/histogram.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/synchronization/lock.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "crypto/openssl_util.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_errors.h" 21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/cert/cert_verifier.h" 22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/cert/single_request_cert_verifier.h" 23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/cert/x509_certificate_net_log_param.h" 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/socket/ssl_error_params.h" 25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/ssl/openssl_client_key_store.h" 262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/ssl/ssl_cert_request_info.h" 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/ssl/ssl_connection_status_flags.h" 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/ssl/ssl_info.h" 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net { 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Enable this to see logging for state machine state transitions. 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if 0 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define GotoState(s) do { DVLOG(2) << (void *)this << " " << __FUNCTION__ << \ 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) " jump to state " << s; \ 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next_handshake_state_ = s; } while (0) 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define GotoState(s) next_handshake_state_ = s 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kSessionCacheTimeoutSeconds = 60 * 60; 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const size_t kSessionCacheMaxEntires = 1024; 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// This constant can be any non-negative/non-zero value (eg: it does not 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// overlap with any value of the net::Error range, including net::OK). 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kNoPendingReadResult = 1; 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// If a client doesn't have a list of protocols that it supports, but 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the server supports NPN, choosing "http/1.1" is the best answer. 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kDefaultSupportedNPNProtocol[] = "http/1.1"; 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if OPENSSL_VERSION_NUMBER < 0x1000103fL 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This method doesn't seem to have made it into the OpenSSL headers. 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)unsigned long SSL_CIPHER_get_id(const SSL_CIPHER* cipher) { return cipher->id; } 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Used for encoding the |connection_status| field of an SSLInfo object. 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int EncodeSSLConnectionStatus(int cipher_suite, 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int compression, 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int version) { 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ((cipher_suite & SSL_CONNECTION_CIPHERSUITE_MASK) << 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SSL_CONNECTION_CIPHERSUITE_SHIFT) | 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ((compression & SSL_CONNECTION_COMPRESSION_MASK) << 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SSL_CONNECTION_COMPRESSION_SHIFT) | 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ((version & SSL_CONNECTION_VERSION_MASK) << 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SSL_CONNECTION_VERSION_SHIFT); 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns the net SSL version number (see ssl_connection_status_flags.h) for 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// this SSL connection. 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int GetNetSSLVersion(SSL* ssl) { 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (SSL_version(ssl)) { 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SSL2_VERSION: 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SSL_CONNECTION_VERSION_SSL2; 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SSL3_VERSION: 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SSL_CONNECTION_VERSION_SSL3; 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case TLS1_VERSION: 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SSL_CONNECTION_VERSION_TLS1; 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case 0x0302: 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SSL_CONNECTION_VERSION_TLS1_1; 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case 0x0303: 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SSL_CONNECTION_VERSION_TLS1_2; 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SSL_CONNECTION_VERSION_UNKNOWN; 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int MapOpenSSLErrorSSL() { 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Walk down the error stack to find the SSLerr generated reason. 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned long error_code; 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) do { 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_code = ERR_get_error(); 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (error_code == 0) 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_SSL_PROTOCOL_ERROR; 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } while (ERR_GET_LIB(error_code) != ERR_LIB_SSL); 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(1) << "OpenSSL SSL error, reason: " << ERR_GET_REASON(error_code) 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << ", name: " << ERR_error_string(error_code, NULL); 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (ERR_GET_REASON(error_code)) { 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SSL_R_READ_TIMEOUT_EXPIRED: 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_TIMED_OUT; 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SSL_R_BAD_RESPONSE_ARGUMENT: 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_INVALID_ARGUMENT; 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SSL_R_UNKNOWN_CERTIFICATE_TYPE: 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SSL_R_UNKNOWN_CIPHER_TYPE: 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SSL_R_UNKNOWN_KEY_EXCHANGE_TYPE: 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SSL_R_UNKNOWN_PKEY_TYPE: 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SSL_R_UNKNOWN_REMOTE_ERROR_TYPE: 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SSL_R_UNKNOWN_SSL_VERSION: 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_NOT_IMPLEMENTED; 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SSL_R_UNSUPPORTED_SSL_VERSION: 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SSL_R_NO_CIPHER_MATCH: 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SSL_R_NO_SHARED_CIPHER: 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SSL_R_TLSV1_ALERT_INSUFFICIENT_SECURITY: 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SSL_R_TLSV1_ALERT_PROTOCOL_VERSION: 1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case SSL_R_UNSUPPORTED_PROTOCOL: 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_SSL_VERSION_OR_CIPHER_MISMATCH; 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SSL_R_SSLV3_ALERT_BAD_CERTIFICATE: 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SSL_R_SSLV3_ALERT_UNSUPPORTED_CERTIFICATE: 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SSL_R_SSLV3_ALERT_CERTIFICATE_REVOKED: 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SSL_R_SSLV3_ALERT_CERTIFICATE_EXPIRED: 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN: 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SSL_R_TLSV1_ALERT_ACCESS_DENIED: 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SSL_R_TLSV1_ALERT_UNKNOWN_CA: 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_BAD_SSL_CLIENT_AUTH_CERT; 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SSL_R_BAD_DECOMPRESSION: 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SSL_R_SSLV3_ALERT_DECOMPRESSION_FAILURE: 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_SSL_DECOMPRESSION_FAILURE_ALERT; 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SSL_R_SSLV3_ALERT_BAD_RECORD_MAC: 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_SSL_BAD_RECORD_MAC_ALERT; 1337d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) case SSL_R_TLSV1_ALERT_DECRYPT_ERROR: 1347d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return ERR_SSL_DECRYPT_ERROR_ALERT; 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SSL_R_UNSAFE_LEGACY_RENEGOTIATION_DISABLED: 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_SSL_UNSAFE_NEGOTIATION; 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SSL_R_WRONG_NUMBER_OF_KEY_BITS: 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_SSL_WEAK_SERVER_EPHEMERAL_DH_KEY; 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // SSL_R_UNKNOWN_PROTOCOL is reported if premature application data is 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // received (see http://crbug.com/42538), and also if all the protocol 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // versions supported by the server were disabled in this socket instance. 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Mapped to ERR_SSL_PROTOCOL_ERROR for compatibility with other SSL sockets 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // in the former scenario. 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SSL_R_UNKNOWN_PROTOCOL: 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SSL_R_SSL_HANDSHAKE_FAILURE: 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SSL_R_DECRYPTION_FAILED: 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SSL_R_DECRYPTION_FAILED_OR_BAD_RECORD_MAC: 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SSL_R_DH_PUBLIC_VALUE_LENGTH_IS_WRONG: 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SSL_R_DIGEST_CHECK_FAILED: 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SSL_R_DUPLICATE_COMPRESSION_ID: 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SSL_R_ECGROUP_TOO_LARGE_FOR_CIPHER: 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SSL_R_ENCRYPTED_LENGTH_TOO_LONG: 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SSL_R_ERROR_IN_RECEIVED_CIPHER_LIST: 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SSL_R_EXCESSIVE_MESSAGE_SIZE: 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SSL_R_EXTRA_DATA_IN_MESSAGE: 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SSL_R_GOT_A_FIN_BEFORE_A_CCS: 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SSL_R_ILLEGAL_PADDING: 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SSL_R_INVALID_CHALLENGE_LENGTH: 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SSL_R_INVALID_COMMAND: 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SSL_R_INVALID_PURPOSE: 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SSL_R_INVALID_STATUS_RESPONSE: 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SSL_R_INVALID_TICKET_KEYS_LENGTH: 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SSL_R_KEY_ARG_TOO_LONG: 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SSL_R_READ_WRONG_PACKET_TYPE: 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SSL_R_SSLV3_ALERT_UNEXPECTED_MESSAGE: 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(joth): SSL_R_SSLV3_ALERT_HANDSHAKE_FAILURE may be returned from the 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // server after receiving ClientHello if there's no common supported cipher. 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Ideally we'd map that specific case to ERR_SSL_VERSION_OR_CIPHER_MISMATCH 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to match the NSS implementation. See also http://goo.gl/oMtZW 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SSL_R_SSLV3_ALERT_HANDSHAKE_FAILURE: 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SSL_R_SSLV3_ALERT_NO_CERTIFICATE: 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SSL_R_SSLV3_ALERT_ILLEGAL_PARAMETER: 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SSL_R_TLSV1_ALERT_DECODE_ERROR: 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SSL_R_TLSV1_ALERT_DECRYPTION_FAILED: 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SSL_R_TLSV1_ALERT_EXPORT_RESTRICTION: 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SSL_R_TLSV1_ALERT_INTERNAL_ERROR: 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SSL_R_TLSV1_ALERT_NO_RENEGOTIATION: 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SSL_R_TLSV1_ALERT_RECORD_OVERFLOW: 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SSL_R_TLSV1_ALERT_USER_CANCELLED: 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_SSL_PROTOCOL_ERROR; 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << "Unmapped error reason: " << ERR_GET_REASON(error_code); 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_FAILED; 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Converts an OpenSSL error code into a net error code, walking the OpenSSL 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// error stack if needed. Note that |tracer| is not currently used in the 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// implementation, but is passed in anyway as this ensures the caller will clear 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// any residual codes left on the error stack. 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int MapOpenSSLError(int err, const crypto::OpenSSLErrStackTracer& tracer) { 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (err) { 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SSL_ERROR_WANT_READ: 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SSL_ERROR_WANT_WRITE: 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_IO_PENDING; 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SSL_ERROR_SYSCALL: 197eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch LOG(ERROR) << "OpenSSL SYSCALL error, earliest error code in " 198eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch "error queue: " << ERR_peek_error() << ", errno: " 199eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch << errno; 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_SSL_PROTOCOL_ERROR; 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SSL_ERROR_SSL: 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return MapOpenSSLErrorSSL(); 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(joth): Implement full mapping. 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << "Unknown OpenSSL error " << err; 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_SSL_PROTOCOL_ERROR; 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We do certificate verification after handshake, so we disable the default 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// by registering a no-op verify function. 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int NoOpVerifyCallback(X509_STORE_CTX*, void *) { 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(3) << "skipping cert verify"; 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 1; 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// OpenSSL manages a cache of SSL_SESSION, this class provides the application 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// side policy for that cache about session re-use: we retain one session per 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// unique HostPortPair, per shard. 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SSLSessionCache { 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SSLSessionCache() {} 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void OnSessionAdded(const HostPortPair& host_and_port, 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& shard, 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SSL_SESSION* session) { 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Declare the session cleaner-upper before the lock, so any call into 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // OpenSSL to free the session will happen after the lock is released. 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) crypto::ScopedOpenSSL<SSL_SESSION, SSL_SESSION_free> session_to_free; 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock lock(lock_); 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(0U, session_map_.count(session)); 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string cache_key = GetCacheKey(host_and_port, shard); 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::pair<HostPortMap::iterator, bool> res = 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) host_port_map_.insert(std::make_pair(cache_key, session)); 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!res.second) { // Already exists: replace old entry. 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) session_to_free.reset(res.first->second); 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) session_map_.erase(session_to_free.get()); 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) res.first->second = session; 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(2) << "Adding session " << session << " => " 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << cache_key << ", new entry = " << res.second; 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(host_port_map_[cache_key] == session); 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) session_map_[session] = res.first; 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(host_port_map_.size(), session_map_.size()); 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_LE(host_port_map_.size(), kSessionCacheMaxEntires); 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void OnSessionRemoved(SSL_SESSION* session) { 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Declare the session cleaner-upper before the lock, so any call into 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // OpenSSL to free the session will happen after the lock is released. 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) crypto::ScopedOpenSSL<SSL_SESSION, SSL_SESSION_free> session_to_free; 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock lock(lock_); 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SessionMap::iterator it = session_map_.find(session); 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (it == session_map_.end()) 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(2) << "Remove session " << session << " => " << it->second->first; 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(it->second->second == session); 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) host_port_map_.erase(it->second); 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) session_map_.erase(it); 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) session_to_free.reset(session); 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(host_port_map_.size(), session_map_.size()); 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Looks up the host:port in the cache, and if a session is found it is added 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to |ssl|, returning true on success. 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool SetSSLSession(SSL* ssl, const HostPortPair& host_and_port, 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& shard) { 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock lock(lock_); 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string cache_key = GetCacheKey(host_and_port, shard); 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HostPortMap::iterator it = host_port_map_.find(cache_key); 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (it == host_port_map_.end()) 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(2) << "Lookup session: " << it->second << " => " << cache_key; 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SSL_SESSION* session = it->second; 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(session); 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(session_map_[session] == it); 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Ideally we'd release |lock_| before calling into OpenSSL here, however 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // that opens a small risk |session| will go out of scope before it is used. 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Alternatively we would take a temporary local refcount on |session|, 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // except OpenSSL does not provide a public API for adding a ref (c.f. 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // SSL_SESSION_free which decrements the ref). 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SSL_set_session(ssl, session) == 1; 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Flush removes all entries from the cache. This is called when a client 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // certificate is added. 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void Flush() { 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (HostPortMap::iterator i = host_port_map_.begin(); 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i != host_port_map_.end(); i++) { 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SSL_SESSION_free(i->second); 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) host_port_map_.clear(); 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) session_map_.clear(); 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static std::string GetCacheKey(const HostPortPair& host_and_port, 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& shard) { 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return host_and_port.ToString() + "/" + shard; 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // A pair of maps to allow bi-directional lookups between host:port and an 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // associated session. 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef std::map<std::string, SSL_SESSION*> HostPortMap; 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef std::map<SSL_SESSION*, HostPortMap::iterator> SessionMap; 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HostPortMap host_port_map_; 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SessionMap session_map_; 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Protects access to both the above maps. 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Lock lock_; 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(SSLSessionCache); 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SSLContext { 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static SSLContext* GetInstance() { return Singleton<SSLContext>::get(); } 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SSL_CTX* ssl_ctx() { return ssl_ctx_.get(); } 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SSLSessionCache* session_cache() { return &session_cache_; } 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SSLClientSocketOpenSSL* GetClientSocketFromSSL(SSL* ssl) { 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(ssl); 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SSLClientSocketOpenSSL* socket = static_cast<SSLClientSocketOpenSSL*>( 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SSL_get_ex_data(ssl, ssl_socket_data_index_)); 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(socket); 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return socket; 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool SetClientSocketForSSL(SSL* ssl, SSLClientSocketOpenSSL* socket) { 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SSL_set_ex_data(ssl, ssl_socket_data_index_, socket) != 0; 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) friend struct DefaultSingletonTraits<SSLContext>; 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SSLContext() { 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) crypto::EnsureOpenSSLInit(); 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ssl_socket_data_index_ = SSL_get_ex_new_index(0, 0, 0, 0, 0); 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_NE(ssl_socket_data_index_, -1); 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ssl_ctx_.reset(SSL_CTX_new(SSLv23_client_method())); 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SSL_CTX_set_cert_verify_callback(ssl_ctx_.get(), NoOpVerifyCallback, NULL); 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SSL_CTX_set_session_cache_mode(ssl_ctx_.get(), SSL_SESS_CACHE_CLIENT); 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SSL_CTX_sess_set_new_cb(ssl_ctx_.get(), NewSessionCallbackStatic); 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SSL_CTX_sess_set_remove_cb(ssl_ctx_.get(), RemoveSessionCallbackStatic); 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SSL_CTX_set_timeout(ssl_ctx_.get(), kSessionCacheTimeoutSeconds); 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SSL_CTX_sess_set_cache_size(ssl_ctx_.get(), kSessionCacheMaxEntires); 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SSL_CTX_set_client_cert_cb(ssl_ctx_.get(), ClientCertCallback); 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OPENSSL_NPN_NEGOTIATED) 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(kristianm): Only select this if ssl_config_.next_proto is not empty. 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // It would be better if the callback were not a global setting, 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // but that is an OpenSSL issue. 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SSL_CTX_set_next_proto_select_cb(ssl_ctx_.get(), SelectNextProtoCallback, 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NULL); 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static int NewSessionCallbackStatic(SSL* ssl, SSL_SESSION* session) { 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GetInstance()->NewSessionCallback(ssl, session); 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int NewSessionCallback(SSL* ssl, SSL_SESSION* session) { 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SSLClientSocketOpenSSL* socket = GetClientSocketFromSSL(ssl); 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) session_cache_.OnSessionAdded(socket->host_and_port(), 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) socket->ssl_session_cache_shard(), 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) session); 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 1; // 1 => We took ownership of |session|. 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static void RemoveSessionCallbackStatic(SSL_CTX* ctx, SSL_SESSION* session) { 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GetInstance()->RemoveSessionCallback(ctx, session); 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void RemoveSessionCallback(SSL_CTX* ctx, SSL_SESSION* session) { 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(ctx == ssl_ctx()); 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) session_cache_.OnSessionRemoved(session); 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static int ClientCertCallback(SSL* ssl, X509** x509, EVP_PKEY** pkey) { 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SSLClientSocketOpenSSL* socket = GetInstance()->GetClientSocketFromSSL(ssl); 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(socket); 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return socket->ClientCertRequestCallback(ssl, x509, pkey); 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static int SelectNextProtoCallback(SSL* ssl, 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned char** out, unsigned char* outlen, 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const unsigned char* in, 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned int inlen, void* arg) { 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SSLClientSocketOpenSSL* socket = GetInstance()->GetClientSocketFromSSL(ssl); 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return socket->SelectNextProtoCallback(out, outlen, in, inlen); 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This is the index used with SSL_get_ex_data to retrieve the owner 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // SSLClientSocketOpenSSL object from an SSL instance. 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int ssl_socket_data_index_; 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // session_cache_ must appear before |ssl_ctx_| because the destruction of 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |ssl_ctx_| may trigger callbacks into |session_cache_|. Therefore, 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |session_cache_| must be destructed after |ssl_ctx_|. 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SSLSessionCache session_cache_; 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) crypto::ScopedOpenSSL<SSL_CTX, SSL_CTX_free> ssl_ctx_; 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Utility to construct the appropriate set & clear masks for use the OpenSSL 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// options and mode configuration functions. (SSL_set_options etc) 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct SslSetClearMask { 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SslSetClearMask() : set_mask(0), clear_mask(0) {} 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void ConfigureFlag(long flag, bool state) { 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (state ? set_mask : clear_mask) |= flag; 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Make sure we haven't got any intersection in the set & clear options. 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(0, set_mask & clear_mask) << flag << ":" << state; 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) long set_mask; 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) long clear_mask; 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocket::ClearSessionCache() { 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SSLContext* context = SSLContext::GetInstance(); 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) context->session_cache()->Flush(); 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SSLClientSocketOpenSSL::SSLClientSocketOpenSSL( 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ClientSocketHandle* transport_socket, 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const HostPortPair& host_and_port, 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const SSLConfig& ssl_config, 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const SSLClientSocketContext& context) 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : transport_send_busy_(false), 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) transport_recv_busy_(false), 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) transport_recv_eof_(false), 435a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) weak_factory_(this), 4362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) pending_read_error_(kNoPendingReadResult), 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) completed_handshake_(false), 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) client_auth_cert_needed_(false), 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cert_verifier_(context.cert_verifier), 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ssl_(NULL), 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) transport_bio_(NULL), 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) transport_(transport_socket), 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) host_and_port_(host_and_port), 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ssl_config_(ssl_config), 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ssl_session_cache_shard_(context.ssl_session_cache_shard), 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) trying_cached_session_(false), 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next_handshake_state_(STATE_NONE), 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) npn_status_(kNextProtoUnsupported), 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log_(transport_socket->socket()->NetLog()) { 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SSLClientSocketOpenSSL::~SSLClientSocketOpenSSL() { 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Disconnect(); 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SSLClientSocketOpenSSL::Init() { 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!ssl_); 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!transport_bio_); 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SSLContext* context = SSLContext::GetInstance(); 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ssl_ = SSL_new(context->ssl_ctx()); 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!ssl_ || !context->SetClientSocketForSSL(ssl_, this)) 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!SSL_set_tlsext_host_name(ssl_, host_and_port_.host().c_str())) 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) trying_cached_session_ = 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) context->session_cache()->SetSSLSession(ssl_, host_and_port_, 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ssl_session_cache_shard_); 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BIO* ssl_bio = NULL; 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 0 => use default buffer sizes. 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!BIO_new_bio_pair(&ssl_bio, 0, &transport_bio_, 0)) 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(ssl_bio); 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(transport_bio_); 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SSL_set_bio(ssl_, ssl_bio, ssl_bio); 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // OpenSSL defaults some options to on, others to off. To avoid ambiguity, 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // set everything we care about to an absolute value. 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SslSetClearMask options; 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) options.ConfigureFlag(SSL_OP_NO_SSLv2, true); 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool ssl3_enabled = (ssl_config_.version_min == SSL_PROTOCOL_VERSION_SSL3); 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) options.ConfigureFlag(SSL_OP_NO_SSLv3, !ssl3_enabled); 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool tls1_enabled = (ssl_config_.version_min <= SSL_PROTOCOL_VERSION_TLS1 && 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ssl_config_.version_max >= SSL_PROTOCOL_VERSION_TLS1); 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) options.ConfigureFlag(SSL_OP_NO_TLSv1, !tls1_enabled); 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(SSL_OP_NO_TLSv1_1) 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool tls1_1_enabled = 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (ssl_config_.version_min <= SSL_PROTOCOL_VERSION_TLS1_1 && 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ssl_config_.version_max >= SSL_PROTOCOL_VERSION_TLS1_1); 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) options.ConfigureFlag(SSL_OP_NO_TLSv1_1, !tls1_1_enabled); 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(SSL_OP_NO_TLSv1_2) 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool tls1_2_enabled = 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (ssl_config_.version_min <= SSL_PROTOCOL_VERSION_TLS1_2 && 5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ssl_config_.version_max >= SSL_PROTOCOL_VERSION_TLS1_2); 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) options.ConfigureFlag(SSL_OP_NO_TLSv1_2, !tls1_2_enabled); 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(SSL_OP_NO_COMPRESSION) 5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) options.ConfigureFlag(SSL_OP_NO_COMPRESSION, true); 5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(joth): Set this conditionally, see http://crbug.com/55410 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) options.ConfigureFlag(SSL_OP_LEGACY_SERVER_CONNECT, true); 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SSL_set_options(ssl_, options.set_mask); 5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SSL_clear_options(ssl_, options.clear_mask); 5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Same as above, this time for the SSL mode. 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SslSetClearMask mode; 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(SSL_MODE_RELEASE_BUFFERS) 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mode.ConfigureFlag(SSL_MODE_RELEASE_BUFFERS, true); 5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(SSL_MODE_SMALL_BUFFERS) 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mode.ConfigureFlag(SSL_MODE_SMALL_BUFFERS, true); 5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SSL_set_mode(ssl_, mode.set_mask); 5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SSL_clear_mode(ssl_, mode.clear_mask); 5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Removing ciphers by ID from OpenSSL is a bit involved as we must use the 5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // textual name with SSL_set_cipher_list because there is no public API to 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // directly remove a cipher by ID. 5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) STACK_OF(SSL_CIPHER)* ciphers = SSL_get_ciphers(ssl_); 5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(ciphers); 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // See SSLConfig::disabled_cipher_suites for description of the suites 535eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // disabled by default. Note that !SHA384 only removes HMAC-SHA384 cipher 536eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch // suites, not GCM cipher suites with SHA384 as the handshake hash. 537eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch std::string command("DEFAULT:!NULL:!aNULL:!IDEA:!FZA:!SRP:!SHA384:!aECDH"); 5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Walk through all the installed ciphers, seeing if any need to be 5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // appended to the cipher removal |command|. 5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < sk_SSL_CIPHER_num(ciphers); ++i) { 5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const SSL_CIPHER* cipher = sk_SSL_CIPHER_value(ciphers, i); 5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const uint16 id = SSL_CIPHER_get_id(cipher); 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Remove any ciphers with a strength of less than 80 bits. Note the NSS 5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // implementation uses "effective" bits here but OpenSSL does not provide 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // this detail. This only impacts Triple DES: reports 112 vs. 168 bits, 5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // both of which are greater than 80 anyway. 5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool disable = SSL_CIPHER_get_bits(cipher, NULL) < 80; 5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!disable) { 5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) disable = std::find(ssl_config_.disabled_cipher_suites.begin(), 5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ssl_config_.disabled_cipher_suites.end(), id) != 5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ssl_config_.disabled_cipher_suites.end(); 5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (disable) { 5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* name = SSL_CIPHER_get_name(cipher); 5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(3) << "Found cipher to remove: '" << name << "', ID: " << id 5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << " strength: " << SSL_CIPHER_get_bits(cipher, NULL); 5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) command.append(":!"); 5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) command.append(name); 5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int rv = SSL_set_cipher_list(ssl_, command.c_str()); 5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If this fails (rv = 0) it means there are no ciphers enabled on this SSL. 5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This will almost certainly result in the socket failing to complete the 5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // handshake at which point the appropriate error is bubbled up to the client. 5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG_IF(WARNING, rv != 1) << "SSL_set_cipher_list('" << command << "') " 5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "returned " << rv; 5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketOpenSSL::ClientCertRequestCallback(SSL* ssl, 5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) X509** x509, 5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EVP_PKEY** pkey) { 5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(3) << "OpenSSL ClientCertRequestCallback called"; 5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(ssl == ssl_); 5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(*x509 == NULL); 5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(*pkey == NULL); 5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!ssl_config_.send_client_cert) { 5792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // First pass: we know that a client certificate is needed, but we do not 5802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // have one at hand. 5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) client_auth_cert_needed_ = true; 5822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) STACK_OF(X509_NAME) *authorities = SSL_get_client_CA_list(ssl); 5832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (int i = 0; i < sk_X509_NAME_num(authorities); i++) { 5842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) X509_NAME *ca_name = (X509_NAME *)sk_X509_NAME_value(authorities, i); 5852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) unsigned char* str = NULL; 5862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int length = i2d_X509_NAME(ca_name, &str); 5872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) cert_authorities_.push_back(std::string( 5882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) reinterpret_cast<const char*>(str), 5892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static_cast<size_t>(length))); 5902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) OPENSSL_free(str); 5912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 5922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return -1; // Suspends handshake. 5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Second pass: a client certificate should have been selected. 5977d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (ssl_config_.client_cert.get()) { 5982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // A note about ownership: FetchClientCertPrivateKey() increments 5992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // the reference count of the EVP_PKEY. Ownership of this reference 6002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // is passed directly to OpenSSL, which will release the reference 6012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // using EVP_PKEY_free() when the SSL object is destroyed. 6022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) OpenSSLClientKeyStore::ScopedEVP_PKEY privkey; 6032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (OpenSSLClientKeyStore::GetInstance()->FetchClientCertPrivateKey( 6042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ssl_config_.client_cert.get(), &privkey)) { 6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(joth): (copied from NSS) We should wait for server certificate 6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // verification before sending our credentials. See http://crbug.com/13934 6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *x509 = X509Certificate::DupOSCertHandle( 6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ssl_config_.client_cert->os_cert_handle()); 6092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *pkey = privkey.release(); 6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 1; 6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << "Client cert found without private key"; 6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Send no client certificate. 6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0; 6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// SSLClientSocket methods 6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SSLClientSocketOpenSSL::GetSSLInfo(SSLInfo* ssl_info) { 6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ssl_info->Reset(); 6237d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (!server_cert_.get()) 6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ssl_info->cert = server_cert_verify_result_.verified_cert; 6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ssl_info->cert_status = server_cert_verify_result_.cert_status; 6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ssl_info->is_issued_by_known_root = 6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) server_cert_verify_result_.is_issued_by_known_root; 6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ssl_info->public_key_hashes = 6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) server_cert_verify_result_.public_key_hashes; 6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ssl_info->client_cert_sent = 6337d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) ssl_config_.send_client_cert && ssl_config_.client_cert.get(); 6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ssl_info->channel_id_sent = WasChannelIDSent(); 6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const SSL_CIPHER* cipher = SSL_get_current_cipher(ssl_); 6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(cipher); 6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ssl_info->security_bits = SSL_CIPHER_get_bits(cipher, NULL); 6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const COMP_METHOD* compression = SSL_get_current_compression(ssl_); 6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ssl_info->connection_status = EncodeSSLConnectionStatus( 6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SSL_CIPHER_get_id(cipher), 6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) compression ? compression->type : 0, 6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetNetSSLVersion(ssl_)); 6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool peer_supports_renego_ext = !!SSL_get_secure_renegotiation_support(ssl_); 6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!peer_supports_renego_ext) 6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ssl_info->connection_status |= SSL_CONNECTION_NO_RENEGOTIATION_EXTENSION; 6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UMA_HISTOGRAM_ENUMERATION("Net.RenegotiationExtensionSupported", 6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) implicit_cast<int>(peer_supports_renego_ext), 2); 6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ssl_config_.version_fallback) 6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ssl_info->connection_status |= SSL_CONNECTION_VERSION_FALLBACK; 6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ssl_info->handshake_type = SSL_session_reused(ssl_) ? 6562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SSLInfo::HANDSHAKE_RESUME : SSLInfo::HANDSHAKE_FULL; 6572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(3) << "Encoded connection status: cipher suite = " 6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << SSLConnectionStatusToCipherSuite(ssl_info->connection_status) 6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << " version = " 6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << SSLConnectionStatusToVersion(ssl_info->connection_status); 6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocketOpenSSL::GetSSLCertRequestInfo( 6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SSLCertRequestInfo* cert_request_info) { 6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cert_request_info->host_and_port = host_and_port_.ToString(); 6682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) cert_request_info->cert_authorities = cert_authorities_; 6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketOpenSSL::ExportKeyingMaterial( 6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const base::StringPiece& label, 6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool has_context, const base::StringPiece& context, 6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned char* out, unsigned int outlen) { 6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); 6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int rv = SSL_export_keying_material( 6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ssl_, out, outlen, const_cast<char*>(label.data()), 6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) label.size(), 6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<unsigned char*>(const_cast<char*>(context.data())), 6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) context.length(), 6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) context.length() > 0); 6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (rv != 1) { 6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int ssl_error = SSL_get_error(ssl_, rv); 6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Failed to export keying material;" 6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << " returned " << rv 6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << ", SSL error code " << ssl_error; 6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return MapOpenSSLError(ssl_error, err_tracer); 6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return OK; 6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketOpenSSL::GetTLSUniqueChannelBinding(std::string* out) { 6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_NOT_IMPLEMENTED; 6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SSLClientSocket::NextProtoStatus SSLClientSocketOpenSSL::GetNextProto( 6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string* proto, std::string* server_protos) { 7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *proto = npn_proto_; 7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *server_protos = server_protos_; 7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return npn_status_; 7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ServerBoundCertService* 7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SSLClientSocketOpenSSL::GetServerBoundCertService() const { 7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocketOpenSSL::DoReadCallback(int rv) { 7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Since Run may result in Read being called, clear |user_read_callback_| 7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // up front. 7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) user_read_buf_ = NULL; 7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) user_read_buf_len_ = 0; 7152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::ResetAndReturn(&user_read_callback_).Run(rv); 7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocketOpenSSL::DoWriteCallback(int rv) { 7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Since Run may result in Write being called, clear |user_write_callback_| 7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // up front. 7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) user_write_buf_ = NULL; 7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) user_write_buf_len_ = 0; 7232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::ResetAndReturn(&user_write_callback_).Run(rv); 7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// StreamSocket implementation. 7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketOpenSSL::Connect(const CompletionCallback& callback) { 7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log_.BeginEvent(NetLog::TYPE_SSL_CONNECT); 7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Set up new ssl object. 7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!Init()) { 7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int result = ERR_UNEXPECTED; 7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_CONNECT, result); 7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Set SSL to client mode. Handshake happens in the loop below. 7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SSL_set_connect_state(ssl_); 7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GotoState(STATE_HANDSHAKE); 7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int rv = DoHandshakeLoop(net::OK); 7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (rv == ERR_IO_PENDING) { 7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) user_connect_callback_ = callback; 7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_CONNECT, rv); 7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return rv > OK ? OK : rv; 7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocketOpenSSL::Disconnect() { 7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ssl_) { 7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Calling SSL_shutdown prevents the session from being marked as 7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // unresumable. 7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SSL_shutdown(ssl_); 7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SSL_free(ssl_); 7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ssl_ = NULL; 7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (transport_bio_) { 7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BIO_free_all(transport_bio_); 7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) transport_bio_ = NULL; 7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Shut down anything that may call us back. 7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) verifier_.reset(); 7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) transport_->socket()->Disconnect(); 7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Null all callbacks, delete all buffers. 7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) transport_send_busy_ = false; 7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) send_buffer_ = NULL; 7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) transport_recv_busy_ = false; 7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) transport_recv_eof_ = false; 7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) recv_buffer_ = NULL; 7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) user_connect_callback_.Reset(); 7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) user_read_callback_.Reset(); 7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) user_write_callback_.Reset(); 7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) user_read_buf_ = NULL; 7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) user_read_buf_len_ = 0; 7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) user_write_buf_ = NULL; 7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) user_write_buf_len_ = 0; 7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) server_cert_verify_result_.Reset(); 7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) completed_handshake_ = false; 7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) cert_authorities_.clear(); 7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) client_auth_cert_needed_ = false; 7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketOpenSSL::DoHandshakeLoop(int last_io_result) { 7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int rv = last_io_result; 7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) do { 7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Default to STATE_NONE for next state. 7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // (This is a quirk carried over from the windows 7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // implementation. It makes reading the logs a bit harder.) 7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // State handlers can and often do call GotoState just 7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to stay in the current state. 7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) State state = next_handshake_state_; 7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GotoState(STATE_NONE); 8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (state) { 8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case STATE_HANDSHAKE: 8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rv = DoHandshake(); 8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case STATE_VERIFY_CERT: 8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(rv == OK); 8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rv = DoVerifyCert(rv); 8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case STATE_VERIFY_CERT_COMPLETE: 8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rv = DoVerifyCertComplete(rv); 8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case STATE_NONE: 8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rv = ERR_UNEXPECTED; 8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED() << "unexpected state" << state; 8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool network_moved = DoTransportIO(); 8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (network_moved && next_handshake_state_ == STATE_HANDSHAKE) { 8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // In general we exit the loop if rv is ERR_IO_PENDING. In this 8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // special case we keep looping even if rv is ERR_IO_PENDING because 8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the transport IO may allow DoHandshake to make progress. 8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rv = OK; // This causes us to stay in the loop. 8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } while (rv != ERR_IO_PENDING && next_handshake_state_ != STATE_NONE); 8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return rv; 8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketOpenSSL::DoHandshake() { 8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); 8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int net_error = net::OK; 8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int rv = SSL_do_handshake(ssl_); 8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (client_auth_cert_needed_) { 8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_error = ERR_SSL_CLIENT_AUTH_CERT_NEEDED; 8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the handshake already succeeded (because the server requests but 8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // doesn't require a client cert), we need to invalidate the SSL session 8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // so that we won't try to resume the non-client-authenticated session in 8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the next handshake. This will cause the server to ask for a client 8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // cert again. 8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (rv == 1) { 8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Remove from session cache but don't clear this connection. 8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SSL_SESSION* session = SSL_get_session(ssl_); 8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (session) { 8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int rv = SSL_CTX_remove_session(SSL_get_SSL_CTX(ssl_), session); 8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG_IF(WARNING, !rv) << "Couldn't invalidate SSL session: " << session; 8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (rv == 1) { 8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (trying_cached_session_ && logging::DEBUG_MODE) { 8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(2) << "Result of session reuse for " << host_and_port_.ToString() 8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << " is: " << (SSL_session_reused(ssl_) ? "Success" : "Fail"); 8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // SSL handshake is completed. Let's verify the certificate. 8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const bool got_cert = !!UpdateServerCert(); 8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(got_cert); 8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log_.AddEvent( 8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NetLog::TYPE_SSL_CERTIFICATES_RECEIVED, 8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&NetLogX509CertificateCallback, 8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Unretained(server_cert_.get()))); 8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GotoState(STATE_VERIFY_CERT); 8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int ssl_error = SSL_get_error(ssl_, rv); 8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_error = MapOpenSSLError(ssl_error, err_tracer); 8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If not done, stay in this state 8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (net_error == ERR_IO_PENDING) { 8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GotoState(STATE_HANDSHAKE); 8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "handshake failed; returned " << rv 8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << ", SSL error code " << ssl_error 8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << ", net_error " << net_error; 8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log_.AddEvent( 8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NetLog::TYPE_SSL_HANDSHAKE_ERROR, 8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CreateNetLogSSLErrorCallback(net_error, ssl_error)); 8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return net_error; 8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// SelectNextProtoCallback is called by OpenSSL during the handshake. If the 8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// server supports NPN, selects a protocol from the list that the server 8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// provides. According to third_party/openssl/openssl/ssl/ssl_lib.c, the 8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// callback can assume that |in| is syntactically valid. 8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketOpenSSL::SelectNextProtoCallback(unsigned char** out, 8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned char* outlen, 8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const unsigned char* in, 8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned int inlen) { 8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OPENSSL_NPN_NEGOTIATED) 8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ssl_config_.next_protos.empty()) { 8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *out = reinterpret_cast<uint8*>( 8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const_cast<char*>(kDefaultSupportedNPNProtocol)); 8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *outlen = arraysize(kDefaultSupportedNPNProtocol) - 1; 8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) npn_status_ = kNextProtoUnsupported; 8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SSL_TLSEXT_ERR_OK; 8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Assume there's no overlap between our protocols and the server's list. 8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) npn_status_ = kNextProtoNoOverlap; 9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // For each protocol in server preference order, see if we support it. 9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (unsigned int i = 0; i < inlen; i += in[i] + 1) { 9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (std::vector<std::string>::const_iterator 9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) j = ssl_config_.next_protos.begin(); 9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) j != ssl_config_.next_protos.end(); ++j) { 9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (in[i] == j->size() && 9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) memcmp(&in[i + 1], j->data(), in[i]) == 0) { 9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We found a match. 9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *out = const_cast<unsigned char*>(in) + i + 1; 9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *outlen = in[i]; 9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) npn_status_ = kNextProtoNegotiated; 9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (npn_status_ == kNextProtoNegotiated) 9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we didn't find a protocol, we select the first one from our list. 9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (npn_status_ == kNextProtoNoOverlap) { 9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *out = reinterpret_cast<uint8*>(const_cast<char*>( 9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ssl_config_.next_protos[0].data())); 9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *outlen = ssl_config_.next_protos[0].size(); 9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) npn_proto_.assign(reinterpret_cast<const char*>(*out), *outlen); 9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) server_protos_.assign(reinterpret_cast<const char*>(in), inlen); 9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(2) << "next protocol: '" << npn_proto_ << "' status: " << npn_status_; 9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SSL_TLSEXT_ERR_OK; 9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketOpenSSL::DoVerifyCert(int result) { 9347d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) DCHECK(server_cert_.get()); 9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GotoState(STATE_VERIFY_CERT_COMPLETE); 9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CertStatus cert_status; 9387d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (ssl_config_.IsAllowedBadCert(server_cert_.get(), &cert_status)) { 9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(1) << "Received an expected bad cert with status: " << cert_status; 9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) server_cert_verify_result_.Reset(); 9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) server_cert_verify_result_.cert_status = cert_status; 9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) server_cert_verify_result_.verified_cert = server_cert_; 9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return OK; 9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int flags = 0; 9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ssl_config_.rev_checking_enabled) 9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) flags |= CertVerifier::VERIFY_REV_CHECKING_ENABLED; 9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ssl_config_.verify_ev_cert) 9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) flags |= CertVerifier::VERIFY_EV_CERT; 9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ssl_config_.cert_io_enabled) 9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) flags |= CertVerifier::VERIFY_CERT_IO_ENABLED; 953558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch if (ssl_config_.rev_checking_required_local_anchors) 954558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch flags |= CertVerifier::VERIFY_REV_CHECKING_REQUIRED_LOCAL_ANCHORS; 9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) verifier_.reset(new SingleRequestCertVerifier(cert_verifier_)); 9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return verifier_->Verify( 9577d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) server_cert_.get(), 9587d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) host_and_port_.host(), 9597d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) flags, 9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NULL /* no CRL set */, 9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &server_cert_verify_result_, 9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&SSLClientSocketOpenSSL::OnHandshakeIOComplete, 9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Unretained(this)), 9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log_); 9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketOpenSSL::DoVerifyCertComplete(int result) { 9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) verifier_.reset(); 9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (result == OK) { 9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(joth): Work out if we need to remember the intermediate CA certs 9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // when the server sends them to us, and do so here. 9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(1) << "DoVerifyCertComplete error " << ErrorToString(result) 9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << " (" << result << ")"; 9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) completed_handshake_ = true; 9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Exit DoHandshakeLoop and return the result to the caller to Connect. 9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(STATE_NONE, next_handshake_state_); 9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)X509Certificate* SSLClientSocketOpenSSL::UpdateServerCert() { 9857d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (server_cert_.get()) 9867d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return server_cert_.get(); 9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) crypto::ScopedOpenSSL<X509, X509_free> cert(SSL_get_peer_certificate(ssl_)); 9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!cert.get()) { 9905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << "SSL_get_peer_certificate returned NULL"; 9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Unlike SSL_get_peer_certificate, SSL_get_peer_cert_chain does not 9955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // increment the reference so sk_X509_free does not need to be called. 9965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) STACK_OF(X509)* chain = SSL_get_peer_cert_chain(ssl_); 9975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) X509Certificate::OSCertHandles intermediates; 9985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (chain) { 9995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < sk_X509_num(chain); ++i) 10005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) intermediates.push_back(sk_X509_value(chain, i)); 10015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) server_cert_ = X509Certificate::CreateFromHandle(cert.get(), intermediates); 10037d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) DCHECK(server_cert_.get()); 10045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10057d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return server_cert_.get(); 10065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SSLClientSocketOpenSSL::DoTransportIO() { 10095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool network_moved = false; 1010b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) int rv; 1011b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // Read and write as much data as possible. The loop is necessary because 1012b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // Write() may return synchronously. 1013b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) do { 1014b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) rv = BufferSend(); 1015b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (rv != ERR_IO_PENDING && rv != 0) 1016b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) network_moved = true; 1017b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } while (rv > 0); 1018b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!transport_recv_eof_ && BufferRecv() != ERR_IO_PENDING) 10195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) network_moved = true; 10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return network_moved; 10215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketOpenSSL::BufferSend(void) { 10245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (transport_send_busy_) 10255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_IO_PENDING; 10265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10277d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (!send_buffer_.get()) { 10285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Get a fresh send buffer out of the send BIO. 10295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t max_read = BIO_ctrl_pending(transport_bio_); 1030b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (!max_read) 1031b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return 0; // Nothing pending in the OpenSSL write BIO. 1032b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) send_buffer_ = new DrainableIOBuffer(new IOBuffer(max_read), max_read); 1033b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) int read_bytes = BIO_read(transport_bio_, send_buffer_->data(), max_read); 1034b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) DCHECK_GT(read_bytes, 0); 1035b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) CHECK_EQ(static_cast<int>(max_read), read_bytes); 10365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1038b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) int rv = transport_->socket()->Write( 10397d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) send_buffer_.get(), 10407d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) send_buffer_->BytesRemaining(), 10417d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) base::Bind(&SSLClientSocketOpenSSL::BufferSendComplete, 10427d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) base::Unretained(this))); 1043b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (rv == ERR_IO_PENDING) { 1044b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) transport_send_busy_ = true; 1045b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } else { 10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TransportWriteComplete(rv); 10475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return rv; 10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocketOpenSSL::BufferSendComplete(int result) { 10525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) transport_send_busy_ = false; 10535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TransportWriteComplete(result); 10545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OnSendComplete(result); 10555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocketOpenSSL::TransportWriteComplete(int result) { 10585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(ERR_IO_PENDING != result); 10595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (result < 0) { 10605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Got a socket write error; close the BIO to indicate this upward. 10615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(1) << "TransportWriteComplete error " << result; 10625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (void)BIO_shutdown_wr(transport_bio_); 1063a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) BIO_set_mem_eof_return(transport_bio_, 0); 10645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) send_buffer_ = NULL; 10655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 10667d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) DCHECK(send_buffer_.get()); 10675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) send_buffer_->DidConsume(result); 10685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_GE(send_buffer_->BytesRemaining(), 0); 10695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (send_buffer_->BytesRemaining() <= 0) 10705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) send_buffer_ = NULL; 10715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketOpenSSL::BufferRecv(void) { 10755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (transport_recv_busy_) 10765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_IO_PENDING; 10775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Determine how much was requested from |transport_bio_| that was not 10792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // actually available. 10802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) size_t requested = BIO_ctrl_get_read_request(transport_bio_); 10812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (requested == 0) { 10822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // This is not a perfect match of error codes, as no operation is 10832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // actually pending. However, returning 0 would be interpreted as 10842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // a possible sign of EOF, which is also an inappropriate match. 10852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return ERR_IO_PENDING; 10862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 10875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Known Issue: While only reading |requested| data is the more correct 10892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // implementation, it has the downside of resulting in frequent reads: 10902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // One read for the SSL record header (~5 bytes) and one read for the SSL 10912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // record body. Rather than issuing these reads to the underlying socket 10922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // (and constantly allocating new IOBuffers), a single Read() request to 10932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // fill |transport_bio_| is issued. As long as an SSL client socket cannot 10942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // be gracefully shutdown (via SSL close alerts) and re-used for non-SSL 10952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // traffic, this over-subscribed Read()ing will not cause issues. 10962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) size_t max_write = BIO_ctrl_get_write_guarantee(transport_bio_); 10975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!max_write) 10985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_IO_PENDING; 10995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) recv_buffer_ = new IOBuffer(max_write); 11015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int rv = transport_->socket()->Read( 11027d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) recv_buffer_.get(), 11037d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) max_write, 11045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&SSLClientSocketOpenSSL::BufferRecvComplete, 11055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Unretained(this))); 11065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (rv == ERR_IO_PENDING) { 11075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) transport_recv_busy_ = true; 11085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 11095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TransportReadComplete(rv); 11105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return rv; 11125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocketOpenSSL::BufferRecvComplete(int result) { 11155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TransportReadComplete(result); 11165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OnRecvComplete(result); 11175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocketOpenSSL::TransportReadComplete(int result) { 11205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(ERR_IO_PENDING != result); 11215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (result <= 0) { 11225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(1) << "TransportReadComplete result " << result; 11235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Received 0 (end of file) or an error. Either way, bubble it up to the 11245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // SSL layer via the BIO. TODO(joth): consider stashing the error code, to 11255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // relay up to the SSL socket client (i.e. via DoReadCallback). 11265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (result == 0) 11275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) transport_recv_eof_ = true; 11285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BIO_set_mem_eof_return(transport_bio_, 0); 11295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (void)BIO_shutdown_wr(transport_bio_); 11305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 11317d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) DCHECK(recv_buffer_.get()); 11325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int ret = BIO_write(transport_bio_, recv_buffer_->data(), result); 11335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // A write into a memory BIO should always succeed. 11345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK_EQ(result, ret); 11355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) recv_buffer_ = NULL; 11375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) transport_recv_busy_ = false; 11385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocketOpenSSL::DoConnectCallback(int rv) { 11415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!user_connect_callback_.is_null()) { 11425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CompletionCallback c = user_connect_callback_; 11435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) user_connect_callback_.Reset(); 11445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) c.Run(rv > OK ? OK : rv); 11455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocketOpenSSL::OnHandshakeIOComplete(int result) { 11495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int rv = DoHandshakeLoop(result); 11505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (rv != ERR_IO_PENDING) { 11515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log_.EndEventWithNetErrorCode(NetLog::TYPE_SSL_CONNECT, rv); 11525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DoConnectCallback(rv); 11535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocketOpenSSL::OnSendComplete(int result) { 11575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (next_handshake_state_ == STATE_HANDSHAKE) { 11585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // In handshake phase. 11595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OnHandshakeIOComplete(result); 11605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 11615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // OnSendComplete may need to call DoPayloadRead while the renegotiation 11645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // handshake is in progress. 11655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int rv_read = ERR_IO_PENDING; 11665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int rv_write = ERR_IO_PENDING; 11675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool network_moved; 11685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) do { 11697d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (user_read_buf_.get()) 11707d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) rv_read = DoPayloadRead(); 11717d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (user_write_buf_.get()) 11727d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) rv_write = DoPayloadWrite(); 11737d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) network_moved = DoTransportIO(); 11747d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) } while (rv_read == ERR_IO_PENDING && rv_write == ERR_IO_PENDING && 11757d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) (user_read_buf_.get() || user_write_buf_.get()) && network_moved); 11765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1177a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) // Performing the Read callback may cause |this| to be deleted. If this 1178a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) // happens, the Write callback should not be invoked. Guard against this by 1179a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) // holding a WeakPtr to |this| and ensuring it's still valid. 1180a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) base::WeakPtr<SSLClientSocketOpenSSL> guard(weak_factory_.GetWeakPtr()); 11817d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (user_read_buf_.get() && rv_read != ERR_IO_PENDING) 11827d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) DoReadCallback(rv_read); 1183a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 1184a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) if (!guard.get()) 1185a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) return; 1186a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 11877d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (user_write_buf_.get() && rv_write != ERR_IO_PENDING) 11887d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) DoWriteCallback(rv_write); 11895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocketOpenSSL::OnRecvComplete(int result) { 11925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (next_handshake_state_ == STATE_HANDSHAKE) { 11935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // In handshake phase. 11945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OnHandshakeIOComplete(result); 11955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 11965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Network layer received some data, check if client requested to read 11995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // decrypted data. 12007d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (!user_read_buf_.get()) 12015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 12025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int rv = DoReadLoop(result); 12045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (rv != ERR_IO_PENDING) 12055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DoReadCallback(rv); 12065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SSLClientSocketOpenSSL::IsConnected() const { 12092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If the handshake has not yet completed. 12102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!completed_handshake_) 12112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 12122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If an asynchronous operation is still pending. 12137d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (user_read_buf_.get() || user_write_buf_.get()) 12142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 12152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 12162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return transport_->socket()->IsConnected(); 12175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SSLClientSocketOpenSSL::IsConnectedAndIdle() const { 12202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If the handshake has not yet completed. 12212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!completed_handshake_) 12222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 12232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If an asynchronous operation is still pending. 12247d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (user_read_buf_.get() || user_write_buf_.get()) 12252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 12262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If there is data waiting to be sent, or data read from the network that 12272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // has not yet been consumed. 12282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (BIO_ctrl_pending(transport_bio_) > 0 || 12292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) BIO_ctrl_wpending(transport_bio_) > 0) { 12302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 12312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 12322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 12332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return transport_->socket()->IsConnectedAndIdle(); 12345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketOpenSSL::GetPeerAddress(IPEndPoint* addressList) const { 12375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return transport_->socket()->GetPeerAddress(addressList); 12385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketOpenSSL::GetLocalAddress(IPEndPoint* addressList) const { 12415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return transport_->socket()->GetLocalAddress(addressList); 12425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const BoundNetLog& SSLClientSocketOpenSSL::NetLog() const { 12455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return net_log_; 12465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocketOpenSSL::SetSubresourceSpeculation() { 12495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (transport_.get() && transport_->socket()) { 12505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) transport_->socket()->SetSubresourceSpeculation(); 12515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 12525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 12535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SSLClientSocketOpenSSL::SetOmniboxSpeculation() { 12575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (transport_.get() && transport_->socket()) { 12585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) transport_->socket()->SetOmniboxSpeculation(); 12595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 12605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 12615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SSLClientSocketOpenSSL::WasEverUsed() const { 12655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (transport_.get() && transport_->socket()) 12665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return transport_->socket()->WasEverUsed(); 12675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 12695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 12705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SSLClientSocketOpenSSL::UsingTCPFastOpen() const { 12735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (transport_.get() && transport_->socket()) 12745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return transport_->socket()->UsingTCPFastOpen(); 12755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 12775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 12785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Socket methods 12815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketOpenSSL::Read(IOBuffer* buf, 12835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int buf_len, 12845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const CompletionCallback& callback) { 12855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) user_read_buf_ = buf; 12865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) user_read_buf_len_ = buf_len; 12875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int rv = DoReadLoop(OK); 12895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (rv == ERR_IO_PENDING) { 12915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) user_read_callback_ = callback; 12925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 12935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) user_read_buf_ = NULL; 12945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) user_read_buf_len_ = 0; 12955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return rv; 12985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketOpenSSL::DoReadLoop(int result) { 13015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (result < 0) 13025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 13035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool network_moved; 13055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int rv; 13065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) do { 13075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rv = DoPayloadRead(); 13085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) network_moved = DoTransportIO(); 13095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } while (rv == ERR_IO_PENDING && network_moved); 13105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return rv; 13125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 13135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketOpenSSL::Write(IOBuffer* buf, 13155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int buf_len, 13165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const CompletionCallback& callback) { 13175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) user_write_buf_ = buf; 13185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) user_write_buf_len_ = buf_len; 13195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int rv = DoWriteLoop(OK); 13215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (rv == ERR_IO_PENDING) { 13235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) user_write_callback_ = callback; 13245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 13255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) user_write_buf_ = NULL; 13265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) user_write_buf_len_ = 0; 13275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 13285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return rv; 13305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 13315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketOpenSSL::DoWriteLoop(int result) { 13335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (result < 0) 13345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 13355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool network_moved; 13375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int rv; 13385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) do { 13395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rv = DoPayloadWrite(); 13405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) network_moved = DoTransportIO(); 13415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } while (rv == ERR_IO_PENDING && network_moved); 13425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return rv; 13445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 13455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SSLClientSocketOpenSSL::SetReceiveBufferSize(int32 size) { 13475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return transport_->socket()->SetReceiveBufferSize(size); 13485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 13495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SSLClientSocketOpenSSL::SetSendBufferSize(int32 size) { 13515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return transport_->socket()->SetSendBufferSize(size); 13525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 13535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketOpenSSL::DoPayloadRead() { 13555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); 13562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 13572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int rv; 13582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (pending_read_error_ != kNoPendingReadResult) { 13592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) rv = pending_read_error_; 13602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) pending_read_error_ = kNoPendingReadResult; 13612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (rv == 0) { 13622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) net_log_.AddByteTransferEvent(NetLog::TYPE_SSL_SOCKET_BYTES_RECEIVED, 13632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) rv, user_read_buf_->data()); 13642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 13652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return rv; 13662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 13672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 13682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int total_bytes_read = 0; 13692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) do { 13702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) rv = SSL_read(ssl_, user_read_buf_->data() + total_bytes_read, 13712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) user_read_buf_len_ - total_bytes_read); 13722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (rv > 0) 13732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) total_bytes_read += rv; 13742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } while (total_bytes_read < user_read_buf_len_ && rv > 0); 13752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 13762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (total_bytes_read == user_read_buf_len_) { 13772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) rv = total_bytes_read; 13782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 13792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Otherwise, an error occurred (rv <= 0). The error needs to be handled 13802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // immediately, while the OpenSSL errors are still available in 13812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // thread-local storage. However, the handled/remapped error code should 13822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // only be returned if no application data was already read; if it was, the 13832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // error code should be deferred until the next call of DoPayloadRead. 13842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // 13852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If no data was read, |*next_result| will point to the return value of 13862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // this function. If at least some data was read, |*next_result| will point 13872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // to |pending_read_error_|, to be returned in a future call to 13882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // DoPayloadRead() (e.g.: after the current data is handled). 13892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int *next_result = &rv; 13902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (total_bytes_read > 0) { 13912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) pending_read_error_ = rv; 13922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) rv = total_bytes_read; 13932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) next_result = &pending_read_error_; 13942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 13952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 13962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (client_auth_cert_needed_) { 13972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *next_result = ERR_SSL_CLIENT_AUTH_CERT_NEEDED; 13982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else if (*next_result < 0) { 13992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int err = SSL_get_error(ssl_, *next_result); 14002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *next_result = MapOpenSSLError(err, err_tracer); 14012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (rv > 0 && *next_result == ERR_IO_PENDING) { 14022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If at least some data was read from SSL_read(), do not treat 14032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // insufficient data as an error to return in the next call to 14042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // DoPayloadRead() - instead, let the call fall through to check 14052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // SSL_read() again. This is because DoTransportIO() may complete 14062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // in between the next call to DoPayloadRead(), and thus it is 14072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // important to check SSL_read() on subsequent invocations to see 14082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // if a complete record may now be read. 14092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *next_result = kNoPendingReadResult; 14102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 14112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 14122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 14135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (rv >= 0) { 14155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log_.AddByteTransferEvent(NetLog::TYPE_SSL_SOCKET_BYTES_RECEIVED, rv, 14165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) user_read_buf_->data()); 14175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return rv; 14195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 14205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SSLClientSocketOpenSSL::DoPayloadWrite() { 14225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); 14235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int rv = SSL_write(ssl_, user_write_buf_->data(), user_write_buf_len_); 14245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (rv >= 0) { 14265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) net_log_.AddByteTransferEvent(NetLog::TYPE_SSL_SOCKET_BYTES_SENT, rv, 14275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) user_write_buf_->data()); 14285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return rv; 14295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int err = SSL_get_error(ssl_, rv); 14325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return MapOpenSSLError(err, err_tracer); 14335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 14345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace net 1436