Fixes to fwfilter rule processing.
This commit is contained in:
@ -625,6 +625,95 @@ void add_users(char* rule, FW_INSTANCE* instance)
|
|||||||
instance->userstrings = link;
|
instance->userstrings = link;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool check_throttle_timers(FW_INSTANCE* my_instance, FW_SESSION* my_session, USER* user, RULELIST *rulelist)
|
||||||
|
{
|
||||||
|
RULELIST* rlist = rulelist;
|
||||||
|
QUERYSPEED* queryspeed = NULL;
|
||||||
|
QUERYSPEED* rule_qs = NULL;
|
||||||
|
time_t time_now = time(NULL);
|
||||||
|
bool rval = false;
|
||||||
|
while(rlist)
|
||||||
|
{
|
||||||
|
if(rlist->rule->type == RT_THROTTLE)
|
||||||
|
{
|
||||||
|
spinlock_acquire(my_instance->lock);
|
||||||
|
rule_qs = (QUERYSPEED*) rlist->rule->data;
|
||||||
|
spinlock_release(my_instance->lock);
|
||||||
|
|
||||||
|
spinlock_acquire(user->lock);
|
||||||
|
queryspeed = user->qs_limit;
|
||||||
|
spinlock_release(user->lock);
|
||||||
|
|
||||||
|
while(queryspeed)
|
||||||
|
{
|
||||||
|
if(queryspeed->id == rule_qs->id)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
queryspeed = queryspeed->next;
|
||||||
|
}
|
||||||
|
if(queryspeed)
|
||||||
|
{
|
||||||
|
if(difftime(time_now,queryspeed->triggered) < queryspeed->cooldown)
|
||||||
|
{
|
||||||
|
rval = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
queryspeed->triggered = 0;
|
||||||
|
queryspeed->first_query = 0;
|
||||||
|
queryspeed->count = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rlist = rlist->next;
|
||||||
|
}
|
||||||
|
return rval;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
is_throttle_active(FW_INSTANCE* my_instance, FW_SESSION* my_session, USER* user, RULELIST *rulelist)
|
||||||
|
{
|
||||||
|
bool rval = false;
|
||||||
|
QUERYSPEED* queryspeed = NULL;
|
||||||
|
QUERYSPEED* rule_qs = NULL;
|
||||||
|
time_t time_now;
|
||||||
|
char emsg[1024];
|
||||||
|
|
||||||
|
if(rulelist->rule->type == RT_THROTTLE)
|
||||||
|
{
|
||||||
|
time(&time_now);
|
||||||
|
|
||||||
|
spinlock_acquire(my_instance->lock);
|
||||||
|
rule_qs = (QUERYSPEED*) rulelist->rule->data;
|
||||||
|
spinlock_release(my_instance->lock);
|
||||||
|
|
||||||
|
spinlock_acquire(user->lock);
|
||||||
|
queryspeed = user->qs_limit;
|
||||||
|
spinlock_release(user->lock);
|
||||||
|
|
||||||
|
while(queryspeed)
|
||||||
|
{
|
||||||
|
if(queryspeed->id == rule_qs->id)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
queryspeed = queryspeed->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(queryspeed && difftime(time_now,queryspeed->triggered) < queryspeed->cooldown)
|
||||||
|
{
|
||||||
|
rval = true;
|
||||||
|
double blocked_for = queryspeed->cooldown - difftime(time_now,queryspeed->triggered);
|
||||||
|
|
||||||
|
sprintf(emsg,"Queries denied for %f seconds",blocked_for);
|
||||||
|
skygw_log_write(LOGFILE_TRACE, "fwfilter: rule '%s': user denied for %f seconds",rulelist->rule->name,blocked_for);
|
||||||
|
my_session->errmsg = strdup(emsg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rval;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses the list of rule strings for users and links them against the listed rules.
|
* Parses the list of rule strings for users and links them against the listed rules.
|
||||||
* Only adds those rules that are found. If the rule isn't found a message is written to the error log.
|
* Only adds those rules that are found. If the rule isn't found a message is written to the error log.
|
||||||
@ -1440,7 +1529,14 @@ bool rule_matches(FW_INSTANCE* my_instance, FW_SESSION* my_session, GWBUF *queue
|
|||||||
user->qs_limit = queryspeed;
|
user->qs_limit = queryspeed;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(queryspeed->count > queryspeed->limit)
|
block_triggered:
|
||||||
|
|
||||||
|
if(queryspeed->limit == 1)
|
||||||
|
{
|
||||||
|
matches = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(queryspeed->count >= queryspeed->limit)
|
||||||
{
|
{
|
||||||
queryspeed->triggered = time_now;
|
queryspeed->triggered = time_now;
|
||||||
queryspeed->count = 0;
|
queryspeed->count = 0;
|
||||||
@ -1468,7 +1564,7 @@ bool rule_matches(FW_INSTANCE* my_instance, FW_SESSION* my_session, GWBUF *queue
|
|||||||
|
|
||||||
matches = true;
|
matches = true;
|
||||||
}
|
}
|
||||||
else if(difftime(time_now,queryspeed->first_query) < queryspeed->period)
|
else if(difftime(time_now,queryspeed->first_query) <= queryspeed->period)
|
||||||
{
|
{
|
||||||
queryspeed->count++;
|
queryspeed->count++;
|
||||||
}
|
}
|
||||||
@ -1477,6 +1573,11 @@ bool rule_matches(FW_INSTANCE* my_instance, FW_SESSION* my_session, GWBUF *queue
|
|||||||
queryspeed->first_query = time_now;
|
queryspeed->first_query = time_now;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(!matches && queryspeed->count >= queryspeed->limit)
|
||||||
|
{
|
||||||
|
goto block_triggered;
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RT_CLAUSE:
|
case RT_CLAUSE:
|
||||||
@ -1536,7 +1637,10 @@ bool check_match_any(FW_INSTANCE* my_instance, FW_SESSION* my_session, GWBUF *qu
|
|||||||
memset(fullquery + qlen,0,1);
|
memset(fullquery + qlen,0,1);
|
||||||
}
|
}
|
||||||
|
|
||||||
rulelist = user->rules_or;
|
if((rulelist = user->rules_or) == NULL)
|
||||||
|
{
|
||||||
|
goto retblock;
|
||||||
|
}
|
||||||
|
|
||||||
while(rulelist){
|
while(rulelist){
|
||||||
|
|
||||||
@ -1544,9 +1648,19 @@ bool check_match_any(FW_INSTANCE* my_instance, FW_SESSION* my_session, GWBUF *qu
|
|||||||
rulelist = rulelist->next;
|
rulelist = rulelist->next;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if((rval = rule_matches(my_instance,my_session,queue,user,rulelist,fullquery))){
|
if((rval = rule_matches(my_instance,my_session,queue,user,rulelist,fullquery))){
|
||||||
goto retblock;
|
goto retblock;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(rulelist->rule->type == RT_THROTTLE)
|
||||||
|
{
|
||||||
|
if(is_throttle_active(my_instance,my_session,user,rulelist))
|
||||||
|
{
|
||||||
|
rval = true;
|
||||||
|
goto retblock;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
rulelist = rulelist->next;
|
rulelist = rulelist->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1567,7 +1681,7 @@ bool check_match_any(FW_INSTANCE* my_instance, FW_SESSION* my_session, GWBUF *qu
|
|||||||
*/
|
*/
|
||||||
bool check_match_all(FW_INSTANCE* my_instance, FW_SESSION* my_session, GWBUF *queue, USER* user)
|
bool check_match_all(FW_INSTANCE* my_instance, FW_SESSION* my_session, GWBUF *queue, USER* user)
|
||||||
{
|
{
|
||||||
bool is_sql, rval = 0;
|
bool is_sql, rval = true;
|
||||||
int qlen;
|
int qlen;
|
||||||
char *fullquery = NULL,*ptr;
|
char *fullquery = NULL,*ptr;
|
||||||
|
|
||||||
@ -1586,7 +1700,11 @@ bool check_match_all(FW_INSTANCE* my_instance, FW_SESSION* my_session, GWBUF *qu
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
rulelist = user->rules_or;
|
if((rulelist = user->rules_and) == NULL)
|
||||||
|
{
|
||||||
|
rval = false;
|
||||||
|
goto retblock;
|
||||||
|
}
|
||||||
|
|
||||||
while(rulelist){
|
while(rulelist){
|
||||||
|
|
||||||
@ -1595,13 +1713,19 @@ bool check_match_all(FW_INSTANCE* my_instance, FW_SESSION* my_session, GWBUF *qu
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if(!rule_matches(my_instance,my_session,queue,user,rulelist,fullquery)){
|
if(!rule_matches(my_instance,my_session,queue,user,rulelist,fullquery)){
|
||||||
rval = false;
|
rval = false;
|
||||||
goto retblock;
|
|
||||||
}
|
}
|
||||||
rulelist = rulelist->next;
|
rulelist = rulelist->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(rval == false)
|
||||||
|
{
|
||||||
|
rulelist = user->rules_and;
|
||||||
|
rval = check_throttle_timers(my_instance,my_session,user,rulelist);
|
||||||
|
}
|
||||||
|
|
||||||
retblock:
|
retblock:
|
||||||
|
|
||||||
free(fullquery);
|
free(fullquery);
|
||||||
|
Reference in New Issue
Block a user