Fixes to fwfilter rule processing.

This commit is contained in:
Markus Makela
2015-02-19 16:41:40 +02:00
parent 3ca09dc77c
commit 20b075c67b

View File

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