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,
|
* 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.
|
* 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:
|
* 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
|
* rule NAME deny|allow [wildcard | columns VALUE ... | regex REGEX] [at_times VALUE...]
|
||||||
* [wildcard|columns VALUE ...]
|
|
||||||
* [times VALUE...]
|
|
||||||
* [on_queries [all|select|update|delete|insert]...]
|
|
||||||
*/
|
*/
|
||||||
#include <my_config.h>
|
#include <my_config.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
@ -432,7 +429,9 @@ char* next_ip_class(char* str)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(ptr == str){
|
if(ptr == str){
|
||||||
return NULL;
|
*ptr++ = '%';
|
||||||
|
*ptr = '\0';
|
||||||
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
*++ptr = '%';
|
*++ptr = '%';
|
||||||
@ -751,7 +750,7 @@ void link_rules(char* rule, FW_INSTANCE* instance)
|
|||||||
user->name = strdup(userptr);
|
user->name = strdup(userptr);
|
||||||
tl = rlistdup(rulelist);
|
tl = rlistdup(rulelist);
|
||||||
tail = tl;
|
tail = tl;
|
||||||
while(tail->next){
|
while(tail && tail->next){
|
||||||
tail = tail->next;
|
tail = tail->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -797,6 +796,7 @@ void parse_rule(char* rule, FW_INSTANCE* instance)
|
|||||||
rlist = (RULELIST*)calloc(1,sizeof(RULELIST));
|
rlist = (RULELIST*)calloc(1,sizeof(RULELIST));
|
||||||
ruledef->name = strdup(tok);
|
ruledef->name = strdup(tok);
|
||||||
ruledef->type = RT_UNDEFINED;
|
ruledef->type = RT_UNDEFINED;
|
||||||
|
ruledef->on_queries = ALL;
|
||||||
rlist->rule = ruledef;
|
rlist->rule = ruledef;
|
||||||
rlist->next = instance->rules;
|
rlist->next = instance->rules;
|
||||||
instance->rules = rlist;
|
instance->rules = rlist;
|
||||||
@ -830,7 +830,7 @@ void parse_rule(char* rule, FW_INSTANCE* instance)
|
|||||||
STRLINK *tail = NULL,*current;
|
STRLINK *tail = NULL,*current;
|
||||||
ruledef->type = RT_COLUMN;
|
ruledef->type = RT_COLUMN;
|
||||||
tok = strtok(NULL, " ,");
|
tok = strtok(NULL, " ,");
|
||||||
while(tok && strcmp(tok,"times") != 0){
|
while(tok && strcmp(tok,"at_times") != 0){
|
||||||
current = malloc(sizeof(STRLINK));
|
current = malloc(sizeof(STRLINK));
|
||||||
current->value = strdup(tok);
|
current->value = strdup(tok);
|
||||||
current->next = tail;
|
current->next = tail;
|
||||||
@ -842,15 +842,20 @@ void parse_rule(char* rule, FW_INSTANCE* instance)
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
}
|
}
|
||||||
else if(strcmp(tok,"times") == 0)
|
else if(strcmp(tok,"at_times") == 0)
|
||||||
{
|
{
|
||||||
|
|
||||||
tok = strtok(NULL, " ,");
|
tok = strtok(NULL, " ,");
|
||||||
|
TIMERANGE *tr = NULL;
|
||||||
|
while(tok){
|
||||||
|
TIMERANGE *tmp = parse_time(tok,instance);
|
||||||
|
|
||||||
TIMERANGE *tr = parse_time(tok,instance);
|
if(IS_RVRS_TIME(tmp)){
|
||||||
|
tmp = split_reverse_time(tmp);
|
||||||
if(IS_RVRS_TIME(tr)){
|
}
|
||||||
tr = split_reverse_time(tr);
|
tmp->next = tr;
|
||||||
|
tr = tmp;
|
||||||
|
tok = strtok(NULL, " ,");
|
||||||
}
|
}
|
||||||
ruledef->active = tr;
|
ruledef->active = tr;
|
||||||
}
|
}
|
||||||
@ -873,8 +878,9 @@ void parse_rule(char* rule, FW_INSTANCE* instance)
|
|||||||
}
|
}
|
||||||
|
|
||||||
str = malloc(((tok - start) + 1)*sizeof(char));
|
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));
|
regex_t *re = malloc(sizeof(regex_t));
|
||||||
|
|
||||||
@ -911,16 +917,19 @@ static FILTER *
|
|||||||
createInstance(char **options, FILTER_PARAMETER **params)
|
createInstance(char **options, FILTER_PARAMETER **params)
|
||||||
{
|
{
|
||||||
FW_INSTANCE *my_instance;
|
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){
|
if ((my_instance = calloc(1, sizeof(FW_INSTANCE))) == NULL){
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
int i;
|
|
||||||
HASHTABLE* ht;
|
|
||||||
STRLINK *ptr,*tmp;
|
|
||||||
|
|
||||||
if((ht = hashtable_alloc(7, hashkeyfun, hashcmpfun)) == NULL){
|
if((ht = hashtable_alloc(7, hashkeyfun, hashcmpfun)) == NULL){
|
||||||
skygw_log_write(LOGFILE_ERROR, "Unable to allocate hashtable.");
|
skygw_log_write(LOGFILE_ERROR, "Unable to allocate hashtable.");
|
||||||
|
free(my_instance);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -930,14 +939,37 @@ createInstance(char **options, FILTER_PARAMETER **params)
|
|||||||
my_instance->def_op = true;
|
my_instance->def_op = true;
|
||||||
|
|
||||||
for(i = 0;params[i];i++){
|
for(i = 0;params[i];i++){
|
||||||
if(strstr(params[i]->name,"rule")){
|
if(strcmp(params[i]->name, "rulelist") == 0){
|
||||||
parse_rule(params[i]->value,my_instance);
|
filename = strdup(params[i]->value);
|
||||||
}else if(strcmp(params[i]->name,"mode") == 0 &&
|
|
||||||
strcmp(params[i]->value,"whitelist") == 0){
|
|
||||||
my_instance->def_op = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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*/
|
/**Apply the rules to users*/
|
||||||
ptr = my_instance->userstrings;
|
ptr = my_instance->userstrings;
|
||||||
while(ptr){
|
while(ptr){
|
||||||
@ -1148,6 +1180,7 @@ 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,
|
is_sql = false,
|
||||||
is_real = false,rule_match;
|
is_real = false,rule_match;
|
||||||
@ -1164,6 +1197,7 @@ routeQuery(FILTER *instance, void *session, GWBUF *queue)
|
|||||||
sprintf(uname_addr,"%s@%s",dcb->user,ipaddr);
|
sprintf(uname_addr,"%s@%s",dcb->user,ipaddr);
|
||||||
|
|
||||||
time(&time_now);
|
time(&time_now);
|
||||||
|
tm_now = localtime(&time_now);
|
||||||
|
|
||||||
if((user = (USER*)hashtable_fetch(my_instance->htable, uname_addr)) == NULL){
|
if((user = (USER*)hashtable_fetch(my_instance->htable, uname_addr)) == NULL){
|
||||||
while(user == NULL && next_ip_class(ipaddr)){
|
while(user == NULL && next_ip_class(ipaddr)){
|
||||||
@ -1216,6 +1250,7 @@ routeQuery(FILTER *instance, void *session, GWBUF *queue)
|
|||||||
switch(rulelist->rule->type){
|
switch(rulelist->rule->type){
|
||||||
|
|
||||||
case RT_UNDEFINED:
|
case RT_UNDEFINED:
|
||||||
|
skygw_log_write_flush(LOGFILE_ERROR, "Error: Undefined rule type found.");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case RT_REGEX:
|
case RT_REGEX:
|
||||||
@ -1226,6 +1261,7 @@ routeQuery(FILTER *instance, void *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);
|
||||||
goto queryresolved;
|
goto queryresolved;
|
||||||
}else{
|
}else{
|
||||||
break;
|
break;
|
||||||
@ -1238,6 +1274,7 @@ routeQuery(FILTER *instance, void *session, GWBUF *queue)
|
|||||||
if(!rulelist->rule->allow){
|
if(!rulelist->rule->allow){
|
||||||
accept = false;
|
accept = false;
|
||||||
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));
|
||||||
goto queryresolved;
|
goto queryresolved;
|
||||||
}else{
|
}else{
|
||||||
break;
|
break;
|
||||||
@ -1260,6 +1297,7 @@ routeQuery(FILTER *instance, void *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);
|
||||||
msg = strdup(emsg);
|
msg = strdup(emsg);
|
||||||
goto queryresolved;
|
goto queryresolved;
|
||||||
}else{
|
}else{
|
||||||
@ -1287,6 +1325,7 @@ routeQuery(FILTER *instance, void *session, GWBUF *queue)
|
|||||||
|
|
||||||
if(!rulelist->rule->allow){
|
if(!rulelist->rule->allow){
|
||||||
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);
|
||||||
goto queryresolved;
|
goto queryresolved;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1295,6 +1334,9 @@ routeQuery(FILTER *instance, void *session, GWBUF *queue)
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
rulelist = rulelist->next;
|
rulelist = rulelist->next;
|
||||||
|
|||||||
Reference in New Issue
Block a user