/* tsiproxy request handling */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "libfuncs/libfuncs.h" #include "data.h" #include "conf.h" #include "commands.h" #include "request.h" #include "proxy_common.h" extern LIST *netconf; extern regex_t request_get; extern regex_t request_authmatch; extern CONFIG *config; extern STATS allstats; #define FREE_DATA { FREE(path); FREE(IP); FREE(agent); FREE(buf); } #define NEXT_CLIENT { FREE_DATA; pthread_exit(0); } #define SHUTDOWN_CLIENT { FREE_DATA; shutdown_fd(&clientsock); pthread_exit(0); } #define BUF_SIZE 1024 void process_request(void *in_req) { request_info *req = (request_info *)in_req; regmatch_t res[8]; uint32_t src_ip; char *path=NULL, *IP=NULL, *agent=NULL, *buf=NULL; unsigned long client_id = 0; int client_udp_port = 0; int smart_client = 0; int clientsock = req->clientsock; struct sockaddr_in client = req->client; time_t expire = -1; acl_t acl; FREE(req); buf = calloc(1, BUF_SIZE); if (!buf) { log_perror("Can't allocate buffer", errno); SHUTDOWN_CLIENT; } IP=strdup(inet_ntoa(client.sin_addr)); src_ip = client.sin_addr.s_addr; if (fdgetline(clientsock, buf, BUF_SIZE-1)<=0) { SHUTDOWN_CLIENT; } if (regexec(&request_get,buf,2,res,0)==REG_NOMATCH) { send_501_not_implemented(clientsock); SHUTDOWN_CLIENT; } buf[res[1].rm_eo]=0; chomp(buf+res[1].rm_so); if (buf[res[1].rm_eo-1]=='/') buf[res[1].rm_eo-1]=0; path = strdup(buf+res[1].rm_so); int plen = strlen(path); { int k = 0; int qmarkpos = 0; int esc_7e = 2; // max replaces int esc_2b = 32; // max replaces int esc_2c = 8; // max replaces while (k < plen) { /* Fix escaped symbols only when it's safe */ if (path[k]=='%' && k+2 <= plen) { int mv = 0; if (esc_7e >= 0 && path[k+1]=='7' && (path[k+2]=='E' || path[k+2]=='e')) { /* %7E -> ~ */ path[k] = '~'; esc_7e--; mv = 1; } if (esc_2b >= 0 && path[k+1]=='2' && (path[k+2]=='B' || path[k+2]=='b')) { /* %2B -> + */ path[k] = '+'; esc_2b--; mv = 1; } if (esc_2c >= 0 && path[k+1]=='2' && (path[k+2]=='C' || path[k+2]=='c')) { /* %2C -> , */ path[k] = ','; esc_2c--; mv = 1; } if (mv) { memmove(&path[k+1], &path[k+3], plen-(k+2)); plen -= 2; } } /* Bugfix for Windows Media Player. If path have // sequence (in base64 it is happening) WMP send just one / thus invalidating signature To fix this, URL generator replaces // with /_ so now we change _ back to / */ if (path[k] == '_') path[k] = '/'; /* Some shitty player replaces // with /~ */ if (path[k] == '~') path[k] = '/'; /* Leave only "safe" characters */ if (path[k] < '*' || path[k] > 'z' || path[k]=='`') path[k] = '*'; if (path[k] == '?') qmarkpos = k; k++; } if (qmarkpos && qmarkpos < plen) { path[qmarkpos] = 0; client_udp_port = atoi(path+qmarkpos+1); } } while (fdgetline(clientsock, buf, BUF_SIZE-1) > 0) { if (buf[0] == '\n' || buf[0] == '\r') // End of headers break; if (strstr(buf, "X-Smart-Client: yes")==buf) { smart_client = 1; } if (memcmp(buf,"User-Agent: ",12)==0 && strlen(buf) > 12) { unsigned int k = 0; agent=chomp(strdup(buf+12)); while(k 122 || agent[k]==96) /* Do not allow ( < && > z && ` */ agent[k]=' '; k++; } } } int pathlen = strlen(path); if (!pathlen) { send_302_redirect(clientsock, "https://georgi.unixsol.org/"); SHUTDOWN_CLIENT; } int acl_found = acl_search(netconf, client.sin_addr.s_addr, &acl); if (!acl_found) { LOGf("DENY : Access denied | IP: %s Path: /%s Agent: %s\n", IP, path, agent); send_403_forbidden_msg(clientsock, "access-denied"); SHUTDOWN_CLIENT; } if (strncmp(path,"ping",4)==0) { run_ping(clientsock, acl, src_ip, IP); SHUTDOWN_CLIENT; } if (strncmp(path,"stats",5)==0) { show_stats(clientsock, acl, IP); SHUTDOWN_CLIENT; } if (strncmp(path,"info",4)==0) { show_info(clientsock, acl, IP); SHUTDOWN_CLIENT; } if (strncmp(path,"readinfo",8)==0) { read_info(clientsock, acl, IP); SHUTDOWN_CLIENT; } if (strncmp(path,"netconf",7)==0) { run_netconf(clientsock, acl, IP); SHUTDOWN_CLIENT; } if (strncmp(path,"chanconf",8)==0) { run_chanconf(clientsock, acl, IP); SHUTDOWN_CLIENT; } if (strncmp(path,"getnetconf",10)==0) { run_getnetconf(clientsock, acl, IP); SHUTDOWN_CLIENT; } if (strncmp(path,"getchanconf",10)==0) { run_getchanconf(clientsock, acl, IP); SHUTDOWN_CLIENT; } if (strncmp(path,"livecheck",9)==0) { run_livecheck(clientsock, acl, IP); SHUTDOWN_CLIENT; } if (strncmp(path,"channels",8)==0) { run_channels(clientsock, acl, IP); SHUTDOWN_CLIENT; } if (!is_ext(path, ".asf") && !is_ext(path, ".mpg") && !is_ext(path, ".ts")) { if (!is_ext(path, ".ico") && // favicon.ico !is_ext(path, ".txt") && // robots.txt !is_ext(path, ".asx") && // Playlists !is_ext(path, ".m3u") && // Playlists !is_ext(path, ".smi") && // Subtitles !is_ext(path, ".ass") && !is_ext(path, ".wse") && !is_ext(path, ".idx") && !is_ext(path, ".psb") && !is_ext(path, ".srt") && !is_ext(path, ".ssa") && !is_ext(path, ".sub") && !is_ext(path, ".ASF") && // some crap player desides to UPPERCASE the request !is_ext(path, ".wmv") && // No wmv files here !is_ext(path, "atus") && // apstatus !is_ext(path, ".exe") && // ShitZ !is_ext(path, ".php") && !is_ext(path, ".pl") && !is_ext(path, ".dll")) { LOGf("404 : File not found | IP: %s Path: /%s Agent: %s\n", IP, path, agent); } send_404_not_found(clientsock); SHUTDOWN_CLIENT; } if (config_redirect_enabled(config, clientsock, path)) { SHUTDOWN_CLIENT; } CLIENT *c = new_client(clientsock, expire, path, IP, agent, client_id, acl, client_udp_port, smart_client); process_client(clientsock, c); NEXT_CLIENT; }