List:Commits« Previous MessageNext Message »
From:Georgi Kodinov Date:July 30 2010 3:45pm
Subject:bzr commit into mysql-next-mr-wl1054 branch (Georgi.Kodinov:2971)
View as plain text  
#At file:///home/kgeorge/mysql/work/wl1054-next-mr/ based on revid:georgi.kodinov@stripped

 2971 Georgi Kodinov	2010-07-30
      WL1054: Addressed code review remarks.
      
      * Taken out the thd object from the mpvio and used mpvio for encapsulation of 
       state data.
      * Fixed a memory leak in handling the external user variable

    modified:
      include/mysql/plugin_auth.h
      sql/sql_acl.cc
      sql/sql_audit.h
      sql/sql_class.cc
      sql/sql_connect.cc
      sql/sql_connect.h
=== modified file 'include/mysql/plugin_auth.h'
--- a/include/mysql/plugin_auth.h	2010-06-04 10:51:12 +0000
+++ b/include/mysql/plugin_auth.h	2010-07-30 15:43:16 +0000
@@ -39,7 +39,7 @@ typedef struct st_mysql_server_auth_info
     User name as sent by the client and shown in USER().
     NULL if the client packet with the user name was not received yet.
   */
-  const char *user_name;
+  char *user_name;
 
   /**
     Length of user_name

=== modified file 'sql/sql_acl.cc'
--- a/sql/sql_acl.cc	2010-07-26 09:08:37 +0000
+++ b/sql/sql_acl.cc	2010-07-30 15:43:16 +0000
@@ -7772,6 +7772,23 @@ get_cached_table_access(GRANT_INTERNAL_I
 #define sslaccept(A,B,C) 1
 #endif
 
+
+class Thd_charset_adapter
+{
+  THD *thd;
+public:
+  Thd_charset_adapter(THD *thd_arg) : thd (thd_arg) {} 
+  bool init_client_charset(uint cs_number)
+  {
+    thd_init_client_charset(thd, cs_number);
+    thd->update_charset();
+    return thd->is_error();
+  }
+
+  CHARSET_INFO *charset() { return thd->charset(); }
+};
+
+
 /**
   The internal version of what plugins know as MYSQL_PLUGIN_VIO,
   basically the context of the authentication session
@@ -7779,8 +7796,7 @@ get_cached_table_access(GRANT_INTERNAL_I
 struct MPVIO_EXT : public MYSQL_PLUGIN_VIO
 {
   MYSQL_SERVER_AUTH_INFO auth_info;
-  THD *thd;
-  ACL_USER *acl_user;       ///< a copy, independent from acl_users array
+  const ACL_USER *acl_user;
   plugin_ref plugin;        ///< what plugin we're under
   LEX_STRING db;            ///< db name from the handshake packet
   /** when restarting a plugin this caches the last client reply */
@@ -7797,21 +7813,51 @@ struct MPVIO_EXT : public MYSQL_PLUGIN_V
   uint connect_errors;      ///< if there were connect errors for this host
   /** when plugin returns a failure this tells us what really happened */
   enum { SUCCESS, FAILURE, RESTART } status;
+
+  /* encapsulation members */
+  ulong client_capabilities;
+  char *scramble;
+  MEM_ROOT *mem_root;
+  struct  rand_struct *rand;
+  my_thread_id  thread_id;
+  uint      *server_status;
+  NET *net;
+  ulong max_client_packet_length;
+  char *priv_user;
+  char *ip;
+  char *host;
+  Thd_charset_adapter *charset_adapter;
+  LEX_STRING acl_user_plugin;
 };
 
+static LEX_STRING *
+make_lex_string_root(MEM_ROOT *mem_root,
+                     LEX_STRING *lex_str, const char* str, uint length,
+                     bool allocate_lex_string)
+{
+  if (allocate_lex_string)
+    if (!(lex_str= (LEX_STRING *)alloc_root(mem_root, sizeof(LEX_STRING))))
+      return 0;
+  if (!(lex_str->str= strmake_root(mem_root, str, length)))
+    return 0;
+  lex_str->length= length;
+  return lex_str;
+}
+
 /**
   a helper function to report an access denied error in all the proper places
 */
