Refined the rule syntax,moved over to separate rule files and fixed some bugs.
This commit is contained in:
@ -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 = parse_time(tok,instance);
|
||||
TIMERANGE *tr = NULL;
|
||||
while(tok){
|
||||
TIMERANGE *tmp = 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;
|
||||
|
||||
Reference in New Issue
Block a user