@cryptotaxi247 / netdata-1 / commits / 06c16139f

hostnames: convert to utf8 and santitize (#19418)

* hostnames: convert to utf8 and santitize * add windows version of the hostname * fix warnings on windows * fix freebsd * disable iconv on posix systems

Costa Tsaousis committed Jan 16, 2025 at 19:59 UTC 06c16139f8a57d05d9bd60e65baca6feea6438c4
10 files changed +199 -21
CMakeLists.txt
+2
@@ -987,6 +987,8 @@ set(LIBNETDATA_FILES
987 src/libnetdata/memory/alignment.h
988 src/libnetdata/os/get_system_pagesize.c
989 src/libnetdata/os/get_system_pagesize.h
990 + src/libnetdata/os/hostname.c
991 + src/libnetdata/os/hostname.h
992 )
993
994 set(LIBH2O_FILES
packaging/cmake/config.cmake.h.in
+1
@@ -68,6 +68,7 @@
68 #cmakedefine HAVE_SETENV
69 #cmakedefine HAVE_DLSYM
70 #cmakedefine HAVE_LIBCURL
71 +#cmakedefine HAVE_LIBICONV
72
73 #cmakedefine HAVE_ARC4RANDOM_BUF
74 #cmakedefine HAVE_ARC4RANDOM_UNIFORM
src/daemon/config/netdata-conf-global.c
+2 -18
@@ -40,22 +40,6 @@ skip:
40 return processors;
41 }
42
43 -static int get_hostname(char *buf, size_t buf_size) {
44 - if (netdata_configured_host_prefix && *netdata_configured_host_prefix) {
45 - char filename[FILENAME_MAX + 1];
46 - snprintfz(filename, FILENAME_MAX, "%s/etc/hostname", netdata_configured_host_prefix);
47 -
48 - if (!read_txt_file(filename, buf, buf_size)) {
49 - trim(buf);
50 - return 0;
51 - }
52 - }
53 -
54 - int rc = gethostname(buf, buf_size);
55 - buf[buf_size - 1] = '\0';
56 - return rc;
57 -}
58 -
43 void netdata_conf_glibc_malloc_initialize(size_t wanted_arenas, size_t trim_threshold __maybe_unused) {
44 wanted_arenas = config_get_number(CONFIG_SECTION_GLOBAL, "glibc malloc arena max for plugins", wanted_arenas);
45 if(wanted_arenas < 1 || wanted_arenas > os_get_system_cpus_cached(true)) {
@@ -119,8 +103,8 @@ void netdata_conf_section_global(void) {
103 netdata_configured_host_prefix = config_get(CONFIG_SECTION_GLOBAL, "host access prefix", "");
104 (void) verify_netdata_host_prefix(true);
105
122 - char buf[HOSTNAME_MAX + 1];
123 - if (get_hostname(buf, sizeof(buf)))
106 + char buf[HOST_NAME_MAX * 4 + 1];
107 + if (!os_hostname(buf, sizeof(buf), netdata_configured_host_prefix))
108 netdata_log_error("Cannot get machine hostname.");
109
110 netdata_configured_hostname = config_get(CONFIG_SECTION_GLOBAL, "hostname", buf);
src/daemon/pulse/pulse-daemon-memory-system.c
+1 -1
@@ -107,7 +107,7 @@ cleanup:
107 }
108 #endif // HAVE_C_MALLOC_INFO
109
110 -void pulse_daemon_memory_system_do(bool extended) {
110 +void pulse_daemon_memory_system_do(bool extended __maybe_unused) {
111
112 #ifdef HAVE_C_MALLOC_INFO
113 size_t glibc_arenas, glibc_allocated_arenas, glibc_unused_fast, glibc_unused_rest, glibc_allocated_mmap;
src/database/rrdlabels.c
+4
@@ -1577,6 +1577,10 @@ int rrdlabels_unittest_sanitization() {
1577 const unsigned char invalid5[] = "app.clewd修改\xe7\x89_fd_open_limits";
1578 errors += rrdlabels_unittest_sanitize_value((const char *)invalid5, "app.clewd修改e789_fd_open_limits");
1579
1580 + // invalid UTF8 No 6
1581 + const unsigned char invalid6[] = "\260\327\312\300\322\242";
1582 + errors += rrdlabels_unittest_sanitize_value((const char *)invalid6, "d7cac0Ң");
1583 +
1584 return errors;
1585 }
1586
src/libnetdata/common.h
+6
@@ -400,6 +400,12 @@ typedef uint32_t uid_t;
400
401 // --------------------------------------------------------------------------------------------------------------------
402
403 +#ifndef HOST_NAME_MAX
404 +#define HOST_NAME_MAX 256
405 +#endif
406 +
407 +// --------------------------------------------------------------------------------------------------------------------
408 +
409 #if defined(OS_WINDOWS)
410 #include <windows.h>
411 #include <wctype.h>
src/libnetdata/os/hostname.c new
+161
@@ -0,0 +1,161 @@
1 +// SPDX-License-Identifier: GPL-3.0-or-later
2 +
3 +#include "libnetdata/libnetdata.h"
4 +
5 +#if defined(OS_WINDOWS)
6 +bool os_hostname(char *dst, size_t dst_size, const char *filesystem_root __maybe_unused) {
7 + WCHAR wbuf[HOST_NAME_MAX * 4 + 1];
8 + char buf[HOST_NAME_MAX * 4 + 1];
9 + DWORD size = _countof(wbuf);
10 + bool success = false;
11 +
12 + // First try DNS hostname
13 + if (GetComputerNameExW(ComputerNameDnsHostname, wbuf, &size)) {
14 + success = true;
15 + }
16 + // Then try NetBIOS name
17 + else {
18 + size = _countof(wbuf);
19 + if (GetComputerNameW(wbuf, &size)) {
20 + success = true;
21 + }
22 + }
23 +
24 + if (success) {
25 + // Convert UTF-16 to UTF-8
26 + int utf8_size = WideCharToMultiByte(CP_UTF8, 0, wbuf, -1, NULL, 0, NULL, NULL);
27 + if (utf8_size > 0 && utf8_size <= (int)sizeof(buf)) {
28 + WideCharToMultiByte(CP_UTF8, 0, wbuf, -1, buf, utf8_size, NULL, NULL);
29 + }
30 + else {
31 + success = false;
32 + }
33 + }
34 +
35 + if (!success) {
36 + // Try getting the machine GUID first
37 + HKEY hKey;
38 + if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Cryptography", 0, KEY_READ, &hKey) == ERROR_SUCCESS) {
39 + WCHAR guidW[64];
40 + DWORD guidSize = sizeof(guidW);
41 + DWORD type = REG_SZ;
42 +
43 + if (RegQueryValueExW(hKey, L"MachineGuid", NULL, &type, (LPBYTE)guidW, &guidSize) == ERROR_SUCCESS) {
44 + // Convert GUID to UTF-8
45 + if (WideCharToMultiByte(CP_UTF8, 0, guidW, -1, buf, sizeof(buf), NULL, NULL) > 0) {
46 + success = true;
47 + }
48 + }
49 + RegCloseKey(hKey);
50 + }
51 +
52 + if (!success) {
53 + // If machine GUID fails, try getting volume serial number of C: drive
54 + WCHAR rootPath[] = L"C:\\";
55 + DWORD serialNumber;
56 + if (GetVolumeInformationW(rootPath, NULL, 0, &serialNumber, NULL, NULL, NULL, 0)) {
57 + snprintf(buf, sizeof(buf), "host%08lx", (long unsigned)serialNumber);
58 + success = true;
59 + }
60 + else {
61 + // Last resort: use process ID
62 + snprintf(buf, sizeof(buf), "host%lu", (long unsigned)GetCurrentProcessId());
63 + }
64 + }
65 + }
66 +
67 + char *hostname = trim(buf);
68 + rrdlabels_sanitize_value(dst, hostname, dst_size);
69 + return *dst != '\0';
70 +}
71 +#else // !OS_WINDOWS
72 +
73 +#ifdef HAVE_LIBICONV
74 +#include <iconv.h>
75 +
76 +static const char *get_current_locale(void) {
77 + const char *locale = getenv("LC_ALL"); // LC_ALL overrides all other locale settings
78 +
79 + if (!locale || !*locale) {
80 + locale = getenv("LC_CTYPE"); // Check LC_CTYPE for character encoding
81 +
82 + if (!locale || !*locale)
83 + locale = getenv("LANG"); // Fallback to LANG
84 + }
85 +
86 + return locale;
87 +}
88 +
89 +static const char *get_encoding_from_locale(const char *locale) {
90 + if(!locale || !*locale)
91 + return NULL;
92 +
93 + const char *dot = strchr(locale, '.');
94 + if (dot)
95 + return dot + 1;
96 +
97 + return locale;
98 +}
99 +
100 +// Function to convert from a source encoding to UTF-8
101 +static bool iconv_convert_to_utf8(const char *input, const char *src_encoding, char *output, size_t output_size) {
102 + iconv_t cd = iconv_open("UTF-8", src_encoding);
103 + if (cd == (iconv_t)-1) {
104 + int i = errno;
105 + return false;
106 + }
107 +
108 + char *input_ptr = (char *)input; // iconv() may modify this pointer
109 + char *output_ptr = output; // iconv() modifies this pointer
110 + size_t input_len = strlen(input);
111 + size_t output_len = output_size;
112 +
113 + // Perform the conversion
114 + if (iconv(cd, &input_ptr, &input_len, &output_ptr, &output_len) == (size_t)-1) {
115 + iconv_close(cd);
116 + return false;
117 + }
118 +
119 + // Null-terminate the output string
120 + *output_ptr = '\0';
121 +
122 + iconv_close(cd);
123 + return true;
124 +}
125 +#endif
126 +
127 +bool os_hostname(char *dst, size_t dst_size, const char *filesystem_root) {
128 + *dst = '\0';
129 +
130 + char buf[HOST_NAME_MAX * 4 + 1];
131 + *buf = '\0';
132 +
133 + if (filesystem_root && *filesystem_root) {
134 + char filename[FILENAME_MAX + 1];
135 + snprintfz(filename, FILENAME_MAX, "%s/etc/hostname", netdata_configured_host_prefix);
136 +
137 + if (read_txt_file(filename, buf, sizeof(buf)))
138 + *buf = '\0';
139 + }
140 +
141 + if(!*buf && gethostname(buf, sizeof(buf)) != 0)
142 + snprintf(buf, sizeof(buf), "host%ld", gethostid());
143 +
144 + char *original_hostname = trim(buf);
145 +
146 +#ifdef HAVE_LIBICONV
147 + const char *locale = get_current_locale();
148 + if (locale && *locale) {
149 + char utf8_output[HOST_NAME_MAX * 4 + 1] = "";
150 + if(iconv_convert_to_utf8(original_hostname, get_encoding_from_locale(locale), utf8_output, sizeof(utf8_output))) {
151 + rrdlabels_sanitize_value(dst, trim(utf8_output), dst_size);
152 + return *dst != '\0';
153 + }
154 + }
155 +#endif
156 +
157 + rrdlabels_sanitize_value(dst, original_hostname, dst_size);
158 + return *dst != '\0';
159 +}
160 +
161 +#endif // !OS_WINDOWS
src/libnetdata/os/hostname.h new
+21
@@ -0,0 +1,21 @@
1 +// SPDX-License-Identifier: GPL-3.0-or-later
2 +
3 +#ifndef NETDATA_HOSTNAME_H
4 +#define NETDATA_HOSTNAME_H
5 +
6 +#include "libnetdata/libnetdata.h"
7 +
8 +/**
9 + * Get system hostname in UTF-8 encoding
10 + *
11 + * @param dst Buffer to store the hostname
12 + * @param dst_size Size of the destination buffer
13 + * @param filesystem_root Optional root directory (for Unix-like systems, when running in a container)
14 + * @return true on success, false on failure
15 + *
16 + * The function guarantees to return a UTF-8 encoded hostname.
17 + * On Windows, filesystem_root is ignored.
18 + */
19 + bool os_hostname(char *dst, size_t dst_size, const char *filesystem_root);
20 +
21 +#endif //NETDATA_HOSTNAME_H
src/libnetdata/os/os.h
+1
@@ -23,6 +23,7 @@
23 #include "sleep.h"
24 #include "uuid_generate.h"
25 #include "setenv.h"
26 +#include "hostname.h"
27 #include "os-freebsd-wrappers.h"
28 #include "os-macos-wrappers.h"
29 #include "os-windows-wrappers.h"
src/web/api/formatters/rrd2json.h
-2
@@ -18,8 +18,6 @@
18
19 #include "web/server/web_client.h"
20
21 -#define HOSTNAME_MAX 1024
22 -
21 void rrd_stats_api_v1_chart(RRDSET *st, BUFFER *wb);
22
23 int data_query_execute(ONEWAYALLOC *owa, BUFFER *wb, struct query_target *qt, time_t *latest_timestamp);