From da215a152e41ed8d9c184aeb94009d66965cb9cd Mon Sep 17 00:00:00 2001 From: z3APA3A <3APA3A@3proxy.ru> Date: Fri, 16 Oct 2020 01:38:21 +0300 Subject: [PATCH] Preauthorization added ACL which can be checked prior to request parsing and authentication (first entries with only IP and time, if any) are automatically marked as preauthentication and checked immediately after connection is accepted, prior to any resources are allocated. Connection is silently dropped if preauthentication fails. --- src/auth.c | 79 +++++++++++++------ src/conf.c | 1 + src/plugins.c | 2 + src/plugins/LdapPlugin/ldapauth.c | 1 + src/plugins/PamAuth/pamauth.c | 1 + .../WindowsAuthentication.c | 1 + src/proxy.h | 4 +- src/proxymain.c | 37 +++++++-- src/structures.h | 5 +- 9 files changed, 97 insertions(+), 34 deletions(-) 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);