diff --git a/src/auth.c b/src/auth.c index b7b3851..1ccb802 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/conf.c b/src/conf.c index 6626ea9..53ccf9e 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; diff --git a/src/plugins.c b/src/plugins.c index a0681df..fbffc28 100644 --- a/src/plugins.c +++ b/src/plugins.c @@ -74,6 +74,7 @@ struct symbol symbols[] = { {symbols+47, "parsestr", (void *) parsestr}, {symbols+48, "make_ace", (void *) make_ace}, {symbols+49, "freeacl", (void *) freeacl}, + {symbols+50, "checkpreACL", (void *) checkpreACL}, {NULL, "", NULL} }; @@ -108,6 +109,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 1572b4d..7e14867 100644 --- a/src/plugins/LdapPlugin/ldapauth.c +++ b/src/plugins/LdapPlugin/ldapauth.c @@ -488,6 +488,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 85beda4..abc9982 100644 --- a/src/proxy.h +++ b/src/proxy.h @@ -184,6 +184,7 @@ void close_sql(); 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); @@ -248,10 +249,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); diff --git a/src/proxymain.c b/src/proxymain.c index afdf362..280a166 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); @@ -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; @@ -774,6 +774,13 @@ int MODULEMAINFUNC (int argc, char** argv){ else { srv.fds.events = 0; } + +#ifndef STDMAIN + if((dopreauth(&defparam)) != 0){ + if(!isudp) so._closesocket(new_sock); + continue; + } +#endif if(! (newparam = myalloc (sizeof(defparam)))){ if(!isudp) so._closesocket(new_sock); defparam.res = 21; @@ -784,6 +791,7 @@ int MODULEMAINFUNC (int argc, char** argv){ *newparam = defparam; if(defparam.hostname)newparam->hostname=(unsigned char *)mystrdup((char *)defparam.hostname); clearstat(newparam); + if(!isudp) newparam->clisock = new_sock; #ifndef STDMAIN if(makefilters(&srv, newparam) > CONTINUE){ @@ -946,6 +954,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 +1045,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 +1079,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/structures.h b/src/structures.h index 6e41a03..39fb906 100644 --- a/src/structures.h +++ b/src/structures.h @@ -216,6 +216,7 @@ typedef int (*PLUGINFUNC)(struct pluginlink *pluginlink, int argc, char** argv); struct auth { struct auth *next; + AUTHFUNC preauthorize; AUTHFUNC authenticate; AUTHFUNC authorize; char * desc; @@ -461,7 +462,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; @@ -503,6 +504,7 @@ struct clientparam { operation, nfilters, nreqfilters, nhdrfilterscli, nhdrfilterssrv, npredatfilters, ndatfilterscli, ndatfilterssrv, unsafefilter, + preauthorized, bandlimver; int res, @@ -744,6 +746,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);