1
/* Copyright (C) 2007 MySQL AB
3
This program is free software; you can redistribute it and/or modify
4
it under the terms of the GNU General Public License as published by
5
the Free Software Foundation; version 2 of the License.
7
This program is distributed in the hope that it will be useful,
8
but WITHOUT ANY WARRANTY; without even the implied warranty of
9
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
GNU General Public License for more details.
12
You should have received a copy of the GNU General Public License
13
along with this program; if not, write to the Free Software
14
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
18
Functions to autenticate and handle reqests for a connection
21
#include "mysql_priv.h"
25
Without SSL the handshake consists of one packet. This packet
26
has both client capabilites and scrambled password.
27
With SSL the handshake might consist of two packets. If the first
28
packet (client capabilities) has CLIENT_SSL flag set, we have to
29
switch to SSL and read the second packet. The scrambled password
30
is in the second packet and client_capabilites field will be ignored.
31
Maybe it is better to accept flags other than CLIENT_SSL from the
34
#define SSL_HANDSHAKE_SIZE 2
35
#define NORMAL_HANDSHAKE_SIZE 6
36
#define MIN_HANDSHAKE_SIZE 2
38
#define MIN_HANDSHAKE_SIZE 6
39
#endif /* HAVE_OPENSSL */
42
extern void win_install_sigabrt_handler();
46
Get structure for logging connection data for the current user
49
#ifndef NO_EMBEDDED_ACCESS_CHECKS
50
static HASH hash_user_connections;
52
static int get_or_create_user_conn(THD *thd, const char *user,
57
size_t temp_len, user_len;
58
char temp_user[USER_HOST_BUFF_SIZE];
61
DBUG_ASSERT(user != 0);
62
DBUG_ASSERT(host != 0);
64
user_len= strlen(user);
65
temp_len= (strmov(strmov(temp_user, user)+1, host) - temp_user)+1;
66
(void) pthread_mutex_lock(&LOCK_user_conn);
67
if (!(uc = (struct user_conn *) hash_search(&hash_user_connections,
68
(uchar*) temp_user, temp_len)))
70
/* First connection for user; Create a user connection object */
71
if (!(uc= ((struct user_conn*)
72
my_malloc(sizeof(struct user_conn) + temp_len+1,
75
/* MY_WME ensures an error is set in THD. */
79
uc->user=(char*) (uc+1);
80
memcpy(uc->user,temp_user,temp_len+1);
81
uc->host= uc->user + user_len + 1;
83
uc->connections= uc->questions= uc->updates= uc->conn_per_hour= 0;
84
uc->user_resources= *mqh;
85
uc->reset_utime= thd->thr_create_utime;
86
if (my_hash_insert(&hash_user_connections, (uchar*) uc))
88
/* The only possible error is out of memory, MY_WME sets an error. */
89
my_free((char*) uc,0);
97
(void) pthread_mutex_unlock(&LOCK_user_conn);
104
check if user has already too many connections
107
check_for_max_user_connections()
109
uc User connect object
112
If check fails, we decrease user connection count, which means one
113
shouldn't call decrease_user_connections() after this function.
121
int check_for_max_user_connections(THD *thd, USER_CONN *uc)
124
DBUG_ENTER("check_for_max_user_connections");
126
(void) pthread_mutex_lock(&LOCK_user_conn);
127
if (max_user_connections && !uc->user_resources.user_conn &&
128
max_user_connections < (uint) uc->connections)
130
my_error(ER_TOO_MANY_USER_CONNECTIONS, MYF(0), uc->user);
134
time_out_user_resource_limits(thd, uc);
135
if (uc->user_resources.user_conn &&
136
uc->user_resources.user_conn < uc->connections)
138
my_error(ER_USER_LIMIT_REACHED, MYF(0), uc->user,
139
"max_user_connections",
140
(long) uc->user_resources.user_conn);
144
if (uc->user_resources.conn_per_hour &&
145
uc->user_resources.conn_per_hour <= uc->conn_per_hour)
147
my_error(ER_USER_LIMIT_REACHED, MYF(0), uc->user,
148
"max_connections_per_hour",
149
(long) uc->user_resources.conn_per_hour);
157
uc->connections--; // no need for decrease_user_connections() here
158
(void) pthread_mutex_unlock(&LOCK_user_conn);
164
Decrease user connection count
167
decrease_user_connections()
168
uc User connection object
171
If there is a n user connection object for a connection
172
(which only happens if 'max_user_connections' is defined or
173
if someone has created a resource grant for a user), then
174
the connection count is always incremented on connect.
176
The user connect object is not freed if some users has
177
'max connections per hour' defined as we need to be able to hold
178
count over the lifetime of the connection.
181
void decrease_user_connections(USER_CONN *uc)
183
DBUG_ENTER("decrease_user_connections");
184
(void) pthread_mutex_lock(&LOCK_user_conn);
185
DBUG_ASSERT(uc->connections);
186
if (!--uc->connections && !mqh_used)
188
/* Last connection for user; Delete it */
189
(void) hash_delete(&hash_user_connections,(uchar*) uc);
191
(void) pthread_mutex_unlock(&LOCK_user_conn);
197
Reset per-hour user resource limits when it has been more than
198
an hour since they were last checked
201
time_out_user_resource_limits()
203
uc User connection details
206
This assumes that the LOCK_user_conn mutex has been acquired, so it is
207
safe to test and modify members of the USER_CONN structure.
210
void time_out_user_resource_limits(THD *thd, USER_CONN *uc)
212
ulonglong check_time= thd->start_utime;
213
DBUG_ENTER("time_out_user_resource_limits");
215
/* If more than a hour since last check, reset resource checking */
216
if (check_time - uc->reset_utime >= LL(3600000000))
221
uc->reset_utime= check_time;
228
Check if maximum queries per hour limit has been reached
232
bool check_mqh(THD *thd, uint check_command)
235
USER_CONN *uc=thd->user_connect;
236
DBUG_ENTER("check_mqh");
237
DBUG_ASSERT(uc != 0);
239
(void) pthread_mutex_lock(&LOCK_user_conn);
241
time_out_user_resource_limits(thd, uc);
243
/* Check that we have not done too many questions / hour */
244
if (uc->user_resources.questions &&
245
uc->questions++ >= uc->user_resources.questions)
247
my_error(ER_USER_LIMIT_REACHED, MYF(0), uc->user, "max_questions",
248
(long) uc->user_resources.questions);
252
if (check_command < (uint) SQLCOM_END)
254
/* Check that we have not done too many updates / hour */
255
if (uc->user_resources.updates &&
256
(sql_command_flags[check_command] & CF_CHANGES_DATA) &&
257
uc->updates++ >= uc->user_resources.updates)
259
my_error(ER_USER_LIMIT_REACHED, MYF(0), uc->user, "max_updates",
260
(long) uc->user_resources.updates);
266
(void) pthread_mutex_unlock(&LOCK_user_conn);
270
#endif /* NO_EMBEDDED_ACCESS_CHECKS */
274
Check if user exist and password supplied is correct.
276
@param thd thread handle, thd->security_ctx->{host,user,ip} are used
277
@param command originator of the check: now check_user is called
278
during connect and change user procedures; used for
280
@param passwd scrambled password received from client
281
@param passwd_len length of scrambled password
282
@param db database name to connect to, may be NULL
283
@param check_count TRUE if establishing a new connection. In this case
284
check that we have not exceeded the global
285
max_connections limist
287
@note Host, user and passwd may point to communication buffer.
288
Current implementation does not depend on that, but future changes
289
should be done with this in mind; 'thd' is INOUT, all other params
292
@retval 0 OK; thd->security_ctx->user/master_access/priv_user/db_access and
293
thd->db are updated; OK is sent to the client.
294
@retval 1 error, e.g. access denied or handshake error, not sent to
295
the client. A message is pushed into the error stack.
299
check_user(THD *thd, enum enum_server_command command,
300
const char *passwd, uint passwd_len, const char *db,
303
DBUG_ENTER("check_user");
304
LEX_STRING db_str= { (char *) db, db ? strlen(db) : 0 };
307
Clear thd->db as it points to something, that will be freed when
308
connection is closed. We don't want to accidentally free a wrong
309
pointer if connect failed. Also in case of 'CHANGE USER' failure,
310
current database will be switched to 'no database selected'.
312
thd->reset_db(NULL, 0);
314
#ifdef NO_EMBEDDED_ACCESS_CHECKS
315
thd->main_security_ctx.master_access= GLOBAL_ACLS; // Full rights
316
/* Change database if necessary */
319
if (mysql_change_db(thd, &db_str, FALSE))
326
my_bool opt_secure_auth_local;
327
pthread_mutex_lock(&LOCK_global_system_variables);
328
opt_secure_auth_local= opt_secure_auth;
329
pthread_mutex_unlock(&LOCK_global_system_variables);
332
If the server is running in secure auth mode, short scrambles are
335
if (opt_secure_auth_local && passwd_len == SCRAMBLE_LENGTH_323)
337
my_error(ER_NOT_SUPPORTED_AUTH_MODE, MYF(0));
338
general_log_print(thd, COM_CONNECT, ER(ER_NOT_SUPPORTED_AUTH_MODE));
341
if (passwd_len != 0 &&
342
passwd_len != SCRAMBLE_LENGTH &&
343
passwd_len != SCRAMBLE_LENGTH_323)
345
my_error(ER_HANDSHAKE_ERROR, MYF(0), thd->main_security_ctx.host_or_ip);
350
int res= acl_getroot(thd, &ur, passwd, passwd_len);
351
#ifndef EMBEDDED_LIBRARY
355
This happens when client (new) sends password scrambled with
356
scramble(), but database holds old value (scrambled with
357
scramble_323()). Here we please client to send scrambled_password
361
if (opt_secure_auth_local)
363
my_error(ER_SERVER_IS_IN_SECURE_AUTH_MODE, MYF(0),
364
thd->main_security_ctx.user,
365
thd->main_security_ctx.host_or_ip);
366
general_log_print(thd, COM_CONNECT, ER(ER_SERVER_IS_IN_SECURE_AUTH_MODE),
367
thd->main_security_ctx.user,
368
thd->main_security_ctx.host_or_ip);
371
/* We have to read very specific packet size */
372
if (send_old_password_request(thd) ||
373
my_net_read(net) != SCRAMBLE_LENGTH_323 + 1)
375
inc_host_errors(&thd->remote.sin_addr);
376
my_error(ER_HANDSHAKE_ERROR, MYF(0), thd->main_security_ctx.host_or_ip);
379
/* Final attempt to check the user based on reply */
380
/* So as passwd is short, errcode is always >= 0 */
381
res= acl_getroot(thd, &ur, (char *) net->read_pos, SCRAMBLE_LENGTH_323);
383
#endif /*EMBEDDED_LIBRARY*/
384
/* here res is always >= 0 */
387
if (!(thd->main_security_ctx.master_access &
388
NO_ACCESS)) // authentication is OK
391
("Capabilities: %lu packet_length: %ld Host: '%s' "
392
"Login user: '%s' Priv_user: '%s' Using password: %s "
393
"Access: %lu db: '%s'",
394
thd->client_capabilities,
395
thd->max_client_packet_length,
396
thd->main_security_ctx.host_or_ip,
397
thd->main_security_ctx.user,
398
thd->main_security_ctx.priv_user,
399
passwd_len ? "yes": "no",
400
thd->main_security_ctx.master_access,
401
(thd->db ? thd->db : "*none*")));
405
pthread_mutex_lock(&LOCK_connection_count);
406
bool count_ok= connection_count <= max_connections ||
407
(thd->main_security_ctx.master_access & SUPER_ACL);
408
VOID(pthread_mutex_unlock(&LOCK_connection_count));
411
{ // too many connections
412
my_error(ER_CON_COUNT_ERROR, MYF(0));
418
Log the command before authentication checks, so that the user can
419
check the log for the tried login tried and also to detect
422
general_log_print(thd, command,
423
(thd->main_security_ctx.priv_user ==
424
thd->main_security_ctx.user ?
425
(char*) "%s@%s on %s" :
426
(char*) "%s@%s as anonymous on %s"),
427
thd->main_security_ctx.user,
428
thd->main_security_ctx.host_or_ip,
429
db ? db : (char*) "");
432
This is the default access rights for the current database. It's
433
set to 0 here because we don't have an active database yet (and we
434
may not have an active database to set.
436
thd->main_security_ctx.db_access=0;
438
/* Don't allow user to connect if he has done too many queries */
439
if ((ur.questions || ur.updates || ur.conn_per_hour || ur.user_conn ||
440
max_user_connections) &&
441
get_or_create_user_conn(thd,
442
(opt_old_style_user_limits ? thd->main_security_ctx.user :
443
thd->main_security_ctx.priv_user),
444
(opt_old_style_user_limits ? thd->main_security_ctx.host_or_ip :
445
thd->main_security_ctx.priv_host),
448
/* The error is set by get_or_create_user_conn(). */
451
if (thd->user_connect &&
452
(thd->user_connect->user_resources.conn_per_hour ||
453
thd->user_connect->user_resources.user_conn ||
454
max_user_connections) &&
455
check_for_max_user_connections(thd, thd->user_connect))
457
/* The error is set in check_for_max_user_connections(). */
461
/* Change database if necessary */
464
if (mysql_change_db(thd, &db_str, FALSE))
466
/* mysql_change_db() has pushed the error message. */
467
if (thd->user_connect)
468
decrease_user_connections(thd->user_connect);
473
thd->password= test(passwd_len); // remember for error messages
474
/* Ready to handle queries */
478
else if (res == 2) // client gave short hash, server has long hash
480
my_error(ER_NOT_SUPPORTED_AUTH_MODE, MYF(0));
481
general_log_print(thd, COM_CONNECT, ER(ER_NOT_SUPPORTED_AUTH_MODE));
484
my_error(ER_ACCESS_DENIED_ERROR, MYF(0),
485
thd->main_security_ctx.user,
486
thd->main_security_ctx.host_or_ip,
487
passwd_len ? ER(ER_YES) : ER(ER_NO));
488
general_log_print(thd, COM_CONNECT, ER(ER_ACCESS_DENIED_ERROR),
489
thd->main_security_ctx.user,
490
thd->main_security_ctx.host_or_ip,
491
passwd_len ? ER(ER_YES) : ER(ER_NO));
493
#endif /* NO_EMBEDDED_ACCESS_CHECKS */
498
Check for maximum allowable user connections, if the mysqld server is
499
started with corresponding variable that is greater then 0.
502
extern "C" uchar *get_key_conn(user_conn *buff, size_t *length,
503
my_bool not_used __attribute__((unused)))
506
return (uchar*) buff->user;
510
extern "C" void free_user(struct user_conn *uc)
512
my_free((char*) uc,MYF(0));
516
void init_max_user_conn(void)
518
#ifndef NO_EMBEDDED_ACCESS_CHECKS
519
(void) hash_init(&hash_user_connections,system_charset_info,max_connections,
521
(hash_get_key) get_key_conn, (hash_free_key) free_user,
527
void free_max_user_conn(void)
529
#ifndef NO_EMBEDDED_ACCESS_CHECKS
530
hash_free(&hash_user_connections);
531
#endif /* NO_EMBEDDED_ACCESS_CHECKS */
535
void reset_mqh(LEX_USER *lu, bool get_them= 0)
537
#ifndef NO_EMBEDDED_ACCESS_CHECKS
538
(void) pthread_mutex_lock(&LOCK_user_conn);
542
uint temp_len=lu->user.length+lu->host.length+2;
543
char temp_user[USER_HOST_BUFF_SIZE];
545
memcpy(temp_user,lu->user.str,lu->user.length);
546
memcpy(temp_user+lu->user.length+1,lu->host.str,lu->host.length);
547
temp_user[lu->user.length]='\0'; temp_user[temp_len-1]=0;
548
if ((uc = (struct user_conn *) hash_search(&hash_user_connections,
549
(uchar*) temp_user, temp_len)))
552
get_mqh(temp_user,&temp_user[lu->user.length+1],uc);
559
/* for FLUSH PRIVILEGES and FLUSH USER_RESOURCES */
560
for (uint idx=0;idx < hash_user_connections.records; idx++)
562
USER_CONN *uc=(struct user_conn *) hash_element(&hash_user_connections,
565
get_mqh(uc->user,uc->host,uc);
571
(void) pthread_mutex_unlock(&LOCK_user_conn);
572
#endif /* NO_EMBEDDED_ACCESS_CHECKS */
576
void thd_init_client_charset(THD *thd, uint cs_number)
579
Use server character set and collation if
580
- opt_character_set_client_handshake is not set
581
- client has not specified a character set
582
- client character set is the same as the servers
583
- client character set doesn't exists in server
585
if (!opt_character_set_client_handshake ||
586
!(thd->variables.character_set_client= get_charset(cs_number, MYF(0))) ||
587
!my_strcasecmp(&my_charset_latin1,
588
global_system_variables.character_set_client->name,
589
thd->variables.character_set_client->name))
591
thd->variables.character_set_client=
592
global_system_variables.character_set_client;
593
thd->variables.collation_connection=
594
global_system_variables.collation_connection;
595
thd->variables.character_set_results=
596
global_system_variables.character_set_results;
600
thd->variables.character_set_results=
601
thd->variables.collation_connection=
602
thd->variables.character_set_client;
608
Initialize connection threads
611
bool init_new_connection_handler_thread()
613
pthread_detach_this_thread();
615
win_install_sigabrt_handler();
617
/* Win32 calls this in pthread_create */
618
if (my_thread_init())
625
Perform handshake, authorize client and update thd ACL variables.
632
0 success, OK is sent to user, thd is updated.
633
-1 error, which is sent to user
634
> 0 error code (not sent to user)
637
#ifndef EMBEDDED_LIBRARY
638
static int check_connection(THD *thd)
640
uint connect_errors= 0;
646
("New connection received on %s", vio_description(net->vio)));
647
#ifdef SIGNAL_WITH_VIO_CLOSE
648
thd->set_active_vio(net->vio);
651
if (!thd->main_security_ctx.host) // If TCP/IP connection
655
if (vio_peer_addr(net->vio, ip, &thd->peer_port))
657
my_error(ER_BAD_HOST_ERROR, MYF(0), thd->main_security_ctx.host_or_ip);
660
if (!(thd->main_security_ctx.ip= my_strdup(ip,MYF(MY_WME))))
661
return 1; /* The error is set by my_strdup(). */
662
thd->main_security_ctx.host_or_ip= thd->main_security_ctx.ip;
663
vio_in_addr(net->vio,&thd->remote.sin_addr);
664
if (!(specialflag & SPECIAL_NO_RESOLVE))
666
vio_in_addr(net->vio,&thd->remote.sin_addr);
667
thd->main_security_ctx.host=
668
ip_to_hostname(&thd->remote.sin_addr, &connect_errors);
669
/* Cut very long hostnames to avoid possible overflows */
670
if (thd->main_security_ctx.host)
672
if (thd->main_security_ctx.host != my_localhost)
673
thd->main_security_ctx.host[min(strlen(thd->main_security_ctx.host),
674
HOSTNAME_LENGTH)]= 0;
675
thd->main_security_ctx.host_or_ip= thd->main_security_ctx.host;
677
if (connect_errors > max_connect_errors)
679
my_error(ER_HOST_IS_BLOCKED, MYF(0), thd->main_security_ctx.host_or_ip);
683
DBUG_PRINT("info",("Host: %s ip: %s",
684
(thd->main_security_ctx.host ?
685
thd->main_security_ctx.host : "unknown host"),
686
(thd->main_security_ctx.ip ?
687
thd->main_security_ctx.ip : "unknown ip")));
688
if (acl_check_host(thd->main_security_ctx.host, thd->main_security_ctx.ip))
690
my_error(ER_HOST_NOT_PRIVILEGED, MYF(0),
691
thd->main_security_ctx.host_or_ip);
695
else /* Hostname given means that the connection was on a socket */
697
DBUG_PRINT("info",("Host: %s", thd->main_security_ctx.host));
698
thd->main_security_ctx.host_or_ip= thd->main_security_ctx.host;
699
thd->main_security_ctx.ip= 0;
701
bzero((char*) &thd->remote, sizeof(thd->remote));
703
vio_keepalive(net->vio, TRUE);
705
ulong server_capabilites;
707
/* buff[] needs to big enough to hold the server_version variable */
708
char buff[SERVER_VERSION_LENGTH + 1 + SCRAMBLE_LENGTH + 1 + 64];
709
server_capabilites= CLIENT_BASIC_FLAGS;
711
if (opt_using_transactions)
712
server_capabilites|= CLIENT_TRANSACTIONS;
714
server_capabilites|= CLIENT_COMPRESS;
715
#endif /* HAVE_COMPRESS */
719
server_capabilites |= CLIENT_SSL; /* Wow, SSL is available! */
720
server_capabilites |= CLIENT_SSL_VERIFY_SERVER_CERT;
722
#endif /* HAVE_OPENSSL */
724
end= strnmov(buff, server_version, SERVER_VERSION_LENGTH) + 1;
725
int4store((uchar*) end, thd->thread_id);
728
So as check_connection is the only entry point to authorization
729
procedure, scramble is set here. This gives us new scramble for
732
create_random_string(thd->scramble, SCRAMBLE_LENGTH, &thd->rand);
734
Old clients does not understand long scrambles, but can ignore packet
735
tail: that's why first part of the scramble is placed here, and second
736
part at the end of packet.
738
end= strmake(end, thd->scramble, SCRAMBLE_LENGTH_323) + 1;
740
int2store(end, server_capabilites);
741
/* write server characteristics: up to 16 bytes allowed */
742
end[2]=(char) default_charset_info->number;
743
int2store(end+3, thd->server_status);
746
/* write scramble tail */
747
end= strmake(end, thd->scramble + SCRAMBLE_LENGTH_323,
748
SCRAMBLE_LENGTH - SCRAMBLE_LENGTH_323) + 1;
750
/* At this point we write connection message and read reply */
751
if (net_write_command(net, (uchar) protocol_version, (uchar*) "", 0,
752
(uchar*) buff, (size_t) (end-buff)) ||
753
(pkt_len= my_net_read(net)) == packet_error ||
754
pkt_len < MIN_HANDSHAKE_SIZE)
756
inc_host_errors(&thd->remote.sin_addr);
757
my_error(ER_HANDSHAKE_ERROR, MYF(0),
758
thd->main_security_ctx.host_or_ip);
762
#ifdef _CUSTOMCONFIG_
763
#include "_cust_sql_parse.h"
766
reset_host_errors(&thd->remote.sin_addr);
767
if (thd->packet.alloc(thd->variables.net_buffer_length))
768
return 1; /* The error is set by alloc(). */
770
thd->client_capabilities= uint2korr(net->read_pos);
771
if (thd->client_capabilities & CLIENT_PROTOCOL_41)
773
thd->client_capabilities|= ((ulong) uint2korr(net->read_pos+2)) << 16;
774
thd->max_client_packet_length= uint4korr(net->read_pos+4);
775
DBUG_PRINT("info", ("client_character_set: %d", (uint) net->read_pos[8]));
776
thd_init_client_charset(thd, (uint) net->read_pos[8]);
777
thd->update_charset();
778
end= (char*) net->read_pos+32;
782
thd->max_client_packet_length= uint3korr(net->read_pos+2);
783
end= (char*) net->read_pos+5;
786
Disable those bits which are not supported by the server.
787
This is a precautionary measure, if the client lies. See Bug#27944.
789
thd->client_capabilities&= server_capabilites;
791
if (thd->client_capabilities & CLIENT_IGNORE_SPACE)
792
thd->variables.sql_mode|= MODE_IGNORE_SPACE;
794
DBUG_PRINT("info", ("client capabilities: %lu", thd->client_capabilities));
795
if (thd->client_capabilities & CLIENT_SSL)
797
/* Do the SSL layering. */
798
if (!ssl_acceptor_fd)
800
inc_host_errors(&thd->remote.sin_addr);
801
my_error(ER_HANDSHAKE_ERROR, MYF(0), thd->main_security_ctx.host_or_ip);
804
DBUG_PRINT("info", ("IO layer change in progress..."));
805
if (sslaccept(ssl_acceptor_fd, net->vio, net->read_timeout))
807
DBUG_PRINT("error", ("Failed to accept new SSL connection"));
808
inc_host_errors(&thd->remote.sin_addr);
809
my_error(ER_HANDSHAKE_ERROR, MYF(0), thd->main_security_ctx.host_or_ip);
812
DBUG_PRINT("info", ("Reading user information over SSL layer"));
813
if ((pkt_len= my_net_read(net)) == packet_error ||
814
pkt_len < NORMAL_HANDSHAKE_SIZE)
816
DBUG_PRINT("error", ("Failed to read user information (pkt_len= %lu)",
818
inc_host_errors(&thd->remote.sin_addr);
819
my_error(ER_HANDSHAKE_ERROR, MYF(0), thd->main_security_ctx.host_or_ip);
823
#endif /* HAVE_OPENSSL */
825
if (end >= (char*) net->read_pos+ pkt_len +2)
827
inc_host_errors(&thd->remote.sin_addr);
828
my_error(ER_HANDSHAKE_ERROR, MYF(0), thd->main_security_ctx.host_or_ip);
832
if (thd->client_capabilities & CLIENT_INTERACTIVE)
833
thd->variables.net_wait_timeout= thd->variables.net_interactive_timeout;
834
if ((thd->client_capabilities & CLIENT_TRANSACTIONS) &&
835
opt_using_transactions)
836
net->return_status= &thd->server_status;
839
char *passwd= strend(user)+1;
840
uint user_len= passwd - user - 1;
842
char db_buff[NAME_LEN + 1]; // buffer to store db in utf8
843
char user_buff[USERNAME_LENGTH + 1]; // buffer to store user in utf8
847
Old clients send null-terminated string as password; new clients send
848
the size (1 byte) + string (not null-terminated). Hence in case of empty
849
password both send '\0'.
851
This strlen() can't be easily deleted without changing protocol.
853
Cast *passwd to an unsigned char, so that it doesn't extend the sign for
854
*passwd > 127 and become 2**32-127+ after casting to uint.
856
uint passwd_len= thd->client_capabilities & CLIENT_SECURE_CONNECTION ?
857
(uchar)(*passwd++) : strlen(passwd);
858
db= thd->client_capabilities & CLIENT_CONNECT_WITH_DB ?
859
db + passwd_len + 1 : 0;
860
/* strlen() can't be easily deleted without changing protocol */
861
uint db_len= db ? strlen(db) : 0;
863
if (passwd + passwd_len + db_len > (char *)net->read_pos + pkt_len)
865
inc_host_errors(&thd->remote.sin_addr);
866
my_error(ER_HANDSHAKE_ERROR, MYF(0), thd->main_security_ctx.host_or_ip);
870
/* Since 4.1 all database names are stored in utf8 */
873
db_buff[copy_and_convert(db_buff, sizeof(db_buff)-1,
876
thd->charset(), &dummy_errors)]= 0;
880
user_buff[user_len= copy_and_convert(user_buff, sizeof(user_buff)-1,
881
system_charset_info, user, user_len,
882
thd->charset(), &dummy_errors)]= '\0';
885
/* If username starts and ends in "'", chop them off */
886
if (user_len > 1 && user[0] == '\'' && user[user_len - 1] == '\'')
893
if (thd->main_security_ctx.user)
894
x_free(thd->main_security_ctx.user);
895
if (!(thd->main_security_ctx.user= my_strdup(user, MYF(MY_WME))))
896
return 1; /* The error is set by my_strdup(). */
897
return check_user(thd, COM_CONNECT, passwd, passwd_len, db, TRUE);
902
Setup thread to be used with the current thread
905
bool setup_connection_thread_globals()
906
thd Thread/connection handler
910
1 Error (out of memory)
911
In this case we will close the connection and increment status
914
bool setup_connection_thread_globals(THD *thd)
916
if (thd->store_globals())
918
close_connection(thd, ER_OUT_OF_RESOURCES, 1);
919
statistic_increment(aborted_connects,&LOCK_status);
920
thread_scheduler.end_thread(thd, 0);
928
Autenticate user, with error reporting
935
Connection is not closed in case of errors
943
static bool login_connection(THD *thd)
947
DBUG_ENTER("login_connection");
948
DBUG_PRINT("info", ("login_connection called by thread %lu",
951
/* Use "connect_timeout" value during connection phase */
952
my_net_set_read_timeout(net, connect_timeout);
953
my_net_set_write_timeout(net, connect_timeout);
955
error= check_connection(thd);
956
net_end_statement(thd);
959
{ // Wrong permissions
961
if (vio_type(net->vio) == VIO_TYPE_NAMEDPIPE)
962
my_sleep(1000); /* must wait after eof() */
964
statistic_increment(aborted_connects,&LOCK_status);
967
/* Connect completed, set read/write timeouts back to default */
968
my_net_set_read_timeout(net, thd->variables.net_read_timeout);
969
my_net_set_write_timeout(net, thd->variables.net_write_timeout);
975
Close an established connection
978
This mainly updates status variables
981
static void end_connection(THD *thd)
984
plugin_thdvar_cleanup(thd);
985
if (thd->user_connect)
986
decrease_user_connections(thd->user_connect);
988
if (thd->killed || (net->error && net->vio != 0))
990
statistic_increment(aborted_threads,&LOCK_status);
993
if (net->error && net->vio != 0)
995
if (!thd->killed && thd->variables.log_warnings > 1)
997
Security_context *sctx= thd->security_ctx;
999
sql_print_warning(ER(ER_NEW_ABORTING_CONNECTION),
1000
thd->thread_id,(thd->db ? thd->db : "unconnected"),
1001
sctx->user ? sctx->user : "unauthenticated",
1003
(thd->main_da.is_error() ? thd->main_da.message() :
1004
ER(ER_UNKNOWN_ERROR)));
1011
Initialize THD to handle queries
1014
static void prepare_new_connection_state(THD* thd)
1016
Security_context *sctx= thd->security_ctx;
1019
netware_reg_user(sctx->ip, sctx->user, "MySQL");
1022
if (thd->variables.max_join_size == HA_POS_ERROR)
1023
thd->options |= OPTION_BIG_SELECTS;
1024
if (thd->client_capabilities & CLIENT_COMPRESS)
1025
thd->net.compress=1; // Use compression
1028
Much of this is duplicated in create_embedded_thd() for the
1029
embedded server library.
1030
TODO: refactor this to avoid code duplication there
1032
thd->version= refresh_version;
1034
thd->command= COM_SLEEP;
1036
thd->init_for_queries();
1038
if (sys_init_connect.value_length && !(sctx->master_access & SUPER_ACL))
1040
execute_init_command(thd, &sys_init_connect, &LOCK_sys_init_connect);
1041
if (thd->is_error())
1043
thd->killed= THD::KILL_CONNECTION;
1044
sql_print_warning(ER(ER_NEW_ABORTING_CONNECTION),
1045
thd->thread_id,(thd->db ? thd->db : "unconnected"),
1046
sctx->user ? sctx->user : "unauthenticated",
1047
sctx->host_or_ip, "init_connect command failed");
1048
sql_print_warning("%s", thd->main_da.message());
1052
thd->init_for_queries();
1058
Thread handler for a connection
1061
handle_one_connection()
1062
arg Connection object (THD)
1065
This function (normally) does the following:
1067
- Initialize THD to be used with this thread
1069
- Execute all queries sent on the connection
1070
- Take connection down
1071
- End thread / Handle next connection using thread from thread cache
1074
pthread_handler_t handle_one_connection(void *arg)
1076
THD *thd= (THD*) arg;
1078
thd->thr_create_utime= my_micro_time();
1080
if (thread_scheduler.init_new_connection_thread())
1082
close_connection(thd, ER_OUT_OF_RESOURCES, 1);
1083
statistic_increment(aborted_connects,&LOCK_status);
1084
thread_scheduler.end_thread(thd,0);
1089
If a thread was created to handle this connection:
1090
increment slow_launch_threads counter if it took more than
1091
slow_launch_time seconds to create the thread.
1093
if (thd->prior_thr_create_utime)
1095
ulong launch_time= (ulong) (thd->thr_create_utime -
1096
thd->prior_thr_create_utime);
1097
if (launch_time >= slow_launch_time*1000000L)
1098
statistic_increment(slow_launch_threads, &LOCK_status);
1099
thd->prior_thr_create_utime= 0;
1103
handle_one_connection() is normally the only way a thread would
1104
start and would always be on the very high end of the stack ,
1105
therefore, the thread stack always starts at the address of the
1106
first local variable of handle_one_connection, which is thd. We
1107
need to know the start of the stack so that we could check for
1110
thd->thread_stack= (char*) &thd;
1111
if (setup_connection_thread_globals(thd))
1116
NET *net= &thd->net;
1119
if (login_connection(thd))
1122
prepare_new_connection_state(thd);
1124
while (!net->error && net->vio != 0 &&
1125
!(thd->killed == THD::KILL_CONNECTION))
1127
if (do_command(thd))
1130
end_connection(thd);
1133
close_connection(thd, 0, 1);
1134
if (thread_scheduler.end_thread(thd,1))
1135
return 0; // Probably no-threads
1138
If end_thread() returns, we are either running with
1139
thread-handler=no-threads or this thread has been schedule to
1140
handle the next connection.
1143
thd->thread_stack= (char*) &thd;
1146
#endif /* EMBEDDED_LIBRARY */