diff --git a/src/common.c b/src/common.c index 52287c2..bcaa637 100644 --- a/src/common.c +++ b/src/common.c @@ -216,6 +216,24 @@ int ceparseargs(const char *str){ #endif +void parsehost(int family, char *host, struct sockaddr *sa){ + char *sp=NULL,*se=NULL; + unsigned short port; + + if(*host == '[') se=strchr(host, ']'); + if ( (sp = strchr(se?se:host, ':')) ) *sp = 0; + if(se){ + *se = 0; + } + if(sp){ + port = atoi(sp+1); + } + getip46(family, host + (se!=0), (struct sockaddr *)sa); + if(se) *se = ']'; + if(sp) *sp = ':'; + *SAPORT(sa) = htons(port); +} + int parsehostname(char *hostname, struct clientparam *param, unsigned short port){ char *sp=NULL,*se=NULL; diff --git a/src/proxy.h b/src/proxy.h index f72519a..6573d5b 100644 --- a/src/proxy.h +++ b/src/proxy.h @@ -235,10 +235,12 @@ void mschap(const unsigned char *win_password, struct hashtable; void hashadd(struct hashtable *ht, const unsigned char* name, unsigned char* value, time_t expires); +void parsehost(int family, char *host, struct sockaddr *sa); int parsehostname(char *hostname, struct clientparam *param, unsigned short port); int parseusername(char *username, struct clientparam *param, int extpasswd); int parseconnusername(char *username, struct clientparam *param, int extpasswd, unsigned short port); int ACLmatches(struct ace* acentry, struct clientparam * param); +int checkACL(struct clientparam * param); unsigned long udpresolve(int af, unsigned char * name, unsigned char * value, unsigned *retttl, struct clientparam* param, int makeauth); diff --git a/src/proxymain.c b/src/proxymain.c index 0306b99..5b94656 100644 --- a/src/proxymain.c +++ b/src/proxymain.c @@ -9,8 +9,46 @@ #include "proxy.h" - - +#define param ((struct clientparam *) p) +#ifdef _WIN32 +DWORD WINAPI threadfunc(LPVOID p) { +#else +void * threadfunc (void *p) { +#endif + if(param->srv->cbsock != INVALID_SOCKET){ + SASIZETYPE size = sizeof(param->sinsr); + param->remsock = so._accept(param->srv->cbsock, (struct sockaddr*)¶m->sinsr, &size); + if(param->remsock == INVALID_SOCKET) { + param->res = 13; + param->srv->logfunc(param, "Connect back accept() failed"); +#ifdef _WIN32 + return 0; +#else + return NULL; +#endif + } +#ifndef WITHMAIN + memcpy(¶m->req, ¶m->sinsr, size); + if(param->srv->acl) param->res = checkACL(param); + if(param->res){ + param->srv->logfunc(param, "Connect back ACL failed"); + } +#ifdef _WIN32 + return 0; +#else + return NULL; +#endif +#endif + + } + ((struct clientparam *) p)->srv->pf((struct clientparam *)p); +#ifdef _WIN32 + return 0; +#else + return NULL; +#endif +} +#undef param @@ -42,7 +80,7 @@ int MODULEMAINFUNC (int argc, char** argv){ - SOCKET sock = INVALID_SOCKET; + SOCKET sock = INVALID_SOCKET, new_sock = INVALID_SOCKET; int i=0; SASIZETYPE size; pthread_t thread; @@ -53,8 +91,15 @@ int MODULEMAINFUNC (int argc, char** argv){ unsigned sleeptime; unsigned char buf[256]; char *hostname=NULL; - int opt = 1, isudp; + int opt = 1, isudp = 0, iscbl = 0, iscbc = 0; + unsigned char *cbc_string = NULL, *cbl_string = NULL; +#ifndef NOIPV6 + struct sockaddr_in6 cbsa; +#else + struct sockaddr_in cbsa; +#endif FILE *fp = NULL; + struct linger lg; int nlog = 5000; char loghelp[] = #ifdef STDMAIN @@ -73,6 +118,8 @@ int MODULEMAINFUNC (int argc, char** argv){ " -t be silent (do not log service start/stop)\n" " -iIP ip address or internal interface (clients are expected to connect)\n" " -eIP ip address or external interface (outgoing connection will have this)\n" + " -rIP:PORT Use IP:port for connect back proxy instead of listen port\n" + " -RPORT Use PORT to listen connect back proxy connection to pass data to\n" " -4 Use IPv4 for outgoing connections\n" " -6 Use IPv6 for outgoing connections\n" " -46 Prefer IPv4 for outgoing connections, use both IPv4 and IPv6\n" @@ -85,8 +132,6 @@ int MODULEMAINFUNC (int argc, char** argv){ int inetd = 0; #endif #endif - SOCKET new_sock = INVALID_SOCKET; - struct linger lg; #ifdef _WIN32 HANDLE h; #endif @@ -222,6 +267,14 @@ int MODULEMAINFUNC (int argc, char** argv){ case 'h': hostname = argv[i] + 2; break; + case 'r': + cbc_string = mystrdup(argv[i] + 2); + iscbc = 1; + break; + case 'R': + cbl_string = mystrdup(argv[i] + 2); + iscbl = 1; + break; case 'u': srv.nouser = 1; break; @@ -255,6 +308,8 @@ int MODULEMAINFUNC (int argc, char** argv){ "Available options are:\n" "%s" " -pPORT - service port to accept connections\n" + " -RIP:PORT - connect back IP:PORT to listen and accept connections\n" + " -rIP:PORT - connect back IP:PORT to establish connect back connection\n" "%s" "\tExample: %s -i127.0.0.1\n\n" "%s", @@ -284,6 +339,8 @@ int MODULEMAINFUNC (int argc, char** argv){ " [-e] " " \n" "Available options are:\n" + " -RIP:PORT - connect back IP:PORT to listen and accept connections\n" + " -rIP:PORT - connect back IP:PORT to establish connect back connection\n" "%s" "%s" "\tExample: %s -d -i127.0.0.1 6666 serv.somehost.ru 6666\n\n" @@ -343,56 +400,7 @@ int MODULEMAINFUNC (int argc, char** argv){ #endif - if(srv.srvsock == INVALID_SOCKET){ - if(!isudp){ - lg.l_onoff = 1; - lg.l_linger = conf.timeouts[STRING_L]; - sock=so._socket(SASOCK(&srv.intsa), SOCK_STREAM, IPPROTO_TCP); - } - else { - sock=so._socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); - } - if( sock == INVALID_SOCKET) { - perror("socket()"); - return -2; - } -#ifdef _WIN32 - ioctlsocket(sock, FIONBIO, &ul); -#else - fcntl(sock,F_SETFL,O_NONBLOCK); -#endif - srv.srvsock = sock; - if(so._setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (unsigned char *)&opt, sizeof(int)))perror("setsockopt()"); -#ifdef SO_REUSEPORT - so._setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, (unsigned char *)&opt, sizeof(int)); -#endif - } - - size = sizeof(srv.intsa); - for(sleeptime = SLEEPTIME * 100; so._bind(sock, (struct sockaddr*)&srv.intsa, size)==-1; usleep(sleeptime)) { - sprintf((char *)buf, "bind(): %s", strerror(errno)); - if(!srv.silent)(*srv.logfunc)(&defparam, buf); - sleeptime = (sleeptime<<1); - if(!sleeptime) { - so._closesocket(sock); - return -3; - } - } - if(!isudp){ - if(so._listen (sock, 1 + (srv.maxchild>>4))==-1) { - sprintf((char *)buf, "listen(): %s", strerror(errno)); - if(!srv.silent)(*srv.logfunc)(&defparam, buf); - return -4; - } - } - else - defparam.clisock = sock; - - if(!srv.silent){ - sprintf((char *)buf, "Accepting connections [%u/%u]", (unsigned)getpid(), (unsigned)pthread_self()); - (*srv.logfunc)(&defparam, buf); - } memset(&defparam.sincr, 0, sizeof(defparam.sincr)); memset(&defparam.sincl, 0, sizeof(defparam.sincl)); memset(&defparam.sinsl, 0, sizeof(defparam.sinsl)); @@ -404,6 +412,76 @@ int MODULEMAINFUNC (int argc, char** argv){ *SAFAMILY(&defparam.sinsr) = AF_INET; *SAFAMILY(&defparam.req) = AF_INET; + if (!iscbc) { + if(srv.srvsock == INVALID_SOCKET){ + + if(!isudp){ + lg.l_onoff = 1; + lg.l_linger = conf.timeouts[STRING_L]; + sock=so._socket(SASOCK(&srv.intsa), SOCK_STREAM, IPPROTO_TCP); + } + else { + sock=so._socket(SASOCK(&srv.intsa), SOCK_DGRAM, IPPROTO_UDP); + } + if( sock == INVALID_SOCKET) { + perror("socket()"); + return -2; + } +#ifdef _WIN32 + ioctlsocket(sock, FIONBIO, &ul); +#else + fcntl(sock,F_SETFL,O_NONBLOCK); +#endif + srv.srvsock = sock; + if(so._setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (unsigned char *)&opt, sizeof(int)))perror("setsockopt()"); +#ifdef SO_REUSEPORT + so._setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, (unsigned char *)&opt, sizeof(int)); +#endif + } + size = sizeof(srv.intsa); + for(sleeptime = SLEEPTIME * 100; so._bind(sock, (struct sockaddr*)&srv.intsa, size)==-1; usleep(sleeptime)) { + sprintf((char *)buf, "bind(): %s", strerror(errno)); + if(!srv.silent)(*srv.logfunc)(&defparam, buf); + sleeptime = (sleeptime<<1); + if(!sleeptime) { + so._closesocket(sock); + return -3; + } + } + if(!isudp){ + if(so._listen (sock, 1 + (srv.maxchild>>4))==-1) { + sprintf((char *)buf, "listen(): %s", strerror(errno)); + if(!srv.silent)(*srv.logfunc)(&defparam, buf); + return -4; + } + } + else + defparam.clisock = sock; + + if(!srv.silent && !iscbc){ + sprintf((char *)buf, "Accepting connections [%u/%u]", (unsigned)getpid(), (unsigned)pthread_self()); + (*srv.logfunc)(&defparam, buf); + } + } + else { + parsehost(srv.family, cbc_string, (struct sockaddr *)&defparam.sincr); + } + if(iscbl){ + parsehost(srv.family, cbl_string, (struct sockaddr *)&cbsa); + if((srv.cbsock=so._socket(SASOCK(&cbsa), SOCK_STREAM, IPPROTO_TCP))==INVALID_SOCKET) { + (*srv.logfunc)(&defparam, "Failed to allocate connect back socket"); + return -6; + } + if(so._bind(srv.cbsock, (struct sockaddr*)&cbsa, sizeof(cbsa))==-1) { + (*srv.logfunc)(&defparam, "Failed to bind connect back socket"); + return -7; + } + if(so._listen(srv.cbsock, 1 + (srv.maxchild>>4))==-1) { + (*srv.logfunc)(&defparam, "Failed to listen connect back socket"); + return -8; + } + } + srv.fds.fd = sock; srv.fds.events = POLLIN; @@ -419,6 +497,7 @@ int MODULEMAINFUNC (int argc, char** argv){ } usleep(SLEEPTIME); } + if (iscbc) break; if (conf.paused != srv.version) break; if (srv.fds.events & POLLIN) { error = so._poll(&srv.fds, 1, 1000); @@ -439,11 +518,23 @@ int MODULEMAINFUNC (int argc, char** argv){ if((conf.paused != srv.version) || (error < 0)) break; if(!isudp){ size = sizeof(defparam.sincr); - new_sock = so._accept(sock, (struct sockaddr*)&defparam.sincr, &size); - if(new_sock == INVALID_SOCKET){ - sprintf((char *)buf, "accept(): %s", strerror(errno)); - if(!srv.silent)(*srv.logfunc)(&defparam, buf); - continue; + if(iscbc){ + new_sock=so._socket(SASOCK(&defparam.sincr), SOCK_STREAM, IPPROTO_TCP); + if(new_sock != INVALID_SOCKET){ + if(so._connect(new_sock,(struct sockaddr *)&defparam.sincr,sizeof(defparam.sincr))) { + so._closesocket(new_sock); + new_sock = INVALID_SOCKET; + continue; + } + } + } + else { + new_sock = so._accept(sock, (struct sockaddr*)&defparam.sincr, &size); + if(new_sock == INVALID_SOCKET){ + sprintf((char *)buf, "accept(): %s", strerror(errno)); + if(!srv.silent)(*srv.logfunc)(&defparam, buf); + continue; + } } size = sizeof(defparam.sincl); if(so._getsockname(new_sock, (struct sockaddr *)&defparam.sincl, &size)){ @@ -490,9 +581,9 @@ int MODULEMAINFUNC (int argc, char** argv){ } #ifdef _WIN32 #ifndef _WINCE - h = (HANDLE)_beginthreadex((LPSECURITY_ATTRIBUTES )NULL, (unsigned)16384, (BEGINTHREADFUNC)srv.pf, (void *) newparam, 0, &thread); + h = (HANDLE)_beginthreadex((LPSECURITY_ATTRIBUTES )NULL, (unsigned)16384, threadfunc, (void *) newparam, 0, &thread); #else - h = (HANDLE)CreateThread((LPSECURITY_ATTRIBUTES )NULL, (unsigned)32768, (BEGINTHREADFUNC)srv.pf, (void *) newparam, 0, &thread); + h = (HANDLE)CreateThread((LPSECURITY_ATTRIBUTES )NULL, (unsigned)32768, threadfunc, (void *) newparam, 0, &thread); #endif srv.childcount++; if (h) { @@ -506,7 +597,7 @@ int MODULEMAINFUNC (int argc, char** argv){ } #else - error = pthread_create(&thread, &pa, (PTHREADFUNC)srv.pf, (void *)newparam); + error = pthread_create(&thread, &pa, threadfunc, (void *)newparam); srv.childcount++; if(error){ sprintf((char *)buf, "pthread_create(): %s", strerror(error)); @@ -527,6 +618,8 @@ int MODULEMAINFUNC (int argc, char** argv){ if(fp) fclose(fp); srvfree(&srv); if(defparam.hostname)myfree(defparam.hostname); + if(cbc_string)myfree(cbc_string); + if(cbl_string)myfree(cbc_string); #ifndef STDMAIN if(srv.next)srv.next->prev = srv.prev; @@ -553,6 +646,7 @@ void srvinit(struct srvparam * srv, struct clientparam *param){ srv->srvsock = INVALID_SOCKET; srv->logdumpsrv = conf.logdumpsrv; srv->logdumpcli = conf.logdumpcli; + srv->cbsock = INVALID_SOCKET; memset(param, 0, sizeof(struct clientparam)); param->srv = srv; param->remsock = param->clisock = param->ctrlsock = param->ctrlsocksrv = INVALID_SOCKET; @@ -588,6 +682,7 @@ void srvinit2(struct srvparam * srv, struct clientparam *param){ void srvfree(struct srvparam * srv){ if(srv->srvsock != INVALID_SOCKET) so._closesocket(srv->srvsock); + if(srv->cbsock != INVALID_SOCKET) so._closesocket(srv->cbsock); srv->srvsock = INVALID_SOCKET; srv->service = S_ZOMBIE; while(srv->child) usleep(SLEEPTIME * 100); diff --git a/src/structures.h b/src/structures.h index 16b065e..e646c66 100644 --- a/src/structures.h +++ b/src/structures.h @@ -34,7 +34,6 @@ extern "C" { #define pthread_mutex_lock(x) EnterCriticalSection(x) #define pthread_mutex_unlock(x) LeaveCriticalSection(x) #define pthread_mutex_destroy(x) DeleteCriticalSection(x) -typedef unsigned (__stdcall *BEGINTHREADFUNC)(void *); #ifdef MSVC #pragma warning (disable : 4996) #endif @@ -140,6 +139,8 @@ typedef enum { S_FTPPR, S_SMTPP, S_ICQPR, + S_REVLI, + S_REVCO, /* S_MSNPR, */ @@ -162,7 +163,6 @@ typedef void * (*EXTENDFUNC) (struct node *node); typedef void (*CBFUNC)(void *cb, char * buf, int inbuf); typedef void (*PRINTFUNC) (struct node *node, CBFUNC cbf, void*cb); typedef int (*PLUGINFUNC) (struct pluginlink *pluginlink, int argc, char** argv); -typedef void * (*PTHREADFUNC)(void *); struct auth { struct auth *next; @@ -360,7 +360,7 @@ struct srvparam { LOGFUNC logfunc; AUTHFUNC authfunc; PROXYFUNC pf; - SOCKET srvsock; + SOCKET srvsock, cbsock; int childcount; int maxchild; int version; diff --git a/src/version.h b/src/version.h index 75aca7f..550d8ec 100644 --- a/src/version.h +++ b/src/version.h @@ -1,2 +1,2 @@ #define VERSION "3proxy-0.8b-devel" -#define BUILDDATE "150904014330" +#define BUILDDATE "150920205624"