Merge branch 'firewall' into develop

This commit is contained in:
Markus Makela 2015-01-13 09:45:33 +02:00
commit e0a460b869
23 changed files with 1945 additions and 37 deletions

View File

@ -3079,7 +3079,7 @@ static int find_last_seqno(
for (i=0, p=parts; p->sp_string != NULL; i++, p=p->sp_next)
{
if (snstr != NULL && i == seqnoidx && strnlen(snstr,NAME_MAX) < NAME_MAX)
if (snstr != NULL && i == seqnoidx)
{
strncat(filename, snstr, NAME_MAX - 1); /*< add sequence number */
}

View File

@ -1210,7 +1210,124 @@ bool is_drop_table_query(GWBUF* querybuf)
lex->sql_command == SQLCOM_DROP_TABLE);
}
inline void add_str(char** buf, int* buflen, int* bufsize, char* str)
{
int isize = strlen(str) + 1;
if(*buf == NULL || isize + *buflen >= *bufsize)
{
char *tmp = (char*)calloc((*bufsize) * 2 + isize, sizeof(char));
if(tmp){
memcpy(tmp,*buf,*bufsize);
if(*buf){
free(*buf);
}
*buf = tmp;
*bufsize = (*bufsize) * 2 + isize;
}
}
if(*buflen > 0){
strcat(*buf," ");
}
strcat(*buf,str);
*buflen += isize;
}
/**
* Returns all the fields that the query affects.
* @param buf Buffer to parse
* @return Pointer to newly allocated string or NULL if nothing was found
*/
char* skygw_get_affected_fields(GWBUF* buf)
{
LEX* lex;
int buffsz = 0,bufflen = 0;
char* where = NULL;
Item* item;
Item::Type itype;
if(!query_is_parsed(buf)){
parse_query(buf);
}
if((lex = get_lex(buf)) == NULL){
return NULL;
}
lex->current_select = lex->all_selects_list;
while(lex->current_select)
{
List_iterator<Item> ilist(lex->current_select->item_list);
item = (Item*)ilist.next();
for (item; item != NULL; item=(Item*)ilist.next())
{
itype = item->type();
if(item->name && itype == Item::FIELD_ITEM){
add_str(&where,&buffsz,&bufflen,item->name);
}
}
if(lex->current_select->where){
for (item=lex->current_select->where; item != NULL; item=item->next)
{
itype = item->type();
if(item->name && itype == Item::FIELD_ITEM){
add_str(&where,&buffsz,&bufflen,item->name);
}
}
}
if(lex->current_select->having){
for (item=lex->current_select->having; item != NULL; item=item->next)
{
itype = item->type();
if(item->name && itype == Item::FIELD_ITEM){
add_str(&where,&buffsz,&bufflen,item->name);
}
}
}
lex->current_select = lex->current_select->next_select_in_list();
}
return where;
}
bool skygw_query_has_clause(GWBUF* buf)
{
LEX* lex;
SELECT_LEX* current;
bool clause = false;
if(!query_is_parsed(buf)){
parse_query(buf);
}
if((lex = get_lex(buf)) == NULL){
return false;
}
current = lex->all_selects_list;
while(current)
{
if(current->where || current->having){
clause = true;
}
current = current->next_select_in_list();
}
return clause;
}
/*
* Replace user-provided literals with question marks. Return a copy of the
* querystr with replacements.
*
@ -1425,7 +1542,7 @@ static void parsing_info_set_plain_str(
* @return string representing the query type value
*/
char* skygw_get_qtype_str(
skygw_query_type_t qtype)
skygw_query_type_t qtype)
{
int t1 = (int)qtype;
int t2 = 1;
@ -1437,26 +1554,72 @@ char* skygw_get_qtype_str(
* t1 is completely cleared.
*/
while (t1 != 0)
{
if (t1&t2)
{
t = (skygw_query_type_t)t2;
{
if (t1&t2)
{
t = (skygw_query_type_t)t2;
if (qtype_str == NULL)
{
qtype_str = strdup(STRQTYPE(t));
}
else
{
size_t len = strlen(STRQTYPE(t));
/** reallocate space for delimiter, new string and termination */
qtype_str = (char *)realloc(qtype_str, strlen(qtype_str)+1+len+1);
snprintf(qtype_str+strlen(qtype_str), 1+len+1, "|%s", STRQTYPE(t));
}
/** Remove found value from t1 */
t1 &= ~t2;
if (qtype_str == NULL)
{
qtype_str = strdup(STRQTYPE(t));
}
else
{
size_t len = strlen(STRQTYPE(t));
/** reallocate space for delimiter, new string and termination */
qtype_str = (char *)realloc(qtype_str, strlen(qtype_str)+1+len+1);
snprintf(qtype_str+strlen(qtype_str), 1+len+1, "|%s", STRQTYPE(t));
}
/** Remove found value from t1 */
t1 &= ~t2;
}
t2 <<= 1;
}
t2 <<= 1;
}
return qtype_str;
}
skygw_query_op_t query_classifier_get_operation(GWBUF* querybuf)
{
LEX* lex = get_lex(querybuf);
skygw_query_op_t operation;
if(lex){
switch(lex->sql_command){
case SQLCOM_SELECT:
operation = QUERY_OP_SELECT;
break;
case SQLCOM_CREATE_TABLE:
operation = QUERY_OP_CREATE_TABLE;
break;
case SQLCOM_CREATE_INDEX:
operation = QUERY_OP_CREATE_INDEX;
break;
case SQLCOM_ALTER_TABLE:
operation = QUERY_OP_ALTER_TABLE;
break;
case SQLCOM_UPDATE:
operation = QUERY_OP_UPDATE;
break;
case SQLCOM_INSERT:
operation = QUERY_OP_INSERT;
break;
case SQLCOM_INSERT_SELECT:
operation = QUERY_OP_INSERT_SELECT;
break;
case SQLCOM_DELETE:
operation = QUERY_OP_DELETE;
break;
case SQLCOM_TRUNCATE:
operation = QUERY_OP_TRUNCATE;
break;
case SQLCOM_DROP_TABLE:
operation = QUERY_OP_DROP_TABLE;
break;
case SQLCOM_DROP_INDEX:
operation = QUERY_OP_DROP_INDEX;
break;
default:
operation = QUERY_OP_UNDEFINED;
}
}
return operation;
}

View File

@ -60,6 +60,20 @@ typedef enum {
QUERY_TYPE_SHOW_TABLES = 0x400000 /*< Show list of tables */
} skygw_query_type_t;
typedef enum {
QUERY_OP_UNDEFINED = 0,
QUERY_OP_SELECT = 1,
QUERY_OP_UPDATE = (1 << 1),
QUERY_OP_INSERT = (1 << 2),
QUERY_OP_DELETE = (1 << 3),
QUERY_OP_INSERT_SELECT = (1 << 4),
QUERY_OP_TRUNCATE = (1 << 5),
QUERY_OP_ALTER_TABLE = (1 << 6),
QUERY_OP_CREATE_TABLE = (1 << 7),
QUERY_OP_CREATE_INDEX = (1 << 8),
QUERY_OP_DROP_TABLE = (1 << 9),
QUERY_OP_DROP_INDEX = (1 << 10)
}skygw_query_op_t;
typedef struct parsing_info_st {
#if defined(SS_DEBUG)
@ -81,7 +95,7 @@ typedef struct parsing_info_st {
* classify the query.
*/
skygw_query_type_t query_classifier_get_type(GWBUF* querybuf);
skygw_query_op_t query_classifier_get_operation(GWBUF* querybuf);
/** Free THD context and close MYSQL */
#if defined(NOT_USED)
char* skygw_query_classifier_get_stmtname(GWBUF* buf);
@ -95,8 +109,9 @@ bool parse_query (GWBUF* querybuf);
parsing_info_t* parsing_info_init(void (*donefun)(void *));
void parsing_info_done(void* ptr);
bool query_is_parsed(GWBUF* buf);
bool skygw_query_has_clause(GWBUF* buf);
char* skygw_get_qtype_str(skygw_query_type_t qtype);
char* skygw_get_affected_fields(GWBUF* buf);
EXTERN_C_BLOCK_END

View File

@ -24,8 +24,13 @@ add_library(topfilter SHARED topfilter.c)
target_link_libraries(topfilter log_manager utils)
install(TARGETS topfilter DESTINATION modules)
add_library(fwfilter SHARED fwfilter.c)
target_link_libraries(fwfilter log_manager utils query_classifier)
install(TARGETS fwfilter DESTINATION modules)
add_subdirectory(hint)
if(BUILD_TESTS)
add_subdirectory(test)
endif()
endif()

File diff suppressed because it is too large Load Diff

View File

@ -11,9 +11,17 @@ add_executable(harness harness_util.c harness_common.c ${CORE})
target_link_libraries(harness_ui fullcore log_manager utils)
target_link_libraries(harness fullcore)
execute_process(COMMAND ${CMAKE_COMMAND} -E copy ${ERRMSG} ${CMAKE_CURRENT_BINARY_DIR})
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")
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/testdriver.sh ${CMAKE_CURRENT_BINARY_DIR}/testdriver.sh @ONLY)
add_test(TestRegexfilter /bin/sh -c "MAXSCALE_HOME=\"${CMAKE_BINARY_DIR}\" ${CMAKE_CURRENT_BINARY_DIR}/harness -i ${CMAKE_CURRENT_SOURCE_DIR}/regextest.input -o ${CMAKE_CURRENT_BINARY_DIR}/regextest.output -c ${CMAKE_CURRENT_SOURCE_DIR}/regextest.cnf -t 1 -s 1 -e ${CMAKE_CURRENT_SOURCE_DIR}/regextest.expected")
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/hintfilter/hint_testing.cnf ${CMAKE_CURRENT_BINARY_DIR}/hintfilter/hint_testing.cnf)
add_test(TestHintfilter testdriver.sh hintfilter/hint_testing.cnf hintfilter/hint_testing.input hintfilter/hint_testing.output hintfilter/hint_testing.expected)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/regexfilter/regextest.cnf ${CMAKE_CURRENT_BINARY_DIR}/regexfilter/regextest.cnf)
add_test(TestRegexfilter testdriver.sh regexfilter/regextest.cnf regexfilter/regextest.input regexfilter/regextest.output regexfilter/regextest.expected)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/fwfilter/fwtest.cnf.in ${CMAKE_CURRENT_BINARY_DIR}/fwfilter/fwtest.cnf)
add_test(TestFwfilter1 testdriver.sh fwfilter/fwtest.cnf fwfilter/fwtest.input fwfilter/fwtest.output fwfilter/fwtest.expected)
add_test(TestFwfilter2 testdriver.sh fwfilter/fwtest.cnf fwfilter/fwtest2.input fwfilter/fwtest2.output fwfilter/fwtest2.expected)
add_test(TestTeeRecursion ${CMAKE_CURRENT_SOURCE_DIR}/tee_recursion.sh
${CMAKE_BINARY_DIR}
@ -22,3 +30,7 @@ add_test(TestTeeRecursion ${CMAKE_CURRENT_SOURCE_DIR}/tee_recursion.sh
${TEST_PASSWORD}
${TEST_HOST}
${TEST_PORT})
set_tests_properties(TestHintfilter TestRegexfilter TestFwfilter1 TestFwfilter2 TestTeeRecursion
PROPERTIES
ENVIRONMENT MAXSCALE_HOME=${CMAKE_BINARY_DIR}/)

View File

@ -0,0 +1,4 @@
[Firewall]
type=filter
module=fwfilter
rules=@CMAKE_CURRENT_SOURCE_DIR@/rules

View File

@ -0,0 +1,8 @@
select id from t1;
select id from t1;
select id from t1;
select id from t1;
select id from t1;
select id from t1;
select id from t1;
select id from t1;

View File

@ -0,0 +1,10 @@
delete from t1;
select id from t1;
select id from t1;
select id from t1;
delete from t1;
select id from t1;
select id from t1;
select id from t1;
select id from t1;
select id from t1;

View File

@ -0,0 +1,8 @@
select id from t1;
select id from t1;
select id from t1;
select id from t1;
select id from t1;
select id from t1;
select id from t1;
select id from t1;

View File

@ -0,0 +1,8 @@
select id from t1;
select id from t1;
select id from t1;
select id from t1;
select id from t1;
select id from t1;
select id from t1;
select id from t1;

View File

@ -0,0 +1,10 @@
select id from t1;
select id from t1 union select name from t2;
select id from t1;
select id from t1;
select id from t1;
select id from t1;
select id from t1;
select id from t1 union select name from t2;
select id from t1;
select id from t1;

View File

@ -10,7 +10,7 @@ int dcbfun(struct dcb* dcb, GWBUF * buffer)
int harness_init(int argc, char** argv, HARNESS_INSTANCE** inst){
int i = 0;
int i = 0,rval = 0;
MYSQL_session* mysqlsess;
DCB* dcb;
char cwd[1024];
@ -60,7 +60,7 @@ int harness_init(int argc, char** argv, HARNESS_INSTANCE** inst){
skygw_logmanager_init( 3, optstr);
free(optstr);
process_opts(argc,argv);
rval = process_opts(argc,argv);
if(!(instance.thrpool = malloc(instance.thrcount * sizeof(pthread_t)))){
printf("Error: Out of memory\n");
@ -72,10 +72,10 @@ int harness_init(int argc, char** argv, HARNESS_INSTANCE** inst){
pthread_mutex_lock(&instance.work_mtx);
size_t thr_num = 1;
for(i = 0;i<instance.thrcount;i++){
pthread_create(&instance.thrpool[i],NULL,(void*)work_buffer,(void*)thr_num++);
rval |= pthread_create(&instance.thrpool[i],NULL,(void*)work_buffer,(void*)thr_num++);
}
return 0;
return rval;
}
void free_filters()
@ -543,10 +543,14 @@ int load_config( char* fname)
{
CONFIG* iter;
CONFIG_ITEM* item;
int config_ok = 1;
int config_ok = 1,inirval;
free_filters();
if(ini_parse(fname,handler,instance.conf) < 0){
if((inirval = ini_parse(fname,handler,instance.conf)) < 0){
printf("Error parsing configuration file!\n");
if(inirval == -1)
printf("Inih file open error.\n");
else if(inirval == -2)
printf("inih memory error.\n");
skygw_log_write(LOGFILE_ERROR,"Error parsing configuration file!\n");
config_ok = 0;
goto cleanup;
@ -991,7 +995,7 @@ GWBUF* gen_packet(PACKET pkt)
int process_opts(int argc, char** argv)
{
int fd, buffsize = 1024;
int rd,rdsz, rval = 0;
int rd,rdsz, rval = 0,error;
size_t fsize;
char *buff = calloc(buffsize,sizeof(char)), *tok = NULL;
@ -1071,6 +1075,7 @@ int process_opts(int argc, char** argv)
free(conf_name);
}
conf_name = strdup(optarg);
printf("Configuration: %s\n",optarg);
break;
case 'q':
@ -1079,12 +1084,12 @@ int process_opts(int argc, char** argv)
case 's':
instance.session_count = atoi(optarg);
printf("Sessions: %i ",instance.session_count);
printf("Sessions: %i\n",instance.session_count);
break;
case 't':
instance.thrcount = atoi(optarg);
printf("Threads: %i ",instance.thrcount);
printf("Threads: %i\n",instance.thrcount);
break;
case 'd':
@ -1121,7 +1126,7 @@ int process_opts(int argc, char** argv)
}
printf("\n");
if(conf_name && load_config(conf_name)){
if(conf_name && (error = load_config(conf_name))){
load_query();
}else{
instance.running = 0;
@ -1129,6 +1134,11 @@ int process_opts(int argc, char** argv)
free(conf_name);
close(fd);
if(!error)
{
rval = 1;
}
return rval;
}

View File

@ -41,7 +41,8 @@ int main(int argc,char** argv)
}
route_buffers();
if(inst->expected){
if(inst->expected > 0){
return compare_files(inst->outfile,inst->expected);
}
return 0;

View File

@ -0,0 +1,4 @@
rule union_regex deny regex '.*union.*'
rule dont_delete_everything deny no_where_clause on_operations delete|update
rule no_wildcard deny wildcard
users %@% match any rules union_regex dont_delete_everything no_wildcard

View File

@ -0,0 +1,11 @@
#! /bin/bash
if [[ $# -lt 4 ]]
then
echo "Usage: $0 <config file> <input> <output> <expected>"
exit 1
fi
TESTDIR=@CMAKE_CURRENT_BINARY_DIR@
SRCDIR=@CMAKE_CURRENT_SOURCE_DIR@
$TESTDIR/harness -i $SRCDIR/$2 -o $TESTDIR/$3 -c $TESTDIR/$1 -t 1 -s 1 -e $SRCDIR/$4
exit $?