Refined the rule syntax,moved over to separate rule files and fixed some bugs.

This commit is contained in:
Markus Makela
2014-10-29 16:10:04 +02:00
parent a78f1e1b6c
commit 39cee913cc

View File

@ -25,20 +25,17 @@
* This filter uses "rules" to define the blcking parameters. To configure rules into the configuration file,
* give each rule a unique name and assing the rule contents by passing a string enclosed in quotes.
*
* For example, to define a rule denying users from accessing the column 'salary', the following is needed in the configuration file:
* For example, to define a rule denying users from accessing the column 'salary' between 15:00 and 17:00, the following is needed in the configuration file:
*
* rule1="rule block_salary deny columns salary"
* rule1="rule block_salary deny columns salary at_times 15:00:00-17:00:00"
*
* To apply this rule to users John, connecting from any address, and Jane, connecting from the address 192.168.0.1, use the following:
*
* rule2="users John@% Jane@192.168.0.1 rules block_salary"
* rule2="users John@% Jane@192.168.0.1 match any rules block_salary"
*
* Rule syntax TODO: implement timeranges, query type restrictions
* Rule syntax TODO: query type restrictions
*
* rule NAME deny|allow|require
* [wildcard|columns VALUE ...]
* [times VALUE...]
* [on_queries [all|select|update|delete|insert]...]
* rule NAME deny|allow [wildcard | columns VALUE ... | regex REGEX] [at_times VALUE...]
*/
#include <my_config.h>
#include <stdint.h>
@ -432,7 +429,9 @@ char* next_ip_class(char* str)
}
if(ptr == str){
return NULL;
*ptr++ = '%';
*ptr = '\0';
return str;
}
*++ptr = '%';
@ -751,7 +750,7 @@ void link_rules(char* rule, FW_INSTANCE* instance)
user->name = strdup(userptr);
tl = rlistdup(rulelist);
tail = tl;
while(tail->next){
while(tail && tail->next){
tail = tail->next;
}
@ -797,6 +796,7 @@ void parse_rule(char* rule, FW_INSTANCE* instance)
rlist = (RULELIST*)calloc(1,sizeof(RULELIST));
ruledef->name = strdup(tok);
ruledef->type = RT_UNDEFINED;
ruledef->on_queries = ALL;
rlist->rule = ruledef;
rlist->next = instance->rules;
instance->rules = rlist;
@ -830,7 +830,7 @@ void parse_rule(char* rule, FW_INSTANCE* instance)
STRLINK *tail = NULL,*current;
ruledef->type = RT_COLUMN;
tok = strtok(NULL, " ,");
while(tok && strcmp(tok,"times") != 0){
while(tok && strcmp(tok,"at_times") != 0){
current = malloc(sizeof(STRLINK));
current->value = strdup(tok);
current->next = tail;
@ -842,15 +842,20 @@ void parse_rule(char* rule, FW_INSTANCE* instance)
continue;
}
else if(strcmp(tok,"times") == 0)
else if(strcmp(tok,"at_times") == 0)
{
tok = strtok(NULL, " ,");
TIMERANGE *tr = NULL;
while(tok){
TIMERANGE *tmp = parse_time(tok,instance);
TIMERANGE *tr = parse_time(tok,instance);
if(IS_RVRS_TIME(tr)){
tr = split_reverse_time(tr);
if(IS_RVRS_TIME(tmp)){
tmp = split_reverse_time(tmp);
}
tmp->next = tr;
tr = tmp;
tok = strtok(NULL, " ,");
}
ruledef->active = tr;
}
@ -873,8 +878,9 @@ void parse_rule(char* rule, FW_INSTANCE* instance)
}
str = malloc(((tok - start) + 1)*sizeof(char));
*tok = '\0';
memcpy(str, start, (tok-start) + 1);
memcpy(str, start, (tok-start));
memset((str + (tok-start) +1),0,1);
regex_t *re = malloc(sizeof(regex_t));
@ -911,16 +917,19 @@ static FILTER *
createInstance(char **options, FILTER_PARAMETER **params)
{
FW_INSTANCE *my_instance;
int i,paramc;
HASHTABLE* ht;
STRLINK *ptr,*tmp;
char *filename, *nl;
char buffer[2048];
FILE* file;
if ((my_instance = calloc(1, sizeof(FW_INSTANCE))) == NULL){
return NULL;
}
int i;
HASHTABLE* ht;
STRLINK *ptr,*tmp;
if((ht = hashtable_alloc(7, hashkeyfun, hashcmpfun)) == NULL){
skygw_log_write(LOGFILE_ERROR, "Unable to allocate hashtable.");
free(my_instance);
return NULL;
}
@ -930,14 +939,37 @@ createInstance(char **options, FILTER_PARAMETER **params)
my_instance->def_op = true;
for(i = 0;params[i];i++){
if(strstr(params[i]->name,"rule")){
parse_rule(params[i]->value,my_instance);
}else if(strcmp(params[i]->name,"mode") == 0 &&
strcmp(params[i]->value,"whitelist") == 0){
my_instance->def_op = false;
if(strcmp(params[i]->name, "rulelist") == 0){
filename = strdup(params[i]->value);
}
}
if((file = fopen(filename,"rb")) == NULL ){
free(my_instance);
free(filename);
return NULL;
}
free(filename);
while(!feof(file))
{
if(fgets(buffer,2048,file) == NULL){
free(my_instance);
return NULL;
}
if((nl = strchr(buffer,'\n')) != NULL && ((char*)nl - (char*)buffer) < 2048){
*nl = '\0';
}
parse_rule(buffer,my_instance);
}
fclose(file);
/**Apply the rules to users*/
ptr = my_instance->userstrings;
while(ptr){
@ -1148,6 +1180,7 @@ routeQuery(FILTER *instance, void *session, GWBUF *queue)
FW_SESSION *my_session = (FW_SESSION *)session;
FW_INSTANCE *my_instance = (FW_INSTANCE *)instance;
time_t time_now;
struct tm* tm_now;
bool accept = my_instance->def_op,
is_sql = false,
is_real = false,rule_match;
@ -1164,6 +1197,7 @@ routeQuery(FILTER *instance, void *session, GWBUF *queue)
sprintf(uname_addr,"%s@%s",dcb->user,ipaddr);
time(&time_now);
tm_now = localtime(&time_now);
if((user = (USER*)hashtable_fetch(my_instance->htable, uname_addr)) == NULL){
while(user == NULL && next_ip_class(ipaddr)){
@ -1216,6 +1250,7 @@ routeQuery(FILTER *instance, void *session, GWBUF *queue)
switch(rulelist->rule->type){
case RT_UNDEFINED:
skygw_log_write_flush(LOGFILE_ERROR, "Error: Undefined rule type found.");
break;
case RT_REGEX:
@ -1226,6 +1261,7 @@ routeQuery(FILTER *instance, void *session, GWBUF *queue)
if(!rulelist->rule->allow){
msg = strdup("Permission denied, query matched regular expression.");
skygw_log_write(LOGFILE_TRACE, "fwfilter: rule '%s': regex matched on query",rulelist->rule->name);
goto queryresolved;
}else{
break;
@ -1238,6 +1274,7 @@ routeQuery(FILTER *instance, void *session, GWBUF *queue)
if(!rulelist->rule->allow){
accept = false;
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));
goto queryresolved;
}else{
break;
@ -1260,6 +1297,7 @@ routeQuery(FILTER *instance, void *session, GWBUF *queue)
if(!rulelist->rule->allow){
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);
msg = strdup(emsg);
goto queryresolved;
}else{
@ -1287,6 +1325,7 @@ routeQuery(FILTER *instance, void *session, GWBUF *queue)
if(!rulelist->rule->allow){
msg = strdup("Usage of wildcard denied.");
skygw_log_write(LOGFILE_TRACE, "fwfilter: rule '%s': query contains a wildcard.",rulelist->rule->name);
goto queryresolved;
}
}
@ -1295,6 +1334,9 @@ routeQuery(FILTER *instance, void *session, GWBUF *queue)
break;
default:
break;
}
rulelist = rulelist->next;