Index: net/socket/ssl_client_socket_impl.cc |
diff --git a/net/socket/ssl_client_socket_impl.cc b/net/socket/ssl_client_socket_impl.cc |
index 77f305914444c20fedfbec5ff2c108c0114e18f5..648d45956106f0ef05d38696a6f4a66de3170be2 100644 |
--- a/net/socket/ssl_client_socket_impl.cc |
+++ b/net/socket/ssl_client_socket_impl.cc |
@@ -236,6 +236,40 @@ bool AreLegacyECDSACiphersEnabled() { |
const base::Feature kShortRecordHeaderFeature{ |
"SSLShortRecordHeader", base::FEATURE_DISABLED_BY_DEFAULT}; |
+std::unique_ptr<base::Value> NetLogSSLAlertCallback( |
+ const void* bytes, |
+ size_t len, |
+ NetLogCaptureMode capture_mode) { |
+ std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue()); |
+ dict->SetString("hex_encoded_bytes", base::HexEncode(bytes, len)); |
+ return std::move(dict); |
+} |
+ |
+std::unique_ptr<base::Value> NetLogSSLMessageCallback( |
+ bool is_write, |
+ const void* bytes, |
+ size_t len, |
+ NetLogCaptureMode capture_mode) { |
+ std::unique_ptr<base::DictionaryValue> dict(new base::DictionaryValue()); |
+ if (len == 0) { |
+ NOTREACHED(); |
+ return std::move(dict); |
+ } |
+ |
+ // The handshake message type is the first byte. Include it so elided messages |
+ // still report their type. |
+ uint8_t type = reinterpret_cast<const uint8_t*>(bytes)[0]; |
+ dict->SetInteger("type", type); |
+ |
+ // Elide client certificate messages unless logging socket bytes. |
+ if (!is_write || type != SSL3_MT_CERTIFICATE || |
+ capture_mode.include_socket_bytes()) { |
+ dict->SetString("hex_encoded_bytes", base::HexEncode(bytes, len)); |
+ } |
+ |
+ return std::move(dict); |
+} |
+ |
} // namespace |
class SSLClientSocketImpl::SSLContext { |
@@ -299,6 +333,8 @@ class SSLClientSocketImpl::SSLContext { |
SSL_CTX_set_short_header_enabled(ssl_ctx_.get(), 1); |
} |
+ SSL_CTX_set_msg_callback(ssl_ctx_.get(), MessageCallback); |
+ |
if (!SSL_CTX_add_client_custom_ext(ssl_ctx_.get(), kTbExtNum, |
&TokenBindingAddCallback, |
&TokenBindingFreeCallback, nullptr, |
@@ -398,6 +434,17 @@ class SSLClientSocketImpl::SSLContext { |
} |
#endif |
+ static void MessageCallback(int is_write, |
+ int version, |
+ int content_type, |
+ const void* buf, |
+ size_t len, |
+ SSL* ssl, |
+ void* arg) { |
+ SSLClientSocketImpl* socket = GetInstance()->GetClientSocketFromSSL(ssl); |
+ return socket->MessageCallback(is_write, content_type, buf, len); |
+ } |
+ |
// This is the index used with SSL_get_ex_data to retrieve the owner |
// SSLClientSocketImpl object from an SSL instance. |
int ssl_socket_data_index_; |
@@ -1901,6 +1948,29 @@ void SSLClientSocketImpl::OnPrivateKeyComplete( |
RetryAllOperations(); |
} |
+void SSLClientSocketImpl::MessageCallback(int is_write, |
+ int content_type, |
+ const void* buf, |
+ size_t len) { |
+ switch (content_type) { |
+ case SSL3_RT_ALERT: |
+ net_log_.AddEvent( |
+ is_write ? NetLogEventType::SSL_ALERT_SENT |
+ : NetLogEventType::SSL_ALERT_RECEIVED, |
+ base::Bind(&NetLogSSLAlertCallback, base::Unretained(buf), len)); |
eroman
2017/02/17 22:16:51
Is Unretained() needed here, or is it just for doc
davidben
2017/04/18 20:51:17
Oh, I didn't realize they weren't needed. Removed.
|
+ break; |
+ case SSL3_RT_HANDSHAKE: |
+ net_log_.AddEvent(is_write |
+ ? NetLogEventType::SSL_HANDSHAKE_MESSAGE_SENT |
+ : NetLogEventType::SSL_HANDSHAKE_MESSAGE_RECEIVED, |
+ base::Bind(&NetLogSSLMessageCallback, !!is_write, |
+ base::Unretained(buf), len)); |
+ break; |
+ default: |
+ return; |
+ } |
+} |
+ |
int SSLClientSocketImpl::TokenBindingAdd(const uint8_t** out, |
size_t* out_len, |
int* out_alert_value) { |