Add support for wildcard in mysql_query_rules.client_addr #1450

Input validation:
- client_addr not longer than INET6_ADDRSTRLEN
- % allowed only at the end of client_addr

Query rule itself remembers if there is a wildcard or not.
If there is a wildcard compares string till the wildcard.
If client_addr=='%' , it is a match all.
This commit is contained in:
René Cannaò 2018-04-06 08:00:33 +02:00
Родитель 52fdaa15d3
Коммит d1a14e6c12
3 изменённых файлов: 46 добавлений и 3 удалений

Просмотреть файл

@ -14,6 +14,7 @@ struct _Query_Processor_rule_t {
char *schemaname;
int flagIN;
char *client_addr;
int client_addr_wildcard_position;
char *proxy_addr;
int proxy_port;
uint64_t digest;

Просмотреть файл

@ -7005,6 +7005,22 @@ char * ProxySQL_Admin::load_mysql_query_rules_to_runtime() {
QP_rule_t * nqpr;
for (std::vector<SQLite3_row *>::iterator it = resultset->rows.begin() ; it != resultset->rows.end(); ++it) {
SQLite3_row *r=*it;
if (r->fields[4]) {
char *pct = NULL;
if (strlen(r->fields[4]) >= INET6_ADDRSTRLEN) {
proxy_error("Query rule with rule_id=%s has an invalid client_addr: %s\n", r->fields[0], r->fields[4]);
continue;
}
pct = strchr(r->fields[4],'%');
if (pct) { // there is a wildcard
if (strlen(pct) == 1) {
// % is at the end of the string, good
} else {
proxy_error("Query rule with rule_id=%s has a wildcard that is not at the end of client_addr: %s\n", r->fields[0], r->fields[4]);
continue;
}
}
}
nqpr=GloQPro->new_query_rule(
atoi(r->fields[0]), // rule_id
true,

Просмотреть файл

@ -493,7 +493,23 @@ QP_rule_t * Query_Processor::new_query_rule(int rule_id, bool active, char *user
newQR->regex_engine2=NULL;
newQR->hits=0;
newQR->client_addr_wildcard_position = -1; // not existing by default
newQR->client_addr=(client_addr ? strdup(client_addr) : NULL);
if (newQR->client_addr) {
char *pct = strchr(newQR->client_addr,'%');
if (pct) { // there is a wildcard . We assume Admin did already all the input validation
if (pct == newQR->client_addr) {
// client_addr == '%'
// % is at the end of the string, but also at the beginning
// becoming a catch all
newQR->client_addr_wildcard_position = 0;
} else {
// this math is valid also if (pct == newQR->client_addr)
// but we separate it to clarify that client_addr_wildcard_position is a match all
newQR->client_addr_wildcard_position = strlen(newQR->client_addr) - strlen(pct);
}
}
}
newQR->proxy_addr=(proxy_addr ? strdup(proxy_addr) : NULL);
newQR->proxy_port=proxy_port;
newQR->log=log;
@ -952,9 +968,19 @@ __internal_loop:
// match on client address
if (qr->client_addr && strlen(qr->client_addr)) {
if (sess->client_myds->addr.addr) {
if (strcmp(qr->client_addr,sess->client_myds->addr.addr)!=0) {
proxy_debug(PROXY_DEBUG_MYSQL_QUERY_PROCESSOR, 5, "query rule %d has no matching client_addr\n", qr->rule_id);
continue;
if (qr->client_addr_wildcard_position == -1) { // no wildcard , old algorithm
if (strcmp(qr->client_addr,sess->client_myds->addr.addr)!=0) {
proxy_debug(PROXY_DEBUG_MYSQL_QUERY_PROCESSOR, 5, "query rule %d has no matching client_addr\n", qr->rule_id);
continue;
}
} else if (qr->client_addr_wildcard_position==0) {
// catch all!
// therefore we have a match
} else { // client_addr_wildcard_position > 0
if (strncmp(qr->client_addr,sess->client_myds->addr.addr,qr->client_addr_wildcard_position)!=0) {
proxy_debug(PROXY_DEBUG_MYSQL_QUERY_PROCESSOR, 5, "query rule %d has no matching client_addr\n", qr->rule_id);
continue;
}
}
}
}