No Description
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

request_tsiproxy.c 6.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. /* tsiproxy request handling */
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <stdarg.h>
  5. #include <unistd.h>
  6. #include <string.h>
  7. #include <signal.h>
  8. #include <netdb.h>
  9. #include <pthread.h>
  10. #include <regex.h>
  11. #include <arpa/inet.h>
  12. #include <netinet/in.h>
  13. #include <sys/socket.h>
  14. #include <sys/time.h>
  15. #include <sys/types.h>
  16. #include <fcntl.h>
  17. #include <errno.h>
  18. #include "libfuncs/libfuncs.h"
  19. #include "data.h"
  20. #include "conf.h"
  21. #include "commands.h"
  22. #include "request.h"
  23. #include "proxy_common.h"
  24. extern LIST *netconf;
  25. extern regex_t request_get;
  26. extern regex_t request_authmatch;
  27. extern CONFIG *config;
  28. extern STATS allstats;
  29. #define FREE_DATA { FREE(path); FREE(IP); FREE(agent); FREE(buf); }
  30. #define NEXT_CLIENT { FREE_DATA; pthread_exit(0); }
  31. #define SHUTDOWN_CLIENT { FREE_DATA; shutdown_fd(&clientsock); pthread_exit(0); }
  32. #define BUF_SIZE 1024
  33. void process_request(void *in_req) {
  34. request_info *req = (request_info *)in_req;
  35. regmatch_t res[8];
  36. uint32_t src_ip;
  37. char *path=NULL, *IP=NULL, *agent=NULL, *buf=NULL;
  38. unsigned long client_id = 0;
  39. int client_udp_port = 0;
  40. int smart_client = 0;
  41. int clientsock = req->clientsock;
  42. struct sockaddr_in client = req->client;
  43. time_t expire = -1;
  44. acl_t acl;
  45. FREE(req);
  46. buf = calloc(1, BUF_SIZE);
  47. if (!buf) {
  48. log_perror("Can't allocate buffer", errno);
  49. SHUTDOWN_CLIENT;
  50. }
  51. IP=strdup(inet_ntoa(client.sin_addr));
  52. src_ip = client.sin_addr.s_addr;
  53. if (fdgetline(clientsock, buf, BUF_SIZE-1)<=0) {
  54. SHUTDOWN_CLIENT;
  55. }
  56. if (regexec(&request_get,buf,2,res,0)==REG_NOMATCH) {
  57. send_501_not_implemented(clientsock);
  58. SHUTDOWN_CLIENT;
  59. }
  60. buf[res[1].rm_eo]=0;
  61. chomp(buf+res[1].rm_so);
  62. if (buf[res[1].rm_eo-1]=='/') buf[res[1].rm_eo-1]=0;
  63. path = strdup(buf+res[1].rm_so);
  64. int plen = strlen(path);
  65. {
  66. int k = 0;
  67. int qmarkpos = 0;
  68. int esc_7e = 2; // max replaces
  69. int esc_2b = 32; // max replaces
  70. int esc_2c = 8; // max replaces
  71. while (k < plen) {
  72. /* Fix escaped symbols only when it's safe */
  73. if (path[k]=='%' && k+2 <= plen) {
  74. int mv = 0;
  75. if (esc_7e >= 0 && path[k+1]=='7' && (path[k+2]=='E' || path[k+2]=='e')) { /* %7E -> ~ */
  76. path[k] = '~';
  77. esc_7e--;
  78. mv = 1;
  79. }
  80. if (esc_2b >= 0 && path[k+1]=='2' && (path[k+2]=='B' || path[k+2]=='b')) { /* %2B -> + */
  81. path[k] = '+';
  82. esc_2b--;
  83. mv = 1;
  84. }
  85. if (esc_2c >= 0 && path[k+1]=='2' && (path[k+2]=='C' || path[k+2]=='c')) { /* %2C -> , */
  86. path[k] = ',';
  87. esc_2c--;
  88. mv = 1;
  89. }
  90. if (mv) {
  91. memmove(&path[k+1], &path[k+3], plen-(k+2));
  92. plen -= 2;
  93. }
  94. }
  95. /* Bugfix for Windows Media Player. If path have // sequence
  96. (in base64 it is happening) WMP send just one / thus invalidating signature
  97. To fix this, URL generator replaces // with /_ so now we change _ back to / */
  98. if (path[k] == '_')
  99. path[k] = '/';
  100. /* Some shitty player replaces // with /~ */
  101. if (path[k] == '~')
  102. path[k] = '/';
  103. /* Leave only "safe" characters */
  104. if (path[k] < '*' || path[k] > 'z' || path[k]=='`')
  105. path[k] = '*';
  106. if (path[k] == '?')
  107. qmarkpos = k;
  108. k++;
  109. }
  110. if (qmarkpos && qmarkpos < plen) {
  111. path[qmarkpos] = 0;
  112. client_udp_port = atoi(path+qmarkpos+1);
  113. }
  114. }
  115. while (fdgetline(clientsock, buf, BUF_SIZE-1) > 0) {
  116. if (buf[0] == '\n' || buf[0] == '\r') // End of headers
  117. break;
  118. if (strstr(buf, "X-Smart-Client: yes")==buf) {
  119. smart_client = 1;
  120. }
  121. if (memcmp(buf,"User-Agent: ",12)==0 && strlen(buf) > 12) {
  122. unsigned int k = 0;
  123. agent=chomp(strdup(buf+12));
  124. while(k<strlen(agent)) {
  125. if (agent[k] < 32 || agent[k] > 122 || agent[k]==96) /* Do not allow ( < && > z && ` */
  126. agent[k]=' ';
  127. k++;
  128. }
  129. }
  130. }
  131. int pathlen = strlen(path);
  132. if (!pathlen) {
  133. send_302_redirect(clientsock, "https://georgi.unixsol.org/");
  134. SHUTDOWN_CLIENT;
  135. }
  136. int acl_found = acl_search(netconf, client.sin_addr.s_addr, &acl);
  137. if (!acl_found) {
  138. LOGf("DENY : Access denied | IP: %s Path: /%s Agent: %s\n", IP, path, agent);
  139. send_403_forbidden_msg(clientsock, "access-denied");
  140. SHUTDOWN_CLIENT;
  141. }
  142. if (strncmp(path,"ping",4)==0) {
  143. run_ping(clientsock, acl, src_ip, IP);
  144. SHUTDOWN_CLIENT;
  145. }
  146. if (strncmp(path,"stats",5)==0) {
  147. show_stats(clientsock, acl, IP);
  148. SHUTDOWN_CLIENT;
  149. }
  150. if (strncmp(path,"info",4)==0) {
  151. show_info(clientsock, acl, IP);
  152. SHUTDOWN_CLIENT;
  153. }
  154. if (strncmp(path,"readinfo",8)==0) {
  155. read_info(clientsock, acl, IP);
  156. SHUTDOWN_CLIENT;
  157. }
  158. if (strncmp(path,"netconf",7)==0) {
  159. run_netconf(clientsock, acl, IP);
  160. SHUTDOWN_CLIENT;
  161. }
  162. if (strncmp(path,"chanconf",8)==0) {
  163. run_chanconf(clientsock, acl, IP);
  164. SHUTDOWN_CLIENT;
  165. }
  166. if (strncmp(path,"getnetconf",10)==0) {
  167. run_getnetconf(clientsock, acl, IP);
  168. SHUTDOWN_CLIENT;
  169. }
  170. if (strncmp(path,"getchanconf",10)==0) {
  171. run_getchanconf(clientsock, acl, IP);
  172. SHUTDOWN_CLIENT;
  173. }
  174. if (strncmp(path,"livecheck",9)==0) {
  175. run_livecheck(clientsock, acl, IP);
  176. SHUTDOWN_CLIENT;
  177. }
  178. if (strncmp(path,"channels",8)==0) {
  179. run_channels(clientsock, acl, IP);
  180. SHUTDOWN_CLIENT;
  181. }
  182. if (!is_ext(path, ".asf") && !is_ext(path, ".mpg") && !is_ext(path, ".ts")) {
  183. if (!is_ext(path, ".ico") && // favicon.ico
  184. !is_ext(path, ".txt") && // robots.txt
  185. !is_ext(path, ".asx") && // Playlists
  186. !is_ext(path, ".m3u") && // Playlists
  187. !is_ext(path, ".smi") && // Subtitles
  188. !is_ext(path, ".ass") &&
  189. !is_ext(path, ".wse") &&
  190. !is_ext(path, ".idx") &&
  191. !is_ext(path, ".psb") &&
  192. !is_ext(path, ".srt") &&
  193. !is_ext(path, ".ssa") &&
  194. !is_ext(path, ".sub") &&
  195. !is_ext(path, ".ASF") && // some crap player desides to UPPERCASE the request
  196. !is_ext(path, ".wmv") && // No wmv files here
  197. !is_ext(path, "atus") && // apstatus
  198. !is_ext(path, ".exe") && // ShitZ
  199. !is_ext(path, ".php") &&
  200. !is_ext(path, ".pl") &&
  201. !is_ext(path, ".dll"))
  202. {
  203. LOGf("404 : File not found | IP: %s Path: /%s Agent: %s\n", IP, path, agent);
  204. }
  205. send_404_not_found(clientsock);
  206. SHUTDOWN_CLIENT;
  207. }
  208. if (config_redirect_enabled(config, clientsock, path)) {
  209. SHUTDOWN_CLIENT;
  210. }
  211. CLIENT *c = new_client(clientsock, expire, path, IP, agent, client_id, acl, client_udp_port, smart_client);
  212. process_client(clientsock, c);
  213. NEXT_CLIENT;
  214. }