fix(tls): User friendly logging of OpenSSL errors (#1851)

* fix(tls): User friendly logging of OpenSSL errors

* Remove duplicate definition
This commit is contained in:
Roy Jacobson 2023-09-13 11:23:18 +03:00 committed by GitHub
parent 761a1a7e78
commit ef0502238c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 63 additions and 12 deletions

View file

@ -1,6 +1,6 @@
add_library(dfly_facade dragonfly_listener.cc dragonfly_connection.cc facade.cc
memcache_parser.cc redis_parser.cc reply_builder.cc op_status.cc
reply_capture.cc resp_expr.cc cmd_arg_parser.cc)
reply_capture.cc resp_expr.cc cmd_arg_parser.cc tls_error.cc)
if (DF_USE_SSL)
set(TLS_LIB tls_lib)

View file

@ -4,6 +4,10 @@
#include "facade/dragonfly_listener.h"
#include <openssl/err.h>
#include "facade/tls_error.h"
#ifdef DFLY_USE_SSL
#include <openssl/ssl.h>
#endif
@ -58,6 +62,7 @@ using absl::GetFlag;
namespace {
#ifdef DFLY_USE_SSL
// To connect: openssl s_client -state -crlf -connect 127.0.0.1:6380
SSL_CTX* CreateSslServerCntx() {
const auto& tls_key_file = GetFlag(FLAGS_tls_key_file);
@ -69,13 +74,13 @@ SSL_CTX* CreateSslServerCntx() {
SSL_CTX* ctx = SSL_CTX_new(TLS_server_method());
unsigned mask = SSL_VERIFY_NONE;
CHECK_EQ(1, SSL_CTX_use_PrivateKey_file(ctx, tls_key_file.c_str(), SSL_FILETYPE_PEM));
DFLY_SSL_CHECK(1 == SSL_CTX_use_PrivateKey_file(ctx, tls_key_file.c_str(), SSL_FILETYPE_PEM));
const auto& tls_cert_file = GetFlag(FLAGS_tls_cert_file);
if (!tls_cert_file.empty()) {
// TO connect with redis-cli you need both tls-key-file and tls-cert-file
// loaded. Use `redis-cli --tls -p 6380 --insecure PING` to test
CHECK_EQ(1, SSL_CTX_use_certificate_chain_file(ctx, tls_cert_file.c_str()));
DFLY_SSL_CHECK(1 == SSL_CTX_use_certificate_chain_file(ctx, tls_cert_file.c_str()));
}
const auto tls_ca_cert_file = GetFlag(FLAGS_tls_ca_cert_file);
@ -83,11 +88,11 @@ SSL_CTX* CreateSslServerCntx() {
if (!tls_ca_cert_file.empty() || !tls_ca_cert_dir.empty()) {
const auto* file = tls_ca_cert_file.empty() ? nullptr : tls_ca_cert_file.data();
const auto* dir = tls_ca_cert_dir.empty() ? nullptr : tls_ca_cert_dir.data();
CHECK_EQ(1, SSL_CTX_load_verify_locations(ctx, file, dir));
DFLY_SSL_CHECK(1 == SSL_CTX_load_verify_locations(ctx, file, dir));
mask = SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
}
CHECK_EQ(1, SSL_CTX_set_cipher_list(ctx, "DEFAULT"));
DFLY_SSL_CHECK(1 == SSL_CTX_set_cipher_list(ctx, "DEFAULT"));
SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION);
@ -95,7 +100,7 @@ SSL_CTX* CreateSslServerCntx() {
SSL_CTX_set_verify(ctx, mask, NULL);
CHECK_EQ(1, SSL_CTX_set_dh_auto(ctx, 1));
DFLY_SSL_CHECK(1 == SSL_CTX_set_dh_auto(ctx, 1));
return ctx;
}

25
src/facade/tls_error.cc Normal file
View file

@ -0,0 +1,25 @@
#include "facade/tls_error.h"
#include <openssl/err.h>
#include <string_view>
#include "base/logging.h"
#ifdef DFLY_USE_SSL
void facade::PrintSSLError() {
ERR_print_errors_cb(
[](const char* str, size_t len, void* u) {
LOG(ERROR) << std::string_view(str, len);
return 1;
},
nullptr);
}
#else
void facade::PrintSSLError() {
}
#endif

18
src/facade/tls_error.h Normal file
View file

@ -0,0 +1,18 @@
// Copyright 2023, DragonflyDB authors. All rights reserved.
// See LICENSE for licensing terms.
//
#pragma once
namespace facade {
void PrintSSLError();
}
#define DFLY_SSL_CHECK(condition) \
if (!(condition)) { \
LOG(ERROR) << "OpenSSL Error: " #condition; \
PrintSSLError(); \
exit(17); \
}

View file

@ -3,6 +3,8 @@
//
#include "server/protocol_client.h"
#include "facade/tls_error.h"
extern "C" {
#include "redis/rdb.h"
}
@ -51,6 +53,7 @@ using absl::StrCat;
namespace {
#ifdef DFLY_USE_SSL
static ProtocolClient::SSL_CTX* CreateSslClientCntx() {
ProtocolClient::SSL_CTX* ctx = SSL_CTX_new(TLS_client_method());
const auto& tls_key_file = GetFlag(FLAGS_tls_key_file);
@ -58,11 +61,11 @@ static ProtocolClient::SSL_CTX* CreateSslClientCntx() {
// Load client certificate if given.
if (!tls_key_file.empty()) {
CHECK_EQ(1, SSL_CTX_use_PrivateKey_file(ctx, tls_key_file.c_str(), SSL_FILETYPE_PEM));
DFLY_SSL_CHECK(1 == SSL_CTX_use_PrivateKey_file(ctx, tls_key_file.c_str(), SSL_FILETYPE_PEM));
// We checked that the flag is non empty in ValidateClientTlsFlags.
const auto& tls_cert_file = GetFlag(FLAGS_tls_cert_file);
CHECK_EQ(1, SSL_CTX_use_certificate_chain_file(ctx, tls_cert_file.c_str()));
DFLY_SSL_CHECK(1 == SSL_CTX_use_certificate_chain_file(ctx, tls_cert_file.c_str()));
}
// Load custom certificate validation if given.
@ -72,19 +75,19 @@ static ProtocolClient::SSL_CTX* CreateSslClientCntx() {
const auto* file = tls_ca_cert_file.empty() ? nullptr : tls_ca_cert_file.data();
const auto* dir = tls_ca_cert_dir.empty() ? nullptr : tls_ca_cert_dir.data();
if (file || dir) {
CHECK_EQ(1, SSL_CTX_load_verify_locations(ctx, file, dir));
DFLY_SSL_CHECK(1 == SSL_CTX_load_verify_locations(ctx, file, dir));
} else {
CHECK_EQ(1, SSL_CTX_set_default_verify_paths(ctx));
DFLY_SSL_CHECK(1 == SSL_CTX_set_default_verify_paths(ctx));
}
CHECK_EQ(1, SSL_CTX_set_cipher_list(ctx, "DEFAULT"));
DFLY_SSL_CHECK(1 == SSL_CTX_set_cipher_list(ctx, "DEFAULT"));
SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION);
SSL_CTX_set_options(ctx, SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS);
SSL_CTX_set_verify(ctx, mask, NULL);
CHECK_EQ(1, SSL_CTX_set_dh_auto(ctx, 1));
DFLY_SSL_CHECK(1 == SSL_CTX_set_dh_auto(ctx, 1));
return ctx;
}
#endif