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);