diff --git a/lib/transport/tls-context.c b/lib/transport/tls-context.c index 46dbc5b8bb8..be2fea68dbe 100644 --- a/lib/transport/tls-context.c +++ b/lib/transport/tls-context.c @@ -502,6 +502,32 @@ _set_client_ca_list(TLSContext *self) #endif } +gboolean +tls_context_verify_peer(TLSContext *self, X509 *peer_cert, const gchar *peer_name) +{ + if ((tls_context_get_verify_mode(self) & TVM_TRUSTED) == 0) + { + msg_warning("Bypassing certificate validation, peer certificate is always accepted"); + return TRUE; + } + + if (!peer_name) + return TRUE; + + if (!tls_verify_certificate_name(peer_cert, peer_name)) + { + if (tls_context_ignore_hostname_mismatch(self)) + { + msg_warning("Ignoring certificate subject validation error due to options(ignore-hostname-mismatch)", + evt_tag_str("hostname", peer_name)); + return TRUE; + } + return FALSE; + } + + return TRUE; +} + TLSContextSetupResult tls_context_setup_context(TLSContext *self) { @@ -662,6 +688,8 @@ tls_context_set_ssl_options_by_name(TLSContext *self, GList *options) else if (strcasecmp(l->data, "ignore-unexpected-eof") == 0 || strcasecmp(l->data, "ignore_unexpected_eof") == 0) self->ssl_options |= TSO_IGNORE_UNEXPECTED_EOF; #endif + else if (strcasecmp(l->data, "ignore-hostname-mismatch") == 0 || strcasecmp(l->data, "ignore_hostname_mismatch") == 0) + self->ssl_options |= TSO_IGNORE_HOSTNAME_MISMATCH; else return FALSE; } @@ -681,6 +709,12 @@ tls_context_set_verify_mode(TLSContext *self, gint verify_mode) self->verify_mode = verify_mode; } +gboolean +tls_context_ignore_hostname_mismatch(TLSContext *self) +{ + return self->ssl_options & TSO_IGNORE_HOSTNAME_MISMATCH; +} + static int _pem_passwd_callback(char *buf, int size, int rwflag, void *user_data) { diff --git a/lib/transport/tls-context.h b/lib/transport/tls-context.h index e3241f23341..08c3fc96154 100644 --- a/lib/transport/tls-context.h +++ b/lib/transport/tls-context.h @@ -54,6 +54,7 @@ typedef enum TSO_NOTLSv12=0x0010, TSO_NOTLSv13=0x0020, TSO_IGNORE_UNEXPECTED_EOF=0x0040, + TSO_IGNORE_HOSTNAME_MISMATCH=0x0080, } TLSSslOptions; typedef enum @@ -116,6 +117,7 @@ gboolean tls_context_set_verify_mode_by_name(TLSContext *self, const gchar *mode gboolean tls_context_set_ssl_options_by_name(TLSContext *self, GList *options); gint tls_context_get_verify_mode(const TLSContext *self); void tls_context_set_verify_mode(TLSContext *self, gint verify_mode); +gboolean tls_context_ignore_hostname_mismatch(TLSContext *self); void tls_context_set_key_file(TLSContext *self, const gchar *key_file); void tls_context_set_cert_file(TLSContext *self, const gchar *cert_file); gboolean tls_context_set_keylog_file(TLSContext *self, gchar *keylog_file_path, GError **error); @@ -135,6 +137,7 @@ void tls_context_set_ocsp_stapling_verify(TLSContext *self, gboolean ocsp_stapli const gchar *tls_context_get_key_file(TLSContext *self); EVTTAG *tls_context_format_tls_error_tag(TLSContext *self); EVTTAG *tls_context_format_location_tag(TLSContext *self); +gboolean tls_context_verify_peer(TLSContext *self, X509 *peer_cert, const gchar *peer_name); TLSContextSetupResult tls_context_setup_context(TLSContext *self); TLSSession *tls_context_setup_session(TLSContext *self); TLSContext *tls_context_new(TLSMode mode, const gchar *config_location); diff --git a/modules/afsocket/afinet-dest.c b/modules/afsocket/afinet-dest.c index 352f148997b..62016830e29 100644 --- a/modules/afsocket/afinet-dest.c +++ b/modules/afsocket/afinet-dest.c @@ -141,14 +141,14 @@ afinet_dd_verify_callback(gint ok, X509_STORE_CTX *ctx, gpointer user_data) X509 *current_cert = X509_STORE_CTX_get_current_cert(ctx); X509 *cert = X509_STORE_CTX_get0_cert(ctx); - if (ok && current_cert == cert && self->hostname - && (tls_context_get_verify_mode(self->tls_context) & TVM_TRUSTED)) + if (ok && current_cert == cert) { - ok = tls_verify_certificate_name(cert, self->hostname); + ok = tls_context_verify_peer(self->tls_context, cert, self->hostname); if (ok) { AFSocketTLSCertificateValidationSignalData signal_data = {0}; signal_data.ctx = ctx; + signal_data.tls_context = self->tls_context; EMIT(self->signal_connector, signal_afsocket_tls_certificate_validation, &signal_data); diff --git a/modules/afsocket/afsocket-signals.h b/modules/afsocket/afsocket-signals.h index 85ca7cb6a46..4db4e100a3b 100644 --- a/modules/afsocket/afsocket-signals.h +++ b/modules/afsocket/afsocket-signals.h @@ -25,10 +25,11 @@ #define AFSOCKET_SIGNALS_H_INCLUDED #include "signal-slot-connector/signal-slot-connector.h" -#include +#include "transport/tls-context.h" typedef struct _AFSocketTLSCertificateValidationSignalData { + TLSContext *tls_context; X509_STORE_CTX *ctx; gboolean failure; } AFSocketTLSCertificateValidationSignalData; diff --git a/modules/examples/inner-destinations/tls-test-validation/tls-test-validation.c b/modules/examples/inner-destinations/tls-test-validation/tls-test-validation.c index 649072a94e7..50f761e44a2 100644 --- a/modules/examples/inner-destinations/tls-test-validation/tls-test-validation.c +++ b/modules/examples/inner-destinations/tls-test-validation/tls-test-validation.c @@ -22,7 +22,7 @@ #include "tls-test-validation.h" #include "modules/afsocket/afsocket-signals.h" -#include "transport/tls-verifier.h" +#include "transport/tls-context.h" #include "compat/openssl_support.h" #define TLS_TEST_VALIDATION_PLUGIN "tls-test-validation" @@ -44,7 +44,7 @@ static void _slot_append_test_identity(TlsTestValidationPlugin *self, AFSocketTLSCertificateValidationSignalData *data) { X509 *cert = X509_STORE_CTX_get0_cert(data->ctx); - data->failure = !tls_verify_certificate_name(cert, self->identity); + data->failure = !tls_context_verify_peer(data->tls_context, cert, self->identity); msg_debug("TlsTestValidationPlugin validated"); } diff --git a/news/feature-4628.md b/news/feature-4628.md new file mode 100644 index 00000000000..1204ce69cdd --- /dev/null +++ b/news/feature-4628.md @@ -0,0 +1,6 @@ +Add `ignore-hostname-mismatch` as a new flag to `ssl-options()`: by +specifying `ignore-hostname-mismatch`, you can ignore the subject name of a +certificate during the validation process. This means that syslog-ng will +only check if the certificate itself is trusted by the current set of trust +anchors (e.g. trusted CAs) ignoring the mismatch between the targeted +hostname and the certificate subject.