diff --git a/Documentation/Filters/Database-Firewall-Filter.md b/Documentation/Filters/Database-Firewall-Filter.md index b715e1119..7f6e23681 100644 --- a/Documentation/Filters/Database-Firewall-Filter.md +++ b/Documentation/Filters/Database-Firewall-Filter.md @@ -32,7 +32,21 @@ Absolute path to a file with the rule definitions in it. The file should be read #### `action` -This parameter is optional and determines what action is taken when a query matches a rule. The value can be either `allow`, which allows all matching queries to proceed but blocks those that don't match, or `block`, which blocks all matching queries, or `ignore` which allows all queries to proceed. +This parameter is optional and determines what action is taken when a query +matches a rule. The value can be either `allow`, which allows all matching +queries to proceed but blocks those that don't match, or `block`, which blocks +all matching queries, or `ignore` which allows all queries to proceed. + +The following statement types will always be allowed through when `action` is +set to `allow`: + + - COM_QUIT: Client closes connection + - COM_PING: Server is pinged + - COM_CHANGE_USER: The user is changed for an active connection + - COM_SET_OPTION: Client multi-statements are being configured + - COM_FIELD_LIST: Alias for the `SHOW TABLES;` query + - COM_PROCESS_KILL: Alias for `KILL ;` query + - COM_PROCESS_INFO: Alias for `SHOW PROCESSLIST;` You can have both blacklist and whitelist functionality by configuring one filter with `action=allow` and another one with `action=block`. You can then use diff --git a/server/modules/filter/dbfwfilter/dbfwfilter.c b/server/modules/filter/dbfwfilter/dbfwfilter.c index 13da00544..b504ea0af 100644 --- a/server/modules/filter/dbfwfilter/dbfwfilter.c +++ b/server/modules/filter/dbfwfilter/dbfwfilter.c @@ -2174,6 +2174,26 @@ USER* find_user_data(HASHTABLE *hash, const char *name, const char *remote) return user; } +static bool command_is_mandatory(GWBUF *buffer) +{ + uint8_t cmd = *(((uint8_t*)GWBUF_DATA(buffer)) + 4); + + switch (cmd) + { + case MYSQL_COM_QUIT: + case MYSQL_COM_PING: + case MYSQL_COM_CHANGE_USER: + case MYSQL_COM_SET_OPTION: + case MYSQL_COM_FIELD_LIST: + case MYSQL_COM_PROCESS_KILL: + case MYSQL_COM_PROCESS_INFO: + return true; + + default: + return false; + } +} + /** * The routeQuery entry point. This is passed the query buffer * to which the filter should be applied. Once processed the @@ -2223,7 +2243,7 @@ routeQuery(FILTER *instance, void *session, GWBUF *queue) else { USER *user = find_user_data(my_instance->htable, dcb->user, dcb->remote); - bool query_ok = false; + bool query_ok = command_is_mandatory(queue); if (user) {