-static void login_failed_error(THD *thd, int passwd_used)
+static void login_failed_error(MPVIO_EXT *mpvio, int passwd_used)
 {
+  THD *thd= current_thd;
   if (passwd_used == 2)
   {
     my_error(ER_ACCESS_DENIED_NO_PASSWORD_ERROR, MYF(0),
-             thd->main_security_ctx.user,
-             thd->main_security_ctx.host_or_ip);
+             mpvio->auth_info.user_name,
+             mpvio->auth_info.host_or_ip);
     general_log_print(thd, COM_CONNECT, ER(ER_ACCESS_DENIED_NO_PASSWORD_ERROR),
-                      thd->main_security_ctx.user,
-                      thd->main_security_ctx.host_or_ip);
+                      mpvio->auth_info.user_name,
+                      mpvio->auth_info.host_or_ip);
     /* 
       Log access denied messages to the error log when log-warnings = 2
       so that the overhead of the general query log is not required to track 
@@ -7820,19 +7866,19 @@ static void login_failed_error(THD *thd,
     if (global_system_variables.log_warnings > 1)
     {
       sql_print_warning(ER(ER_ACCESS_DENIED_NO_PASSWORD_ERROR),
-                        thd->main_security_ctx.user,
-                        thd->main_security_ctx.host_or_ip);      
+                        mpvio->auth_info.user_name,
+                        mpvio->auth_info.host_or_ip);      
     }
   }
   else
   {
     my_error(ER_ACCESS_DENIED_ERROR, MYF(0),
-             thd->main_security_ctx.user,
-             thd->main_security_ctx.host_or_ip,
+             mpvio->auth_info.user_name,
+             mpvio->auth_info.host_or_ip,
              passwd_used ? ER(ER_YES) : ER(ER_NO));
     general_log_print(thd, COM_CONNECT, ER(ER_ACCESS_DENIED_ERROR),
-                      thd->main_security_ctx.user,
-                      thd->main_security_ctx.host_or_ip,
+                      mpvio->auth_info.user_name,
+                      mpvio->auth_info.host_or_ip,
                       passwd_used ? ER(ER_YES) : ER(ER_NO));
     /* 
       Log access denied messages to the error log when log-warnings = 2
@@ -7842,8 +7888,8 @@ static void login_failed_error(THD *thd,
     if (global_system_variables.log_warnings > 1)
     {
       sql_print_warning(ER(ER_ACCESS_DENIED_ERROR),
-                        thd->main_security_ctx.user,
-                        thd->main_security_ctx.host_or_ip,
+                        mpvio->auth_info.user_name,
+                        mpvio->auth_info.host_or_ip,
                         passwd_used ? ER(ER_YES) : ER(ER_NO));      
     }
   }
@@ -7880,7 +7926,6 @@ static bool send_server_handshake_packet
   DBUG_ASSERT(mpvio->status == MPVIO_EXT::FAILURE);
   DBUG_ASSERT(data_len <= 255);
 
-  THD *thd= mpvio->thd;
   char *buff= (char *)my_alloca(1 + SERVER_VERSION_LENGTH + data_len + 64);
   char scramble_buf[SCRAMBLE_LENGTH];
   char *end= buff;
@@ -7888,11 +7933,23 @@ static bool send_server_handshake_packet
   DBUG_ENTER ("send_server_handshake_packet");
   *end++= protocol_version;
 
-  thd->client_capabilities= CLIENT_BASIC_FLAGS;
+  mpvio->client_capabilities= CLIENT_BASIC_FLAGS;
+
+  if (opt_using_transactions)
+    mpvio->client_capabilities|= CLIENT_TRANSACTIONS;
+
+  mpvio->client_capabilities|= CAN_CLIENT_COMPRESS;
+
+  if (ssl_acceptor_fd)
+  {
+    mpvio->client_capabilities |= CLIENT_SSL;
+    mpvio->client_capabilities |= CLIENT_SSL_VERIFY_SERVER_CERT;
+  }
 
   if (data_len)
   {
-    mpvio->cached_server_packet.pkt= (char*)thd->memdup(data, data_len);
+    mpvio->cached_server_packet.pkt= (char*)memdup_root(mpvio->mem_root, 
+                                                        data, data_len);
     mpvio->cached_server_packet.pkt_len= data_len;
   }
 
@@ -7918,25 +7975,14 @@ static bool send_server_handshake_packet
         native_password_plugin will have to send it in a separate packet,
         adding one more round trip.
       */
-      create_random_string(thd->scramble, SCRAMBLE_LENGTH, &thd->rand);
-      data= thd->scramble;
+      create_random_string(mpvio->scramble, SCRAMBLE_LENGTH, mpvio->rand);
+      data= mpvio->scramble;
     }
     data_len= SCRAMBLE_LENGTH;
   }
 
-  if (opt_using_transactions)
-    thd->client_capabilities|= CLIENT_TRANSACTIONS;
-
-  thd->client_capabilities|= CAN_CLIENT_COMPRESS;
-
-  if (ssl_acceptor_fd)
-  {
-    thd->client_capabilities |= CLIENT_SSL;
-    thd->client_capabilities |= CLIENT_SSL_VERIFY_SERVER_CERT;
-  }
-
   end= strnmov(end, server_version, SERVER_VERSION_LENGTH) + 1;
-  int4store((uchar*) end, mpvio->thd->thread_id);
+  int4store((uchar*) end, mpvio->thread_id);
   end+= 4;
 
   /*
@@ -7948,11 +7994,11 @@ static bool send_server_handshake_packet
   end+= SCRAMBLE_LENGTH_323;
   *end++= 0;
  
-  int2store(end, thd->client_capabilities);
+  int2store(end, mpvio->client_capabilities);
   /* write server characteristics: up to 16 bytes allowed */
   end[2]=(char) default_charset_info->number;
-  int2store(end+3, mpvio->thd->server_status);
-  int2store(end+5, thd->client_capabilities >> 16);
+  int2store(end+3, mpvio->server_status[0]);
+  int2store(end+5, mpvio->client_capabilities >> 16);
   end[7]= data_len;
   bzero(end+8, 10);
   end+= 18;
@@ -7963,28 +8009,31 @@ static bool send_server_handshake_packet
   end= strmake(end, plugin_name(mpvio->plugin)->str,
                     plugin_name(mpvio->plugin)->length);
 
-  int res= my_net_write(&mpvio->thd->net, (uchar*) buff, (size_t) (end-buff)) ||
-           net_flush(&mpvio->thd->net);
+  int res= my_net_write(mpvio->net, (uchar*) buff, (size_t) (end-buff)) ||
+           net_flush(mpvio->net);
   my_afree(buff);
   DBUG_RETURN (res);
 }
 
