diff options
Diffstat (limited to 'sql/sql_connect.cc')
-rw-r--r-- | sql/sql_connect.cc | 137 |
1 files changed, 88 insertions, 49 deletions
diff --git a/sql/sql_connect.cc b/sql/sql_connect.cc index d8ac571b578..0d79a4c0042 100644 --- a/sql/sql_connect.cc +++ b/sql/sql_connect.cc @@ -37,6 +37,7 @@ #include "sql_acl.h" // acl_getroot, NO_ACCESS, SUPER_ACL #include "sql_callback.h" #include "wsrep_mysqld.h" +#include "proxy_protocol.h" HASH global_user_stats, global_client_stats, global_table_stats; HASH global_index_stats; @@ -836,6 +837,89 @@ bool init_new_connection_handler_thread() return 0; } +int thd_set_peer_addr(THD *thd, sockaddr_storage *addr, const char *ip,uint port, bool check_proxy_networks) +{ + uint connect_errors; + thd->peer_port = port; + + char ip_string[128]; + if (!ip) + { + void *addr_data; + if (addr->ss_family == AF_UNIX) + { + /* local connection */ + my_free((void *)thd->main_security_ctx.ip); + thd->main_security_ctx.host_or_ip= thd->main_security_ctx.host = my_localhost; + thd->main_security_ctx.ip= 0; + return 0; + } + else if (addr->ss_family == AF_INET) + addr_data= &((struct sockaddr_in *)addr)->sin_addr; + else + addr_data= &((struct sockaddr_in6 *)addr)->sin6_addr; + if (!inet_ntop(addr->ss_family,addr_data, ip_string, sizeof(ip_string))) + { + DBUG_ASSERT(0); + return 1; + } + ip= ip_string; + } + + my_free((void *)thd->main_security_ctx.ip); + if (!(thd->main_security_ctx.ip = my_strdup(ip, MYF(MY_WME)))) + { + /* + No error accounting per IP in host_cache, + this is treated as a global server OOM error. + TODO: remove the need for my_strdup. + */ + statistic_increment(aborted_connects, &LOCK_status); + statistic_increment(connection_errors_internal, &LOCK_status); + return 1; /* The error is set by my_strdup(). */ + } + thd->main_security_ctx.host_or_ip = thd->main_security_ctx.ip; + if (!(specialflag & SPECIAL_NO_RESOLVE)) + { + int rc; + + rc = ip_to_hostname(addr, + thd->main_security_ctx.ip, + &thd->main_security_ctx.host, + &connect_errors); + + /* Cut very long hostnames to avoid possible overflows */ + if (thd->main_security_ctx.host) + { + if (thd->main_security_ctx.host != my_localhost) + ((char*)thd->main_security_ctx.host)[MY_MIN(strlen(thd->main_security_ctx.host), + HOSTNAME_LENGTH)] = 0; + thd->main_security_ctx.host_or_ip = thd->main_security_ctx.host; + } + + if (rc == RC_BLOCKED_HOST) + { + /* HOST_CACHE stats updated by ip_to_hostname(). */ + my_error(ER_HOST_IS_BLOCKED, MYF(0), thd->main_security_ctx.host_or_ip); + return 1; + } + } + DBUG_PRINT("info", ("Host: %s ip: %s", + (thd->main_security_ctx.host ? + thd->main_security_ctx.host : "unknown host"), + (thd->main_security_ctx.ip ? + thd->main_security_ctx.ip : "unknown ip"))); + if ((!check_proxy_networks || !is_proxy_protocol_allowed((struct sockaddr *) addr)) + && acl_check_host(thd->main_security_ctx.host, thd->main_security_ctx.ip)) + { + /* HOST_CACHE stats updated by acl_check_host(). */ + my_error(ER_HOST_NOT_PRIVILEGED, MYF(0), + thd->main_security_ctx.host_or_ip); + return 1; + } + return 0; +} + /* Perform handshake, authorize client and update thd ACL variables. @@ -865,8 +949,9 @@ static int check_connection(THD *thd) { my_bool peer_rc; char ip[NI_MAXHOST]; + uint16 peer_port; - peer_rc= vio_peer_addr(net->vio, ip, &thd->peer_port, NI_MAXHOST); + peer_rc= vio_peer_addr(net->vio, ip, &peer_port, NI_MAXHOST); /* =========================================================================== @@ -941,55 +1026,9 @@ static int check_connection(THD *thd) my_error(ER_BAD_HOST_ERROR, MYF(0)); return 1; } - if (!(thd->main_security_ctx.ip= my_strdup(ip,MYF(MY_WME)))) - { - /* - No error accounting per IP in host_cache, - this is treated as a global server OOM error. - TODO: remove the need for my_strdup. - */ - statistic_increment(aborted_connects,&LOCK_status); - statistic_increment(connection_errors_internal, &LOCK_status); - return 1; /* The error is set by my_strdup(). */ - } - thd->main_security_ctx.host_or_ip= thd->main_security_ctx.ip; - if (!(specialflag & SPECIAL_NO_RESOLVE)) - { - int rc; - - rc= ip_to_hostname(&net->vio->remote, - thd->main_security_ctx.ip, - &thd->main_security_ctx.host, - &connect_errors); - - /* Cut very long hostnames to avoid possible overflows */ - if (thd->main_security_ctx.host) - { - if (thd->main_security_ctx.host != my_localhost) - ((char*) thd->main_security_ctx.host)[MY_MIN(strlen(thd->main_security_ctx.host), - HOSTNAME_LENGTH)]= 0; - thd->main_security_ctx.host_or_ip= thd->main_security_ctx.host; - } - - if (rc == RC_BLOCKED_HOST) - { - /* HOST_CACHE stats updated by ip_to_hostname(). */ - my_error(ER_HOST_IS_BLOCKED, MYF(0), thd->main_security_ctx.host_or_ip); - return 1; - } - } - DBUG_PRINT("info",("Host: %s ip: %s", - (thd->main_security_ctx.host ? - thd->main_security_ctx.host : "unknown host"), - (thd->main_security_ctx.ip ? - thd->main_security_ctx.ip : "unknown ip"))); - if (acl_check_host(thd->main_security_ctx.host, thd->main_security_ctx.ip)) - { - /* HOST_CACHE stats updated by acl_check_host(). */ - my_error(ER_HOST_NOT_PRIVILEGED, MYF(0), - thd->main_security_ctx.host_or_ip); + + if (thd_set_peer_addr(thd, &net->vio->remote, ip, peer_port, true)) return 1; - } } else /* Hostname given means that the connection was on a socket */ { |