Improve certificate verification error logging in ACLK connections (#21513)
* Improve certificate verification error logging and memory handling in ACLK clients Replace deprecated `X509_NAME_oneline` with `BIO` for more robust subject name extraction. Ensure proper management of `BIO` resources to prevent memory leaks. Provide fallback logging for cases where subject name extraction fails. * Additional checks for certificate verification * Resolve windows compilation conflict * Improve netdata_ssl_log_verify_error
Stelios Fragkakis committed
Jan 5, 2026 at 10:23 UTC
8a15f8fbf004f812f4b90453b35476eacb6cac90
5 files changed
+60
-21
src/aclk/https_client.c
+2
-11
@@ -737,20 +737,11 @@ err_exit:
737
738
static int cert_verify_callback(int preverify_ok, X509_STORE_CTX *ctx)
739
{
740
- X509 *err_cert;
741
- int err, depth;
742
- char *err_str;
740
+ int err = 0;
741
742
if (!preverify_ok) {
743
err = X509_STORE_CTX_get_error(ctx);
746
- depth = X509_STORE_CTX_get_error_depth(ctx);
747
- err_cert = X509_STORE_CTX_get_current_cert(ctx);
748
- err_str = X509_NAME_oneline(X509_get_subject_name(err_cert), NULL, 0);
749
-
750
- netdata_log_error("Cert Chain verify error:num=%d:%s:depth=%d:%s", err,
751
- X509_verify_cert_error_string(err), depth, err_str);
752
-
753
- free(err_str);
744
+ netdata_ssl_log_verify_error(ctx);
745
}
746
747
if(cloud_config_insecure_get()) {
src/aclk/mqtt_websockets/mqtt_wss_client.c
+1
-10
@@ -239,18 +239,9 @@ static int cert_verify_callback(int preverify_ok, X509_STORE_CTX *ctx)
239
SSL* ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
240
mqtt_wss_client client = SSL_get_ex_data(ssl, 0);
241
242
- // TODO handle depth as per https://www.openssl.org/docs/man1.0.2/man3/SSL_CTX_set_verify.html
243
-
242
if (!preverify_ok) {
243
err = X509_STORE_CTX_get_error(ctx);
246
- int depth = X509_STORE_CTX_get_error_depth(ctx);
247
- X509* err_cert = X509_STORE_CTX_get_current_cert(ctx);
248
- char* err_str = X509_NAME_oneline(X509_get_subject_name(err_cert), NULL, 0);
249
-
250
- nd_log(NDLS_DAEMON, NDLP_ERR, "verify error:num=%d:%s:depth=%d:%s", err,
251
- X509_verify_cert_error_string(err), depth, err_str);
252
-
253
- freez(err_str);
244
+ netdata_ssl_log_verify_error(ctx);
245
}
246
247
if (!preverify_ok && err == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT &&
src/libnetdata/common.h
+17
@@ -466,6 +466,23 @@ typedef uint32_t uid_t;
466
#include <wbemidl.h>
467
#include <sddl.h>
468
// #include <winternl.h> // conflicts on STRING,
469
+
470
+// wincrypt.h (included via windows.h) defines macros that conflict with OpenSSL
471
+#ifdef X509_NAME
472
+#undef X509_NAME
473
+#endif
474
+#ifdef X509_EXTENSIONS
475
+#undef X509_EXTENSIONS
476
+#endif
477
+#ifdef PKCS7_SIGNER_INFO
478
+#undef PKCS7_SIGNER_INFO
479
+#endif
480
+#ifdef OCSP_REQUEST
481
+#undef OCSP_REQUEST
482
+#endif
483
+#ifdef OCSP_RESPONSE
484
+#undef OCSP_RESPONSE
485
+#endif
486
#endif
487
488
// --------------------------------------------------------------------------------------------------------------------
src/libnetdata/socket/security.c
+38
@@ -858,3 +858,41 @@ int ssl_security_location_for_context(SSL_CTX *ctx, const char *file, const char
858
859
return 0;
860
}
861
+
862
+void netdata_ssl_log_verify_error(X509_STORE_CTX *ctx) {
863
+ int err = X509_STORE_CTX_get_error(ctx);
864
+ int depth = X509_STORE_CTX_get_error_depth(ctx);
865
+
866
+ BIO *bio = NULL;
867
+ const char *subject = NULL;
868
+ int subject_len = 0;
869
+
870
+ X509 *cert = X509_STORE_CTX_get_current_cert(ctx);
871
+ if (cert) {
872
+ X509_NAME *name = X509_get_subject_name(cert);
873
+ if (name) {
874
+ bio = BIO_new(BIO_s_mem());
875
+ if (bio && X509_NAME_print_ex(bio, name, 0, XN_FLAG_ONELINE) >= 0) {
876
+ BUF_MEM *bptr = NULL;
877
+ /* Optional defensive check:
878
+ * BIO_get_mem_ptr() returns 1 on success, 0 on failure. */
879
+ if (BIO_get_mem_ptr(bio, &bptr) > 0 && bptr && bptr->data && bptr->length > 0) {
880
+ subject = bptr->data;
881
+ subject_len = (int)bptr->length;
882
+ }
883
+ }
884
+ }
885
+ }
886
+
887
+ if (subject && subject_len > 0) {
888
+ nd_log(NDLS_DAEMON, NDLP_ERR,
889
+ "SSL: certificate verify error %d:%s at depth %d, subject: %.*s",
890
+ err, X509_verify_cert_error_string(err), depth, subject_len, subject);
891
+ } else {
892
+ nd_log(NDLS_DAEMON, NDLP_ERR,
893
+ "SSL: certificate verify error %d:%s at depth %d",
894
+ err, X509_verify_cert_error_string(err), depth);
895
+ }
896
+
897
+ BIO_free(bio);
898
+}
src/libnetdata/socket/security.h
+2
@@ -53,4 +53,6 @@ ssize_t netdata_ssl_peek(NETDATA_SSL *ssl, void *buf, size_t num);
53
ssize_t netdata_ssl_pending(NETDATA_SSL *ssl);
54
bool netdata_ssl_has_pending(NETDATA_SSL *ssl);
55
56
+void netdata_ssl_log_verify_error(X509_STORE_CTX *ctx);
57
+
58
#endif //NETDATA_SECURITY_H