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,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, ""}
};

View File

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

View File

@ -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,

View File

@ -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";

View File

@ -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";

View File

@ -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";

View File

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

View File

@ -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;
}

View File

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