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.
This commit is contained in:
z3APA3A 2020-10-16 01:38:21 +03:00
parent b1a3755a94
commit da215a152e
9 changed files with 97 additions and 34 deletions

View File

@ -676,14 +676,16 @@ int alwaysauth(struct clientparam * param){
return res; return res;
} }
int checkACL(struct clientparam * param){ int checkACL2(struct clientparam * param, int pre){
struct ace* acentry; struct ace* acentry;
if(!param->srv->acl) { acentry = pre?param->srv->preacl:param->srv->acl;
if(!acentry) {
return 0; return 0;
} }
for(acentry = param->srv->acl; acentry; acentry = acentry->next) { for(; acentry; acentry = acentry->next) {
if(ACLmatches(acentry, param)) { if(ACLmatches(acentry, param)) {
if(!pre){
param->nolog = acentry->nolog; param->nolog = acentry->nolog;
param->weight = acentry->weight; param->weight = acentry->weight;
if(acentry->action == 2) { if(acentry->action == 2) {
@ -698,12 +700,26 @@ int checkACL(struct clientparam * param){
dup = *acentry; dup = *acentry;
return handleredirect(param, &dup); return handleredirect(param, &dup);
} }
}
return acentry->action; return acentry->action;
} }
} }
return 3; 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 { struct authcache {
char * username; char * username;
char * password; char * password;
@ -771,6 +787,16 @@ int cacheauth(struct clientparam * param){
return 4; 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 doauth(struct clientparam * param){
int res = 0; int res = 0;
struct auth *authfuncs; struct auth *authfuncs;
@ -781,7 +807,8 @@ int doauth(struct clientparam * param){
for(authfuncs=param->srv->authfuncs; authfuncs; authfuncs=authfuncs->next){ for(authfuncs=param->srv->authfuncs; authfuncs; authfuncs=authfuncs->next){
res = authfuncs->authenticate?(*authfuncs->authenticate)(param):0; res = authfuncs->authenticate?(*authfuncs->authenticate)(param):0;
if(!res) { if(!res) {
if(authfuncs->authorize &&
if(!param->preauthorized && authfuncs->authorize &&
(res = (*authfuncs->authorize)(param))) (res = (*authfuncs->authorize)(param)))
return res; return res;
if(conf.authcachetype && authfuncs->authenticate && authfuncs->authenticate != cacheauth && param->username && (!(conf.authcachetype&4) || (!param->pwtype && param->password))){ 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 ipauth(struct clientparam * param){
int res; int res;
unsigned char *username; unsigned char *username;
if(param->preauthorized) return (0);
username = param->username; username = param->username;
param->username = NULL; param->username = NULL;
res = checkACL(param); res = checkACL2(param,0);
param->username = username; param->username = username;
return res; return res;
} }
@ -960,20 +989,20 @@ int strongauth(struct clientparam * param){
int radauth(struct clientparam * param); int radauth(struct clientparam * param);
struct auth authfuncs[] = { struct auth authfuncs[] = {
{authfuncs+1, NULL, NULL, ""}, {authfuncs+1, NULL,NULL, NULL, ""},
{authfuncs+2, ipauth, NULL, "iponly"}, {authfuncs+2, checkpreACL, ipauth, NULL, "iponly"},
{authfuncs+3, userauth, checkACL, "useronly"}, {authfuncs+3, checkpreACL, userauth, checkACL, "useronly"},
{authfuncs+4, dnsauth, checkACL, "dnsname"}, {authfuncs+4, checkpreACL, dnsauth, checkACL, "dnsname"},
{authfuncs+5, strongauth, checkACL, "strong"}, {authfuncs+5, checkpreACL, strongauth, checkACL, "strong"},
{authfuncs+6, cacheauth, checkACL, "cache"}, {authfuncs+6, checkpreACL, cacheauth, checkACL, "cache"},
#ifndef NORADIUS #ifndef NORADIUS
#define AUTHOFFSET 1 #define AUTHOFFSET 1
{authfuncs+7, radauth, checkACL, "radius"}, {authfuncs+7, checkpreACL, radauth, checkACL, "radius"},
#else #else
#define AUTHOFFSET 0 #define AUTHOFFSET 0
#endif #endif
{authfuncs+7+AUTHOFFSET, NULL, NULL, "none"}, {authfuncs+7+AUTHOFFSET, NULL, NULL, NULL, "none"},
{NULL, NULL, NULL, ""} {NULL, NULL, NULL, NULL, ""}
}; };

View File

@ -481,6 +481,7 @@ static int h_auth(int argc, unsigned char **argv){
newau->next = conf.authfuncs; newau->next = conf.authfuncs;
conf.authfuncs = newau; conf.authfuncs = newau;
conf.authfuncs->desc = au->desc; conf.authfuncs->desc = au->desc;
conf.authfuncs->preauthorize = au->preauthorize;
conf.authfuncs->authenticate = au->authenticate; conf.authfuncs->authenticate = au->authenticate;
conf.authfuncs->authorize = au->authorize; conf.authfuncs->authorize = au->authorize;
break; break;

View File

@ -74,6 +74,7 @@ struct symbol symbols[] = {
{symbols+47, "parsestr", (void *) parsestr}, {symbols+47, "parsestr", (void *) parsestr},
{symbols+48, "make_ace", (void *) make_ace}, {symbols+48, "make_ace", (void *) make_ace},
{symbols+49, "freeacl", (void *) freeacl}, {symbols+49, "freeacl", (void *) freeacl},
{symbols+50, "checkpreACL", (void *) checkpreACL},
{NULL, "", NULL} {NULL, "", NULL}
}; };
@ -108,6 +109,7 @@ struct pluginlink pluginlink = {
ACLmatches, ACLmatches,
alwaysauth, alwaysauth,
checkACL, checkACL,
checkpreACL,
nametohash, nametohash,
hashindex, hashindex,
en64, en64,

View File

@ -488,6 +488,7 @@ PLUGINAPI int PLUGINCALL start(struct pluginlink * pluginlink,
myalwaysauth.preauthorize = pluginlink->checkpreACL;
myalwaysauth.authenticate = ldapfunc; myalwaysauth.authenticate = ldapfunc;
myalwaysauth.authorize = pluginlink->checkACL; myalwaysauth.authorize = pluginlink->checkACL;
myalwaysauth.desc = "ldap"; myalwaysauth.desc = "ldap";

View File

@ -139,6 +139,7 @@ PLUGINAPI int PLUGINCALL start(struct pluginlink * pluginlink, int argc, unsigne
already_loaded = 1; already_loaded = 1;
pthread_mutex_init(&pam_mutex, NULL); pthread_mutex_init(&pam_mutex, NULL);
pamauth.preauthorize = pluginlink->checkpreACL;
pamauth.authenticate = pamfunc; pamauth.authenticate = pamfunc;
pamauth.authorize = pluginlink->checkACL; pamauth.authorize = pluginlink->checkACL;
pamauth.desc = "pam"; pamauth.desc = "pam";

View File

@ -78,6 +78,7 @@ PLUGINAPI int PLUGINCALL WindowsAuthentication(struct pluginlink * pluginlink, i
(LPTSTR) tmpbuf, &dlen, &snu)) return 100000 + (int)GetLastError(); (LPTSTR) tmpbuf, &dlen, &snu)) return 100000 + (int)GetLastError();
if(snu != SidTypeGroup && snu != SidTypeAlias && snu != SidTypeWellKnownGroup) return 12; if(snu != SidTypeGroup && snu != SidTypeAlias && snu != SidTypeWellKnownGroup) return 12;
if(!loaded){ if(!loaded){
alwaysauth.preauthorize = pluginlink->checkpreACL;
alwaysauth.authenticate = windowsfunc; alwaysauth.authenticate = windowsfunc;
alwaysauth.authorize = pluginlink->checkACL; alwaysauth.authorize = pluginlink->checkACL;
alwaysauth.desc = "windows"; alwaysauth.desc = "windows";

View File

@ -184,6 +184,7 @@ void close_sql();
int doconnect(struct clientparam * param); int doconnect(struct clientparam * param);
int alwaysauth(struct clientparam * param); int alwaysauth(struct clientparam * param);
int ipauth(struct clientparam * param); int ipauth(struct clientparam * param);
int dopreauth(struct clientparam * param);
int doauth(struct clientparam * param); int doauth(struct clientparam * param);
int strongauth(struct clientparam * param); int strongauth(struct clientparam * param);
void trafcountfunc(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 parseconnusername(char *username, struct clientparam *param, int extpasswd, unsigned short port);
int ACLmatches(struct ace* acentry, struct clientparam * param); int ACLmatches(struct ace* acentry, struct clientparam * param);
int checkACL(struct clientparam * param); int checkACL(struct clientparam * param);
int checkpreACL(struct clientparam * param);
extern int havelog; extern int havelog;
unsigned long udpresolve(int af, unsigned char * name, unsigned char * value, unsigned *retttl, struct clientparam* param, int makeauth); 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 *); struct auth * copyauth (struct auth *);
void * itfree(void *data, void * retval); void * itfree(void *data, void * retval);
void freeacl(struct ace *ac); void freeacl(struct ace *ac);

View File

@ -34,7 +34,7 @@ void * threadfunc (void *p) {
} }
#ifndef WITHMAIN #ifndef WITHMAIN
param->req = param->sinsr; param->req = param->sinsr;
if(param->srv->acl) param->res = checkACL(param); if(param->srv->preacl) param->res = checkpreACL(param);
if(param->res){ if(param->res){
dolog(param, (unsigned char *)"Connect back ACL failed"); dolog(param, (unsigned char *)"Connect back ACL failed");
so._closesocket(param->remsock); so._closesocket(param->remsock);
@ -277,7 +277,7 @@ int MODULEMAINFUNC (int argc, char** argv){
srv.service = defparam.service = childdef.service; srv.service = defparam.service = childdef.service;
#ifndef STDMAIN #ifndef STDMAIN
srv.acl = copyacl(conf.acl); copyacl(conf.acl, &srv);
srv.authfuncs = copyauth(conf.authfuncs); srv.authfuncs = copyauth(conf.authfuncs);
if(!conf.services){ if(!conf.services){
conf.services = &srv; conf.services = &srv;
@ -774,6 +774,13 @@ int MODULEMAINFUNC (int argc, char** argv){
else { else {
srv.fds.events = 0; srv.fds.events = 0;
} }
#ifndef STDMAIN
if((dopreauth(&defparam)) != 0){
if(!isudp) so._closesocket(new_sock);
continue;
}
#endif
if(! (newparam = myalloc (sizeof(defparam)))){ if(! (newparam = myalloc (sizeof(defparam)))){
if(!isudp) so._closesocket(new_sock); if(!isudp) so._closesocket(new_sock);
defparam.res = 21; defparam.res = 21;
@ -784,6 +791,7 @@ int MODULEMAINFUNC (int argc, char** argv){
*newparam = defparam; *newparam = defparam;
if(defparam.hostname)newparam->hostname=(unsigned char *)mystrdup((char *)defparam.hostname); if(defparam.hostname)newparam->hostname=(unsigned char *)mystrdup((char *)defparam.hostname);
clearstat(newparam); clearstat(newparam);
if(!isudp) newparam->clisock = new_sock; if(!isudp) newparam->clisock = new_sock;
#ifndef STDMAIN #ifndef STDMAIN
if(makefilters(&srv, newparam) > CONTINUE){ if(makefilters(&srv, newparam) > CONTINUE){
@ -946,6 +954,7 @@ void srvfree(struct srvparam * srv){
} }
if(srv->acl)freeacl(srv->acl); if(srv->acl)freeacl(srv->acl);
if(srv->preacl)freeacl(srv->preacl);
if(srv->authfuncs)freeauth(srv->authfuncs); if(srv->authfuncs)freeauth(srv->authfuncs);
#endif #endif
pthread_mutex_destroy(&srv->counter_mutex); pthread_mutex_destroy(&srv->counter_mutex);
@ -1036,16 +1045,17 @@ struct auth * copyauth (struct auth * authfuncs){
return newauth; return newauth;
} }
struct ace * copyacl (struct ace *ac){ void copyacl (struct ace *ac, struct srvparam *srv){
struct ace * ret = NULL;
struct iplist *ipl; struct iplist *ipl;
struct portlist *pl; struct portlist *pl;
struct userlist *ul; struct userlist *ul;
struct chain *ch; struct chain *ch;
struct period *pel; struct period *pel;
struct hostname *hst; 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))){ for( ; ac; ac = ac->next = itcopy(ac->next, sizeof(struct ace))){
ac->src = itcopy(ac->src, sizeof(struct iplist)); ac->src = itcopy(ac->src, sizeof(struct iplist));
for(ipl = ac->src; ipl; ipl = ipl->next = itcopy(ipl->next, 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->extpass)ch->extpass = (unsigned char*)mystrdup((char *)ch->extpass);
if(ch->exthost)ch->exthost = (unsigned char*)mystrdup((char *)ch->exthost); 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;
} }

View File

@ -216,6 +216,7 @@ typedef int (*PLUGINFUNC)(struct pluginlink *pluginlink, int argc, char** argv);
struct auth { struct auth {
struct auth *next; struct auth *next;
AUTHFUNC preauthorize;
AUTHFUNC authenticate; AUTHFUNC authenticate;
AUTHFUNC authorize; AUTHFUNC authorize;
char * desc; char * desc;
@ -461,7 +462,7 @@ struct srvparam {
#endif #endif
struct auth *authenticate; struct auth *authenticate;
struct pollfd * srvfds; struct pollfd * srvfds;
struct ace *acl; struct ace *preacl, *acl;
struct auth *authfuncs; struct auth *authfuncs;
struct filter *filter; struct filter *filter;
unsigned char * logformat; unsigned char * logformat;
@ -503,6 +504,7 @@ struct clientparam {
operation, operation,
nfilters, nreqfilters, nhdrfilterscli, nhdrfilterssrv, npredatfilters, ndatfilterscli, ndatfilterssrv, nfilters, nreqfilters, nhdrfilterscli, nhdrfilterssrv, npredatfilters, ndatfilterscli, ndatfilterssrv,
unsafefilter, unsafefilter,
preauthorized,
bandlimver; bandlimver;
int res, int res,
@ -744,6 +746,7 @@ struct pluginlink {
int (*ACLMatches)(struct ace* acentry, struct clientparam * param); int (*ACLMatches)(struct ace* acentry, struct clientparam * param);
int (*alwaysauth)(struct clientparam * param); int (*alwaysauth)(struct clientparam * param);
int (*checkACL)(struct clientparam * param); int (*checkACL)(struct clientparam * param);
int (*checkpreACL)(struct clientparam * param);
void (*nametohash)(const unsigned char * name, unsigned char *hash); void (*nametohash)(const unsigned char * name, unsigned char *hash);
unsigned (*hashindex)(const unsigned char* hash); unsigned (*hashindex)(const unsigned char* hash);
unsigned char* (*en64)(const unsigned char *in, unsigned char *out, int inlen); unsigned char* (*en64)(const unsigned char *in, unsigned char *out, int inlen);