~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to server/sql_connect.cc

MergingĀ mainline

Show diffs side-by-side

added added

removed removed

Lines of Context:
17
17
/*
18
18
  Functions to autenticate and handle reqests for a connection
19
19
*/
20
 
#include <drizzled/server_includes.h>
21
 
#include <drizzled/authentication.h>
22
 
#include <drizzled/drizzled_error_messages.h>
 
20
 
 
21
#include "mysql_priv.h"
23
22
 
24
23
#define MIN_HANDSHAKE_SIZE      6
25
24
 
70
69
  should be done with this in mind; 'thd' is INOUT, all other params
71
70
  are 'IN'.
72
71
 
73
 
  @retval  0  OK
 
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.
76
76
*/
77
77
 
78
78
int
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,
81
82
           bool check_count)
82
83
{
83
84
  LEX_STRING db_str= { (char *) db, db ? strlen(db) : 0 };
84
 
  bool is_authenticated;
85
85
 
86
86
  /*
87
87
    Clear thd->db as it points to something, that will be freed when
91
91
  */
92
92
  thd->reset_db(NULL, 0);
93
93
 
94
 
  if (passwd_len != 0 && passwd_len != SCRAMBLE_LENGTH)
95
 
  {
96
 
    my_error(ER_HANDSHAKE_ERROR, MYF(0), thd->main_security_ctx.ip);
97
 
    return(1);
98
 
  }
99
 
 
100
 
  is_authenticated= authenticate_user(thd, passwd);
101
 
 
102
 
  if (is_authenticated != true)
103
 
  {
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));
108
 
 
109
 
    return 1;
110
 
  }
111
 
 
 
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);
 
98
 
 
99
  /*
 
100
    If the server is running in secure auth mode, short scrambles are 
 
101
    forbidden.
 
102
  */
 
103
  if (opt_secure_auth_local && passwd_len == SCRAMBLE_LENGTH_323)
 
104
  {
 
105
    my_error(ER_NOT_SUPPORTED_AUTH_MODE, MYF(0));
 
106
    general_log_print(thd, COM_CONNECT, ER(ER_NOT_SUPPORTED_AUTH_MODE));
 
107
    return(1);
 
108
  }
 
109
  if (passwd_len != 0 &&
 
110
      passwd_len != SCRAMBLE_LENGTH &&
 
111
      passwd_len != SCRAMBLE_LENGTH_323)
 
112
  {
 
113
    my_error(ER_HANDSHAKE_ERROR, MYF(0), thd->main_security_ctx.host_or_ip);
 
114
    return(1);
 
115
  }
112
116
 
113
117
  USER_RESOURCES ur;
114
118
  thd->security_ctx->skip_grants();
118
122
  {
119
123
    pthread_mutex_lock(&LOCK_connection_count);
120
124
    bool count_ok= connection_count <= max_connections;
121
 
    pthread_mutex_unlock(&LOCK_connection_count);
 
125
    VOID(pthread_mutex_unlock(&LOCK_connection_count));
122
126
 
123
127
    if (!count_ok)
124
128
    {                                         // too many connections
127
131
    }
128
132
  }
129
133
 
 
134
  /*
 
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
 
137
    break-in attempts.
 
138
  */
 
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*) "");
 
147
 
 
148
  /*
 
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.
 
152
  */
 
153
  thd->main_security_ctx.db_access=0;
 
154
 
130
155
  /* Change database if necessary */
131
156
  if (db && db[0])
132
157
  {
148
173
  started with corresponding variable that is greater then 0.
149
174
*/
150
175
 
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)))
153
178
{
154
179
  *length= buff->len;
155
 
  return (unsigned char*) buff->user;
 
180
  return (uchar*) buff->user;
156
181
}
157
182
 
158
183
 
159
184
extern "C" void free_user(struct user_conn *uc)
160
185
{
161
 
  free((char*) uc);
 
186
  my_free((char*) uc,MYF(0));
162
187
}
163
188
 
164
 
void thd_init_client_charset(THD *thd, uint32_t cs_number)
 
189
void thd_init_client_charset(THD *thd, uint cs_number)
165
190
{
166
191
  /*
167
192
   Use server character set and collation if
172
197
  */
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))
178
203
  {
221
246
static int check_connection(THD *thd)
222
247
{
223
248
  NET *net= &thd->net;
224
 
  uint32_t pkt_len= 0;
 
249
  ulong pkt_len= 0;
225
250
  char *end;
226
251
 
227
 
  // TCP/IP connection
 
252
#ifdef SIGNAL_WITH_VIO_CLOSE
 
253
  thd->set_active_vio(net->vio);
 
254
#endif
 
255
 
 
256
  if (!thd->main_security_ctx.host)         // If TCP/IP connection
228
257
  {
229
258
    char ip[NI_MAXHOST];
230
259
 
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))
232
261
    {
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);
234
263
      return 1;
235
264
    }
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(). */
238
 
  }
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, 
 
