diff --git a/deps/libinjection/Makefile b/deps/libinjection/Makefile index 37688b74c..f4c65434f 100644 --- a/deps/libinjection/Makefile +++ b/deps/libinjection/Makefile @@ -3,7 +3,7 @@ AR=ar r CC=cc LD=ld LDSHARED=ld -shared -CFLAGS=-Wall -Werror -ansi -g -O3 +CFLAGS=-Wall -Werror -ansi -g -O3 -fPIC # MAC #AR=libtool -static diff --git a/doc/internal/query_parser.txt b/doc/internal/query_parser.txt new file mode 100644 index 000000000..00871249f --- /dev/null +++ b/doc/internal/query_parser.txt @@ -0,0 +1,21 @@ +ProxySQL implements query parsing in the Query_Processor class. + +4 virtual functions are introduced in Query_Processor class: + virtual void * query_parser_init(char *query, int query_length, int flags) {return NULL;}; + virtual enum MYSQL_COM_QUERY_command query_parser_command_type(void *args) {return MYSQL_COM_QUERY___UNKNOWN;} + virtual char * query_parser_first_comment(void *args) { return NULL; } + virtual void query_parser_free(void *args) {}; + +query_parser_init() +query_parser_init() get as arguments a pointer to the query, its length, and flags that are specific to Query_Processor implementation or simply ignored. +Because multiple implementations of the query parsing should be possible, query_parser_init() returns a generic pointer that should point to a data structure created by query_parser_init() itself. The pointer needs to be passed at the end to query_parser_free() to be freed. + +query_parser_free() +Free the structure originally created by query_parser_init() + +query_parser_command_type() +Accept as argument the structure created by query_parser_init() and returns the type of query processed. + +query_parser_first_comment() +Not implemented yet. +In case the filterning need to be performed based on comments in the query, query_parser_first_comment() can return such comment. diff --git a/include/mysql_session.h b/include/mysql_session.h index 9359d076c..bc09c8fd0 100644 --- a/include/mysql_session.h +++ b/include/mysql_session.h @@ -36,6 +36,7 @@ class MySQL_Session int active_transactions; bool transaction_persistent; int to_process; + void *query_parser_args; unsigned long long pause; MySQL_Session_userinfo userinfo_client; MySQL_Session_userinfo userinfo_server; diff --git a/include/query_processor.h b/include/query_processor.h index 99331f062..abadeb3d3 100644 --- a/include/query_processor.h +++ b/include/query_processor.h @@ -3,6 +3,53 @@ #include "proxysql.h" #include "cpp.h" + +enum MYSQL_COM_QUERY_command { + MYSQL_COM_QUERY_ALTER_TABLE, + MYSQL_COM_QUERY_ANALYZE, + MYSQL_COM_QUERY_BEGIN, + MYSQL_COM_QUERY_CHANGE_MASTER, + MYSQL_COM_QUERY_CREATE_DATABASE, + MYSQL_COM_QUERY_CREATE_INDEX, + MYSQL_COM_QUERY_CREATE_TABLE, + MYSQL_COM_QUERY_CREATE_TEMPORARY, + MYSQL_COM_QUERY_CREATE_TRIGGER, + MYSQL_COM_QUERY_CREATE_USER, + MYSQL_COM_QUERY_DELETE, + MYSQL_COM_QUERY_DESCRIBE, + MYSQL_COM_QUERY_DROP_DATABASE, + MYSQL_COM_QUERY_DROP_INDEX, + MYSQL_COM_QUERY_DROP_TABLE, + MYSQL_COM_QUERY_DROP_TRIGGER, + MYSQL_COM_QUERY_DROP_USER, + MYSQL_COM_QUERY_GRANT, + MYSQL_COM_QUERY_EXPLAIN, + MYSQL_COM_QUERY_FLUSH, + MYSQL_COM_QUERY_INSERT, + MYSQL_COM_QUERY_KILL, + MYSQL_COM_QUERY_LOAD, + MYSQL_COM_QUERY_LOCK_TABLE, + MYSQL_COM_QUERY_OPTIMIZE, + MYSQL_COM_QUERY_PREPARE, + MYSQL_COM_QUERY_PURGE, + MYSQL_COM_QUERY_RENAME_TABLE, + MYSQL_COM_QUERY_RESET_MASTER, + MYSQL_COM_QUERY_RESET_SLAVE, + MYSQL_COM_QUERY_REPLACE, + MYSQL_COM_QUERY_REVOKE, + MYSQL_COM_QUERY_ROLLBACK, + MYSQL_COM_QUERY_SAVEPOINT, + MYSQL_COM_QUERY_SELECT, + MYSQL_COM_QUERY_SELECT_FOR_UPDATE, + MYSQL_COM_QUERY_SET, + MYSQL_COM_QUERY_START_TRANSACTION, + MYSQL_COM_QUERY_UNLOCK_TABLES, + MYSQL_COM_QUERY_UPDATE, + MYSQL_COM_QUERY_USE, + MYSQL_COM_QUERY_SHOW, + MYSQL_COM_QUERY___UNKNOWN +}; + struct _Query_Processor_rule_t { int rule_id; bool active; @@ -61,9 +108,15 @@ class Query_Processor { virtual void end_thread() {}; virtual void commit() {}; // this applies all the changes in memory virtual SQLite3_result * get_current_query_rules() {return NULL;}; - virtual SQLite3_result * get_stats_query_rules() {return NULL;}; + virtual void update_query_processor_stats() {}; + + virtual void * query_parser_init(char *query, int query_length, int flags) {return NULL;}; + virtual enum MYSQL_COM_QUERY_command query_parser_command_type(void *args) {return MYSQL_COM_QUERY___UNKNOWN;} + virtual char * query_parser_first_comment(void *args) { return NULL; } + virtual void query_parser_free(void *args) {}; + }; diff --git a/lib/Makefile b/lib/Makefile index dc98bd711..4a3749304 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -23,6 +23,10 @@ LIBCONFIG_PATH=$(DEPS_PATH)/libconfig/libconfig-1.4.9 LIBCONFIG_IDIR=-I$(LIBCONFIG_PATH)/lib +INJECTION_PATH=$(DEPS_PATH)/libinjection +INJECTION_IDIR=$(INJECTION_PATH) + + RE2_PATH=$(DEPS_PATH)/re2/re2 RE2_IDIR=$(RE2_PATH) @@ -31,7 +35,7 @@ IDIR=../include #IDIRS=-I$(IDIR) -I$(JEMALLOC_IDIR) -I$(MARIADB_IDIR) $(LIBEVENT_IDIR) $(GLIB_IDIRS) $(LIBCONFIG_IDIR) IDIRS=-I$(IDIR) -I$(JEMALLOC_IDIR) -I$(MARIADB_IDIR) $(LIBCONFIG_IDIR) -I$(RE2_IDIR) -LDIRS=-L$(JEMALLOC_PATH)/lib -L$(RE2_PATH)/obj +LDIRS=-L$(JEMALLOC_PATH)/lib -L$(RE2_PATH)/obj -L$(INJECTION_PATH) LIBS=-rdynamic -Wl,-Bstatic -ljemalloc_pic -lre2 -Wl,-Bdynamic -ldl -lpthread -lm -lz -lrt @@ -64,7 +68,7 @@ Standard_ProxySQL_Admin.so: Standard_ProxySQL_Admin.ko Standard_MySQL_Thread.ko $(CPP) -shared -fPIC -o $@ $(CPPFLAGS) Standard_ProxySQL_Admin.ko Standard_MySQL_Thread.ko libproxysql.a -lcrypto $(LIBS) Standard_Query_Processor.so: Standard_Query_Processor.ko libproxysql.a - $(CPP) -shared -fPIC -o $@ $(CPPFLAGS) Standard_Query_Processor.ko libproxysql.a -lcrypto $(LIBS) + $(CPP) -shared -fPIC -o $@ $(CPPFLAGS) Standard_Query_Processor.ko libproxysql.a -lcrypto $(LIBS) -linjection Standard_MySQL_Authentication.so: Standard_MySQL_Authentication.ko libproxysql.a $(CPP) -shared -fPIC -o $@ $(CPPFLAGS) Standard_MySQL_Authentication.ko libproxysql.a -lcrypto $(LIBS) diff --git a/lib/Standard_Query_Processor.cpp b/lib/Standard_Query_Processor.cpp index 05e526896..ef63239eb 100644 --- a/lib/Standard_Query_Processor.cpp +++ b/lib/Standard_Query_Processor.cpp @@ -5,7 +5,8 @@ #include "re2/regexp.h" #include "proxysql.h" #include "cpp.h" - +#include "../deps/libinjection/libinjection.h" +#include "../deps/libinjection/libinjection_sqli.h" #define QUERY_PROCESSOR_VERSION "0.1.728" @@ -108,6 +109,13 @@ class QP_rule_text { }; +struct __SQP_query_parser_t { + sfilter sf; +}; + +typedef struct __SQP_query_parser_t SQP_par_t; + + struct __RE2_objects_t { re2::RE2::Options *opt; RE2 *re; @@ -505,8 +513,27 @@ virtual void update_query_processor_stats() { } } spin_rdunlock(&rwlock); +}; + +virtual void * query_parser_init(char *query, int query_length, int flags) { + SQP_par_t *qp=(SQP_par_t *)malloc(sizeof(SQP_par_t)); + libinjection_sqli_init(&qp->sf, query, query_length, FLAG_SQL_MYSQL); + return (void *)qp; +}; + +virtual enum MYSQL_COM_QUERY_command query_parser_command_type(void *args) { + SQP_par_t *qp=(SQP_par_t *)args; + + return MYSQL_COM_QUERY___UNKNOWN; } +virtual char * query_parser_first_comment(void *args) { return NULL; } + +virtual void query_parser_free(void *args) { + SQP_par_t *qp=(SQP_par_t *)args; + free(qp); +}; + }; extern "C" Query_Processor * create_Query_Processor_func() { diff --git a/lib/mysql_session.cpp b/lib/mysql_session.cpp index 0bbc1a96c..e16da58af 100644 --- a/lib/mysql_session.cpp +++ b/lib/mysql_session.cpp @@ -344,6 +344,8 @@ int MySQL_Session::handler() { switch ((enum_mysql_command)c) { case _MYSQL_COM_QUERY: if (admin==false) { + query_parser_args=GloQPro->query_parser_init((char *)pkt.ptr+5, pkt.size-5, 0); + GloQPro->query_parser_free(query_parser_args); myprot_client.process_pkt_COM_QUERY((unsigned char *)pkt.ptr,pkt.size); qpo=GloQPro->process_mysql_query(this,pkt.ptr,pkt.size,false); if (qpo) {