aclk_common.c 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. #include "aclk_common.h"
  2. #include "../../daemon/common.h"
  3. #ifdef ENABLE_ACLK
  4. #include <libwebsockets.h>
  5. #endif
  6. netdata_mutex_t aclk_shared_state_mutex = NETDATA_MUTEX_INITIALIZER;
  7. int aclk_disable_runtime = 0;
  8. int aclk_kill_link = 0;
  9. struct aclk_shared_state aclk_shared_state = {
  10. .version_neg = 0,
  11. .version_neg_wait_till = 0
  12. };
  13. struct {
  14. ACLK_PROXY_TYPE type;
  15. const char *url_str;
  16. } supported_proxy_types[] = {
  17. { .type = PROXY_TYPE_SOCKS5, .url_str = "socks5" ACLK_PROXY_PROTO_ADDR_SEPARATOR },
  18. { .type = PROXY_TYPE_SOCKS5, .url_str = "socks5h" ACLK_PROXY_PROTO_ADDR_SEPARATOR },
  19. { .type = PROXY_TYPE_HTTP, .url_str = "http" ACLK_PROXY_PROTO_ADDR_SEPARATOR },
  20. { .type = PROXY_TYPE_UNKNOWN, .url_str = NULL },
  21. };
  22. const char *aclk_proxy_type_to_s(ACLK_PROXY_TYPE *type)
  23. {
  24. switch (*type) {
  25. case PROXY_DISABLED:
  26. return "disabled";
  27. case PROXY_TYPE_HTTP:
  28. return "HTTP";
  29. case PROXY_TYPE_SOCKS5:
  30. return "SOCKS";
  31. default:
  32. return "Unknown";
  33. }
  34. }
  35. static inline ACLK_PROXY_TYPE aclk_find_proxy(const char *string)
  36. {
  37. int i = 0;
  38. while (supported_proxy_types[i].url_str) {
  39. if (!strncmp(supported_proxy_types[i].url_str, string, strlen(supported_proxy_types[i].url_str)))
  40. return supported_proxy_types[i].type;
  41. i++;
  42. }
  43. return PROXY_TYPE_UNKNOWN;
  44. }
  45. ACLK_PROXY_TYPE aclk_verify_proxy(const char *string)
  46. {
  47. if (!string)
  48. return PROXY_TYPE_UNKNOWN;
  49. while (*string == 0x20 && *string!=0) // Help coverity (compiler will remove)
  50. string++;
  51. if (!*string)
  52. return PROXY_TYPE_UNKNOWN;
  53. return aclk_find_proxy(string);
  54. }
  55. // helper function to censor user&password
  56. // for logging purposes
  57. void safe_log_proxy_censor(char *proxy)
  58. {
  59. size_t length = strlen(proxy);
  60. char *auth = proxy + length - 1;
  61. char *cur;
  62. while ((auth >= proxy) && (*auth != '@'))
  63. auth--;
  64. //if not found or @ is first char do nothing
  65. if (auth <= proxy)
  66. return;
  67. cur = strstr(proxy, ACLK_PROXY_PROTO_ADDR_SEPARATOR);
  68. if (!cur)
  69. cur = proxy;
  70. else
  71. cur += strlen(ACLK_PROXY_PROTO_ADDR_SEPARATOR);
  72. while (cur < auth) {
  73. *cur = 'X';
  74. cur++;
  75. }
  76. }
  77. static inline void safe_log_proxy_error(char *str, const char *proxy)
  78. {
  79. char *log = strdupz(proxy);
  80. safe_log_proxy_censor(log);
  81. error("%s Provided Value:\"%s\"", str, log);
  82. freez(log);
  83. }
  84. static inline int check_socks_enviroment(const char **proxy)
  85. {
  86. char *tmp = getenv("socks_proxy");
  87. if (!tmp)
  88. return 1;
  89. if (aclk_verify_proxy(tmp) == PROXY_TYPE_SOCKS5) {
  90. *proxy = tmp;
  91. return 0;
  92. }
  93. safe_log_proxy_error(
  94. "Environment var \"socks_proxy\" defined but of unknown format. Supported syntax: \"socks5[h]://[user:pass@]host:ip\".",
  95. tmp);
  96. return 1;
  97. }
  98. static inline int check_http_enviroment(const char **proxy)
  99. {
  100. char *tmp = getenv("http_proxy");
  101. if (!tmp)
  102. return 1;
  103. if (aclk_verify_proxy(tmp) == PROXY_TYPE_HTTP) {
  104. *proxy = tmp;
  105. return 0;
  106. }
  107. safe_log_proxy_error(
  108. "Environment var \"http_proxy\" defined but of unknown format. Supported syntax: \"http[s]://[user:pass@]host:ip\".",
  109. tmp);
  110. return 1;
  111. }
  112. const char *aclk_lws_wss_get_proxy_setting(ACLK_PROXY_TYPE *type)
  113. {
  114. const char *proxy = config_get(CONFIG_SECTION_CLOUD, ACLK_PROXY_CONFIG_VAR, ACLK_PROXY_ENV);
  115. *type = PROXY_DISABLED;
  116. if (strcmp(proxy, "none") == 0)
  117. return proxy;
  118. if (strcmp(proxy, ACLK_PROXY_ENV) == 0) {
  119. if (check_socks_enviroment(&proxy) == 0) {
  120. #ifdef LWS_WITH_SOCKS5
  121. *type = PROXY_TYPE_SOCKS5;
  122. return proxy;
  123. #else
  124. safe_log_proxy_error("socks_proxy environment variable set to use SOCKS5 proxy "
  125. "but Libwebsockets used doesn't have SOCKS5 support built in. "
  126. "Ignoring and checking for other options.",
  127. proxy);
  128. #endif
  129. }
  130. if (check_http_enviroment(&proxy) == 0)
  131. *type = PROXY_TYPE_HTTP;
  132. return proxy;
  133. }
  134. *type = aclk_verify_proxy(proxy);
  135. #ifndef LWS_WITH_SOCKS5
  136. if (*type == PROXY_TYPE_SOCKS5) {
  137. safe_log_proxy_error(
  138. "Config var \"" ACLK_PROXY_CONFIG_VAR
  139. "\" set to use SOCKS5 proxy but Libwebsockets used is built without support for SOCKS proxy. ACLK will be disabled.",
  140. proxy);
  141. }
  142. #endif
  143. if (*type == PROXY_TYPE_UNKNOWN) {
  144. *type = PROXY_DISABLED;
  145. safe_log_proxy_error(
  146. "Config var \"" ACLK_PROXY_CONFIG_VAR
  147. "\" defined but of unknown format. Supported syntax: \"socks5[h]://[user:pass@]host:ip\".",
  148. proxy);
  149. }
  150. return proxy;
  151. }
  152. // helper function to read settings only once (static)
  153. // as claiming, challenge/response and ACLK
  154. // read the same thing, no need to parse again
  155. const char *aclk_get_proxy(ACLK_PROXY_TYPE *type)
  156. {
  157. static const char *proxy = NULL;
  158. static ACLK_PROXY_TYPE proxy_type = PROXY_NOT_SET;
  159. if (proxy_type == PROXY_NOT_SET)
  160. proxy = aclk_lws_wss_get_proxy_setting(&proxy_type);
  161. *type = proxy_type;
  162. return proxy;
  163. }
  164. int aclk_decode_base_url(char *url, char **aclk_hostname, int *aclk_port)
  165. {
  166. int pos = 0;
  167. if (!strncmp("https://", url, 8)) {
  168. pos = 8;
  169. } else if (!strncmp("http://", url, 7)) {
  170. error("Cannot connect ACLK over %s -> unencrypted link is not supported", url);
  171. return 1;
  172. }
  173. int host_end = pos;
  174. while (url[host_end] != 0 && url[host_end] != '/' && url[host_end] != ':')
  175. host_end++;
  176. if (url[host_end] == 0) {
  177. *aclk_hostname = strdupz(url + pos);
  178. *aclk_port = 443;
  179. info("Setting ACLK target host=%s port=%d from %s", *aclk_hostname, *aclk_port, url);
  180. return 0;
  181. }
  182. if (url[host_end] == ':') {
  183. *aclk_hostname = callocz(host_end - pos + 1, 1);
  184. strncpy(*aclk_hostname, url + pos, host_end - pos);
  185. int port_end = host_end + 1;
  186. while (url[port_end] >= '0' && url[port_end] <= '9')
  187. port_end++;
  188. if (port_end - host_end > 6) {
  189. error("Port specified in %s is invalid", url);
  190. return 0;
  191. }
  192. *aclk_port = atoi(&url[host_end+1]);
  193. }
  194. if (url[host_end] == '/') {
  195. *aclk_port = 443;
  196. *aclk_hostname = callocz(1, host_end - pos + 1);
  197. strncpy(*aclk_hostname, url+pos, host_end - pos);
  198. }
  199. info("Setting ACLK target host=%s port=%d from %s", *aclk_hostname, *aclk_port, url);
  200. return 0;
  201. }
  202. struct label *add_aclk_host_labels(struct label *label) {
  203. #ifdef ENABLE_ACLK
  204. ACLK_PROXY_TYPE aclk_proxy;
  205. char *proxy_str;
  206. aclk_get_proxy(&aclk_proxy);
  207. switch(aclk_proxy) {
  208. case PROXY_TYPE_SOCKS5:
  209. proxy_str = "SOCKS5";
  210. break;
  211. case PROXY_TYPE_HTTP:
  212. proxy_str = "HTTP";
  213. break;
  214. default:
  215. proxy_str = "none";
  216. break;
  217. }
  218. label = add_label_to_list(label, "_aclk_impl", "Legacy", LABEL_SOURCE_AUTO);
  219. return add_label_to_list(label, "_aclk_proxy", proxy_str, LABEL_SOURCE_AUTO);
  220. #else
  221. return label;
  222. #endif
  223. }