269
                                                net->vio->addrLen);
 
270
    thd->main_security_ctx.host_or_ip= thd->main_security_ctx.host;
 
271
  }
 
272
  else /* Hostname given means that the connection was on a socket */
 
273
  {
 
274
    thd->main_security_ctx.host_or_ip= thd->main_security_ctx.host;
 
275
    thd->main_security_ctx.ip= 0;
 
276
    /* Reset sin_addr */
 
277
    bzero((char*) &net->vio->remote, sizeof(net->vio->remote));
 
278
  }
 
279
  vio_keepalive(net->vio, true);
240
280
  
241
 
  uint32_t server_capabilites;
 
281
  ulong server_capabilites;
242
282
  {
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 */
252
292
 
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);
255
295
    end+= 4;
256
296
    /*
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);
 
313
    bzero(end+5, 13);
274
314
    end+= 18;
275
315
    /* write scramble tail */
276
316
    end= strmake(end, thd->scramble + SCRAMBLE_LENGTH_323, 
277
317
                 SCRAMBLE_LENGTH - SCRAMBLE_LENGTH_323) + 1;
278
318
 
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)
284
324
    {
285
325
      my_error(ER_HANDSHAKE_ERROR, MYF(0),
286
 
               thd->main_security_ctx.ip);
 
326
               thd->main_security_ctx.host_or_ip);
287
327
      return 1;
288
328
    }
289
329
  }
 
330
#ifdef _CUSTOMCONFIG_
 
331
#include "_cust_sql_parse.h"
 
332
#endif
290
333
  if (thd->packet.alloc(thd->variables.net_buffer_length))
291
334
    return 1; /* The error is set by alloc(). */
292
335
 
293
336
  thd->client_capabilities= uint2korr(net->read_pos);
294
 
 
295
 
 
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;
301
 
 
 
337
  if (thd->client_capabilities & CLIENT_PROTOCOL_41)
 
338
  {
 
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;
 
344
  }
 
345
  else
 
346
  {
 
347
    thd->max_client_packet_length= uint3korr(net->read_pos+2);
 
348
    end= (char*) net->read_pos+5;
 
349
  }
302
350
  /*
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.
305
353
  */
306
354
  thd->client_capabilities&= server_capabilites;
307
355
 
 
356
  if (thd->client_capabilities & CLIENT_IGNORE_SPACE)
 
357
    thd->variables.sql_mode|= MODE_IGNORE_SPACE;
 
358
 
308
359
  if (end >= (char*) net->read_pos+ pkt_len +2)
309
360
  {
310
361
 
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);
312
363
    return 1;
313
364
  }
314
365
 
319
370
    net->return_status= &thd->server_status;
320
371
 
321
372
  char *user= end;
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;
 
378
  uint dummy_errors;
328
379
 
329
380
  /*
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.
338
389
  */
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;
345
396
 
346
397
  if (passwd + passwd_len + db_len > (char *)net->read_pos + pkt_len)
347
398
  {
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);
349
400
    return 1;
350
401
  }
351
402
 
373
424
  }
374
425
 
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);
381
431
}
382
432
 
383
433
 
475
525
      sql_print_warning(ER(ER_NEW_ABORTING_CONNECTION),
476
526
                        thd->thread_id,(thd->db ? thd->db : "unconnected"),
477
527
                        sctx->user ? sctx->user : "unauthenticated",
478
 
                        sctx->ip,
 
528
                        sctx->host_or_ip,
479
529
                        (thd->main_da.is_error() ? thd->main_da.message() :
480
530
                         ER(ER_UNKNOWN_ERROR)));
481
531
    }
502
552
    TODO: refactor this to avoid code duplication there
503
553
  */
504
554
  thd->version= refresh_version;
505
 
  thd->set_proc_info(0);
 
555
  thd->proc_info= 0;
506
556
  thd->command= COM_SLEEP;
507
557
  thd->set_time();
508
558
  thd->init_for_queries();
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());
522
572
    }
523
 
    thd->set_proc_info(0);
 
573
    thd->proc_info=0;
524
574
    thd->set_time();
525
575
    thd->init_for_queries();
526
576
  }
547
597
pthread_handler_t handle_one_connection(void *arg)
548
598
{
549
599
  THD *thd= (THD*) arg;
550
 
  uint32_t launch_time= (uint32_t) ((thd->thr_create_utime= my_micro_time()) -
 
600
  ulong launch_time= (ulong) ((thd->thr_create_utime= my_micro_time()) -
551
601
                              thd->connect_utime);
552
602
 
553
603
  if (thread_scheduler.init_new_connection_thread())