@cryptotaxi247 / netdata-1 / commits / 3e15a013d

detect the system ca bundle at runtime (#19622)

* detect the system ca bundle at runtime * minor fix * fix for older libcurl versions * added X509_get_default_cert_file() * added validation for the certificates * moved ssl/curl code to separate file; now it configured both libcurl and openssl; added defaults to libcurl static install * run the new code only in netdata static builds * auto to check * disable runtime ssl checks

Costa Tsaousis committed Feb 12, 2025 at 14:28 UTC 3e15a013d04f6394ad8c69e43325c923537eec8b
10 files changed +112 -6
CMakeLists.txt
+2
@@ -1182,6 +1182,8 @@ set(DAEMON_FILES
1182 src/daemon/pulse/pulse-db-dbengine-retention.h
1183 src/daemon/pulse/pulse-parents.c
1184 src/daemon/pulse/pulse-parents.h
1185 + src/daemon/config/netdata-conf-ssl.c
1186 + src/daemon/config/netdata-conf-ssl.h
1187 )
1188
1189 set(H2O_FILES
packaging/makeself/install-or-update.sh
+1 -1
@@ -27,7 +27,7 @@ fi
27
28 STARTIT=1
29 REINSTALL_OPTIONS=""
30 -NETDATA_CERT_MODE="${NETDATA_CERT_MODE:-auto}"
30 +NETDATA_CERT_MODE="${NETDATA_CERT_MODE:-check}"
31 NETDATA_CERT_TEST_URL="${NETDATA_CERT_TEST_URL:-https://app.netdata.cloud}"
32 RELEASE_CHANNEL="nightly"
33
packaging/makeself/jobs/50-curl.install.sh
+2
@@ -57,6 +57,8 @@ if [ "${CACHE_HIT:-0}" -eq 0 ]; then
57 --enable-cookies \
58 --with-ca-fallback \
59 --with-openssl \
60 + --with-ca-bundle=/opt/netdata/etc/ssl/certs/ca-certificates.crt \
61 + --with-ca-path=/opt/netdata/etc/ssl/certs \
62 --disable-dependency-tracking
63
64 # Curl autoconf does not honour the curl_LDFLAGS environment variable
packaging/makeself/jobs/70-netdata-git.install.sh
+2 -2
@@ -7,9 +7,9 @@
7 cd "${NETDATA_SOURCE_PATH}" || exit 1
8
9 if [ "${NETDATA_BUILD_WITH_DEBUG}" -eq 0 ]; then
10 - export CFLAGS="${TUNING_FLAGS} -ffunction-sections -fdata-sections -static -O2 -funroll-loops -I/openssl-static/include -I/libnetfilter-acct-static/include/libnetfilter_acct -I/curl-local/include/curl -I/usr/include/libmnl -pipe"
10 + export CFLAGS="${TUNING_FLAGS} -ffunction-sections -fdata-sections -static -O2 -funroll-loops -DNETDATA_STATIC_BUILD=1 -I/openssl-static/include -I/libnetfilter-acct-static/include/libnetfilter_acct -I/curl-local/include/curl -I/usr/include/libmnl -pipe"
11 else
12 - export CFLAGS="${TUNING_FLAGS} -static -O1 -pipe -ggdb -Wall -Wextra -Wformat-signedness -DNETDATA_INTERNAL_CHECKS=1 -I/openssl-static/include -I/libnetfilter-acct-static/include/libnetfilter_acct -I/curl-local/include/curl -I/usr/include/libmnl"
12 + export CFLAGS="${TUNING_FLAGS} -static -O1 -pipe -ggdb -Wall -Wextra -Wformat-signedness -DNETDATA_STATIC_BUILD=1 -DNETDATA_INTERNAL_CHECKS=1 -I/openssl-static/include -I/libnetfilter-acct-static/include/libnetfilter_acct -I/curl-local/include/curl -I/usr/include/libmnl"
13 fi
14
15 export LDFLAGS="-Wl,--gc-sections -static -L/openssl-static/lib64 -L/libnetfilter-acct-static/lib -lnetfilter_acct -L/usr/lib -lmnl -L/usr/lib -lzstd -L/curl-local/lib"
src/daemon/config/netdata-conf-ssl.c new
+93
@@ -0,0 +1,93 @@
1 +// SPDX-License-Identifier: GPL-3.0-or-later
2 +
3 +#include "daemon/common.h"
4 +#include "netdata-conf-ssl.h"
5 +#include <curl/curl.h>
6 +
7 +static bool is_ca_bundle_valid(const char *ca_path) {
8 + if (!ca_path || !*ca_path)
9 + return false;
10 +
11 + FILE *fp = fopen(ca_path, "r");
12 + if (!fp)
13 + return false;
14 +
15 + ERR_clear_error();
16 +
17 + int valid_certs = 0;
18 + X509 *cert = NULL;
19 + while ((cert = PEM_read_X509(fp, NULL, NULL, NULL)) != NULL) {
20 + ASN1_TIME *not_after = X509_get_notAfter(cert);
21 + int day, sec;
22 +
23 + if (ASN1_TIME_diff(&day, &sec, NULL, not_after) == 1) {
24 + if (day > 0 || (day == 0 && sec > 0)) {
25 + valid_certs++;
26 +
27 + // we found 1 valid, stop reading the file
28 + X509_free(cert);
29 + break;
30 + }
31 + }
32 +
33 + X509_free(cert);
34 + }
35 +
36 + fclose(fp);
37 +
38 + ERR_clear_error();
39 + return valid_certs > 0;
40 +}
41 +
42 +const char *detect_libcurl_default_ca() {
43 +#if LIBCURL_VERSION_NUM >= 0x074600 // 7.70.0 (CURLVERSION_SEVENTH)
44 + curl_version_info_data *info = curl_version_info(CURLVERSION_NOW);
45 + if (info) {
46 + // Check built-in CA bundle
47 + if (info->cainfo &&
48 + access(info->cainfo, R_OK) == 0 &&
49 + is_ca_bundle_valid(info->cainfo))
50 + return info->cainfo;
51 + }
52 +#endif
53 + return NULL;
54 +}
55 +
56 +static const char *detect_ca_path(void) {
57 + static const char *paths[] = {
58 + "/etc/ssl/certs/ca-certificates.crt", // Debian, Ubuntu, Arch
59 + "/etc/pki/tls/certs/ca-bundle.crt", // RHEL, CentOS, Fedora
60 + "/etc/ssl/ca-bundle.pem", // OpenSUSE
61 + "/etc/ssl/cert.pem", // Alpine
62 + "/opt/netdata/etc/ssl/certs/ca-certificates.crt", // Netdata static build
63 + "/opt/netdata/share/ssl/certs/ca-certificates.crt", // Netdata static build - fallback
64 + NULL
65 + };
66 +
67 + for (int i = 0; paths[i] != NULL; i++) {
68 + if (access(paths[i], R_OK) == 0 &&
69 + is_ca_bundle_valid(paths[i]))
70 + return paths[i];
71 + }
72 +
73 + return NULL;
74 +}
75 +
76 +void netdata_conf_ssl(void) {
77 + netdata_ssl_initialize_openssl();
78 +
79 +#if 0
80 + const char *p = getenv("CURL_CA_BUNDLE");
81 + if(!p || !*p) p = getenv("SSL_CERT_FILE");
82 + if(!p || !*p) {
83 + p = X509_get_default_cert_file();
84 + if(!p || !*p || !is_ca_bundle_valid(p))
85 + p = NULL;
86 + }
87 + if(!p || !*p) p = detect_libcurl_default_ca();
88 + if(!p || !*p) p = detect_ca_path();
89 + setenv("CURL_CA_BUNDLE", inicfg_get(&netdata_config, CONFIG_SECTION_ENV_VARS, "CURL_CA_BUNDLE", p ? p : ""), 1);
90 + setenv("SSL_CERT_FILE", inicfg_get(&netdata_config, CONFIG_SECTION_ENV_VARS, "SSL_CERT_FILE", p ? p : ""), 1);
91 +#endif
92 +
93 +}
src/daemon/config/netdata-conf-ssl.h new
+8
@@ -0,0 +1,8 @@
1 +// SPDX-License-Identifier: GPL-3.0-or-later
2 +
3 +#ifndef NETDATA_NETDATA_CONF_SSL_H
4 +#define NETDATA_NETDATA_CONF_SSL_H
5 +
6 +void netdata_conf_ssl(void);
7 +
8 +#endif //NETDATA_NETDATA_CONF_SSL_H
src/daemon/config/netdata-conf-web.c
-2
@@ -159,7 +159,5 @@ void netdata_conf_web_security_init(void) {
159
160 tls_version = inicfg_get(&netdata_config, CONFIG_SECTION_WEB, "tls version", "1.3");
161 tls_ciphers = inicfg_get(&netdata_config, CONFIG_SECTION_WEB, "tls ciphers", "none");
162 -
163 - netdata_ssl_initialize_openssl();
162 }
163
src/daemon/config/netdata-conf.h
+1
@@ -16,5 +16,6 @@ bool netdata_conf_load(char *filename, char overwrite_used, const char **user);
16 #include "netdata-conf-logs.h"
17 #include "netdata-conf-web.h"
18 #include "netdata-conf-cloud.h"
19 +#include "netdata-conf-ssl.h"
20
21 #endif //NETDATA_DAEMON_NETDATA_CONF_H
src/daemon/environment.c
+2 -1
@@ -81,7 +81,8 @@ void set_environment_for_plugins_and_scripts(void) {
81 freez((char *)default_port);
82
83 // set the path we need
84 - char path[4096], *p = getenv("PATH");
84 + char path[4096];
85 + const char *p = getenv("PATH");
86 if (!p) p = "/bin:/usr/bin";
87 snprintfz(path, sizeof(path), "%s:%s", p, "/sbin:/usr/sbin:/usr/local/bin:/usr/local/sbin");
88 setenv("PATH", inicfg_get(&netdata_config, CONFIG_SECTION_ENV_VARS, "PATH", path), 1);
src/daemon/main.c
+1
@@ -762,6 +762,7 @@ int netdata_main(int argc, char **argv) {
762 // ----------------------------------------------------------------------------------------------------------------
763 // global configuration
764
765 + netdata_conf_ssl();
766 netdata_conf_section_global();
767
768 // Get execution path before switching user to avoid permission issues