mirror of
https://github.com/3proxy/3proxy.git
synced 2025-02-24 02:55:40 +08:00
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:
parent
b1a3755a94
commit
da215a152e
57
src/auth.c
57
src/auth.c
@ -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, ""}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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,
|
||||||
|
@ -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";
|
||||||
|
@ -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";
|
||||||
|
@ -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";
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
Loading…
Reference in New Issue
Block a user