aclk_proxy.c 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. #include "aclk_proxy.h"
  2. #include "daemon/common.h"
  3. #define ACLK_PROXY_ENV "env"
  4. #define ACLK_PROXY_CONFIG_VAR "proxy"
  5. struct {
  6. ACLK_PROXY_TYPE type;
  7. const char *url_str;
  8. } supported_proxy_types[] = {
  9. { .type = PROXY_TYPE_SOCKS5, .url_str = "socks5" ACLK_PROXY_PROTO_ADDR_SEPARATOR },
  10. { .type = PROXY_TYPE_SOCKS5, .url_str = "socks5h" ACLK_PROXY_PROTO_ADDR_SEPARATOR },
  11. { .type = PROXY_TYPE_HTTP, .url_str = "http" ACLK_PROXY_PROTO_ADDR_SEPARATOR },
  12. { .type = PROXY_TYPE_UNKNOWN, .url_str = NULL },
  13. };
  14. static inline ACLK_PROXY_TYPE aclk_find_proxy(const char *string)
  15. {
  16. int i = 0;
  17. while (supported_proxy_types[i].url_str) {
  18. if (!strncmp(supported_proxy_types[i].url_str, string, strlen(supported_proxy_types[i].url_str)))
  19. return supported_proxy_types[i].type;
  20. i++;
  21. }
  22. return PROXY_TYPE_UNKNOWN;
  23. }
  24. ACLK_PROXY_TYPE aclk_verify_proxy(const char *string)
  25. {
  26. if (!string)
  27. return PROXY_TYPE_UNKNOWN;
  28. while (*string == 0x20)
  29. string++;
  30. if (!*string)
  31. return PROXY_TYPE_UNKNOWN;
  32. return aclk_find_proxy(string);
  33. }
  34. // helper function to censor user&password
  35. // for logging purposes
  36. void safe_log_proxy_censor(char *proxy)
  37. {
  38. size_t length = strlen(proxy);
  39. char *auth = proxy + length - 1;
  40. char *cur;
  41. while ((auth >= proxy) && (*auth != '@'))
  42. auth--;
  43. //if not found or @ is first char do nothing
  44. if (auth <= proxy)
  45. return;
  46. cur = strstr(proxy, ACLK_PROXY_PROTO_ADDR_SEPARATOR);
  47. if (!cur)
  48. cur = proxy;
  49. else
  50. cur += strlen(ACLK_PROXY_PROTO_ADDR_SEPARATOR);
  51. while (cur < auth) {
  52. *cur = 'X';
  53. cur++;
  54. }
  55. }
  56. static inline void safe_log_proxy_error(char *str, const char *proxy)
  57. {
  58. char *log = strdupz(proxy);
  59. safe_log_proxy_censor(log);
  60. netdata_log_error("%s Provided Value:\"%s\"", str, log);
  61. freez(log);
  62. }
  63. static inline int check_socks_enviroment(const char **proxy)
  64. {
  65. char *tmp = getenv("socks_proxy");
  66. if (!tmp)
  67. return 1;
  68. if (aclk_verify_proxy(tmp) == PROXY_TYPE_SOCKS5) {
  69. *proxy = tmp;
  70. return 0;
  71. }
  72. safe_log_proxy_error(
  73. "Environment var \"socks_proxy\" defined but of unknown format. Supported syntax: \"socks5[h]://[user:pass@]host:ip\".",
  74. tmp);
  75. return 1;
  76. }
  77. static inline int check_http_enviroment(const char **proxy)
  78. {
  79. char *tmp = getenv("http_proxy");
  80. if (!tmp)
  81. return 1;
  82. if (aclk_verify_proxy(tmp) == PROXY_TYPE_HTTP) {
  83. *proxy = tmp;
  84. return 0;
  85. }
  86. safe_log_proxy_error(
  87. "Environment var \"http_proxy\" defined but of unknown format. Supported syntax: \"http[s]://[user:pass@]host:ip\".",
  88. tmp);
  89. return 1;
  90. }
  91. const char *aclk_lws_wss_get_proxy_setting(ACLK_PROXY_TYPE *type)
  92. {
  93. const char *proxy = config_get(CONFIG_SECTION_CLOUD, ACLK_PROXY_CONFIG_VAR, ACLK_PROXY_ENV);
  94. *type = PROXY_DISABLED;
  95. if (strcmp(proxy, "none") == 0)
  96. return proxy;
  97. if (strcmp(proxy, ACLK_PROXY_ENV) == 0) {
  98. if (check_socks_enviroment(&proxy) == 0) {
  99. #ifdef LWS_WITH_SOCKS5
  100. *type = PROXY_TYPE_SOCKS5;
  101. return proxy;
  102. #else
  103. safe_log_proxy_error("socks_proxy environment variable set to use SOCKS5 proxy "
  104. "but Libwebsockets used doesn't have SOCKS5 support built in. "
  105. "Ignoring and checking for other options.",
  106. proxy);
  107. #endif
  108. }
  109. if (check_http_enviroment(&proxy) == 0)
  110. *type = PROXY_TYPE_HTTP;
  111. return proxy;
  112. }
  113. *type = aclk_verify_proxy(proxy);
  114. #ifndef LWS_WITH_SOCKS5
  115. if (*type == PROXY_TYPE_SOCKS5) {
  116. safe_log_proxy_error(
  117. "Config var \"" ACLK_PROXY_CONFIG_VAR
  118. "\" set to use SOCKS5 proxy but Libwebsockets used is built without support for SOCKS proxy. ACLK will be disabled.",
  119. proxy);
  120. }
  121. #endif
  122. if (*type == PROXY_TYPE_UNKNOWN) {
  123. *type = PROXY_DISABLED;
  124. safe_log_proxy_error(
  125. "Config var \"" ACLK_PROXY_CONFIG_VAR
  126. "\" defined but of unknown format. Supported syntax: \"socks5[h]://[user:pass@]host:ip\".",
  127. proxy);
  128. }
  129. return proxy;
  130. }
  131. // helper function to read settings only once (static)
  132. // as claiming, challenge/response and ACLK
  133. // read the same thing, no need to parse again
  134. const char *aclk_get_proxy(ACLK_PROXY_TYPE *type)
  135. {
  136. static const char *proxy = NULL;
  137. static ACLK_PROXY_TYPE proxy_type = PROXY_NOT_SET;
  138. if (proxy_type == PROXY_NOT_SET)
  139. proxy = aclk_lws_wss_get_proxy_setting(&proxy_type);
  140. *type = proxy_type;
  141. return proxy;
  142. }