aclk_common.c 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. #include "aclk_common.h"
  2. #include "../daemon/common.h"
  3. struct {
  4. ACLK_PROXY_TYPE type;
  5. const char *url_str;
  6. } supported_proxy_types[] = {
  7. { .type = PROXY_TYPE_SOCKS5, .url_str = "socks5" ACLK_PROXY_PROTO_ADDR_SEPARATOR },
  8. { .type = PROXY_TYPE_SOCKS5, .url_str = "socks5h" ACLK_PROXY_PROTO_ADDR_SEPARATOR },
  9. { .type = PROXY_TYPE_HTTP, .url_str = "http" ACLK_PROXY_PROTO_ADDR_SEPARATOR },
  10. { .type = PROXY_TYPE_UNKNOWN, .url_str = NULL },
  11. };
  12. const char *aclk_proxy_type_to_s(ACLK_PROXY_TYPE *type)
  13. {
  14. switch (*type) {
  15. case PROXY_DISABLED:
  16. return "disabled";
  17. case PROXY_TYPE_HTTP:
  18. return "HTTP";
  19. case PROXY_TYPE_SOCKS5:
  20. return "SOCKS";
  21. default:
  22. return "Unknown";
  23. }
  24. }
  25. static inline ACLK_PROXY_TYPE aclk_find_proxy(const char *string)
  26. {
  27. int i = 0;
  28. while (supported_proxy_types[i].url_str) {
  29. if (!strncmp(supported_proxy_types[i].url_str, string, strlen(supported_proxy_types[i].url_str)))
  30. return supported_proxy_types[i].type;
  31. i++;
  32. }
  33. return PROXY_TYPE_UNKNOWN;
  34. }
  35. ACLK_PROXY_TYPE aclk_verify_proxy(const char *string)
  36. {
  37. if (!string)
  38. return PROXY_TYPE_UNKNOWN;
  39. while (*string == 0x20 && *string!=0) // Help coverity (compiler will remove)
  40. string++;
  41. if (!*string)
  42. return PROXY_TYPE_UNKNOWN;
  43. return aclk_find_proxy(string);
  44. }
  45. // helper function to censor user&password
  46. // for logging purposes
  47. void safe_log_proxy_censor(char *proxy)
  48. {
  49. size_t length = strlen(proxy);
  50. char *auth = proxy + length - 1;
  51. char *cur;
  52. while ((auth >= proxy) && (*auth != '@'))
  53. auth--;
  54. //if not found or @ is first char do nothing
  55. if (auth <= proxy)
  56. return;
  57. cur = strstr(proxy, ACLK_PROXY_PROTO_ADDR_SEPARATOR);
  58. if (!cur)
  59. cur = proxy;
  60. else
  61. cur += strlen(ACLK_PROXY_PROTO_ADDR_SEPARATOR);
  62. while (cur < auth) {
  63. *cur = 'X';
  64. cur++;
  65. }
  66. }
  67. static inline void safe_log_proxy_error(char *str, const char *proxy)
  68. {
  69. char *log = strdupz(proxy);
  70. safe_log_proxy_censor(log);
  71. error("%s Provided Value:\"%s\"", str, log);
  72. freez(log);
  73. }
  74. static inline int check_socks_enviroment(const char **proxy)
  75. {
  76. char *tmp = getenv("socks_proxy");
  77. if (!tmp)
  78. return 1;
  79. if (aclk_verify_proxy(tmp) == PROXY_TYPE_SOCKS5) {
  80. *proxy = tmp;
  81. return 0;
  82. }
  83. safe_log_proxy_error(
  84. "Environment var \"socks_proxy\" defined but of unknown format. Supported syntax: \"socks5[h]://[user:pass@]host:ip\".",
  85. tmp);
  86. return 1;
  87. }
  88. static inline int check_http_enviroment(const char **proxy)
  89. {
  90. char *tmp = getenv("http_proxy");
  91. if (!tmp)
  92. return 1;
  93. if (aclk_verify_proxy(tmp) == PROXY_TYPE_HTTP) {
  94. *proxy = tmp;
  95. return 0;
  96. }
  97. safe_log_proxy_error(
  98. "Environment var \"http_proxy\" defined but of unknown format. Supported syntax: \"http[s]://[user:pass@]host:ip\".",
  99. tmp);
  100. return 1;
  101. }
  102. const char *aclk_lws_wss_get_proxy_setting(ACLK_PROXY_TYPE *type)
  103. {
  104. const char *proxy = config_get(CONFIG_SECTION_CLOUD, ACLK_PROXY_CONFIG_VAR, ACLK_PROXY_ENV);
  105. *type = PROXY_DISABLED;
  106. if (strcmp(proxy, "none") == 0)
  107. return proxy;
  108. if (strcmp(proxy, ACLK_PROXY_ENV) == 0) {
  109. if (check_socks_enviroment(&proxy) == 0)
  110. *type = PROXY_TYPE_SOCKS5;
  111. else if (check_http_enviroment(&proxy) == 0)
  112. *type = PROXY_TYPE_HTTP;
  113. return proxy;
  114. }
  115. *type = aclk_verify_proxy(proxy);
  116. if (*type == PROXY_TYPE_UNKNOWN) {
  117. *type = PROXY_DISABLED;
  118. safe_log_proxy_error(
  119. "Config var \"" ACLK_PROXY_CONFIG_VAR
  120. "\" defined but of unknown format. Supported syntax: \"socks5[h]://[user:pass@]host:ip\".",
  121. proxy);
  122. }
  123. return proxy;
  124. }
  125. // helper function to read settings only once (static)
  126. // as claiming, challenge/response and ACLK
  127. // read the same thing, no need to parse again
  128. const char *aclk_get_proxy(ACLK_PROXY_TYPE *type)
  129. {
  130. static const char *proxy = NULL;
  131. static ACLK_PROXY_TYPE proxy_type = PROXY_NOT_SET;
  132. if (proxy_type == PROXY_NOT_SET)
  133. proxy = aclk_lws_wss_get_proxy_setting(&proxy_type);
  134. *type = proxy_type;
  135. return proxy;
  136. }
  137. int aclk_decode_base_url(char *url, char **aclk_hostname, char **aclk_port)
  138. {
  139. int pos = 0;
  140. if (!strncmp("https://", url, 8)) {
  141. pos = 8;
  142. } else if (!strncmp("http://", url, 7)) {
  143. error("Cannot connect ACLK over %s -> unencrypted link is not supported", url);
  144. return 1;
  145. }
  146. int host_end = pos;
  147. while (url[host_end] != 0 && url[host_end] != '/' && url[host_end] != ':')
  148. host_end++;
  149. if (url[host_end] == 0) {
  150. *aclk_hostname = strdupz(url + pos);
  151. *aclk_port = strdupz("443");
  152. info("Setting ACLK target host=%s port=%s from %s", *aclk_hostname, *aclk_port, url);
  153. return 0;
  154. }
  155. if (url[host_end] == ':') {
  156. *aclk_hostname = callocz(host_end - pos + 1, 1);
  157. strncpy(*aclk_hostname, url + pos, host_end - pos);
  158. int port_end = host_end + 1;
  159. while (url[port_end] >= '0' && url[port_end] <= '9')
  160. port_end++;
  161. if (port_end - host_end > 6) {
  162. error("Port specified in %s is invalid", url);
  163. return 0;
  164. }
  165. *aclk_port = callocz(port_end - host_end + 1, 1);
  166. for (int i = host_end + 1; i < port_end; i++)
  167. (*aclk_port)[i - host_end - 1] = url[i];
  168. }
  169. if (url[host_end] == '/') {
  170. *aclk_port = strdupz("443");
  171. *aclk_hostname = callocz(1, host_end - pos + 1);
  172. strncpy(*aclk_hostname, url+pos, host_end - pos);
  173. }
  174. info("Setting ACLK target host=%s port=%s from %s", *aclk_hostname, *aclk_port, url);
  175. return 0;
  176. }