Updated test harness.
This commit is contained in:
@ -20,25 +20,37 @@
|
|||||||
* @file fwfilter.c
|
* @file fwfilter.c
|
||||||
* Firewall Filter
|
* Firewall Filter
|
||||||
*
|
*
|
||||||
* A filter that acts as a firewall, denying queries that do not meet a set requirements.
|
* A filter that acts as a firewall, denying queries that do not meet a set of rules.
|
||||||
*
|
*
|
||||||
* This filter uses "rules" to define the blcking parameters. Write the rules to a separate file and
|
* Filter configuration parameters:
|
||||||
* set the path to the file:
|
|
||||||
*
|
*
|
||||||
* rules=<path to file>
|
* rules=<path to file> Location of the rule file
|
||||||
*
|
*
|
||||||
*
|
* Rules are defined in a separate rule file that lists all the rules and the users to whom the rules are applied.
|
||||||
* 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:
|
* Rules follow a simple syntax that denies the queries that meet the requirements of the rules.
|
||||||
|
* For example, to define a rule denying users from accessing the column 'salary' between
|
||||||
|
* the times 15:00 and 17:00, the following rule is to be configured into the configuration file:
|
||||||
*
|
*
|
||||||
* rule block_salary deny columns salary at_times 15:00:00-17:00:00
|
* 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:
|
* The users are matched by username and network address. Wildcard values can be provided by using the '%' character.
|
||||||
|
* For example, to apply this rule to users John, connecting from any address
|
||||||
|
* that starts with the octets 198.168.%, and Jane, connecting from the address 192.168.0.1:
|
||||||
*
|
*
|
||||||
* users John@% Jane@192.168.0.1 match any rules block_salary
|
* users John@192.168.% Jane@192.168.0.1 match any rules block_salary
|
||||||
*
|
*
|
||||||
* Rule syntax TODO: update the documentation
|
|
||||||
*
|
*
|
||||||
* rule NAME deny|allow [wildcard | columns VALUE ... | regex REGEX | limit_queries COUNT TIMEPERIOD HOLDOFF|no_where_clause [select|insert|delete|update]] [at_times VALUE...]
|
* The 'match' keyword controls the way rules are matched. If it is set to 'any' the first active rule that is triggered will cause the query to be denied.
|
||||||
|
* If it is set to 'all' all the active rules need to match before the query is denied.
|
||||||
|
*
|
||||||
|
* Rule syntax
|
||||||
|
*
|
||||||
|
* rule NAME deny [wildcard | columns VALUE ... | regex REGEX | limit_queries COUNT TIMEPERIOD HOLDOFF | no_where_clause] [at_times VALUE...] [on_queries [select|update|insert|delete]]
|
||||||
|
*
|
||||||
|
* User syntax
|
||||||
|
*
|
||||||
|
* users NAME ... match [any|all] rules RULE ...
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
#include <my_config.h>
|
#include <my_config.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
@ -91,20 +103,7 @@ static FILTER_OBJECT MyObject = {
|
|||||||
diagnostic,
|
diagnostic,
|
||||||
};
|
};
|
||||||
|
|
||||||
#define QUERY_TYPES 5
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Query types
|
|
||||||
*/
|
|
||||||
/*typedef enum{
|
|
||||||
NONE = 0,
|
|
||||||
ALL = (1),
|
|
||||||
SELECT = (1<<1),
|
|
||||||
INSERT = (1<<2),
|
|
||||||
UPDATE = (1<<3),
|
|
||||||
DELETE = (1<<4)
|
|
||||||
}querytype_t;
|
|
||||||
*/
|
|
||||||
/**
|
/**
|
||||||
* Rule types
|
* Rule types
|
||||||
*/
|
*/
|
||||||
@ -259,12 +258,6 @@ void* rlistdup(void* fval)
|
|||||||
return (void*)rule;
|
return (void*)rule;
|
||||||
|
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
static void* hruledup(void* fval)
|
|
||||||
{
|
|
||||||
return fval;
|
|
||||||
}*/
|
|
||||||
|
|
||||||
|
|
||||||
static void* hrulefree(void* fval)
|
static void* hrulefree(void* fval)
|
||||||
{
|
{
|
||||||
@ -291,6 +284,7 @@ static void* hrulefree(void* fval)
|
|||||||
* Replace all non-essential characters with whitespace from a null-terminated string.
|
* Replace all non-essential characters with whitespace from a null-terminated string.
|
||||||
* This function modifies the passed string.
|
* This function modifies the passed string.
|
||||||
* @param str String to purify
|
* @param str String to purify
|
||||||
|
* @return Pointer to the modified string
|
||||||
*/
|
*/
|
||||||
char* strip_tags(char* str)
|
char* strip_tags(char* str)
|
||||||
{
|
{
|
||||||
@ -354,7 +348,12 @@ char* next_ip_class(char* str)
|
|||||||
|
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* Parses the strign for the types of queries this rule should be applied to.
|
||||||
|
* @param str String to parse
|
||||||
|
* @param rule Poiter to a rule
|
||||||
|
* @return True if the string was parses successfully, false if an error occurred
|
||||||
|
*/
|
||||||
bool parse_querytypes(char* str,RULE* rule)
|
bool parse_querytypes(char* str,RULE* rule)
|
||||||
{
|
{
|
||||||
char buffer[512];
|
char buffer[512];
|
||||||
@ -562,6 +561,7 @@ RULE* find_rule(char* tok, FW_INSTANCE* instance)
|
|||||||
skygw_log_write(LOGFILE_ERROR, "fwfilter: Rule not found: %s",tok);
|
skygw_log_write(LOGFILE_ERROR, "fwfilter: Rule not found: %s",tok);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds the given rule string to the list of strings to be parsed for users.
|
* Adds the given rule string to the list of strings to be parsed for users.
|
||||||
* @param rule The rule string, assumed to be null-terminated
|
* @param rule The rule string, assumed to be null-terminated
|
||||||
|
|||||||
@ -10,4 +10,4 @@ add_executable(harness_ui harness_ui.c harness_common.c)
|
|||||||
add_executable(harness harness_util.c harness_common.c ${CORE})
|
add_executable(harness harness_util.c harness_common.c ${CORE})
|
||||||
target_link_libraries(harness_ui fullcore log_manager utils)
|
target_link_libraries(harness_ui fullcore log_manager utils)
|
||||||
target_link_libraries(harness fullcore)
|
target_link_libraries(harness fullcore)
|
||||||
add_test(TestHintfilter /bin/sh -c "MAXSCALE_HOME=\"${CMAKE_BINARY_DIR}\" ${CMAKE_CURRENT_BINARY_DIR}/harness -i ${CMAKE_CURRENT_SOURCE_DIR}/hint_testing.input -o ${CMAKE_CURRENT_BINARY_DIR}/hint_testing.output -c ${CMAKE_CURRENT_SOURCE_DIR}/hint_testing.cnf -t 1 -s 1 && diff ${CMAKE_CURRENT_SOURCE_DIR}/hint_testing.expected ${CMAKE_CURRENT_BINARY_DIR}/hint_testing.output;exit $?")
|
add_test(TestHintfilter /bin/sh -c "MAXSCALE_HOME=\"${CMAKE_BINARY_DIR}\" ${CMAKE_CURRENT_BINARY_DIR}/harness -i ${CMAKE_CURRENT_SOURCE_DIR}/hint_testing.input -o ${CMAKE_CURRENT_BINARY_DIR}/hint_testing.output -c ${CMAKE_CURRENT_SOURCE_DIR}/hint_testing.cnf -t 1 -s 1 -e ${CMAKE_CURRENT_SOURCE_DIR}/hint_testing.expected")
|
||||||
@ -69,6 +69,7 @@
|
|||||||
#include <ini.h>
|
#include <ini.h>
|
||||||
#include <hint.h>
|
#include <hint.h>
|
||||||
#include <modutil.h>
|
#include <modutil.h>
|
||||||
|
#include <errno.h>
|
||||||
/**
|
/**
|
||||||
* A single name-value pair and a link to the next item in the
|
* A single name-value pair and a link to the next item in the
|
||||||
* configuration.
|
* configuration.
|
||||||
@ -117,6 +118,7 @@ typedef struct
|
|||||||
int running;
|
int running;
|
||||||
int verbose; /**Whether to print to stdout*/
|
int verbose; /**Whether to print to stdout*/
|
||||||
int infile; /**A file where the queries are loaded from*/
|
int infile; /**A file where the queries are loaded from*/
|
||||||
|
int expected;
|
||||||
int error;
|
int error;
|
||||||
char* mod_dir; /**Module directory absolute path*/
|
char* mod_dir; /**Module directory absolute path*/
|
||||||
char* infile_name;
|
char* infile_name;
|
||||||
@ -172,7 +174,7 @@ typedef packet_t PACKET;
|
|||||||
/**
|
/**
|
||||||
* Initialize the static instance.
|
* Initialize the static instance.
|
||||||
*/
|
*/
|
||||||
int harness_init(int argc,char** argv);
|
int harness_init(int argc,char** argv,HARNESS_INSTANCE** inst);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Frees all the query buffers
|
* Frees all the query buffers
|
||||||
@ -359,4 +361,14 @@ GWBUF* gen_packet(PACKET pkt);
|
|||||||
*/
|
*/
|
||||||
int process_opts(int argc, char** argv);
|
int process_opts(int argc, char** argv);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compares the contents of two files.
|
||||||
|
* This function resets the offsets of the file descriptors and leaves them in an
|
||||||
|
* undefined state.
|
||||||
|
* @param a The first file
|
||||||
|
* @param b The second file
|
||||||
|
* @return 0 if the files do not differ and 1 if they do or an error occurred.
|
||||||
|
*/
|
||||||
|
int compare_files(int a, int b);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
#include <harness.h>
|
#include <harness.h>
|
||||||
|
|
||||||
int harness_init(int argc, char** argv){
|
int harness_init(int argc, char** argv, HARNESS_INSTANCE** inst){
|
||||||
int i = 0;
|
int i = 0;
|
||||||
if(!(argc == 2 && strcmp(argv[1],"-h") == 0)){
|
if(!(argc == 2 && strcmp(argv[1],"-h") == 0)){
|
||||||
skygw_logmanager_init(0,NULL);
|
skygw_logmanager_init(0,NULL);
|
||||||
@ -14,9 +14,11 @@ int harness_init(int argc, char** argv){
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*inst = &instance;
|
||||||
instance.running = 1;
|
instance.running = 1;
|
||||||
instance.infile = -1;
|
instance.infile = -1;
|
||||||
instance.outfile = -1;
|
instance.outfile = -1;
|
||||||
|
instance.expected = -1;
|
||||||
instance.buff_ind = -1;
|
instance.buff_ind = -1;
|
||||||
instance.last_ind = -1;
|
instance.last_ind = -1;
|
||||||
instance.sess_ind = -1;
|
instance.sess_ind = -1;
|
||||||
@ -84,15 +86,17 @@ void free_buffers()
|
|||||||
}
|
}
|
||||||
int open_file(char* str, unsigned int write)
|
int open_file(char* str, unsigned int write)
|
||||||
{
|
{
|
||||||
int mode;
|
int mode,fd;
|
||||||
|
|
||||||
if(write){
|
if(write){
|
||||||
mode = O_RDWR|O_CREAT;
|
mode = O_RDWR|O_CREAT;
|
||||||
}else{
|
}else{
|
||||||
mode = O_RDONLY;
|
mode = O_RDONLY;
|
||||||
}
|
}
|
||||||
|
if((fd = open(str,mode,S_IRWXU|S_IRGRP|S_IXGRP|S_IXOTH)) < 0){
|
||||||
return open(str,mode,S_IRWXU|S_IRGRP|S_IXGRP|S_IXOTH);
|
printf("Error %d: %s\n",errno,strerror(errno));
|
||||||
|
}
|
||||||
|
return fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -863,9 +867,14 @@ void work_buffer(void* thr_num)
|
|||||||
index < instance.session_count &&
|
index < instance.session_count &&
|
||||||
instance.buff_ind < instance.buffer_count)
|
instance.buff_ind < instance.buffer_count)
|
||||||
{
|
{
|
||||||
instance.head->instance->routeQuery(instance.head->filter,
|
if(instance.head->instance->routeQuery(instance.head->filter,
|
||||||
instance.head->session[index],
|
instance.head->session[index],
|
||||||
instance.buffer[instance.buff_ind]);
|
instance.buffer[instance.buff_ind]) == 0){
|
||||||
|
if(instance.outfile > 0){
|
||||||
|
const char* msg = "Query returned 0.\n";
|
||||||
|
write(instance.outfile,msg,strlen(msg));
|
||||||
|
}
|
||||||
|
}
|
||||||
if(instance.tail->instance->clientReply){
|
if(instance.tail->instance->clientReply){
|
||||||
instance.tail->instance->clientReply(instance.tail->filter,
|
instance.tail->instance->clientReply(instance.tail->filter,
|
||||||
instance.tail->session[index],
|
instance.tail->session[index],
|
||||||
@ -929,10 +938,11 @@ GWBUF* gen_packet(PACKET pkt)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int process_opts(int argc, char** argv)
|
int process_opts(int argc, char** argv)
|
||||||
{
|
{
|
||||||
int fd, buffsize = 1024;
|
int fd, buffsize = 1024;
|
||||||
int rd,rdsz, rval;
|
int rd,rdsz, rval = 0;
|
||||||
size_t fsize;
|
size_t fsize;
|
||||||
char *buff = calloc(buffsize,sizeof(char)), *tok = NULL;
|
char *buff = calloc(buffsize,sizeof(char)), *tok = NULL;
|
||||||
|
|
||||||
@ -985,10 +995,18 @@ int process_opts(int argc, char** argv)
|
|||||||
close(fd);
|
close(fd);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
char* conf_name = NULL;
|
char* conf_name = NULL;
|
||||||
while((rd = getopt(argc,argv,"m:c:i:o:s:t:d:qh")) > 0){
|
rval = 0;
|
||||||
|
|
||||||
|
while((rd = getopt(argc,argv,"e:m:c:i:o:s:t:d:qh")) > 0){
|
||||||
switch(rd){
|
switch(rd){
|
||||||
|
|
||||||
|
case 'e':
|
||||||
|
instance.expected = open_file(optarg,0);
|
||||||
|
printf("Expected output is read from: %s\n",optarg);
|
||||||
|
break;
|
||||||
|
|
||||||
case 'o':
|
case 'o':
|
||||||
instance.outfile = open_file(optarg,1);
|
instance.outfile = open_file(optarg,1);
|
||||||
printf("Output is written to: %s\n",optarg);
|
printf("Output is written to: %s\n",optarg);
|
||||||
@ -1053,6 +1071,7 @@ int process_opts(int argc, char** argv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
printf("\n");
|
printf("\n");
|
||||||
|
|
||||||
if(conf_name && load_config(conf_name)){
|
if(conf_name && load_config(conf_name)){
|
||||||
load_query();
|
load_query();
|
||||||
}else{
|
}else{
|
||||||
@ -1061,5 +1080,30 @@ int process_opts(int argc, char** argv)
|
|||||||
free(conf_name);
|
free(conf_name);
|
||||||
close(fd);
|
close(fd);
|
||||||
|
|
||||||
|
return rval;
|
||||||
|
}
|
||||||
|
|
||||||
|
int compare_files(int a,int b)
|
||||||
|
{
|
||||||
|
char in[4098];
|
||||||
|
char exp[4098];
|
||||||
|
int line = 1;
|
||||||
|
|
||||||
|
if(a < 1 || b < 1){
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(lseek(a,0,SEEK_SET) < 0 ||
|
||||||
|
lseek(b,0,SEEK_SET) < 0){
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
while(fdgets(a,in,4098) && fdgets(b,exp,4098)){
|
||||||
|
if(strcmp(in,exp)){
|
||||||
|
printf("The files differ at line %d:\n%s\n-------------------------------------\n%s\n",line,in,exp);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
line++;
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,9 +6,9 @@ int main(int argc, char** argv){
|
|||||||
char* tk;
|
char* tk;
|
||||||
FILTERCHAIN* tmp_chn;
|
FILTERCHAIN* tmp_chn;
|
||||||
FILTERCHAIN* del_chn;
|
FILTERCHAIN* del_chn;
|
||||||
|
HARNESS_INSTANCE* hinstance;
|
||||||
|
|
||||||
if(harness_init(argc,argv)){
|
if(harness_init(argc,argv,&hinstance)){
|
||||||
printf("Error: Initialization failed.\n");
|
printf("Error: Initialization failed.\n");
|
||||||
skygw_log_write(LOGFILE_ERROR,"Error: Initialization failed.\n");
|
skygw_log_write(LOGFILE_ERROR,"Error: Initialization failed.\n");
|
||||||
skygw_logmanager_done();
|
skygw_logmanager_done();
|
||||||
|
|||||||
@ -1,7 +1,8 @@
|
|||||||
#include <harness.h>
|
#include <harness.h>
|
||||||
int main(int argc,char** argv)
|
int main(int argc,char** argv)
|
||||||
{
|
{
|
||||||
if(harness_init(argc,argv) || instance.error){
|
HARNESS_INSTANCE* inst;
|
||||||
|
if(harness_init(argc,argv,&inst) || inst->error){
|
||||||
printf("Error: Initialization failed.\n");
|
printf("Error: Initialization failed.\n");
|
||||||
skygw_log_write(LOGFILE_ERROR,"Error: Initialization failed.\n");
|
skygw_log_write(LOGFILE_ERROR,"Error: Initialization failed.\n");
|
||||||
skygw_logmanager_done();
|
skygw_logmanager_done();
|
||||||
@ -10,5 +11,8 @@ int main(int argc,char** argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
route_buffers();
|
route_buffers();
|
||||||
|
if(inst->expected){
|
||||||
|
return compare_files(inst->outfile,inst->expected);
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user