diff options
Diffstat (limited to 'vespalib/src/vespa/vespalib/net/tls/impl/openssl_crypto_codec_impl.cpp')
-rw-r--r-- | vespalib/src/vespa/vespalib/net/tls/impl/openssl_crypto_codec_impl.cpp | 30 |
1 files changed, 21 insertions, 9 deletions
diff --git a/vespalib/src/vespa/vespalib/net/tls/impl/openssl_crypto_codec_impl.cpp b/vespalib/src/vespa/vespalib/net/tls/impl/openssl_crypto_codec_impl.cpp index 3049c02b798..5315754d53a 100644 --- a/vespalib/src/vespa/vespalib/net/tls/impl/openssl_crypto_codec_impl.cpp +++ b/vespalib/src/vespa/vespalib/net/tls/impl/openssl_crypto_codec_impl.cpp @@ -17,7 +17,7 @@ #include <openssl/err.h> #include <openssl/pem.h> -#include <vespa/log/log.h> +#include <vespa/log/bufferedlogger.h> LOG_SETUP(".vespalib.net.tls.openssl_crypto_codec_impl"); #if (OPENSSL_VERSION_NUMBER < 0x10000000L) @@ -159,15 +159,23 @@ vespalib::string ssl_error_from_stack() { return vespalib::string(buf); } -void log_ssl_error(const char* source, int ssl_error) { - LOG(error, "%s returned unexpected error: %s (%s)", - source, ssl_error_to_str(ssl_error), ssl_error_from_stack().c_str()); +void log_ssl_error(const char* source, const SocketAddress& peer_address, int ssl_error) { + // Buffer the emitted log messages on the peer's IP address. This prevents a single misbehaving + // client from flooding our logs, while at the same time ensuring that logs for other clients + // aren't lost. + LOGBT(warning, peer_address.ip_address(), + "%s (with peer '%s') returned unexpected error: %s (%s)", + source, peer_address.spec().c_str(), + ssl_error_to_str(ssl_error), ssl_error_from_stack().c_str()); } } // anon ns -OpenSslCryptoCodecImpl::OpenSslCryptoCodecImpl(std::shared_ptr<OpenSslTlsContextImpl> ctx, Mode mode) +OpenSslCryptoCodecImpl::OpenSslCryptoCodecImpl(std::shared_ptr<OpenSslTlsContextImpl> ctx, + const SocketAddress& peer_address, + Mode mode) : _ctx(std::move(ctx)), + _peer_address(peer_address), _ssl(::SSL_new(_ctx->native_context())), _mode(mode), _deferred_handshake_params(), @@ -214,6 +222,10 @@ OpenSslCryptoCodecImpl::OpenSslCryptoCodecImpl(std::shared_ptr<OpenSslTlsContext } else { ::SSL_set_accept_state(_ssl.get()); } + // Store self-reference that can be fished out of SSL object during certificate verification callbacks + if (SSL_set_app_data(_ssl.get(), this) != 1) { + throw CryptoException("SSL_set_app_data() failed"); + } } OpenSslCryptoCodecImpl::~OpenSslCryptoCodecImpl() = default; @@ -302,7 +314,7 @@ HandshakeResult OpenSslCryptoCodecImpl::do_handshake_and_consume_peer_input_byte ConnectionStatistics::get(_mode == Mode::Server).inc_tls_connections(); return handshake_consumed_bytes_and_is_complete(static_cast<size_t>(consumed)); } else { - log_ssl_error("SSL_do_handshake()", ssl_result); + log_ssl_error("SSL_do_handshake()", _peer_address, ssl_result); ConnectionStatistics::get(_mode == Mode::Server).inc_failed_tls_handshakes(); return handshake_failed(); } @@ -327,7 +339,7 @@ EncodeResult OpenSslCryptoCodecImpl::encode(const char* plaintext, size_t plaint // SSL_write encodes plaintext to ciphertext and writes to _output_bio const int consumed = ::SSL_write(_ssl.get(), plaintext, to_consume); if (consumed < 0) { - log_ssl_error("SSL_write()", ::SSL_get_error(_ssl.get(), consumed)); + log_ssl_error("SSL_write()", _peer_address, ::SSL_get_error(_ssl.get(), consumed)); ConnectionStatistics::get(_mode == Mode::Server).inc_broken_tls_connections(); return encode_failed(); // TODO explicitly detect and log TLS renegotiation error (SSL_ERROR_WANT_READ)? } else if (consumed != to_consume) { @@ -391,7 +403,7 @@ DecodeResult OpenSslCryptoCodecImpl::remap_ssl_read_failure_to_decode_result(int LOG(debug, "SSL_read() returned SSL_ERROR_ZERO_RETURN; connection has been shut down normally by the peer"); return decode_peer_has_closed(); default: - log_ssl_error("SSL_read()", ssl_error); + log_ssl_error("SSL_read()", _peer_address, ssl_error); ConnectionStatistics::get(_mode == Mode::Server).inc_broken_tls_connections(); return decode_failed(); } @@ -403,7 +415,7 @@ EncodeResult OpenSslCryptoCodecImpl::half_close(char* ciphertext, size_t ciphert const int pending_before = BIO_pending(_output_bio); int ssl_result = ::SSL_shutdown(_ssl.get()); if (ssl_result < 0) { - log_ssl_error("SSL_shutdown()", ::SSL_get_error(_ssl.get(), ssl_result)); + log_ssl_error("SSL_shutdown()", _peer_address, ::SSL_get_error(_ssl.get(), ssl_result)); return encode_failed(); } const int pending_after = BIO_pending(_output_bio); |