123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260 |
- #include "aclk_common.h"
- #include "../../daemon/common.h"
- #ifdef ENABLE_ACLK
- #include <libwebsockets.h>
- #endif
- netdata_mutex_t aclk_shared_state_mutex = NETDATA_MUTEX_INITIALIZER;
- int aclk_disable_runtime = 0;
- int aclk_kill_link = 0;
- struct aclk_shared_state aclk_shared_state = {
- .version_neg = 0,
- .version_neg_wait_till = 0
- };
- struct {
- ACLK_PROXY_TYPE type;
- const char *url_str;
- } supported_proxy_types[] = {
- { .type = PROXY_TYPE_SOCKS5, .url_str = "socks5" ACLK_PROXY_PROTO_ADDR_SEPARATOR },
- { .type = PROXY_TYPE_SOCKS5, .url_str = "socks5h" ACLK_PROXY_PROTO_ADDR_SEPARATOR },
- { .type = PROXY_TYPE_HTTP, .url_str = "http" ACLK_PROXY_PROTO_ADDR_SEPARATOR },
- { .type = PROXY_TYPE_UNKNOWN, .url_str = NULL },
- };
- const char *aclk_proxy_type_to_s(ACLK_PROXY_TYPE *type)
- {
- switch (*type) {
- case PROXY_DISABLED:
- return "disabled";
- case PROXY_TYPE_HTTP:
- return "HTTP";
- case PROXY_TYPE_SOCKS5:
- return "SOCKS";
- default:
- return "Unknown";
- }
- }
- static inline ACLK_PROXY_TYPE aclk_find_proxy(const char *string)
- {
- int i = 0;
- while (supported_proxy_types[i].url_str) {
- if (!strncmp(supported_proxy_types[i].url_str, string, strlen(supported_proxy_types[i].url_str)))
- return supported_proxy_types[i].type;
- i++;
- }
- return PROXY_TYPE_UNKNOWN;
- }
- ACLK_PROXY_TYPE aclk_verify_proxy(const char *string)
- {
- if (!string)
- return PROXY_TYPE_UNKNOWN;
- while (*string == 0x20 && *string!=0) // Help coverity (compiler will remove)
- string++;
- if (!*string)
- return PROXY_TYPE_UNKNOWN;
- return aclk_find_proxy(string);
- }
- // helper function to censor user&password
- // for logging purposes
- void safe_log_proxy_censor(char *proxy)
- {
- size_t length = strlen(proxy);
- char *auth = proxy + length - 1;
- char *cur;
- while ((auth >= proxy) && (*auth != '@'))
- auth--;
- //if not found or @ is first char do nothing
- if (auth <= proxy)
- return;
- cur = strstr(proxy, ACLK_PROXY_PROTO_ADDR_SEPARATOR);
- if (!cur)
- cur = proxy;
- else
- cur += strlen(ACLK_PROXY_PROTO_ADDR_SEPARATOR);
- while (cur < auth) {
- *cur = 'X';
- cur++;
- }
- }
- static inline void safe_log_proxy_error(char *str, const char *proxy)
- {
- char *log = strdupz(proxy);
- safe_log_proxy_censor(log);
- error("%s Provided Value:\"%s\"", str, log);
- freez(log);
- }
- static inline int check_socks_enviroment(const char **proxy)
- {
- char *tmp = getenv("socks_proxy");
- if (!tmp)
- return 1;
- if (aclk_verify_proxy(tmp) == PROXY_TYPE_SOCKS5) {
- *proxy = tmp;
- return 0;
- }
- safe_log_proxy_error(
- "Environment var \"socks_proxy\" defined but of unknown format. Supported syntax: \"socks5[h]://[user:pass@]host:ip\".",
- tmp);
- return 1;
- }
- static inline int check_http_enviroment(const char **proxy)
- {
- char *tmp = getenv("http_proxy");
- if (!tmp)
- return 1;
- if (aclk_verify_proxy(tmp) == PROXY_TYPE_HTTP) {
- *proxy = tmp;
- return 0;
- }
- safe_log_proxy_error(
- "Environment var \"http_proxy\" defined but of unknown format. Supported syntax: \"http[s]://[user:pass@]host:ip\".",
- tmp);
- return 1;
- }
- const char *aclk_lws_wss_get_proxy_setting(ACLK_PROXY_TYPE *type)
- {
- const char *proxy = config_get(CONFIG_SECTION_CLOUD, ACLK_PROXY_CONFIG_VAR, ACLK_PROXY_ENV);
- *type = PROXY_DISABLED;
- if (strcmp(proxy, "none") == 0)
- return proxy;
- if (strcmp(proxy, ACLK_PROXY_ENV) == 0) {
- if (check_socks_enviroment(&proxy) == 0) {
- #ifdef LWS_WITH_SOCKS5
- *type = PROXY_TYPE_SOCKS5;
- return proxy;
- #else
- safe_log_proxy_error("socks_proxy environment variable set to use SOCKS5 proxy "
- "but Libwebsockets used doesn't have SOCKS5 support built in. "
- "Ignoring and checking for other options.",
- proxy);
- #endif
- }
- if (check_http_enviroment(&proxy) == 0)
- *type = PROXY_TYPE_HTTP;
- return proxy;
- }
- *type = aclk_verify_proxy(proxy);
- #ifndef LWS_WITH_SOCKS5
- if (*type == PROXY_TYPE_SOCKS5) {
- safe_log_proxy_error(
- "Config var \"" ACLK_PROXY_CONFIG_VAR
- "\" set to use SOCKS5 proxy but Libwebsockets used is built without support for SOCKS proxy. ACLK will be disabled.",
- proxy);
- }
- #endif
- if (*type == PROXY_TYPE_UNKNOWN) {
- *type = PROXY_DISABLED;
- safe_log_proxy_error(
- "Config var \"" ACLK_PROXY_CONFIG_VAR
- "\" defined but of unknown format. Supported syntax: \"socks5[h]://[user:pass@]host:ip\".",
- proxy);
- }
- return proxy;
- }
- // helper function to read settings only once (static)
- // as claiming, challenge/response and ACLK
- // read the same thing, no need to parse again
- const char *aclk_get_proxy(ACLK_PROXY_TYPE *type)
- {
- static const char *proxy = NULL;
- static ACLK_PROXY_TYPE proxy_type = PROXY_NOT_SET;
- if (proxy_type == PROXY_NOT_SET)
- proxy = aclk_lws_wss_get_proxy_setting(&proxy_type);
- *type = proxy_type;
- return proxy;
- }
- int aclk_decode_base_url(char *url, char **aclk_hostname, int *aclk_port)
- {
- int pos = 0;
- if (!strncmp("https://", url, 8)) {
- pos = 8;
- } else if (!strncmp("http://", url, 7)) {
- error("Cannot connect ACLK over %s -> unencrypted link is not supported", url);
- return 1;
- }
- int host_end = pos;
- while (url[host_end] != 0 && url[host_end] != '/' && url[host_end] != ':')
- host_end++;
- if (url[host_end] == 0) {
- *aclk_hostname = strdupz(url + pos);
- *aclk_port = 443;
- info("Setting ACLK target host=%s port=%d from %s", *aclk_hostname, *aclk_port, url);
- return 0;
- }
- if (url[host_end] == ':') {
- *aclk_hostname = callocz(host_end - pos + 1, 1);
- strncpy(*aclk_hostname, url + pos, host_end - pos);
- int port_end = host_end + 1;
- while (url[port_end] >= '0' && url[port_end] <= '9')
- port_end++;
- if (port_end - host_end > 6) {
- error("Port specified in %s is invalid", url);
- return 0;
- }
- *aclk_port = atoi(&url[host_end+1]);
- }
- if (url[host_end] == '/') {
- *aclk_port = 443;
- *aclk_hostname = callocz(1, host_end - pos + 1);
- strncpy(*aclk_hostname, url+pos, host_end - pos);
- }
- info("Setting ACLK target host=%s port=%d from %s", *aclk_hostname, *aclk_port, url);
- return 0;
- }
- struct label *add_aclk_host_labels(struct label *label) {
- #ifdef ENABLE_ACLK
- ACLK_PROXY_TYPE aclk_proxy;
- char *proxy_str;
- aclk_get_proxy(&aclk_proxy);
- switch(aclk_proxy) {
- case PROXY_TYPE_SOCKS5:
- proxy_str = "SOCKS5";
- break;
- case PROXY_TYPE_HTTP:
- proxy_str = "HTTP";
- break;
- default:
- proxy_str = "none";
- break;
- }
- label = add_label_to_list(label, "_aclk_impl", "Legacy", LABEL_SOURCE_AUTO);
- return add_label_to_list(label, "_aclk_proxy", proxy_str, LABEL_SOURCE_AUTO);
- #else
- return label;
- #endif
- }
|