aclk_proxy.c 4.9 KB

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