-static bool secure_auth(THD *thd)
+static bool secure_auth(MPVIO_EXT *mpvio)
 {
+  THD *thd;
   if (!opt_secure_auth)
     return 0;
   /*
     If the server is running in secure auth mode, short scrambles are 
     forbidden. Extra juggling to report the same error as the old code.
   */
-  if (thd->client_capabilities & CLIENT_PROTOCOL_41)
+
+  thd= current_thd;
+  if (mpvio->client_capabilities & CLIENT_PROTOCOL_41)
   {
     my_error(ER_SERVER_IS_IN_SECURE_AUTH_MODE, MYF(0),
-             thd->security_ctx->user,
-             thd->security_ctx->host_or_ip);
+             mpvio->auth_info.user_name,
+             mpvio->auth_info.host_or_ip);
     general_log_print(thd, COM_CONNECT, ER(ER_SERVER_IS_IN_SECURE_AUTH_MODE),
-                      thd->security_ctx->user,
-                      thd->security_ctx->host_or_ip);
+                      mpvio->auth_info.user_name,
+                      mpvio->auth_info.host_or_ip);
   }
   else
   {
@@ -8020,7 +8069,7 @@ static bool send_plugin_request_packet(M
 {
   DBUG_ASSERT(mpvio->packets_written == 1);
   DBUG_ASSERT(mpvio->packets_read == 1);
-  NET *net= &mpvio->thd->net;
+  NET *net= mpvio->net;
   static uchar switch_plugin_request_buf[]= { 254 };
 
   DBUG_ENTER ("send_plugin_request_packet");
@@ -8045,7 +8094,7 @@ static bool send_plugin_request_packet(M
     client_auth_plugin == old_password_plugin_name.str;
 
   if (switch_from_long_to_short_scramble)
-    DBUG_RETURN (secure_auth(mpvio->thd) ||
+    DBUG_RETURN (secure_auth(mpvio) ||
                  my_net_write(net, switch_plugin_request_buf, 1) ||
                  net_flush(net));
 
@@ -8061,7 +8110,7 @@ static bool send_plugin_request_packet(M
   if (switch_from_short_to_long_scramble)
   {
     my_error(ER_NOT_SUPPORTED_AUTH_MODE, MYF(0));
-    general_log_print(mpvio->thd, COM_CONNECT, ER(ER_NOT_SUPPORTED_AUTH_MODE));
+    general_log_print(current_thd, COM_CONNECT, ER(ER_NOT_SUPPORTED_AUTH_MODE));
     DBUG_RETURN (1);
   }
 
@@ -8086,19 +8135,28 @@ static bool send_plugin_request_packet(M
    @retval 0    found
    @retval 1    not found
 */
-static bool find_mpvio_user(MPVIO_EXT *mpvio, Security_context *sctx)
+static bool find_mpvio_user(MPVIO_EXT *mpvio)
 {
   DBUG_ENTER ("find_mpvio_user");
-  DBUG_PRINT ("info", ("entry: %s", sctx->user));
+  DBUG_PRINT ("info", ("entry: %s", mpvio->auth_info.user_name));
   DBUG_ASSERT(mpvio->acl_user == 0);
   mysql_mutex_lock(&acl_cache->lock);
   for (uint i=0 ; i < acl_users.elements ; i++)
   {
     ACL_USER *acl_user_tmp= dynamic_element(&acl_users,i,ACL_USER*);
-    if ((!acl_user_tmp->user || !strcmp(sctx->user, acl_user_tmp->user)) &&
-        compare_hostname(&acl_user_tmp->host, sctx->host, sctx->ip))
+    if ((!acl_user_tmp->user || 
+         !strcmp(mpvio->auth_info.user_name, acl_user_tmp->user)) &&
+        compare_hostname(&acl_user_tmp->host, mpvio->host, mpvio->ip))
     {
-      mpvio->acl_user= acl_user_tmp->copy(mpvio->thd->mem_root);
+      mpvio->acl_user= acl_user_tmp->copy(mpvio->mem_root);
+      if (acl_user_tmp->plugin.str == native_password_plugin_name.str ||
+          acl_user_tmp->plugin.str == old_password_plugin_name.str)
+        mpvio->acl_user_plugin= acl_user_tmp->plugin;
+      else
+        make_lex_string_root(mpvio->mem_root, 
+                             &mpvio->acl_user_plugin, 
+                             acl_user_tmp->plugin.str, 
+                             acl_user_tmp->plugin.length, 0);
       break;
     }
   }
@@ -8106,26 +8164,24 @@ static bool find_mpvio_user(MPVIO_EXT *m
 
   if (!mpvio->acl_user)
   {
-    login_failed_error(mpvio->thd, 0);
+    login_failed_error(mpvio, 0);
     DBUG_RETURN (1);
   }
 
   /* user account requires non-default plugin and the client is too old */
   if (mpvio->acl_user->plugin.str != native_password_plugin_name.str &&
       mpvio->acl_user->plugin.str != old_password_plugin_name.str &&
-      !(mpvio->thd->client_capabilities & CLIENT_PLUGIN_AUTH))
+      !(mpvio->client_capabilities & CLIENT_PLUGIN_AUTH))
   {
     DBUG_ASSERT(my_strcasecmp(system_charset_info, mpvio->acl_user->plugin.str,
                               native_password_plugin_name.str));
     DBUG_ASSERT(my_strcasecmp(system_charset_info, mpvio->acl_user->plugin.str,
                               old_password_plugin_name.str));
     my_error(ER_NOT_SUPPORTED_AUTH_MODE, MYF(0));
-    general_log_print(mpvio->thd, COM_CONNECT, ER(ER_NOT_SUPPORTED_AUTH_MODE));
+    general_log_print(current_thd, COM_CONNECT, ER(ER_NOT_SUPPORTED_AUTH_MODE));
     DBUG_RETURN (1);
   }
 
-  mpvio->auth_info.user_name= sctx->user;
-  mpvio->auth_info.user_name_length= (unsigned int) strlen(sctx->user);
   mpvio->auth_info.auth_string= mpvio->acl_user->auth_string.str;
   mpvio->auth_info.auth_string_length= 
     (unsigned long) mpvio->acl_user->auth_string.length;
@@ -8144,9 +8200,7 @@ static bool find_mpvio_user(MPVIO_EXT *m
 /* the packet format is described in send_change_user_packet() */
 static bool parse_com_change_user_packet(MPVIO_EXT *mpvio, uint packet_length)
 {
-  THD *thd= mpvio->thd;
-  NET *net= &thd->net;
-  Security_context *sctx= thd->security_ctx;
+  NET *net= mpvio->net;
 
   char *user= (char*) net->read_pos;
   char *end= user + packet_length;
@@ -8175,7 +8229,7 @@ static bool parse_com_change_user_packet
     Cast *passwd to an unsigned char, so that it doesn't extend the sign for
     *passwd > 127 and become 2**32-127+ after casting to uint.
   */
-  uint passwd_len= (thd->client_capabilities & CLIENT_SECURE_CONNECTION ?
+  uint passwd_len= (mpvio->client_capabilities & CLIENT_SECURE_CONNECTION ?
                     (uchar)(*passwd++) : strlen(passwd));
 
   db+= passwd_len + 1;
@@ -8195,38 +8249,34 @@ static bool parse_com_change_user_packet
 
   if (ptr+1 < end)
   {
-    uint cs_number= uint2korr(ptr);
-    thd_init_client_charset(thd, cs_number);
-    thd->update_charset();
+    if (mpvio->charset_adapter->init_client_charset(uint2korr(ptr)))
+      DBUG_RETURN(1);
   }
 
+
   /* Convert database and user names to utf8 */
   db_len= copy_and_convert(db_buff, sizeof(db_buff)-1, system_charset_info,
-                           db, db_len, thd->charset(), &dummy_errors);
+                           db, db_len, mpvio->charset_adapter->charset(), 
+                           &dummy_errors);
   db_buff[db_len]= 0;
 
   user_len= copy_and_convert(user_buff, sizeof(user_buff)-1,
                                   system_charset_info, user, user_len,
-                                  thd->charset(), &dummy_errors);
+                                  mpvio->charset_adapter->charset(), 
+                                  &dummy_errors);
   user_buff[user_len]= 0;
 
-  if (!(sctx->user= my_strndup(user_buff, user_len, MYF(MY_WME))))
+  /* we should not free mpvio->user here: it's saved by dispatch_command() */
+  if (!(mpvio->auth_info.user_name= my_strndup(user_buff, user_len, MYF(MY_WME))))
     return 1;
+  mpvio->auth_info.user_name_length= user_len;
 
-  /* Clear variables that are allocated */
-  thd->user_connect= 0;
-  strmake(sctx->priv_user, sctx->user, USERNAME_LENGTH);
+  strmake(mpvio->priv_user, mpvio->auth_info.user_name, USERNAME_LENGTH);
 
-  if (thd->make_lex_string(&mpvio->db, db_buff, db_len, 0) == 0)
+  if (make_lex_string_root(mpvio->mem_root, 
+                           &mpvio->db, db_buff, db_len, 0) == 0)
     DBUG_RETURN (1); /* The error is set by make_lex_string(). */
 
-  /*
-    Clear thd->db as it points to something, that will be freed when
-    connection is closed. We don't want to accidentally free a wrong
-    pointer if connect failed.
-  */
-  thd->reset_db(NULL, 0);
-
   if (!initialized)
   {
     // if mysqld's been started with --skip-grant-tables option
@@ -8235,11 +8285,11 @@ static bool parse_com_change_user_packet
   }
 
 #ifndef NO_EMBEDDED_ACCESS_CHECKS
-  if (find_mpvio_user(mpvio, sctx))
+  if (find_mpvio_user(mpvio))
     DBUG_RETURN (1);
 
   char *client_plugin;
-  if (thd->client_capabilities & CLIENT_PLUGIN_AUTH)
+  if (mpvio->client_capabilities & CLIENT_PLUGIN_AUTH)
   {
     client_plugin= ptr + 2;
     if (client_plugin >= end)
@@ -8250,7 +8300,7 @@ static bool parse_com_change_user_packet
   }
   else
   {
-    if (thd->client_capabilities & CLIENT_SECURE_CONNECTION)
+    if (mpvio->client_capabilities & CLIENT_SECURE_CONNECTION)
       client_plugin= native_password_plugin_name.str;
     else
     {
@@ -8262,7 +8312,7 @@ static bool parse_com_change_user_packet
         and client plugins don't match.
       */
       if (mpvio->acl_user->auth_string.length == 0)
-        mpvio->acl_user->plugin= old_password_plugin_name;
+        mpvio->acl_user_plugin= old_password_plugin_name;
     }
   }
 
@@ -8285,8 +8335,7 @@ static ulong parse_client_handshake_pack
                                            uchar **buff, ulong pkt_len)
 {
 #ifndef EMBEDDED_LIBRARY
-  THD *thd= mpvio->thd;
-  NET *net= &thd->net;
+  NET *net= mpvio->net;
   char *end;
 
   DBUG_ASSERT(mpvio->status == MPVIO_EXT::FAILURE);
@@ -8295,33 +8344,31 @@ static ulong parse_client_handshake_pack
     return packet_error;
 
   if (mpvio->connect_errors)
-    reset_host_errors(thd->main_security_ctx.ip);
+    reset_host_errors(mpvio->ip);
 
   ulong client_capabilities= uint2korr(net->read_pos);
   if (client_capabilities & CLIENT_PROTOCOL_41)
   {
     client_capabilities|= ((ulong) uint2korr(net->read_pos+2)) << 16;
-    thd->max_client_packet_length= uint4korr(net->read_pos+4);
+    mpvio->max_client_packet_length= uint4korr(net->read_pos+4);
     DBUG_PRINT("info", ("client_character_set: %d", (uint) net->read_pos[8]));
-    thd_init_client_charset(thd, (uint) net->read_pos[8]);
-    thd->update_charset();
+    if (mpvio->charset_adapter->init_client_charset((uint) net->read_pos[8]))
+      return packet_error;
     end= (char*) net->read_pos+32;
   }
   else
   {
-    thd->max_client_packet_length= uint3korr(net->read_pos+2);
+    mpvio->max_client_packet_length= uint3korr(net->read_pos+2);
     end= (char*) net->read_pos+5;
   }
 
   /* Disable those bits which are not supported by the client. */
-  thd->client_capabilities&= client_capabilities;
+  mpvio->client_capabilities&= client_capabilities;
 
-  if (thd->client_capabilities & CLIENT_IGNORE_SPACE)
-    thd->variables.sql_mode|= MODE_IGNORE_SPACE;
 
 #if defined(HAVE_OPENSSL)
-  DBUG_PRINT("info", ("client capabilities: %lu", thd->client_capabilities));
-  if (thd->client_capabilities & CLIENT_SSL)
+  DBUG_PRINT("info", ("client capabilities: %lu", mpvio->client_capabilities));
+  if (mpvio->client_capabilities & CLIENT_SSL)
   {
     char error_string[1024] __attribute__((unused));
 
@@ -8350,11 +8397,9 @@ static ulong parse_client_handshake_pack
   if (end >= (char*) net->read_pos+ pkt_len +2)
     return packet_error;
 
-  if (thd->client_capabilities & CLIENT_INTERACTIVE)
-    thd->variables.net_wait_timeout= thd->variables.net_interactive_timeout;
-  if ((thd->client_capabilities & CLIENT_TRANSACTIONS) &&
+  if ((mpvio->client_capabilities & CLIENT_TRANSACTIONS) &&
       opt_using_transactions)
-    net->return_status= &thd->server_status;
+    net->return_status= mpvio->server_status;
 
   char *user= end;
   char *passwd= strend(user)+1;
@@ -8374,10 +8419,10 @@ static ulong parse_client_handshake_pack
     Cast *passwd to an unsigned char, so that it doesn't extend the sign for
     *passwd > 127 and become 2**32-127+ after casting to uint.
   */
-  uint passwd_len= thd->client_capabilities & CLIENT_SECURE_CONNECTION ?
+  uint passwd_len= mpvio->client_capabilities & CLIENT_SECURE_CONNECTION ?
                    (uchar)(*passwd++) : strlen(passwd);
   
-  if (thd->client_capabilities & CLIENT_CONNECT_WITH_DB)
+  if (mpvio->client_capabilities & CLIENT_CONNECT_WITH_DB)
   {
     db= db + passwd_len + 1;
     /* strlen() can't be easily deleted without changing protocol */
@@ -8398,14 +8443,16 @@ static ulong parse_client_handshake_pack
   if (db)
   {
     db_len= copy_and_convert(db_buff, sizeof(db_buff)-1, system_charset_info,
-                             db, db_len, thd->charset(), &dummy_errors);
+                             db, db_len, mpvio->charset_adapter->charset(), 
+                             &dummy_errors);
     db= db_buff;
     db_buff[db_len]= 0;
   }
 
   user_len= copy_and_convert(user_buff, sizeof(user_buff)-1,
                                 system_charset_info, user, user_len,
-                                thd->charset(), &dummy_errors);
+                                mpvio->charset_adapter->charset(), 
+                                &dummy_errors);
   user= user_buff;
   user_buff[user_len]= 0;
 
@@ -8417,21 +8464,14 @@ static ulong parse_client_handshake_pack
     user_len-= 2;
   }
 
-  Security_context *sctx= thd->security_ctx;
-
-  if (thd->make_lex_string(&mpvio->db, db, db_len, 0) == 0)
+  if (make_lex_string_root(mpvio->mem_root, 
+                           &mpvio->db, db, db_len, 0) == 0)
     return packet_error; /* The error is set by make_lex_string(). */
-  if (sctx->user)
-    my_free(sctx->user);
-  if (!(sctx->user= my_strndup(user, user_len, MYF(MY_WME))))
+  if (mpvio->auth_info.user_name)
+    my_free(mpvio->auth_info.user_name);
+  if (!(mpvio->auth_info.user_name= my_strndup(user, user_len, MYF(MY_WME))))
     return packet_error; /* The error is set by my_strdup(). */
-
-  /*
-    Clear thd->db as it points to something, that will be freed when
-    connection is closed. We don't want to accidentally free a wrong
-    pointer if connect failed.
-  */
-  thd->reset_db(NULL, 0);
+  mpvio->auth_info.user_name_length= user_len;
 
   if (!initialized)
   {
@@ -8440,10 +8480,10 @@ static ulong parse_client_handshake_pack
     return packet_error;
   }
 
-  if (find_mpvio_user(mpvio, sctx))
+  if (find_mpvio_user(mpvio))
     return packet_error;
 
-  if (thd->client_capabilities & CLIENT_PLUGIN_AUTH)
+  if (mpvio->client_capabilities & CLIENT_PLUGIN_AUTH)
   {
     if ((client_plugin + strlen(client_plugin)) > 
           (char *)net->read_pos + pkt_len)
@@ -8451,7 +8491,7 @@ static ulong parse_client_handshake_pack
   }
   else
   {
-    if (thd->client_capabilities & CLIENT_SECURE_CONNECTION)
+    if (mpvio->client_capabilities & CLIENT_SECURE_CONNECTION)
       client_plugin= native_password_plugin_name.str;
     else
     {
@@ -8463,7 +8503,7 @@ static ulong parse_client_handshake_pack
         and client plugins don't match.
       */
       if (mpvio->acl_user->auth_string.length == 0)
-        mpvio->acl_user->plugin= old_password_plugin_name;
+        mpvio->acl_user_plugin= old_password_plugin_name;
     }
   }
   
@@ -8476,7 +8516,7 @@ static ulong parse_client_handshake_pack
     restarted and a server auth plugin will read the data that the client
     has just send. Cache them to return in the next server_mpvio_read_packet().
   */
-  if (my_strcasecmp(system_charset_info, mpvio->acl_user->plugin.str,
+  if (my_strcasecmp(system_charset_info, mpvio->acl_user_plugin.str,
                     plugin_name(mpvio->plugin)->str) != 0)
   {
     mpvio->cached_client_reply.pkt= passwd;
@@ -8504,8 +8544,8 @@ static ulong parse_client_handshake_pack
                                    mpvio->cached_server_packet.pkt_len))
       return packet_error;
 
-    passwd_len= my_net_read(&mpvio->thd->net);
-    passwd = (char*)mpvio->thd->net.read_pos;
+    passwd_len= my_net_read(mpvio->net);
+    passwd = (char*)mpvio->net->read_pos;
   }
 
   *buff= (uchar*)passwd;
@@ -8547,13 +8587,13 @@ static int server_mpvio_write_packet(MYS
       We'll escape these bytes with \1. Consequently, we
       have to escape \1 byte too.
     */
-    res= net_write_command(&mpvio->thd->net, 1, (uchar*)"", 0,
+    res= net_write_command(mpvio->net, 1, (uchar*)"", 0,
                            packet, packet_len);
   }
   else
   {
-    res= my_net_write(&mpvio->thd->net, packet, packet_len) ||
-         net_flush(&mpvio->thd->net);
+    res= my_net_write(mpvio->net, packet, packet_len) ||
+         net_flush(mpvio->net);
   }
   mpvio->packets_written++;
   DBUG_RETURN (res);
@@ -8584,7 +8624,7 @@ static int server_mpvio_read_packet(MYSQ
     if (server_mpvio_write_packet(mpvio, 0, 0))
       pkt_len= packet_error;
     else
-      pkt_len= my_net_read(&mpvio->thd->net);
+      pkt_len= my_net_read(mpvio->net);
   }
   else 
   if (mpvio->cached_client_reply.pkt)
@@ -8617,10 +8657,10 @@ static int server_mpvio_read_packet(MYSQ
     if (server_mpvio_write_packet(mpvio, 0, 0))
       pkt_len= packet_error;
     else
-      pkt_len= my_net_read(&mpvio->thd->net);
+      pkt_len= my_net_read(mpvio->net);
   }
   else
-    pkt_len= my_net_read(&mpvio->thd->net);
+    pkt_len= my_net_read(mpvio->net);
 
   if (pkt_len == packet_error)
     goto err;
@@ -8638,16 +8678,15 @@ static int server_mpvio_read_packet(MYSQ
       goto err;
   }
   else
-    *buf = mpvio->thd->net.read_pos;
+    *buf = mpvio->net->read_pos;
 
   DBUG_RETURN ((int)pkt_len);
 
 err:
-  if (mpvio->status == MPVIO_EXT::FAILURE && !mpvio->thd->is_error())
+  if (mpvio->status == MPVIO_EXT::FAILURE)
   {
-    inc_host_errors(mpvio->thd->security_ctx->ip);
-    my_error(ER_HANDSHAKE_ERROR, MYF(0),
-             mpvio->thd->security_ctx->host_or_ip);
+    inc_host_errors(mpvio->ip);
+    my_error(ER_HANDSHAKE_ERROR, MYF(0), mpvio->auth_info.host_or_ip);
   }
   DBUG_RETURN (-1);
 }
@@ -8660,10 +8699,10 @@ static void server_mpvio_info(MYSQL_PLUG
                               MYSQL_PLUGIN_VIO_INFO *info)
 {
   MPVIO_EXT *mpvio= (MPVIO_EXT*)vio;
-  mpvio_info(mpvio->thd->net.vio, info);
+  mpvio_info(mpvio->net->vio, info);
 }
 
-static bool acl_check_ssl(THD *thd, ACL_USER *acl_user)
+static bool acl_check_ssl(THD *thd, const ACL_USER *acl_user)
 {
 #if defined(HAVE_OPENSSL)
   Vio *vio=thd->net.vio;
@@ -8769,7 +8808,7 @@ static bool acl_check_ssl(THD *thd, ACL_
 }
 
 
-static int do_auth_once(THD *thd, LEX_STRING *auth_plugin_name,
+static int do_auth_once(THD *thd, const LEX_STRING *auth_plugin_name,
                         MPVIO_EXT *mpvio)
 {
   int res= CR_OK, old_status= MPVIO_EXT::FAILURE;
@@ -8822,6 +8861,49 @@ static int do_auth_once(THD *thd, LEX_ST
 }
 
 
+static void
+server_mpvio_initialize(THD *thd, MPVIO_EXT *mpvio, uint connect_errors,
+                        Thd_charset_adapter *charset_adapter)
+{
+  bzero(mpvio, sizeof(MPVIO_EXT));
+  mpvio->read_packet= server_mpvio_read_packet;
+  mpvio->write_packet= server_mpvio_write_packet;
+  mpvio->info= server_mpvio_info;
+  mpvio->auth_info.host_or_ip= thd->security_ctx->host_or_ip;
+  mpvio->auth_info.host_or_ip_length= 
+    (unsigned int) strlen (thd->security_ctx->host_or_ip);
+  mpvio->auth_info.user_name= thd->security_ctx->user;
+  mpvio->auth_info.user_name_length= thd->security_ctx->user ? 
+    (unsigned int) strlen(thd->security_ctx->user) : 0;
+  mpvio->connect_errors= connect_errors;
+  mpvio->status= MPVIO_EXT::FAILURE;
+
+  mpvio->client_capabilities= thd->client_capabilities;
+  mpvio->mem_root= thd->mem_root;
+  mpvio->scramble= thd->scramble;
+  mpvio->rand= &thd->rand;
+  mpvio->thread_id= thd->thread_id;
+  mpvio->server_status= &thd->server_status;
+  mpvio->net= &thd->net;
+  mpvio->priv_user= thd->security_ctx->priv_user;
+  mpvio->ip= thd->security_ctx->ip;
+  mpvio->host= thd->security_ctx->host;
+  mpvio->charset_adapter= charset_adapter;
+}
+
+
+static void
+server_mpvio_update_thd(THD *thd, MPVIO_EXT *mpvio)
+{
+  thd->client_capabilities= mpvio->client_capabilities;
+  thd->max_client_packet_length= mpvio->max_client_packet_length;
+  if (mpvio->client_capabilities & CLIENT_INTERACTIVE)
+    thd->variables.net_wait_timeout= thd->variables.net_interactive_timeout;
+  thd->security_ctx->user= mpvio->auth_info.user_name;
+  if (thd->client_capabilities & CLIENT_IGNORE_SPACE)
+    thd->variables.sql_mode|= MODE_IGNORE_SPACE;
+}
+
 /**
   Perform the handshake, authorize the client and update thd sctx variables.
 
@@ -8841,32 +8923,39 @@ acl_authenticate(THD *thd, uint connect_
 {
   int res= CR_OK;
   MPVIO_EXT mpvio;
-  LEX_STRING *auth_plugin_name= default_auth_plugin_name;
+  Thd_charset_adapter charset_adapter(thd);
+
+  const LEX_STRING *auth_plugin_name= default_auth_plugin_name;
   enum  enum_server_command command= com_change_user_pkt_len ? COM_CHANGE_USER
                                                              : COM_CONNECT;
 
   DBUG_ENTER ("acl_authenticate");
   compile_time_assert(MYSQL_USERNAME_LENGTH == USERNAME_LENGTH);
 
-  bzero(&mpvio, sizeof(mpvio));
-  mpvio.read_packet= server_mpvio_read_packet;
-  mpvio.write_packet= server_mpvio_write_packet;
-  mpvio.info= server_mpvio_info;
-  mpvio.thd= thd;
-  mpvio.auth_info.host_or_ip= thd->main_security_ctx.host_or_ip;
-  mpvio.auth_info.host_or_ip_length= 
-    (unsigned int) strlen (thd->main_security_ctx.host_or_ip);
-  mpvio.connect_errors= connect_errors;
-  mpvio.status= MPVIO_EXT::FAILURE;
+  server_mpvio_initialize(thd, &mpvio, connect_errors, &charset_adapter);
 
   DBUG_PRINT ("info", ("com_change_user_pkt_len=%u", com_change_user_pkt_len));
+
+  /*
+    Clear thd->db as it points to something, that will be freed when
+    connection is closed. We don't want to accidentally free a wrong
+    pointer if connect failed.
+  */
+  thd->reset_db(NULL, 0);
+
   if (command == COM_CHANGE_USER)
   {
     mpvio.packets_written++; // pretend that a server handshake packet was sent
     mpvio.packets_read++;    // take COM_CHANGE_USER packet into account
 
+    /* Clear variables that are allocated */
+    thd->user_connect= 0;
+
     if (parse_com_change_user_packet(&mpvio, com_change_user_pkt_len))
+    {
+      server_mpvio_update_thd(thd, &mpvio);
       DBUG_RETURN(1);
+    }
 
     DBUG_ASSERT(mpvio.status == MPVIO_EXT::RESTART ||
                 mpvio.status == MPVIO_EXT::SUCCESS);
@@ -8874,7 +8963,7 @@ acl_authenticate(THD *thd, uint connect_
   else
   {
     /* mark the thd as having no scramble yet */
-    thd->scramble[SCRAMBLE_LENGTH]= 1;
+    mpvio.scramble[SCRAMBLE_LENGTH]= 1;
     
     /*
      perform the first authentication attempt, with the default plugin.
@@ -8883,7 +8972,7 @@ acl_authenticate(THD *thd, uint connect_
      the correct plugin.
     */
 
-    res= do_auth_once (thd, auth_plugin_name, &mpvio);  
+    res= do_auth_once(thd, auth_plugin_name, &mpvio);  
   }
 
   /*
@@ -8900,8 +8989,10 @@ acl_authenticate(THD *thd, uint connect_
     res= do_auth_once (thd, auth_plugin_name, &mpvio);
   }
 
+  server_mpvio_update_thd(thd, &mpvio);
+
   Security_context *sctx= thd->security_ctx;
-  ACL_USER *acl_user= mpvio.acl_user;
+  const ACL_USER *acl_user= mpvio.acl_user;
 
   thd->password= mpvio.auth_info.password_used;  // remember for error messages 
 
@@ -8911,18 +9002,19 @@ acl_authenticate(THD *thd, uint connect_
 
     if sctx->user is unset it's protocol failure, bad packet.
   */
-  if (sctx->user)
+  if (mpvio.auth_info.user_name)
   {
-    if (strcmp(sctx->priv_user, sctx->user))
+    if (strcmp(mpvio.auth_info.authenticated_as, mpvio.auth_info.user_name))
     {
       general_log_print(thd, command, "%s@%s as %s on %s",
-                        sctx->user, sctx->host_or_ip,
-                        sctx->priv_user[0] ? sctx->priv_user : "anonymous",
+                        mpvio.auth_info.user_name, mpvio.auth_info.host_or_ip,
+                        mpvio.auth_info.authenticated_as ? 
+                          mpvio.auth_info.authenticated_as : "anonymous",
                         mpvio.db.str ? mpvio.db.str : (char*) "");
     }
     else
       general_log_print(thd, command, (char*) "%s@%s on %s",
-                        sctx->user, sctx->host_or_ip,
+                        mpvio.auth_info.user_name, mpvio.auth_info.host_or_ip,
                         mpvio.db.str ? mpvio.db.str : (char*) "");
   }
 
@@ -8931,7 +9023,7 @@ acl_authenticate(THD *thd, uint connect_
     DBUG_ASSERT(mpvio.status == MPVIO_EXT::FAILURE);
 
     if (!thd->is_error())
-      login_failed_error(thd, thd->password);
+      login_failed_error(&mpvio, mpvio.auth_info.password_used);
     DBUG_RETURN (1);
   }
 
@@ -8943,19 +9035,19 @@ acl_authenticate(THD *thd, uint connect_
     bool is_proxy_user= FALSE;
     const char *auth_user = mpvio.acl_user->user ? mpvio.acl_user->user : "";
     /* check if the user is allowed to proxy as another user */
-    if (acl_find_proxy_user (auth_user, sctx->host, sctx->ip, 
-                              mpvio.auth_info.authenticated_as,
-                              &is_proxy_user))
+    if (acl_find_proxy_user(auth_user, sctx->host, sctx->ip, 
+                            mpvio.auth_info.authenticated_as,
+                            &is_proxy_user))
     {
       if (!thd->is_error())
-        login_failed_error(thd, thd->password);
+        login_failed_error(&mpvio, mpvio.auth_info.password_used);
       DBUG_RETURN(1);
     }
 
     if (is_proxy_user)
-      my_snprintf (sctx->proxy_user, sizeof (sctx->proxy_user) - 1,
-                   "'%s'@'%s'", auth_user,
-                   acl_user->host.hostname ? acl_user->host.hostname : "");
+      my_snprintf(sctx->proxy_user, sizeof (sctx->proxy_user) - 1,
+                  "'%s'@'%s'", auth_user,
+                  acl_user->host.hostname ? acl_user->host.hostname : "");
 #endif
 
     sctx->master_access= acl_user->access;
@@ -8973,7 +9065,8 @@ acl_authenticate(THD *thd, uint connect_
     */
     if (acl_check_ssl(thd, acl_user))
     {
-      login_failed_error(thd, thd->password);
+      if (!thd->is_error())
+        login_failed_error(&mpvio, thd->password);
       DBUG_RETURN (1);
     }
 
@@ -9047,7 +9140,7 @@ acl_authenticate(THD *thd, uint connect_
   }
 
   if (mpvio.auth_info.external_user[0])
-    sctx->external_user= my_strdup (mpvio.auth_info.external_user, MYF(0));
+    sctx->external_user= my_strdup(mpvio.auth_info.external_user, MYF(0));
 
   if (res == CR_OK_HANDSHAKE_COMPLETE)
     thd->stmt_da->disable_status();
@@ -9082,16 +9175,15 @@ static int native_password_authenticate(
   uchar *pkt;
   int pkt_len;
   MPVIO_EXT *mpvio=(MPVIO_EXT*)vio;
-  THD *thd=mpvio->thd;
 
   DBUG_ENTER ("native_password_authenticate");
 
   /* generate the scramble, or reuse the old one */
-  if (thd->scramble[SCRAMBLE_LENGTH])
-    create_random_string(thd->scramble, SCRAMBLE_LENGTH, &thd->rand);
+  if (mpvio->scramble[SCRAMBLE_LENGTH])
+    create_random_string(mpvio->scramble, SCRAMBLE_LENGTH, mpvio->rand);
 
   /* send it to the client */
-  if (mpvio->write_packet(mpvio, (uchar*)thd->scramble, SCRAMBLE_LENGTH + 1))
+  if (mpvio->write_packet(mpvio, (uchar*)mpvio->scramble, SCRAMBLE_LENGTH + 1))
     return CR_ERROR;
 
   /* reply and authenticate */
@@ -9149,12 +9241,12 @@ static int native_password_authenticate(
     if (!mpvio->acl_user->salt_len)
       DBUG_RETURN(CR_ERROR);
 
-    DBUG_RETURN (check_scramble(pkt, thd->scramble, mpvio->acl_user->salt) ?
+    DBUG_RETURN (check_scramble(pkt, mpvio->scramble, mpvio->acl_user->salt) ?
                  CR_ERROR : CR_OK);
   }
 
-  inc_host_errors(mpvio->thd->main_security_ctx.ip);
-  my_error(ER_HANDSHAKE_ERROR, MYF(0), thd->main_security_ctx.host_or_ip);
+  inc_host_errors(mpvio->ip);
+  my_error(ER_HANDSHAKE_ERROR, MYF(0), mpvio->auth_info.host_or_ip);
   DBUG_RETURN (CR_ERROR);
 }
 
@@ -9164,14 +9256,13 @@ static int old_password_authenticate(MYS
   uchar *pkt;
   int pkt_len;
   MPVIO_EXT *mpvio=(MPVIO_EXT*)vio;
-  THD *thd=mpvio->thd;
 
   /* generate the scramble, or reuse the old one */
-  if (thd->scramble[SCRAMBLE_LENGTH])
-    create_random_string(thd->scramble, SCRAMBLE_LENGTH, &thd->rand);
+  if (mpvio->scramble[SCRAMBLE_LENGTH])
+    create_random_string(mpvio->scramble, SCRAMBLE_LENGTH, mpvio->rand);
 
   /* send it to the client */
-  if (mpvio->write_packet(mpvio, (uchar*)thd->scramble, SCRAMBLE_LENGTH + 1))
+  if (mpvio->write_packet(mpvio, (uchar*)mpvio->scramble, SCRAMBLE_LENGTH + 1))
     return CR_ERROR;
 
   /* read the reply and authenticate */
@@ -9193,7 +9284,7 @@ static int old_password_authenticate(MYS
   if (pkt_len == 0) /* no password */
     return info->auth_string[0] ? CR_ERROR : CR_OK;
 
-  if (secure_auth(thd))
+  if (secure_auth(mpvio))
     return CR_ERROR;
 
   info->password_used = 1;
@@ -9203,12 +9294,12 @@ static int old_password_authenticate(MYS
     if (!mpvio->acl_user->salt_len)
       return CR_ERROR;
 
-    return check_scramble_323(pkt, thd->scramble,
+    return check_scramble_323(pkt, mpvio->scramble,
                              (ulong *)mpvio->acl_user->salt) ? CR_ERROR : CR_OK;
   }
 
-  inc_host_errors(mpvio->thd->main_security_ctx.ip);
-  my_error(ER_HANDSHAKE_ERROR, MYF(0), thd->main_security_ctx.host_or_ip);
+  inc_host_errors(mpvio->ip);
+  my_error(ER_HANDSHAKE_ERROR, MYF(0), mpvio->auth_info.host_or_ip);
   return CR_ERROR;
 }
 

=== modified file 'sql/sql_audit.h'
--- a/sql/sql_audit.h	2010-07-02 18:15:21 +0000
+++ b/sql/sql_audit.h	2010-07-30 15:43:16 +0000
@@ -40,7 +40,7 @@ static inline uint make_user_name(THD *t
 {
   Security_context *sctx= thd->security_ctx;
   return strxnmov(buf, MAX_USER_HOST_SIZE,
-                  sctx->priv_user ? sctx->priv_user : "", "[",
+                  sctx->priv_user[0] ? sctx->priv_user : "", "[",
                   sctx->user ? sctx->user : "", "] @ ",
                   sctx->host ? sctx->host : "", " [",
                   sctx->ip ? sctx->ip : "", "]", NullS) - buf;

=== modified file 'sql/sql_class.cc'
--- a/sql/sql_class.cc	2010-07-26 09:08:37 +0000
+++ b/sql/sql_class.cc	2010-07-30 15:43:16 +0000
@@ -2952,7 +2952,7 @@ void THD::set_status_var_init()
 
 void Security_context::init()
 {
-  host= user= ip= 0;
+  host= user= ip= external_user= 0;
   host_or_ip= "connecting host";
   priv_user[0]= priv_host[0]= '\0';
   master_access= 0;
@@ -2976,6 +2976,12 @@ void Security_context::destroy()
     user= NULL;
   }
 
+  if (external_user)
+  {
+    my_free(external_user);
+    user= NULL;
+  }
+
   my_free(ip);
   ip= NULL;
 }

=== modified file 'sql/sql_connect.cc'
--- a/sql/sql_connect.cc	2010-07-26 09:08:37 +0000
+++ b/sql/sql_connect.cc	2010-07-30 15:43:16 +0000
@@ -63,7 +63,7 @@ static HASH hash_user_connections;
 
 int get_or_create_user_conn(THD *thd, const char *user,
                             const char *host,
-                            USER_RESOURCES *mqh)
+                            const USER_RESOURCES *mqh)
 {
   int return_val= 0;
   size_t temp_len, user_len;

=== modified file 'sql/sql_connect.h'
--- a/sql/sql_connect.h	2010-07-26 09:08:37 +0000
+++ b/sql/sql_connect.h	2010-07-30 15:43:16 +0000
@@ -41,7 +41,7 @@ int check_user(THD *thd, enum enum_serve
 	       bool check_count);
 
 int get_or_create_user_conn(THD *thd, const char *user,
-                            const char *host, USER_RESOURCES *mqh);
+                            const char *host, const USER_RESOURCES *mqh);
 int check_for_max_user_connections(THD *thd, USER_CONN *uc);
 
 #endif /* SQL_CONNECT_INCLUDED */


Attachment: [text/bzr-bundle] bzr/georgi.kodinov@oracle.com-20100730154316-su90esbjxmnnea91.bundle
Thread
bzr commit into mysql-next-mr-wl1054 branch (Georgi.Kodinov:2971) Georgi Kodinov30 Jul