Added a regex rule.

This commit is contained in:
Markus Makela 2014-10-27 13:38:31 +02:00
parent 38de0909c3
commit 339974ae84

View File

@ -58,7 +58,7 @@
#include <skygw_types.h> #include <skygw_types.h>
#include <time.h> #include <time.h>
#include <assert.h> #include <assert.h>
#include <regex.h>
MODULE_INFO info = { MODULE_INFO info = {
MODULE_API_FILTER, MODULE_API_FILTER,
MODULE_ALPHA_RELEASE, MODULE_ALPHA_RELEASE,
@ -110,9 +110,9 @@ typedef enum{
typedef enum { typedef enum {
RT_UNDEFINED, RT_UNDEFINED,
RT_COLUMN, RT_COLUMN,
RT_TIME,
RT_PERMISSION, RT_PERMISSION,
RT_WILDCARD RT_WILDCARD,
RT_REGEX
}ruletype_t; }ruletype_t;
/** /**
@ -495,7 +495,7 @@ TIMERANGE* parse_time(char* str, FW_INSTANCE* instance)
tr = (TIMERANGE*)malloc(sizeof(TIMERANGE)); tr = (TIMERANGE*)malloc(sizeof(TIMERANGE));
if(tr == NULL){ if(tr == NULL){
skygw_log_write(LOGFILE_ERROR, "fwfilter error: malloc returned NULL."); skygw_log_write(LOGFILE_ERROR, "fwfilter: malloc returned NULL.");
return NULL; return NULL;
} }
@ -678,7 +678,7 @@ void link_rules(char* rule, FW_INSTANCE* instance)
(void *)userptr, (void *)userptr,
(void *)rulelist) == 0) (void *)rulelist) == 0)
{ {
skygw_log_write(LOGFILE_TRACE, "Name conflict in fwfilter: %s was found twice.",tok); skygw_log_write(LOGFILE_TRACE, "fwfilter: Name conflict (%s was found twice)",tok);
} }
userptr = strtok(NULL," ,"); userptr = strtok(NULL," ,");
@ -732,6 +732,8 @@ void parse_rule(char* rule, FW_INSTANCE* instance)
ruledef->type = RT_PERMISSION; ruledef->type = RT_PERMISSION;
tok = strtok(NULL, " ,"); tok = strtok(NULL, " ,");
while(tok){
if(strcmp(tok,"wildcard") == 0) if(strcmp(tok,"wildcard") == 0)
{ {
ruledef->type = RT_WILDCARD; ruledef->type = RT_WILDCARD;
@ -750,6 +752,7 @@ void parse_rule(char* rule, FW_INSTANCE* instance)
} }
ruledef->data = (void*)tail; ruledef->data = (void*)tail;
continue;
} }
else if(strcmp(tok,"times") == 0) else if(strcmp(tok,"times") == 0)
@ -764,6 +767,42 @@ void parse_rule(char* rule, FW_INSTANCE* instance)
} }
ruledef->active = tr; ruledef->active = tr;
} }
else if(strcmp(tok,"regex") == 0)
{
bool escaped = false;
tok += 6;
while(isspace(*tok) || *tok == '\'' || *tok == '"'){
tok++;
}
char* start = tok, *str;
while(true){
if((*tok == '\'' || *tok == '"') && !escaped){
break;
}
escaped = (*tok == '\\');
tok++;
}
str = malloc(((tok - start) + 1)*sizeof(char));
*tok = '\0';
memcpy(str, start, (tok-start) + 1);
regex_t *re = malloc(sizeof(regex_t));
if(regcomp(re, str,REG_NOSUB)){
skygw_log_write(LOGFILE_ERROR, "fwfilter: Invalid regular expression '%s'.", str);
free(re);
}
ruledef->type = RT_REGEX;
ruledef->data = (void*) re;
}
tok = strtok(NULL," ,");
}
goto retblock; goto retblock;
} }
@ -805,7 +844,7 @@ createInstance(char **options, FILTER_PARAMETER **params)
for(i = 0;params[i];i++){ for(i = 0;params[i];i++){
if(strstr(params[i]->name,"rule")){ if(strstr(params[i]->name,"rule")){
parse_rule(strip_tags(params[i]->value),my_instance); parse_rule(params[i]->value,my_instance);
}else if(strcmp(params[i]->name,"mode") == 0 && }else if(strcmp(params[i]->name,"mode") == 0 &&
strcmp(params[i]->value,"whitelist") == 0){ strcmp(params[i]->value,"whitelist") == 0){
my_instance->def_op = false; my_instance->def_op = false;
@ -1002,9 +1041,10 @@ routeQuery(FILTER *instance, void *session, GWBUF *queue)
FW_SESSION *my_session = (FW_SESSION *)session; FW_SESSION *my_session = (FW_SESSION *)session;
FW_INSTANCE *my_instance = (FW_INSTANCE *)instance; FW_INSTANCE *my_instance = (FW_INSTANCE *)instance;
time_t time_now; time_t time_now;
struct tm* tm_now; bool accept = my_instance->def_op,
bool accept = my_instance->def_op; is_sql = false,
char *where, *msg = NULL; is_real = false;
char *where, *msg = NULL, *fullquery,*ptr;
char uname[128]; char uname[128];
char uname_addr[128]; char uname_addr[128];
char addr[128]; char addr[128];
@ -1013,13 +1053,13 @@ routeQuery(FILTER *instance, void *session, GWBUF *queue)
RULELIST *rulelist = NULL; RULELIST *rulelist = NULL;
STRLINK* strln = NULL; STRLINK* strln = NULL;
TIMERANGE *times; TIMERANGE *times;
int qlen;
sprintf(uname_addr,"%s@%s",dcb->user,dcb->remote); sprintf(uname_addr,"%s@%s",dcb->user,dcb->remote);
sprintf(uname,"%s@%%",dcb->user); sprintf(uname,"%s@%%",dcb->user);
sprintf(addr,"%%@%s",dcb->remote); sprintf(addr,"%%@%s",dcb->remote);
time(&time_now); time(&time_now);
tm_now = localtime(&time_now);
@ -1039,6 +1079,19 @@ routeQuery(FILTER *instance, void *session, GWBUF *queue)
goto queryresolved; goto queryresolved;
} }
is_sql = modutil_is_SQL(queue);
if(is_sql){
if(!query_is_parsed(queue)){
parse_query(queue);
}
modutil_extract_SQL(queue, &ptr, &qlen);
fullquery = malloc((qlen + 1) * sizeof(char));
memcpy(fullquery,ptr,qlen);
memset(fullquery + qlen,0,1);
is_real = skygw_is_real_query(queue);
}
while(rulelist){ while(rulelist){
if(rulelist->rule->active != NULL){ if(rulelist->rule->active != NULL){
@ -1065,10 +1118,26 @@ routeQuery(FILTER *instance, void *session, GWBUF *queue)
case RT_UNDEFINED: case RT_UNDEFINED:
break; break;
case RT_REGEX:
if(fullquery && regexec(rulelist->rule->data,fullquery,0,NULL,0) == 0){
accept = rulelist->rule->allow;
if(!rulelist->rule->allow){
msg = strdup("Permission denied, query matched regular expression.");
goto queryresolved;
}else{
break;
}
}
break;
case RT_PERMISSION: case RT_PERMISSION:
if(!rulelist->rule->allow){ if(!rulelist->rule->allow){
accept = false; accept = false;
msg = strdup("Permission denied."); msg = strdup("Permission denied at this time.");
goto queryresolved; goto queryresolved;
}else{ }else{
break; break;
@ -1077,13 +1146,7 @@ routeQuery(FILTER *instance, void *session, GWBUF *queue)
case RT_COLUMN: case RT_COLUMN:
if(modutil_is_SQL(queue)){ if(is_sql && is_real){
if(!query_is_parsed(queue)){
parse_query(queue);
}
if(skygw_is_real_query(queue)){
strln = (STRLINK*)rulelist->rule->data; strln = (STRLINK*)rulelist->rule->data;
where = skygw_get_affected_fields(queue); where = skygw_get_affected_fields(queue);
@ -1107,41 +1170,13 @@ routeQuery(FILTER *instance, void *session, GWBUF *queue)
} }
} }
} }
}
break;
case RT_TIME: /**Obsolete*/
times = (TIMERANGE*)rulelist->rule->data;
while(times){
if(inside_timerange(times)){
accept = rulelist->rule->allow;
skygw_log_write(LOGFILE_TRACE, "Firewall: Query entered at %s, rule %s activated.",asctime(tm_now),rulelist->rule->name);
if(!rulelist->rule->allow){
goto queryresolved;
}else{
break;
}
break;
}
times = times->next;
}
break; break;
case RT_WILDCARD: case RT_WILDCARD:
if(modutil_is_SQL(queue)){ if(is_sql && is_real){
if(!query_is_parsed(queue)){
parse_query(queue);
}
if(skygw_is_real_query(queue)){
where = skygw_get_affected_fields(queue); where = skygw_get_affected_fields(queue);
@ -1157,7 +1192,7 @@ routeQuery(FILTER *instance, void *session, GWBUF *queue)
} }
} }
} }
}
break; break;
} }