diff --git a/3proxy.rc b/3proxy.rc index bc117b2..8959417 100644 --- a/3proxy.rc +++ b/3proxy.rc @@ -2,8 +2,8 @@ 1 VERSIONINFO -FILEVERSION 0,9,0,0 -PRODUCTVERSION 0,9,0,0 +FILEVERSION 10,0,0,0 +PRODUCTVERSION 10,0,0,0 FILETYPE 1 FILESUBTYPE 0x0L BEGIN @@ -14,12 +14,12 @@ BEGIN VALUE "Comments", "3proxy - tiny proxy server, http://3proxy.org/\0" VALUE "CompanyName", "Vladimir Dubrovin\0" VALUE "FileDescription", "3proxy - tiny proxy server\0" - VALUE "FileVersion", "0.9-devel-" BUILDDATE "\0" + VALUE "FileVersion", "10-devel-" BUILDDATE "\0" VALUE "InternalName", "3proxy\0" - VALUE "LegalCopyright", "Copyright (C) 2002-2019 Vladimir Dubrovin\0" + VALUE "LegalCopyright", "Copyright (C) 2002-2020 Vladimir Dubrovin\0" VALUE "OriginalFilename", "3proxy.exe\0" VALUE "ProductName", "3proxy\0" - VALUE "ProductVersion", "0.9-devel-" BUILDDATE "\0" + VALUE "ProductVersion", "10-devel-" BUILDDATE "\0" END END BLOCK "VarFileInfo" diff --git a/README b/README index 0fc98be..ae8dddb 100644 --- a/README +++ b/README @@ -1,5 +1,11 @@ # 3APA3A 3proxy tiny proxy server -(c) 2002-2019 by Vladimir '3APA3A' Dubrovin <3proxy@3proxy.ru> +(c) 2002-2020 by Vladimir '3APA3A' Dubrovin <3proxy@3proxy.ru> + + +Branches: +Master (stable) branch - 3proxy 0.9 +Devel branch - 3proxy 10 + Download: https://github.com/z3APA3A/3proxy/releases @@ -58,7 +64,7 @@ Please read doc/html/index.html and man pages. + Threaded application (no child process). + Web administration and statistics + Plugins for functionality extension - + Native 64 bit application + + Native 32/64 bit application 2. Proxy chaining and network connections + Can be used as a bridge between client and different proxy type (e.g. convert incoming HTTP proxy request from client to SOCKSv5 @@ -78,9 +84,8 @@ Please read doc/html/index.html and man pages. + syslog logging (Unix) + ODBC logging + RADIUS accounting - + log file rotation (hourly, daily, weekly, monthly) - + automatic log file comperssion with external archiver (for files) - + automatic removal of older log files + + log file rotation + + automatic log file processing with external archiver (for files) + Character filtering for log files + different log files for different servces are supported 4. Access control @@ -89,12 +94,13 @@ Please read doc/html/index.html and man pages. (POST, PUT, GET, etc), weekday and daytime. + ACL-driven (user/source/destination/protocol/weekday/daytime or combined) bandwith limitation for incoming and (!)outgoing trafic. - + ACL-driven (user/source/destination/protocol/weekday/daytime or - combined) traffic limitation per day, week or month for incoming and + + ACL-driven traffic limitation per day, week or month for incoming and outgoing traffic + + Connection limitation and ratelimting + User authentication by username / password + RADIUS Authentication and Authorization + User authentication by DNS hostname + + Authentication cache with possibility to limit user to single IP address + Access control by username/password for SOCKSv5 and HTTP/HTTPS/FTP + Cleartext or encrypted (crypt/MD5 or NT) passwords. + Connection redirection diff --git a/doc/html/howtoe.html b/doc/html/howtoe.html index 36b250b..109d8b5 100644 --- a/doc/html/howtoe.html +++ b/doc/html/howtoe.html @@ -873,12 +873,12 @@ You can control 3proxy service via "Services" administration ot via "net" comman
  • since 0.9
  • 90 - unexpected system error (should not happen)
  • 91 - unexpected poll error (should not happen) -
  • 92 - connection terminated by timeout -
  • 93 - dirty connection termination by server or client (or network issue) with unsent data -
  • 94 - clear connection termination by server or client with unsent data -
  • 95 - dirty connection termination by client (or network issue) -
  • 96 - dirty connection termination by server (or network issue) -
  • 97 - dirty connection termination by both client and server (probably network issue) +
  • 92 - connection terminated by timeout (see timeouts) +
  • 93 - connection terminated by ratelimit-related timeout or due to errors limit +
  • 94 - connection termination by server or client with unsent data +
  • 95 - dirty connection termination by client (or networking issue) +
  • 96 - dirty connection termination by server (or networking issue) +
  • 97 - dirty connection termination by both client and server (probably networking issue)
  • prior to 0.9:
  • 90 - socket error or connection broken
  • 91 - TCP/IP common failure diff --git a/doc/html/howtor.html b/doc/html/howtor.html index c34a9cc..2119a72 100644 --- a/doc/html/howtor.html +++ b/doc/html/howtor.html @@ -1049,9 +1049,9 @@
  • с версии 0.9
  • 90 - неожиданная системная ошибка (не должно происходить)
  • 91 - ошибка poll (не должно происходить) -
  • 92 - соединение прервано по таймауту -
  • 93 - клиент или сервер "грязно" закрыли соединение или произошла сетевая ошибка, остались неотправленные данные -
  • 94 - клиент или сервер "чисто" закрыли соединение или произошла сетевая ошибка, остались неотправленные данные +
  • 92 - соединение прервано по таймауту на сетевую операцию (см. timeouts) +
  • 93 - соединение прервано по таймауту связанному с рейтлимитом или из-за превышения числа ошибок +
  • 94 - клиент или сервер закрыли соединение или произошла сетевая ошибка, остались неотправленные данные
  • 95 - клиент "грязно" закрыл соединение или сетевая ошибка
  • 96 - сервер "грязно" закрыл соединение или сетевая ошибка
  • 97 - клиент и сервер "грязно" закрыли соединение или сетевая ошибка diff --git a/man/3proxy.cfg.3 b/man/3proxy.cfg.3 index 344e176..76b49fd 100644 --- a/man/3proxy.cfg.3 +++ b/man/3proxy.cfg.3 @@ -240,6 +240,8 @@ alternate config file. Think twice before using it. @ (for Unix) use syslog, filename is used as ident name .br & use ODBC, filename consists of comma-delimited datasource,username,password (username and password are optional) +.br + radius - use RADIUS for logging .br LOGTYPE is one of: .br @@ -388,6 +390,28 @@ can use %A as produced archive name and %F as filename. .br default timeouts 1 5 30 60 180 1800 15 60 15 5 +.br +.B radius + +.br + Configures RADIUS servers to be used for logging and authentication (log and auth types +must be set to radius). port and local address to use with given server may be specified. +.br + Attributes within request: User-Name, Password: (username and password if presented by client), +Service Type: Authenticate-Only, +NAS-Port-Type: NAS-Port-Virtual, +NAS-Port-ID: (proxy service port, e.g. 1080), +NAS-IPv6-Address / NAS-IP-Address: (proxy interface accessed by client), +NAS-Identifier: (text identifing proxy, e.g. PROXY or SOCKSv5), +Framed-IPv6-Address / Framed-IP-Address: (IP address of the client), +Called-Station-ID: (requested Hostname, if presents), +Login-Service: (type of request, e.g. 1001 - SOCKS CONNECT, 1010 - HTTP GET, 1013 - HTTP CONNECT), +Login-TCP-Port: (requested port), +Login-IPv6-Host / Login-IP-Host: (requested IP). +.br + Supported reply attributes for authentication: +Framed-IP-Address / Framed-IPv6-Address (IP to assign to user), Reply-Message. +Use authcache to speedup authentication. RADIUS feature is currently experimental. .br .B nserver @@ -503,6 +527,8 @@ NB: there is no any password check, name may be spoofed. SOCKSv5, FTP, POP3 and HTTP proxy. .br cache - cached authentication, may be used with \'authcache\'. +.br + radius - authentication with RADIUS. .br Plugins may add additional authentication types. diff --git a/src/auth.c b/src/auth.c index 24e0474..342511c 100644 --- a/src/auth.c +++ b/src/auth.c @@ -676,27 +676,30 @@ int alwaysauth(struct clientparam * param){ return res; } -int checkACL(struct clientparam * param){ +int checkACL2(struct clientparam * param, int pre){ struct ace* acentry; - if(!param->srv->acl) { + acentry = pre?param->srv->preacl:param->srv->acl; + if(!acentry) { return 0; } - for(acentry = param->srv->acl; acentry; acentry = acentry->next) { + for(; acentry; acentry = acentry->next) { if(ACLmatches(acentry, param)) { - param->nolog = acentry->nolog; - param->weight = acentry->weight; - if(acentry->action == 2) { - struct ace dup; + if(!pre){ + param->nolog = acentry->nolog; + param->weight = acentry->weight; + if(acentry->action == 2) { + struct ace dup; - if(param->operation < 256 && !(param->operation & CONNECT)){ - continue; + if(param->operation < 256 && !(param->operation & CONNECT)){ + continue; + } + if(param->redirected && acentry->chains && SAISNULL(&acentry->chains->addr) && !*SAPORT(&acentry->chains->addr)) { + continue; + } + dup = *acentry; + return handleredirect(param, &dup); } - if(param->redirected && acentry->chains && SAISNULL(&acentry->chains->addr) && !*SAPORT(&acentry->chains->addr)) { - continue; - } - dup = *acentry; - return handleredirect(param, &dup); } return acentry->action; } @@ -704,6 +707,19 @@ int checkACL(struct clientparam * param){ return 3; } +int checkACL(struct clientparam * param){ + int res; + res = checkACL2(param, 1); + if(res < 2) return res; + return checkACL2(param, 0); +} + + +int checkpreACL(struct clientparam * param){ + return checkACL2(param, 1); +} + + struct authcache { char * username; char * password; @@ -771,6 +787,16 @@ int cacheauth(struct clientparam * param){ return 4; } +int dopreauth(struct clientparam * param){ + int res = 0; + + if(param->srv && param->srv->authfuncs && param->srv->authfuncs->preauthorize){ + res = param->srv->authfuncs->preauthorize(param); + param->preauthorized = !res; + if(res != 1) res = 0; + } + return res; +} int doauth(struct clientparam * param){ int res = 0; struct auth *authfuncs; @@ -781,7 +807,8 @@ int doauth(struct clientparam * param){ for(authfuncs=param->srv->authfuncs; authfuncs; authfuncs=authfuncs->next){ res = authfuncs->authenticate?(*authfuncs->authenticate)(param):0; if(!res) { - if(authfuncs->authorize && + + if(!param->preauthorized && authfuncs->authorize && (res = (*authfuncs->authorize)(param))) return res; if(conf.authcachetype && authfuncs->authenticate && authfuncs->authenticate != cacheauth && param->username && (!(conf.authcachetype&4) || (!param->pwtype && param->password))){ @@ -847,9 +874,11 @@ int doauth(struct clientparam * param){ int ipauth(struct clientparam * param){ int res; unsigned char *username; + + if(param->preauthorized) return (0); username = param->username; param->username = NULL; - res = checkACL(param); + res = checkACL2(param,0); param->username = username; return res; } @@ -960,20 +989,20 @@ int strongauth(struct clientparam * param){ int radauth(struct clientparam * param); struct auth authfuncs[] = { - {authfuncs+1, NULL, NULL, ""}, - {authfuncs+2, ipauth, NULL, "iponly"}, - {authfuncs+3, userauth, checkACL, "useronly"}, - {authfuncs+4, dnsauth, checkACL, "dnsname"}, - {authfuncs+5, strongauth, checkACL, "strong"}, - {authfuncs+6, cacheauth, checkACL, "cache"}, + {authfuncs+1, NULL,NULL, NULL, ""}, + {authfuncs+2, checkpreACL, ipauth, NULL, "iponly"}, + {authfuncs+3, checkpreACL, userauth, checkACL, "useronly"}, + {authfuncs+4, checkpreACL, dnsauth, checkACL, "dnsname"}, + {authfuncs+5, checkpreACL, strongauth, checkACL, "strong"}, + {authfuncs+6, checkpreACL, cacheauth, checkACL, "cache"}, #ifndef NORADIUS #define AUTHOFFSET 1 - {authfuncs+7, radauth, checkACL, "radius"}, + {authfuncs+7, checkpreACL, radauth, checkACL, "radius"}, #else #define AUTHOFFSET 0 #endif - {authfuncs+7+AUTHOFFSET, NULL, NULL, "none"}, - {NULL, NULL, NULL, ""} + {authfuncs+7+AUTHOFFSET, NULL, NULL, NULL, "none"}, + {NULL, NULL, NULL, NULL, ""} }; diff --git a/src/authradius.c b/src/authradius.c index 58f872e..f462182 100644 --- a/src/authradius.c +++ b/src/authradius.c @@ -578,6 +578,7 @@ int radsend(const char *buf, int total_length, int auth){ } else remsock = radiuslist[loop].logsock; */ + so._bind(param->remsock,(struct sockaddr *)&radiuslist[loop].localaddr,SASIZE(&radiuslist[loop].localaddr)); len = so._sendto(remsock, (char *)&packet, total_length, 0, (struct sockaddr *)&saremote, sizeof(saremote)); if(len != ntohs(packet.length)){ diff --git a/src/common.c b/src/common.c index c42774f..57da0db 100644 --- a/src/common.c +++ b/src/common.c @@ -292,7 +292,10 @@ int parsehostname(char *hostname, struct clientparam *param, unsigned short port if(!hostname || !*hostname)return 2; if(*hostname == '[') se=strchr(hostname, ']'); - if ( (sp = strchr(se?se:hostname, ':')) && !strchr(sp+1, ':')) *sp = 0; + if (sp = strchr(se?se:hostname, ':')) { + if(strchr(sp+1, ':'))sp = NULL; + else *sp = 0; + } if(se){ *se = 0; } diff --git a/src/conf.c b/src/conf.c index eff390c..62f6455 100644 --- a/src/conf.c +++ b/src/conf.c @@ -481,6 +481,7 @@ static int h_auth(int argc, unsigned char **argv){ newau->next = conf.authfuncs; conf.authfuncs = newau; conf.authfuncs->desc = au->desc; + conf.authfuncs->preauthorize = au->preauthorize; conf.authfuncs->authenticate = au->authenticate; conf.authfuncs->authorize = au->authorize; break; @@ -1329,13 +1330,19 @@ static int h_radius(int argc, unsigned char **argv){ if(strlen(argv[1]) > 63) argv[1][63] = 0; strcpy(radiussecret, argv[1]); for( nradservers=0; nradservers < MAXRADIUS && nradservers < argc -2; nradservers++){ + char *s = 0; + if(strchr(argv[nradservers + 2], '/')){ + *s = 0; + s++; + } if( !getip46(46, argv[nradservers + 2], (struct sockaddr *)&radiuslist[nradservers].authaddr)) return 1; + if( s && !getip46(46, s, (struct sockaddr *)&radiuslist[nradservers].localaddr)) return 2; if(!*SAPORT(&radiuslist[nradservers].authaddr))*SAPORT(&radiuslist[nradservers].authaddr) = htons(1812); port = ntohs(*SAPORT(&radiuslist[nradservers].authaddr)); radiuslist[nradservers].logaddr = radiuslist[nradservers].authaddr; *SAPORT(&radiuslist[nradservers].logaddr) = htons(port+1); /* - bindaddr = conf.intsa; + bindaddr = radiuslist[nradservers].localaddr; if ((radiuslist[nradservers].logsock = so._socket(SASOCK(&radiuslist[nradservers].logaddr), SOCK_DGRAM, 0)) < 0) return 2; if (so._bind(radiuslist[nradservers].logsock, (struct sockaddr *)&bindaddr, SASIZE(&bindaddr))) return 3; */ diff --git a/src/plugins.c b/src/plugins.c index e9d8aa0..a2621c5 100644 --- a/src/plugins.c +++ b/src/plugins.c @@ -74,9 +74,10 @@ struct symbol symbols[] = { {symbols+47, "parsestr", (void *) parsestr}, {symbols+48, "make_ace", (void *) make_ace}, {symbols+49, "freeacl", (void *) freeacl} - {symbols+50, "dolog", (void *) dolog}, - {symbols+50, "logfuncs", (void *) logfuncs}, - {symbols+50, "prelog", (void *) prelog}, + {symbols+50, "checkpreACL", (void *) checkpreACL}, + {symbols+51, "dolog", (void *) dolog}, + {symbols+52, "logfuncs", (void *) logfuncs}, + {symbols+53, "prelog", (void *) prelog}, {NULL, "", NULL} }; @@ -111,6 +112,7 @@ struct pluginlink pluginlink = { ACLmatches, alwaysauth, checkACL, + checkpreACL, nametohash, hashindex, en64, diff --git a/src/plugins/LdapPlugin/ldapauth.c b/src/plugins/LdapPlugin/ldapauth.c index 14b912d..c6c177a 100644 --- a/src/plugins/LdapPlugin/ldapauth.c +++ b/src/plugins/LdapPlugin/ldapauth.c @@ -494,6 +494,7 @@ PLUGINAPI int PLUGINCALL start(struct pluginlink * pluginlink, + myalwaysauth.preauthorize = pluginlink->checkpreACL; myalwaysauth.authenticate = ldapfunc; myalwaysauth.authorize = pluginlink->checkACL; myalwaysauth.desc = "ldap"; diff --git a/src/plugins/PamAuth/pamauth.c b/src/plugins/PamAuth/pamauth.c index da65ee9..890beb1 100644 --- a/src/plugins/PamAuth/pamauth.c +++ b/src/plugins/PamAuth/pamauth.c @@ -139,6 +139,7 @@ PLUGINAPI int PLUGINCALL start(struct pluginlink * pluginlink, int argc, unsigne already_loaded = 1; pthread_mutex_init(&pam_mutex, NULL); + pamauth.preauthorize = pluginlink->checkpreACL; pamauth.authenticate = pamfunc; pamauth.authorize = pluginlink->checkACL; pamauth.desc = "pam"; diff --git a/src/plugins/WindowsAuthentication/WindowsAuthentication.c b/src/plugins/WindowsAuthentication/WindowsAuthentication.c index 818237e..46e5324 100644 --- a/src/plugins/WindowsAuthentication/WindowsAuthentication.c +++ b/src/plugins/WindowsAuthentication/WindowsAuthentication.c @@ -78,6 +78,7 @@ PLUGINAPI int PLUGINCALL WindowsAuthentication(struct pluginlink * pluginlink, i (LPTSTR) tmpbuf, &dlen, &snu)) return 100000 + (int)GetLastError(); if(snu != SidTypeGroup && snu != SidTypeAlias && snu != SidTypeWellKnownGroup) return 12; if(!loaded){ + alwaysauth.preauthorize = pluginlink->checkpreACL; alwaysauth.authenticate = windowsfunc; alwaysauth.authorize = pluginlink->checkACL; alwaysauth.desc = "windows"; diff --git a/src/proxy.h b/src/proxy.h index faf022b..d10c291 100644 --- a/src/proxy.h +++ b/src/proxy.h @@ -173,6 +173,7 @@ int dobuf2(struct clientparam * param, unsigned char * buf, const unsigned char int doconnect(struct clientparam * param); int alwaysauth(struct clientparam * param); int ipauth(struct clientparam * param); +int dopreauth(struct clientparam * param); int doauth(struct clientparam * param); int strongauth(struct clientparam * param); void trafcountfunc(struct clientparam *param); @@ -236,10 +237,11 @@ 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); +int checkpreACL(struct clientparam * param); extern int havelog; unsigned long udpresolve(int af, unsigned char * name, unsigned char * value, unsigned *retttl, struct clientparam* param, int makeauth); -struct ace * copyacl (struct ace *ac); +void copyacl (struct ace *ac, struct srvparam *srv); struct auth * copyauth (struct auth *); void * itfree(void *data, void * retval); void freeacl(struct ace *ac); @@ -308,9 +310,9 @@ extern struct commands commandhandlers[]; extern struct radserver { #ifdef NOIPV6 - struct sockaddr_in authaddr, logaddr; + struct sockaddr_in authaddr, logaddr, localaddr; #else - struct sockaddr_in6 authaddr, logaddr; + struct sockaddr_in6 authaddr, logaddr, localaddr; #endif /* SOCKET logsock; diff --git a/src/proxymain.c b/src/proxymain.c index efad58b..5266201 100644 --- a/src/proxymain.c +++ b/src/proxymain.c @@ -1,4 +1,4 @@ -/* +/* 3APA3A simpliest proxy server (c) 2002-2017 by Vladimir Dubrovin <3proxy@3proxy.ru> @@ -34,7 +34,7 @@ void * threadfunc (void *p) { } #ifndef WITHMAIN param->req = param->sinsr; - if(param->srv->acl) param->res = checkACL(param); + if(param->srv->preacl) param->res = checkpreACL(param); if(param->res){ dolog(param, (unsigned char *)"Connect back ACL failed"); so._closesocket(param->remsock); @@ -61,7 +61,7 @@ void * threadfunc (void *p) { #ifndef _WIN32 sigset_t mask; sigfillset(&mask); - pthread_sigmask(SIG_SETMASK, &mask, NULL); + if(param->srv->service != S_UDPPM)pthread_sigmask(SIG_SETMASK, &mask, NULL); #endif ((struct clientparam *) p)->srv->pf((struct clientparam *)p); @@ -277,7 +277,7 @@ int MODULEMAINFUNC (int argc, char** argv){ srv.service = defparam.service = childdef.service; #ifndef STDMAIN - srv.acl = copyacl(conf.acl); + copyacl(conf.acl, &srv); srv.authfuncs = copyauth(conf.authfuncs); if(!conf.services){ conf.services = &srv; @@ -286,11 +286,6 @@ int MODULEMAINFUNC (int argc, char** argv){ srv.next = conf.services; conf.services = conf.services->prev = &srv; } -#else - srv.needuser = 0; - initlog(); -#endif - #ifndef _WIN32 { sigset_t mask; @@ -298,6 +293,10 @@ int MODULEMAINFUNC (int argc, char** argv){ pthread_sigmask(SIG_SETMASK, &mask, NULL); } #endif +#else + srv.needuser = 0; + initlog(); +#endif for (i=1; ihostname=(unsigned char *)mystrdup((char *)defparam.hostname); clearstat(newparam); + if(!isudp) newparam->clisock = new_sock; #ifndef STDMAIN if(makefilters(&srv, newparam) > CONTINUE){ @@ -946,6 +953,7 @@ void srvfree(struct srvparam * srv){ } if(srv->acl)freeacl(srv->acl); + if(srv->preacl)freeacl(srv->preacl); if(srv->authfuncs)freeauth(srv->authfuncs); #endif pthread_mutex_destroy(&srv->counter_mutex); @@ -1036,16 +1044,17 @@ struct auth * copyauth (struct auth * authfuncs){ return newauth; } -struct ace * copyacl (struct ace *ac){ - struct ace * ret = NULL; +void copyacl (struct ace *ac, struct srvparam *srv){ struct iplist *ipl; struct portlist *pl; struct userlist *ul; struct chain *ch; struct period *pel; struct hostname *hst; + int preacl = 1; + struct ace *acc; - ret = ac = itcopy(ac, sizeof(struct ace)); + ac = itcopy(ac, sizeof(struct ace)); for( ; ac; ac = ac->next = itcopy(ac->next, sizeof(struct ace))){ ac->src = itcopy(ac->src, sizeof(struct iplist)); for(ipl = ac->src; ipl; ipl = ipl->next = itcopy(ipl->next, sizeof(struct iplist))); @@ -1069,8 +1078,21 @@ struct ace * copyacl (struct ace *ac){ if(ch->extpass)ch->extpass = (unsigned char*)mystrdup((char *)ch->extpass); if(ch->exthost)ch->exthost = (unsigned char*)mystrdup((char *)ch->exthost); } + if(preacl){ + if(ac->dst || ac->ports || ac->users || ac->dstnames || ac->chains|| ac->action>1){ + preacl = 0; + for(acc = srv->preacl; acc; acc=acc->next)if(acc->next == ac) { + acc->next = NULL; + break; + } + srv->acl = ac; + } + else { + if(!srv->preacl) srv->preacl = ac; + } + } + } - return ret; } diff --git a/src/sockmap.c b/src/sockmap.c index dfc80eb..61f020f 100644 --- a/src/sockmap.c +++ b/src/sockmap.c @@ -8,6 +8,8 @@ #include "proxy.h" +#define MAXFAILATTEMPT 10 + #ifdef WITHLOG #if WITHLOG > 1 char logbuf[1024]; @@ -57,6 +59,7 @@ int sockmap(struct clientparam * param, int timeo, int usesplice){ FILTER_ACTION action; int res; SASIZETYPE sasize; + int needaction = 0; #ifdef WITHSPLICE uint64_t inclientpipe = 0, inserverpipe = 0; @@ -120,17 +123,17 @@ int sockmap(struct clientparam * param, int timeo, int usesplice){ if(action != PASS) RETURN(19); while( - ((!CLIENTTERM) && (inserverbuf + ((!CLIENTTERM) && fromserver && (inserverbuf #ifdef WITHSPLICE || inserverpipe #endif - || (!SERVERTERM && fromserver))) + || (!SERVERTERM ))) || - ((!SERVERTERM) && (inclientbuf + ((!SERVERTERM) && fromclient && (inclientbuf #ifdef WITHSPLICE || inclientpipe #endif - || (!CLIENTTERM && fromclient))) + || (!CLIENTTERM ))) ){ @@ -155,8 +158,12 @@ sprintf(logbuf, "int FROMCLIENT = %d, TOCLIENTBUF = %d, FROMCLIENTBUF = %d, TOSE log(logbuf); #endif + if(needaction > 2 && !sleeptime){ + if(needaction > (MAXFAILATTEMPT+1)){RETURN (93);} + sleeptime = (1<<(needaction-2)); + } if(sleeptime > 0) { - if(sleeptime > (timeo * 1000)){RETURN (92);} + if(sleeptime > (timeo * 1000)){RETURN (93);} memset(fds, 0, sizeof(fds)); fds[0].fd = param->clisock; fds[1].fd = param->remsock; @@ -216,6 +223,7 @@ log("done send to server from buf"); sl1 = (*param->bandlimfunc)(param, 0, res); if(sl1 > sleeptime) sleeptime = sl1; } + needaction = 0; continue; } } @@ -247,6 +255,7 @@ log("done send to client from buf"); param->srvoffset += res; if(param->srvoffset == param->srvinbuf)param->srvoffset = param->srvinbuf =0; if(param->srvinbuf < param->srvbufsize) TOSERVERBUF = 1; + needaction = 0; continue; } } @@ -270,6 +279,7 @@ log("done send to server from pipe"); sl1 = (*param->bandlimfunc)(param, 0, res); if(sl1 > sleeptime) sleeptime = sl1; } + needaction = 0; continue; } else { @@ -288,6 +298,7 @@ log("done send to client from pipe"); inserverpipe -= res; fromserver -= res; if(fromserver)TOSERVERPIPE = 1; + needaction = 0; continue; } else { @@ -306,6 +317,10 @@ log("read from client to pipe"); log("read failed"); #endif FROMCLIENT = TOCLIENTPIPE = 0; + if(res == 0) { + CLIENTTERM = 1; + continue; + } } else { #ifdef WITHLOG @@ -313,6 +328,7 @@ log("done read from client to pipe"); #endif inclientpipe += res; if(inclientpipe >= MAXSPLICE) TOCLIENTPIPE = 0; + needaction = 0; continue; } } @@ -328,6 +344,10 @@ log("splice finished\n"); #endif if(res <= 0) { FROMSERVER = TOSERVERPIPE = 0; + if(res == 0 || !errno) { + SERVERTERM = 1; + continue; + } } else { #ifdef WITHLOG @@ -346,8 +366,9 @@ log("done read from server to pipe\n"); fromserver = inserverpipe; FROMSERVER = 0; } + needaction = 0; + continue; } - continue; } } else @@ -360,8 +381,11 @@ log("read from client to buf"); sasize = sizeof(param->sincr); res = so._recvfrom(param->clisock, (char *)param->clibuf + param->cliinbuf, (int)MIN((uint64_t)param->clibufsize - param->cliinbuf, fromclient-inclientbuf), 0, (struct sockaddr *)¶m->sincr, &sasize); if(res <= 0) { - if(!errno)CLIENTTERM = 1; FROMCLIENT = 0; + if(res == 0){ + CLIENTTERM = 1; + continue; + } } else { #ifdef WITHLOG @@ -370,6 +394,7 @@ log("done read from client to buf"); inclientbuf += res; param->cliinbuf += res; if(param->clibufsize == param->cliinbuf) TOCLIENTBUF = 0; + needaction = 0; continue; } } @@ -381,8 +406,11 @@ log("read from server to buf"); sasize = sizeof(param->sinsr); res = so._recvfrom(param->remsock, (char *)param->srvbuf + param->srvinbuf, (int)MIN((uint64_t)param->srvbufsize - param->srvinbuf, fromserver-inserverbuf), 0, (struct sockaddr *)¶m->sinsr, &sasize); if(res <= 0) { - if(!errno) SERVERTERM = 1; FROMSERVER = 0; + if(res == 0) { + SERVERTERM = 1; + continue; + } } else { #ifdef WITHLOG @@ -402,6 +430,7 @@ log("done read from server to buf"); fromserver = inserverbuf; FROMSERVER = 0; } + needaction = 0; continue; } } @@ -639,7 +668,7 @@ log("leaving poll"); #ifdef WITHLOG log("poll error"); #endif - if(errno != EAGAIN && errno != EINTR) RETURN(91); + if(errno != EINTR) RETURN(91); break; } if(res < 1){ @@ -650,14 +679,15 @@ log("timeout"); } } } + needaction++; } res = 0; if(!fromserver && param->waitserver64) res = 98; else if(!fromclient && param->waitclient64) res = 99; - else if((inclientbuf || inserverbuf)) res = HASERROR?93:94; + else if((inclientbuf || inserverbuf)) res = 94; #ifdef WITHSPLICE - else if(inclientpipe || inserverpipe) res = HASERROR?93:94; + else if(inclientpipe || inserverpipe) res = 94; #endif else if(HASERROR) res = 94+HASERROR; diff --git a/src/structures.h b/src/structures.h index a0d01de..48735d9 100644 --- a/src/structures.h +++ b/src/structures.h @@ -215,6 +215,7 @@ typedef int (*PLUGINFUNC)(struct pluginlink *pluginlink, int argc, char** argv); struct auth { struct auth *next; + AUTHFUNC preauthorize; AUTHFUNC authenticate; AUTHFUNC authorize; char * desc; @@ -477,7 +478,7 @@ struct srvparam { #endif struct auth *authenticate; struct pollfd * srvfds; - struct ace *acl; + struct ace *preacl, *acl; struct auth *authfuncs; struct filter *filter; unsigned char * logformat; @@ -519,6 +520,7 @@ struct clientparam { operation, nfilters, nreqfilters, nhdrfilterscli, nhdrfilterssrv, npredatfilters, ndatfilterscli, ndatfilterssrv, unsafefilter, + preauthorized, bandlimver; int res, @@ -759,6 +761,7 @@ struct pluginlink { int (*ACLMatches)(struct ace* acentry, struct clientparam * param); int (*alwaysauth)(struct clientparam * param); int (*checkACL)(struct clientparam * param); + int (*checkpreACL)(struct clientparam * param); void (*nametohash)(const unsigned char * name, unsigned char *hash); unsigned (*hashindex)(const unsigned char* hash); unsigned char* (*en64)(const unsigned char *in, unsigned char *out, int inlen); diff --git a/src/tcppm.c b/src/tcppm.c index f079b00..43c1ce5 100644 --- a/src/tcppm.c +++ b/src/tcppm.c @@ -16,7 +16,7 @@ void * tcppmchild(struct clientparam* param) { int res; - if(!param->hostname)parsehostname((char *)param->srv->target, param, ntohs(param->srv->targetport)); + if(!param->hostname && parsehostname((char *)param->srv->target, param, ntohs(param->srv->targetport))) RETURN(100); param->operation = CONNECT; res = (*param->srv->authfunc)(param); if(res) {RETURN(res);} diff --git a/src/udppm.c b/src/udppm.c index 01a66df..7d01730 100644 --- a/src/udppm.c +++ b/src/udppm.c @@ -38,7 +38,7 @@ void * udppmchild(struct clientparam* param) { struct pollfd fds[256]; - if(!param->hostname)parsehostname((char *)param->srv->target, param, ntohs(param->srv->targetport)); + if(!param->hostname && parsehostname((char *)param->srv->target, param, ntohs(param->srv->targetport))) RETURN(100); if (SAISNULL(¶m->req)) { param->srv->fds.events = POLLIN; RETURN (100);