Fix to MXS-71 and MXS-72.

at_times now fails if the parameter is not a properly formatted time.
on_queries was falsely identified as on_operations, the behavior is now in line with the documentation.
This commit is contained in:
Markus Makela
2015-03-28 16:03:44 +02:00
parent e0319067c9
commit 0b7e1d5a51

View File

@ -444,7 +444,7 @@ bool check_time(char* str)
char* ptr = str;
int colons = 0,numbers = 0,dashes = 0;
while(*ptr){
while(*ptr && ptr - str < 18){
if(isdigit(*ptr)){numbers++;}
else if(*ptr == ':'){colons++;}
else if(*ptr == '-'){dashes++;}
@ -498,7 +498,7 @@ TIMERANGE* parse_time(char* str, FW_INSTANCE* instance)
while(ptr - str < 19){
if(isdigit(*ptr)){
*sdest = *ptr;
}else if(*ptr == ':' ||*ptr == '-' || *ptr == '\0'){
}else if(*ptr == ':' ||*ptr == '-' || *ptr == '\0' || *ptr == ' '){
*sdest = '\0';
*idest++ = atoi(strbuffer);
sdest = strbuffer;
@ -511,7 +511,7 @@ TIMERANGE* parse_time(char* str, FW_INSTANCE* instance)
CHK_TIMES(tmptr);
if(*ptr == '\0'){
if(*ptr == '\0' || *ptr == ' '){
return tr;
}
@ -525,8 +525,8 @@ TIMERANGE* parse_time(char* str, FW_INSTANCE* instance)
sdest++;
}
return tr;
free(tr);
return NULL;
}
@ -802,89 +802,105 @@ bool link_rules(char* orig, FW_INSTANCE* instance)
return rval;
}
/**
* Parse the configuration value either as a new rule or a list of users.
* @param rule The string to parse
* @param instance The FW_FILTER instance
*/
void parse_rule(char* rule, FW_INSTANCE* instance)
bool parse_rule(char* rule, FW_INSTANCE* instance)
{
ss_dassert(rule != NULL && instance != NULL);
ss_dassert(rule != NULL && instance != NULL);
char *rulecpy = strdup(rule);
char *saveptr = NULL;
char *tok = strtok_r(rulecpy," ,",&saveptr);
bool allow,deny,mode;
RULE* ruledef = NULL;
if(tok == NULL) goto retblock;
char *rulecpy = strdup(rule);
char *saveptr = NULL;
char *tok = strtok_r(rulecpy," ,",&saveptr);
bool allow,deny,mode;
RULE* ruledef = NULL;
bool rval = true;
if(strcmp("rule",tok) == 0){ /**Define a new rule*/
if(tok == NULL)
{
skygw_log_write(LOGFILE_ERROR,"dbfwfilter: Rule parsing failed, no rule rule: %s",rule);
rval = false;
goto retblock;
}
tok = strtok_r(NULL," ,",&saveptr);
if(tok == NULL)
{
skygw_log_write(LOGFILE_ERROR,"dbfwfilter: Rule parsing failed, incomplete rule: %s",rule);
goto retblock;
}
RULELIST* rlist = NULL;
ruledef = (RULE*)calloc(1,sizeof(RULE));
if(ruledef == NULL)
{
skygw_log_write(LOGFILE_ERROR,"Error: Memory allocation failed.");
goto retblock;
}
rlist = (RULELIST*)calloc(1,sizeof(RULELIST));
if(rlist == NULL)
{
free(ruledef);
skygw_log_write(LOGFILE_ERROR,"Error: Memory allocation failed.");
goto retblock;
}
ruledef->name = strdup(tok);
ruledef->type = RT_UNDEFINED;
ruledef->on_queries = QUERY_OP_UNDEFINED;
rlist->rule = ruledef;
rlist->next = instance->rules;
instance->rules = rlist;
if(strcmp("rule",tok) == 0)
{
/**Define a new rule*/
}else if(strcmp("users",tok) == 0){
tok = strtok_r(NULL," ,",&saveptr);
/**Apply rules to users*/
add_users(rule, instance);
goto retblock;
if(tok == NULL)
{
skygw_log_write(LOGFILE_ERROR,"dbfwfilter: Rule parsing failed, incomplete rule: %s",rule);
rval = false;
goto retblock;
}
else
{
skygw_log_write(LOGFILE_ERROR,"Error : Unknown token in rule file: %s",tok);
goto retblock;
}
RULELIST* rlist = NULL;
ruledef = (RULE*)calloc(1,sizeof(RULE));
if(ruledef == NULL)
{
skygw_log_write(LOGFILE_ERROR,"Error: Memory allocation failed.");
rval = false;
goto retblock;
}
rlist = (RULELIST*)calloc(1,sizeof(RULELIST));
if(rlist == NULL)
{
free(ruledef);
skygw_log_write(LOGFILE_ERROR,"Error: Memory allocation failed.");
rval = false;
goto retblock;
}
ruledef->name = strdup(tok);
ruledef->type = RT_UNDEFINED;
ruledef->on_queries = QUERY_OP_UNDEFINED;
rlist->rule = ruledef;
rlist->next = instance->rules;
instance->rules = rlist;
}else if(strcmp("users",tok) == 0)
{
/**Apply rules to users*/
add_users(rule, instance);
goto retblock;
}
else
{
skygw_log_write(LOGFILE_ERROR,"Error : Unknown token in rule file: %s",tok);
rval = false;
goto retblock;
}
tok = strtok_r(NULL, " ,",&saveptr);
if((allow = (strcmp(tok,"allow") == 0)) ||
(deny = (strcmp(tok,"deny") == 0)))
{
mode = allow ? true:false;
ruledef->allow = mode;
ruledef->type = RT_PERMISSION;
tok = strtok_r(NULL, " ,",&saveptr);
if((allow = (strcmp(tok,"allow") == 0)) ||
(deny = (strcmp(tok,"deny") == 0))){
mode = allow ? true:false;
ruledef->allow = mode;
ruledef->type = RT_PERMISSION;
tok = strtok_r(NULL, " ,",&saveptr);
while(tok){
if(strcmp(tok,"wildcard") == 0)
while(tok)
{
if(strcmp(tok,"wildcard") == 0)
{
ruledef->type = RT_WILDCARD;
}
else if(strcmp(tok,"columns") == 0)
else if(strcmp(tok,"columns") == 0)
{
STRLINK *tail = NULL,*current;
ruledef->type = RT_COLUMN;
@ -896,20 +912,36 @@ void parse_rule(char* rule, FW_INSTANCE* instance)
tail = current;
tok = strtok_r(NULL, " ,",&saveptr);
}
ruledef->data = (void*)tail;
continue;
}
else if(strcmp(tok,"at_times") == 0)
else if(strcmp(tok,"at_times") == 0)
{
tok = strtok_r(NULL, " ,",&saveptr);
TIMERANGE *tr = NULL;
bool not_valid = false;
while(tok){
if(!check_time(tok))
{
not_valid = true;
break;
}
TIMERANGE *tmp = parse_time(tok,instance);
if(IS_RVRS_TIME(tmp)){
if(tmp == NULL)
{
skygw_log_write(LOGFILE_ERROR,"dbfwfilter: Rule parsing failed, unexpected characters after time definition.");
rval = false;
goto retblock;
}
if(IS_RVRS_TIME(tmp))
{
tmp = split_reverse_time(tmp);
}
tmp->next = tr;
@ -917,44 +949,68 @@ void parse_rule(char* rule, FW_INSTANCE* instance)
tok = strtok_r(NULL, " ,",&saveptr);
}
ruledef->active = tr;
if(not_valid)
{
continue;
}
}
else if(strcmp(tok,"regex") == 0)
else if(strcmp(tok,"regex") == 0)
{
bool escaped = false;
regex_t *re;
char* start, *str;
tok = strtok_r(NULL," ",&saveptr);
char delim = '\'';
while(*tok == '\'' || *tok == '"'){
char delim = '\'';
int n_char = 0;
while(*tok == '\'' || *tok == '"')
{
delim = *tok;
tok++;
}
start = tok;
while(isspace(*tok) || *tok == delim){
while(isspace(*tok) || *tok == delim)
{
tok++;
}
while(true){
if((*tok == delim) && !escaped){
while(n_char < 2048)
{
/** Hard-coded regex length cap */
if((*tok == delim) && !escaped)
{
break;
}
escaped = (*tok == '\\');
tok++;
n_char++;
}
if(n_char >= 2048)
{
skygw_log_write_flush(LOGFILE_ERROR, "dbfwfilter: Failed to parse rule, regular expression length is over 2048 characters.");
rval = false;
goto retblock;
}
str = calloc(((tok - start) + 1),sizeof(char));
if(str == NULL)
{
skygw_log_write_flush(LOGFILE_ERROR, "Fatal Error: malloc returned NULL.");
rval = false;
goto retblock;
}
re = (regex_t*)malloc(sizeof(regex_t));
if(re == NULL){
skygw_log_write_flush(LOGFILE_ERROR, "Fatal Error: malloc returned NULL.");
skygw_log_write_flush(LOGFILE_ERROR, "Fatal Error: malloc returned NULL.");
rval = false;
free(str);
goto retblock;
}
@ -963,7 +1019,9 @@ void parse_rule(char* rule, FW_INSTANCE* instance)
if(regcomp(re, str,REG_NOSUB)){
skygw_log_write(LOGFILE_ERROR, "dbfwfilter: Invalid regular expression '%s'.", str);
rval = false;
free(re);
goto retblock;
}
else
{
@ -973,9 +1031,9 @@ void parse_rule(char* rule, FW_INSTANCE* instance)
free(str);
}
else if(strcmp(tok,"limit_queries") == 0)
else if(strcmp(tok,"limit_queries") == 0)
{
QUERYSPEED* qs = (QUERYSPEED*)calloc(1,sizeof(QUERYSPEED));
spinlock_acquire(instance->lock);
@ -985,6 +1043,8 @@ void parse_rule(char* rule, FW_INSTANCE* instance)
tok = strtok_r(NULL," ",&saveptr);
if(tok == NULL){
free(qs);
rval = false;
skygw_log_write(LOGFILE_ERROR, "dbfwfilter: Missing parameter in limit_queries: '%s'.", rule);
goto retblock;
}
qs->limit = atoi(tok);
@ -992,41 +1052,48 @@ void parse_rule(char* rule, FW_INSTANCE* instance)
tok = strtok_r(NULL," ",&saveptr);
if(tok == NULL){
free(qs);
rval = false;
skygw_log_write(LOGFILE_ERROR, "dbfwfilter: Missing parameter in limit_queries: '%s'.", rule);
goto retblock;
}
qs->period = atof(tok);
tok = strtok_r(NULL," ",&saveptr);
if(tok == NULL){
free(qs);
rval = false;
skygw_log_write(LOGFILE_ERROR, "dbfwfilter: Missing parameter in limit_queries: '%s'.", rule);
goto retblock;
}
qs->cooldown = atof(tok);
ruledef->type = RT_THROTTLE;
ruledef->data = (void*)qs;
}
else if(strcmp(tok,"no_where_clause") == 0)
else if(strcmp(tok,"no_where_clause") == 0)
{
ruledef->type = RT_CLAUSE;
ruledef->data = (void*)mode;
}
else if(strcmp(tok,"on_operations") == 0)
else if(strcmp(tok,"on_queries") == 0)
{
tok = strtok_r(NULL," ",&saveptr);
if(!parse_querytypes(tok,ruledef)){
skygw_log_write(LOGFILE_ERROR,
"dbfwfilter: Invalid query type"
"requirements on where/having clauses: %s."
,tok);
"requirements on where/having clauses: %s."
,tok);
rval = false;
goto retblock;
}
}
tok = strtok_r(NULL," ,",&saveptr);
}
goto retblock;
tok = strtok_r(NULL," ,",&saveptr);
}
goto retblock;
}
retblock:
free(rulecpy);
free(rulecpy);
return rval;
}
@ -1048,7 +1115,8 @@ createInstance(char **options, FILTER_PARAMETER **params)
char *filename = NULL, *nl;
char buffer[2048];
FILE* file;
bool err = false;
if ((my_instance = calloc(1, sizeof(FW_INSTANCE))) == NULL ||
(my_instance->lock = (SPINLOCK*)malloc(sizeof(SPINLOCK))) == NULL){
skygw_log_write(LOGFILE_ERROR, "Memory allocation for firewall filter failed.");
@ -1119,13 +1187,18 @@ createInstance(char **options, FILTER_PARAMETER **params)
*nl = '\0';
}
parse_rule(buffer,my_instance);
if(!parse_rule(buffer,my_instance))
{
fclose(file);
err = true;
goto retblock;
}
}
fclose(file);
/**Apply the rules to users*/
bool err = false;
ptr = my_instance->userstrings;
while(ptr){
@ -1141,6 +1214,8 @@ createInstance(char **options, FILTER_PARAMETER **params)
free(tmp);
}
retblock:
if(err)
{
hrulefree(my_instance->rules);
@ -1657,6 +1732,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 strict_all)
{
bool is_sql, rval = true;
bool have_active_rule = false;
int qlen;
unsigned char* memptr = (unsigned char*)queue->start;
char *fullquery = NULL,*ptr;
@ -1697,7 +1773,8 @@ bool check_match_all(FW_INSTANCE* my_instance, FW_SESSION* my_session, GWBUF *qu
rulelist = rulelist->next;
continue;
}
have_active_rule = true;
if(!rule_matches(my_instance,my_session,queue,user,rulelist,fullquery)){
rval = false;
@ -1707,6 +1784,12 @@ bool check_match_all(FW_INSTANCE* my_instance, FW_SESSION* my_session, GWBUF *qu
rulelist = rulelist->next;
}
if(!have_active_rule)
{
/** No active rules */
rval = false;
}
retblock:
free(fullquery);