@cryptotaxi247 / netdata-1 / commits / 66c854601

Re-write of SSL support in Netdata; restoration of SIGCHLD; detection of stale plugins; streaming improvements (#15113)

* add information about streaming connections to /api/v2/nodes; reset defer time when sender or receivers connect or disconnect * make each streaming destination respect its SSL settings * to not send SSL traffic over non-SSL connection * keep track of outgoing streaming connection attempts * retry SSL reads when SSL_read() returns SSL_ERROR_WANT_READ * Revert "retry SSL reads when SSL_read() returns SSL_ERROR_WANT_READ" This reverts commit 14c858677c6f2d3b08c94f298e2f45ecdb74c801. * cleanup SSL connections properly * initialize SSL in rpt before takeover * sender should free SSL when talking to a non-SSL destination * do not shutdown SSL when receiver exits * restore operation of SIGCHLD when the reaper is not enabled * create an fgets function that checks for data and times out * work on error handling of plugins exiting * remove newlines from logs * global call to waitid(), caching the result for netdata_pclose() to process * receiver tid * parser timeouts in 2 minutes instead of 10 * fix crash when UUID is NULL in SQLite * abstract sqlite3 parsing for uuid and text * write proper ssl errors on read and write * fix for SSL_ERROR_WANT_RETRY_VERIFY * SSL WANT per function * unified SSL error logging * fix compilation warning * additional logging about parser cleanup * streaming parser should call the pluginsd parser cleanup * SSL error handling work * SSL initialization unification * check for pending data when receiving SSL response with timeout * macro to check if an SSL connection has been established * remove SSL_pending() * check for SSL macros * use SSL_peek() to find if there is a response * SSL renames * more SSL renames & cleanup * rrdpush ssl connection function * abstract all SSL functions into security.c * keep track of SSL connections and always attempt to use SSL read/write when on SSL connection * signal openssl to skip certificate validation when configured to do so * better SSL error handling and logging * SSL code cleanup * SSL retry on SSL_connect and SSL_accept * SSL provide default return value for old compilers * SSL read/write functions emulate system read/write functions * fix receive/send timeout and switch from SSL_peek() to SSL_pending() * remove SSL_pending() * removed sender auto-retry and debug info for initial recevier response * ssl skip certificate verification config for web server * ssl errors log ip and port of the peer * keep ssl with web_client for its whole lifetime * thread safe socket peers to text * use error_limit() for common ssl errors * cleanup * more cleanup * coverity fixes * ssl error logs include both local and remote ip/port info * remove obsolete code

Costa Tsaousis committed Jun 7, 2023 at 21:10 UTC 66c85460199dbf65aad09cdfcdbae25c6bde265b
35 files changed +1174 -802
aclk/https_client.c
+1 -1
@@ -528,7 +528,7 @@ int https_request(https_req_t *request, https_req_response_t *response) {
528 }
529 ctx->request = request;
530
531 - ctx->ssl_ctx = security_initialize_openssl_client();
531 + ctx->ssl_ctx = netdata_ssl_create_client_ctx(0);
532 if (ctx->ssl_ctx==NULL) {
533 error("Cannot allocate SSL context");
534 goto exit_sock;
collectors/plugins.d/plugins_d.c
+1 -1
@@ -72,7 +72,7 @@ static void pluginsd_worker_thread_cleanup(void *arg)
72 info("PLUGINSD: 'host:%s', waiting for data collection child process pid %d to exit...",
73 rrdhost_hostname(cd->host), pid);
74
75 - waitid(P_PID, (id_t)pid, &info, WEXITED);
75 + netdata_waitid(P_PID, (id_t)pid, &info, WEXITED);
76 }
77 }
78 }
collectors/plugins.d/plugins_d.h
+1
@@ -87,6 +87,7 @@ struct plugind {
87 extern struct plugind *pluginsd_root;
88
89 size_t pluginsd_process(RRDHOST *host, struct plugind *cd, FILE *fp_plugin_input, FILE *fp_plugin_output, int trust_durations);
90 +void pluginsd_process_thread_cleanup(void *ptr);
91
92 size_t pluginsd_initialize_plugin_directories();
93
collectors/plugins.d/pluginsd_parser.c
+17 -13
@@ -11,10 +11,10 @@ static int send_to_plugin(const char *txt, void *data) {
11 return 0;
12
13 #ifdef ENABLE_HTTPS
14 - struct netdata_ssl *ssl = parser->ssl_output;
14 + NETDATA_SSL *ssl = parser->ssl_output;
15 if(ssl) {
16 - if(ssl->conn && ssl->flags == NETDATA_SSL_HANDSHAKE_COMPLETE)
17 - return (int)netdata_ssl_write(ssl->conn, (void *)txt, strlen(txt));
16 + if(SSL_connection(ssl))
17 + return (int)netdata_ssl_write(ssl, (void *)txt, strlen(txt));
18
19 error("PLUGINSD: cannot send command (SSL)");
20 return -1;
@@ -108,11 +108,12 @@ void pluginsd_rrdset_cleanup(RRDSET *st) {
108 st->pluginsd.pos = 0;
109 }
110
111 -static inline void pluginsd_set_chart_from_parent(void *user, RRDSET *st, const char *keyword) {
111 +static inline void pluginsd_unlock_previous_chart(void *user, const char *keyword, bool stale) {
112 PARSER_USER_OBJECT *u = (PARSER_USER_OBJECT *) user;
113
114 if(unlikely(pluginsd_unlock_rrdset_data_collection(user))) {
115 - error("PLUGINSD: 'host:%s/chart:%s/' stale data collection lock found during %s; it has been unlocked",
115 + if(stale)
116 + error("PLUGINSD: 'host:%s/chart:%s/' stale data collection lock found during %s; it has been unlocked",
117 rrdhost_hostname(u->st->rrdhost), rrdset_id(u->st), keyword);
118 }
119
@@ -120,9 +121,16 @@ static inline void pluginsd_set_chart_from_parent(void *user, RRDSET *st, const
121 ml_chart_update_end(u->st);
122 u->v2.ml_locked = false;
123
123 - error("PLUGINSD: 'host:%s/chart:%s/' stale ML lock found during %s, it has been unlocked",
124 + if(stale)
125 + error("PLUGINSD: 'host:%s/chart:%s/' stale ML lock found during %s, it has been unlocked",
126 rrdhost_hostname(u->st->rrdhost), rrdset_id(u->st), keyword);
127 }
128 +}
129 +
130 +static inline void pluginsd_set_chart_from_parent(void *user, RRDSET *st, const char *keyword) {
131 + PARSER_USER_OBJECT *u = (PARSER_USER_OBJECT *) user;
132 +
133 + pluginsd_unlock_previous_chart(user, keyword, true);
134
135 if(st) {
136 size_t dims = dictionary_entries(st->rrddim_root_index);
@@ -1783,12 +1791,7 @@ PARSER_RC pluginsd_end_v2(char **words __maybe_unused, size_t num_words __maybe_
1791 // ------------------------------------------------------------------------
1792 // unblock data collection
1793
1786 - ml_chart_update_end(st);
1787 - u->v2.ml_locked = false;
1788 -
1789 - timing_step(TIMING_STEP_END2_ML);
1790 -
1791 - pluginsd_unlock_rrdset_data_collection(user);
1794 + pluginsd_unlock_previous_chart(user, PLUGINSD_KEYWORD_END_V2, false);
1795 rrdcontext_collected_rrdset(st);
1796 store_metric_collection_completed();
1797
@@ -1823,13 +1826,14 @@ PARSER_RC pluginsd_end_v2(char **words __maybe_unused, size_t num_words __maybe_
1826 return PARSER_RC_OK;
1827 }
1828
1826 -static void pluginsd_process_thread_cleanup(void *ptr) {
1829 +void pluginsd_process_thread_cleanup(void *ptr) {
1830 PARSER *parser = (PARSER *)ptr;
1831
1832 pluginsd_cleanup_v2(parser->user);
1833 pluginsd_host_define_cleanup(parser->user);
1834
1835 rrd_collector_finished();
1836 +
1837 parser_destroy(parser);
1838 }
1839
collectors/tc.plugin/plugin_tc.c
+1 -1
@@ -864,7 +864,7 @@ static void tc_main_cleanup(void *ptr) {
864 siginfo_t info;
865
866 collector_info("TC: waiting for tc plugin child process pid %d to exit...", tc_child_pid);
867 - waitid(P_PID, (id_t) tc_child_pid, &info, WEXITED);
867 + netdata_waitid(P_PID, (id_t) tc_child_pid, &info, WEXITED);
868 }
869
870 tc_child_pid = 0;
daemon/analytics.c
+6 -2
@@ -375,8 +375,12 @@ void analytics_https(void)
375 BUFFER *b = buffer_create(30, NULL);
376 #ifdef ENABLE_HTTPS
377 analytics_exporting_connectors_ssl(b);
378 - buffer_strcat(b, netdata_ssl_client_ctx && rrdhost_flag_check(localhost, RRDHOST_FLAG_RRDPUSH_SENDER_CONNECTED) && localhost->sender->ssl.flags == NETDATA_SSL_HANDSHAKE_COMPLETE ? "streaming|" : "|");
379 - buffer_strcat(b, netdata_ssl_srv_ctx ? "web" : "");
378 +
379 + buffer_strcat(b, netdata_ssl_streaming_sender_ctx &&
380 + rrdhost_flag_check(localhost, RRDHOST_FLAG_RRDPUSH_SENDER_CONNECTED) &&
381 + SSL_connection(&localhost->sender->ssl) ? "streaming|" : "|");
382 +
383 + buffer_strcat(b, netdata_ssl_web_server_ctx ? "web" : "");
384 #else
385 buffer_strcat(b, "||");
386 #endif
daemon/main.c
+2 -2
@@ -482,7 +482,7 @@ void netdata_cleanup_and_exit(int ret) {
482
483 #ifdef ENABLE_HTTPS
484 delta_shutdown_time("free openssl structures");
485 - security_clean_openssl();
485 + netdata_ssl_cleanup();
486 #endif
487
488 delta_shutdown_time("remove incomplete shutdown file");
@@ -834,7 +834,7 @@ static void security_init(){
834 tls_version = config_get(CONFIG_SECTION_WEB, "tls version", "1.3");
835 tls_ciphers = config_get(CONFIG_SECTION_WEB, "tls ciphers", "none");
836
837 - security_openssl_library();
837 + netdata_ssl_initialize_openssl();
838 }
839 #endif
840
daemon/signals.c
+33 -65
@@ -2,8 +2,6 @@
2
3 #include "common.h"
4
5 -static int reaper_enabled = 0;
6 -
5 typedef enum signal_action {
6 NETDATA_SIGNAL_END_OF_LIST,
7 NETDATA_SIGNAL_IGNORE,
@@ -78,16 +76,6 @@ void signals_init(void) {
76 struct sigaction sa;
77 sa.sa_flags = 0;
78
81 - // Enable process tracking / reaper if running as init (pid == 1).
82 - // This prevents zombie processes when running in a container.
83 - if (getpid() == 1) {
84 - info("SIGNAL: Enabling reaper");
85 - netdata_popen_tracking_init();
86 - reaper_enabled = 1;
87 - } else {
88 - info("SIGNAL: Not enabling reaper");
89 - }
90 -
79 // ignore all signals while we run in a signal handler
80 sigfillset(&sa.sa_mask);
81
@@ -97,10 +85,6 @@ void signals_init(void) {
85 case NETDATA_SIGNAL_IGNORE:
86 sa.sa_handler = SIG_IGN;
87 break;
100 - case NETDATA_SIGNAL_CHILD:
101 - if (reaper_enabled == 0)
102 - continue;
103 - // FALLTHROUGH
88 default:
89 sa.sa_handler = signal_handler;
90 break;
@@ -115,9 +99,6 @@ void signals_restore_SIGCHLD(void)
99 {
100 struct sigaction sa;
101
118 - if (reaper_enabled == 0)
119 - return;
120 -
102 sa.sa_flags = 0;
103 sigfillset(&sa.sa_mask);
104 sa.sa_handler = signal_handler;
@@ -137,9 +118,6 @@ void signals_reset(void) {
118 if(sigaction(signals_waiting[i].signo, &sa, NULL) == -1)
119 error("SIGNAL: Failed to reset signal handler for: %s", signals_waiting[i].name);
120 }
140 -
141 - if (reaper_enabled == 1)
142 - netdata_popen_tracking_cleanup();
121 }
122
123 // reap_child reaps the child identified by pid.
@@ -147,39 +125,42 @@ static void reap_child(pid_t pid) {
125 siginfo_t i;
126
127 errno = 0;
150 - debug(D_CHILDS, "SIGNAL: Reaping pid: %d...", pid);
151 - if (waitid(P_PID, (id_t)pid, &i, WEXITED|WNOHANG) == -1) {
128 + debug(D_CHILDS, "SIGNAL: reap_child(%d)...", pid);
129 + if (netdata_waitid(P_PID, (id_t)pid, &i, WEXITED|WNOHANG) == -1) {
130 if (errno != ECHILD)
153 - error("SIGNAL: Failed to wait for: %d", pid);
131 + error("SIGNAL: waitid(%d): failed to wait for child", pid);
132 else
155 - debug(D_CHILDS, "SIGNAL: Already reaped: %d", pid);
133 + info("SIGNAL: waitid(%d): failed - it seems the child is already reaped", pid);
134 return;
157 - } else if (i.si_pid == 0) {
135 + }
136 + else if (i.si_pid == 0) {
137 // Process didn't exit, this shouldn't happen.
138 + error("SIGNAL: waitid(%d): reports pid 0 - child has not exited", pid);
139 return;
140 }
141
142 switch (i.si_code) {
163 - case CLD_EXITED:
164 - debug(D_CHILDS, "SIGNAL: Child %d exited: %d", pid, i.si_status);
165 - break;
166 - case CLD_KILLED:
167 - debug(D_CHILDS, "SIGNAL: Child %d killed by signal: %d", pid, i.si_status);
168 - break;
169 - case CLD_DUMPED:
170 - debug(D_CHILDS, "SIGNAL: Child %d dumped core by signal: %d", pid, i.si_status);
171 - break;
172 - case CLD_STOPPED:
173 - debug(D_CHILDS, "SIGNAL: Child %d stopped by signal: %d", pid, i.si_status);
174 - break;
175 - case CLD_TRAPPED:
176 - debug(D_CHILDS, "SIGNAL: Child %d trapped by signal: %d", pid, i.si_status);
177 - break;
178 - case CLD_CONTINUED:
179 - debug(D_CHILDS, "SIGNAL: Child %d continued by signal: %d", pid, i.si_status);
180 - break;
181 - default:
182 - debug(D_CHILDS, "SIGNAL: Child %d gave us a SIGCHLD with code %d and status %d.", pid, i.si_code, i.si_status);
143 + case CLD_EXITED:
144 + info("SIGNAL: reap_child(%d) exited with code: %d", pid, i.si_status);
145 + break;
146 + case CLD_KILLED:
147 + info("SIGNAL: reap_child(%d) killed by signal: %d", pid, i.si_status);
148 + break;
149 + case CLD_DUMPED:
150 + info("SIGNAL: reap_child(%d) dumped core by signal: %d", pid, i.si_status);
151 + break;
152 + case CLD_STOPPED:
153 + info("SIGNAL: reap_child(%d) stopped by signal: %d", pid, i.si_status);
154 + break;
155 + case CLD_TRAPPED:
156 + info("SIGNAL: reap_child(%d) trapped by signal: %d", pid, i.si_status);
157 + break;
158 + case CLD_CONTINUED:
159 + info("SIGNAL: reap_child(%d) continued by signal: %d", pid, i.si_status);
160 + break;
161 + default:
162 + info("SIGNAL: reap_child(%d) gave us a SIGCHLD with code %d and status %d.", pid, i.si_code, i.si_status);
163 + break;
164 }
165 }
166
@@ -187,25 +168,13 @@ static void reap_child(pid_t pid) {
168 static void reap_children() {
169 siginfo_t i;
170
190 - while (1 == 1) {
191 - // Identify which process caused the signal so we can determine
192 - // if we need to reap a re-parented process.
171 + while(1) {
172 i.si_pid = 0;
194 - if (waitid(P_ALL, (id_t)0, &i, WEXITED|WNOHANG|WNOWAIT) == -1) {
195 - if (errno != ECHILD) // This shouldn't happen with WNOHANG but does.
196 - error("SIGNAL: Failed to wait");
197 - return;
198 - } else if (i.si_pid == 0) {
199 - // No child exited.
173 + if (netdata_waitid(P_ALL, (id_t)0, &i, WEXITED|WNOHANG|WNOWAIT) == -1 || i.si_pid == 0)
174 + // nothing to do
175 return;
201 - } else if (netdata_popen_tracking_pid_shoud_be_reaped(i.si_pid) == 0) {
202 - // myp managed, sleep for a short time to avoid busy wait while
203 - // this is handled by myp.
204 - usleep(10000);
205 - } else {
206 - // Unknown process, likely a re-parented child, reap it.
207 - reap_child(i.si_pid);
208 - }
176 +
177 + reap_child(i.si_pid);
178 }
179 }
180
@@ -267,7 +236,6 @@ void signals_handle(void) {
236 break;
237
238 case NETDATA_SIGNAL_CHILD:
270 - debug(D_CHILDS, "SIGNAL: Received %s. Reaping...", name);
239 reap_children();
240 break;
241
database/contexts/api_v2.c
+46 -2
@@ -352,6 +352,7 @@ static ssize_t rrdcontext_to_json_v2_add_host(void *data, RRDHOST *host, bool qu
352 buffer_json_member_add_string_or_empty(wb, "osVersion", host->system_info->host_os_version);
353 }
354
355 + time_t now = now_realtime_sec();
356 buffer_json_member_add_object(wb, "status");
357
358 size_t receiver_hops = host->system_info ? host->system_info->hops : (host == localhost) ? 0 : 1;
@@ -359,12 +360,55 @@ static ssize_t rrdcontext_to_json_v2_add_host(void *data, RRDHOST *host, bool qu
360 buffer_json_member_add_uint64(wb, "hops", receiver_hops);
361 buffer_json_member_add_boolean(wb, "online", host == localhost || !rrdhost_flag_check(host, RRDHOST_FLAG_ORPHAN | RRDHOST_FLAG_RRDPUSH_RECEIVER_DISCONNECTED));
362 buffer_json_member_add_boolean(wb, "replicating", rrdhost_receiver_replicating_charts(host));
363 + if(host != localhost && host->receiver) {
364 + buffer_json_member_add_object(wb, "source");
365 +
366 + char buf[1024 + 1];
367 + snprintfz(buf, 1024, "%s:%s", host->receiver->client_ip ? host->receiver->client_ip : "", host->receiver->client_port ? host->receiver->client_port : "");
368 + buffer_json_member_add_string(wb, "connection", buf);
369 + stream_capabilities_to_json_array(wb, host->receiver->capabilities, "capabilities");
370 +
371 + buffer_json_object_close(wb);
372 + }
373 buffer_json_object_close(wb); // collection
374
375 + bool sender_connected = rrdhost_flag_check(host, RRDHOST_FLAG_RRDPUSH_SENDER_CONNECTED);
376 buffer_json_member_add_object(wb, "streaming");
377 buffer_json_member_add_uint64(wb, "hops", host->sender ? host->sender->hops : receiver_hops + 1);
366 - buffer_json_member_add_boolean(wb, "online", rrdhost_flag_check(host, RRDHOST_FLAG_RRDPUSH_SENDER_CONNECTED));
367 - buffer_json_member_add_boolean(wb, "replicating", rrdhost_sender_replicating_charts(host));
378 + buffer_json_member_add_boolean(wb, "online", sender_connected);
379 + buffer_json_member_add_boolean(wb, "replicating", sender_connected && rrdhost_sender_replicating_charts(host));
380 +
381 + if(host->sender) {
382 + buffer_json_member_add_object(wb, "destination");
383 + buffer_json_member_add_string(wb, "connected_to", sender_connected ? host->sender->connected_to : "");
384 + stream_capabilities_to_json_array(wb, sender_connected ? host->sender->capabilities : 0, "capabilities");
385 +
386 + buffer_json_member_add_array(wb, "candidates");
387 + struct rrdpush_destinations *d;
388 + for(d = host->destinations ; d ; d = d->next) {
389 + buffer_json_add_array_item_object(wb);
390 +
391 + if(d->ssl) {
392 + char buf[1024 + 1];
393 + snprintfz(buf, 1024, "%s:SSL", string2str(d->destination));
394 + buffer_json_member_add_string(wb, "destination", buf);
395 + }
396 + else
397 + buffer_json_member_add_string(wb, "destination", string2str(d->destination));
398 +
399 + buffer_json_member_add_time_t(wb, "last_check", d->last_attempt);
400 + buffer_json_member_add_time_t(wb, "last_check_secs_ago", now - d->last_attempt);
401 + buffer_json_member_add_string(wb, "last_error", d->last_error);
402 + buffer_json_member_add_string(wb, "last_handshake", stream_handshake_error_to_string(d->last_handshake));
403 + buffer_json_member_add_time_t(wb, "next_check", d->postpone_reconnection_until);
404 + buffer_json_member_add_time_t(wb, "next_check_in_secs", (d->postpone_reconnection_until > now) ? d->postpone_reconnection_until - now : 0);
405 + buffer_json_object_close(wb);
406 + }
407 + buffer_json_array_close(wb);
408 +
409 + buffer_json_object_close(wb); // destination
410 + }
411 +
412 buffer_json_object_close(wb); // streaming
413
414 buffer_json_object_close(wb); // status
database/rrdhost.c
+1 -2
@@ -257,8 +257,7 @@ static void rrdhost_initialize_rrdpush_sender(RRDHOST *host,
257 rrdhost_streaming_sender_structures_init(host);
258
259 #ifdef ENABLE_HTTPS
260 - host->sender->ssl.conn = NULL;
261 - host->sender->ssl.flags = NETDATA_SSL_START;
260 + host->sender->ssl = NETDATA_SSL_UNSET_CONNECTION;
261 #endif
262
263 host->rrdpush_send_destination = strdupz(rrdpush_destination);
exporting/clean_connectors.c
+1 -4
@@ -68,8 +68,7 @@ void simple_connector_cleanup(struct instance *instance)
68 }
69
70 #ifdef ENABLE_HTTPS
71 - if (simple_connector_data->conn)
72 - SSL_free(simple_connector_data->conn);
71 + netdata_ssl_close(&simple_connector_data->ssl);
72 #endif
73
74 freez(simple_connector_data);
@@ -80,6 +79,4 @@ void simple_connector_cleanup(struct instance *instance)
79
80 info("EXPORTING: instance %s exited", instance->config.name);
81 instance->exited = 1;
83 -
84 - return;
82 }
exporting/exporting_engine.c
+1 -1
@@ -10,7 +10,7 @@ void analytics_exporting_connectors_ssl(BUFFER *b)
10 if (netdata_ssl_exporting_ctx) {
11 for (struct instance *instance = engine->instance_root; instance; instance = instance->next) {
12 struct simple_connector_data *connector_specific_data = instance->connector_specific_data;
13 - if (connector_specific_data->flags == NETDATA_SSL_HANDSHAKE_COMPLETE) {
13 + if (SSL_connection(&connector_specific_data->ssl)) {
14 buffer_strcat(b, "exporting");
15 break;
16 }
exporting/exporting_engine.h
+1 -2
@@ -126,8 +126,7 @@ struct simple_connector_data {
126 struct simple_connector_buffer *last_buffer;
127
128 #ifdef ENABLE_HTTPS
129 - SSL *conn; //SSL connection
130 - int flags; //The flags for SSL connection
129 + NETDATA_SSL ssl;
130 #endif
131 };
132
exporting/graphite/graphite.c
+2 -3
@@ -20,10 +20,9 @@ int init_graphite_instance(struct instance *instance)
20 instance->connector_specific_data = connector_specific_data;
21
22 #ifdef ENABLE_HTTPS
23 - connector_specific_data->flags = NETDATA_SSL_START;
24 - connector_specific_data->conn = NULL;
23 + connector_specific_data->ssl = NETDATA_SSL_UNSET_CONNECTION;
24 if (instance->config.options & EXPORTING_OPTION_USE_TLS) {
26 - security_start_ssl(NETDATA_SSL_CONTEXT_EXPORTING);
25 + netdata_ssl_initialize_ctx(NETDATA_SSL_EXPORTING_CTX);
26 }
27 #endif
28
exporting/json/json.c
+2 -3
@@ -71,10 +71,9 @@ int init_json_http_instance(struct instance *instance)
71 instance->connector_specific_data = connector_specific_data;
72
73 #ifdef ENABLE_HTTPS
74 - connector_specific_data->flags = NETDATA_SSL_START;
75 - connector_specific_data->conn = NULL;
74 + connector_specific_data->ssl = NETDATA_SSL_UNSET_CONNECTION;
75 if (instance->config.options & EXPORTING_OPTION_USE_TLS) {
77 - security_start_ssl(NETDATA_SSL_CONTEXT_EXPORTING);
76 + netdata_ssl_initialize_ctx(NETDATA_SSL_EXPORTING_CTX);
77 }
78 #endif
79
exporting/opentsdb/opentsdb.c
+4 -6
@@ -21,10 +21,9 @@ int init_opentsdb_telnet_instance(struct instance *instance)
21 instance->connector_specific_data = connector_specific_data;
22
23 #ifdef ENABLE_HTTPS
24 - connector_specific_data->flags = NETDATA_SSL_START;
25 - connector_specific_data->conn = NULL;
24 + connector_specific_data->ssl = NETDATA_SSL_UNSET_CONNECTION;
25 if (instance->config.options & EXPORTING_OPTION_USE_TLS) {
27 - security_start_ssl(NETDATA_SSL_CONTEXT_EXPORTING);
26 + netdata_ssl_initialize_ctx(NETDATA_SSL_EXPORTING_CTX);
27 }
28 #endif
29
@@ -77,10 +76,9 @@ int init_opentsdb_http_instance(struct instance *instance)
76
77 struct simple_connector_data *connector_specific_data = callocz(1, sizeof(struct simple_connector_data));
78 #ifdef ENABLE_HTTPS
80 - connector_specific_data->flags = NETDATA_SSL_START;
81 - connector_specific_data->conn = NULL;
79 + connector_specific_data->ssl = NETDATA_SSL_UNSET_CONNECTION;
80 if (instance->config.options & EXPORTING_OPTION_USE_TLS) {
83 - security_start_ssl(NETDATA_SSL_CONTEXT_EXPORTING);
81 + netdata_ssl_initialize_ctx(NETDATA_SSL_EXPORTING_CTX);
82 }
83 #endif
84 instance->connector_specific_data = connector_specific_data;
exporting/prometheus/remote_write/remote_write.c
+2 -3
@@ -115,10 +115,9 @@ int init_prometheus_remote_write_instance(struct instance *instance)
115 instance->connector_specific_data = simple_connector_data;
116
117 #ifdef ENABLE_HTTPS
118 - simple_connector_data->flags = NETDATA_SSL_START;
119 - simple_connector_data->conn = NULL;
118 + simple_connector_data->ssl = NETDATA_SSL_UNSET_CONNECTION;
119 if (instance->config.options & EXPORTING_OPTION_USE_TLS) {
121 - security_start_ssl(NETDATA_SSL_CONTEXT_EXPORTING);
120 + netdata_ssl_initialize_ctx(NETDATA_SSL_EXPORTING_CTX);
121 }
122 #endif
123
exporting/send_data.c
+28 -77
@@ -81,37 +81,11 @@ void simple_connector_receive_response(int *sock, struct instance *instance)
81 while (*sock != -1 && errno != EWOULDBLOCK) {
82 ssize_t r;
83 #ifdef ENABLE_HTTPS
84 - if (exporting_tls_is_enabled(instance->config.type, options) &&
85 - connector_specific_data->conn &&
86 - connector_specific_data->flags == NETDATA_SSL_HANDSHAKE_COMPLETE) {
87 - r = (ssize_t)SSL_read(connector_specific_data->conn,
88 - &response->buffer[response->len],
89 - (int) (response->size - response->len));
90 -
91 - if (likely(r > 0)) {
92 - // we received some data
93 - response->len += r;
94 - stats->received_bytes += r;
95 - stats->receptions++;
96 - continue;
97 - } else {
98 - int sslerrno = SSL_get_error(connector_specific_data->conn, (int) r);
99 - u_long sslerr = ERR_get_error();
100 - char buf[256];
101 - switch (sslerrno) {
102 - case SSL_ERROR_WANT_READ:
103 - case SSL_ERROR_WANT_WRITE:
104 - goto endloop;
105 - default:
106 - ERR_error_string_n(sslerr, buf, sizeof(buf));
107 - error("SSL error (%s)",
108 - ERR_error_string((long)SSL_get_error(connector_specific_data->conn, (int)r), NULL));
109 - goto endloop;
110 - }
111 - }
112 - } else {
84 + if (SSL_connection(&connector_specific_data->ssl))
85 + r = netdata_ssl_read(&connector_specific_data->ssl, &response->buffer[response->len],
86 + (int) (response->size - response->len));
87 + else
88 r = recv(*sock, &response->buffer[response->len], response->size - response->len, MSG_DONTWAIT);
114 - }
89 #else
90 r = recv(*sock, &response->buffer[response->len], response->size - response->len, MSG_DONTWAIT);
91 #endif
@@ -120,11 +94,13 @@ void simple_connector_receive_response(int *sock, struct instance *instance)
94 response->len += r;
95 stats->received_bytes += r;
96 stats->receptions++;
123 - } else if (r == 0) {
97 + }
98 + else if (r == 0) {
99 error("EXPORTING: '%s' closed the socket", instance->config.destination);
100 close(*sock);
101 *sock = -1;
127 - } else {
102 + }
103 + else {
104 // failed to receive data
105 if (errno != EAGAIN && errno != EWOULDBLOCK) {
106 error("EXPORTING: cannot receive data from '%s'.", instance->config.destination);
@@ -135,9 +111,6 @@ void simple_connector_receive_response(int *sock, struct instance *instance)
111 break;
112 #endif
113 }
138 -#ifdef ENABLE_HTTPS
139 -endloop:
140 -#endif
114
115 // if we received data, process them
116 if (buffer_strlen(response))
@@ -174,14 +147,16 @@ void simple_connector_send_buffer(
147 size_t buffer_len = buffer_strlen(buffer);
148
149 #ifdef ENABLE_HTTPS
177 - if (exporting_tls_is_enabled(instance->config.type, options) &&
178 - connector_specific_data->conn &&
179 - connector_specific_data->flags == NETDATA_SSL_HANDSHAKE_COMPLETE) {
150 + if (SSL_connection(&connector_specific_data->ssl)) {
151 +
152 if (header_len)
181 - header_sent_bytes = (ssize_t)SSL_write(connector_specific_data->conn, buffer_tostring(header), header_len);
153 + header_sent_bytes = netdata_ssl_write(&connector_specific_data->ssl, buffer_tostring(header), header_len);
154 +
155 if ((size_t)header_sent_bytes == header_len)
183 - buffer_sent_bytes = (ssize_t)SSL_write(connector_specific_data->conn, buffer_tostring(buffer), buffer_len);
184 - } else {
156 + buffer_sent_bytes = netdata_ssl_write(&connector_specific_data->ssl, buffer_tostring(buffer), buffer_len);
157 +
158 + }
159 + else {
160 if (header_len)
161 header_sent_bytes = send(*sock, buffer_tostring(header), header_len, flags);
162 if ((size_t)header_sent_bytes == header_len)
@@ -326,43 +301,19 @@ void simple_connector_worker(void *instance_p)
301 if (sock_delnonblock(sock) < 0)
302 error("Exporting cannot remove the non-blocking flag from socket %d", sock);
303
329 - if (connector_specific_data->conn == NULL) {
330 - connector_specific_data->conn = SSL_new(netdata_ssl_exporting_ctx);
331 - if (connector_specific_data->conn == NULL) {
332 - error("Failed to allocate SSL structure to socket %d.", sock);
333 - connector_specific_data->flags = NETDATA_SSL_NO_HANDSHAKE;
334 - }
335 - } else {
336 - SSL_clear(connector_specific_data->conn);
337 - }
304 + if(netdata_ssl_open(&connector_specific_data->ssl, netdata_ssl_exporting_ctx, sock)) {
305 + if(netdata_ssl_connect(&connector_specific_data->ssl)) {
306 + info("Exporting established a SSL connection.");
307 +
308 + struct timeval tv;
309 + tv.tv_sec = timeout.tv_sec / 4;
310 + tv.tv_usec = 0;
311 +
312 + if (!tv.tv_sec)
313 + tv.tv_sec = 2;
314
339 - if (connector_specific_data->conn) {
340 - if (SSL_set_fd(connector_specific_data->conn, sock) != 1) {
341 - error("Failed to set the socket to the SSL on socket fd %d.", sock);
342 - connector_specific_data->flags = NETDATA_SSL_NO_HANDSHAKE;
343 - } else {
344 - connector_specific_data->flags = NETDATA_SSL_HANDSHAKE_COMPLETE;
345 - SSL_set_connect_state(connector_specific_data->conn);
346 - int err = SSL_connect(connector_specific_data->conn);
347 - if (err != 1) {
348 - err = SSL_get_error(connector_specific_data->conn, err);
349 - error(
350 - "SSL cannot connect with the server: %s ",
351 - ERR_error_string((long)SSL_get_error(connector_specific_data->conn, err), NULL));
352 - connector_specific_data->flags = NETDATA_SSL_NO_HANDSHAKE;
353 - } else {
354 - info("Exporting established a SSL connection.");
355 -
356 - struct timeval tv;
357 - tv.tv_sec = timeout.tv_sec / 4;
358 - tv.tv_usec = 0;
359 -
360 - if (!tv.tv_sec)
361 - tv.tv_sec = 2;
362 -
363 - if (setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (const char *)&tv, sizeof(tv)))
364 - error("Cannot set timeout to socket %d, this can block communication", sock);
365 - }
315 + if (setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (const char *)&tv, sizeof(tv)))
316 + error("Cannot set timeout to socket %d, this can block communication", sock);
317 }
318 }
319 }
libnetdata/parser/parser.c
+66 -15
@@ -1,4 +1,6 @@
1 // SPDX-License-Identifier: GPL-3.0-or-later
2 +#include <poll.h>
3 +#include <stdio.h>
4
5 #include "parser.h"
6 #include "collectors/plugins.d/pluginsd_parser.h"
@@ -124,26 +126,77 @@ void parser_destroy(PARSER *parser)
126 *
127 */
128
127 -int parser_next(PARSER *parser, char *buffer, size_t buffer_size)
128 -{
129 - char *tmp = fgets(buffer, (int)buffer_size, (FILE *)parser->fp_input);
129 +typedef enum {
130 + PARSER_FGETS_RESULT_OK,
131 + PARSER_FGETS_RESULT_TIMEOUT,
132 + PARSER_FGETS_RESULT_ERROR,
133 + PARSER_FGETS_RESULT_EOF,
134 +} PARSER_FGETS_RESULT;
135 +
136 +static inline PARSER_FGETS_RESULT parser_fgets(char *s, int size, FILE *stream) {
137 + errno = 0;
138 +
139 + struct pollfd fds[1];
140 + int timeout_msecs = 2 * 60 * MSEC_PER_SEC;
141 +
142 + fds[0].fd = fileno(stream);
143 + fds[0].events = POLLIN;
144 +
145 + int ret = poll(fds, 1, timeout_msecs);
146
131 - if (unlikely(!tmp)) {
132 - if (feof((FILE *)parser->fp_input))
133 - error("PARSER: read failed: end of file");
147 + if (ret > 0) {
148 + /* There is data to read */
149 + if (fds[0].revents & POLLIN) {
150 + char *tmp = fgets(s, size, stream);
151
135 - else if (ferror((FILE *)parser->fp_input))
136 - error("PARSER: read failed: input error");
152 + if(unlikely(!tmp)) {
153 + if (feof(stream)) {
154 + error("PARSER: read failed: end of file.");
155 + return PARSER_FGETS_RESULT_EOF;
156 + }
157
138 - else
139 - error("PARSER: read failed: unknown error");
158 + else if (ferror(stream)) {
159 + error("PARSER: read failed: input error.");
160 + return PARSER_FGETS_RESULT_ERROR;
161 + }
162
141 - return 1;
163 + error("PARSER: read failed: unknown error.");
164 + return PARSER_FGETS_RESULT_ERROR;
165 + }
166 +
167 + return PARSER_FGETS_RESULT_OK;
168 + }
169 + else if(fds[0].revents & POLLERR) {
170 + error("PARSER: read failed: POLLERR.");
171 + return PARSER_FGETS_RESULT_ERROR;
172 + }
173 + else if(fds[0].revents & POLLHUP) {
174 + error("PARSER: read failed: POLLHUP.");
175 + return PARSER_FGETS_RESULT_ERROR;
176 + }
177 + else if(fds[0].revents & POLLNVAL) {
178 + error("PARSER: read failed: POLLNVAL.");
179 + return PARSER_FGETS_RESULT_ERROR;
180 + }
181 +
182 + error("PARSER: poll() returned positive number, but POLLIN|POLLERR|POLLHUP|POLLNVAL are not set.");
183 + return PARSER_FGETS_RESULT_ERROR;
184 + }
185 + else if (ret == 0) {
186 + error("PARSER: timeout while waiting for data.");
187 + return PARSER_FGETS_RESULT_TIMEOUT;
188 }
189
144 - return 0;
190 + error("PARSER: poll() failed with code %d.", ret);
191 + return PARSER_FGETS_RESULT_ERROR;
192 }
193
194 +int parser_next(PARSER *parser, char *buffer, size_t buffer_size) {
195 + if(likely(parser_fgets(buffer, (int)buffer_size, (FILE *)parser->fp_input) == PARSER_FGETS_RESULT_OK))
196 + return 0;
197 +
198 + return 1;
199 +}
200
201 /*
202 * Takes an initialized parser object that has an unprocessed entry (by calling parser_next)
@@ -202,7 +255,6 @@ inline int parser_action(PARSER *parser, char *input)
255 else
256 rc = PARSER_RC_ERROR;
257
205 -#ifdef NETDATA_INTERNAL_CHECKS
258 if(rc == PARSER_RC_ERROR) {
259 BUFFER *wb = buffer_create(PLUGINSD_LINE_MAX, NULL);
260 for(size_t i = 0; i < num_words ;i++) {
@@ -214,12 +266,11 @@ inline int parser_action(PARSER *parser, char *input)
266 buffer_fast_strcat(wb, "\"", 1);
267 }
268
217 - internal_error(true, "PLUGINSD: parser_action('%s') failed on line %zu: { %s } (quotes added to show parsing)",
269 + error("PLUGINSD: parser_action('%s') failed on line %zu: { %s } (quotes added to show parsing)",
270 command, parser->line, buffer_tostring(wb));
271
272 buffer_free(wb);
273 }
222 -#endif
274
275 return (rc == PARSER_RC_ERROR || rc == PARSER_RC_STOP);
276 }
libnetdata/parser/parser.h
+1 -1
@@ -44,7 +44,7 @@ typedef struct parser {
44 FILE *fp_input; // Input source e.g. stream
45 FILE *fp_output; // Stream to send commands to plugin
46 #ifdef ENABLE_HTTPS
47 - struct netdata_ssl *ssl_output;
47 + NETDATA_SSL *ssl_output;
48 #endif
49 void *user; // User defined structure to hold extra state between calls
50 uint32_t flags;
libnetdata/popen/popen.c
+48 -58
@@ -5,11 +5,13 @@
5 // ----------------------------------------------------------------------------
6 // popen with tracking
7
8 -static pthread_mutex_t netdata_popen_tracking_mutex;
9 -static bool netdata_popen_tracking_enabled = false;
8 +static pthread_mutex_t netdata_popen_tracking_mutex = NETDATA_MUTEX_INITIALIZER;
9
10 struct netdata_popen {
11 pid_t pid;
12 + bool reaped;
13 + siginfo_t infop;
14 + int waitid_ret;
15 struct netdata_popen *next;
16 struct netdata_popen *prev;
17 };
@@ -18,29 +20,20 @@ static struct netdata_popen *netdata_popen_root = NULL;
20
21 // myp_add_lock takes the lock if we're tracking.
22 static void netdata_popen_tracking_lock(void) {
21 - if(!netdata_popen_tracking_enabled)
22 - return;
23 -
23 netdata_mutex_lock(&netdata_popen_tracking_mutex);
24 }
25
26 // myp_add_unlock release the lock if we're tracking.
27 static void netdata_popen_tracking_unlock(void) {
29 - if(!netdata_popen_tracking_enabled)
30 - return;
31 -
28 netdata_mutex_unlock(&netdata_popen_tracking_mutex);
29 }
30
31 // myp_add_locked adds pid if we're tracking.
32 // myp_add_lock must have been called previously.
33 static void netdata_popen_tracking_add_pid_unsafe(pid_t pid) {
38 - if(!netdata_popen_tracking_enabled)
39 - return;
40 -
34 struct netdata_popen *mp;
35
43 - mp = mallocz(sizeof(struct netdata_popen));
36 + mp = callocz(1, sizeof(struct netdata_popen));
37 mp->pid = pid;
38
39 DOUBLE_LINKED_LIST_PREPEND_ITEM_UNSAFE(netdata_popen_root, mp, prev, next);
@@ -48,12 +41,9 @@ static void netdata_popen_tracking_add_pid_unsafe(pid_t pid) {
41
42 // myp_del deletes pid if we're tracking.
43 static void netdata_popen_tracking_del_pid(pid_t pid) {
51 - if(!netdata_popen_tracking_enabled)
52 - return;
53 -
44 struct netdata_popen *mp;
45
56 - netdata_mutex_lock(&netdata_popen_tracking_mutex);
46 + netdata_popen_tracking_lock();
47
48 DOUBLE_LINKED_LIST_FOREACH_FORWARD(netdata_popen_root, mp, prev, next) {
49 if(unlikely(mp->pid == pid))
@@ -65,34 +55,15 @@ static void netdata_popen_tracking_del_pid(pid_t pid) {
55 freez(mp);
56 }
57 else
68 - error("Cannot find pid %d.", pid);
69 -
70 - netdata_mutex_unlock(&netdata_popen_tracking_mutex);
71 -}
58 + error("POPEN: Cannot find pid %d.", pid);
59
73 -// netdata_popen_tracking_init() should be called by apps which act as init
74 -// (pid 1) so that processes created by mypopen and mypopene
75 -// are tracked. This enables the reaper to ignore processes
76 -// which will be handled internally, by calling myp_reap, to
77 -// avoid issues with already reaped processes during wait calls.
78 -//
79 -// Callers should call myp_free() to clean up resources.
80 -void netdata_popen_tracking_init(void) {
81 - info("process tracking enabled.");
82 - netdata_popen_tracking_enabled = true;
83 -
84 - if (netdata_mutex_init(&netdata_popen_tracking_mutex) != 0)
85 - fatal("netdata_popen_tracking_init() mutex init failed.");
60 + netdata_popen_tracking_unlock();
61 }
62
63 // myp_free cleans up any resources allocated for process
64 // tracking.
65 void netdata_popen_tracking_cleanup(void) {
91 - if(!netdata_popen_tracking_enabled)
92 - return;
93 -
94 - netdata_mutex_lock(&netdata_popen_tracking_mutex);
95 - netdata_popen_tracking_enabled = false;
66 + netdata_popen_tracking_lock();
67
68 while(netdata_popen_root) {
69 struct netdata_popen *mp = netdata_popen_root;
@@ -100,26 +71,45 @@ void netdata_popen_tracking_cleanup(void) {
71 freez(mp);
72 }
73
103 - netdata_mutex_unlock(&netdata_popen_tracking_mutex);
74 + netdata_popen_tracking_unlock();
75 }
76
106 -// myp_reap returns 1 if pid should be reaped, 0 otherwise.
107 -int netdata_popen_tracking_pid_shoud_be_reaped(pid_t pid) {
108 - if(!netdata_popen_tracking_enabled)
109 - return 0;
77 +int netdata_waitid(idtype_t idtype, id_t id, siginfo_t *infop, int options) {
78 + struct netdata_popen *mp = NULL;
79
111 - netdata_mutex_lock(&netdata_popen_tracking_mutex);
80 + if(idtype == P_PID && id != 0) {
81 + // the caller is asking to waitid() for a specific child pid
82
113 - int ret = 1;
114 - struct netdata_popen *mp;
115 - DOUBLE_LINKED_LIST_FOREACH_FORWARD(netdata_popen_root, mp, prev, next) {
116 - if(unlikely(mp->pid == pid)) {
117 - ret = 0;
118 - break;
83 + netdata_popen_tracking_lock();
84 + DOUBLE_LINKED_LIST_FOREACH_FORWARD(netdata_popen_root, mp, prev, next) {
85 + if(unlikely(mp->pid == (pid_t)id))
86 + break;
87 }
88 +
89 + if(!mp)
90 + netdata_popen_tracking_unlock();
91 }
92
122 - netdata_mutex_unlock(&netdata_popen_tracking_mutex);
93 + int ret;
94 + if(mp && mp->reaped) {
95 + // we have already reaped this child
96 + ret = mp->waitid_ret;
97 + *infop = mp->infop;
98 + }
99 + else {
100 + // we haven't reaped this child yet
101 + ret = waitid(idtype, id, infop, options);
102 +
103 + if(mp && !mp->reaped) {
104 + mp->reaped = true;
105 + mp->infop = *infop;
106 + mp->waitid_ret = ret;
107 + }
108 + }
109 +
110 + if(mp)
111 + netdata_popen_tracking_unlock();
112 +
113 return ret;
114 }
115
@@ -404,7 +394,7 @@ int netdata_pclose(FILE *fp_child_input, FILE *fp_child_output, pid_t pid) {
394
395 errno = 0;
396
407 - ret = waitid(P_PID, (id_t) pid, &info, WEXITED);
397 + ret = netdata_waitid(P_PID, (id_t) pid, &info, WEXITED);
398 netdata_popen_tracking_del_pid(pid);
399
400 if (ret != -1) {
@@ -415,8 +405,12 @@ int netdata_pclose(FILE *fp_child_input, FILE *fp_child_output, pid_t pid) {
405 return(info.si_status);
406
407 case CLD_KILLED:
418 - if(info.si_status == 15) {
419 - info("child pid %d killed by signal %d.", info.si_pid, info.si_status);
408 + if(info.si_status == SIGTERM) {
409 + info("child pid %d killed by SIGTERM", info.si_pid);
410 + return(0);
411 + }
412 + else if(info.si_status == SIGPIPE) {
413 + info("child pid %d killed by SIGPIPE.", info.si_pid);
414 return(0);
415 }
416 else {
@@ -450,7 +444,3 @@ int netdata_pclose(FILE *fp_child_input, FILE *fp_child_output, pid_t pid) {
444
445 return 0;
446 }
453 -
454 -int netdata_spawn_waitpid(pid_t pid) {
455 - return netdata_pclose(NULL, NULL, pid);
456 -}
libnetdata/popen/popen.h
+1 -8
@@ -28,13 +28,6 @@ int netdata_popene_variadic_internal_dont_use_directly(volatile pid_t *pidptr, c
28 int netdata_pclose(FILE *fp_child_input, FILE *fp_child_output, pid_t pid);
29
30 int netdata_spawn(const char *command, volatile pid_t *pidptr);
31 -int netdata_spawn_waitpid(pid_t pid);
32 -
33 -void netdata_popen_tracking_init(void);
34 -void netdata_popen_tracking_cleanup(void);
35 -int netdata_popen_tracking_pid_shoud_be_reaped(pid_t pid);
36 -
37 -void signals_unblock(void);
38 -void signals_reset(void);
31 +int netdata_waitid(idtype_t idtype, id_t id, siginfo_t *infop, int options);
32
33 #endif /* NETDATA_POPEN_H */
libnetdata/socket/security.c
+444 -118
@@ -3,13 +3,389 @@
3 #ifdef ENABLE_HTTPS
4
5 SSL_CTX *netdata_ssl_exporting_ctx =NULL;
6 -SSL_CTX *netdata_ssl_client_ctx =NULL;
7 -SSL_CTX *netdata_ssl_srv_ctx =NULL;
6 +SSL_CTX *netdata_ssl_streaming_sender_ctx =NULL;
7 +SSL_CTX *netdata_ssl_web_server_ctx =NULL;
8 const char *netdata_ssl_security_key =NULL;
9 const char *netdata_ssl_security_cert =NULL;
10 const char *tls_version=NULL;
11 const char *tls_ciphers=NULL;
12 -int netdata_ssl_validate_server = NETDATA_SSL_VALID_CERTIFICATE;
12 +bool netdata_ssl_validate_certificate = true;
13 +bool netdata_ssl_validate_certificate_sender = true;
14 +
15 +static SOCKET_PEERS netdata_ssl_peers(NETDATA_SSL *ssl) {
16 + int sock_fd;
17 +
18 + if(unlikely(!ssl->conn))
19 + sock_fd = -1;
20 + else
21 + sock_fd = SSL_get_rfd(ssl->conn);
22 +
23 + return socket_peers(sock_fd);
24 +}
25 +
26 +bool netdata_ssl_open(NETDATA_SSL *ssl, SSL_CTX *ctx, int fd) {
27 + errno = 0;
28 + ssl->ssl_errno = 0;
29 +
30 + if(ssl->conn) {
31 + if(!ctx || SSL_get_SSL_CTX(ssl->conn) != ctx) {
32 + SSL_free(ssl->conn);
33 + ssl->conn = NULL;
34 + }
35 + else if (SSL_clear(ssl->conn) == 0) {
36 + netdata_ssl_log_error_queue("SSL_clear", ssl);
37 + SSL_free(ssl->conn);
38 + ssl->conn = NULL;
39 + }
40 + }
41 +
42 + if(!ssl->conn) {
43 + if(!ctx) {
44 + internal_error(true, "SSL: not CTX given");
45 + ssl->state = NETDATA_SSL_STATE_FAILED;
46 + return false;
47 + }
48 +
49 + ssl->conn = SSL_new(ctx);
50 + if (!ssl->conn) {
51 + netdata_ssl_log_error_queue("SSL_new", ssl);
52 + ssl->state = NETDATA_SSL_STATE_FAILED;
53 + return false;
54 + }
55 + }
56 +
57 + if(SSL_set_fd(ssl->conn, fd) != 1) {
58 + netdata_ssl_log_error_queue("SSL_set_fd", ssl);
59 + ssl->state = NETDATA_SSL_STATE_FAILED;
60 + return false;
61 + }
62 +
63 + ssl->state = NETDATA_SSL_STATE_INIT;
64 +
65 + ERR_clear_error();
66 +
67 + return true;
68 +}
69 +
70 +void netdata_ssl_close(NETDATA_SSL *ssl) {
71 + errno = 0;
72 + ssl->ssl_errno = 0;
73 +
74 + if(ssl->conn) {
75 + if(SSL_connection(ssl)) {
76 + int ret = SSL_shutdown(ssl->conn);
77 + if(ret == 0)
78 + SSL_shutdown(ssl->conn);
79 + }
80 +
81 + SSL_free(ssl->conn);
82 +
83 + ERR_clear_error();
84 + }
85 +
86 + *ssl = NETDATA_SSL_UNSET_CONNECTION;
87 +}
88 +
89 +void netdata_ssl_log_error_queue(const char *call, NETDATA_SSL *ssl) {
90 + error_limit_static_thread_var(erl, 1, 0);
91 + unsigned long err;
92 + while((err = ERR_get_error())) {
93 + char *code;
94 +
95 + switch (err) {
96 + case SSL_ERROR_NONE:
97 + code = "SSL_ERROR_NONE";
98 + break;
99 +
100 + case SSL_ERROR_SSL:
101 + code = "SSL_ERROR_SSL";
102 + ssl->state = NETDATA_SSL_STATE_FAILED;
103 + break;
104 +
105 + case SSL_ERROR_WANT_READ:
106 + code = "SSL_ERROR_WANT_READ";
107 + break;
108 +
109 + case SSL_ERROR_WANT_WRITE:
110 + code = "SSL_ERROR_WANT_WRITE";
111 + break;
112 +
113 + case SSL_ERROR_WANT_X509_LOOKUP:
114 + code = "SSL_ERROR_WANT_X509_LOOKUP";
115 + break;
116 +
117 + case SSL_ERROR_SYSCALL:
118 + code = "SSL_ERROR_SYSCALL";
119 + ssl->state = NETDATA_SSL_STATE_FAILED;
120 + break;
121 +
122 + case SSL_ERROR_ZERO_RETURN:
123 + code = "SSL_ERROR_ZERO_RETURN";
124 + break;
125 +
126 + case SSL_ERROR_WANT_CONNECT:
127 + code = "SSL_ERROR_WANT_CONNECT";
128 + break;
129 +
130 + case SSL_ERROR_WANT_ACCEPT:
131 + code = "SSL_ERROR_WANT_ACCEPT";
132 + break;
133 +
134 +#ifdef SSL_ERROR_WANT_ASYNC
135 + case SSL_ERROR_WANT_ASYNC:
136 + code = "SSL_ERROR_WANT_ASYNC";
137 + break;
138 +#endif
139 +
140 +#ifdef SSL_ERROR_WANT_ASYNC_JOB
141 + case SSL_ERROR_WANT_ASYNC_JOB:
142 + code = "SSL_ERROR_WANT_ASYNC_JOB";
143 + break;
144 +#endif
145 +
146 +#ifdef SSL_ERROR_WANT_CLIENT_HELLO_CB
147 + case SSL_ERROR_WANT_CLIENT_HELLO_CB:
148 + code = "SSL_ERROR_WANT_CLIENT_HELLO_CB";
149 + break;
150 +#endif
151 +
152 +#ifdef SSL_ERROR_WANT_RETRY_VERIFY
153 + case SSL_ERROR_WANT_RETRY_VERIFY:
154 + code = "SSL_ERROR_WANT_RETRY_VERIFY";
155 + break;
156 +#endif
157 +
158 + default:
159 + code = "SSL_ERROR_UNKNOWN";
160 + break;
161 + }
162 +
163 + char str[1024 + 1];
164 + ERR_error_string_n(err, str, 1024);
165 + str[1024] = '\0';
166 + SOCKET_PEERS peers = netdata_ssl_peers(ssl);
167 + error_limit(&erl, "SSL: %s() on socket local [[%s]:%d] <-> remote [[%s]:%d], returned error %lu (%s): %s",
168 + call, peers.local.ip, peers.local.port, peers.peer.ip, peers.peer.port, err, code, str);
169 + }
170 +}
171 +
172 +static inline bool is_handshake_complete(NETDATA_SSL *ssl, const char *op) {
173 + error_limit_static_thread_var(erl, 1, 0);
174 +
175 + if(unlikely(!ssl->conn)) {
176 + internal_error(true, "SSL: trying to %s on a NULL connection", op);
177 + return false;
178 + }
179 +
180 + switch(ssl->state) {
181 + case NETDATA_SSL_STATE_NOT_SSL: {
182 + SOCKET_PEERS peers = netdata_ssl_peers(ssl);
183 + error_limit(&erl, "SSL: on socket local [[%s]:%d] <-> remote [[%s]:%d], attempt to %s on non-SSL connection",
184 + peers.local.ip, peers.local.port, peers.peer.ip, peers.peer.port, op);
185 + return false;
186 + }
187 +
188 + case NETDATA_SSL_STATE_INIT: {
189 + SOCKET_PEERS peers = netdata_ssl_peers(ssl);
190 + error_limit(&erl, "SSL: on socket local [[%s]:%d] <-> remote [[%s]:%d], attempt to %s on an incomplete connection",
191 + peers.local.ip, peers.local.port, peers.peer.ip, peers.peer.port, op);
192 + return false;
193 + }
194 +
195 + case NETDATA_SSL_STATE_FAILED: {
196 + SOCKET_PEERS peers = netdata_ssl_peers(ssl);
197 + error_limit(&erl, "SSL: on socket local [[%s]:%d] <-> remote [[%s]:%d], attempt to %s on a failed connection",
198 + peers.local.ip, peers.local.port, peers.peer.ip, peers.peer.port, op);
199 + return false;
200 + }
201 +
202 + case NETDATA_SSL_STATE_COMPLETE: {
203 + return true;
204 + }
205 + }
206 +
207 + return false;
208 +}
209 +
210 +/*
211 + * netdata_ssl_read() should return the same as read():
212 + *
213 + * Positive value: The read() function succeeded and read some bytes. The exact number of bytes read is returned.
214 + *
215 + * Zero: For files and sockets, a return value of zero signifies end-of-file (EOF), meaning no more data is available
216 + * for reading. For sockets, this usually means the other side has closed the connection.
217 + *
218 + * -1: An error occurred. The specific error can be found by examining the errno variable.
219 + * EAGAIN or EWOULDBLOCK: The file descriptor is in non-blocking mode, and the read operation would block.
220 + * (These are often the same value, but can be different on some systems.)
221 + */
222 +
223 +ssize_t netdata_ssl_read(NETDATA_SSL *ssl, void *buf, size_t num) {
224 + errno = 0;
225 + ssl->ssl_errno = 0;
226 +
227 + if(unlikely(!is_handshake_complete(ssl, "read")))
228 + return -1;
229 +
230 + int bytes = SSL_read(ssl->conn, buf, (int)num);
231 +
232 + if(unlikely(bytes <= 0)) {
233 + int err = SSL_get_error(ssl->conn, bytes);
234 + netdata_ssl_log_error_queue("SSL_read", ssl);
235 + if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) {
236 + ssl->ssl_errno = err;
237 + errno = EWOULDBLOCK;
238 + }
239 +
240 + bytes = -1; // according to read() or recv()
241 + }
242 +
243 + return bytes;
244 +}
245 +
246 +/*
247 + * netdata_ssl_write() should return the same as write():
248 + *
249 + * Positive value: The write() function succeeded and wrote some bytes. The exact number of bytes written is returned.
250 + *
251 + * Zero: It's technically possible for write() to return zero, indicating that zero bytes were written. However, for a
252 + * socket, this generally does not happen unless the size of the data to be written is zero.
253 + *
254 + * -1: An error occurred. The specific error can be found by examining the errno variable.
255 + * EAGAIN or EWOULDBLOCK: The file descriptor is in non-blocking mode, and the write operation would block.
256 + * (These are often the same value, but can be different on some systems.)
257 + */
258 +
259 +ssize_t netdata_ssl_write(NETDATA_SSL *ssl, const void *buf, size_t num) {
260 + errno = 0;
261 + ssl->ssl_errno = 0;
262 +
263 + if(unlikely(!is_handshake_complete(ssl, "write")))
264 + return -1;
265 +
266 + int bytes = SSL_write(ssl->conn, (uint8_t *)buf, (int)num);
267 +
268 + if(unlikely(bytes <= 0)) {
269 + int err = SSL_get_error(ssl->conn, bytes);
270 + netdata_ssl_log_error_queue("SSL_write", ssl);
271 + if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) {
272 + ssl->ssl_errno = err;
273 + errno = EWOULDBLOCK;
274 + }
275 +
276 + bytes = -1; // according to write() or send()
277 + }
278 +
279 + return bytes;
280 +}
281 +
282 +static inline bool is_handshake_initialized(NETDATA_SSL *ssl, const char *op) {
283 + error_limit_static_thread_var(erl, 1, 0);
284 +
285 + if(unlikely(!ssl->conn)) {
286 + internal_error(true, "SSL: trying to %s on a NULL connection", op);
287 + return false;
288 + }
289 +
290 + switch(ssl->state) {
291 + case NETDATA_SSL_STATE_NOT_SSL: {
292 + SOCKET_PEERS peers = netdata_ssl_peers(ssl);
293 + error_limit(&erl, "SSL: on socket local [[%s]:%d] <-> remote [[%s]:%d], attempt to %s on non-SSL connection",
294 + peers.local.ip, peers.local.port, peers.peer.ip, peers.peer.port, op);
295 + return false;
296 + }
297 +
298 + case NETDATA_SSL_STATE_INIT: {
299 + return true;
300 + }
301 +
302 + case NETDATA_SSL_STATE_FAILED: {
303 + SOCKET_PEERS peers = netdata_ssl_peers(ssl);
304 + error_limit(&erl, "SSL: on socket local [[%s]:%d] <-> remote [[%s]:%d], attempt to %s on a failed connection",
305 + peers.local.ip, peers.local.port, peers.peer.ip, peers.peer.port, op);
306 + return false;
307 + }
308 +
309 + case NETDATA_SSL_STATE_COMPLETE: {
310 + SOCKET_PEERS peers = netdata_ssl_peers(ssl);
311 + error_limit(&erl, "SSL: on socket local [[%s]:%d] <-> remote [[%s]:%d], attempt to %s on an complete connection",
312 + peers.local.ip, peers.local.port, peers.peer.ip, peers.peer.port, op);
313 + return false;
314 + }
315 + }
316 +
317 + return false;
318 +}
319 +
320 +#define WANT_READ_WRITE_TIMEOUT_MS 10
321 +
322 +static inline bool want_read_write_should_retry(NETDATA_SSL *ssl, int err) {
323 + int ssl_errno = SSL_get_error(ssl->conn, err);
324 + if(ssl_errno == SSL_ERROR_WANT_READ || ssl_errno == SSL_ERROR_WANT_WRITE) {
325 + struct pollfd pfds[1] = { [0] = {
326 + .fd = SSL_get_rfd(ssl->conn),
327 + .events = (short)(((ssl_errno == SSL_ERROR_WANT_READ ) ? POLLIN : 0) |
328 + ((ssl_errno == SSL_ERROR_WANT_WRITE) ? POLLOUT : 0)),
329 + }};
330 +
331 + if(poll(pfds, 1, WANT_READ_WRITE_TIMEOUT_MS) <= 0)
332 + return false; // timeout (0) or error (<0)
333 +
334 + return true; // we have activity, so we should retry
335 + }
336 +
337 + return false; // an unknown error
338 +}
339 +
340 +bool netdata_ssl_connect(NETDATA_SSL *ssl) {
341 + errno = 0;
342 + ssl->ssl_errno = 0;
343 +
344 + if(unlikely(!is_handshake_initialized(ssl, "connect")))
345 + return false;
346 +
347 + SSL_set_connect_state(ssl->conn);
348 +
349 + int err;
350 + while ((err = SSL_connect(ssl->conn)) != 1) {
351 + if(!want_read_write_should_retry(ssl, err))
352 + break;
353 + }
354 +
355 + if (err != 1) {
356 + netdata_ssl_log_error_queue("SSL_connect", ssl);
357 + ssl->state = NETDATA_SSL_STATE_FAILED;
358 + return false;
359 + }
360 +
361 + ssl->state = NETDATA_SSL_STATE_COMPLETE;
362 + return true;
363 +}
364 +
365 +bool netdata_ssl_accept(NETDATA_SSL *ssl) {
366 + errno = 0;
367 + ssl->ssl_errno = 0;
368 +
369 + if(unlikely(!is_handshake_initialized(ssl, "accept")))
370 + return false;
371 +
372 + SSL_set_accept_state(ssl->conn);
373 +
374 + int err;
375 + while ((err = SSL_accept(ssl->conn)) != 1) {
376 + if(!want_read_write_should_retry(ssl, err))
377 + break;
378 + }
379 +
380 + if (err != 1) {
381 + netdata_ssl_log_error_queue("SSL_accept", ssl);
382 + ssl->state = NETDATA_SSL_STATE_FAILED;
383 + return false;
384 + }
385 +
386 + ssl->state = NETDATA_SSL_STATE_COMPLETE;
387 + return true;
388 +}
389
390 /**
391 * Info Callback
@@ -20,7 +396,7 @@ int netdata_ssl_validate_server = NETDATA_SSL_VALID_CERTIFICATE;
396 * @param where the variable with the flags set.
397 * @param ret the return of the caller
398 */
23 -static void security_info_callback(const SSL *ssl, int where, int ret __maybe_unused) {
399 +static void netdata_ssl_info_callback(const SSL *ssl, int where, int ret __maybe_unused) {
400 (void)ssl;
401 if (where & SSL_CB_ALERT) {
402 debug(D_WEB_CLIENT,"SSL INFO CALLBACK %s %s", SSL_alert_type_string(ret), SSL_alert_desc_string_long(ret));
@@ -32,8 +408,8 @@ static void security_info_callback(const SSL *ssl, int where, int ret __maybe_un
408 *
409 * Starts the openssl library for the Netdata.
410 */
35 -void security_openssl_library()
36 -{
411 +void netdata_ssl_initialize_openssl() {
412 +
413 #if OPENSSL_VERSION_NUMBER < OPENSSL_VERSION_110
414 # if (SSLEAY_VERSION_NUMBER >= OPENSSL_VERSION_097)
415 OPENSSL_config(NULL);
@@ -42,10 +418,13 @@ void security_openssl_library()
418 SSL_load_error_strings();
419
420 SSL_library_init();
421 +
422 #else
423 +
424 if (OPENSSL_init_ssl(OPENSSL_INIT_LOAD_CONFIG, NULL) != 1) {
425 error("SSL library cannot be initialized.");
426 }
427 +
428 #endif
429 }
430
@@ -59,7 +438,7 @@ void security_openssl_library()
438 *
439 * @return it returns the version number.
440 */
62 -int tls_select_version(const char *lversion) {
441 +static int netdata_ssl_select_tls_version(const char *lversion) {
442 if (!strcmp(lversion, "1") || !strcmp(lversion, "1.0"))
443 return TLS1_VERSION;
444 else if (!strcmp(lversion, "1.1"))
@@ -79,36 +458,6 @@ int tls_select_version(const char *lversion) {
458 }
459 #endif
460
82 -/**
83 - * OpenSSL common options
84 - *
85 - * Clients and SERVER have common options, this function is responsible to set them in the context.
86 - *
87 - * @param ctx the initialized SSL context.
88 - * @param side 0 means server, and 1 client.
89 - */
90 -void security_openssl_common_options(SSL_CTX *ctx, int side) {
91 -#if OPENSSL_VERSION_NUMBER >= OPENSSL_VERSION_110
92 - if (!side) {
93 - int version = tls_select_version(tls_version) ;
94 -#endif
95 -#if OPENSSL_VERSION_NUMBER < OPENSSL_VERSION_110
96 - SSL_CTX_set_options (ctx,SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3|SSL_OP_NO_COMPRESSION);
97 -#else
98 - SSL_CTX_set_min_proto_version(ctx, TLS1_VERSION);
99 - SSL_CTX_set_max_proto_version(ctx, version);
100 -
101 - if(tls_ciphers && strcmp(tls_ciphers, "none") != 0) {
102 - if (!SSL_CTX_set_cipher_list(ctx, tls_ciphers)) {
103 - error("SSL error. cannot set the cipher list");
104 - }
105 - }
106 - }
107 -#endif
108 -
109 - SSL_CTX_set_mode(ctx, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);
110 -}
111 -
461 /**
462 * Initialize Openssl Client
463 *
@@ -116,7 +465,7 @@ void security_openssl_common_options(SSL_CTX *ctx, int side) {
465 *
466 * @return It returns the context on success or NULL otherwise
467 */
119 -SSL_CTX * security_initialize_openssl_client() {
468 +SSL_CTX * netdata_ssl_create_client_ctx(unsigned long mode) {
469 SSL_CTX *ctx;
470 #if OPENSSL_VERSION_NUMBER < OPENSSL_VERSION_110
471 ctx = SSL_CTX_new(SSLv23_client_method());
@@ -138,6 +487,9 @@ SSL_CTX * security_initialize_openssl_client() {
487 #endif
488 }
489
490 + if(mode)
491 + SSL_CTX_set_mode(ctx, mode);
492 +
493 return ctx;
494 }
495
@@ -148,7 +500,7 @@ SSL_CTX * security_initialize_openssl_client() {
500 *
501 * @return It returns the context on success or NULL otherwise
502 */
151 -static SSL_CTX * security_initialize_openssl_server() {
503 +static SSL_CTX * netdata_ssl_create_server_ctx(unsigned long mode) {
504 SSL_CTX *ctx;
505 char lerror[512];
506 static int netdata_id_context = 1;
@@ -171,7 +523,19 @@ static SSL_CTX * security_initialize_openssl_server() {
523
524 SSL_CTX_use_certificate_chain_file(ctx, netdata_ssl_security_cert);
525 #endif
174 - security_openssl_common_options(ctx, 0);
526 +
527 +#if OPENSSL_VERSION_NUMBER < OPENSSL_VERSION_110
528 + SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3|SSL_OP_NO_COMPRESSION);
529 +#else
530 + SSL_CTX_set_min_proto_version(ctx, TLS1_VERSION);
531 + SSL_CTX_set_max_proto_version(ctx, netdata_ssl_select_tls_version(tls_version));
532 +
533 + if(tls_ciphers && strcmp(tls_ciphers, "none") != 0) {
534 + if (!SSL_CTX_set_cipher_list(ctx, tls_ciphers)) {
535 + error("SSL error. cannot set the cipher list");
536 + }
537 + }
538 +#endif
539
540 SSL_CTX_use_PrivateKey_file(ctx, netdata_ssl_security_key,SSL_FILETYPE_PEM);
541
@@ -183,13 +547,15 @@ static SSL_CTX * security_initialize_openssl_server() {
547 }
548
549 SSL_CTX_set_session_id_context(ctx,(void*)&netdata_id_context,(unsigned int)sizeof(netdata_id_context));
186 - SSL_CTX_set_info_callback(ctx,security_info_callback);
550 + SSL_CTX_set_info_callback(ctx, netdata_ssl_info_callback);
551
552 #if (OPENSSL_VERSION_NUMBER < OPENSSL_VERSION_095)
553 SSL_CTX_set_verify_depth(ctx,1);
554 #endif
555 debug(D_WEB_CLIENT,"SSL GLOBAL CONTEXT STARTED\n");
556
557 + SSL_CTX_set_mode(ctx, mode);
558 +
559 return ctx;
560 }
561
@@ -203,39 +569,54 @@ static SSL_CTX * security_initialize_openssl_server() {
569 * NETDATA_SSL_CONTEXT_STREAMING - Starts the streaming context.
570 * NETDATA_SSL_CONTEXT_EXPORTING - Starts the OpenTSDB context
571 */
206 -void security_start_ssl(int selector) {
572 +void netdata_ssl_initialize_ctx(int selector) {
573 static SPINLOCK sp = NETDATA_SPINLOCK_INITIALIZER;
574 netdata_spinlock_lock(&sp);
575
576 switch (selector) {
211 - case NETDATA_SSL_CONTEXT_SERVER: {
212 - if(!netdata_ssl_srv_ctx) {
577 + case NETDATA_SSL_WEB_SERVER_CTX: {
578 + if(!netdata_ssl_web_server_ctx) {
579 struct stat statbuf;
580 if (stat(netdata_ssl_security_key, &statbuf) || stat(netdata_ssl_security_cert, &statbuf))
581 info("To use encryption it is necessary to set \"ssl certificate\" and \"ssl key\" in [web] !\n");
582 else {
217 - netdata_ssl_srv_ctx = security_initialize_openssl_server();
218 - SSL_CTX_set_mode(netdata_ssl_srv_ctx, SSL_MODE_ENABLE_PARTIAL_WRITE);
583 + netdata_ssl_web_server_ctx = netdata_ssl_create_server_ctx(
584 + SSL_MODE_ENABLE_PARTIAL_WRITE |
585 + SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
586 + // SSL_MODE_AUTO_RETRY |
587 + 0);
588 +
589 + if(netdata_ssl_web_server_ctx && !netdata_ssl_validate_certificate)
590 + SSL_CTX_set_verify(netdata_ssl_web_server_ctx, SSL_VERIFY_NONE, NULL);
591 }
592 }
593 break;
594 }
595
224 - case NETDATA_SSL_CONTEXT_STREAMING: {
225 - if(!netdata_ssl_client_ctx) {
226 - netdata_ssl_client_ctx = security_initialize_openssl_client();
596 + case NETDATA_SSL_STREAMING_SENDER_CTX: {
597 + if(!netdata_ssl_streaming_sender_ctx) {
598 //This is necessary for the stream, because it is working sometimes with nonblock socket.
599 //It returns the bitmask after to change, there is not any description of errors in the documentation
229 - SSL_CTX_set_mode(netdata_ssl_client_ctx,
230 - SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
231 - SSL_MODE_AUTO_RETRY);
600 + netdata_ssl_streaming_sender_ctx = netdata_ssl_create_client_ctx(
601 + SSL_MODE_ENABLE_PARTIAL_WRITE |
602 + SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER |
603 + // SSL_MODE_AUTO_RETRY |
604 + 0
605 + );
606 +
607 + if(netdata_ssl_streaming_sender_ctx && !netdata_ssl_validate_certificate_sender)
608 + SSL_CTX_set_verify(netdata_ssl_streaming_sender_ctx, SSL_VERIFY_NONE, NULL);
609 }
610 break;
611 }
612
236 - case NETDATA_SSL_CONTEXT_EXPORTING: {
237 - if(!netdata_ssl_exporting_ctx)
238 - netdata_ssl_exporting_ctx = security_initialize_openssl_client();
613 + case NETDATA_SSL_EXPORTING_CTX: {
614 + if(!netdata_ssl_exporting_ctx) {
615 + netdata_ssl_exporting_ctx = netdata_ssl_create_client_ctx(0);
616 +
617 + if(netdata_ssl_exporting_ctx && !netdata_ssl_validate_certificate)
618 + SSL_CTX_set_verify(netdata_ssl_exporting_ctx, SSL_VERIFY_NONE, NULL);
619 + }
620 break;
621 }
622 }
@@ -248,18 +629,21 @@ void security_start_ssl(int selector) {
629 *
630 * Clean all the allocated contexts from netdata.
631 */
251 -void security_clean_openssl()
632 +void netdata_ssl_cleanup()
633 {
253 - if (netdata_ssl_srv_ctx) {
254 - SSL_CTX_free(netdata_ssl_srv_ctx);
634 + if (netdata_ssl_web_server_ctx) {
635 + SSL_CTX_free(netdata_ssl_web_server_ctx);
636 + netdata_ssl_web_server_ctx = NULL;
637 }
638
257 - if (netdata_ssl_client_ctx) {
258 - SSL_CTX_free(netdata_ssl_client_ctx);
639 + if (netdata_ssl_streaming_sender_ctx) {
640 + SSL_CTX_free(netdata_ssl_streaming_sender_ctx);
641 + netdata_ssl_streaming_sender_ctx = NULL;
642 }
643
644 if (netdata_ssl_exporting_ctx) {
645 SSL_CTX_free(netdata_ssl_exporting_ctx);
646 + netdata_ssl_exporting_ctx = NULL;
647 }
648
649 #if OPENSSL_VERSION_NUMBER < OPENSSL_VERSION_110
@@ -267,64 +651,6 @@ void security_clean_openssl()
651 #endif
652 }
653
270 -/**
271 - * Process accept
272 - *
273 - * Process the SSL handshake with the client case it is necessary.
274 - *
275 - * @param ssl is a pointer for the SSL structure
276 - * @param msg is a copy of the first 8 bytes of the initial message received
277 - *
278 - * @return it returns 0 case it performs the handshake, 8 case it is clean connection
279 - * and another integer power of 2 otherwise.
280 - */
281 -int security_process_accept(SSL *ssl,int msg) {
282 - int sock = SSL_get_fd(ssl);
283 - int test;
284 - if (msg > 0x17)
285 - {
286 - return NETDATA_SSL_NO_HANDSHAKE;
287 - }
288 -
289 - ERR_clear_error();
290 - if ((test = SSL_accept(ssl)) <= 0) {
291 - int sslerrno = SSL_get_error(ssl, test);
292 - switch(sslerrno) {
293 - case SSL_ERROR_WANT_READ:
294 - {
295 - error("SSL handshake did not finish and it wanna read on socket %d!", sock);
296 - return NETDATA_SSL_WANT_READ;
297 - }
298 - case SSL_ERROR_WANT_WRITE:
299 - {
300 - error("SSL handshake did not finish and it wanna read on socket %d!", sock);
301 - return NETDATA_SSL_WANT_WRITE;
302 - }
303 - case SSL_ERROR_NONE:
304 - case SSL_ERROR_SSL:
305 - case SSL_ERROR_SYSCALL:
306 - default:
307 - {
308 - u_long err;
309 - char buf[256];
310 - int counter = 0;
311 - while ((err = ERR_get_error()) != 0) {
312 - ERR_error_string_n(err, buf, sizeof(buf));
313 - error("%d SSL Handshake error (%s) on socket %d", counter++, ERR_error_string((long)SSL_get_error(ssl, test), NULL), sock);
314 - }
315 - return NETDATA_SSL_NO_HANDSHAKE;
316 - }
317 - }
318 - }
319 -
320 - if (SSL_is_init_finished(ssl))
321 - {
322 - debug(D_WEB_CLIENT_ACCESS,"SSL Handshake finished %s errno %d on socket fd %d", ERR_error_string((long)SSL_get_error(ssl, test), NULL), errno, sock);
323 - }
324 -
325 - return NETDATA_SSL_HANDSHAKE_COMPLETE;
326 -}
327 -
654 /**
655 * Test Certificate
656 *
libnetdata/socket/security.h
+37 -26
@@ -1,20 +1,16 @@
1 #ifndef NETDATA_SECURITY_H
2 # define NETDATA_SECURITY_H
3
4 -# define NETDATA_SSL_HANDSHAKE_COMPLETE 0 //All the steps were successful
5 -# define NETDATA_SSL_START 1 //Starting handshake, conn variable is NULL
6 -# define NETDATA_SSL_WANT_READ 2 //The connection wanna read from socket
7 -# define NETDATA_SSL_WANT_WRITE 4 //The connection wanna write on socket
8 -# define NETDATA_SSL_NO_HANDSHAKE 8 //Continue without encrypt connection.
9 -# define NETDATA_SSL_OPTIONAL 16 //Flag to define the HTTP request
10 -# define NETDATA_SSL_FORCE 32 //We only accepts HTTPS request
11 -# define NETDATA_SSL_INVALID_CERTIFICATE 64 //Accepts invalid certificate
12 -# define NETDATA_SSL_VALID_CERTIFICATE 128 //Accepts invalid certificate
13 -# define NETDATA_SSL_PROXY_HTTPS 256 //Proxy is using HTTPS
14 -
15 -#define NETDATA_SSL_CONTEXT_SERVER 0
16 -#define NETDATA_SSL_CONTEXT_STREAMING 1
17 -#define NETDATA_SSL_CONTEXT_EXPORTING 2
4 +typedef enum __attribute__((packed)) {
5 + NETDATA_SSL_STATE_NOT_SSL = 1, // This connection is not SSL
6 + NETDATA_SSL_STATE_INIT, // SSL handshake is initialized
7 + NETDATA_SSL_STATE_FAILED, // SSL handshake failed
8 + NETDATA_SSL_STATE_COMPLETE, // SSL handshake successful
9 +} NETDATA_SSL_STATE;
10 +
11 +#define NETDATA_SSL_WEB_SERVER_CTX 0
12 +#define NETDATA_SSL_STREAMING_SENDER_CTX 1
13 +#define NETDATA_SSL_EXPORTING_CTX 2
14
15 # ifdef ENABLE_HTTPS
16
@@ -37,27 +33,42 @@
33 #include <openssl/decoder.h>
34 #endif
35
40 -struct netdata_ssl {
41 - SSL *conn; //SSL connection
42 - uint32_t flags; //The flags for SSL connection
43 -};
36 +typedef struct netdata_ssl {
37 + SSL *conn; // SSL connection
38 + NETDATA_SSL_STATE state; // The state for SSL connection
39 + unsigned long ssl_errno; // The SSL errno of the last SSL call
40 +} NETDATA_SSL;
41 +
42 +#define NETDATA_SSL_UNSET_CONNECTION (NETDATA_SSL){ .conn = NULL, .state = NETDATA_SSL_STATE_NOT_SSL }
43 +
44 +#define SSL_connection(ssl) ((ssl)->conn && (ssl)->state != NETDATA_SSL_STATE_NOT_SSL)
45
46 extern SSL_CTX *netdata_ssl_exporting_ctx;
46 -extern SSL_CTX *netdata_ssl_client_ctx;
47 -extern SSL_CTX *netdata_ssl_srv_ctx;
47 +extern SSL_CTX *netdata_ssl_streaming_sender_ctx;
48 +extern SSL_CTX *netdata_ssl_web_server_ctx;
49 extern const char *netdata_ssl_security_key;
50 extern const char *netdata_ssl_security_cert;
51 extern const char *tls_version;
52 extern const char *tls_ciphers;
52 -extern int netdata_ssl_validate_server;
53 +extern bool netdata_ssl_validate_certificate;
54 +extern bool netdata_ssl_validate_certificate_sender;
55 int ssl_security_location_for_context(SSL_CTX *ctx,char *file,char *path);
56
55 -void security_openssl_library();
56 -void security_clean_openssl();
57 -void security_start_ssl(int selector);
58 -int security_process_accept(SSL *ssl,int msg);
57 +void netdata_ssl_initialize_openssl();
58 +void netdata_ssl_cleanup();
59 +void netdata_ssl_initialize_ctx(int selector);
60 int security_test_certificate(SSL *ssl);
60 -SSL_CTX * security_initialize_openssl_client();
61 +SSL_CTX * netdata_ssl_create_client_ctx(unsigned long mode);
62 +
63 +bool netdata_ssl_connect(NETDATA_SSL *ssl);
64 +bool netdata_ssl_accept(NETDATA_SSL *ssl);
65 +
66 +bool netdata_ssl_open(NETDATA_SSL *ssl, SSL_CTX *ctx, int fd);
67 +void netdata_ssl_close(NETDATA_SSL *ssl);
68 +void netdata_ssl_log_error_queue(const char *call, NETDATA_SSL *ssl);
69 +
70 +ssize_t netdata_ssl_read(NETDATA_SSL *ssl, void *buf, size_t num);
71 +ssize_t netdata_ssl_write(NETDATA_SSL *ssl, const void *buf, size_t num);
72
73 # endif //ENABLE_HTTPS
74 #endif //NETDATA_SECURITY_H
libnetdata/socket/socket.c
+67 -48
@@ -10,6 +10,63 @@
10
11 #include "../libnetdata.h"
12
13 +
14 +SOCKET_PEERS socket_peers(int sock_fd) {
15 + SOCKET_PEERS peers;
16 +
17 + if(sock_fd < 0) {
18 + strncpyz(peers.peer.ip, "unknown", sizeof(peers.peer.ip) - 1);
19 + peers.peer.port = 0;
20 +
21 + strncpyz(peers.local.ip, "unknown", sizeof(peers.local.ip) - 1);
22 + peers.local.port = 0;
23 +
24 + return peers;
25 + }
26 +
27 + struct sockaddr_storage addr;
28 + socklen_t addr_len = sizeof(addr);
29 +
30 + // Get peer info
31 + if (getpeername(sock_fd, (struct sockaddr *)&addr, &addr_len) == 0) {
32 + if (addr.ss_family == AF_INET) { // IPv4
33 + struct sockaddr_in *s = (struct sockaddr_in *)&addr;
34 + inet_ntop(AF_INET, &s->sin_addr, peers.peer.ip, sizeof(peers.peer.ip));
35 + peers.peer.port = ntohs(s->sin_port);
36 + }
37 + else { // IPv6
38 + struct sockaddr_in6 *s = (struct sockaddr_in6 *)&addr;
39 + inet_ntop(AF_INET6, &s->sin6_addr, peers.peer.ip, sizeof(peers.peer.ip));
40 + peers.peer.port = ntohs(s->sin6_port);
41 + }
42 + }
43 + else {
44 + strncpyz(peers.peer.ip, "unknown", sizeof(peers.peer.ip) - 1);
45 + peers.peer.port = 0;
46 + }
47 +
48 + // Get local info
49 + addr_len = sizeof(addr);
50 + if (getsockname(sock_fd, (struct sockaddr *)&addr, &addr_len) == 0) {
51 + if (addr.ss_family == AF_INET) { // IPv4
52 + struct sockaddr_in *s = (struct sockaddr_in *) &addr;
53 + inet_ntop(AF_INET, &s->sin_addr, peers.local.ip, sizeof(peers.local.ip));
54 + peers.local.port = ntohs(s->sin_port);
55 + } else { // IPv6
56 + struct sockaddr_in6 *s = (struct sockaddr_in6 *) &addr;
57 + inet_ntop(AF_INET6, &s->sin6_addr, peers.local.ip, sizeof(peers.local.ip));
58 + peers.local.port = ntohs(s->sin6_port);
59 + }
60 + }
61 + else {
62 + strncpyz(peers.local.ip, "unknown", sizeof(peers.local.ip) - 1);
63 + peers.local.port = 0;
64 + }
65 +
66 + return peers;
67 +}
68 +
69 +
70 // --------------------------------------------------------------------------------------------------------------------
71 // various library calls
72
@@ -967,49 +1024,11 @@ int connect_to_one_of_urls(const char *destination, int default_port, struct tim
1024 }
1025
1026
970 -#ifdef ENABLE_HTTPS
971 -ssize_t netdata_ssl_read(SSL *ssl, void *buf, size_t num) {
972 - error_limit_static_thread_var(erl, 1, 0);
973 -
974 - int bytes, err;
975 -
976 - bytes = SSL_read(ssl, buf, (int)num);
977 - err = SSL_get_error(ssl, bytes);
978 -
979 - if(unlikely(bytes <= 0)) {
980 - if (err == SSL_ERROR_WANT_WRITE || err == SSL_ERROR_WANT_READ) {
981 - bytes = 0;
982 - } else
983 - error_limit(&erl, "SSL_write() returned %d bytes, SSL error %d", bytes, err);
984 - }
985 -
986 - return bytes;
987 -}
988 -
989 -ssize_t netdata_ssl_write(SSL *ssl, const void *buf, size_t num) {
990 - error_limit_static_thread_var(erl, 1, 0);
991 -
992 - int bytes, err;
993 -
994 - bytes = SSL_write(ssl, (uint8_t *)buf, (int)num);
995 - err = SSL_get_error(ssl, bytes);
996 -
997 - if(unlikely(bytes <= 0)) {
998 - if (err == SSL_ERROR_WANT_WRITE || err == SSL_ERROR_WANT_READ) {
999 - bytes = 0;
1000 - } else
1001 - error_limit(&erl, "SSL_write() returned %d bytes, SSL error %d", bytes, err);
1002 - }
1003 -
1004 - return bytes;
1005 -}
1006 -#endif
1007 -
1027 // --------------------------------------------------------------------------------------------------------------------
1028 // helpers to send/receive data in one call, in blocking mode, with a timeout
1029
1030 #ifdef ENABLE_HTTPS
1012 -ssize_t recv_timeout(struct netdata_ssl *ssl,int sockfd, void *buf, size_t len, int flags, int timeout) {
1031 +ssize_t recv_timeout(NETDATA_SSL *ssl,int sockfd, void *buf, size_t len, int flags, int timeout) {
1032 #else
1033 ssize_t recv_timeout(int sockfd, void *buf, size_t len, int flags, int timeout) {
1034 #endif
@@ -1033,24 +1052,24 @@ ssize_t recv_timeout(int sockfd, void *buf, size_t len, int flags, int timeout)
1052 return -1;
1053 }
1054
1036 - if(!retval) {
1055 + if(!retval)
1056 // timeout
1057 return 0;
1039 - }
1058
1041 - if(fd.events & POLLIN) break;
1059 + if(fd.revents & POLLIN)
1060 + break;
1061 }
1062
1063 #ifdef ENABLE_HTTPS
1045 - if (ssl->conn && ssl->flags == NETDATA_SSL_HANDSHAKE_COMPLETE)
1046 - return netdata_ssl_read(ssl->conn, buf, len);
1064 + if (SSL_connection(ssl))
1065 + return netdata_ssl_read(ssl, buf, len);
1066 #endif
1067
1068 return recv(sockfd, buf, len, flags);
1069 }
1070
1071 #ifdef ENABLE_HTTPS
1053 -ssize_t send_timeout(struct netdata_ssl *ssl,int sockfd, void *buf, size_t len, int flags, int timeout) {
1072 +ssize_t send_timeout(NETDATA_SSL *ssl,int sockfd, void *buf, size_t len, int flags, int timeout) {
1073 #else
1074 ssize_t send_timeout(int sockfd, void *buf, size_t len, int flags, int timeout) {
1075 #endif
@@ -1079,13 +1098,13 @@ ssize_t send_timeout(int sockfd, void *buf, size_t len, int flags, int timeout)
1098 return 0;
1099 }
1100
1082 - if(fd.events & POLLOUT) break;
1101 + if(fd.revents & POLLOUT) break;
1102 }
1103
1104 #ifdef ENABLE_HTTPS
1105 if(ssl->conn) {
1087 - if (ssl->flags == NETDATA_SSL_HANDSHAKE_COMPLETE) {
1088 - return netdata_ssl_write(ssl->conn, buf, len);
1106 + if (SSL_connection(ssl)) {
1107 + return netdata_ssl_write(ssl, buf, len);
1108 }
1109 else {
1110 error("cannot write to SSL connection - connection is not ready.");
libnetdata/socket/socket.h
+20 -4
@@ -68,10 +68,8 @@ int connect_to_one_of_urls(const char *destination, int default_port, struct tim
68
69
70 #ifdef ENABLE_HTTPS
71 -ssize_t recv_timeout(struct netdata_ssl *ssl,int sockfd, void *buf, size_t len, int flags, int timeout);
72 -ssize_t send_timeout(struct netdata_ssl *ssl,int sockfd, void *buf, size_t len, int flags, int timeout);
73 -ssize_t netdata_ssl_read(SSL *ssl, void *buf, size_t num);
74 -ssize_t netdata_ssl_write(SSL *ssl, const void *buf, size_t num);
71 +ssize_t recv_timeout(NETDATA_SSL *ssl,int sockfd, void *buf, size_t len, int flags, int timeout);
72 +ssize_t send_timeout(NETDATA_SSL *ssl,int sockfd, void *buf, size_t len, int flags, int timeout);
73 #else
74 ssize_t recv_timeout(int sockfd, void *buf, size_t len, int flags, int timeout);
75 ssize_t send_timeout(int sockfd, void *buf, size_t len, int flags, int timeout);
@@ -219,4 +217,22 @@ void poll_events(LISTEN_SOCKETS *sockets
217 , size_t max_tcp_sockets
218 );
219
220 +#ifndef INET6_ADDRSTRLEN
221 +#define INET6_ADDRSTRLEN 46
222 +#endif
223 +
224 +typedef struct socket_peers {
225 + struct {
226 + char ip[INET6_ADDRSTRLEN];
227 + int port;
228 + } local;
229 +
230 + struct {
231 + char ip[INET6_ADDRSTRLEN];
232 + int port;
233 + } peer;
234 +} SOCKET_PEERS;
235 +
236 +SOCKET_PEERS socket_peers(int sock_fd);
237 +
238 #endif //NETDATA_SOCKET_H
streaming/receiver.c
+35 -49
@@ -31,10 +31,14 @@ void receiver_state_free(struct receiver_state *rpt) {
31 freez(rpt->program_version);
32
33 #ifdef ENABLE_HTTPS
34 - if(rpt->ssl.conn)
35 - SSL_free(rpt->ssl.conn);
34 + netdata_ssl_close(&rpt->ssl);
35 #endif
36
37 + if(rpt->fd != -1) {
38 + internal_error(true, "closing socket...");
39 + close(rpt->fd);
40 + }
41 +
42 #ifdef ENABLE_COMPRESSION
43 if (rpt->decompressor)
44 rpt->decompressor->destroy(&rpt->decompressor);
@@ -100,13 +104,18 @@ static int read_stream(struct receiver_state *r, char* buffer, size_t size) {
104 return 0;
105 }
106
107 + ssize_t bytes_read;
108 +
109 #ifdef ENABLE_HTTPS
104 - if (r->ssl.conn && r->ssl.flags == NETDATA_SSL_HANDSHAKE_COMPLETE)
105 - return (int)netdata_ssl_read(r->ssl.conn, buffer, size);
110 + if (SSL_connection(&r->ssl))
111 + bytes_read = netdata_ssl_read(&r->ssl, buffer, size);
112 + else
113 + bytes_read = read(r->fd, buffer, size);
114 +#else
115 + bytes_read = read(r->fd, buffer, size);
116 #endif
117
108 - ssize_t bytes_read = read(r->fd, buffer, size);
109 - if(bytes_read == 0 && (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS)) {
118 + if((bytes_read == 0 || bytes_read == -1) && (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS)) {
119 error("STREAM: %s(): timeout while waiting for data on socket!", __FUNCTION__);
120 bytes_read = -3;
121 }
@@ -119,23 +128,6 @@ static int read_stream(struct receiver_state *r, char* buffer, size_t size) {
128 bytes_read = -2;
129 }
130
122 -// do {
123 -// bytes_read = (int) fread(buffer, 1, size, fp);
124 -// if (unlikely(bytes_read <= 0)) {
125 -// if(feof(fp)) {
126 -// internal_error(true, "%s(): fread() failed with EOF", __FUNCTION__);
127 -// bytes_read = -2;
128 -// }
129 -// else if(ferror(fp)) {
130 -// internal_error(true, "%s(): fread() failed with ERROR", __FUNCTION__);
131 -// bytes_read = -3;
132 -// }
133 -// else bytes_read = 0;
134 -// }
135 -// else
136 -// worker_set_metric(WORKER_RECEIVER_JOB_BYTES_READ, bytes_read);
137 -// } while(bytes_read == 0);
138 -
131 return (int)bytes_read;
132 }
133
@@ -323,12 +315,6 @@ static char *receiver_next_line(struct receiver_state *r, char *buffer, size_t b
315 return NULL;
316 }
317
326 -static void streaming_parser_thread_cleanup(void *ptr) {
327 - PARSER *parser = (PARSER *)ptr;
328 - rrd_collector_finished();
329 - parser_destroy(parser);
330 -}
331 -
318 bool plugin_is_enabled(struct plugind *cd);
319
320 static size_t streaming_parser(struct receiver_state *rpt, struct plugind *cd, int fd, void *ssl) {
@@ -352,7 +338,7 @@ static size_t streaming_parser(struct receiver_state *rpt, struct plugind *cd, i
338
339 // this keeps the parser with its current value
340 // so, parser needs to be allocated before pushing it
355 - netdata_thread_cleanup_push(streaming_parser_thread_cleanup, parser);
341 + netdata_thread_cleanup_push(pluginsd_process_thread_cleanup, parser);
342
343 parser_add_keyword(parser, "CLAIMED_ID", streaming_claimed_id);
344
@@ -474,6 +460,8 @@ static bool rrdhost_set_receiver(RRDHOST *host, struct receiver_state *rpt) {
460 rrdhost_flag_clear(rpt->host, RRDHOST_FLAG_RRDPUSH_RECEIVER_DISCONNECTED);
461 aclk_queue_node_info(rpt->host, true);
462
463 + rrdpush_reset_destinations_postpone_time(host);
464 +
465 set_this = true;
466 }
467
@@ -506,16 +494,16 @@ static void rrdhost_clear_receiver(struct receiver_state *rpt) {
494 signal_rrdcontext = true;
495 rrdpush_receiver_replication_reset(host);
496
509 - if (host->receiver == rpt)
510 - host->receiver = NULL;
511 -
497 rrdhost_flag_set(host, RRDHOST_FLAG_ORPHAN);
498 + host->receiver = NULL;
499 }
500
501 netdata_mutex_unlock(&host->receiver_lock);
502
503 if(signal_rrdcontext)
504 rrdcontext_host_child_disconnected(host);
505 +
506 + rrdpush_reset_destinations_postpone_time(host);
507 }
508 }
509
@@ -549,7 +537,7 @@ bool stop_streaming_receiver(RRDHOST *host, const char *reason) {
537 "thread %d takes too long to stop, giving up..."
538 , rrdhost_hostname(host)
539 , host->receiver->client_ip, host->receiver->client_port
552 - , gettid());
540 + , host->receiver->tid);
541 else
542 ret = true;
543
@@ -585,7 +573,7 @@ static void rrdhost_reset_destinations(RRDHOST *host) {
573 d->postpone_reconnection_until = 0;
574 }
575
588 -static int rrdpush_receive(struct receiver_state *rpt)
576 +static void rrdpush_receive(struct receiver_state *rpt)
577 {
578 rpt->config.mode = default_rrd_memory_mode;
579 rpt->config.history = default_rrd_history_entries;
@@ -689,14 +677,12 @@ static int rrdpush_receive(struct receiver_state *rpt)
677
678 if(!host) {
679 rrdpush_receive_log_status(rpt, "failed to find/create host structure", "INTERNAL ERROR DROPPING CONNECTION");
692 - close(rpt->fd);
693 - return 1;
680 + goto cleanup;
681 }
682
683 if (unlikely(rrdhost_flag_check(host, RRDHOST_FLAG_PENDING_CONTEXT_LOAD))) {
684 rrdpush_receive_log_status(rpt, "host is initializing", "INITIALIZATION IN PROGRESS RETRY LATER");
698 - close(rpt->fd);
699 - return 1;
685 + goto cleanup;
686 }
687
688 // system_info has been consumed by the host structure
@@ -704,8 +690,7 @@ static int rrdpush_receive(struct receiver_state *rpt)
690
691 if(!rrdhost_set_receiver(host, rpt)) {
692 rrdpush_receive_log_status(rpt, "host is already served by another receiver", "DUPLICATE RECEIVER DROPPING CONNECTION");
707 - close(rpt->fd);
708 - return 1;
693 + goto cleanup;
694 }
695 }
696
@@ -776,15 +761,16 @@ static int rrdpush_receive(struct receiver_state *rpt)
761 }
762
763 debug(D_STREAM, "Initial response to %s: %s", rpt->client_ip, initial_response);
779 - if(send_timeout(
764 + ssize_t bytes_sent = send_timeout(
765 #ifdef ENABLE_HTTPS
766 &rpt->ssl,
767 #endif
783 - rpt->fd, initial_response, strlen(initial_response), 0, 60) != (ssize_t)strlen(initial_response)) {
768 + rpt->fd, initial_response, strlen(initial_response), 0, 60);
769
770 + if(bytes_sent != (ssize_t)strlen(initial_response)) {
771 + internal_error(true, "Cannot send response, got %zd bytes, expecting %zu bytes", bytes_sent, strlen(initial_response));
772 rrdpush_receive_log_status(rpt, "cannot reply back", "CANT REPLY DROPPING CONNECTION");
786 - close(rpt->fd);
787 - return 0;
773 + goto cleanup;
774 }
775 }
776
@@ -850,9 +836,8 @@ static int rrdpush_receive(struct receiver_state *rpt)
836
837 rrdhost_set_is_parent_label(--localhost->connected_children_count);
838
853 - // cleanup
854 - close(rpt->fd);
855 - return (int)count;
839 +cleanup:
840 + ;
841 }
842
843 static void rrdpush_receiver_thread_cleanup(void *ptr) {
@@ -879,7 +864,8 @@ void *rrdpush_receiver_thread(void *ptr) {
864 worker_register_job_custom_metric(WORKER_RECEIVER_JOB_REPLICATION_COMPLETION, "replication completion", "%", WORKER_METRIC_ABSOLUTE);
865
866 struct receiver_state *rpt = (struct receiver_state *)ptr;
882 - info("STREAM %s [%s]:%s: receive thread created (task id %d)", rpt->hostname, rpt->client_ip, rpt->client_port, gettid());
867 + rpt->tid = gettid();
868 + info("STREAM %s [%s]:%s: receive thread created (task id %d)", rpt->hostname, rpt->client_ip, rpt->client_port, rpt->tid);
869
870 rrdpush_receive(rpt);
871
streaming/rrdpush.c
+123 -44
@@ -49,7 +49,6 @@ bool default_rrdpush_enable_replication = true;
49 time_t default_rrdpush_seconds_to_replicate = 86400;
50 time_t default_rrdpush_replication_step = 600;
51 #ifdef ENABLE_HTTPS
52 -int netdata_use_ssl_on_stream = NETDATA_SSL_OPTIONAL;
52 char *netdata_ssl_ca_path = NULL;
53 char *netdata_ssl_ca_file = NULL;
54 #endif
@@ -137,24 +136,10 @@ int rrdpush_init() {
136 }
137
138 #ifdef ENABLE_HTTPS
140 - if (netdata_use_ssl_on_stream == NETDATA_SSL_OPTIONAL) {
141 - if (default_rrdpush_destination){
142 - char *test = strstr(default_rrdpush_destination,":SSL");
143 - if(test){
144 - *test = 0X00;
145 - netdata_use_ssl_on_stream = NETDATA_SSL_FORCE;
146 - }
147 - }
148 - }
139 + netdata_ssl_validate_certificate_sender = !appconfig_get_boolean(&stream_config, CONFIG_SECTION_STREAM, "ssl skip certificate verification", !netdata_ssl_validate_certificate);
140
150 - bool invalid_certificate = appconfig_get_boolean(&stream_config, CONFIG_SECTION_STREAM, "ssl skip certificate verification", CONFIG_BOOLEAN_NO);
151 -
152 - if(invalid_certificate == CONFIG_BOOLEAN_YES){
153 - if(netdata_ssl_validate_server == NETDATA_SSL_VALID_CERTIFICATE){
154 - info("Netdata is configured to accept invalid SSL certificate.");
155 - netdata_ssl_validate_server = NETDATA_SSL_INVALID_CERTIFICATE;
156 - }
157 - }
141 + if(!netdata_ssl_validate_certificate_sender)
142 + info("SSL: streaming senders will skip SSL certificates verification.");
143
144 netdata_ssl_ca_path = appconfig_get(&stream_config, CONFIG_SECTION_STREAM, "CApath", NULL);
145 netdata_ssl_ca_file = appconfig_get(&stream_config, CONFIG_SECTION_STREAM, "CAfile", NULL);
@@ -579,6 +564,7 @@ int connect_to_one_of_destinations(
564 if (reconnects_counter)
565 *reconnects_counter += 1;
566
567 + d->last_attempt = now;
568 sock = connect_to_this(string2str(d->destination), default_port, timeout);
569
570 if (sock != -1) {
@@ -610,6 +596,14 @@ bool destinations_init_add_one(char *entry, void *data) {
596 struct destinations_init_tmp *t = data;
597
598 struct rrdpush_destinations *d = callocz(1, sizeof(struct rrdpush_destinations));
599 + char *colon_ssl = strstr(entry, ":SSL");
600 + if(colon_ssl) {
601 + *colon_ssl = '\0';
602 + d->ssl = true;
603 + }
604 + else
605 + d->ssl = false;
606 +
607 d->destination = string_strdupz(entry);
608
609 __atomic_add_fetch(&netdata_buffers_statistics.rrdhost_senders, sizeof(struct rrdpush_destinations), __ATOMIC_RELAXED);
@@ -724,6 +718,31 @@ int rrdpush_receiver_too_busy_now(struct web_client *w) {
718 return HTTP_RESP_SERVICE_UNAVAILABLE;
719 }
720
721 +static void rrdpush_receiver_takeover_web_connection(struct web_client *w, struct receiver_state *rpt) {
722 + rpt->fd = w->ifd;
723 +
724 +#ifdef ENABLE_HTTPS
725 + rpt->ssl.conn = w->ssl.conn;
726 + rpt->ssl.state = w->ssl.state;
727 +
728 + w->ssl = NETDATA_SSL_UNSET_CONNECTION;
729 +#endif
730 +
731 + WEB_CLIENT_IS_DEAD(w);
732 +
733 + if(web_server_mode == WEB_SERVER_MODE_STATIC_THREADED) {
734 + web_client_flag_set(w, WEB_CLIENT_FLAG_DONT_CLOSE_SOCKET);
735 + }
736 + else {
737 + if(w->ifd == w->ofd)
738 + w->ifd = w->ofd = -1;
739 + else
740 + w->ifd = -1;
741 + }
742 +
743 + buffer_flush(w->response.data);
744 +}
745 +
746 void *rrdpush_receiver_thread(void *ptr);
747 int rrdpush_receiver_thread_spawn(struct web_client *w, char *decoded_query_string) {
748
@@ -741,20 +760,16 @@ int rrdpush_receiver_thread_spawn(struct web_client *w, char *decoded_query_stri
760 rpt->system_info = callocz(1, sizeof(struct rrdhost_system_info));
761 rpt->system_info->hops = rpt->hops;
762
744 - rpt->fd = w->ifd;
763 + rpt->fd = -1;
764 rpt->client_ip = strdupz(w->client_ip);
765 rpt->client_port = strdupz(w->client_port);
766
748 - rpt->config.update_every = default_rrd_update_every;
749 -
767 #ifdef ENABLE_HTTPS
751 - rpt->ssl.conn = w->ssl.conn;
752 - rpt->ssl.flags = w->ssl.flags;
753 -
754 - w->ssl.conn = NULL;
755 - w->ssl.flags = NETDATA_SSL_START;
768 + rpt->ssl = NETDATA_SSL_UNSET_CONNECTION;
769 #endif
770
771 + rpt->config.update_every = default_rrd_update_every;
772 +
773 // parse the parameters and fill rpt and rpt->system_info
774
775 while(decoded_query_string) {
@@ -1011,6 +1026,8 @@ int rrdpush_receiver_thread_spawn(struct web_client *w, char *decoded_query_stri
1026
1027 if (strcmp(rpt->machine_guid, localhost->machine_guid) == 0) {
1028
1029 + rrdpush_receiver_takeover_web_connection(w, rpt);
1030 +
1031 rrdpush_receive_log_status(
1032 rpt,
1033 "machine GUID is my own",
@@ -1032,9 +1049,8 @@ int rrdpush_receiver_thread_spawn(struct web_client *w, char *decoded_query_stri
1049 );
1050 }
1051
1035 - close(rpt->fd);
1052 receiver_state_free(rpt);
1037 - return web_client_socket_is_now_used_for_streaming(w);
1053 + return HTTP_RESP_OK;
1054 }
1055
1056 if(unlikely(web_client_streaming_rate_t > 0)) {
@@ -1138,8 +1154,11 @@ int rrdpush_receiver_thread_spawn(struct web_client *w, char *decoded_query_stri
1154
1155 debug(D_SYSTEM, "starting STREAM receive thread.");
1156
1141 - char tag[FILENAME_MAX + 1];
1142 - snprintfz(tag, FILENAME_MAX, THREAD_TAG_STREAM_RECEIVER "[%s,[%s]:%s]", rpt->hostname, w->client_ip, w->client_port);
1157 + rrdpush_receiver_takeover_web_connection(w, rpt);
1158 +
1159 + char tag[NETDATA_THREAD_TAG_MAX + 1];
1160 + snprintfz(tag, NETDATA_THREAD_TAG_MAX, THREAD_TAG_STREAM_RECEIVER "[%s]", rpt->hostname);
1161 + tag[NETDATA_THREAD_TAG_MAX] = '\0';
1162
1163 if(netdata_thread_create(&rpt->thread, tag, NETDATA_THREAD_OPTION_DEFAULT, rrdpush_receiver_thread, (void *)rpt)) {
1164 rrdpush_receive_log_status(
@@ -1154,23 +1173,83 @@ int rrdpush_receiver_thread_spawn(struct web_client *w, char *decoded_query_stri
1173 }
1174
1175 // prevent the caller from closing the streaming socket
1157 - return web_client_socket_is_now_used_for_streaming(w);
1176 + return HTTP_RESP_OK;
1177 +}
1178 +
1179 +void rrdpush_reset_destinations_postpone_time(RRDHOST *host) {
1180 + struct rrdpush_destinations *d;
1181 + for (d = host->destinations; d; d = d->next)
1182 + d->postpone_reconnection_until = 0;
1183 }
1184
1185 +static struct {
1186 + STREAM_HANDSHAKE err;
1187 + const char *str;
1188 +} handshake_errors[] = {
1189 + { STREAM_HANDSHAKE_OK_V5, "OK_V5" },
1190 + { STREAM_HANDSHAKE_OK_V4, "OK_V4" },
1191 + { STREAM_HANDSHAKE_OK_V3, "OK_V3" },
1192 + { STREAM_HANDSHAKE_OK_V2, "OK_V2" },
1193 + { STREAM_HANDSHAKE_OK_V1, "OK_V1" },
1194 + { STREAM_HANDSHAKE_ERROR_BAD_HANDSHAKE, "ERROR_BAD_HANDSHAKE" },
1195 + { STREAM_HANDSHAKE_ERROR_LOCALHOST, "ERROR_LOCALHOST" },
1196 + { STREAM_HANDSHAKE_ERROR_ALREADY_CONNECTED, "ERROR_ALREADY_CONNECTED" },
1197 + { STREAM_HANDSHAKE_ERROR_DENIED, "ERROR_DENIED" },
1198 + { STREAM_HANDSHAKE_ERROR_SEND_TIMEOUT, "ERROR_SEND_TIMEOUT" },
1199 + { STREAM_HANDSHAKE_ERROR_RECEIVE_TIMEOUT, "ERROR_RECEIVE_TIMEOUT" },
1200 + { STREAM_HANDSHAKE_ERROR_INVALID_CERTIFICATE, "ERROR_INVALID_CERTIFICATE" },
1201 + { STREAM_HANDSHAKE_ERROR_SSL_ERROR, "ERROR_SSL_ERROR" },
1202 + { STREAM_HANDSHAKE_ERROR_CANT_CONNECT, "ERROR_CANT_CONNECT" },
1203 + { 0, NULL },
1204 +};
1205 +
1206 +const char *stream_handshake_error_to_string(STREAM_HANDSHAKE handshake_error) {
1207 + for(size_t i = 0; handshake_errors[i].str ; i++) {
1208 + if(handshake_error == handshake_errors[i].err)
1209 + return handshake_errors[i].str;
1210 + }
1211 +
1212 + return "";
1213 +}
1214 +
1215 +static struct {
1216 + STREAM_CAPABILITIES cap;
1217 + const char *str;
1218 +} capability_names[] = {
1219 + { STREAM_CAP_V1, "V1" },
1220 + { STREAM_CAP_V2, "V2" },
1221 + { STREAM_CAP_VN, "VN" },
1222 + { STREAM_CAP_VCAPS, "VCAPS" },
1223 + { STREAM_CAP_HLABELS, "HLABELS" },
1224 + { STREAM_CAP_CLAIM, "CLAIM" },
1225 + { STREAM_CAP_CLABELS, "CLABELS" },
1226 + { STREAM_CAP_COMPRESSION, "COMPRESSION" },
1227 + { STREAM_CAP_FUNCTIONS, "FUNCTIONS" },
1228 + { STREAM_CAP_REPLICATION, "REPLICATION" },
1229 + { STREAM_CAP_BINARY, "BINARY" },
1230 + { STREAM_CAP_INTERPOLATED, "INTERPOLATED" },
1231 + { STREAM_CAP_IEEE754, "IEEE754" },
1232 + { 0 , NULL },
1233 +};
1234 +
1235 static void stream_capabilities_to_string(BUFFER *wb, STREAM_CAPABILITIES caps) {
1161 - if(caps & STREAM_CAP_V1) buffer_strcat(wb, "V1 ");
1162 - if(caps & STREAM_CAP_V2) buffer_strcat(wb, "V2 ");
1163 - if(caps & STREAM_CAP_VN) buffer_strcat(wb, "VN ");
1164 - if(caps & STREAM_CAP_VCAPS) buffer_strcat(wb, "VCAPS ");
1165 - if(caps & STREAM_CAP_HLABELS) buffer_strcat(wb, "HLABELS ");
1166 - if(caps & STREAM_CAP_CLAIM) buffer_strcat(wb, "CLAIM ");
1167 - if(caps & STREAM_CAP_CLABELS) buffer_strcat(wb, "CLABELS ");
1168 - if(caps & STREAM_CAP_COMPRESSION) buffer_strcat(wb, "COMPRESSION ");
1169 - if(caps & STREAM_CAP_FUNCTIONS) buffer_strcat(wb, "FUNCTIONS ");
1170 - if(caps & STREAM_CAP_REPLICATION) buffer_strcat(wb, "REPLICATION ");
1171 - if(caps & STREAM_CAP_BINARY) buffer_strcat(wb, "BINARY ");
1172 - if(caps & STREAM_CAP_INTERPOLATED) buffer_strcat(wb, "INTERPOLATED ");
1173 - if(caps & STREAM_CAP_IEEE754) buffer_strcat(wb, "IEEE754 ");
1236 + for(size_t i = 0; capability_names[i].str ; i++) {
1237 + if(caps & capability_names[i].cap) {
1238 + buffer_strcat(wb, capability_names[i].str);
1239 + buffer_strcat(wb, " ");
1240 + }
1241 + }
1242 +}
1243 +
1244 +void stream_capabilities_to_json_array(BUFFER *wb, STREAM_CAPABILITIES caps, const char *key) {
1245 + buffer_json_member_add_array(wb, key);
1246 +
1247 + for(size_t i = 0; capability_names[i].str ; i++) {
1248 + if(caps & capability_names[i].cap)
1249 + buffer_json_add_array_item_string(wb, capability_names[i].str);
1250 + }
1251 +
1252 + buffer_json_array_close(wb);
1253 }
1254
1255 void log_receiver_capabilities(struct receiver_state *rpt) {
streaming/rrdpush.h
+8 -3
@@ -166,7 +166,7 @@ struct sender_state {
166 struct compressor_state *compressor;
167 #endif
168 #ifdef ENABLE_HTTPS
169 - struct netdata_ssl ssl; // structure used to encrypt the connection
169 + NETDATA_SSL ssl; // structure used to encrypt the connection
170 #endif
171
172 struct {
@@ -221,6 +221,7 @@ struct sender_state {
221
222 struct receiver_state {
223 RRDHOST *host;
224 + pid_t tid;
225 netdata_thread_t thread;
226 int fd;
227 char *key;
@@ -266,7 +267,7 @@ struct receiver_state {
267 } config;
268
269 #ifdef ENABLE_HTTPS
269 - struct netdata_ssl ssl;
270 + NETDATA_SSL ssl;
271 #endif
272 #ifdef ENABLE_COMPRESSION
273 unsigned int rrdpush_compression;
@@ -278,8 +279,10 @@ struct receiver_state {
279
280 struct rrdpush_destinations {
281 STRING *destination;
282 + bool ssl;
283
284 const char *last_error;
285 + time_t last_attempt;
286 time_t postpone_reconnection_until;
287 STREAM_HANDSHAKE last_handshake;
288
@@ -351,7 +354,9 @@ void rrdpush_signal_sender_to_wake_up(struct sender_state *s);
354 struct compressor_state *create_compressor();
355 struct decompressor_state *create_decompressor();
356 #endif
354 -
357 +void rrdpush_reset_destinations_postpone_time(RRDHOST *host);
358 +const char *stream_handshake_error_to_string(STREAM_HANDSHAKE handshake_error);
359 +void stream_capabilities_to_json_array(BUFFER *wb, STREAM_CAPABILITIES caps, const char *key);
360 void rrdpush_receive_log_status(struct receiver_state *rpt, const char *msg, const char *status);
361 void log_receiver_capabilities(struct receiver_state *rpt);
362 void log_sender_capabilities(struct sender_state *s);
streaming/sender.c
+108 -104
@@ -29,7 +29,6 @@
29 #endif
30
31 extern struct config stream_config;
32 -extern int netdata_use_ssl_on_stream;
32 extern char *netdata_ssl_ca_path;
33 extern char *netdata_ssl_ca_file;
34
@@ -320,6 +319,10 @@ static void rrdpush_sender_after_connect(RRDHOST *host) {
319 }
320
321 static inline void rrdpush_sender_thread_close_socket(RRDHOST *host) {
322 +#ifdef ENABLE_HTTPS
323 + netdata_ssl_close(&host->sender->ssl);
324 +#endif
325 +
326 if(host->sender->rrdpush_sender_socket != -1) {
327 close(host->sender->rrdpush_sender_socket);
328 host->sender->rrdpush_sender_socket = -1;
@@ -480,6 +483,53 @@ static inline bool rrdpush_sender_validate_response(RRDHOST *host, struct sender
483 return false;
484 }
485
486 +static bool rrdpush_sender_connect_ssl(struct sender_state *s) {
487 +#ifdef ENABLE_HTTPS
488 + RRDHOST *host = s->host;
489 + bool ssl_required = host->destination && host->destination->ssl;
490 +
491 + netdata_ssl_close(&host->sender->ssl);
492 +
493 + if(!ssl_required)
494 + return true;
495 +
496 + if (netdata_ssl_open(&host->sender->ssl, netdata_ssl_streaming_sender_ctx, s->rrdpush_sender_socket)) {
497 + if(!netdata_ssl_connect(&host->sender->ssl)) {
498 + // couldn't connect
499 +
500 + worker_is_busy(WORKER_SENDER_JOB_DISCONNECT_SSL_ERROR);
501 + rrdpush_sender_thread_close_socket(host);
502 + host->destination->last_error = "SSL error";
503 + host->destination->last_handshake = STREAM_HANDSHAKE_ERROR_SSL_ERROR;
504 + host->destination->postpone_reconnection_until = now_realtime_sec() + 5 * 60;
505 + return false;
506 + }
507 +
508 + if (netdata_ssl_validate_certificate_sender &&
509 + security_test_certificate(host->sender->ssl.conn)) {
510 + // certificate is not valid
511 +
512 + worker_is_busy(WORKER_SENDER_JOB_DISCONNECT_SSL_ERROR);
513 + error("SSL: closing the stream connection, because the server SSL certificate is not valid.");
514 + rrdpush_sender_thread_close_socket(host);
515 + host->destination->last_error = "invalid SSL certificate";
516 + host->destination->last_handshake = STREAM_HANDSHAKE_ERROR_INVALID_CERTIFICATE;
517 + host->destination->postpone_reconnection_until = now_realtime_sec() + 5 * 60;
518 + return false;
519 + }
520 +
521 + return true;
522 + }
523 +
524 + // failed to establish connection
525 + return false;
526 +
527 +#else
528 + // SSL is not enabled
529 + return true;
530 +#endif
531 +}
532 +
533 static bool rrdpush_sender_thread_connect_to_parent(RRDHOST *host, int default_port, int timeout, struct sender_state *s) {
534
535 struct timeval tv = {
@@ -507,35 +557,6 @@ static bool rrdpush_sender_thread_connect_to_parent(RRDHOST *host, int default_p
557
558 // info("STREAM %s [send to %s]: initializing communication...", rrdhost_hostname(host), s->connected_to);
559
510 -#ifdef ENABLE_HTTPS
511 - if(netdata_ssl_client_ctx){
512 - host->sender->ssl.flags = NETDATA_SSL_START;
513 - if (!host->sender->ssl.conn){
514 - host->sender->ssl.conn = SSL_new(netdata_ssl_client_ctx);
515 - if(!host->sender->ssl.conn){
516 - error("Failed to allocate SSL structure.");
517 - host->sender->ssl.flags = NETDATA_SSL_NO_HANDSHAKE;
518 - }
519 - }
520 - else{
521 - SSL_clear(host->sender->ssl.conn);
522 - }
523 -
524 - if (host->sender->ssl.conn)
525 - {
526 - if (SSL_set_fd(host->sender->ssl.conn, s->rrdpush_sender_socket) != 1) {
527 - error("Failed to set the socket to the SSL on socket fd %d.", s->rrdpush_sender_socket);
528 - host->sender->ssl.flags = NETDATA_SSL_NO_HANDSHAKE;
529 - } else{
530 - host->sender->ssl.flags = NETDATA_SSL_HANDSHAKE_COMPLETE;
531 - }
532 - }
533 - }
534 - else {
535 - host->sender->ssl.flags = NETDATA_SSL_NO_HANDSHAKE;
536 - }
537 -#endif
538 -
560 // reset our capabilities to default
561 s->capabilities = stream_our_capabilities();
562
@@ -651,43 +672,8 @@ static bool rrdpush_sender_thread_connect_to_parent(RRDHOST *host, int default_p
672 http[eol] = 0x00;
673 rrdpush_clean_encoded(&se);
674
654 -#ifdef ENABLE_HTTPS
655 - if (!host->sender->ssl.flags) {
656 - ERR_clear_error();
657 - SSL_set_connect_state(host->sender->ssl.conn);
658 - int err = SSL_connect(host->sender->ssl.conn);
659 - if (err != 1){
660 - err = SSL_get_error(host->sender->ssl.conn, err);
661 - error("SSL cannot connect with the server: %s ",ERR_error_string((long)SSL_get_error(host->sender->ssl.conn,err),NULL));
662 - if (netdata_use_ssl_on_stream == NETDATA_SSL_FORCE) {
663 - worker_is_busy(WORKER_SENDER_JOB_DISCONNECT_SSL_ERROR);
664 - rrdpush_sender_thread_close_socket(host);
665 - host->destination->last_error = "SSL error";
666 - host->destination->last_handshake = STREAM_HANDSHAKE_ERROR_SSL_ERROR;
667 - host->destination->postpone_reconnection_until = now_realtime_sec() + 5 * 60;
668 - return false;
669 - }
670 - else {
671 - host->sender->ssl.flags = NETDATA_SSL_NO_HANDSHAKE;
672 - }
673 - }
674 - else {
675 - if (netdata_use_ssl_on_stream == NETDATA_SSL_FORCE) {
676 - if (netdata_ssl_validate_server == NETDATA_SSL_VALID_CERTIFICATE) {
677 - if ( security_test_certificate(host->sender->ssl.conn)) {
678 - worker_is_busy(WORKER_SENDER_JOB_DISCONNECT_SSL_ERROR);
679 - error("Closing the stream connection, because the server SSL certificate is not valid.");
680 - rrdpush_sender_thread_close_socket(host);
681 - host->destination->last_error = "invalid SSL certificate";
682 - host->destination->last_handshake = STREAM_HANDSHAKE_ERROR_INVALID_CERTIFICATE;
683 - host->destination->postpone_reconnection_until = now_realtime_sec() + 5 * 60;
684 - return false;
685 - }
686 - }
687 - }
688 - }
689 - }
690 -#endif
675 + if(!rrdpush_sender_connect_ssl(s))
676 + return false;
677
678 ssize_t bytes;
679
@@ -733,6 +719,12 @@ static bool rrdpush_sender_thread_connect_to_parent(RRDHOST *host, int default_p
719 return false;
720 }
721
722 + if(sock_setnonblock(s->rrdpush_sender_socket) < 0)
723 + error("STREAM %s [send to %s]: cannot set non-blocking mode for socket.", rrdhost_hostname(host), s->connected_to);
724 +
725 + if(sock_enlarge_out(s->rrdpush_sender_socket) < 0)
726 + error("STREAM %s [send to %s]: cannot enlarge the socket buffer.", rrdhost_hostname(host), s->connected_to);
727 +
728 http[bytes] = '\0';
729 debug(D_STREAM, "Response to sender from far end: %s", http);
730 if(!rrdpush_sender_validate_response(host, s, http, bytes))
@@ -749,12 +741,6 @@ static bool rrdpush_sender_thread_connect_to_parent(RRDHOST *host, int default_p
741
742 log_sender_capabilities(s);
743
752 - if(sock_setnonblock(s->rrdpush_sender_socket) < 0)
753 - error("STREAM %s [send to %s]: cannot set non-blocking mode for socket.", rrdhost_hostname(host), s->connected_to);
754 -
755 - if(sock_enlarge_out(s->rrdpush_sender_socket) < 0)
756 - error("STREAM %s [send to %s]: cannot enlarge the socket buffer.", rrdhost_hostname(host), s->connected_to);
757 -
744 debug(D_STREAM, "STREAM: Connected on fd %d...", s->rrdpush_sender_socket);
745
746 return true;
@@ -819,9 +805,8 @@ static ssize_t attempt_to_send(struct sender_state *s) {
805 debug(D_STREAM, "STREAM: Sending data. Buffer r=%zu w=%zu s=%zu, next chunk=%zu", cb->read, cb->write, cb->size, outstanding);
806
807 #ifdef ENABLE_HTTPS
822 - SSL *conn = s->ssl.conn ;
823 - if(conn && s->ssl.flags == NETDATA_SSL_HANDSHAKE_COMPLETE)
824 - ret = netdata_ssl_write(conn, chunk, outstanding);
808 + if(SSL_connection(&s->ssl))
809 + ret = netdata_ssl_write(&s->ssl, chunk, outstanding);
810 else
811 ret = send(s->rrdpush_sender_socket, chunk, outstanding, MSG_DONTWAIT);
812 #else
@@ -852,25 +837,17 @@ static ssize_t attempt_to_send(struct sender_state *s) {
837 }
838
839 static ssize_t attempt_read(struct sender_state *s) {
855 - ssize_t ret = 0;
840 + ssize_t ret;
841
842 #ifdef ENABLE_HTTPS
858 - if (s->ssl.conn && s->ssl.flags == NETDATA_SSL_HANDSHAKE_COMPLETE) {
859 - size_t desired = sizeof(s->read_buffer) - s->read_len - 1;
860 - ret = netdata_ssl_read(s->ssl.conn, s->read_buffer, desired);
861 - if (ret > 0 ) {
862 - s->read_len += (int)ret;
863 - return ret;
864 - }
865 -
866 - if (ret == -1) {
867 - worker_is_busy(WORKER_SENDER_JOB_DISCONNECT_SSL_ERROR);
868 - rrdpush_sender_thread_close_socket(s->host);
869 - }
870 - return ret;
871 - }
872 -#endif
843 + if (SSL_connection(&s->ssl))
844 + ret = netdata_ssl_read(&s->ssl, s->read_buffer + s->read_len, sizeof(s->read_buffer) - s->read_len - 1);
845 + else
846 + ret = recv(s->rrdpush_sender_socket, s->read_buffer + s->read_len, sizeof(s->read_buffer) - s->read_len - 1,MSG_DONTWAIT);
847 +#else
848 ret = recv(s->rrdpush_sender_socket, s->read_buffer + s->read_len, sizeof(s->read_buffer) - s->read_len - 1,MSG_DONTWAIT);
849 +#endif
850 +
851 if (ret > 0) {
852 s->read_len += ret;
853 return ret;
@@ -879,6 +856,12 @@ static ssize_t attempt_read(struct sender_state *s) {
856 if (ret < 0 && (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR))
857 return ret;
858
859 +#ifdef ENABLE_HTTPS
860 + if (SSL_connection(&s->ssl))
861 + worker_is_busy(WORKER_SENDER_JOB_DISCONNECT_SSL_ERROR);
862 + else
863 +#endif
864 +
865 if (ret == 0 || errno == ECONNRESET) {
866 worker_is_busy(WORKER_SENDER_JOB_DISCONNECT_PARENT_CLOSED);
867 error("STREAM %s [send to %s]: connection closed by far end.", rrdhost_hostname(s->host), s->connected_to);
@@ -887,6 +870,7 @@ static ssize_t attempt_read(struct sender_state *s) {
870 worker_is_busy(WORKER_SENDER_JOB_DISCONNECT_RECEIVE_ERROR);
871 error("STREAM %s [send to %s]: error during receive (%zd) - closing connection.", rrdhost_hostname(s->host), s->connected_to, ret);
872 }
873 +
874 rrdpush_sender_thread_close_socket(s->host);
875
876 return ret;
@@ -1096,6 +1080,8 @@ static bool rrdhost_set_sender(RRDHOST *host) {
1080 }
1081 netdata_mutex_unlock(&host->sender->mutex);
1082
1083 + rrdpush_reset_destinations_postpone_time(host);
1084 +
1085 return ret;
1086 }
1087
@@ -1108,6 +1094,8 @@ static void rrdhost_clear_sender___while_having_sender_mutex(RRDHOST *host) {
1094 host->sender->exit.reason = NULL;
1095 rrdhost_flag_clear(host, RRDHOST_FLAG_RRDPUSH_SENDER_SPAWN | RRDHOST_FLAG_RRDPUSH_SENDER_CONNECTED | RRDHOST_FLAG_RRDPUSH_SENDER_READY_4_METRICS);
1096 }
1097 +
1098 + rrdpush_reset_destinations_postpone_time(host);
1099 }
1100
1101 static bool rrdhost_sender_should_exit(struct sender_state *s) {
@@ -1134,7 +1122,7 @@ static bool rrdhost_sender_should_exit(struct sender_state *s) {
1122
1123 if(unlikely(rrdhost_flag_check(s->host, RRDHOST_FLAG_ORPHAN))) {
1124 if(!s->exit.reason)
1137 - s->exit.reason = "RECEIVER LEFT";
1125 + s->exit.reason = "RECEIVER LEFT (ORPHAN HOST)";
1126 return true;
1127 }
1128
@@ -1162,6 +1150,32 @@ static void rrdpush_sender_thread_cleanup_callback(void *ptr) {
1150 freez(s);
1151 }
1152
1153 +void rrdpush_initialize_ssl_ctx(RRDHOST *host) {
1154 +#ifdef ENABLE_HTTPS
1155 + static SPINLOCK sp = NETDATA_SPINLOCK_INITIALIZER;
1156 + netdata_spinlock_lock(&sp);
1157 +
1158 + if(netdata_ssl_streaming_sender_ctx || !host) {
1159 + netdata_spinlock_unlock(&sp);
1160 + return;
1161 + }
1162 +
1163 + for(struct rrdpush_destinations *d = host->destinations; d ; d = d->next) {
1164 + if (d->ssl) {
1165 + // we need to initialize SSL
1166 +
1167 + netdata_ssl_initialize_ctx(NETDATA_SSL_STREAMING_SENDER_CTX);
1168 + ssl_security_location_for_context(netdata_ssl_streaming_sender_ctx, netdata_ssl_ca_file, netdata_ssl_ca_path);
1169 +
1170 + // stop the loop
1171 + break;
1172 + }
1173 + }
1174 +
1175 + netdata_spinlock_unlock(&sp);
1176 +#endif
1177 +}
1178 +
1179 void *rrdpush_sender_thread(void *ptr) {
1180 worker_register("STREAMSND");
1181 worker_register_job_name(WORKER_SENDER_JOB_CONNECT, "connect");
@@ -1206,17 +1220,7 @@ void *rrdpush_sender_thread(void *ptr) {
1220 return NULL;
1221 }
1222
1209 -#ifdef ENABLE_HTTPS
1210 - if (netdata_use_ssl_on_stream & NETDATA_SSL_FORCE ) {
1211 - static SPINLOCK sp = NETDATA_SPINLOCK_INITIALIZER;
1212 - netdata_spinlock_lock(&sp);
1213 - if(!netdata_ssl_client_ctx) {
1214 - security_start_ssl(NETDATA_SSL_CONTEXT_STREAMING);
1215 - ssl_security_location_for_context(netdata_ssl_client_ctx, netdata_ssl_ca_file, netdata_ssl_ca_path);
1216 - }
1217 - netdata_spinlock_unlock(&sp);
1218 - }
1219 -#endif
1223 + rrdpush_initialize_ssl_ctx(s->host);
1224
1225 info("STREAM %s [send]: thread created (task id %d)", rrdhost_hostname(s->host), gettid());
1226
web/api/queries/query.c
-1
@@ -3291,7 +3291,6 @@ static void rrd2rrdr_convert_values_to_percentage_of_total(RRDR *r) {
3291
3292 static RRDR *rrd2rrdr_group_by_finalize(RRDR *r_tmp) {
3293 QUERY_TARGET *qt = r_tmp->internal.qt;
3294 - RRDR_OPTIONS options = qt->window.options;
3294
3295 if(!r_tmp->group_by.r) {
3296 // v1 query
web/server/static/static-threaded.c
+20 -39
@@ -211,58 +211,32 @@ static void *web_server_add_callback(POLLINFO *pi, short int *events, void *data
211 }
212
213 #ifdef ENABLE_HTTPS
214 - if ((!web_client_check_unix(w)) && (netdata_ssl_srv_ctx)) {
215 - if( sock_delnonblock(w->ifd) < 0 ){
216 - error("Web server cannot remove the non-blocking flag from socket %d",w->ifd);
217 - }
214 + if ((!web_client_check_unix(w)) && (netdata_ssl_web_server_ctx)) {
215 + sock_delnonblock(w->ifd);
216
217 //Read the first 7 bytes from the message, but the message
218 //is not removed from the queue, because we are using MSG_PEEK
219 char test[8];
222 - if ( recv(w->ifd,test, 7,MSG_PEEK) == 7 ) {
223 - test[7] = 0x00;
220 + if ( recv(w->ifd,test, 7, MSG_PEEK) == 7 ) {
221 + test[7] = '\0';
222 }
223 else {
226 - //Case I do not have success to read 7 bytes,
227 - //this means that the mensage was not completely read, so
228 - //I cannot identify it yet.
224 + // we couldn't read 7 bytes
225 sock_setnonblock(w->ifd);
226 goto cleanup;
227 }
228
233 - //The next two ifs are not together because I am reusing SSL structure
234 - if (!w->ssl.conn)
235 - {
236 - w->ssl.conn = SSL_new(netdata_ssl_srv_ctx);
237 - if ( w->ssl.conn ) {
238 - SSL_set_accept_state(w->ssl.conn);
239 - } else {
240 - error("Failed to create SSL context on socket fd %d.", w->ifd);
241 - if (test[0] < 0x18){
242 - WEB_CLIENT_IS_DEAD(w);
243 - sock_setnonblock(w->ifd);
244 - goto cleanup;
245 - }
246 - }
229 + if(test[0] > 0x17) {
230 + // no SSL
231 + netdata_ssl_close(&w->ssl); // free any previous SSL data
232 }
248 -
249 - if (w->ssl.conn) {
250 - if (SSL_set_fd(w->ssl.conn, w->ifd) != 1) {
251 - error("Failed to set the socket to the SSL on socket fd %d.", w->ifd);
252 - //The client is not set dead, because I received a normal HTTP request
253 - //instead a Client Hello(HTTPS).
254 - if ( test[0] < 0x18 ){
255 - WEB_CLIENT_IS_DEAD(w);
256 - }
257 - }
258 - else{
259 - w->ssl.flags = security_process_accept(w->ssl.conn, (int)test[0]);
260 - }
233 + else {
234 + // SSL
235 + if(!netdata_ssl_open(&w->ssl, netdata_ssl_web_server_ctx, w->ifd) || !netdata_ssl_accept(&w->ssl))
236 + WEB_CLIENT_IS_DEAD(w);
237 }
238
239 sock_setnonblock(w->ifd);
264 - } else{
265 - w->ssl.flags = NETDATA_SSL_NO_HANDSHAKE;
240 }
241 #endif
242
@@ -525,9 +499,15 @@ void *socket_listen_main_static_threaded(void *ptr) {
499 if(!api_sockets.opened)
500 fatal("LISTENER: no listen sockets available.");
501
502 + netdata_ssl_validate_certificate = !config_get_boolean(CONFIG_SECTION_WEB, "ssl skip certificate verification", !netdata_ssl_validate_certificate);
503 +
504 + if(!netdata_ssl_validate_certificate_sender)
505 + info("SSL: web server will skip SSL certificates verification.");
506 +
507 #ifdef ENABLE_HTTPS
529 - security_start_ssl(NETDATA_SSL_CONTEXT_SERVER);
508 + netdata_ssl_initialize_ctx(NETDATA_SSL_WEB_SERVER_CTX);
509 #endif
510 +
511 // 6 threads is the optimal value
512 // since 6 are the parallel connections browsers will do
513 // so, if the machine has more CPUs, avoid using resources unnecessarily
@@ -541,6 +521,7 @@ void *socket_listen_main_static_threaded(void *ptr) {
521 static_threaded_workers_count = config_get_number(CONFIG_SECTION_WEB, "web server threads", def_thread_count);
522
523 if (static_threaded_workers_count < 1) static_threaded_workers_count = 1;
524 +
525 #ifdef ENABLE_HTTPS
526 // See https://github.com/netdata/netdata/issues/11081#issuecomment-831998240 for more details
527 if (OPENSSL_VERSION_NUMBER < OPENSSL_VERSION_110) {
web/server/web_client.c
+38 -84
@@ -34,11 +34,10 @@ static inline int web_client_crock_socket(struct web_client *w __maybe_unused) {
34 return 0;
35 }
36
37 -static inline void web_client_enable_wait_from_ssl(struct web_client *w, int bytes) {
38 - int ssl_err = SSL_get_error(w->ssl.conn, bytes);
39 - if (ssl_err == SSL_ERROR_WANT_READ)
37 +static inline void web_client_enable_wait_from_ssl(struct web_client *w) {
38 + if (w->ssl.ssl_errno == SSL_ERROR_WANT_READ)
39 web_client_enable_ssl_wait_receive(w);
41 - else if (ssl_err == SSL_ERROR_WANT_WRITE)
40 + else if (w->ssl.ssl_errno == SSL_ERROR_WANT_WRITE)
41 web_client_enable_ssl_wait_send(w);
42 else {
43 web_client_disable_ssl_wait_receive(w);
@@ -99,15 +98,6 @@ static void web_client_reset_allocations(struct web_client *w, bool free_all) {
98 freez(w->post_payload);
99 w->post_payload = NULL;
100 w->post_payload_size = 0;
102 -
103 -#ifdef ENABLE_HTTPS
104 - if ((!web_client_check_unix(w)) && (netdata_ssl_srv_ctx)) {
105 - if (w->ssl.conn) {
106 - SSL_free(w->ssl.conn);
107 - w->ssl.conn = NULL;
108 - }
109 - }
110 -#endif
101 }
102 else {
103 // the web client is to be re-used
@@ -121,7 +111,6 @@ static void web_client_reset_allocations(struct web_client *w, bool free_all) {
111 buffer_reset(w->response.data);
112
113 // leave w->post_payload
124 - // leave w->ssl
114 }
115
116 freez(w->server_host);
@@ -794,12 +783,10 @@ static inline char *http_header_parse(struct web_client *w, char *s, int parse_u
783 // web_client_enable_deflate(w, 0);
784 }
785 }
797 -#ifdef ENABLE_HTTPS
786 else if(hash == hash_forwarded_proto && !strcasecmp(s, "X-Forwarded-Proto")) {
787 if(strcasestr(v, "https"))
800 - w->ssl.flags |= NETDATA_SSL_PROXY_HTTPS;
788 + w->flags |= WEB_CLIENT_FLAG_PROXY_HTTPS;
789 }
802 -#endif
790 else if(hash == hash_forwarded_host && !strcasecmp(s, "X-Forwarded-Host")) {
791 char buffer[NI_MAXHOST];
792 strncpyz(buffer, v, ((size_t)(ve - v) < sizeof(buffer) - 1 ? (size_t)(ve - v) : sizeof(buffer) - 1));
@@ -839,7 +826,7 @@ static inline char *web_client_valid_method(struct web_client *w, char *s) {
826 s = &s[7];
827
828 #ifdef ENABLE_HTTPS
842 - if (w->ssl.flags && web_client_is_using_ssl_force(w)){
829 + if (!SSL_connection(&w->ssl) && web_client_is_using_ssl_force(w)) {
830 w->header_parse_tries = 0;
831 w->header_parse_last_size = 0;
832 web_client_disable_wait_receive(w);
@@ -980,8 +967,8 @@ static inline HTTP_VALIDATION http_request_validate(struct web_client *w) {
967 *ue = c;
968
969 #ifdef ENABLE_HTTPS
983 - if ( (!web_client_check_unix(w)) && (netdata_ssl_srv_ctx) ) {
984 - if ((w->ssl.conn) && ((w->ssl.flags & NETDATA_SSL_NO_HANDSHAKE) && (web_client_is_using_ssl_force(w) || web_client_is_using_ssl_default(w)) && (w->mode != WEB_CLIENT_MODE_STREAM)) ) {
970 + if ( (!web_client_check_unix(w)) && (netdata_ssl_web_server_ctx) ) {
971 + if (!w->ssl.conn && (web_client_is_using_ssl_force(w) || web_client_is_using_ssl_default(w)) && (w->mode != WEB_CLIENT_MODE_STREAM)) {
972 w->header_parse_tries = 0;
973 w->header_parse_last_size = 0;
974 web_client_disable_wait_receive(w);
@@ -1010,16 +997,15 @@ static inline ssize_t web_client_send_data(struct web_client *w,const void *buf,
997 {
998 ssize_t bytes;
999 #ifdef ENABLE_HTTPS
1013 - if ( (!web_client_check_unix(w)) && (netdata_ssl_srv_ctx) ) {
1014 - if ( ( w->ssl.conn ) && ( !w->ssl.flags ) ){
1015 - bytes = netdata_ssl_write(w->ssl.conn, buf, len) ;
1016 - web_client_enable_wait_from_ssl(w, bytes);
1017 - } else {
1018 - bytes = send(w->ofd,buf, len , flags);
1000 + if ((!web_client_check_unix(w)) && (netdata_ssl_web_server_ctx)) {
1001 + if (SSL_connection(&w->ssl)) {
1002 + bytes = netdata_ssl_write(&w->ssl, buf, len) ;
1003 + web_client_enable_wait_from_ssl(w);
1004 }
1020 - } else {
1005 + else
1006 + bytes = send(w->ofd,buf, len , flags);
1007 + } else
1008 bytes = send(w->ofd,buf, len , flags);
1022 - }
1009 #else
1010 bytes = send(w->ofd, buf, len, flags);
1011 #endif
@@ -1156,10 +1142,10 @@ static inline void web_client_send_http_header(struct web_client *w) {
1142 size_t count = 0;
1143 ssize_t bytes;
1144 #ifdef ENABLE_HTTPS
1159 - if ( (!web_client_check_unix(w)) && (netdata_ssl_srv_ctx) ) {
1160 - if ( ( w->ssl.conn ) && ( w->ssl.flags == NETDATA_SSL_HANDSHAKE_COMPLETE ) ) {
1161 - bytes = netdata_ssl_write(w->ssl.conn, buffer_tostring(w->response.header_output), buffer_strlen(w->response.header_output));
1162 - web_client_enable_wait_from_ssl(w, bytes);
1145 + if ( (!web_client_check_unix(w)) && (netdata_ssl_web_server_ctx) ) {
1146 + if (SSL_connection(&w->ssl)) {
1147 + bytes = netdata_ssl_write(&w->ssl, buffer_tostring(w->response.header_output), buffer_strlen(w->response.header_output));
1148 + web_client_enable_wait_from_ssl(w);
1149 }
1150 else {
1151 while((bytes = send(w->ofd, buffer_tostring(w->response.header_output), buffer_strlen(w->response.header_output), 0)) == -1) {
@@ -1260,11 +1246,11 @@ static inline int web_client_switch_host(RRDHOST *host, struct web_client *w, ch
1246 if(!url) { //no delim found
1247 debug(D_WEB_CLIENT, "%llu: URL doesn't end with / generating redirect.", w->id);
1248 char *protocol, *url_host;
1249 + protocol = (
1250 #ifdef ENABLE_HTTPS
1264 - protocol = ((w->ssl.conn && !w->ssl.flags) || w->ssl.flags & NETDATA_SSL_PROXY_HTTPS) ? "https" : "http";
1265 -#else
1266 - protocol = "http";
1251 + SSL_connection(&w->ssl) ||
1252 #endif
1253 + (w->flags & WEB_CLIENT_FLAG_PROXY_HTTPS)) ? "https" : "http";
1254
1255 url_host = w->forwarded_host;
1256 if(!url_host) {
@@ -1948,11 +1934,12 @@ ssize_t web_client_receive(struct web_client *w)
1934 buffer_need_bytes(w->response.data, NETDATA_WEB_REQUEST_INITIAL_SIZE);
1935
1936 #ifdef ENABLE_HTTPS
1951 - if ( (!web_client_check_unix(w)) && (netdata_ssl_srv_ctx) ) {
1952 - if ( ( w->ssl.conn ) && (!w->ssl.flags)) {
1953 - bytes = netdata_ssl_read(w->ssl.conn, &w->response.data->buffer[w->response.data->len], (size_t) (left - 1));
1954 - web_client_enable_wait_from_ssl(w, bytes);
1955 - }else {
1937 + if ( (!web_client_check_unix(w)) && (netdata_ssl_web_server_ctx) ) {
1938 + if (SSL_connection(&w->ssl)) {
1939 + bytes = netdata_ssl_read(&w->ssl, &w->response.data->buffer[w->response.data->len], (size_t) (left - 1));
1940 + web_client_enable_wait_from_ssl(w);
1941 + }
1942 + else {
1943 bytes = recv(w->ifd, &w->response.data->buffer[w->response.data->len], (size_t) (left - 1), MSG_DONTWAIT);
1944 }
1945 }
@@ -1985,26 +1972,6 @@ ssize_t web_client_receive(struct web_client *w)
1972 }
1973
1974
1988 -int web_client_socket_is_now_used_for_streaming(struct web_client *w) {
1989 - // prevent the web_client from closing the streaming socket
1990 -
1991 - WEB_CLIENT_IS_DEAD(w);
1992 -
1993 - if(web_server_mode == WEB_SERVER_MODE_STATIC_THREADED) {
1994 - web_client_flag_set(w, WEB_CLIENT_FLAG_DONT_CLOSE_SOCKET);
1995 - }
1996 - else {
1997 - if(w->ifd == w->ofd)
1998 - w->ifd = w->ofd = -1;
1999 - else
2000 - w->ifd = -1;
2001 - }
2002 -
2003 - buffer_flush(w->response.data);
2004 -
2005 - return HTTP_RESP_OK;
2006 -}
2007 -
1975 void web_client_decode_path_and_query_string(struct web_client *w, const char *path_and_query_string) {
1976 char buffer[NETDATA_WEB_REQUEST_URL_SIZE + 2];
1977 buffer[0] = '\0';
@@ -2052,25 +2019,6 @@ void web_client_decode_path_and_query_string(struct web_client *w, const char *p
2019 }
2020 }
2021
2055 -#ifdef ENABLE_HTTPS
2056 -void web_client_reuse_ssl(struct web_client *w) {
2057 - if (netdata_ssl_srv_ctx) {
2058 - if (w->ssl.conn) {
2059 - SSL_SESSION *session = SSL_get_session(w->ssl.conn);
2060 - SSL *old = w->ssl.conn;
2061 - w->ssl.conn = SSL_new(netdata_ssl_srv_ctx);
2062 - if (session) {
2063 -#if OPENSSL_VERSION_NUMBER >= OPENSSL_VERSION_111
2064 - if (SSL_SESSION_is_resumable(session))
2065 -#endif
2066 - SSL_set_session(w->ssl.conn, session);
2067 - }
2068 - SSL_free(old);
2069 - }
2070 - }
2071 -}
2072 -#endif
2073 -
2022 void web_client_zero(struct web_client *w) {
2023 // zero everything about it - but keep the buffers
2024
@@ -2085,8 +2033,7 @@ void web_client_zero(struct web_client *w) {
2033 BUFFER *b6 = w->url_query_string_decoded;
2034
2035 #ifdef ENABLE_HTTPS
2088 - web_client_reuse_ssl(w);
2089 - SSL *ssl = w->ssl.conn;
2036 + NETDATA_SSL ssl = w->ssl;
2037 #endif
2038
2039 size_t use_count = w->use_count;
@@ -2100,9 +2047,7 @@ void web_client_zero(struct web_client *w) {
2047 w->use_count = use_count;
2048
2049 #ifdef ENABLE_HTTPS
2103 - w->ssl.conn = ssl;
2104 - w->ssl.flags = NETDATA_SSL_START;
2105 - debug(D_WEB_CLIENT_ACCESS,"Reusing SSL structure with (w->ssl = NULL, w->accepted = %u)", w->ssl.flags);
2050 + w->ssl = ssl;
2051 #endif
2052
2053 // restore the pointers of the buffers
@@ -2116,6 +2061,11 @@ void web_client_zero(struct web_client *w) {
2061
2062 struct web_client *web_client_create(size_t *statistics_memory_accounting) {
2063 struct web_client *w = (struct web_client *)callocz(1, sizeof(struct web_client));
2064 +
2065 +#ifdef ENABLE_HTTPS
2066 + w->ssl = NETDATA_SSL_UNSET_CONNECTION;
2067 +#endif
2068 +
2069 w->use_count = 1;
2070 w->statistics.memory_accounting = statistics_memory_accounting;
2071
@@ -2132,6 +2082,10 @@ struct web_client *web_client_create(size_t *statistics_memory_accounting) {
2082 }
2083
2084 void web_client_free(struct web_client *w) {
2085 +#ifdef ENABLE_HTTPS
2086 + netdata_ssl_close(&w->ssl);
2087 +#endif
2088 +
2089 web_client_reset_allocations(w, true);
2090
2091 __atomic_sub_fetch(w->statistics.memory_accounting, sizeof(struct web_client), __ATOMIC_RELAXED);
web/server/web_client.h
+3 -7
@@ -52,6 +52,8 @@ typedef enum web_client_flags {
52
53 WEB_CLIENT_FLAG_SSL_WAIT_RECEIVE = 1 << 11, // if set, we are waiting more input data from an ssl conn
54 WEB_CLIENT_FLAG_SSL_WAIT_SEND = 1 << 12, // if set, we have data to send to the client from an ssl conn
55 +
56 + WEB_CLIENT_FLAG_PROXY_HTTPS = 1 << 13, // if set, the client reaches us via an https proxy
57 } WEB_CLIENT_FLAGS;
58
59 #define web_client_flag_check(w, flag) ((w)->flags & (flag))
@@ -168,7 +170,7 @@ struct web_client {
170 size_t pollinfo_filecopy_slot; // POLLINFO slot of the file read
171
172 #ifdef ENABLE_HTTPS
171 - struct netdata_ssl ssl;
173 + NETDATA_SSL ssl;
174 #endif
175
176 struct { // A callback to check if the query should be interrupted / stopped
@@ -213,16 +215,10 @@ int mysendfile(struct web_client *w, char *filename);
215 void web_client_build_http_header(struct web_client *w);
216 char *strip_control_characters(char *url);
217
216 -int web_client_socket_is_now_used_for_streaming(struct web_client *w);
217 -
218 void web_client_zero(struct web_client *w);
219 struct web_client *web_client_create(size_t *statistics_memory_accounting);
220 void web_client_free(struct web_client *w);
221
222 -#ifdef ENABLE_HTTPS
223 -void web_client_reuse_ssl(struct web_client *w);
224 -#endif
225 -
222 #include "web/api/web_api_v1.h"
223 #include "web/api/web_api_v2.h"
224 #include "daemon/common.h"
web/server/web_client_cache.c
+5 -5
@@ -104,11 +104,6 @@ struct web_client *web_client_get_from_cache(void) {
104 // allocate it
105 w = web_client_create(&netdata_buffers_statistics.buffers_web);
106
107 -#ifdef ENABLE_HTTPS
108 - w->ssl.flags = NETDATA_SSL_START;
109 - debug(D_WEB_CLIENT_ACCESS,"Starting SSL structure with (w->ssl = NULL, w->accepted = %u)", w->ssl.flags);
110 -#endif
111 -
107 netdata_spinlock_lock(&web_clients_cache.used.spinlock);
108 web_clients_cache.used.allocated++;
109 }
@@ -127,6 +122,11 @@ struct web_client *web_client_get_from_cache(void) {
122 }
123
124 void web_client_release_to_cache(struct web_client *w) {
125 +
126 +#ifdef ENABLE_HTTPS
127 + netdata_ssl_close(&w->ssl);
128 +#endif
129 +
130 // unlink it from the used
131 netdata_spinlock_lock(&web_clients_cache.used.spinlock);
132 DOUBLE_LINKED_LIST_REMOVE_ITEM_UNSAFE(web_clients_cache.used.head, w, cache.prev, cache.next);