22 #include "my_global.h"
24 #include "sql_audit.h"
25 #include "sql_connect.h"
26 #include "my_global.h"
27 #include "probes_mysql.h"
29 #include "sql_parse.h"
36 #include "sql_callback.h"
43 #if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY)
54 #define SSL_HANDSHAKE_SIZE 2
55 #define NORMAL_HANDSHAKE_SIZE 6
56 #define MIN_HANDSHAKE_SIZE 2
58 #define MIN_HANDSHAKE_SIZE 6
65 #ifndef NO_EMBEDDED_ACCESS_CHECKS
66 static HASH hash_user_connections;
68 int get_or_create_user_conn(THD *thd,
const char *user,
73 size_t temp_len, user_len;
74 char temp_user[USER_HOST_BUFF_SIZE];
77 DBUG_ASSERT(user != 0);
78 DBUG_ASSERT(host != 0);
80 user_len= strlen(user);
81 temp_len= (strmov(strmov(temp_user, user)+1, host) - temp_user)+1;
83 if (!(uc = (
struct user_conn *) my_hash_search(&hash_user_connections,
84 (uchar*) temp_user, temp_len)))
88 my_malloc(
sizeof(
struct user_conn) + temp_len+1,
95 uc->user=(
char*) (uc+1);
96 memcpy(uc->user,temp_user,temp_len+1);
97 uc->host= uc->user + user_len + 1;
99 uc->connections= uc->questions= uc->updates= uc->conn_per_hour= 0;
100 uc->user_resources= *mqh;
102 if (my_hash_insert(&hash_user_connections, (uchar*) uc))
110 thd->set_user_connect(uc);
111 thd->increment_user_connections_counter();
136 int check_for_max_user_connections(THD *thd,
const USER_CONN *uc)
140 DBUG_ENTER(
"check_for_max_user_connections");
143 if (global_system_variables.max_user_connections &&
144 !uc->user_resources.user_conn &&
145 global_system_variables.max_user_connections < (uint) uc->connections)
147 my_error(ER_TOO_MANY_USER_CONNECTIONS, MYF(0), uc->user);
152 thd->time_out_user_resource_limits();
153 if (uc->user_resources.user_conn &&
154 uc->user_resources.user_conn < uc->connections)
156 my_error(ER_USER_LIMIT_REACHED, MYF(0), uc->user,
157 "max_user_connections",
158 (
long) uc->user_resources.user_conn);
163 if (uc->user_resources.conn_per_hour &&
164 uc->user_resources.conn_per_hour <= uc->conn_per_hour)
166 my_error(ER_USER_LIMIT_REACHED, MYF(0), uc->user,
167 "max_connections_per_hour",
168 (
long) uc->user_resources.conn_per_hour);
173 thd->increment_con_per_hour_counter();
178 thd->decrement_user_connections_counter();
184 thd->set_user_connect(NULL);
189 inc_host_errors(thd->main_security_ctx.get_ip()->ptr(), &errors);
213 void decrease_user_connections(
USER_CONN *uc)
215 DBUG_ENTER(
"decrease_user_connections");
217 DBUG_ASSERT(uc->connections);
218 if (!--uc->connections && !mqh_used)
221 (void) my_hash_delete(&hash_user_connections,(uchar*) uc);
235 void release_user_connection(THD *thd)
237 const USER_CONN *uc= thd->get_user_connect();
238 DBUG_ENTER(
"release_user_connection");
243 DBUG_ASSERT(uc->connections > 0);
244 thd->decrement_user_connections_counter();
245 if (!uc->connections && !mqh_used)
248 (void) my_hash_delete(&hash_user_connections,(uchar*) uc);
251 thd->set_user_connect(NULL);
264 bool check_mqh(THD *thd, uint check_command)
267 const USER_CONN *uc=thd->get_user_connect();
268 DBUG_ENTER(
"check_mqh");
269 DBUG_ASSERT(uc != 0);
273 thd->time_out_user_resource_limits();
276 if (uc->user_resources.questions)
278 thd->increment_questions_counter();
279 if ((uc->questions - 1) >= uc->user_resources.questions)
281 my_error(ER_USER_LIMIT_REACHED, MYF(0), uc->user,
"max_questions",
282 (
long) uc->user_resources.questions);
287 if (check_command < (uint) SQLCOM_END)
290 if (uc->user_resources.updates &&
293 thd->increment_updates_counter();
294 if ((uc->updates - 1) >= uc->user_resources.updates)
296 my_error(ER_USER_LIMIT_REACHED, MYF(0), uc->user,
"max_updates",
297 (
long) uc->user_resources.updates);
309 int check_for_max_user_connections(THD *thd,
const USER_CONN *uc)
314 void decrease_user_connections(
USER_CONN *uc)
319 void release_user_connection(THD *thd)
321 const USER_CONN *uc= thd->get_user_connect();
322 DBUG_ENTER(
"release_user_connection");
326 thd->set_user_connect(NULL);
339 extern "C" uchar *get_key_conn(
user_conn *buff,
size_t *length,
340 my_bool not_used __attribute__((unused)))
343 return (uchar*) buff->user;
347 extern "C" void free_user(
struct user_conn *uc)
353 void init_max_user_conn(
void)
355 #ifndef NO_EMBEDDED_ACCESS_CHECKS
357 my_hash_init(&hash_user_connections,system_charset_info,max_connections,
358 0,0, (my_hash_get_key) get_key_conn,
359 (my_hash_free_key) free_user, 0);
364 void free_max_user_conn(
void)
366 #ifndef NO_EMBEDDED_ACCESS_CHECKS
367 my_hash_free(&hash_user_connections);
372 void reset_mqh(
LEX_USER *lu,
bool get_them= 0)
374 #ifndef NO_EMBEDDED_ACCESS_CHECKS
379 uint temp_len=lu->user.length+lu->host.length+2;
380 char temp_user[USER_HOST_BUFF_SIZE];
382 memcpy(temp_user,lu->user.str,lu->user.length);
383 memcpy(temp_user+lu->user.length+1,lu->host.str,lu->host.length);
384 temp_user[lu->user.length]=
'\0'; temp_user[temp_len-1]=0;
385 if ((uc = (
struct user_conn *) my_hash_search(&hash_user_connections,
390 get_mqh(temp_user,&temp_user[lu->user.length+1],uc);
398 for (uint idx=0;idx < hash_user_connections.records; idx++)
401 my_hash_element(&hash_user_connections, idx);
403 get_mqh(uc->user,uc->host,uc);
428 bool thd_init_client_charset(THD *thd, uint cs_number)
438 if (!opt_character_set_client_handshake ||
439 !(cs= get_charset(cs_number, MYF(0))) ||
440 !my_strcasecmp(&my_charset_latin1,
441 global_system_variables.character_set_client->name,
444 if (!is_supported_parser_charset(
445 global_system_variables.character_set_client))
448 my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0),
"character_set_client",
449 global_system_variables.character_set_client->csname);
452 thd->variables.character_set_client=
453 global_system_variables.character_set_client;
454 thd->variables.collation_connection=
455 global_system_variables.collation_connection;
456 thd->variables.character_set_results=
457 global_system_variables.character_set_results;
461 if (!is_supported_parser_charset(cs))
464 my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0),
"character_set_client",
468 thd->variables.character_set_results=
469 thd->variables.collation_connection=
470 thd->variables.character_set_client= cs;
480 bool init_new_connection_handler_thread()
482 pthread_detach_this_thread();
483 if (my_thread_init())
485 statistic_increment(connection_errors_internal, &LOCK_status);
491 #ifndef EMBEDDED_LIBRARY
504 static int check_connection(THD *thd)
506 uint connect_errors= 0;
511 (
"New connection received on %s", vio_description(net->vio)));
512 #ifdef SIGNAL_WITH_VIO_SHUTDOWN
513 thd->set_active_vio(net->vio);
516 if (!thd->main_security_ctx.get_host()->length())
521 peer_rc= vio_peer_addr(net->vio, ip, &thd->peer_port, NI_MAXHOST);
530 DBUG_EXECUTE_IF(
"vio_peer_addr_error",
535 DBUG_EXECUTE_IF(
"vio_peer_addr_fake_ipv4",
537 struct sockaddr *sa= (sockaddr *) &net->vio->remote;
538 sa->sa_family= AF_INET;
539 struct in_addr *ip4= &((
struct sockaddr_in *) sa)->sin_addr;
541 const char* fake=
"192.0.2.4";
542 ip4->s_addr= inet_addr(fake);
549 DBUG_EXECUTE_IF(
"vio_peer_addr_fake_ipv6",
551 struct sockaddr_in6 *sa= (sockaddr_in6 *) &net->vio->remote;
552 sa->sin6_family= AF_INET6;
553 struct in6_addr *ip6= & sa->sin6_addr;
555 const char* fake=
"2001:db8::6:6";
557 ip6->s6_addr[ 0] = 0x20;
558 ip6->s6_addr[ 1] = 0x01;
559 ip6->s6_addr[ 2] = 0x0d;
560 ip6->s6_addr[ 3] = 0xb8;
561 ip6->s6_addr[ 4] = 0x00;
562 ip6->s6_addr[ 5] = 0x00;
563 ip6->s6_addr[ 6] = 0x00;
564 ip6->s6_addr[ 7] = 0x00;
565 ip6->s6_addr[ 8] = 0x00;
566 ip6->s6_addr[ 9] = 0x00;
567 ip6->s6_addr[10] = 0x00;
568 ip6->s6_addr[11] = 0x00;
569 ip6->s6_addr[12] = 0x00;
570 ip6->s6_addr[13] = 0x06;
571 ip6->s6_addr[14] = 0x00;
572 ip6->s6_addr[15] = 0x06;
592 statistic_increment(connection_errors_peer_addr, &LOCK_status);
593 my_error(ER_BAD_HOST_ERROR, MYF(0));
596 thd->main_security_ctx.set_ip(my_strdup(ip, MYF(MY_WME)));
597 if (!(thd->main_security_ctx.get_ip()->length()))
604 statistic_increment(connection_errors_internal, &LOCK_status);
607 thd->main_security_ctx.host_or_ip= thd->main_security_ctx.get_ip()->ptr();
608 if (!(specialflag & SPECIAL_NO_RESOLVE))
611 char *host= (
char *) thd->main_security_ctx.get_host()->ptr();
614 thd->main_security_ctx.get_ip()->ptr(),
615 &host, &connect_errors);
617 thd->main_security_ctx.set_host(host);
619 if (thd->main_security_ctx.get_host()->length())
621 if (thd->main_security_ctx.get_host()->ptr() != my_localhost)
622 thd->main_security_ctx.set_host(thd->main_security_ctx.get_host()->ptr(),
623 min<size_t>(thd->main_security_ctx.get_host()->length(),
625 thd->main_security_ctx.host_or_ip=
626 thd->main_security_ctx.get_host()->ptr();
629 if (rc == RC_BLOCKED_HOST)
632 my_error(ER_HOST_IS_BLOCKED, MYF(0), thd->main_security_ctx.host_or_ip);
636 DBUG_PRINT(
"info",(
"Host: %s ip: %s",
637 (thd->main_security_ctx.get_host()->length() ?
638 thd->main_security_ctx.get_host()->ptr() :
"unknown host"),
639 (thd->main_security_ctx.get_ip()->length() ?
640 thd->main_security_ctx.get_ip()->ptr() :
"unknown ip")));
641 if (acl_check_host(thd->main_security_ctx.get_host()->ptr(),
642 thd->main_security_ctx.get_ip()->ptr()))
645 my_error(ER_HOST_NOT_PRIVILEGED, MYF(0),
646 thd->main_security_ctx.host_or_ip);
652 DBUG_PRINT(
"info",(
"Host: %s", thd->main_security_ctx.get_host()->ptr()));
653 thd->main_security_ctx.host_or_ip= thd->main_security_ctx.get_host()->ptr();
654 thd->main_security_ctx.set_ip(
"");
656 memset(&net->vio->remote, 0,
sizeof(net->vio->remote));
658 vio_keepalive(net->vio, TRUE);
660 if (thd->packet.alloc(thd->variables.net_buffer_length))
673 statistic_increment(connection_errors_internal, &LOCK_status);
677 auth_rc= acl_authenticate(thd, 0);
678 if (auth_rc == 0 && connect_errors != 0)
685 reset_host_connect_errors(thd->main_security_ctx.get_ip()->ptr());
705 bool setup_connection_thread_globals(THD *thd)
707 if (thd->store_globals())
709 close_connection(thd, ER_OUT_OF_RESOURCES);
710 statistic_increment(aborted_connects,&LOCK_status);
711 MYSQL_CALLBACK(thread_scheduler, end_thread, (thd, 0));
734 bool login_connection(THD *thd)
738 DBUG_ENTER(
"login_connection");
739 DBUG_PRINT(
"info", (
"login_connection called by thread %lu",
743 my_net_set_read_timeout(net, connect_timeout);
744 my_net_set_write_timeout(net, connect_timeout);
746 error= check_connection(thd);
747 thd->protocol->end_statement();
752 if (vio_type(net->vio) == VIO_TYPE_NAMEDPIPE)
755 statistic_increment(aborted_connects,&LOCK_status);
759 my_net_set_read_timeout(net, thd->variables.net_read_timeout);
760 my_net_set_write_timeout(net, thd->variables.net_write_timeout);
772 void end_connection(THD *thd)
775 plugin_thdvar_cleanup(thd);
782 release_user_connection(thd);
784 if (thd->killed || (net->error && net->vio != 0))
786 statistic_increment(aborted_threads,&LOCK_status);
789 if (net->error && net->vio != 0)
791 if (!thd->killed && log_warnings > 1)
793 Security_context *sctx= thd->security_ctx;
795 sql_print_warning(ER(ER_NEW_ABORTING_CONNECTION),
796 thd->thread_id,(thd->db ? thd->db :
"unconnected"),
797 sctx->user ? sctx->user :
"unauthenticated",
799 (thd->get_stmt_da()->is_error() ?
800 thd->get_stmt_da()->message() :
801 ER(ER_UNKNOWN_ERROR)));
811 void prepare_new_connection_state(THD* thd)
813 Security_context *sctx= thd->security_ctx;
815 if (thd->client_capabilities & CLIENT_COMPRESS)
824 thd->set_command(COM_SLEEP);
826 thd->init_for_queries();
828 if (opt_init_connect.length && !(sctx->master_access & SUPER_ACL))
830 execute_init_command(thd, &opt_init_connect, &LOCK_sys_init_connect);
837 sql_print_warning(ER(ER_NEW_ABORTING_CONNECTION),
839 thd->db ? thd->db :
"unconnected",
840 sctx->user ? sctx->user :
"unauthenticated",
841 sctx->host_or_ip,
"init_connect command failed");
842 sql_print_warning(
"%s", thd->get_stmt_da()->message());
844 thd->lex->current_select= 0;
845 my_net_set_read_timeout(net, thd->variables.net_wait_timeout);
847 net_new_transaction(net);
853 if (packet_length != packet_error)
854 my_error(ER_NEW_ABORTING_CONNECTION, MYF(0),
856 thd->db ? thd->db :
"unconnected",
857 sctx->user ? sctx->user :
"unauthenticated",
858 sctx->host_or_ip,
"init_connect command failed");
860 thd->server_status&= ~SERVER_STATUS_CLEAR_SET;
861 thd->protocol->end_statement();
862 thd->killed = THD::KILL_CONNECTION;
864 inc_host_errors(thd->main_security_ctx.get_ip()->ptr(), &errors);
870 thd->init_for_queries();
892 pthread_handler_t handle_one_connection(
void *arg)
894 THD *thd= (THD*) arg;
898 do_handle_one_connection(thd);
902 bool thd_prepare_connection(THD *thd)
906 rc= login_connection(thd);
907 MYSQL_AUDIT_NOTIFY_CONNECTION_CONNECT(thd);
911 MYSQL_CONNECTION_START(thd->thread_id, &thd->security_ctx->priv_user[0],
912 (
char *) thd->security_ctx->host_or_ip);
914 prepare_new_connection_state(thd);
918 bool thd_is_connection_alive(THD *thd)
923 !(thd->killed == THD::KILL_CONNECTION))
928 void do_handle_one_connection(THD *thd_arg)
932 thd->thr_create_utime= my_micro_time();
934 if (MYSQL_CALLBACK_ELSE(thread_scheduler, init_new_connection_thread, (), 0))
936 close_connection(thd, ER_OUT_OF_RESOURCES);
937 statistic_increment(aborted_connects,&LOCK_status);
938 MYSQL_CALLBACK(thread_scheduler, end_thread, (thd, 0));
947 if (thd->prior_thr_create_utime)
949 ulong launch_time= (ulong) (thd->thr_create_utime -
950 thd->prior_thr_create_utime);
951 if (launch_time >= slow_launch_time*1000000L)
952 statistic_increment(slow_launch_threads, &LOCK_status);
953 thd->prior_thr_create_utime= 0;
964 thd->thread_stack= (
char*) &thd;
965 if (setup_connection_thread_globals(thd))
973 mysql_socket_set_thread_owner(net->vio->mysql_socket);
975 rc= thd_prepare_connection(thd);
979 while (thd_is_connection_alive(thd))
981 mysql_audit_release(thd);
988 close_connection(thd);
989 if (MYSQL_CALLBACK_ELSE(thread_scheduler, end_thread, (thd, 1), 0))
998 thd->thread_stack= (
char*) &thd;