List:Commits« Previous MessageNext Message »
From:Harin Vadodaria Date:September 18 2012 12:46pm
Subject:bzr push into mysql-trunk-auth branch (harin.vadodaria:4420 to 4421) WL#6486
View as plain text  
 4421 Harin Vadodaria	2012-09-18
      wl#6486 : Refactoring user management code
                (authentication / authorization)
      
      Description : Implementation of Sql_user and
                    Sql_user_implementation classes.

    added:
      sql/auth/sql_authorization.cc
      sql/auth/sql_authorization.h
    modified:
      sql/CMakeLists.txt
      sql/auth/auth_common.h
      sql/auth/sql_acl.cc
      sql/auth/sql_authentication.cc
      sql/auth/sql_authentication.h
      sql/auth/sql_user_table.cc
 4420 Harin Vadodaria	2012-09-18
      wl#6486 : Refactoring user management code
                (authentication / authorization)
      
      Description : Changing tree name

    modified:
      .bzr-mysql/default.conf
=== modified file 'sql/CMakeLists.txt'
--- a/sql/CMakeLists.txt	2012-09-05 11:40:51 +0000
+++ b/sql/CMakeLists.txt	2012-09-18 12:46:18 +0000
@@ -45,6 +45,7 @@ SET(SQL_SHARED_SOURCES
 #  auth/sql_user_table.cc
   auth/sql_user_cache.cc
   auth/sql_authentication.cc
+  auth/sql_authorization.cc
   datadict.cc
   debug_sync.cc
   derror.cc

=== modified file 'sql/auth/auth_common.h'
--- a/sql/auth/auth_common.h	2012-09-06 12:02:23 +0000
+++ b/sql/auth/auth_common.h	2012-09-18 12:46:18 +0000
@@ -180,9 +180,6 @@ uchar* acl_entry_get_key(acl_entry *entr
                                 
 /* ---- */
 
-/* Misc functions not yet categorized  */
-void
-set_user_salt(ACL_USER *acl_user, const char *password, uint password_len);
 #endif // NO_EMBEDDED_ACCESS_CHECKS
 
 /**
@@ -190,7 +187,7 @@ set_user_salt(ACL_USER *acl_user, const
 */
 
 #ifndef NO_EMBEDDED_ACCESS_CHECKS
-extern DYNAMIC_ARRAY acl_users, acl_dbs, acl_proxy_users;
+extern DYNAMIC_ARRAY sql_users, acl_dbs, acl_proxy_users;
 extern hash_filo *acl_cache;
 extern bool initialized;
 extern bool allow_all_hosts;
@@ -205,8 +202,9 @@ extern DYNAMIC_ARRAY acl_wild_hosts;
 
 void optimize_plugin_compare_by_pointer(LEX_STRING *plugin_name);
 #ifndef NO_EMBEDDED_ACCESS_CHECKS
-ACL_USER *find_acl_user(const char *host, const char *user,
-                        my_bool exact);
+class Sql_user_implementation;
+Sql_user_implementation *find_acl_user(const char *host, const char *user,
+                                       my_bool exact);
 #endif
 
 #endif /* AUTH_COMMON_INCLUDED */

=== modified file 'sql/auth/sql_acl.cc'
--- a/sql/auth/sql_acl.cc	2012-09-06 12:02:23 +0000
+++ b/sql/auth/sql_acl.cc	2012-09-18 12:46:18 +0000
@@ -61,6 +61,7 @@
 #endif
 
 #include "auth_common.h"
+#include "sql_authorization.h"
 #include "sql_authentication.h"
 
 using std::min;
@@ -429,7 +430,7 @@ uchar* acl_entry_get_key(acl_entry *entr
 }
 
 
-DYNAMIC_ARRAY acl_users, acl_dbs, acl_proxy_users;
+DYNAMIC_ARRAY sql_users, acl_dbs, acl_proxy_users;
 static MEM_ROOT global_acl_memory, memex;
 bool initialized=0;
 bool allow_all_hosts=1;
@@ -440,6 +441,7 @@ hash_filo *acl_cache;
 
 static ulong get_access(TABLE *form,uint fieldnr, uint *next_field=0);
 static int acl_compare(ACL_ACCESS *a,ACL_ACCESS *b);
+static int sql_user_compare(Sql_user_implementation *a,Sql_user_implementation *b);
 static ulong get_sort(uint count,...);
 static void init_check_host(void);
 static void rebuild_check_host(void);
@@ -458,42 +460,6 @@ static inline void get_grantor(THD *thd,
 #include "sql_user_table.cc" 
 /*************************************************/
 
-/**
-  Convert scrambled password to binary form, according to scramble type, 
-  Binary form is stored in user.salt.
-  
-  @param acl_user The object where to store the salt
-  @param password The password hash containing the salt
-  @param password_len The length of the password hash
-   
-  Despite the name of the function it is used when loading ACLs from disk
-  to store the password hash in the ACL_USER object.
-*/
-
-void
-set_user_salt(ACL_USER *acl_user, const char *password, uint password_len)
-{
-  /* Using old password protocol */
-  if (password_len == SCRAMBLED_PASSWORD_CHAR_LENGTH)
-  {
-    get_salt_from_password(acl_user->salt, password);
-    acl_user->salt_len= SCRAMBLE_LENGTH;
-  }
-  else if (password_len == SCRAMBLED_PASSWORD_CHAR_LENGTH_323)
-  {
-    get_salt_from_password_323((ulong *) acl_user->salt, password);
-    acl_user->salt_len= SCRAMBLE_LENGTH_323;
-  }
-  else
-    acl_user->salt_len= 0;
-
-  /*
-    Since we're changing the password for the user we need to reset the
-    expiration flag.
-  */
-  acl_user->password_expired= false;
-}
-
 /*
   Initialize structures responsible for user/db-level privilege checking and
   load privilege information for them from tables in the 'mysql' database.
@@ -564,7 +530,7 @@ my_bool acl_init(bool dont_read_acl_tabl
 void acl_free(bool end)
 {
   free_root(&global_acl_memory,MYF(0));
-  delete_dynamic(&acl_users);
+  delete_dynamic(&sql_users);
   delete_dynamic(&acl_dbs);
   delete_dynamic(&acl_wild_hosts);
   delete_dynamic(&acl_proxy_users);
@@ -676,7 +642,7 @@ static bool acl_trans_commit_and_close_t
 my_bool acl_reload(THD *thd)
 {
   TABLE_LIST tables[3];
-  DYNAMIC_ARRAY old_acl_users, old_acl_dbs, old_acl_proxy_users;
+  DYNAMIC_ARRAY old_sql_users, old_acl_dbs, old_acl_proxy_users;
   MEM_ROOT old_mem;
   bool old_initialized;
   my_bool return_val= TRUE;
@@ -715,7 +681,7 @@ my_bool acl_reload(THD *thd)
   if ((old_initialized=initialized))
     mysql_mutex_lock(&acl_cache->lock);
 
-  old_acl_users= acl_users;
+  old_sql_users= sql_users;
   old_acl_proxy_users= acl_proxy_users;
   old_acl_dbs= acl_dbs;
   old_mem= global_acl_memory;
@@ -726,7 +692,7 @@ my_bool acl_reload(THD *thd)
   {					// Error. Revert to old list
     DBUG_PRINT("error",("Reverting to old privileges"));
     acl_free();				/* purecov: inspected */
-    acl_users= old_acl_users;
+    sql_users= old_sql_users;
     acl_proxy_users= old_acl_proxy_users;
     acl_dbs= old_acl_dbs;
     global_acl_memory= old_mem;
@@ -735,7 +701,7 @@ my_bool acl_reload(THD *thd)
   else
   {
     free_root(&old_mem,MYF(0));
-    delete_dynamic(&old_acl_users);
+    delete_dynamic(&old_sql_users);
     delete_dynamic(&old_acl_proxy_users);
     delete_dynamic(&old_acl_dbs);
   }
@@ -841,6 +807,17 @@ static int acl_compare(ACL_ACCESS *a,ACL
 }
 
 
+static int sql_user_compare(Sql_user_implementation *a,
+                            Sql_user_implementation *b)
+{
+  if (a->sort() > b->sort())
+    return -1;
+  if (a->sort() < b->sort())
+    return 1;
+  return 0;
+}
+
+
 /*
   Gets user credentials without authentication and resource limit checks.
 
@@ -862,7 +839,7 @@ bool acl_getroot(Security_context *sctx,
 {
   int res= 1;
   uint i;
-  ACL_USER *acl_user= 0;
+  Sql_user *sql_user= 0;
   DBUG_ENTER("acl_getroot");
 
   DBUG_PRINT("enter", ("Host: '%s', Ip: '%s', User: '%s', db: '%s'",
@@ -894,22 +871,25 @@ bool acl_getroot(Security_context *sctx,
      a stored procedure; user is set to what is actually a
      priv_user, which can be ''.
   */
-  for (i=0 ; i < acl_users.elements ; i++)
+  for (i=0 ; i < sql_users.elements ; i++)
   {
-    ACL_USER *acl_user_tmp= dynamic_element(&acl_users,i,ACL_USER*);
-    if ((!acl_user_tmp->user && !user[0]) ||
-        (acl_user_tmp->user && strcmp(user, acl_user_tmp->user) == 0))
+    Sql_user *sql_user_tmp= dynamic_element(&sql_users,i,Sql_user*);
+    const String *user_string= sql_user_tmp->user();
+    if ((!user_string->ptr() && !user[0]) ||
+        (user_string->ptr() &&
+         strcmp(user, user_string->ptr()) == 0))
     {
-      if (acl_user_tmp->host.compare_hostname(host, ip))
+      ACL_HOST_AND_IP *host_ptr= sql_user_tmp->host();
+      if (host_ptr->compare_hostname(host, ip))
       {
-        acl_user= acl_user_tmp;
+        sql_user= sql_user_tmp;
         res= 0;
         break;
       }
     }
   }
 
-  if (acl_user)
+  if (sql_user)
   {
     for (i=0 ; i < acl_dbs.elements ; i++)
     {
@@ -927,29 +907,30 @@ bool acl_getroot(Security_context *sctx,
 	}
       }
     }
-    sctx->master_access= acl_user->access;
+    sctx->master_access= sql_user->global_acl();
 
-    if (acl_user->user)
+    if (sql_user->user()->ptr())
       strmake(sctx->priv_user, user, USERNAME_LENGTH);
     else
       *sctx->priv_user= 0;
 
-    if (acl_user->host.get_host())
-      strmake(sctx->priv_host, acl_user->host.get_host(), MAX_HOSTNAME - 1);
+    if (sql_user->host()->get_host())
+      strmake(sctx->priv_host, sql_user->host()->get_host(), MAX_HOSTNAME - 1);
     else
       *sctx->priv_host= 0;
 
-    sctx->password_expired= acl_user->password_expired;
+    sctx->password_expired= sql_user->password_expired();
   }
   mysql_mutex_unlock(&acl_cache->lock);
   DBUG_RETURN(res);
 }
 
-static uchar* check_get_key(ACL_USER *buff, size_t *length,
+static uchar* check_get_key(Sql_user *buff, size_t *length,
                             my_bool not_used __attribute__((unused)))
 {
-  *length=buff->host.get_host_len();
-  return (uchar*) buff->host.get_host();
+  ACL_HOST_AND_IP *host= buff->host();
+  *length=host->get_host_len();
+  return (uchar*) host->get_host();
 }
 
 
@@ -966,46 +947,49 @@ static void acl_update_user(const char *
 {
   DBUG_ENTER("acl_update_user");
   mysql_mutex_assert_owner(&acl_cache->lock);
-  for (uint i=0 ; i < acl_users.elements ; i++)
+  for (uint i=0 ; i < sql_users.elements ; i++)
   {
-    ACL_USER *acl_user=dynamic_element(&acl_users,i,ACL_USER*);
-    if ((!acl_user->user && !user[0]) ||
-	(acl_user->user && !strcmp(user,acl_user->user)))
-    {
-      if ((!acl_user->host.get_host() && !host[0]) ||
-	  (acl_user->host.get_host() &&
-	  !my_strcasecmp(system_charset_info, host, acl_user->host.get_host())))
+    Sql_user_implementation *sql_user=dynamic_element(&sql_users,i,Sql_user_implementation*);
+    const String *user_string= sql_user->user();
+    ACL_HOST_AND_IP *host_ptr= sql_user->host();
+    if ((!user_string->ptr() && !user[0]) ||
+	(user_string->ptr() && !strcmp(user,user_string->ptr())))
+    {
+      if ((!host_ptr->get_host() && !host[0]) ||
+	  (host_ptr->get_host() &&
+	  !my_strcasecmp(system_charset_info, host, host_ptr->get_host())))
       {
         if (plugin->length > 0)
         {
-          acl_user->plugin.str= strmake_root(&global_acl_memory, plugin->str, plugin->length);
-          acl_user->plugin.length= plugin->length;
-          acl_user->auth_string.str= auth->str ?
-            strmake_root(&global_acl_memory, auth->str,
-                         auth->length) : const_cast<char*>("");
-          acl_user->auth_string.length= auth->length;
+          sql_user->set_authentication_plugin(strmake_root(&global_acl_memory,
+                                                           plugin->str,
+                                                           plugin->length),
+                                                           (uint32)(plugin->length));
+          sql_user->set_authentication_string(auth->str ?
+                                              strmake_root(&global_acl_memory,
+                                                           auth->str, auth->length) :
+                                              const_cast<char*>(""),
+                                              (uint32)(auth->length));
         }
-	acl_user->access=privileges;
-	if (mqh->specified_limits & USER_RESOURCES::QUERIES_PER_HOUR)
-	  acl_user->user_resource.questions=mqh->questions;
-	if (mqh->specified_limits & USER_RESOURCES::UPDATES_PER_HOUR)
-	  acl_user->user_resource.updates=mqh->updates;
-	if (mqh->specified_limits & USER_RESOURCES::CONNECTIONS_PER_HOUR)
-	  acl_user->user_resource.conn_per_hour= mqh->conn_per_hour;
-	if (mqh->specified_limits & USER_RESOURCES::USER_CONNECTIONS)
-	  acl_user->user_resource.user_conn= mqh->user_conn;
+	sql_user->set_global_acl(privileges);
+
+        sql_user->set_user_resources_selective(mqh);
+
 	if (ssl_type != SSL_TYPE_NOT_SPECIFIED)
 	{
-	  acl_user->ssl_type= ssl_type;
-	  acl_user->ssl_cipher= (ssl_cipher ? strdup_root(&global_acl_memory,
-                                                    ssl_cipher) :	0);
-	  acl_user->x509_issuer= (x509_issuer ? strdup_root(&global_acl_memory,
-                                                      x509_issuer) : 0);
-	  acl_user->x509_subject= (x509_subject ?
-				   strdup_root(&global_acl_memory, x509_subject) : 0);
+	  sql_user->set_ssl_authentication_type(ssl_type);
+	  sql_user->set_ssl_cipher((ssl_cipher ?
+                                    strdup_root(&global_acl_memory,
+                                                ssl_cipher) : 0));
+	  sql_user->set_x509_issuer(x509_issuer ?
+                                    strdup_root(&global_acl_memory,
+                                                x509_issuer) : 0);
+	  sql_user->set_x509_subject(x509_subject ?
+				     strdup_root(&global_acl_memory,
+                                                 x509_subject) : 0);
 	}
   if (password)
-          set_user_salt(acl_user, password, password_len);
+          sql_user->set_user_salt(password, password_len);
         /* search complete: */
 	break;
       }
@@ -1027,50 +1011,58 @@ static void acl_insert_user(const char *
 			    const LEX_STRING *auth)
 {
   DBUG_ENTER("acl_insert_user");
-  ACL_USER acl_user;
+  Sql_user_implementation sql_user(&global_acl_memory);
 
   mysql_mutex_assert_owner(&acl_cache->lock);
 
-  acl_user.user= *user ? strdup_root(&global_acl_memory,user) : 0;
-  acl_user.host.update_hostname(*host ? strdup_root(&global_acl_memory, host) : 0);
+  sql_user.set_user(*user ? strdup_root(&global_acl_memory,user) : 0);
+  sql_user.update_hostname(*host ? strdup_root(&global_acl_memory, host) : 0);
   if (plugin->str[0])
   {
-    acl_user.plugin.str= strmake_root(&global_acl_memory, plugin->str, plugin->length);
-    acl_user.plugin.length= plugin->length;
-    acl_user.auth_string.str= auth->str ?
-      strmake_root(&global_acl_memory, auth->str,
-                   auth->length) : const_cast<char*>("");
-    acl_user.auth_string.length= auth->length;
+    sql_user.set_authentication_plugin(strmake_root(&global_acl_memory,
+                                                    plugin->str,
+                                                    plugin->length),
+                                       plugin->length);
+    sql_user.set_authentication_string(auth->str ?
+                                       strmake_root(&global_acl_memory,
+                                                    auth->str, auth->length) :
+                                       const_cast<char*>(""),
+                                       auth->length);
   }
   else
   {
-    acl_user.plugin= password_len == SCRAMBLED_PASSWORD_CHAR_LENGTH_323 ?
-      old_password_plugin_name : native_password_plugin_name;
-    acl_user.auth_string.str= const_cast<char*>("");
-    acl_user.auth_string.length= 0;
-  }
-  acl_user.access= privileges;
-  acl_user.user_resource= *mqh;
-  acl_user.sort= get_sort(2,acl_user.host.get_host(), acl_user.user);
-  //acl_user.hostname_length=(uint) strlen(host);
-  acl_user.ssl_type=
-    (ssl_type != SSL_TYPE_NOT_SPECIFIED ? ssl_type : SSL_TYPE_NONE);
-  acl_user.ssl_cipher=
-    ssl_cipher ? strdup_root(&global_acl_memory, ssl_cipher) : 0;
-  acl_user.x509_issuer=
-    x509_issuer ? strdup_root(&global_acl_memory, x509_issuer) : 0;
-  acl_user.x509_subject=
-    x509_subject ? strdup_root(&global_acl_memory, x509_subject) : 0;
+    if (password_len == SCRAMBLED_PASSWORD_CHAR_LENGTH_323)
+      sql_user.set_authentication_plugin(old_password_plugin_name.str,
+                                         old_password_plugin_name.length);
+    else
+      sql_user.set_authentication_plugin(native_password_plugin_name.str,
+                                         native_password_plugin_name.length);
+    
+    sql_user.set_authentication_string(const_cast<char*>(""), 0);
+  }
+
+  sql_user.set_global_acl(privileges);
+  sql_user.set_user_resources(mqh);
+  sql_user.set_sort(get_sort(2,sql_user.host()->get_host(), sql_user.user()));
+  
+  sql_user.set_ssl_authentication_type(ssl_type != SSL_TYPE_NOT_SPECIFIED ?
+                                       ssl_type : SSL_TYPE_NONE);
+  sql_user.set_ssl_cipher(ssl_cipher ?
+                          strdup_root(&global_acl_memory, ssl_cipher) : 0);
+  sql_user.set_x509_issuer(x509_issuer ?
+                           strdup_root(&global_acl_memory, x509_issuer) : 0);
+  sql_user.set_x509_subject(x509_subject ?
+                            strdup_root(&global_acl_memory, x509_subject) : 0);
 
-  set_user_salt(&acl_user, password, password_len);
+  sql_user.set_user_salt(password, password_len);
 
-  (void) push_dynamic(&acl_users,(uchar*) &acl_user);
-  if (acl_user.host.check_allow_all_hosts())
+  (void) push_dynamic(&sql_users,(uchar*) &sql_user);
+  if (sql_user.host()->check_allow_all_hosts())
     allow_all_hosts=1;		// Anyone can connect /* purecov: tested */
-  my_qsort((uchar*) dynamic_element(&acl_users,0,ACL_USER*),acl_users.elements,
-	   sizeof(ACL_USER),(qsort_cmp) acl_compare);
+  my_qsort((uchar*) dynamic_element(&sql_users,0,Sql_user_implementation*),sql_users.elements,
+	   sizeof(Sql_user_implementation),(qsort_cmp) sql_user_compare);
 
-  /* Rebuild 'acl_check_hosts' since 'acl_users' has been modified */
+  /* Rebuild 'acl_check_hosts' since 'sql_users' has been modified */
   rebuild_check_host();
   DBUG_VOID_RETURN;
 }
@@ -1221,16 +1213,17 @@ static void init_check_host(void)
 {
   DBUG_ENTER("init_check_host");
   (void) my_init_dynamic_array(&acl_wild_hosts,sizeof(class ACL_HOST_AND_IP),
-			  acl_users.elements,1);
+			  sql_users.elements,1);
   (void) my_hash_init(&acl_check_hosts,system_charset_info,
-                      acl_users.elements, 0, 0,
+                      sql_users.elements, 0, 0,
                       (my_hash_get_key) check_get_key, 0, 0);
   if (!allow_all_hosts)
   {
-    for (uint i=0 ; i < acl_users.elements ; i++)
+    for (uint i=0 ; i < sql_users.elements ; i++)
     {
-      ACL_USER *acl_user=dynamic_element(&acl_users,i,ACL_USER*);
-      if (acl_user->host.has_wildcard())
+      Sql_user_implementation *sql_user=dynamic_element(&sql_users,i,Sql_user_implementation*);
+      ACL_HOST_AND_IP *host_ptr= sql_user->host();
+      if (host_ptr->has_wildcard())
       {						// Has wildcard
 	uint j;
 	for (j=0 ; j < acl_wild_hosts.elements ; j++)
@@ -1238,17 +1231,17 @@ static void init_check_host(void)
 	  ACL_HOST_AND_IP *acl=dynamic_element(&acl_wild_hosts,j,
 					       ACL_HOST_AND_IP *);
 	  if (!my_strcasecmp(system_charset_info,
-                             acl_user->host.get_host(), acl->get_host()))
+                             host_ptr->get_host(), acl->get_host()))
 	    break;				// already stored
 	}
 	if (j == acl_wild_hosts.elements)	// If new
-	  (void) push_dynamic(&acl_wild_hosts,(uchar*) &acl_user->host);
+	  (void) push_dynamic(&acl_wild_hosts,(uchar*) host_ptr);
       }
       else if (!my_hash_search(&acl_check_hosts,(uchar*)
-                               acl_user->host.get_host(),
-                               strlen(acl_user->host.get_host())))
+                               host_ptr->get_host(),
+                               strlen(host_ptr->get_host())))
       {
-	if (my_hash_insert(&acl_check_hosts,(uchar*) acl_user))
+	if (my_hash_insert(&acl_check_hosts,(uchar*) sql_user))
 	{					// End of memory
 	  allow_all_hosts=1;			// Should never happen
 	  DBUG_VOID_RETURN;
@@ -1267,8 +1260,9 @@ static void init_check_host(void)
 
   We need to rebuild 'acl_check_hosts' and 'acl_wild_hosts' after adding,
   dropping or renaming user, since they contain pointers to elements of
-  'acl_user' array, which are invalidated by drop operation, and use
-  ACL_USER::host::hostname as a key, which is changed by rename.
+  'Sql_user_implementation' array, which are invalidated by drop operation,
+  and use Sql_user_implementation::m_host::hostname as a key,
+  which is changed by rename.
 */
 void rebuild_check_host(void)
 {
@@ -1392,18 +1386,18 @@ bool change_password(THD *thd, const cha
     thd->clear_current_stmt_binlog_format_row();
 
   mysql_mutex_lock(&acl_cache->lock);
-  ACL_USER *acl_user;
-  if (!(acl_user= find_acl_user(host, user, TRUE)))
+  Sql_user_implementation *sql_user;
+  if (!(sql_user= find_acl_user(host, user, TRUE)))
   {
     mysql_mutex_unlock(&acl_cache->lock);
     my_message(ER_PASSWORD_NO_MATCH, ER(ER_PASSWORD_NO_MATCH), MYF(0));
     goto end;
   }
   
-  if (acl_user->plugin.length == 0)
+  if (sql_user->authentication_plugin()->length() == 0)
   {
-    acl_user->plugin.length= default_auth_plugin_name.length;
-    acl_user->plugin.str= default_auth_plugin_name.str;
+    sql_user->set_authentication_plugin(default_auth_plugin_name.str,
+                                        (uint32)(default_auth_plugin_name.length));
   }
   
 #if defined(HAVE_OPENSSL)
@@ -1412,14 +1406,15 @@ bool change_password(THD *thd, const cha
     TODO Should password depend on @@old_variables here?
     - Probably not if the user exists and have a plugin set already.
   */
-  if (my_strcasecmp(system_charset_info, acl_user->plugin.str,
+  if (my_strcasecmp(system_charset_info,
+                    sql_user->authentication_plugin()->ptr(),
                     sha256_password_plugin_name.str) == 0)
   {
     /*
      Accept empty passwords
     */
     if (new_password_len == 0)
-      acl_user->auth_string= empty_lex_str;
+      sql_user->set_authentication_string(const_cast<char*>(""), 0);
     /*
      Check if password begins with correct magic number
     */
@@ -1431,10 +1426,10 @@ bool change_password(THD *thd, const cha
       if (new_password_len < CRYPT_MAX_PASSWORD_SIZE + 1)
       {
         /* copy string including \0 */
-        acl_user->auth_string.str= (char *) memdup_root(&global_acl_memory,
+        sql_user->set_authentication_string((char *) memdup_root(&global_acl_memory,
                                                        new_password,
-                                                       new_password_len + 1);
-        acl_user->auth_string.length= new_password_len;
+                                                       new_password_len + 1),
+                                             new_password_len);
       }
     } else
     {
@@ -1450,9 +1445,9 @@ bool change_password(THD *thd, const cha
   }
   else
 #endif
-  if (my_strcasecmp(system_charset_info, acl_user->plugin.str,
+  if (my_strcasecmp(system_charset_info, sql_user->authentication_plugin()->ptr(),
                     native_password_plugin_name.str) == 0 ||
-      my_strcasecmp(system_charset_info, acl_user->plugin.str,
+      my_strcasecmp(system_charset_info, sql_user->authentication_plugin()->ptr(),
                     old_password_plugin_name.str) == 0)
   {
     password_field= MYSQL_USER_FIELD_PASSWORD;
@@ -1463,7 +1458,7 @@ bool change_password(THD *thd, const cha
     */
     if (new_password_len != 0)
     {
-      if (my_strcasecmp(system_charset_info, acl_user->plugin.str,
+      if (my_strcasecmp(system_charset_info, sql_user->authentication_plugin()->ptr(),
                         native_password_plugin_name.str) == 0 &&
           new_password_len != SCRAMBLED_PASSWORD_CHAR_LENGTH)
       {
@@ -1473,7 +1468,7 @@ bool change_password(THD *thd, const cha
         goto end;  
       }
       else
-      if (my_strcasecmp(system_charset_info, acl_user->plugin.str,
+      if (my_strcasecmp(system_charset_info, sql_user->authentication_plugin()->ptr(),
                         old_password_plugin_name.str) == 0 &&
           new_password_len != SCRAMBLED_PASSWORD_CHAR_LENGTH_323)
       {
@@ -1486,12 +1481,12 @@ bool change_password(THD *thd, const cha
 
     /*
       Update loaded acl entry in memory.
-      set_user_salt() stores a binary (compact) representation of the password
-      in memory (acl_user->salt and salt_len).
+      sql_user::set_user_salt() stores a binary (compact) representation of the
+      password in memory (sql_user->salt and sql_user->salt_len).
       set_user_plugin() sets the appropriate plugin based on password length and
       if the length doesn't match a warning is issued.
     */
-    set_user_salt(acl_user, new_password, new_password_len);
+    sql_user->set_user_salt(new_password, new_password_len);
     thd->security_ctx->password_expired= false;
   }
   else
@@ -1506,8 +1501,8 @@ bool change_password(THD *thd, const cha
   }
 
   if (update_user_table(thd, table,
-                        acl_user->host.get_host() ? acl_user->host.get_host() : "",
-                        acl_user->user ? acl_user->user : "",
+                        sql_user->host()->get_host() ? sql_user->host()->get_host() : "",
+                        sql_user->user()->ptr() ? sql_user->user()->ptr() : "",
                         new_password, new_password_len, password_field, false))
   {
     mysql_mutex_unlock(&acl_cache->lock); /* purecov: deadcode */
@@ -1518,8 +1513,8 @@ bool change_password(THD *thd, const cha
   mysql_mutex_unlock(&acl_cache->lock);
   result= 0;
   query_length= sprintf(buff, "SET PASSWORD FOR '%-.120s'@'%-.120s'='%-.120s'",
-                        acl_user->user ? acl_user->user : "",
-                        acl_user->host.get_host() ? acl_user->host.get_host() : "",
+                        sql_user->user()->ptr() ? sql_user->user()->ptr() : "",
+                        sql_user->host()->get_host() ? sql_user->host()->get_host() : "",
                         new_password);
   result= write_bin_log(thd, true, buff, query_length,
                         table->file->has_transactions());
@@ -1567,7 +1562,7 @@ bool is_acl_user(const char *host, const
   Find first entry that matches the current user
 */
 
-ACL_USER *
+Sql_user_implementation *
 find_acl_user(const char *host, const char *user, my_bool exact)
 {
   DBUG_ENTER("find_acl_user");
@@ -1575,23 +1570,25 @@ find_acl_user(const char *host, const ch
 
   mysql_mutex_assert_owner(&acl_cache->lock);
 
-  for (uint i=0 ; i < acl_users.elements ; i++)
+  for (uint i=0 ; i < sql_users.elements ; i++)
   {
-    ACL_USER *acl_user=dynamic_element(&acl_users,i,ACL_USER*);
+    Sql_user_implementation *sql_user=dynamic_element(&sql_users,i,Sql_user_implementation*);
+    const String *user_string= sql_user->user();
+    ACL_HOST_AND_IP *host_ptr= sql_user->host();
     DBUG_PRINT("info",("strcmp('%s','%s'), compare_hostname('%s','%s'),",
-                       user, acl_user->user ? acl_user->user : "",
+                       user, user_string->ptr() ? user_string->ptr() : "",
                        host,
-                       acl_user->host.get_host() ? acl_user->host.get_host() :
+                       host_ptr->get_host() ? host_ptr->get_host() :
                        ""));
-    if ((!acl_user->user && !user[0]) ||
-	(acl_user->user && !strcmp(user,acl_user->user)))
+    if ((!user_string->ptr() && !user[0]) ||
+	(user_string->ptr() && !strcmp(user,user_string->ptr())))
     {
       if (exact ? !my_strcasecmp(system_charset_info, host,
-                                 acl_user->host.get_host() ?
-				 acl_user->host.get_host() : "") :
-          acl_user->host.compare_hostname(host,host))
+                                 host_ptr->get_host() ?
+				 host_ptr->get_host() : "") :
+          host_ptr->compare_hostname(host,host))
       {
-	DBUG_RETURN(acl_user);
+	DBUG_RETURN(sql_user);
       }
     }
   }
@@ -5034,13 +5031,13 @@ bool mysql_show_grants(THD *thd,LEX_USER
   ulong want_access;
   uint counter,index;
   int  error = 0;
-  ACL_USER *acl_user;
+  Sql_user *sql_user;
   ACL_DB *acl_db;
   char buff[1024];
   Protocol *protocol= thd->protocol;
   DBUG_ENTER("mysql_show_grants");
 
-  LINT_INIT(acl_user);
+  LINT_INIT(sql_user);
   if (!initialized)
   {
     my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--skip-grant-tables");
@@ -5050,8 +5047,9 @@ bool mysql_show_grants(THD *thd,LEX_USER
   mysql_rwlock_rdlock(&LOCK_grant);
   mysql_mutex_lock(&acl_cache->lock);
 
-  acl_user= find_acl_user(lex_user->host.str, lex_user->user.str, TRUE);
-  if (!acl_user)
+  sql_user= (Sql_user*) find_acl_user(lex_user->host.str,
+                                      lex_user->user.str, TRUE);
+  if (!sql_user)
   {
     mysql_mutex_unlock(&acl_cache->lock);
     mysql_rwlock_unlock(&LOCK_grant);
@@ -5083,7 +5081,7 @@ bool mysql_show_grants(THD *thd,LEX_USER
     global.length(0);
     global.append(STRING_WITH_LEN("GRANT "));
 
-    want_access= acl_user->access;
+    want_access= sql_user->global_acl();
     if (test_all_bits(want_access, (GLOBAL_ACLS & ~ GRANT_ACL)))
       global.append(STRING_WITH_LEN("ALL PRIVILEGES"));
     else if (!(want_access & ~GRANT_ACL))
@@ -5111,76 +5109,83 @@ bool mysql_show_grants(THD *thd,LEX_USER
 		  system_charset_info);
     global.append ('\'');
 #if defined(HAVE_OPENSSL)
-    if (acl_user->plugin.str == sha256_password_plugin_name.str)
+    if (sql_user->authentication_plugin()->ptr() == sha256_password_plugin_name.str)
     {
       global.append(STRING_WITH_LEN(" IDENTIFIED BY PASSWORD '"));
-      global.append((const char *) &acl_user->auth_string.str[0]);
+      global.append((const char *) (sql_user->authentication_string()->ptr()));
       global.append('\'');
     }
     else
 #endif
-    if (acl_user->salt_len)
+    if (sql_user->salt_len())
     {
       char passwd_buff[SCRAMBLED_PASSWORD_CHAR_LENGTH+1];
-      if (acl_user->salt_len == SCRAMBLE_LENGTH)
-        make_password_from_salt(passwd_buff, acl_user->salt);
+      if (sql_user->salt_len() == SCRAMBLE_LENGTH)
+        make_password_from_salt(passwd_buff, sql_user->salt());
       else
-        make_password_from_salt_323(passwd_buff, (ulong *) acl_user->salt);
+        make_password_from_salt_323(passwd_buff, (ulong *) sql_user->salt());
       global.append(STRING_WITH_LEN(" IDENTIFIED BY PASSWORD '"));
       global.append(passwd_buff);
       global.append('\'');
     }
     /* "show grants" SSL related stuff */
-    if (acl_user->ssl_type == SSL_TYPE_ANY)
+    enum SSL_type ssl_type= sql_user->ssl_authentication_type();
+    if (ssl_type == SSL_TYPE_ANY)
       global.append(STRING_WITH_LEN(" REQUIRE SSL"));
-    else if (acl_user->ssl_type == SSL_TYPE_X509)
+    else if (ssl_type == SSL_TYPE_X509)
       global.append(STRING_WITH_LEN(" REQUIRE X509"));
-    else if (acl_user->ssl_type == SSL_TYPE_SPECIFIED)
+    else if (ssl_type == SSL_TYPE_SPECIFIED)
     {
       int ssl_options = 0;
       global.append(STRING_WITH_LEN(" REQUIRE "));
-      if (acl_user->x509_issuer)
+      const String *x509_issuer= sql_user->x509_issuer();
+      const String *x509_subject= sql_user->x509_subject();
+      const String *ssl_cipher= sql_user->ssl_cipher();
+      if (x509_issuer->ptr())
       {
 	ssl_options++;
 	global.append(STRING_WITH_LEN("ISSUER \'"));
-	global.append(acl_user->x509_issuer,strlen(acl_user->x509_issuer));
+	global.append(x509_issuer->ptr(),x509_issuer->length(),
+                      system_charset_info);
 	global.append('\'');
       }
-      if (acl_user->x509_subject)
+      if (x509_subject->ptr())
       {
 	if (ssl_options++)
 	  global.append(' ');
 	global.append(STRING_WITH_LEN("SUBJECT \'"));
-	global.append(acl_user->x509_subject,strlen(acl_user->x509_subject),
+	global.append(x509_subject->ptr(),x509_subject->length(),
                       system_charset_info);
 	global.append('\'');
       }
-      if (acl_user->ssl_cipher)
+      if (ssl_cipher->ptr())
       {
 	if (ssl_options++)
 	  global.append(' ');
 	global.append(STRING_WITH_LEN("CIPHER '"));
-	global.append(acl_user->ssl_cipher,strlen(acl_user->ssl_cipher),
+	global.append(ssl_cipher->ptr(),ssl_cipher->length(),
                       system_charset_info);
 	global.append('\'');
       }
     }
+
+    const USER_RESOURCES *user_resource= sql_user->user_resources();
     if ((want_access & GRANT_ACL) ||
-	(acl_user->user_resource.questions ||
-         acl_user->user_resource.updates ||
-         acl_user->user_resource.conn_per_hour ||
-         acl_user->user_resource.user_conn))
+	(user_resource->questions ||
+         user_resource->updates ||
+         user_resource->conn_per_hour ||
+         user_resource->user_conn))
     {
       global.append(STRING_WITH_LEN(" WITH"));
       if (want_access & GRANT_ACL)
 	global.append(STRING_WITH_LEN(" GRANT OPTION"));
-      add_user_option(&global, acl_user->user_resource.questions,
+      add_user_option(&global, user_resource->questions,
 		      "MAX_QUERIES_PER_HOUR");
-      add_user_option(&global, acl_user->user_resource.updates,
+      add_user_option(&global, user_resource->updates,
 		      "MAX_UPDATES_PER_HOUR");
-      add_user_option(&global, acl_user->user_resource.conn_per_hour,
+      add_user_option(&global, user_resource->conn_per_hour,
 		      "MAX_CONNECTIONS_PER_HOUR");
-      add_user_option(&global, acl_user->user_resource.user_conn,
+      add_user_option(&global, user_resource->user_conn,
 		      "MAX_USER_CONNECTIONS");
     }
     protocol->prepare_for_resend();
@@ -5522,12 +5527,15 @@ void get_privilege_desc(char *to, uint m
 
 void get_mqh(const char *user, const char *host, USER_CONN *uc)
 {
-  ACL_USER *acl_user;
+  Sql_user *sql_user;
 
   mysql_mutex_lock(&acl_cache->lock);
 
-  if (initialized && (acl_user= find_acl_user(host,user, FALSE)))
-    uc->user_resources= acl_user->user_resource;
+  if (initialized && (sql_user= (Sql_user*)find_acl_user(host,user, FALSE)))
+  {
+    const USER_RESOURCES *user_resources= sql_user->user_resources();
+    uc->user_resources= *user_resources;
+  }
   else
     memset(&uc->user_resources, 0, sizeof(uc->user_resources));
 
@@ -5849,7 +5857,7 @@ static int handle_grant_table(TABLE_LIST
     Update in grant structure if drop is false and user_to is not NULL.
     Search in grant structure if drop is false and user_to is NULL.
     Structures are numbered as follows:
-    0 acl_users
+    0 sql_users
     1 acl_dbs
     2 column_priv_hash
     3 proc_priv_hash
@@ -5869,7 +5877,7 @@ static int handle_grant_struct(uint stru
   uint elements;
   const char *user;
   const char *host;
-  ACL_USER *acl_user= NULL;
+  Sql_user_implementation *sql_user= NULL;
   ACL_DB *acl_db= NULL;
   ACL_PROXY_USER *acl_proxy_user= NULL;
   GRANT_NAME *grant_name= NULL;
@@ -5886,7 +5894,7 @@ static int handle_grant_struct(uint stru
   /* Get the number of elements in the in-memory structure. */
   switch (struct_no) {
   case 0:
-    elements= acl_users.elements;
+    elements= sql_users.elements;
     break;
   case 1:
     elements= acl_dbs.elements;
@@ -5922,9 +5930,9 @@ static int handle_grant_struct(uint stru
     */
     switch (struct_no) {
     case 0:
-      acl_user= dynamic_element(&acl_users, idx, ACL_USER*);
-      user= acl_user->user;
-      host= acl_user->host.get_host();
+      sql_user= dynamic_element(&sql_users, idx, Sql_user_implementation*);
+      user= sql_user->user()->ptr();
+      host= sql_user->host()->get_host();
     break;
 
     case 1:
@@ -5968,7 +5976,7 @@ static int handle_grant_struct(uint stru
     {
       switch ( struct_no ) {
       case 0:
-        delete_dynamic_element(&acl_users, idx);
+        delete_dynamic_element(&sql_users, idx);
         break;
 
       case 1:
@@ -6006,8 +6014,8 @@ static int handle_grant_struct(uint stru
     {
       switch ( struct_no ) {
       case 0:
-        acl_user->user= strdup_root(&global_acl_memory, user_to->user.str);
-        acl_user->host.update_hostname(strdup_root(&global_acl_memory, user_to->host.str));
+        sql_user->set_user(strdup_root(&global_acl_memory, user_to->user.str));
+        sql_user->update_hostname(strdup_root(&global_acl_memory, user_to->host.str));
         break;
 
       case 1:
@@ -6511,7 +6519,7 @@ bool mysql_drop_user(THD *thd, List <LEX
     some_users_deleted= TRUE;
   }
 
-  /* Rebuild 'acl_check_hosts' since 'acl_users' has been modified */
+  /* Rebuild 'acl_check_hosts' since 'sql_users' has been modified */
   rebuild_check_host();
 
   mysql_mutex_unlock(&acl_cache->lock);
@@ -6612,7 +6620,7 @@ bool mysql_rename_user(THD *thd, List <L
     some_users_renamed= TRUE;
   }
   
-  /* Rebuild 'acl_check_hosts' since 'acl_users' has been modified */
+  /* Rebuild 'acl_check_hosts' since 'sql_users' has been modified */
   rebuild_check_host();
 
   mysql_mutex_unlock(&acl_cache->lock);
@@ -6696,7 +6704,7 @@ bool mysql_user_password_expire(THD *thd
 
   while ((tmp_user_from= user_list++))
   {
-    ACL_USER *acl_user;
+    Sql_user_implementation *sql_user;
    
     if (!(user_from= get_current_user(thd, tmp_user_from)))
     {
@@ -6707,12 +6715,12 @@ bool mysql_user_password_expire(THD *thd
     }
 
     enum mysql_user_table_field password_field= MYSQL_USER_FIELD_PASSWORD;
-    if ((!(acl_user= find_acl_user(user_from->host.str,
+    if ((!(sql_user= find_acl_user(user_from->host.str,
                                    user_from->user.str, TRUE))) ||
          update_user_table(thd, table,
-                           acl_user->host.get_host() ?
-                           acl_user->host.get_host() : "",
-                           acl_user->user ? acl_user->user : "",
+                           sql_user->host()->get_host() ?
+                           sql_user->host()->get_host() : "",
+                           sql_user->user()->ptr() ? sql_user->user()->ptr() : "",
                            NULL, 0, password_field, true))
     {
       result= true;
@@ -6721,7 +6729,7 @@ bool mysql_user_password_expire(THD *thd
       continue;
     }
 
-    acl_user->password_expired= true;
+    sql_user->set_password_expired();
     some_passwords_expired= true;
   }
 
@@ -7137,7 +7145,7 @@ bool sp_grant_privileges(THD *thd, const
   TABLE_LIST tables[1];
   List<LEX_USER> user_list;
   bool result;
-  ACL_USER *au;
+  Sql_user *su;
   Dummy_error_handler error_handler;
   DBUG_ENTER("sp_grant_privileges");
 
@@ -7148,13 +7156,13 @@ bool sp_grant_privileges(THD *thd, const
 
   mysql_mutex_lock(&acl_cache->lock);
 
-  if ((au= find_acl_user(combo->host.str=(char*)sctx->host_or_ip,combo->user.str,FALSE)))
+  if ((su= (Sql_user*)find_acl_user(combo->host.str=(char*)sctx->host_or_ip,combo->user.str,FALSE)))
     goto found_acl;
-  if ((au= find_acl_user(combo->host.str=(char*)sctx->host, combo->user.str,FALSE)))
+  if ((su= (Sql_user*)find_acl_user(combo->host.str=(char*)sctx->host, combo->user.str,FALSE)))
     goto found_acl;
-  if ((au= find_acl_user(combo->host.str=(char*)sctx->ip, combo->user.str,FALSE)))
+  if ((su= (Sql_user*)find_acl_user(combo->host.str=(char*)sctx->ip, combo->user.str,FALSE)))
     goto found_acl;
-  if((au= find_acl_user(combo->host.str=(char*)"%", combo->user.str, FALSE)))
+  if((su= (Sql_user*)find_acl_user(combo->host.str=(char*)"%", combo->user.str, FALSE)))
     goto found_acl;
 
   mysql_mutex_unlock(&acl_cache->lock);
@@ -7360,7 +7368,7 @@ int fill_schema_user_privileges(THD *thd
 #ifndef NO_EMBEDDED_ACCESS_CHECKS
   int error= 0;
   uint counter;
-  ACL_USER *acl_user;
+  Sql_user *sql_user;
   ulong want_access;
   char buff[100];
   TABLE *table= tables->table;
@@ -7373,13 +7381,13 @@ int fill_schema_user_privileges(THD *thd
     DBUG_RETURN(0);
   mysql_mutex_lock(&acl_cache->lock);
 
-  for (counter=0 ; counter < acl_users.elements ; counter++)
+  for (counter=0 ; counter < sql_users.elements ; counter++)
   {
     const char *user,*host, *is_grantable="YES";
-    acl_user=dynamic_element(&acl_users,counter,ACL_USER*);
-    if (!(user=acl_user->user))
+    sql_user=dynamic_element(&sql_users,counter,Sql_user_implementation*);
+    if (!(user=sql_user->user()->ptr()))
       user= "";
-    if (!(host=acl_user->host.get_host()))
+    if (!(host=sql_user->host()->get_host()))
       host= "";
 
     if (no_global_access &&
@@ -7387,7 +7395,7 @@ int fill_schema_user_privileges(THD *thd
          my_strcasecmp(system_charset_info, curr_host, host)))
       continue;
       
-    want_access= acl_user->access;
+    want_access= sql_user->global_acl();
     if (!(want_access & GRANT_ACL))
       is_grantable= "NO";
 

=== modified file 'sql/auth/sql_authentication.cc'
--- a/sql/auth/sql_authentication.cc	2012-09-06 12:02:23 +0000
+++ b/sql/auth/sql_authentication.cc	2012-09-18 12:46:18 +0000
@@ -23,6 +23,7 @@
 #include "sql_db.h"
 #include <mysql/plugin_validate_password.h>
 #include "auth_common.h"
+#include "sql_authorization.h"
 #include "sql_authentication.h"
 
 static LEX_STRING validate_password_plugin_name= {
@@ -57,7 +58,7 @@ acl_find_proxy_user(const char *user, co
 static bool find_mpvio_user(MPVIO_EXT *mpvio);
 static bool read_client_connect_attrs(char **ptr, size_t *max_bytes_available,
                                       const CHARSET_INFO *from_cs);
-static bool acl_check_ssl(THD *thd, const ACL_USER *acl_user);
+static bool acl_check_ssl(THD *thd, const Sql_user *sql_user);
 #endif /* NO_EMBEDDED_ACCESS_CHECKS */
 
 #ifndef EMBEDDED_LIBRARY
@@ -161,7 +162,7 @@ acl_find_proxy_user(const char *user, co
    failure if a user is not found.
 
    @note find_acl_user is not the same, because it doesn't take into
-   account the case when user is not empty, but acl_user->user is empty
+   account the case when user is not empty, but sql_user->user is empty
 
    @retval 0    found
    @retval 1    not found
@@ -170,67 +171,76 @@ static bool find_mpvio_user(MPVIO_EXT *m
 {
   DBUG_ENTER("find_mpvio_user");
   DBUG_PRINT("info", ("entry: %s", mpvio->auth_info.user_name));
-  DBUG_ASSERT(mpvio->acl_user == 0);
+  DBUG_ASSERT(mpvio->sql_user == 0);
   mysql_mutex_lock(&acl_cache->lock);
-  for (uint i=0; i < acl_users.elements; i++)
+  for (uint i=0; i < sql_users.elements; i++)
   {
-    ACL_USER *acl_user_tmp= dynamic_element(&acl_users, i, ACL_USER*);
-    if ((!acl_user_tmp->user || 
-         !strcmp(mpvio->auth_info.user_name, acl_user_tmp->user)) &&
-        acl_user_tmp->host.compare_hostname(mpvio->host, mpvio->ip))
+    Sql_user_implementation *sql_user_tmp=
+      dynamic_element(&sql_users, i, Sql_user_implementation*);
+    if ((!sql_user_tmp->user()->ptr() || 
+         !strcmp(mpvio->auth_info.user_name, sql_user_tmp->user()->ptr())) &&
+        sql_user_tmp->host()->compare_hostname(mpvio->host, mpvio->ip))
     {
-      mpvio->acl_user= acl_user_tmp->copy(mpvio->mem_root);
+      mpvio->sql_user= (Sql_user *)sql_user_tmp->copy(mpvio->mem_root);
 
       /*
-        When setting mpvio->acl_user_plugin we can save memory allocation if
+        When setting mpvio->sql_user_plugin we can save memory allocation if
         this is a built in plugin.
       */
-      optimize_plugin_compare_by_pointer(&acl_user_tmp->plugin);
-      if (auth_plugin_is_built_in(acl_user_tmp->plugin.str))
-        mpvio->acl_user_plugin= mpvio->acl_user->plugin;
+      LEX_STRING user_plugin;
+      user_plugin.str= (char *)mpvio->sql_user->authentication_plugin()->ptr();
+      user_plugin.length= mpvio->sql_user->authentication_plugin()->length();
+      //optimize_plugin_compare_by_pointer(&sql_user_tmp->plugin);
+      if (auth_plugin_is_built_in(mpvio->sql_user->authentication_plugin()->ptr()))
+      {
+        mpvio->sql_user_plugin = user_plugin;
+      }
       else
         make_lex_string_root(mpvio->mem_root, 
-                             &mpvio->acl_user_plugin, 
-                             acl_user_tmp->plugin.str, 
-                             acl_user_tmp->plugin.length, 0);
+                             &mpvio->sql_user_plugin, 
+                             user_plugin.str, 
+                             user_plugin.length, 0);
       break;
     }
   }
   mysql_mutex_unlock(&acl_cache->lock);
 
-  if (!mpvio->acl_user)
+  if (!mpvio->sql_user)
   {
     login_failed_error(mpvio, mpvio->auth_info.password_used);
     DBUG_RETURN (1);
   }
 
-  if (my_strcasecmp(system_charset_info, mpvio->acl_user->plugin.str,
+  const String *plugin_string= mpvio->sql_user->authentication_plugin();
+  const String *authentication_string= mpvio->sql_user->authentication_string();
+
+  if (my_strcasecmp(system_charset_info, plugin_string->ptr(),
                     native_password_plugin_name.str) != 0 &&
-      my_strcasecmp(system_charset_info, mpvio->acl_user->plugin.str,
+      my_strcasecmp(system_charset_info, plugin_string->ptr(),
                     old_password_plugin_name.str) != 0 &&
       !(mpvio->client_capabilities & CLIENT_PLUGIN_AUTH))
   {
     /* user account requires non-default plugin and the client is too old */
-    DBUG_ASSERT(my_strcasecmp(system_charset_info, mpvio->acl_user->plugin.str,
+    DBUG_ASSERT(my_strcasecmp(system_charset_info, plugin_string->ptr(),
                               native_password_plugin_name.str));
-    DBUG_ASSERT(my_strcasecmp(system_charset_info, mpvio->acl_user->plugin.str,
+    DBUG_ASSERT(my_strcasecmp(system_charset_info, plugin_string->ptr(),
                               old_password_plugin_name.str));
     my_error(ER_NOT_SUPPORTED_AUTH_MODE, MYF(0));
     general_log_print(current_thd, COM_CONNECT, ER(ER_NOT_SUPPORTED_AUTH_MODE));
     DBUG_RETURN (1);
   }
 
-  mpvio->auth_info.auth_string= mpvio->acl_user->auth_string.str;
+  mpvio->auth_info.auth_string= authentication_string->ptr();
   mpvio->auth_info.auth_string_length= 
-    (unsigned long) mpvio->acl_user->auth_string.length;
-  strmake(mpvio->auth_info.authenticated_as, mpvio->acl_user->user ?
-          mpvio->acl_user->user : "", USERNAME_LENGTH);
+    (unsigned long) authentication_string->length();
+  strmake(mpvio->auth_info.authenticated_as, mpvio->sql_user->user()->ptr() ?
+          mpvio->sql_user->user()->ptr() : "", USERNAME_LENGTH);
   DBUG_PRINT("info", ("exit: user=%s, auth_string=%s, authenticated as=%s"
                       ", plugin=%s",
                       mpvio->auth_info.user_name,
                       mpvio->auth_info.auth_string,
                       mpvio->auth_info.authenticated_as,
-                      mpvio->acl_user->plugin.str));
+                      plugin_string->ptr()));
   DBUG_RETURN(0);
 }
 
@@ -271,7 +281,7 @@ read_client_connect_attrs(char **ptr, si
 }
 
 
-static bool acl_check_ssl(THD *thd, const ACL_USER *acl_user)
+static bool acl_check_ssl(THD *thd, const Sql_user *sql_user)
 {
 #if defined(HAVE_OPENSSL)
   Vio *vio= thd->net.vio;
@@ -285,7 +295,7 @@ static bool acl_check_ssl(THD *thd, cons
     we check if SSL is required, if user is using SSL and
     if X509 certificate attributes are OK
   */
-  switch (acl_user->ssl_type) {
+  switch (sql_user->ssl_authentication_type()) {
   case SSL_TYPE_NOT_SPECIFIED:                  // Impossible
   case SSL_TYPE_NONE:                           // SSL is not required
     return 0;
@@ -313,15 +323,16 @@ static bool acl_check_ssl(THD *thd, cons
     if (vio_type(vio) != VIO_TYPE_SSL ||
         SSL_get_verify_result(ssl) != X509_V_OK)
       return 1;
-    if (acl_user->ssl_cipher)
+    const String *ssl_cipher_string= sql_user->ssl_cipher();
+    if (ssl_cipher_string->ptr())
     {
       DBUG_PRINT("info", ("comparing ciphers: '%s' and '%s'",
-                         acl_user->ssl_cipher, SSL_get_cipher(ssl)));
-      if (strcmp(acl_user->ssl_cipher, SSL_get_cipher(ssl)))
+                         ssl_cipher_string->ptr(), SSL_get_cipher(ssl)));
+      if (strcmp(ssl_cipher_string->ptr(), SSL_get_cipher(ssl)))
       {
         if (log_warnings)
           sql_print_information("X509 ciphers mismatch: should be '%s' but is '%s'",
-                            acl_user->ssl_cipher, SSL_get_cipher(ssl));
+                            ssl_cipher_string->ptr(), SSL_get_cipher(ssl));
         return 1;
       }
     }
@@ -329,16 +340,17 @@ static bool acl_check_ssl(THD *thd, cons
     if (!(cert= SSL_get_peer_certificate(ssl)))
       return 1;
     /* If X509 issuer is specified, we check it... */
-    if (acl_user->x509_issuer)
+    const String *x509_issuer_string= sql_user->x509_issuer();
+    if (x509_issuer_string->ptr())
     {
       char *ptr= X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0);
       DBUG_PRINT("info", ("comparing issuers: '%s' and '%s'",
-                         acl_user->x509_issuer, ptr));
-      if (strcmp(acl_user->x509_issuer, ptr))
+                          x509_issuer_string->ptr(), ptr));
+      if (strcmp(x509_issuer_string->ptr(), ptr))
       {
         if (log_warnings)
           sql_print_information("X509 issuer mismatch: should be '%s' "
-                            "but is '%s'", acl_user->x509_issuer, ptr);
+                            "but is '%s'", x509_issuer_string->ptr(), ptr);
         free(ptr);
         X509_free(cert);
         return 1;
@@ -346,16 +358,17 @@ static bool acl_check_ssl(THD *thd, cons
       free(ptr);
     }
     /* X509 subject is specified, we check it .. */
-    if (acl_user->x509_subject)
+    const String *x509_subject_string= sql_user->x509_subject();
+    if (x509_subject_string->ptr())
     {
       char *ptr= X509_NAME_oneline(X509_get_subject_name(cert), 0, 0);
       DBUG_PRINT("info", ("comparing subjects: '%s' and '%s'",
-                         acl_user->x509_subject, ptr));
-      if (strcmp(acl_user->x509_subject, ptr))
+                         x509_subject_string->ptr(), ptr));
+      if (strcmp(x509_subject_string->ptr(), ptr))
       {
         if (log_warnings)
           sql_print_information("X509 subject mismatch: should be '%s' but is '%s'",
-                          acl_user->x509_subject, ptr);
+                          x509_subject_string->ptr(), ptr);
         free(ptr);
         X509_free(cert);
         return 1;
@@ -884,8 +897,8 @@ static bool parse_com_change_user_packet
         old_password_plugin, otherwise MySQL will think that server 
         and client plugins don't match.
       */
-      if (mpvio->acl_user->salt_len == 0)
-        mpvio->acl_user_plugin= old_password_plugin_name;
+      if (mpvio->sql_user->salt_len() == 0)
+        mpvio->sql_user_plugin= old_password_plugin_name;
     }
   }
 
@@ -1441,13 +1454,13 @@ skip_to_ssl:
         old_password_plugin, otherwise MySQL will think that server 
         and client plugins don't match.
       */
-      if (mpvio->acl_user->salt_len == 0)
-        mpvio->acl_user_plugin= old_password_plugin_name;
+      if (mpvio->sql_user->salt_len() == 0)
+        mpvio->sql_user_plugin= old_password_plugin_name;
     }
   }
   
   /*
-    if the acl_user needs a different plugin to authenticate
+    if the sql_user needs a different plugin to authenticate
     (specified in GRANT ... AUTHENTICATED VIA plugin_name ..)
     we need to restart the authentication in the server.
     But perhaps the client has already used the correct plugin -
@@ -1455,7 +1468,7 @@ skip_to_ssl:
     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->sql_user_plugin.str,
                     plugin_name(mpvio->plugin)->str) != 0)
   {
     mpvio->cached_client_reply.pkt= passwd;
@@ -1846,18 +1859,19 @@ acl_authenticate(THD *thd, uint com_chan
   */
   if (mpvio.status == MPVIO_EXT::RESTART)
   {
-    DBUG_ASSERT(mpvio.acl_user);
+    DBUG_ASSERT(mpvio.sql_user);
     DBUG_ASSERT(command == COM_CHANGE_USER ||
                 my_strcasecmp(system_charset_info, auth_plugin_name.str,
-                              mpvio.acl_user->plugin.str));
-    auth_plugin_name= mpvio.acl_user->plugin;
+                              mpvio.sql_user->authentication_plugin()->ptr()));
+    auth_plugin_name.str= (char *)(mpvio.sql_user->authentication_plugin()->ptr());
+    auth_plugin_name.length= (unsigned int)mpvio.sql_user->authentication_plugin()->length();
     res= do_auth_once(thd, &auth_plugin_name, &mpvio);
   }
 
   server_mpvio_update_thd(thd, &mpvio);
 
   Security_context *sctx= thd->security_ctx;
-  const ACL_USER *acl_user= mpvio.acl_user;
+  const Sql_user *sql_user= mpvio.sql_user;
 
   thd->password= mpvio.auth_info.password_used;  // remember for error messages 
 
@@ -1916,7 +1930,7 @@ acl_authenticate(THD *thd, uint com_chan
   {
 #ifndef NO_EMBEDDED_ACCESS_CHECKS
     bool is_proxy_user= FALSE;
-    const char *auth_user = acl_user->user ? acl_user->user : "";
+    const char *auth_user = sql_user->user()->ptr() ? sql_user->user()->ptr() : "";
     ACL_PROXY_USER *proxy_user;
     /* check if the user is allowed to proxy as another user */
     proxy_user= acl_find_proxy_user(auth_user, sctx->host, sctx->ip,
@@ -1924,7 +1938,7 @@ acl_authenticate(THD *thd, uint com_chan
                                           &is_proxy_user);
     if (is_proxy_user)
     {
-      ACL_USER *acl_proxy_user;
+      Sql_user_implementation *sql_proxy_user;
 
       /* we need to find the proxy user, but there was none */
       if (!proxy_user)
@@ -1939,14 +1953,14 @@ acl_authenticate(THD *thd, uint com_chan
 
       my_snprintf(sctx->proxy_user, sizeof(sctx->proxy_user) - 1,
                   "'%s'@'%s'", auth_user,
-                  acl_user->host.get_host() ? acl_user->host.get_host() : "");
+                  sql_user->const_host()->get_host() ? sql_user->const_host()->get_host() : "");
 
       /* we're proxying : find the proxy user definition */
       mysql_mutex_lock(&acl_cache->lock);
-      acl_proxy_user= find_acl_user(proxy_user->get_proxied_host() ? 
+      sql_proxy_user= find_acl_user(proxy_user->get_proxied_host() ? 
                                     proxy_user->get_proxied_host() : "",
                                     mpvio.auth_info.authenticated_as, TRUE);
-      if (!acl_proxy_user)
+      if (!sql_proxy_user)
       {
         Host_errors errors;
         errors.m_proxy_user_acl= 1;
@@ -1956,21 +1970,21 @@ acl_authenticate(THD *thd, uint com_chan
         mysql_mutex_unlock(&acl_cache->lock);
         DBUG_RETURN(1);
       }
-      acl_user= acl_proxy_user->copy(thd->mem_root);
+      sql_user= sql_proxy_user->copy(thd->mem_root);
       DBUG_PRINT("info", ("User %s is a PROXY and will assume a PROXIED"
-                          " identity %s", auth_user, acl_user->user));
+                          " identity %s", auth_user, sql_user->user()->ptr()));
       mysql_mutex_unlock(&acl_cache->lock);
     }
 #endif /* NO_EMBEDDED_ACCESS_CHECKS */
 
-    sctx->master_access= acl_user->access;
-    if (acl_user->user)
-      strmake(sctx->priv_user, acl_user->user, USERNAME_LENGTH - 1);
+    sctx->master_access= sql_user->global_acl();
+    if (sql_user->user()->ptr())
+      strmake(sctx->priv_user, sql_user->user()->ptr(), USERNAME_LENGTH - 1);
     else
       *sctx->priv_user= 0;
 
-    if (acl_user->host.get_host())
-      strmake(sctx->priv_host, acl_user->host.get_host(), MAX_HOSTNAME - 1);
+    if (sql_user->const_host()->get_host())
+      strmake(sctx->priv_host, sql_user->const_host()->get_host(), MAX_HOSTNAME - 1);
     else
       *sctx->priv_host= 0;
 
@@ -1980,7 +1994,7 @@ acl_authenticate(THD *thd, uint com_chan
       as an additional layer, not instead of the password
       (in which case it would've been a plugin too).
     */
-    if (acl_check_ssl(thd, acl_user))
+    if (acl_check_ssl(thd, sql_user))
     {
       Host_errors errors;
       errors.m_ssl= 1;
@@ -1990,18 +2004,19 @@ acl_authenticate(THD *thd, uint com_chan
       DBUG_RETURN(1);
     }
 
+    const USER_RESOURCES *user_resource= sql_user->user_resources();
     /* Don't allow the user to connect if he has done too many queries */
-    if ((acl_user->user_resource.questions || acl_user->user_resource.updates ||
-         acl_user->user_resource.conn_per_hour ||
-         acl_user->user_resource.user_conn || 
+    if ((user_resource->questions || user_resource->updates ||
+         user_resource->conn_per_hour ||
+         user_resource->user_conn || 
          global_system_variables.max_user_connections) &&
         get_or_create_user_conn(thd,
           (opt_old_style_user_limits ? sctx->user : sctx->priv_user),
           (opt_old_style_user_limits ? sctx->host_or_ip : sctx->priv_host),
-          &acl_user->user_resource))
+          sql_user->user_resources()))
       DBUG_RETURN(1); // The error is set by get_or_create_user_conn()
 
-    sctx->password_expired= acl_user->password_expired;
+    sctx->password_expired= sql_user->password_expired();
 #endif /* NO_EMBEDDED_ACCESS_CHECKS */
   }
   else
@@ -2159,15 +2174,15 @@ static int native_password_authenticate(
                   );
 
   if (pkt_len == 0) /* no password */
-    DBUG_RETURN(mpvio->acl_user->salt_len != 0 ? CR_AUTH_USER_CREDENTIALS : CR_OK);
+    DBUG_RETURN(mpvio->sql_user->salt_len() != 0 ? CR_AUTH_USER_CREDENTIALS : CR_OK);
 
   info->password_used= PASSWORD_USED_YES;
   if (pkt_len == SCRAMBLE_LENGTH)
   {
-    if (!mpvio->acl_user->salt_len)
+    if (!mpvio->sql_user->salt_len())
       DBUG_RETURN(CR_AUTH_USER_CREDENTIALS);
 
-    DBUG_RETURN(check_scramble(pkt, mpvio->scramble, mpvio->acl_user->salt) ?
+    DBUG_RETURN(check_scramble(pkt, mpvio->scramble, mpvio->sql_user->salt()) ?
                 CR_AUTH_USER_CREDENTIALS : CR_OK);
   }
 
@@ -2207,7 +2222,7 @@ static int old_password_authenticate(MYS
     pkt_len= strnlen((char*)pkt, pkt_len);
 
   if (pkt_len == 0) /* no password */
-    return mpvio->acl_user->salt_len != 0 ? CR_AUTH_USER_CREDENTIALS : CR_OK;
+    return mpvio->sql_user->salt_len() != 0 ? CR_AUTH_USER_CREDENTIALS : CR_OK;
 
   if (secure_auth(mpvio))
     return CR_AUTH_HANDSHAKE;
@@ -2216,11 +2231,11 @@ static int old_password_authenticate(MYS
 
   if (pkt_len == SCRAMBLE_LENGTH_323)
   {
-    if (!mpvio->acl_user->salt_len)
+    if (!mpvio->sql_user->salt_len())
       return CR_AUTH_USER_CREDENTIALS;
 
     return check_scramble_323(pkt, mpvio->scramble,
-                             (ulong *) mpvio->acl_user->salt) ?
+                             (ulong *) mpvio->sql_user->salt()) ?
                              CR_AUTH_USER_CREDENTIALS : CR_OK;
   }
 
@@ -2508,7 +2523,7 @@ static int sha256_password_authenticate(
 
   /*
     After the call to read_packet() the user name will appear in
-    mpvio->acl_user and info will contain current data.
+    mpvio->sql_user and info will contain current data.
   */
   if ((pkt_len= vio->read_packet(vio, &pkt)) == -1)
     DBUG_RETURN(CR_ERROR);

=== modified file 'sql/auth/sql_authentication.h'
--- a/sql/auth/sql_authentication.h	2012-09-06 12:02:23 +0000
+++ b/sql/auth/sql_authentication.h	2012-09-18 12:46:18 +0000
@@ -2,7 +2,7 @@
 #define SQL_AUTHENTICATION_INCLUDED
 
 #include <mysql/plugin_auth.h> // MYSQL_SERVER_AUTH_INFO
-class ACL_USER;
+class Sql_user;
 
 /* Defines */
 /** Size of the header fields of an authentication packet. */
@@ -28,7 +28,7 @@ public:
 struct MPVIO_EXT :public MYSQL_PLUGIN_VIO
 {
   MYSQL_SERVER_AUTH_INFO auth_info;
-  const ACL_USER *acl_user;
+  const Sql_user *sql_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 */
@@ -57,7 +57,7 @@ struct MPVIO_EXT :public MYSQL_PLUGIN_VI
   char *ip;
   char *host;
   Thd_charset_adapter *charset_adapter;
-  LEX_STRING acl_user_plugin;
+  LEX_STRING sql_user_plugin;
   int vio_is_encrypted;
 };
 

=== added file 'sql/auth/sql_authorization.cc'
--- a/sql/auth/sql_authorization.cc	1970-01-01 00:00:00 +0000
+++ b/sql/auth/sql_authorization.cc	2012-09-18 12:46:18 +0000
@@ -0,0 +1,255 @@
+/* Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; version 2 of the License.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA */
+
+#include "my_global.h"
+#include "sql_acl.h"
+#include "hash_filo.h"
+#include "sql_connect.h"
+#include <mysql/plugin_auth.h>
+#include "sql_common.h"
+#include "hostname.h"
+#include "sql_db.h"
+#include <mysql/plugin_validate_password.h>
+#include "auth_common.h"
+#include "sql_authentication.h"
+#include "sql_authorization.h"
+
+
+Sql_user::~Sql_user()
+{
+}
+
+
+/**
+  Note : Destructor for Sql_user_implementation()
+  is kept empty because destruction of
+  Sql_user_implementation object is expected through
+  delete_dynamic()
+  Trying to free memory through destructor will
+  cause segmentation fault in delete_dynamic()
+*/
+Sql_user_implementation::~Sql_user_implementation()
+{
+}
+
+/**
+  @brief Wrapper around update_hostname() of ACL_HOST_AND_IP.
+  @param host_arg	Value to be stored
+ */
+void Sql_user_implementation::update_hostname(const char *host_arg)
+{
+  m_host.update_hostname(host_arg);
+  uint32 length= host_arg ? (uint32)strlen(host_arg) : 0;
+  m_hostname.set(host_arg, length, system_charset_info);
+}
+
+/**
+  Functions to set various members of Sql_user_implementation.
+ */
+
+/**
+  @brief setting user name in Sql_user_implementation .
+  @param user    Name of the user
+*/
+void Sql_user_implementation::set_user(const char* user)
+{
+  uint32 length= user ? (uint32)strlen(user) : 0;
+  m_user.set(user, length, system_charset_info);
+}
+
+
+/**
+  @brief setting password hash for the user.
+  @param authentication_string    Password hash value
+*/
+void
+Sql_user_implementation::set_authentication_string(const char* authentication_string,
+                                                   uint32 length)
+{
+  m_authentication_string.set(authentication_string, length,
+                              system_charset_info);
+}
+
+
+/**
+  @brief setting plugin details.
+  @param authentication_plugin    Plugin details from user table
+*/
+void
+Sql_user_implementation::set_authentication_plugin(const char* authentication_plugin,
+                                                   uint32 length)
+{
+  m_authentication_plugin.set(authentication_plugin, length,
+                              system_charset_info);
+}
+
+
+/**
+  @brief seting cipher details.
+  @param ssl_cipher    ssl cipher details
+*/
+void Sql_user_implementation::set_ssl_cipher(const char* ssl_cipher)
+{
+  uint32 length= ssl_cipher ? (uint32)strlen(ssl_cipher) : 0;
+  m_ssl_cipher.set(ssl_cipher, length, system_charset_info);
+}
+
+
+/**
+  @brief  setting certificate issuer details.
+  @param x509_issuer    issuer details from the certificate
+*/
+void Sql_user_implementation::set_x509_issuer(const char* x509_issuer)
+{
+  uint32 length= x509_issuer ? (uint32)strlen(x509_issuer) : 0;
+  m_x509_issuer.set(x509_issuer, length, system_charset_info);
+}
+
+
+/**
+  @brief setting certificate subject details.
+  @param x509_subject    subject line of a certificate
+*/
+void Sql_user_implementation::set_x509_subject(const char* x509_subject)
+{
+  uint32 length= x509_subject ? (uint32)strlen(x509_subject) : 0;
+  m_x509_subject.set(x509_subject, length, system_charset_info);
+}
+
+
+/**
+  @brief setting various resource contraints for the user.
+  @param user_resources  USER_RESOURCES structure with
+                         resource details for user
+*/
+void
+Sql_user_implementation::set_user_resources_selective(USER_RESOURCES *user_resources)
+{
+  if (user_resources->specified_limits & USER_RESOURCES::QUERIES_PER_HOUR)
+    m_user_resources.questions= user_resources->questions;
+  if (user_resources->specified_limits & USER_RESOURCES::UPDATES_PER_HOUR)
+    m_user_resources.updates= user_resources->updates;
+  if (user_resources->specified_limits & USER_RESOURCES::CONNECTIONS_PER_HOUR)
+    m_user_resources.conn_per_hour= user_resources->conn_per_hour;
+  if (user_resources->specified_limits & USER_RESOURCES::USER_CONNECTIONS)
+    m_user_resources.user_conn= user_resources->user_conn;
+}
+
+
+/**
+  @brief setting various resource contraints for the user.
+  @param user_resources  USER_RESOURCES structure with
+                         resource details for user
+*/
+void
+Sql_user_implementation::set_user_resources(USER_RESOURCES *user_resources)
+{
+  m_user_resources.questions= user_resources->questions;
+  m_user_resources.updates= user_resources->updates;
+  m_user_resources.conn_per_hour= user_resources->conn_per_hour;
+  m_user_resources.user_conn= user_resources->user_conn;
+  m_user_resources.specified_limits= user_resources->specified_limits;
+}
+
+
+/**
+  Convert scrambled password to binary form, according to scramble type, 
+  Binary form is stored in user.salt.
+  
+  @param sql_user The object where to store the salt
+  @param password The password hash containing the salt
+  @param password_len The length of the password hash
+   
+  Despite the name of the function it is used when loading ACLs from disk
+  to store the password hash in the Sql_user_implementation object.
+*/
+
+void
+Sql_user_implementation::set_user_salt(const char *password, uint password_len)
+{
+  /* Using old password protocol */
+  if (password_len == SCRAMBLED_PASSWORD_CHAR_LENGTH)
+  {
+    get_salt_from_password(m_salt, password);
+    m_salt_len= SCRAMBLE_LENGTH;
+  }
+  else if (password_len == SCRAMBLED_PASSWORD_CHAR_LENGTH_323)
+  {
+    get_salt_from_password_323((ulong *) m_salt, password);
+    m_salt_len= SCRAMBLE_LENGTH_323;
+  }
+  else
+    m_salt_len= 0;
+
+  /*
+    Since we're changing the password for the user we need to reset the
+    expiration flag.
+  */
+  m_password_expired= false;
+}
+
+
+/**
+  @brief Set salt and salt_len. Used by copy() function.
+  @param salt        source salt value
+  @param salt_len    length of salt
+*/
+void Sql_user_implementation::set_salt(uint8 *salt, uint8 salt_len)
+{
+  if(salt_len != 0)
+    for(uint i=0; i < SCRAMBLE_LENGTH + 1; i++)
+    {
+      m_salt[i]= salt[i];
+    }
+
+  m_salt_len= salt_len;
+}
+
+
+/**
+  @brief Make copy of a Sql_user_implementation object
+  @param root    MEM_ROOT pointer of memory allocation
+*/
+Sql_user_implementation *Sql_user_implementation::copy(MEM_ROOT *root)
+{
+  Sql_user_implementation *dst=
+    (Sql_user_implementation *) alloc_root(root, sizeof(Sql_user_implementation));
+
+  dst->set_mem_root(root);
+  dst->set_user(safe_strdup_root(root, m_user.ptr()));
+  dst->update_hostname(safe_strdup_root(root, m_host.get_host()));
+  dst->set_authentication_string(safe_strdup_root(root,
+                                                  m_authentication_string.ptr()),
+                                                  m_authentication_string.length());
+  dst->set_authentication_plugin(safe_strdup_root(root,
+                                                  m_authentication_plugin.ptr()),
+                                                  m_authentication_plugin.length());
+  dst->set_ssl_cipher(safe_strdup_root(root, m_ssl_cipher.ptr()));
+  dst->set_x509_issuer(safe_strdup_root(root, m_x509_issuer.ptr()));
+  dst->set_x509_subject(safe_strdup_root(root, m_x509_subject.ptr()));
+  dst->set_user_resources(&m_user_resources);
+  dst->set_sort(m_sort);
+  dst->set_global_acl(m_access);
+
+  dst->set_salt(m_salt, m_salt_len);
+
+  dst->set_ssl_authentication_type(m_ssl_type);
+
+  m_password_expired ?
+    dst->set_password_expired() : dst->reset_password_expired();
+
+  return dst;
+}
+

=== added file 'sql/auth/sql_authorization.h'
--- a/sql/auth/sql_authorization.h	1970-01-01 00:00:00 +0000
+++ b/sql/auth/sql_authorization.h	2012-09-18 12:46:18 +0000
@@ -0,0 +1,210 @@
+#ifndef SQL_AUTHORIZATION_INCLUDED
+#define SQL_AUTHORIZATION_INCLUDED
+
+class ACL_HOST_AND_IP;
+
+/**
+  Sql_user Interface
+*/
+
+class Sql_user
+{
+  protected:
+    /**
+      Protect the constructor for virtual class
+    */
+    Sql_user() {}
+
+  public:
+    virtual ~Sql_user();
+    /**
+      Interfaces to extract details from user object
+    */
+
+    virtual const String *user() const= 0;
+    virtual const String *hostname() const= 0;
+    virtual const String *authentication_string() const= 0;
+    virtual const String * authentication_plugin() const= 0;
+    virtual const String *ssl_cipher() const= 0;
+    virtual const String *x509_issuer() const= 0;
+    virtual const String *x509_subject() const= 0;
+
+    virtual const USER_RESOURCES *user_resources() const= 0;
+
+    virtual const ACL_HOST_AND_IP *const_host() const= 0;
+    virtual ACL_HOST_AND_IP *host()= 0;
+    
+    virtual bool password_expired() const= 0;
+    virtual SSL_type ssl_authentication_type() const= 0;
+    virtual ulong sort() const= 0;
+    virtual ulong global_acl() const= 0;
+
+    virtual const uint8 *salt() const=0;
+    virtual uint8 salt_len() const=0;
+};
+
+class Sql_user_implementation : public Sql_user
+{
+  private:
+
+    String m_user;
+    String m_hostname;
+    String m_authentication_string;
+    String m_authentication_plugin;
+    String m_ssl_cipher;
+    String m_x509_issuer;
+    String m_x509_subject;
+
+    USER_RESOURCES m_user_resources;
+
+    ACL_HOST_AND_IP m_host;
+
+    ulong m_access;
+    ulong m_sort;
+
+    uint8 m_salt[SCRAMBLE_LENGTH + 1];
+    uint8 m_salt_len;
+
+    enum SSL_type m_ssl_type;
+
+    bool m_password_expired;
+
+    MEM_ROOT *m_mem_root;
+
+  public:
+    /**
+      Functions from Sql_user
+    */
+    const String *user() const
+    {
+      return &m_user;
+    }
+    const String *hostname() const
+    {
+      return &m_hostname;
+    }
+    const String *authentication_string() const
+    {
+      return &m_authentication_string;
+    }
+    const String * authentication_plugin() const
+    {
+      return &m_authentication_plugin;
+    }
+    const String *ssl_cipher() const
+    {
+      return &m_ssl_cipher;
+    }
+    const String *x509_issuer() const
+    {
+      return &m_x509_issuer;
+    }
+    const String *x509_subject() const
+    {
+      return &m_x509_subject;
+    }
+
+    const USER_RESOURCES *user_resources() const
+    {
+      return &m_user_resources;
+    }
+
+    const ACL_HOST_AND_IP *const_host() const
+    {
+      return &m_host;
+    }
+
+    ACL_HOST_AND_IP *host()
+    {
+      return &m_host;
+    }
+
+    virtual ulong sort() const
+    {
+      return m_sort;
+    }
+
+    bool password_expired() const
+    {
+      return m_password_expired;
+    }
+
+    SSL_type ssl_authentication_type() const
+    {
+      return m_ssl_type;
+    }
+
+    ulong global_acl() const
+    {
+      return m_access;
+    }
+
+    virtual const uint8 *salt() const
+    {
+      return m_salt;
+    }
+
+    virtual uint8 salt_len() const
+    {
+      return m_salt_len;
+    }
+
+    /**
+     Functions required by Sql_user_implementation
+    */
+    Sql_user_implementation() {}
+
+    Sql_user_implementation( MEM_ROOT *mem_root )
+    {
+      memset(this, 0, sizeof(*this));
+      m_mem_root= mem_root;
+    }
+
+    /**
+      Note : Destructor for Sql_user_implementation()
+      is kept empty because destruction of
+      Sql_user_implementation object is expected through
+      delete_dynamic()
+      Trying to free memory through destructor will
+      cause segmentation fault in delete_dynamic()
+    */
+    ~Sql_user_implementation();
+
+    Sql_user_implementation *copy(MEM_ROOT *mem_root);
+
+    /**
+      Wrapper around update_hostname() of ACL_HOST_AND_IP
+    */
+    void update_hostname(const char *host_arg);
+    /**
+      Functions to set various members of Sql_user_implementation
+    */
+    void set_user(const char* user);
+    void set_authentication_string(const char* authentication_string,
+                                   uint32 length);
+    void set_authentication_plugin(const char* authentication_plugin,
+                                   uint32 length);
+    void set_ssl_cipher(const char* ssl_cipher);
+    void set_x509_issuer(const char* x509_issuer);
+    void set_x509_subject(const char* x509_subject);
+
+    void set_user_resources_selective(USER_RESOURCES *user_resources);
+    void set_user_resources(USER_RESOURCES *user_resources);
+
+    void set_password_expired() { m_password_expired= true; }
+    void reset_password_expired() { m_password_expired= false; }
+
+    void set_ssl_authentication_type( enum SSL_type ssl_type ) { m_ssl_type= ssl_type; }
+
+    void set_sort( ulong sort) { m_sort= sort; }
+    void set_global_acl( ulong access ) { m_access= access; }
+
+    void set_mem_root(MEM_ROOT *mem_root) { m_mem_root= mem_root; }
+
+    void set_user_salt(const char *password, uint password_len);
+    void set_salt(uint8 *salt, uint8 salt_len);
+
+
+};
+
+#endif /* SQL_AUTHORIZATION_INCLUDED */

=== modified file 'sql/auth/sql_user_table.cc'
--- a/sql/auth/sql_user_table.cc	2012-09-04 07:22:36 +0000
+++ b/sql/auth/sql_user_table.cc	2012-09-18 12:46:18 +0000
@@ -360,6 +360,7 @@ static my_bool acl_load(THD *thd, TABLE_
   char tmp_name[NAME_LEN+1];
   int password_length;
   sql_mode_t old_sql_mode= thd->variables.sql_mode;
+  ulong global_acl= 0;
   DBUG_ENTER("acl_load");
 
   thd->variables.sql_mode&= ~MODE_PAD_CHAR_TO_FULL_LENGTH;
@@ -377,24 +378,27 @@ static my_bool acl_load(THD *thd, TABLE_
                        NULL, 1, 1, FALSE))
     goto end;
   table->use_all_columns();
-  (void) my_init_dynamic_array(&acl_users,sizeof(ACL_USER),50,100);
+  (void) my_init_dynamic_array(&sql_users,sizeof(Sql_user_implementation),50,100);
   
   allow_all_hosts=0;
   while (!(read_record_info.read_record(&read_record_info)))
   {
     /* Reading record from mysql.user */
-    ACL_USER user;
-    memset(&user, 0, sizeof(user));
-    user.host.update_hostname(get_field(&global_acl_memory,
-                                        table->field[MYSQL_USER_FIELD_HOST]));
-    user.user= get_field(&global_acl_memory,
-                         table->field[MYSQL_USER_FIELD_USER]);
-    if (check_no_resolve && hostname_requires_resolving(user.host.get_host()))
+    Sql_user_implementation user(&global_acl_memory);
+    user.update_hostname(get_field(&global_acl_memory,
+                                           table->field[MYSQL_USER_FIELD_HOST]));
+    user.set_user(get_field(&global_acl_memory,
+                            table->field[MYSQL_USER_FIELD_USER]));
+
+    const String *user_string= user.user();
+    const String *host_string= user.hostname();
+    if (check_no_resolve &&
+        hostname_requires_resolving(user.host()->get_host()))
     {
       sql_print_warning("'user' entry '%s@%s' "
                         "ignored in --skip-name-resolve mode.",
-			user.user ? user.user : "",
-			user.host.get_host() ? user.host.get_host() : "");
+			user_string->ptr() ? user_string->ptr() : "",
+			host_string->ptr() ? host_string->ptr() : "");
       continue;
     }
 
@@ -403,95 +407,108 @@ static my_bool acl_load(THD *thd, TABLE_
       char *password= get_field(&global_acl_memory,
                                 table->field[MYSQL_USER_FIELD_PASSWORD]);
       uint password_len= password ? strlen(password) : 0;
-      user.auth_string.str= password ? password : const_cast<char*>("");
-      user.auth_string.length= password_len;
+      user.set_authentication_string(password ?
+                                       password :
+                                       const_cast<char*>(""),
+                                     (uint32)password_len);
       /*
          Transform hex to octets and adjust the format.
        */
-      set_user_salt(&user, password, password_len);
+      user.set_user_salt(password, password_len);
 
       /*
         Set temporary plugin deduced from password length. If there are 
         enough fields in the user table the real plugin will be read later.
        */
-      user.plugin= native_password_plugin_name;
       if (password_len == SCRAMBLED_PASSWORD_CHAR_LENGTH_323)
-        user.plugin= old_password_plugin_name;
+        user.set_authentication_plugin(old_password_plugin_name.str,
+                                       (uint32)old_password_plugin_name.length);
+      else
+        user.set_authentication_plugin(native_password_plugin_name.str,
+                                       (uint32)native_password_plugin_name.length);
+
     } 
 
     {
       uint next_field;
-      user.access= get_access(table,3,&next_field) & GLOBAL_ACLS;
+      global_acl= get_access(table,3,&next_field) & GLOBAL_ACLS;
       /*
         if it is pre 5.0.1 privilege table then map CREATE privilege on
         CREATE VIEW & SHOW VIEW privileges
       */
-      if (table->s->fields <= 31 && (user.access & CREATE_ACL))
-        user.access|= (CREATE_VIEW_ACL | SHOW_VIEW_ACL);
+      if (table->s->fields <= 31 && (global_acl & CREATE_ACL))
+        global_acl|= (CREATE_VIEW_ACL | SHOW_VIEW_ACL);
 
       /*
         if it is pre 5.0.2 privilege table then map CREATE/ALTER privilege on
         CREATE PROCEDURE & ALTER PROCEDURE privileges
       */
-      if (table->s->fields <= 33 && (user.access & CREATE_ACL))
-        user.access|= CREATE_PROC_ACL;
-      if (table->s->fields <= 33 && (user.access & ALTER_ACL))
-        user.access|= ALTER_PROC_ACL;
+      if (table->s->fields <= 33 && (global_acl & CREATE_ACL))
+        global_acl|= CREATE_PROC_ACL;
+      if (table->s->fields <= 33 && (global_acl & ALTER_ACL))
+        global_acl|= ALTER_PROC_ACL;
 
       /*
         pre 5.0.3 did not have CREATE_USER_ACL
       */
-      if (table->s->fields <= 36 && (user.access & GRANT_ACL))
-        user.access|= CREATE_USER_ACL;
+      if (table->s->fields <= 36 && (global_acl & GRANT_ACL))
+        global_acl|= CREATE_USER_ACL;
 
 
       /*
         if it is pre 5.1.6 privilege table then map CREATE privilege on
         CREATE|ALTER|DROP|EXECUTE EVENT
       */
-      if (table->s->fields <= 37 && (user.access & SUPER_ACL))
-        user.access|= EVENT_ACL;
+      if (table->s->fields <= 37 && (global_acl & SUPER_ACL))
+        global_acl|= EVENT_ACL;
 
       /*
         if it is pre 5.1.6 privilege then map TRIGGER privilege on CREATE.
       */
-      if (table->s->fields <= 38 && (user.access & SUPER_ACL))
-        user.access|= TRIGGER_ACL;
+      if (table->s->fields <= 38 && (global_acl & SUPER_ACL))
+        global_acl|= TRIGGER_ACL;
+
+      user.set_global_acl(global_acl);
 
-      user.sort= get_sort(2,user.host.get_host(),user.user);
+      user.set_sort(get_sort(2,user.host()->get_host(),user.user()->ptr()));
 
       /* Starting from 4.0.2 we have more fields */
       if (table->s->fields >= 31)
       {
         char *ssl_type=
           get_field(thd->mem_root, table->field[MYSQL_USER_FIELD_SSL_TYPE]);
+        enum SSL_type ssl_authentication_type;
         if (!ssl_type)
-          user.ssl_type=SSL_TYPE_NONE;
+          ssl_authentication_type= SSL_TYPE_NONE;
         else if (!strcmp(ssl_type, "ANY"))
-          user.ssl_type=SSL_TYPE_ANY;
+          ssl_authentication_type= SSL_TYPE_ANY;
         else if (!strcmp(ssl_type, "X509"))
-          user.ssl_type=SSL_TYPE_X509;
+          ssl_authentication_type= SSL_TYPE_X509;
         else  /* !strcmp(ssl_type, "SPECIFIED") */
-          user.ssl_type=SSL_TYPE_SPECIFIED;
+          ssl_authentication_type= SSL_TYPE_SPECIFIED;
 
-        user.ssl_cipher= 
-          get_field(&global_acl_memory, table->field[MYSQL_USER_FIELD_SSL_CIPHER]);
-        user.x509_issuer=
-          get_field(&global_acl_memory, table->field[MYSQL_USER_FIELD_X509_ISSUER]);
-        user.x509_subject=
-          get_field(&global_acl_memory, table->field[MYSQL_USER_FIELD_X509_SUBJECT]);
+        user.set_ssl_authentication_type(ssl_authentication_type);
 
+        user.set_ssl_cipher(get_field(&global_acl_memory,
+                                      table->field[MYSQL_USER_FIELD_SSL_CIPHER]));
+        user.set_x509_issuer(get_field(&global_acl_memory,
+                                       table->field[MYSQL_USER_FIELD_X509_ISSUER]));
+        user.set_x509_subject(get_field(&global_acl_memory,
+                              table->field[MYSQL_USER_FIELD_X509_SUBJECT]));
+
+        USER_RESOURCES user_resource;
         char *ptr= get_field(thd->mem_root,
                              table->field[MYSQL_USER_FIELD_MAX_QUESTIONS]);
-        user.user_resource.questions=ptr ? atoi(ptr) : 0;
+        user_resource.questions=ptr ? atoi(ptr) : 0;
         ptr= get_field(thd->mem_root,
                        table->field[MYSQL_USER_FIELD_MAX_UPDATES]);
-        user.user_resource.updates=ptr ? atoi(ptr) : 0;
+        user_resource.updates=ptr ? atoi(ptr) : 0;
         ptr= get_field(thd->mem_root,
                        table->field[MYSQL_USER_FIELD_MAX_CONNECTIONS]);
-        user.user_resource.conn_per_hour= ptr ? atoi(ptr) : 0;
-        if (user.user_resource.questions || user.user_resource.updates ||
-            user.user_resource.conn_per_hour)
+        user_resource.conn_per_hour= ptr ? atoi(ptr) : 0;
+
+        if (user_resource.questions || user_resource.updates ||
+            user_resource.conn_per_hour)
           mqh_used=1;
 
         if (table->s->fields >= 36)
@@ -499,9 +516,11 @@ static my_bool acl_load(THD *thd, TABLE_
           /* Starting from 5.0.3 we have max_user_connections field */
           ptr= get_field(thd->mem_root,
                          table->field[MYSQL_USER_FIELD_MAX_USER_CONNECTIONS]);
-          user.user_resource.user_conn= ptr ? atoi(ptr) : 0;
+          user_resource.user_conn= ptr ? atoi(ptr) : 0;
         }
 
+        user.set_user_resources_selective(&user_resource);
+
         if (table->s->fields >= 41)
         {
           /* We may have plugin & auth_String fields */
@@ -513,40 +532,46 @@ static my_bool acl_load(THD *thd, TABLE_
               By comparing the plugin with the built in plugins it is possible
               to optimize the string allocation and comparision.
             */
+            bool throw_warning= false;
             if (my_strcasecmp(system_charset_info, tmpstr,
                               native_password_plugin_name.str) == 0)
-              user.plugin= native_password_plugin_name;
+                user.set_authentication_plugin(native_password_plugin_name.str,
+                                               (uint32)native_password_plugin_name.length);
             else
               if (my_strcasecmp(system_charset_info, tmpstr,
                                 old_password_plugin_name.str) == 0)
-                user.plugin= old_password_plugin_name;
+                user.set_authentication_plugin(old_password_plugin_name.str,
+                                               (uint32)old_password_plugin_name.length);
 #if defined(HAVE_OPENSSL)
             else
               if (my_strcasecmp(system_charset_info, tmpstr,
                                 sha256_password_plugin_name.str) == 0)
-                user.plugin= sha256_password_plugin_name;
+              {
+                 user.set_authentication_plugin(sha256_password_plugin_name.str,
+                                                (uint32)sha256_password_plugin_name.length);
+                 throw_warning= true;
+              }
 #endif
             else
               {
-                user.plugin.str= tmpstr;
-                user.plugin.length= strlen(tmpstr);
+                user.set_authentication_plugin(tmpstr,(uint32)strlen(tmpstr));
+                throw_warning= true;
               }
-            if (user.auth_string.length &&
-                user.plugin.str != native_password_plugin_name.str &&
-                user.plugin.str != old_password_plugin_name.str)
+            if (user.authentication_string()->length() && throw_warning)
             {
               sql_print_warning("'user' entry '%s@%s' has both a password "
                                 "and an authentication plugin specified. The "
                                 "password will be ignored.",
-                                user.user ? user.user : "",
-                                user.host.get_host() ? user.host.get_host() : "");
+                                user_string->ptr() ? user_string->ptr() : "",
+                                host_string->ptr() ? host_string->ptr() : "");
             }
-            user.auth_string.str=
-              get_field(&global_acl_memory,
+            LEX_STRING authentication_string;
+            authentication_string.str= get_field(&global_acl_memory,
                         table->field[MYSQL_USER_FIELD_AUTHENTICATION_STRING]);
-            if (!user.auth_string.str)
-              user.auth_string.str= const_cast<char*>("");
-            user.auth_string.length= strlen(user.auth_string.str);
+            if (!authentication_string.str)
+              authentication_string.str= const_cast<char*>("");
+            user.set_authentication_string(authentication_string.str,
+                                           (uint32)strlen(authentication_string.str));
           }
           else /* skip auth_string if there's no plugin */
             next_field++;
@@ -557,36 +582,39 @@ static my_bool acl_load(THD *thd, TABLE_
           char *tmpstr= get_field(&global_acl_memory,
                                   table->field[MYSQL_USER_FIELD_PASSWORD_EXPIRED]);
           if (tmpstr && (*tmpstr == 'Y' || *tmpstr == 'y'))
-            user.password_expired= true;
+            user.set_password_expired();
         }
       } // end if (table->s->fields >= 31)
       else
       {
-        user.ssl_type=SSL_TYPE_NONE;
+        user.set_ssl_authentication_type(SSL_TYPE_NONE);
 #ifndef TO_BE_REMOVED
+        ulong global_acl_tbr= user.global_acl();
         if (table->s->fields <= 13)
         {						// Without grant
-          if (user.access & CREATE_ACL)
-            user.access|=REFERENCES_ACL | INDEX_ACL | ALTER_ACL;
+          if (global_acl_tbr & CREATE_ACL)
+            global_acl_tbr|=REFERENCES_ACL | INDEX_ACL | ALTER_ACL;
         }
         /* Convert old privileges */
-        user.access|= LOCK_TABLES_ACL | CREATE_TMP_ACL | SHOW_DB_ACL;
-        if (user.access & FILE_ACL)
-          user.access|= REPL_CLIENT_ACL | REPL_SLAVE_ACL;
-        if (user.access & PROCESS_ACL)
-          user.access|= SUPER_ACL | EXECUTE_ACL;
+        global_acl_tbr|= LOCK_TABLES_ACL | CREATE_TMP_ACL | SHOW_DB_ACL;
+        if (global_acl_tbr & FILE_ACL)
+          global_acl_tbr|= REPL_CLIENT_ACL | REPL_SLAVE_ACL;
+        if (global_acl_tbr & PROCESS_ACL)
+          global_acl_tbr|= SUPER_ACL | EXECUTE_ACL;
+
+        user.set_global_acl(global_acl_tbr);
 #endif
       }
-      (void) push_dynamic(&acl_users,(uchar*) &user);
-      if (user.host.check_allow_all_hosts())
+      (void) push_dynamic(&sql_users,(uchar*) &user);
+      if (user.host()->check_allow_all_hosts())
         allow_all_hosts=1;			// Anyone can connect
     }
   } // END while reading records from the mysql.user table
   
-  my_qsort((uchar*) dynamic_element(&acl_users,0,ACL_USER*),acl_users.elements,
-	   sizeof(ACL_USER),(qsort_cmp) acl_compare);
+  my_qsort((uchar*) dynamic_element(&sql_users,0,Sql_user_implementation*),sql_users.elements,
+	   sizeof(Sql_user_implementation),(qsort_cmp) sql_user_compare);
   end_read_record(&read_record_info);
-  freeze_size(&acl_users);
+  freeze_size(&sql_users);
 
   /* Legacy password integrity checks ----------------------------------------*/
   { 

No bundle (reason: useless for push emails).
Thread
bzr push into mysql-trunk-auth branch (harin.vadodaria:4420 to 4421) WL#6486Harin Vadodaria19 Sep