Fix to bug MXS-65: https://mariadb.atlassian.net/browse/MXS-65
Added more checks for incorrect rule syntax.
This commit is contained in:
@ -17,7 +17,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @file fwfilter.c
|
* @file dbfwfilter.c
|
||||||
* @author Markus Mäkelä
|
* @author Markus Mäkelä
|
||||||
* @date 13.2.2015
|
* @date 13.2.2015
|
||||||
* @version 1.0.0
|
* @version 1.0.0
|
||||||
@ -193,7 +193,7 @@ typedef struct rulelist_t{
|
|||||||
|
|
||||||
typedef struct user_t{
|
typedef struct user_t{
|
||||||
char* name;/*< Name of the user */
|
char* name;/*< Name of the user */
|
||||||
SPINLOCK* lock;/*< User spinlock */
|
SPINLOCK lock;/*< User spinlock */
|
||||||
QUERYSPEED* qs_limit;/*< The query speed structure unique to this user */
|
QUERYSPEED* qs_limit;/*< The query speed structure unique to this user */
|
||||||
RULELIST* rules_or;/*< If any of these rules match the action is triggered */
|
RULELIST* rules_or;/*< If any of these rules match the action is triggered */
|
||||||
RULELIST* rules_and;/*< All of these rules must match for the action to trigger */
|
RULELIST* rules_and;/*< All of these rules must match for the action to trigger */
|
||||||
@ -482,7 +482,7 @@ TIMERANGE* parse_time(char* str, FW_INSTANCE* instance)
|
|||||||
tr = (TIMERANGE*)calloc(1,sizeof(TIMERANGE));
|
tr = (TIMERANGE*)calloc(1,sizeof(TIMERANGE));
|
||||||
|
|
||||||
if(tr == NULL){
|
if(tr == NULL){
|
||||||
skygw_log_write(LOGFILE_ERROR, "fwfilter: malloc returned NULL.");
|
skygw_log_write(LOGFILE_ERROR, "dbfwfilter: malloc returned NULL.");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -649,7 +649,7 @@ void link_rules(char* rule, FW_INSTANCE* instance)
|
|||||||
|
|
||||||
if((userptr == NULL || ruleptr == NULL || modeptr == NULL)||
|
if((userptr == NULL || ruleptr == NULL || modeptr == NULL)||
|
||||||
(userptr > modeptr || userptr > ruleptr || modeptr > ruleptr)) {
|
(userptr > modeptr || userptr > ruleptr || modeptr > ruleptr)) {
|
||||||
skygw_log_write(LOGFILE_ERROR, "fwfilter: Rule syntax incorrect, right keywords not found in the correct order: %s",rule);
|
skygw_log_write(LOGFILE_ERROR, "dbfwfilter: Rule syntax incorrect, right keywords not found in the correct order: %s",rule);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -657,8 +657,19 @@ void link_rules(char* rule, FW_INSTANCE* instance)
|
|||||||
*ruleptr++ = '\0';
|
*ruleptr++ = '\0';
|
||||||
|
|
||||||
tok = strtok_r(modeptr," ",&saveptr);
|
tok = strtok_r(modeptr," ",&saveptr);
|
||||||
if(tok && strcmp(tok,"match") == 0){
|
|
||||||
|
if(tok == NULL)
|
||||||
|
{
|
||||||
|
skygw_log_write(LOGFILE_ERROR, "dbfwfilter: Rule syntax incorrect, right keywords not found in the correct order: %s",rule);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(strcmp(tok,"match") == 0){
|
||||||
tok = strtok_r(NULL," ",&saveptr);
|
tok = strtok_r(NULL," ",&saveptr);
|
||||||
|
if(tok == NULL)
|
||||||
|
{
|
||||||
|
skygw_log_write(LOGFILE_ERROR, "dbfwfilter: Rule syntax incorrect, missing keyword after 'match': %s",rule);
|
||||||
|
return;
|
||||||
|
}
|
||||||
if(strcmp(tok,"any") == 0){
|
if(strcmp(tok,"any") == 0){
|
||||||
match_any = true;
|
match_any = true;
|
||||||
}else if(strcmp(tok,"all") == 0){
|
}else if(strcmp(tok,"all") == 0){
|
||||||
@ -667,28 +678,38 @@ void link_rules(char* rule, FW_INSTANCE* instance)
|
|||||||
match_any = false;
|
match_any = false;
|
||||||
strict = true;
|
strict = true;
|
||||||
}else{
|
}else{
|
||||||
skygw_log_write(LOGFILE_ERROR, "fwfilter: Rule syntax incorrect, 'match' was not followed by 'any' or 'all': %s",rule);
|
skygw_log_write(LOGFILE_ERROR, "dbfwfilter: Rule syntax incorrect, 'match' was not followed by correct keyword: %s",rule);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tok = strtok_r(ruleptr," ",&saveptr);
|
tok = strtok_r(ruleptr," ",&saveptr);
|
||||||
tok = strtok_r(NULL," ",&saveptr);
|
tok = strtok_r(NULL," ",&saveptr);
|
||||||
|
|
||||||
while(tok)
|
|
||||||
{
|
|
||||||
RULE* rule_found = NULL;
|
|
||||||
|
|
||||||
if((rule_found = find_rule(tok,instance)) != NULL)
|
|
||||||
{
|
|
||||||
RULELIST* tmp_rl = (RULELIST*)calloc(1,sizeof(RULELIST));
|
|
||||||
tmp_rl->rule = rule_found;
|
|
||||||
tmp_rl->next = rulelist;
|
|
||||||
rulelist = tmp_rl;
|
|
||||||
|
|
||||||
}
|
if(tok == NULL)
|
||||||
tok = strtok_r(NULL," ",&saveptr);
|
{
|
||||||
}
|
skygw_log_write(LOGFILE_ERROR, "dbfwfilter: Rule syntax incorrect, no rules given: %s",rule);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
while(tok)
|
||||||
|
{
|
||||||
|
RULE* rule_found = NULL;
|
||||||
|
|
||||||
|
if((rule_found = find_rule(tok,instance)) != NULL)
|
||||||
|
{
|
||||||
|
RULELIST* tmp_rl = (RULELIST*)calloc(1,sizeof(RULELIST));
|
||||||
|
tmp_rl->rule = rule_found;
|
||||||
|
tmp_rl->next = rulelist;
|
||||||
|
rulelist = tmp_rl;
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
skygw_log_write(LOGFILE_ERROR, "dbfwfilter: Rule syntax incorrect, could not find rule '%s'.",tok);
|
||||||
|
}
|
||||||
|
tok = strtok_r(NULL," ",&saveptr);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Apply this list of rules to all the listed users
|
* Apply this list of rules to all the listed users
|
||||||
@ -698,8 +719,14 @@ void link_rules(char* rule, FW_INSTANCE* instance)
|
|||||||
userptr = strtok_r(rule," ",&saveptr);
|
userptr = strtok_r(rule," ",&saveptr);
|
||||||
userptr = strtok_r(NULL," ",&saveptr);
|
userptr = strtok_r(NULL," ",&saveptr);
|
||||||
|
|
||||||
|
if(tok == NULL)
|
||||||
|
{
|
||||||
|
skygw_log_write(LOGFILE_ERROR, "dbfwfilter: Rule syntax incorrect, no users given: %s",rule);
|
||||||
|
goto parse_err;
|
||||||
|
}
|
||||||
|
|
||||||
while(userptr)
|
while(userptr)
|
||||||
{
|
{
|
||||||
USER* user;
|
USER* user;
|
||||||
RULELIST *tl = NULL,*tail = NULL;
|
RULELIST *tl = NULL,*tail = NULL;
|
||||||
|
|
||||||
@ -709,17 +736,11 @@ void link_rules(char* rule, FW_INSTANCE* instance)
|
|||||||
user = (USER*)calloc(1,sizeof(USER));
|
user = (USER*)calloc(1,sizeof(USER));
|
||||||
|
|
||||||
if(user == NULL){
|
if(user == NULL){
|
||||||
free(rulelist);
|
skygw_log_write(LOGFILE_ERROR,"Error: dbfwfilter: failed to allocate memory when parsing rules.");
|
||||||
return;
|
goto parse_err;
|
||||||
}
|
|
||||||
|
|
||||||
if((user->lock = (SPINLOCK*)malloc(sizeof(SPINLOCK))) == NULL){
|
|
||||||
free(user);
|
|
||||||
free(rulelist);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
spinlock_init(user->lock);
|
spinlock_init(&user->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
user->name = (char*)strdup(userptr);
|
user->name = (char*)strdup(userptr);
|
||||||
@ -749,9 +770,9 @@ void link_rules(char* rule, FW_INSTANCE* instance)
|
|||||||
(void *)user);
|
(void *)user);
|
||||||
|
|
||||||
userptr = strtok_r(NULL," ",&saveptr);
|
userptr = strtok_r(NULL," ",&saveptr);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
parse_err:
|
||||||
|
|
||||||
while(rulelist)
|
while(rulelist)
|
||||||
{
|
{
|
||||||
RULELIST *tmp = rulelist;
|
RULELIST *tmp = rulelist;
|
||||||
@ -782,7 +803,11 @@ void parse_rule(char* rule, FW_INSTANCE* instance)
|
|||||||
|
|
||||||
tok = strtok_r(NULL," ,",&saveptr);
|
tok = strtok_r(NULL," ,",&saveptr);
|
||||||
|
|
||||||
if(tok == NULL) goto retblock;
|
if(tok == NULL)
|
||||||
|
{
|
||||||
|
skygw_log_write(LOGFILE_ERROR,"dbfwfilter: Rule parsing failed, incomplete rule: %s",rule);
|
||||||
|
goto retblock;
|
||||||
|
}
|
||||||
|
|
||||||
RULELIST* rlist = NULL;
|
RULELIST* rlist = NULL;
|
||||||
|
|
||||||
@ -790,7 +815,7 @@ void parse_rule(char* rule, FW_INSTANCE* instance)
|
|||||||
|
|
||||||
if(ruledef == NULL)
|
if(ruledef == NULL)
|
||||||
{
|
{
|
||||||
skygw_log_write(LOGFILE_ERROR,"Error : Memory allocation failed.");
|
skygw_log_write(LOGFILE_ERROR,"Error: Memory allocation failed.");
|
||||||
goto retblock;
|
goto retblock;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -799,7 +824,7 @@ void parse_rule(char* rule, FW_INSTANCE* instance)
|
|||||||
if(rlist == NULL)
|
if(rlist == NULL)
|
||||||
{
|
{
|
||||||
free(ruledef);
|
free(ruledef);
|
||||||
skygw_log_write(LOGFILE_ERROR,"Error : Memory allocation failed.");
|
skygw_log_write(LOGFILE_ERROR,"Error: Memory allocation failed.");
|
||||||
goto retblock;
|
goto retblock;
|
||||||
}
|
}
|
||||||
ruledef->name = strdup(tok);
|
ruledef->name = strdup(tok);
|
||||||
@ -916,7 +941,7 @@ void parse_rule(char* rule, FW_INSTANCE* instance)
|
|||||||
memcpy(str, start, (tok-start));
|
memcpy(str, start, (tok-start));
|
||||||
|
|
||||||
if(regcomp(re, str,REG_NOSUB)){
|
if(regcomp(re, str,REG_NOSUB)){
|
||||||
skygw_log_write(LOGFILE_ERROR, "fwfilter: Invalid regular expression '%s'.", str);
|
skygw_log_write(LOGFILE_ERROR, "dbfwfilter: Invalid regular expression '%s'.", str);
|
||||||
free(re);
|
free(re);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -968,7 +993,7 @@ void parse_rule(char* rule, FW_INSTANCE* instance)
|
|||||||
tok = strtok_r(NULL," ",&saveptr);
|
tok = strtok_r(NULL," ",&saveptr);
|
||||||
if(!parse_querytypes(tok,ruledef)){
|
if(!parse_querytypes(tok,ruledef)){
|
||||||
skygw_log_write(LOGFILE_ERROR,
|
skygw_log_write(LOGFILE_ERROR,
|
||||||
"fwfilter: Invalid query type"
|
"dbfwfilter: Invalid query type"
|
||||||
"requirements on where/having clauses: %s."
|
"requirements on where/having clauses: %s."
|
||||||
,tok);
|
,tok);
|
||||||
}
|
}
|
||||||
@ -1336,7 +1361,7 @@ bool rule_matches(FW_INSTANCE* my_instance, FW_SESSION* my_session, GWBUF *queue
|
|||||||
|
|
||||||
if(!rulelist->rule->allow){
|
if(!rulelist->rule->allow){
|
||||||
msg = strdup("Permission denied, query matched regular expression.");
|
msg = strdup("Permission denied, query matched regular expression.");
|
||||||
skygw_log_write(LOGFILE_TRACE, "fwfilter: rule '%s': regex matched on query",rulelist->rule->name);
|
skygw_log_write(LOGFILE_TRACE, "dbfwfilter: rule '%s': regex matched on query",rulelist->rule->name);
|
||||||
goto queryresolved;
|
goto queryresolved;
|
||||||
}else{
|
}else{
|
||||||
break;
|
break;
|
||||||
@ -1349,7 +1374,7 @@ bool rule_matches(FW_INSTANCE* my_instance, FW_SESSION* my_session, GWBUF *queue
|
|||||||
if(!rulelist->rule->allow){
|
if(!rulelist->rule->allow){
|
||||||
matches = true;
|
matches = true;
|
||||||
msg = strdup("Permission denied at this time.");
|
msg = strdup("Permission denied at this time.");
|
||||||
skygw_log_write(LOGFILE_TRACE, "fwfilter: rule '%s': query denied at: %s",rulelist->rule->name,asctime(tm_now));
|
skygw_log_write(LOGFILE_TRACE, "dbfwfilter: rule '%s': query denied at: %s",rulelist->rule->name,asctime(tm_now));
|
||||||
goto queryresolved;
|
goto queryresolved;
|
||||||
}else{
|
}else{
|
||||||
break;
|
break;
|
||||||
@ -1372,7 +1397,7 @@ bool rule_matches(FW_INSTANCE* my_instance, FW_SESSION* my_session, GWBUF *queue
|
|||||||
|
|
||||||
if(!rulelist->rule->allow){
|
if(!rulelist->rule->allow){
|
||||||
sprintf(emsg,"Permission denied to column '%s'.",strln->value);
|
sprintf(emsg,"Permission denied to column '%s'.",strln->value);
|
||||||
skygw_log_write(LOGFILE_TRACE, "fwfilter: rule '%s': query targets forbidden column: %s",rulelist->rule->name,strln->value);
|
skygw_log_write(LOGFILE_TRACE, "dbfwfilter: rule '%s': query targets forbidden column: %s",rulelist->rule->name,strln->value);
|
||||||
msg = strdup(emsg);
|
msg = strdup(emsg);
|
||||||
goto queryresolved;
|
goto queryresolved;
|
||||||
}else{
|
}else{
|
||||||
@ -1402,7 +1427,7 @@ bool rule_matches(FW_INSTANCE* my_instance, FW_SESSION* my_session, GWBUF *queue
|
|||||||
|
|
||||||
matches = true;
|
matches = true;
|
||||||
msg = strdup("Usage of wildcard denied.");
|
msg = strdup("Usage of wildcard denied.");
|
||||||
skygw_log_write(LOGFILE_TRACE, "fwfilter: rule '%s': query contains a wildcard.",rulelist->rule->name);
|
skygw_log_write(LOGFILE_TRACE, "dbfwfilter: rule '%s': query contains a wildcard.",rulelist->rule->name);
|
||||||
goto queryresolved;
|
goto queryresolved;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1420,9 +1445,9 @@ bool rule_matches(FW_INSTANCE* my_instance, FW_SESSION* my_session, GWBUF *queue
|
|||||||
rule_qs = (QUERYSPEED*)rulelist->rule->data;
|
rule_qs = (QUERYSPEED*)rulelist->rule->data;
|
||||||
spinlock_release(my_instance->lock);
|
spinlock_release(my_instance->lock);
|
||||||
|
|
||||||
spinlock_acquire(user->lock);
|
spinlock_acquire(&user->lock);
|
||||||
queryspeed = user->qs_limit;
|
queryspeed = user->qs_limit;
|
||||||
spinlock_release(user->lock);
|
spinlock_release(&user->lock);
|
||||||
|
|
||||||
while(queryspeed){
|
while(queryspeed){
|
||||||
if(queryspeed->id == rule_qs->id){
|
if(queryspeed->id == rule_qs->id){
|
||||||
@ -1453,7 +1478,7 @@ bool rule_matches(FW_INSTANCE* my_instance, FW_SESSION* my_session, GWBUF *queue
|
|||||||
double blocked_for = queryspeed->cooldown - difftime(time_now,queryspeed->triggered);
|
double blocked_for = queryspeed->cooldown - difftime(time_now,queryspeed->triggered);
|
||||||
|
|
||||||
sprintf(emsg,"Queries denied for %f seconds",blocked_for);
|
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);
|
skygw_log_write(LOGFILE_TRACE, "dbfwfilter: rule '%s': user denied for %f seconds",rulelist->rule->name,blocked_for);
|
||||||
msg = strdup(emsg);
|
msg = strdup(emsg);
|
||||||
|
|
||||||
matches = true;
|
matches = true;
|
||||||
@ -1474,7 +1499,7 @@ bool rule_matches(FW_INSTANCE* my_instance, FW_SESSION* my_session, GWBUF *queue
|
|||||||
queryspeed->active = true;
|
queryspeed->active = true;
|
||||||
|
|
||||||
skygw_log_write(LOGFILE_TRACE,
|
skygw_log_write(LOGFILE_TRACE,
|
||||||
"fwfilter: rule '%s': query limit triggered (%d queries in %f seconds), denying queries from user for %f seconds.",
|
"dbfwfilter: rule '%s': query limit triggered (%d queries in %f seconds), denying queries from user for %f seconds.",
|
||||||
rulelist->rule->name,
|
rulelist->rule->name,
|
||||||
queryspeed->limit,
|
queryspeed->limit,
|
||||||
queryspeed->period,
|
queryspeed->period,
|
||||||
@ -1504,7 +1529,7 @@ bool rule_matches(FW_INSTANCE* my_instance, FW_SESSION* my_session, GWBUF *queue
|
|||||||
{
|
{
|
||||||
matches = true;
|
matches = true;
|
||||||
msg = strdup("Required WHERE/HAVING clause is missing.");
|
msg = strdup("Required WHERE/HAVING clause is missing.");
|
||||||
skygw_log_write(LOGFILE_TRACE, "fwfilter: rule '%s': query has no where/having clause, query is denied.",
|
skygw_log_write(LOGFILE_TRACE, "dbfwfilter: rule '%s': query has no where/having clause, query is denied.",
|
||||||
rulelist->rule->name);
|
rulelist->rule->name);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|||||||
Reference in New Issue
Block a user