70
69
should be done with this in mind; 'thd' is INOUT, all other params
72
@retval 0 OK; thd->security_ctx->user/master_access/priv_user/db_access and
73
thd->db are updated; OK is sent to the client.
74
74
@retval 1 error, e.g. access denied or handshake error, not sent to
75
75
the client. A message is pushed into the error stack.
79
check_user(THD *thd, const char *passwd,
80
uint32_t passwd_len, const char *db,
79
check_user(THD *thd, enum enum_server_command command,
80
const char *passwd __attribute__((__unused__)),
81
uint passwd_len, const char *db,
83
84
LEX_STRING db_str= { (char *) db, db ? strlen(db) : 0 };
84
bool is_authenticated;
87
87
Clear thd->db as it points to something, that will be freed when
92
92
thd->reset_db(NULL, 0);
94
if (passwd_len != 0 && passwd_len != SCRAMBLE_LENGTH)
96
my_error(ER_HANDSHAKE_ERROR, MYF(0), thd->main_security_ctx.ip);
100
is_authenticated= authenticate_user(thd, passwd);
102
if (is_authenticated != true)
104
my_error(ER_ACCESS_DENIED_ERROR, MYF(0),
105
thd->main_security_ctx.user,
106
thd->main_security_ctx.ip,
107
passwd_len ? ER(ER_YES) : ER(ER_NO));
94
my_bool opt_secure_auth_local;
95
pthread_mutex_lock(&LOCK_global_system_variables);
96
opt_secure_auth_local= opt_secure_auth;
97
pthread_mutex_unlock(&LOCK_global_system_variables);
100
If the server is running in secure auth mode, short scrambles are
103
if (opt_secure_auth_local && passwd_len == SCRAMBLE_LENGTH_323)
105
my_error(ER_NOT_SUPPORTED_AUTH_MODE, MYF(0));
106
general_log_print(thd, COM_CONNECT, ER(ER_NOT_SUPPORTED_AUTH_MODE));
109
if (passwd_len != 0 &&
110
passwd_len != SCRAMBLE_LENGTH &&
111
passwd_len != SCRAMBLE_LENGTH_323)
113
my_error(ER_HANDSHAKE_ERROR, MYF(0), thd->main_security_ctx.host_or_ip);
113
117
USER_RESOURCES ur;
114
118
thd->security_ctx->skip_grants();
135
Log the command before authentication checks, so that the user can
136
check the log for the tried login tried and also to detect
139
general_log_print(thd, command,
140
(thd->main_security_ctx.priv_user ==
141
thd->main_security_ctx.user ?
142
(char*) "%s@%s on %s" :
143
(char*) "%s@%s as anonymous on %s"),
144
thd->main_security_ctx.user,
145
thd->main_security_ctx.host_or_ip,
146
db ? db : (char*) "");
149
This is the default access rights for the current database. It's
150
set to 0 here because we don't have an active database yet (and we
151
may not have an active database to set.
153
thd->main_security_ctx.db_access=0;
130
155
/* Change database if necessary */
148
173
started with corresponding variable that is greater then 0.
151
extern "C" unsigned char *get_key_conn(user_conn *buff, size_t *length,
152
bool not_used __attribute__((unused)))
176
extern "C" uchar *get_key_conn(user_conn *buff, size_t *length,
177
my_bool not_used __attribute__((unused)))
154
179
*length= buff->len;
155
return (unsigned char*) buff->user;
180
return (uchar*) buff->user;
159
184
extern "C" void free_user(struct user_conn *uc)
186
my_free((char*) uc,MYF(0));
164
void thd_init_client_charset(THD *thd, uint32_t cs_number)
189
void thd_init_client_charset(THD *thd, uint cs_number)
167
192
Use server character set and collation if
173
198
if (!opt_character_set_client_handshake ||
174
199
!(thd->variables.character_set_client= get_charset(cs_number, MYF(0))) ||
175
!my_strcasecmp(&my_charset_utf8_general_ci,
200
!my_strcasecmp(&my_charset_latin1,
176
201
global_system_variables.character_set_client->name,
177
202
thd->variables.character_set_client->name))
221
246
static int check_connection(THD *thd)
223
248
NET *net= &thd->net;
252
#ifdef SIGNAL_WITH_VIO_CLOSE
253
thd->set_active_vio(net->vio);
256
if (!thd->main_security_ctx.host) // If TCP/IP connection
229
258
char ip[NI_MAXHOST];
231
if (net_peer_addr(net, ip, &thd->peer_port, NI_MAXHOST))
260
if (vio_peer_addr(net->vio, ip, &thd->peer_port, NI_MAXHOST))
233
my_error(ER_BAD_HOST_ERROR, MYF(0), thd->main_security_ctx.ip);
262
my_error(ER_BAD_HOST_ERROR, MYF(0), thd->main_security_ctx.host_or_ip);
236
265
if (!(thd->main_security_ctx.ip= my_strdup(ip,MYF(MY_WME))))
237
266
return 1; /* The error is set by my_strdup(). */
239
net_keepalive(net, true);
267
thd->main_security_ctx.host_or_ip= thd->main_security_ctx.ip;
268
thd->main_security_ctx.host= ip_to_hostname(&net->vio->remote,
270
thd->main_security_ctx.host_or_ip= thd->main_security_ctx.host;
272
else /* Hostname given means that the connection was on a socket */
274
thd->main_security_ctx.host_or_ip= thd->main_security_ctx.host;
275
thd->main_security_ctx.ip= 0;
277
bzero((char*) &net->vio->remote, sizeof(net->vio->remote));
279
vio_keepalive(net->vio, true);
241
uint32_t server_capabilites;
281
ulong server_capabilites;
243
283
/* buff[] needs to big enough to hold the server_version variable */
244
284
char buff[SERVER_VERSION_LENGTH + SCRAMBLE_LENGTH + 64];
250
290
server_capabilites|= CLIENT_COMPRESS;
251
291
#endif /* HAVE_COMPRESS */
253
end= my_stpncpy(buff, server_version, SERVER_VERSION_LENGTH) + 1;
254
int4store((unsigned char*) end, thd->thread_id);
293
end= strnmov(buff, server_version, SERVER_VERSION_LENGTH) + 1;
294
int4store((uchar*) end, thd->thread_id);
257
297
So as check_connection is the only entry point to authorization
270
310
/* write server characteristics: up to 16 bytes allowed */
271
311
end[2]=(char) default_charset_info->number;
272
312
int2store(end+3, thd->server_status);
273
memset(end+5, 0, 13);
275
315
/* write scramble tail */
276
316
end= strmake(end, thd->scramble + SCRAMBLE_LENGTH_323,
277
317
SCRAMBLE_LENGTH - SCRAMBLE_LENGTH_323) + 1;
279
319
/* At this point we write connection message and read reply */
280
if (net_write_command(net, (unsigned char) protocol_version, (unsigned char*) "", 0,
281
(unsigned char*) buff, (size_t) (end-buff)) ||
320
if (net_write_command(net, (uchar) protocol_version, (uchar*) "", 0,
321
(uchar*) buff, (size_t) (end-buff)) ||
282
322
(pkt_len= my_net_read(net)) == packet_error ||
283
323
pkt_len < MIN_HANDSHAKE_SIZE)
285
325
my_error(ER_HANDSHAKE_ERROR, MYF(0),
286
thd->main_security_ctx.ip);
326
thd->main_security_ctx.host_or_ip);
330
#ifdef _CUSTOMCONFIG_
331
#include "_cust_sql_parse.h"
290
333
if (thd->packet.alloc(thd->variables.net_buffer_length))
291
334
return 1; /* The error is set by alloc(). */
293
336
thd->client_capabilities= uint2korr(net->read_pos);
296
thd->client_capabilities|= ((uint32_t) uint2korr(net->read_pos+2)) << 16;
297
thd->max_client_packet_length= uint4korr(net->read_pos+4);
298
thd_init_client_charset(thd, (uint) net->read_pos[8]);
299
thd->update_charset();
300
end= (char*) net->read_pos+32;
337
if (thd->client_capabilities & CLIENT_PROTOCOL_41)
339
thd->client_capabilities|= ((ulong) uint2korr(net->read_pos+2)) << 16;
340
thd->max_client_packet_length= uint4korr(net->read_pos+4);
341
thd_init_client_charset(thd, (uint) net->read_pos[8]);
342
thd->update_charset();
343
end= (char*) net->read_pos+32;
347
thd->max_client_packet_length= uint3korr(net->read_pos+2);
348
end= (char*) net->read_pos+5;
303
351
Disable those bits which are not supported by the server.
304
352
This is a precautionary measure, if the client lies. See Bug#27944.
306
354
thd->client_capabilities&= server_capabilites;
356
if (thd->client_capabilities & CLIENT_IGNORE_SPACE)
357
thd->variables.sql_mode|= MODE_IGNORE_SPACE;
308
359
if (end >= (char*) net->read_pos+ pkt_len +2)
311
my_error(ER_HANDSHAKE_ERROR, MYF(0), thd->main_security_ctx.ip);
362
my_error(ER_HANDSHAKE_ERROR, MYF(0), thd->main_security_ctx.host_or_ip);
319
370
net->return_status= &thd->server_status;
322
char *passwd= strchr(user, '\0')+1;
323
uint32_t user_len= passwd - user - 1;
373
char *passwd= strend(user)+1;
374
uint user_len= passwd - user - 1;
324
375
char *db= passwd;
325
376
char db_buff[NAME_LEN + 1]; // buffer to store db in utf8
326
377
char user_buff[USERNAME_LENGTH + 1]; // buffer to store user in utf8
327
uint32_t dummy_errors;
330
381
Old clients send null-terminated string as password; new clients send
336
387
Cast *passwd to an unsigned char, so that it doesn't extend the sign for
337
388
*passwd > 127 and become 2**32-127+ after casting to uint.
339
uint32_t passwd_len= thd->client_capabilities & CLIENT_SECURE_CONNECTION ?
340
(unsigned char)(*passwd++) : strlen(passwd);
390
uint passwd_len= thd->client_capabilities & CLIENT_SECURE_CONNECTION ?
391
(uchar)(*passwd++) : strlen(passwd);
341
392
db= thd->client_capabilities & CLIENT_CONNECT_WITH_DB ?
342
393
db + passwd_len + 1 : 0;
343
394
/* strlen() can't be easily deleted without changing protocol */
344
uint32_t db_len= db ? strlen(db) : 0;
395
uint db_len= db ? strlen(db) : 0;
346
397
if (passwd + passwd_len + db_len > (char *)net->read_pos + pkt_len)
348
my_error(ER_HANDSHAKE_ERROR, MYF(0), thd->main_security_ctx.ip);
399
my_error(ER_HANDSHAKE_ERROR, MYF(0), thd->main_security_ctx.host_or_ip);
375
426
if (thd->main_security_ctx.user)
376
if (thd->main_security_ctx.user)
377
free(thd->main_security_ctx.user);
427
x_free(thd->main_security_ctx.user);
378
428
if (!(thd->main_security_ctx.user= my_strdup(user, MYF(MY_WME))))
379
429
return 1; /* The error is set by my_strdup(). */
380
return check_user(thd, passwd, passwd_len, db, true);
430
return check_user(thd, COM_CONNECT, passwd, passwd_len, db, true);
517
567
sql_print_warning(ER(ER_NEW_ABORTING_CONNECTION),
518
568
thd->thread_id,(thd->db ? thd->db : "unconnected"),
519
569
sctx->user ? sctx->user : "unauthenticated",
520
sctx->ip, "init_connect command failed");
570
sctx->host_or_ip, "init_connect command failed");
521
571
sql_print_warning("%s", thd->main_da.message());
523
thd->set_proc_info(0);
525
575
thd->init_for_queries();