List:Commits« Previous MessageNext Message »
From:Kristofer Pettersson Date:May 27 2011 2:40pm
Subject:bzr commit into mysql-trunk-wl5602 branch (kristofer.pettersson:3311)
View as plain text  
#At file:///home/thek/bzr/mysql-trunk-security/ based on revid:tor.didriksen@strippedah1q7

 3311 Kristofer Pettersson	2011-05-27
      WL5602 Preview patch
      
      This patch introduces a new built in authentication plugin
      for salted SHA-2 hashed passwords.
      
      The ability to change default authentication plugin for
      CREATE USER, GRANT USER and PASSWORD statements is also 
      introduced.

    added:
      include/crypt_genhash_impl.h
      mysql-test/r/plugin_auth_sha256.result
      mysql-test/t/plugin_auth_sha256.test
      sql-common/crypt_genhash_impl.cc
    modified:
      include/password.h
      libmysql/CMakeLists.txt
      mysql-test/r/grant.result
      mysql-test/r/plugin_auth.result
      mysql-test/r/plugin_auth_qa.result
      mysql-test/r/plugin_auth_qa_1.result
      mysql-test/r/plugin_auth_qa_2.result
      mysql-test/t/plugin_auth.test
      mysql-test/t/plugin_auth_qa.test
      scripts/mysql_system_tables.sql
      scripts/mysql_system_tables_data.sql
      sql-common/client.c
      sql/CMakeLists.txt
      sql/item_strfunc.cc
      sql/item_strfunc.h
      sql/password.c
      sql/set_var.cc
      sql/sql_acl.cc
      sql/sql_acl.h
      sql/sql_class.h
      sql/sql_parse.cc
      sql/sql_yacc.yy
      sql/structs.h
      sql/sys_vars.cc
=== added file 'include/crypt_genhash_impl.h'
--- a/include/crypt_genhash_impl.h	1970-01-01 00:00:00 +0000
+++ b/include/crypt_genhash_impl.h	2011-05-27 14:40:44 +0000
@@ -0,0 +1,32 @@
+#ifndef CRYPT_HASHGEN_IMPL_H
+#define CRYPT_HASHGEN_IMPL_H
+#define	ROUNDS_DEFAULT	5000
+#define	ROUNDS_MIN	1000
+#define	ROUNDS_MAX	999999999
+#define	MIXCHARS	32
+#define CRYPT_SALT_LENGTH  20
+#define CRYPT_MAGIC_LENGTH  3
+#define CRYPT_PARAM_LENGTH 13
+#define CRYPT_MAX_PASSWORD_SIZE (CRYPT_SALT_LENGTH + \
+                                 43 + \
+                                 CRYPT_MAGIC_LENGTH + \
+                                 CRYPT_PARAM_LENGTH)
+
+int extract_user_salt(char **salt_begin,
+                      char **salt_end);
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+char *
+crypt_genhash_impl(char *ctbuffer,
+                   size_t ctbufflen,
+                   const char *plaintext,
+                   int plaintext_len,
+                   const char *switchsalt,
+                   const char **params);
+void generate_user_salt(char *buffer, int buffer_len);
+#ifdef __cplusplus
+} // extern "C"
+#endif 
+#endif

=== modified file 'include/password.h'
--- a/include/password.h	2010-03-31 14:05:33 +0000
+++ b/include/password.h	2011-05-27 14:40:44 +0000
@@ -18,12 +18,18 @@
 
 #include "my_global.h"
 
+struct rand_struct *get_sql_rand();
+                           
 C_MODE_START
 
 void my_make_scrambled_password_323(char *to, const char *password,
                                     size_t pass_len);
 void my_make_scrambled_password(char *to, const char *password,
                                 size_t pass_len);
+void my_make_scrambled_password_sha1(char *to, const char *password,
+                                     size_t pass_len);
+void my_make_scrambled_password_323(char *to, const char *password,
+                                    size_t pass_len);
 
 void hash_password(ulong *result, const char *password, uint password_len);
 

=== modified file 'libmysql/CMakeLists.txt'
--- a/libmysql/CMakeLists.txt	2011-03-28 08:49:43 +0000
+++ b/libmysql/CMakeLists.txt	2011-05-27 14:40:44 +0000
@@ -141,6 +141,7 @@ SET(CLIENT_SOURCES
   ../sql-common/client.c 
   ../sql-common/my_time.c 
   ../sql-common/client_plugin.c 
+  ../sql-common/crypt_genhash_impl.cc
   ../sql/net_serv.cc
   ../sql-common/pack.c 
   ../sql/password.c

=== modified file 'mysql-test/r/grant.result'
Binärfilerna a/mysql-test/r/grant.result	2011-03-21 14:50:06 +0000 och b/mysql-test/r/grant.result	2011-05-27 14:40:44 +0000 skiljer

=== modified file 'mysql-test/r/plugin_auth.result'
--- a/mysql-test/r/plugin_auth.result	2011-04-07 09:55:09 +0000
+++ b/mysql-test/r/plugin_auth.result	2011-05-27 14:40:44 +0000
@@ -36,6 +36,7 @@ select USER(),CURRENT_USER();
 USER()	CURRENT_USER()
 plug@localhost	plug_dest@%
 ## test SET PASSWORD
+Setting password is allowed but it won't affect the authentication mechanism.
 SET PASSWORD = PASSWORD('plug_dest');
 Warnings:
 Note	1699	SET PASSWORD has no significance for users authenticating via plugins
@@ -45,7 +46,7 @@ ERROR 28000: Access denied for user 'plu
 ## test correct default plugin
 select USER(),CURRENT_USER();
 USER()	CURRENT_USER()
-plug@localhost	plug@%
+plug@localhost	plug_dest@%
 ## test no_auto_create_user sql mode with plugin users
 SET @@sql_mode=no_auto_create_user;
 GRANT INSERT ON TEST.* TO grant_user IDENTIFIED WITH 'test_plugin_server';
@@ -85,9 +86,9 @@ CREATE TABLE t1 (a INT);
 DROP TABLE t1;
 DROP USER new_grant_user;
 # try re-create existing user via GRANT IDENTIFIED WITH
+GRANTS which don't affect current plugin are allowed!
 GRANT ALL PRIVILEGES ON test_grant_db.* TO plug
 IDENTIFIED WITH 'test_plugin_server' AS 'plug_dest';
-ERROR HY000: GRANT with IDENTIFIED WITH is illegal because the user plug already exists
 GRANT ALL PRIVILEGES ON test_grant_db.* TO plug_dest
 IDENTIFIED WITH 'test_plugin_server' AS 'plug_dest';
 ERROR HY000: GRANT with IDENTIFIED WITH is illegal because the user plug_dest already exists

=== modified file 'mysql-test/r/plugin_auth_qa.result'
--- a/mysql-test/r/plugin_auth_qa.result	2011-03-18 14:16:17 +0000
+++ b/mysql-test/r/plugin_auth_qa.result	2011-05-27 14:40:44 +0000
@@ -105,7 +105,7 @@ CREATE USER plug_dest IDENTIFIED BY 'plu
 SELECT user,plugin,authentication_string FROM mysql.user WHERE user != 'root';
 user	plugin	authentication_string
 plug	test_plugin_server	plug_dest
-plug_dest		NULL
+plug_dest	mysql_native_password	
 DROP USER plug, plug_dest;
 CREATE USER plug IDENTIFIED WITH 'test_plugin_server' AS 'plug_dest';
 SELECT user,plugin,authentication_string FROM mysql.user WHERE user != 'root';
@@ -115,7 +115,7 @@ DROP USER plug;
 CREATE USER plug_dest IDENTIFIED BY 'plug_dest_passwd';
 SELECT user,plugin,authentication_string FROM mysql.user WHERE user != 'root';
 user	plugin	authentication_string
-plug_dest		NULL
+plug_dest	mysql_native_password	
 DROP USER plug_dest;
 GRANT ALL PRIVILEGES ON test_user_db.* TO plug IDENTIFIED WITH 'test_plugin_server' AS 'plug_dest';
 SELECT user,plugin,authentication_string FROM mysql.user WHERE user != 'root';
@@ -125,7 +125,7 @@ CREATE USER plug_dest IDENTIFIED BY 'plu
 SELECT user,plugin,authentication_string FROM mysql.user WHERE user != 'root';
 user	plugin	authentication_string
 plug	test_plugin_server	plug_dest
-plug_dest		NULL
+plug_dest	mysql_native_password	
 DROP USER plug, plug_dest;
 GRANT ALL PRIVILEGES ON test_user_db.* TO plug IDENTIFIED WITH test_plugin_server AS 'plug_dest';
 SELECT user,plugin,authentication_string FROM mysql.user WHERE user != 'root';
@@ -135,7 +135,7 @@ DROP USER plug;
 CREATE USER plug_dest IDENTIFIED BY 'plug_dest_passwd';
 SELECT user,plugin,authentication_string FROM mysql.user WHERE user != 'root';
 user	plugin	authentication_string
-plug_dest		NULL
+plug_dest	mysql_native_password	
 DROP USER plug_dest;
 CREATE USER plug IDENTIFIED WITH 'test_plugin_server' AS 'plug_dest';
 SELECT user,plugin,authentication_string FROM mysql.user WHERE user != 'root';
@@ -145,7 +145,7 @@ GRANT ALL PRIVILEGES ON test_user_db.* T
 SELECT user,plugin,authentication_string FROM mysql.user WHERE user != 'root';
 user	plugin	authentication_string
 plug	test_plugin_server	plug_dest
-plug_dest		NULL
+plug_dest	mysql_native_password	
 DROP USER plug, plug_dest;
 CREATE USER plug IDENTIFIED WITH 'test_plugin_server' AS 'plug_dest';
 SELECT user,plugin,authentication_string FROM mysql.user WHERE user != 'root';
@@ -155,13 +155,13 @@ DROP USER plug;
 GRANT ALL PRIVILEGES ON test_user_db.* TO plug_dest IDENTIFIED BY 'plug_dest_passwd';
 SELECT user,plugin,authentication_string FROM mysql.user WHERE user != 'root';
 user	plugin	authentication_string
-plug_dest		NULL
+plug_dest	mysql_native_password	
 DROP USER plug_dest;
 CREATE USER plug IDENTIFIED WITH 'test_plugin_server' AS 'plug_dest';
+GRANTs which doesn't change the plugin are allowed
 GRANT ALL PRIVILEGES ON test_user_db.* TO plug IDENTIFIED WITH 'test_plugin_server' AS 'plug_dest';
-ERROR HY000: GRANT with IDENTIFIED WITH is illegal because the user plug already exists
+GRANTs which doesn't change the plugin are allowed
 GRANT ALL PRIVILEGES ON test_user_db.* TO plug IDENTIFIED WITH 'test_plugin_server';
-ERROR HY000: GRANT with IDENTIFIED WITH is illegal because the user plug already exists
 DROP USER plug;
 GRANT ALL PRIVILEGES ON test_user_db.* TO plug IDENTIFIED WITH test_plugin_server AS 'plug_dest';
 CREATE USER plug IDENTIFIED WITH 'test_plugin_server' AS 'plug_dest';
@@ -176,7 +176,7 @@ plug	test_plugin_server	plug_dest	
 GRANT ALL PRIVILEGES ON test_user_db.* TO plug IDENTIFIED BY 'plug_dest_passwd';
 SELECT user,plugin,authentication_string,password FROM mysql.user WHERE user != 'root';
 user	plugin	authentication_string	password
-plug	test_plugin_server	plug_dest	*939AEE68989794C0F408277411C26055CDF41119
+plug	test_plugin_server	plug_dest	
 DROP USER plug;
 GRANT ALL PRIVILEGES ON test_user_db.* TO plug IDENTIFIED WITH test_plugin_server AS 'plug_dest';
 CREATE USER plug IDENTIFIED BY 'plug_dest_passwd';
@@ -210,7 +210,7 @@ DROP USER plüg;
 CREATE USER plüg_dest IDENTIFIED BY 'plug_dest_passwd';
 SELECT user,plugin,authentication_string FROM mysql.user WHERE user != 'root';
 user	plugin	authentication_string
-plüg_dest		NULL
+plüg_dest	mysql_native_password	
 DROP USER plüg_dest;
 SET NAMES ascii;
 CREATE USER 'plüg' IDENTIFIED WITH 'test_plugin_server' AS 'plüg_dest';
@@ -221,7 +221,7 @@ DROP USER 'plüg';
 CREATE USER 'plüg_dest' IDENTIFIED BY 'plug_dest_passwd';
 SELECT user,plugin,authentication_string FROM mysql.user WHERE user != 'root';
 user	plugin	authentication_string
-pl??g_dest		NULL
+pl??g_dest	mysql_native_password	
 DROP USER 'plüg_dest';
 SET NAMES latin1;
 ========== test 1.1.1.5 ====================================
@@ -235,7 +235,7 @@ DROP USER 'plug';
 CREATE USER 'plüg_dest' IDENTIFIED BY 'plug_dest_passwd';
 SELECT user,plugin,authentication_string FROM mysql.user WHERE user != 'root';
 user	plugin	authentication_string
-plüg_dest		NULL
+plüg_dest	mysql_native_password	
 DROP USER 'plüg_dest';
 SET NAMES utf8;
 CREATE USER plüg IDENTIFIED WITH 'test_plügin_server' AS 'plüg_dest';
@@ -248,7 +248,7 @@ DROP USER 'plüg';
 CREATE USER 'plüg_dest' IDENTIFIED BY 'plug_dest_passwd';
 SELECT user,plugin,authentication_string FROM mysql.user WHERE user != 'root';
 user	plugin	authentication_string
-plüg_dest		NULL
+plüg_dest	mysql_native_password	
 DROP USER 'plüg_dest';
 CREATE USER plüg IDENTIFIED WITH test_plugin_server AS 'plüg_dest';
 SELECT user,plugin,authentication_string FROM mysql.user WHERE user != 'root';
@@ -258,7 +258,7 @@ DROP USER plüg;
 CREATE USER plüg_dest IDENTIFIED BY 'plug_dest_passwd';
 SELECT user,plugin,authentication_string FROM mysql.user WHERE user != 'root';
 user	plugin	authentication_string
-plüg_dest		NULL
+plüg_dest	mysql_native_password	
 DROP USER plüg_dest;
 ========== test 1.1.1.2/1.1.2.2=============================
 SET @auth_name= 'test_plugin_server';
@@ -278,7 +278,7 @@ DROP USER plug;
 CREATE USER 'hh''s_plug_dest' IDENTIFIED BY 'plug_dest_passwd';
 SELECT user,plugin,authentication_string FROM mysql.user WHERE user != 'root';
 user	plugin	authentication_string
-hh's_plug_dest		NULL
+hh's_plug_dest	mysql_native_password	
 DROP USER 'hh''s_plug_dest';
 ========== test 1.1.1.4 ====================================
 CREATE USER plug IDENTIFIED WITH hh''s_test_plugin_server AS 'plug_dest';
@@ -294,7 +294,7 @@ GRANT ALL PRIVILEGES ON test_user_db.* T
 SELECT user,plugin,authentication_string FROM mysql.user WHERE user != 'root';
 user	plugin	authentication_string
 grant_user	test_plugin_server	plug_dest
-plug_dest		NULL
+plug_dest	mysql_native_password	
 DROP USER grant_user,plug_dest;
 set @save_sql_mode= @@sql_mode;
 SET @@sql_mode=no_auto_create_user;
@@ -315,13 +315,13 @@ CREATE USER plug_dest IDENTIFIED BY 'plu
 SELECT user,plugin,authentication_string,password FROM mysql.user WHERE user != 'root';
 user	plugin	authentication_string	password
 grant_user	test_plugin_server	plug_dest	
-plug_dest		NULL	*939AEE68989794C0F408277411C26055CDF41119
+plug_dest	mysql_native_password		*939AEE68989794C0F408277411C26055CDF41119
 DROP USER plug_dest;
 GRANT ALL PRIVILEGES ON test_user_db.* TO plug_dest IDENTIFIED BY 'plug_user_passwd';
 SELECT user,plugin,authentication_string,password FROM mysql.user WHERE user != 'root';
 user	plugin	authentication_string	password
 grant_user	test_plugin_server	plug_dest	
-plug_dest		NULL	*560881EB651416CEF77314D07D55EDCD5FC1BD6D
+plug_dest	mysql_native_password		*560881EB651416CEF77314D07D55EDCD5FC1BD6D
 DROP USER grant_user,plug_dest;
 set @@sql_mode= @save_sql_mode;
 DROP DATABASE test_user_db;

=== modified file 'mysql-test/r/plugin_auth_qa_1.result'
--- a/mysql-test/r/plugin_auth_qa_1.result	2011-03-18 14:58:27 +0000
+++ b/mysql-test/r/plugin_auth_qa_1.result	2011-05-27 14:40:44 +0000
@@ -21,7 +21,7 @@ GRANT ALL PRIVILEGES ON test_user_db.* T
 GRANT PROXY ON plug_dest TO plug_user;
 SELECT user,plugin,authentication_string FROM mysql.user WHERE user != 'root';
 user	plugin	authentication_string
-plug_dest		NULL
+plug_dest	mysql_native_password	
 plug_user	test_plugin_server	plug_dest
 1)
 current_user()
@@ -74,7 +74,7 @@ GRANT PROXY ON new_dest TO plug_user;
 ERROR 1045 (28000): Access denied for user 'plug_user'@'localhost' (using password: YES)
 SELECT user,plugin,authentication_string FROM mysql.user WHERE user != 'root';
 user	plugin	authentication_string
-new_dest		NULL
+new_dest	mysql_native_password	
 plug_user	test_plugin_server	plug_dest
 DROP USER plug_user,new_dest;
 CREATE USER plug_user
@@ -92,7 +92,7 @@ GRANT PROXY ON new_dest TO plug_user;
 ERROR 1045 (28000): Access denied for user 'plug_user'@'localhost' (using password: YES)
 SELECT user,plugin,authentication_string FROM mysql.user WHERE user != 'root';
 user	plugin	authentication_string
-new_dest		NULL
+new_dest	mysql_native_password	
 plug_user	test_plugin_server	plug_dest
 DROP USER plug_user,new_dest;
 CREATE USER plug_user
@@ -114,13 +114,13 @@ connection default;
 SELECT user,plugin,authentication_string FROM mysql.user WHERE user != 'root';
 user	plugin	authentication_string
 new_user	test_plugin_server	plug_dest
-plug_dest		NULL
+plug_dest	mysql_native_password	
 disconnect plug_user;
 UPDATE mysql.user SET user='plug_user' WHERE user='new_user';
 FLUSH PRIVILEGES;
 SELECT user,plugin,authentication_string FROM mysql.user WHERE user != 'root';
 user	plugin	authentication_string
-plug_dest		NULL
+plug_dest	mysql_native_password	
 plug_user	test_plugin_server	plug_dest
 DROP USER plug_dest,plug_user;
 ========== test 1.3 ========================================
@@ -136,26 +136,26 @@ connection default;
 disconnect plug_user;
 SELECT user,plugin,authentication_string FROM mysql.user WHERE user != 'root';
 user	plugin	authentication_string
-plug_dest		NULL
+plug_dest	mysql_native_password	
 plug_user	test_plugin_server	plug_dest
 UPDATE mysql.user SET user='new_user' WHERE user='plug_user';
 FLUSH PRIVILEGES;
 SELECT user,plugin,authentication_string FROM mysql.user WHERE user != 'root';
 user	plugin	authentication_string
 new_user	test_plugin_server	plug_dest
-plug_dest		NULL
+plug_dest	mysql_native_password	
 UPDATE mysql.user SET authentication_string='new_dest' WHERE user='new_user';
 FLUSH PRIVILEGES;
 SELECT user,plugin,authentication_string FROM mysql.user WHERE user != 'root';
 user	plugin	authentication_string
 new_user	test_plugin_server	new_dest
-plug_dest		NULL
+plug_dest	mysql_native_password	
 UPDATE mysql.user SET plugin='new_plugin_server' WHERE user='new_user';
 FLUSH PRIVILEGES;
 SELECT user,plugin,authentication_string FROM mysql.user WHERE user != 'root';
 user	plugin	authentication_string
 new_user	new_plugin_server	new_dest
-plug_dest		NULL
+plug_dest	mysql_native_password	
 connect(plug_user,localhost,new_user,new_dest);
 ERROR HY000: Plugin 'new_plugin_server' is not loaded
 UPDATE mysql.user SET plugin='test_plugin_server' WHERE user='new_user';
@@ -164,7 +164,7 @@ FLUSH PRIVILEGES;
 GRANT PROXY ON new_dest TO new_user;
 SELECT user,plugin,authentication_string FROM mysql.user WHERE user != 'root';
 user	plugin	authentication_string
-new_dest		NULL
+new_dest	mysql_native_password	
 new_user	test_plugin_server	new_dest
 connect(plug_user,localhost,new_user,new_dest);
 select USER(),CURRENT_USER();
@@ -177,9 +177,9 @@ FLUSH PRIVILEGES;
 CREATE USER new_dest IDENTIFIED BY 'new_dest_passwd';
 SELECT user,plugin,authentication_string FROM mysql.user WHERE user != 'root';
 user	plugin	authentication_string
-new_dest		NULL
+new_dest	mysql_native_password	
 new_user	test_plugin_server	new_dest
-plug_dest		NULL
+plug_dest	mysql_native_password	
 GRANT ALL PRIVILEGES ON test.* TO new_user;
 connect(plug_user,localhost,new_dest,new_dest_passwd);
 select USER(),CURRENT_USER();
@@ -194,7 +194,7 @@ CREATE USER proxied_user IDENTIFIED BY '
 SELECT user,plugin,authentication_string FROM mysql.user WHERE user != 'root';
 user	plugin	authentication_string
 	test_plugin_server	proxied_user
-proxied_user		NULL
+proxied_user	mysql_native_password	
 connect(proxy_con,localhost,proxied_user,proxied_user_passwd);
 SELECT USER(),CURRENT_USER();
 USER()	CURRENT_USER()
@@ -231,7 +231,7 @@ CREATE USER proxied_user IDENTIFIED BY '
 SELECT user,plugin,authentication_string FROM mysql.user WHERE user != 'root';
 user	plugin	authentication_string
 	test_plugin_server	proxied_user
-proxied_user		NULL
+proxied_user	mysql_native_password	
 connect(proxy_con,localhost,proxied_user,proxied_user_passwd);
 SELECT USER(),CURRENT_USER();
 USER()	CURRENT_USER()
@@ -274,11 +274,11 @@ GRANT PROXY ON proxied_user_5 TO ''@'';
 SELECT user,plugin,authentication_string FROM mysql.user WHERE user != 'root';
 user	plugin	authentication_string
 	test_plugin_server	proxied_user
-proxied_user_1		NULL
-proxied_user_2		NULL
-proxied_user_3		NULL
-proxied_user_4		NULL
-proxied_user_5		NULL
+proxied_user_1	mysql_native_password	
+proxied_user_2	mysql_native_password	
+proxied_user_3	mysql_native_password	
+proxied_user_4	mysql_native_password	
+proxied_user_5	mysql_native_password	
 connect(proxy_con_1,localhost,proxied_user_1,'proxied_user_1_pwd');
 connect(proxy_con_2,localhost,proxied_user_2,proxied_user_2_pwd);
 connect(proxy_con_3,localhost,proxied_user_3,proxied_user_3_pwd);

=== modified file 'mysql-test/r/plugin_auth_qa_2.result'
--- a/mysql-test/r/plugin_auth_qa_2.result	2011-03-18 14:16:17 +0000
+++ b/mysql-test/r/plugin_auth_qa_2.result	2011-05-27 14:40:44 +0000
@@ -7,7 +7,7 @@ GRANT ALL PRIVILEGES ON test_user_db.* T
 GRANT PROXY ON qa_test_1_dest TO qa_test_1_user;
 SELECT user,plugin,authentication_string FROM mysql.user WHERE user != 'root';
 user	plugin	authentication_string
-qa_test_1_dest		NULL
+qa_test_1_dest	mysql_native_password	
 qa_test_1_user	qa_auth_interface	qa_test_1_dest
 SELECT @@proxy_user;
 @@proxy_user
@@ -20,7 +20,7 @@ current_user()	user()	@@local.proxy_user
 qa_test_1_user@%	qa_test_1_user@localhost	NULL	NULL
 SELECT user,plugin,authentication_string FROM mysql.user WHERE user != 'root';
 user	plugin	authentication_string
-qa_test_1_dest		NULL
+qa_test_1_dest	mysql_native_password	
 qa_test_1_user	qa_auth_interface	qa_test_1_dest
 DROP USER qa_test_1_user;
 DROP USER qa_test_1_dest;
@@ -33,8 +33,8 @@ GRANT PROXY ON qa_test_2_dest TO qa_test
 GRANT PROXY ON authenticated_as TO qa_test_2_user;
 SELECT user,plugin,authentication_string FROM mysql.user WHERE user != 'root';
 user	plugin	authentication_string
-authenticated_as		NULL
-qa_test_2_dest		NULL
+authenticated_as	mysql_native_password	
+qa_test_2_dest	mysql_native_password	
 qa_test_2_user	qa_auth_interface	qa_test_2_dest
 SELECT @@proxy_user;
 @@proxy_user
@@ -47,8 +47,8 @@ current_user()	user()	@@local.proxy_user
 authenticated_as@%	user_name@localhost	'qa_test_2_user'@'%'	'qa_test_2_user'@'%'
 SELECT user,plugin,authentication_string FROM mysql.user WHERE user != 'root';
 user	plugin	authentication_string
-authenticated_as		NULL
-qa_test_2_dest		NULL
+authenticated_as	mysql_native_password	
+qa_test_2_dest	mysql_native_password	
 qa_test_2_user	qa_auth_interface	qa_test_2_dest
 DROP USER qa_test_2_user;
 DROP USER qa_test_2_dest;
@@ -83,8 +83,8 @@ GRANT PROXY ON qa_test_5_dest TO qa_test
 GRANT PROXY ON qa_test_5_dest TO ''@'localhost';
 SELECT user,plugin,authentication_string,password FROM mysql.user WHERE user != 'root';
 user	plugin	authentication_string	password
-		NULL	*DFCACE76914AD7BD801FC1A1ECF6562272621A22
-qa_test_5_dest		NULL	*DFCACE76914AD7BD801FC1A1ECF6562272621A22
+	mysql_native_password		*DFCACE76914AD7BD801FC1A1ECF6562272621A22
+qa_test_5_dest	mysql_native_password		*DFCACE76914AD7BD801FC1A1ECF6562272621A22
 qa_test_5_user	qa_auth_interface	qa_test_5_dest	
 exec MYSQL PLUGIN_AUTH_OPT -h localhost -P MASTER_MYPORT --user=qa_test_5_user  --password=qa_test_5_dest test_user_db -e "SELECT current_user(),user(),@@local.proxy_user,@@local.external_user;" 2>&1
 ERROR 1045 (28000): Access denied for user 'qa_test_5_user'@'localhost' (using password: YES)
@@ -98,7 +98,7 @@ GRANT ALL PRIVILEGES ON test_user_db.* T
 GRANT PROXY ON qa_test_6_dest TO qa_test_6_user;
 SELECT user,plugin,authentication_string,password FROM mysql.user;
 user	plugin	authentication_string	password
-qa_test_6_dest		NULL	*DFCACE76914AD7BD801FC1A1ECF6562272621A22
+qa_test_6_dest	mysql_native_password		*DFCACE76914AD7BD801FC1A1ECF6562272621A22
 qa_test_6_user	qa_auth_interface	qa_test_6_dest	
 root			
 root			
@@ -109,7 +109,7 @@ ERROR 1045 (28000): Access denied for us
 GRANT PROXY ON qa_test_6_dest TO root IDENTIFIED WITH qa_auth_interface AS 'qa_test_6_dest';
 SELECT user,plugin,authentication_string,password FROM mysql.user;
 user	plugin	authentication_string	password
-qa_test_6_dest		NULL	*DFCACE76914AD7BD801FC1A1ECF6562272621A22
+qa_test_6_dest	mysql_native_password		*DFCACE76914AD7BD801FC1A1ECF6562272621A22
 qa_test_6_user	qa_auth_interface	qa_test_6_dest	
 root			
 root			
@@ -121,7 +121,7 @@ ERROR 1045 (28000): Access denied for us
 REVOKE PROXY ON qa_test_6_dest FROM root;
 SELECT user,plugin,authentication_string FROM mysql.user;
 user	plugin	authentication_string
-qa_test_6_dest		NULL
+qa_test_6_dest	mysql_native_password	
 qa_test_6_user	qa_auth_interface	qa_test_6_dest
 root		
 root		

=== added file 'mysql-test/r/plugin_auth_sha256.result'
--- a/mysql-test/r/plugin_auth_sha256.result	1970-01-01 00:00:00 +0000
+++ b/mysql-test/r/plugin_auth_sha256.result	2011-05-27 14:40:44 +0000
@@ -0,0 +1,38 @@
+CREATE USER 'kristofer' IDENTIFIED WITH 'sha256_password';
+SET @@old_passwords=2;
+SET PASSWORD FOR 'kristofer'=PASSWORD('secret');
+SELECT user, plugin FROM mysql.user;
+user	plugin
+root	
+root	
+root	
+root	
+kristofer	sha256_password
+SELECT USER(),CURRENT_USER();
+USER()	CURRENT_USER()
+kristofer@localhost	kristofer@%
+DROP USER 'kristofer';
+GRANT ALL ON *.* TO 'kristofer'@'localhost' IDENTIFIED WITH 'sha256_password';
+SET PASSWORD FOR 'kristofer'@'localhost'=PASSWORD('secret2');
+SELECT USER(),CURRENT_USER();
+USER()	CURRENT_USER()
+kristofer@localhost	kristofer@localhost
+SHOW GRANTS FOR 'kristofer'@'localhost';
+Grants for kristofer@localhost
+GRANT ALL PRIVILEGES ON *.* TO 'kristofer'@'localhost' IDENTIFIED BY PASSWORD '{$5}'
+DROP USER 'kristofer'@'localhost';
+GRANT ALL ON *.* TO 'kristofer'@'localhost' IDENTIFIED WITH 'sha256_password';
+SET PASSWORD FOR 'kristofer'@'localhost'=PASSWORD('');
+SELECT USER(),CURRENT_USER();
+USER()	CURRENT_USER()
+kristofer@localhost	kristofer@localhost
+SHOW GRANTS FOR 'kristofer'@'localhost';
+Grants for kristofer@localhost
+GRANT ALL PRIVILEGES ON *.* TO 'kristofer'@'localhost' IDENTIFIED BY PASSWORD '{$5}'
+DROP USER 'kristofer'@'localhost';
+GRANT ALL ON *.* TO 'kristofer'@'33.33.33.33' IDENTIFIED WITH 'sha256_password';
+SET PASSWORD FOR 'kristofer'@'33.33.33.33'=PASSWORD('');
+Connection should fail for localhost
+connect(localhost,kristofer,,test,13000,/home/thek/bzr/mysql-trunk-security/build/mysql-test/var/tmp/mysqld.1.sock);
+ERROR 28000: Access denied for user 'kristofer'@'localhost' (using password: NO)
+DROP USER 'kristofer'@'33.33.33.33';

=== modified file 'mysql-test/t/plugin_auth.test'
--- a/mysql-test/t/plugin_auth.test	2011-04-07 09:55:09 +0000
+++ b/mysql-test/t/plugin_auth.test	2011-05-27 14:40:44 +0000
@@ -8,9 +8,7 @@ query_vertical SELECT PLUGIN_STATUS, PLU
 
 CREATE USER plug IDENTIFIED WITH 'test_plugin_server' AS 'plug_dest';
 CREATE USER plug_dest IDENTIFIED BY 'plug_dest_passwd';
-
 SELECT plugin,authentication_string FROM mysql.user WHERE User='plug';
-
 --echo ## test plugin auth
 --disable_query_log
 --error ER_ACCESS_DENIED_ERROR : this should fail : no grant
@@ -31,6 +29,7 @@ select USER(),CURRENT_USER();
 
 --echo ## test SET PASSWORD
 #--error ER_SET_PASSWORD_AUTH_PLUGIN
+--echo Setting password is allowed but it won't affect the authentication mechanism.
 SET PASSWORD = PASSWORD('plug_dest');
 
 connection default;
@@ -62,7 +61,6 @@ SET @@sql_mode=no_auto_create_user;
 GRANT INSERT ON TEST.* TO grant_user IDENTIFIED WITH 'test_plugin_server';
 SET @@sql_mode=default;
 DROP USER grant_user;
-
 --echo ## test utf-8 user name
 CREATE USER `Ÿ` IDENTIFIED WITH 'test_plugin_server' AS 'plug_dest';
 
@@ -82,8 +80,7 @@ CREATE DATABASE test_grant_db;
 
 --echo # create new user via GRANT WITH
 GRANT ALL PRIVILEGES ON test_grant_db.* TO new_grant_user 
-  IDENTIFIED WITH 'test_plugin_server' AS 'plug_dest';
-
+IDENTIFIED WITH 'test_plugin_server' AS 'plug_dest';
 GRANT PROXY ON plug_dest TO new_grant_user;  
 
 connect(plug_con_grant,localhost,new_grant_user,plug_dest);
@@ -105,7 +102,6 @@ GRANT ALL PRIVILEGES ON test_grant_db.* 
 --error ER_ACCESS_DENIED_ERROR
 connect(plug_con_grant_deny,localhost,new_grant_user,unused_password);
 --enable_query_log
-
 --echo #make sure plugin auth still available
 connect(plug_con_grant,localhost,new_grant_user,plug_dest);
 connection plug_con_grant;
@@ -119,8 +115,8 @@ disconnect plug_con_grant;
 DROP USER new_grant_user;
 
 --echo # try re-create existing user via GRANT IDENTIFIED WITH
-
---error ER_GRANT_PLUGIN_USER_EXISTS
+#--error ER_GRANT_PLUGIN_USER_EXISTS
+--echo GRANTS which don't affect current plugin are allowed!
 GRANT ALL PRIVILEGES ON test_grant_db.* TO plug
   IDENTIFIED WITH 'test_plugin_server' AS 'plug_dest';
 
@@ -512,5 +508,4 @@ SELECT IS_NULLABLE, COLUMN_NAME FROM INF
     COLUMN_NAME IN ('plugin', 'authentication_string')
   ORDER BY COLUMN_NAME;
 
-
 --echo End of 5.5 tests

=== modified file 'mysql-test/t/plugin_auth_qa.test'
--- a/mysql-test/t/plugin_auth_qa.test	2010-10-20 14:56:09 +0000
+++ b/mysql-test/t/plugin_auth_qa.test	2011-05-27 14:40:44 +0000
@@ -166,9 +166,11 @@ SELECT user,plugin,authentication_string
 DROP USER plug_dest;
 # 
 CREATE USER plug IDENTIFIED WITH 'test_plugin_server' AS 'plug_dest';
---error 1700
+#--error 1700
+--echo GRANTs which doesn't change the plugin are allowed
 GRANT ALL PRIVILEGES ON test_user_db.* TO plug IDENTIFIED WITH 'test_plugin_server' AS 'plug_dest';
---error 1700
+#--error 1700
+--echo GRANTs which doesn't change the plugin are allowed
 GRANT ALL PRIVILEGES ON test_user_db.* TO plug IDENTIFIED WITH 'test_plugin_server';
 DROP USER plug;
 #

=== added file 'mysql-test/t/plugin_auth_sha256.test'
--- a/mysql-test/t/plugin_auth_sha256.test	1970-01-01 00:00:00 +0000
+++ b/mysql-test/t/plugin_auth_sha256.test	2011-05-27 14:40:44 +0000
@@ -0,0 +1,41 @@
+--source include/not_embedded.inc
+--source include/mysql_upgrade_preparation.inc
+
+CREATE USER 'kristofer' IDENTIFIED WITH 'sha256_password';
+SET @@old_passwords=2;
+SET PASSWORD FOR 'kristofer'=PASSWORD('secret');
+SELECT user, plugin FROM mysql.user;
+connect(con1,localhost,kristofer,secret,,);
+connection con1;
+SELECT USER(),CURRENT_USER();
+connection default;
+disconnect con1;
+DROP USER 'kristofer';
+
+GRANT ALL ON *.* TO 'kristofer'@'localhost' IDENTIFIED WITH 'sha256_password';
+SET PASSWORD FOR 'kristofer'@'localhost'=PASSWORD('secret2');
+connect(con2,localhost,kristofer,secret2,,);
+connection con2;
+SELECT USER(),CURRENT_USER();
+SHOW GRANTS FOR 'kristofer'@'localhost';
+connection default;
+disconnect con2;
+DROP USER 'kristofer'@'localhost';
+
+GRANT ALL ON *.* TO 'kristofer'@'localhost' IDENTIFIED WITH 'sha256_password';
+SET PASSWORD FOR 'kristofer'@'localhost'=PASSWORD('');
+connect(con3,localhost,kristofer,,,);
+connection con3;
+SELECT USER(),CURRENT_USER();
+SHOW GRANTS FOR 'kristofer'@'localhost';
+connection default;
+disconnect con3;
+DROP USER 'kristofer'@'localhost';
+
+GRANT ALL ON *.* TO 'kristofer'@'33.33.33.33' IDENTIFIED WITH 'sha256_password';
+SET PASSWORD FOR 'kristofer'@'33.33.33.33'=PASSWORD('');
+--echo Connection should fail for localhost
+--error ER_ACCESS_DENIED_ERROR
+connect(con4,localhost,kristofer,,,);
+DROP USER 'kristofer'@'33.33.33.33';
+

=== modified file 'scripts/mysql_system_tables.sql'
--- a/scripts/mysql_system_tables.sql	2011-03-18 22:51:17 +0000
+++ b/scripts/mysql_system_tables.sql	2011-05-27 14:40:44 +0000
@@ -28,7 +28,7 @@ set @had_db_table= @@warning_count != 0;
 CREATE TABLE IF NOT EXISTS host (  Host char(60) binary DEFAULT '' NOT NULL, Db char(64) binary DEFAULT '' NOT NULL, Select_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Insert_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Update_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Delete_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Drop_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Grant_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, References_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Index_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_tmp_table_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Lock_tables_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Show_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Execute_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Trigger_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, PRIMARY KEY Host (Host,Db) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Host privileges;  Merged with database privileges';
 
 
-CREATE TABLE IF NOT EXISTS user (   Host char(60) binary DEFAULT '' NOT NULL, User char(16) binary DEFAULT '' NOT NULL, Password char(41) character set latin1 collate latin1_bin DEFAULT '' NOT NULL, Select_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Insert_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Update_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Delete_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Drop_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Reload_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Shutdown_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Process_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, File_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Grant_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, References_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Index_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Show_db_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Super_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_tmp_table_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Lock_tables_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Execute_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Repl_slave_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Repl_client_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Show_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_user_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Event_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Trigger_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_tablespace_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, ssl_type enum('','ANY','X509', 'SPECIFIED') COLLATE utf8_general_ci DEFAULT '' NOT NULL, ssl_cipher BLOB NOT NULL, x509_issuer BLOB NOT NULL, x509_subject BLOB NOT NULL, max_questions int(11) unsigned DEFAULT 0  NOT NULL, max_updates int(11) unsigned DEFAULT 0  NOT NULL, max_connections int(11) unsigned DEFAULT 0  NOT NULL, max_user_connections int(11) unsigned DEFAULT 0  NOT NULL, plugin char(64) DEFAULT '', authentication_string TEXT, PRIMARY KEY Host (Host,User) ) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Users and global privileges';
+CREATE TABLE IF NOT EXISTS user (  Host char(60) binary DEFAULT '' NOT NULL, User char(16) binary DEFAULT '' NOT NULL, Password char(41) character set latin1 collate latin1_bin DEFAULT '' NOT NULL, Select_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Insert_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Update_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Delete_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Drop_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Reload_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Shutdown_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Process_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, File_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Grant_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, References_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Index_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Show_db_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Super_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_tmp_table_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Lock_tables_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Execute_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Repl_slave_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Repl_client_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Show_view_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Alter_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_user_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Event_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Trigger_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, Create_tablespace_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL, ssl_type enum('','ANY','X509', 'SPECIFIED') COLLATE utf8_general_ci DEFAULT '' NOT NULL, ssl_cipher BLOB NOT NULL, x509_issuer BLOB NOT NULL, x509_subject BLOB NOT NULL, max_questions int(11) unsigned DEFAULT 0  NOT NULL, max_updates int(11) unsigned DEFAULT 0  NOT NULL, max_connections int(11) unsigned DEFAULT 0  NOT NULL, max_user_connections int(11) unsigned DEFAULT 0  NOT NULL, plugin char(64) DEFAULT '', authentication_string TEXT, Password2 VARCHAR(80) character set latin1 collate latin1_bin DEFAULT '' NOT NULL, PRIMARY KEY Host (Host,User)) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Users and global privileges';
 
 -- Remember for later if user table already existed
 set @had_user_table= @@warning_count != 0;

=== modified file 'scripts/mysql_system_tables_data.sql'
--- a/scripts/mysql_system_tables_data.sql	2010-12-29 00:38:59 +0000
+++ b/scripts/mysql_system_tables_data.sql	2011-05-27 14:40:44 +0000
@@ -36,10 +36,10 @@ DROP TABLE tmp_db;
 -- from local machine if "users" table didn't exist before
 CREATE TEMPORARY TABLE tmp_user LIKE user;
 set @current_hostname= @@hostname;
-INSERT INTO tmp_user VALUES ('localhost','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0,'','');
-REPLACE INTO tmp_user SELECT @current_hostname,'root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0,'','' FROM dual WHERE LOWER( @current_hostname) != 'localhost';
-REPLACE INTO tmp_user VALUES ('127.0.0.1','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0,'','');
-REPLACE INTO tmp_user VALUES ('::1','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0,'','');
+INSERT INTO tmp_user VALUES ('localhost','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0,'','','');
+REPLACE INTO tmp_user SELECT @current_hostname,'root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0,'','','' FROM dual WHERE LOWER( @current_hostname) != 'localhost';
+REPLACE INTO tmp_user VALUES ('127.0.0.1','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0,'','','');
+REPLACE INTO tmp_user VALUES ('::1','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0,0,'','','');
 INSERT INTO tmp_user (host,user) VALUES ('localhost','');
 INSERT INTO tmp_user (host,user) SELECT @current_hostname,'' FROM dual WHERE LOWER(@current_hostname ) != 'localhost';
 INSERT INTO user SELECT * FROM tmp_user WHERE @had_user_table=0;

=== modified file 'sql-common/client.c'
--- a/sql-common/client.c	2011-03-17 09:43:28 +0000
+++ b/sql-common/client.c	2011-05-27 14:40:44 +0000
@@ -36,6 +36,7 @@
 #include <my_global.h>
 
 #include "mysql.h"
+#include "crypt_genhash_impl.h"
 
 #ifndef __WIN__
 #include <netdb.h>
@@ -2271,6 +2272,7 @@ static int client_mpvio_write_packet(str
 static int native_password_auth_client(MYSQL_PLUGIN_VIO *vio, MYSQL *mysql);
 static int old_password_auth_client(MYSQL_PLUGIN_VIO *vio, MYSQL *mysql);
 static int clear_password_auth_client(MYSQL_PLUGIN_VIO *vio, MYSQL *mysql);
+static int sha256_password_auth_client(MYSQL_PLUGIN_VIO *vio, MYSQL *mysql);
 
 static auth_plugin_t native_password_client_plugin=
 {
@@ -2320,11 +2322,28 @@ static auth_plugin_t clear_password_clie
   clear_password_auth_client
 };
 
+static auth_plugin_t sha256_password_client_plugin=
+{
+  MYSQL_CLIENT_AUTHENTICATION_PLUGIN,
+  MYSQL_CLIENT_AUTHENTICATION_PLUGIN_INTERFACE_VERSION,
+  "sha256_password",
+  "Oracle Inc",
+  "SHA256 based authentication with salt",
+  {1, 0, 0},
+  "GPL",
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+  sha256_password_auth_client
+};
+
 struct st_mysql_client_plugin *mysql_client_builtins[]=
 {
   (struct st_mysql_client_plugin *)&native_password_client_plugin,
   (struct st_mysql_client_plugin *)&old_password_client_plugin,
   (struct st_mysql_client_plugin *)&clear_password_client_plugin,
+  (struct st_mysql_client_plugin *)&sha256_password_client_plugin,
   0
 };
 
@@ -4411,4 +4430,88 @@ static int clear_password_auth_client(MY
   return res ? CR_ERROR : CR_OK;
 }
 
+static int sha256_password_auth_client(MYSQL_PLUGIN_VIO *vio, MYSQL *mysql)
+{
+  int pkt_len;
+  uchar *pkt;
+  const char *one_round_params[2]= {"rounds=1", 0 };
+  my_bool uses_passwords;
+  
+  uses_passwords= mysql->passwd[0] != 0;
+
+  DBUG_ENTER("sha256_password_auth_client");
+
+  if (((MCPVIO_EXT *)vio)->mysql_change_user)
+  {
+    /*
+      in mysql_change_user() the client sends the first packet.
+      we use the old scramble.
+    */
+    pkt= (uchar*)mysql->scramble;
+    pkt_len= SCRAMBLE_LENGTH + 1;
+  }
+  else
+  {
+    /* read the scramble */
+    if ((pkt_len= vio->read_packet(vio, &pkt)) < 0)
+      DBUG_RETURN(CR_ERROR);
+
+    if (pkt_len != SCRAMBLE_LENGTH + 1)
+      DBUG_RETURN(CR_SERVER_HANDSHAKE_ERR);
+
+    /* save it in MYSQL */
+    memcpy(mysql->scramble, pkt, SCRAMBLE_LENGTH);
+    mysql->scramble[SCRAMBLE_LENGTH] = 0;
+  }
+
+  /* Send package to request user salt */
+  if (vio->write_packet(vio, (uchar*)&uses_passwords,1))
+    DBUG_RETURN(CR_ERROR);
+  
+  /*
+    If no password is used the server got all information it needs and the 
+    plugin authentication process is done. Authentication will fail if the
+    network address of the client doesn't match server host restrictions.
+  */
+  if (!uses_passwords)
+    DBUG_RETURN(CR_OK);
+  
+  /* Receive user salt */
+  unsigned length;
+  if ((length= vio->read_packet(vio, &pkt)) < 0)
+    DBUG_RETURN(CR_ERROR);
+    
+  /* Validate salt */
+  length= ((length < (CRYPT_SALT_LENGTH)) ?
+            length : (CRYPT_SALT_LENGTH));
+  char user_salt[CRYPT_SALT_LENGTH+1];
+  memcpy(user_salt, pkt, length);
+  user_salt[length]= 0;
+  
+  /* Generate password hash */
+  char scrambled[CRYPT_MAX_PASSWORD_SIZE+1];
+  char scrambled_random[CRYPT_MAX_PASSWORD_SIZE+1];
+  int passwd_len= strlen(mysql->passwd);
+  DBUG_PRINT("info", ("sending scramble"));
+  crypt_genhash_impl(scrambled,
+                     CRYPT_MAX_PASSWORD_SIZE,
+                     mysql->passwd,
+                     passwd_len,
+                     user_salt,
+                     0);
+  int scrambled_len= strlen(scrambled);
+  crypt_genhash_impl(scrambled_random,
+                     CRYPT_MAX_PASSWORD_SIZE,
+                     scrambled,
+                     scrambled_len,
+                     mysql->scramble,
+                     one_round_params);                                         
+  if (vio->write_packet(vio, (uchar*)scrambled_random,
+                             strlen(scrambled_random)))
+    DBUG_RETURN(CR_ERROR);
+ 
+  DBUG_RETURN(CR_OK);
+}
+
+
 

=== added file 'sql-common/crypt_genhash_impl.cc'
--- a/sql-common/crypt_genhash_impl.cc	1970-01-01 00:00:00 +0000
+++ b/sql-common/crypt_genhash_impl.cc	2011-05-27 14:40:44 +0000
@@ -0,0 +1,423 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <errno.h>
+#include <string.h>
+#include <time.h>
+#ifdef HAVE_OPENSSL
+#ifdef HAVE_YASSL
+#include <sha.hpp>
+#else
+#include <sys/types.h>
+#include <openssl/sha.h>
+#endif
+#endif
+
+#include "crypt_genhash_impl.h"
+
+#ifndef HAVE_YASSL
+#define	DIGEST_CTX	SHA256_CTX
+#define	DIGESTInit	SHA256_Init
+#define	DIGESTUpdate	SHA256_Update
+#define	DIGESTFinal	SHA256_Final
+#define	DIGEST_LEN	SHA256_DIGEST_LENGTH
+#else
+#define DIGEST_CTX TaoCrypt::SHA256
+#define DIGEST_LEN 32
+void DIGESTInit(DIGEST_CTX *ctx)
+{
+  ctx->Init();
+}
+
+void DIGESTUpdate(DIGEST_CTX *ctx, const void *plaintext, int len)
+{
+  ctx->Update((const TaoCrypt::byte *)plaintext, len);
+}
+
+void DIGESTFinal(void *txt, DIGEST_CTX *ctx)
+{
+  ctx->Final((TaoCrypt::byte *)txt);
+}
+
+#endif // HAVE_YASSL
+
+static const char crypt_alg_magic[] = "$5";
+
+#ifndef MAX
+#define MAX(a, b)  (((a) > (b)) ? (a) : (b))
+#endif
+#ifndef MIN
+#define MIN(a, b)  (((a) < (b)) ? (a) : (b))
+#endif
+#ifndef B_FALSE
+#define B_FALSE 0
+#endif
+#ifndef B_TRUE
+#define B_TRUE 1
+#endif
+
+
+size_t
+strlcat(char *dst, const char *src, size_t siz)
+{
+  char *d= dst;
+  const char *s= src;
+  size_t n= siz;
+  size_t dlen;
+  /* Find the end of dst and adjust bytes left but don't go past end */
+  while (n-- != 0 && *d != '\0')
+    d++;
+  dlen= d - dst;
+  n= siz - dlen;
+  if (n == 0)
+    return(dlen + strlen(s));
+  while (*s != '\0')
+  {
+    if (n != 1)
+    {
+      *d++= *s;
+      n--;
+    }
+    s++;
+  }
+  *d= '\0';
+  return(dlen + (s - src));       /* count does not include NUL */
+}
+
+static const int crypt_alg_magic_len = sizeof (crypt_alg_magic) - 1;
+
+static unsigned char b64t[] =		/* 0 ... 63 => ascii - 64 */
+	"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+
+#define	b64_from_24bit(B2, B1, B0, N) \
+{ \
+	uint32_t w = ((B2) << 16) | ((B1) << 8) | (B0); \
+	int n = (N); \
+	while (--n >= 0 && ctbufflen > 0) { \
+		*p++ = b64t[w & 0x3f]; \
+		w >>= 6; \
+		ctbufflen--; \
+} \
+}
+
+#define	ROUNDS		"rounds="
+#define	ROUNDSLEN	(sizeof (ROUNDS) - 1)
+
+typedef bool boolean_t;
+
+/**
+  Get the integer value after rounds= where ever it occurs in the string.
+  if the last char after the int is a , or $ that is fine anything else is an
+  error.
+*/
+static uint getrounds(const char *s)
+{
+	const char *r;
+	const char *p;
+	char *e;
+	long val;
+
+	if (s == NULL)
+		return (0);
+
+	if ((r = strstr(s, ROUNDS)) == NULL)
+	{
+		return (0);
+	}
+
+	if (strncmp(r, ROUNDS, ROUNDSLEN) != 0)
+	{
+		return (0);
+	}
+
+	p = r + ROUNDSLEN;
+	errno= 0;
+	val = strtol(p, &e, 10);
+	/*
+	 * An error occurred or there is non-numeric stuff at the end
+	 * which isn't one of the crypt(3c) special chars ',' or '$'
+	 */
+	if (errno != 0 || val < 0 || !(*e == '\0' || *e == ',' || *e == '$'))
+  {
+		return (0);
+	}
+
+	return ((uint32_t)val);
+}
+
+/**
+  Finds the intervall which envelopes the user salt in a crypt password
+  The crypt format is assumed to be $a$bbbb$cccccc\0 and the salt is found
+  by counting the delimiters and marking begin and end.
+
+   @param salt_being[in] Pointer to start of crypt passwd
+   @param salt_being[out] Pointer to first byte of the salt
+   @param salt_end[in] Pointer to the last byte in passwd
+   @param salt_end[out] Pointer to the byte immediatly following the salt ($)
+
+   @return The size of the salt identified
+*/
+
+int extract_user_salt(char **salt_begin,
+                      char **salt_end)
+{
+  char *it= *salt_begin;
+  int delimiter_count= 0;
+  while(it != *salt_end)
+  {
+    if (*it == '$')
+    {
+      ++delimiter_count;
+      if (delimiter_count == 2)
+      {
+        *salt_begin= it+1;
+      }
+      if (delimiter_count == 3)
+        break;
+    }
+    ++it;
+  }
+  *salt_end= it;
+  return *salt_end - *salt_begin;
+}
+
+const char *sha256_find_digest(char *pass)
+{
+  int sz= strlen(pass);
+  return pass+sz-(10*4+3);
+}
+
+/*
+ * Portions of the below code come from crypt_bsdmd5.so (bsdmd5.c) :
+ * ----------------------------------------------------------------------------
+ * "THE BEER-WARE LICENSE" (Revision 42):
+ * <phk@strippedt.dk> wrote this file.  As long as you retain this notice you
+ * can do whatever you want with this stuff. If we meet some day, and you think
+ * this stuff is worth it, you can buy me a beer in return.   Poul-Henning Kamp
+ * ----------------------------------------------------------------------------
+ *
+ * $FreeBSD: crypt.c,v 1.5 1996/10/14 08:34:02 phk Exp $
+ *
+ */
+
+/*
+ * The below code implements the specification from:
+ *
+ * From http://people.redhat.com/drepper/SHA-crypt.txt
+ *
+ * Portions of the code taken from inspired by or verified against the
+ * source in the above document which is licensed as:
+ *
+ * "Released into the Public Domain by Ulrich Drepper <drepper@stripped>."
+ */
+ 
+/* ARGSUSED4 */
+extern "C"
+char *
+crypt_genhash_impl(char *ctbuffer,
+                   size_t ctbufflen,
+                   const char *plaintext,
+                   int plaintext_len,
+                   const char *switchsalt,
+                   const char **params)
+{
+  int salt_len, i;
+  char *salt;
+  unsigned char A[DIGEST_LEN];
+  unsigned char B[DIGEST_LEN];
+  unsigned char DP[DIGEST_LEN];
+  unsigned char DS[DIGEST_LEN];
+  DIGEST_CTX ctxA, ctxB, ctxC, ctxDP, ctxDS;
+  int rounds = ROUNDS_DEFAULT;
+  int srounds = 0;
+  boolean_t custom_rounds = B_FALSE;
+  char *p;
+  char *P, *Pp;
+  char *S, *Sp;
+
+  /* Refine the salt */
+  salt = (char *)switchsalt;
+
+  /* skip our magic string */
+  if (strncmp((char *)salt, crypt_alg_magic, crypt_alg_magic_len) == 0)
+  {
+          salt += crypt_alg_magic_len + 1;
+  }
+
+  srounds = getrounds(salt);
+  if (srounds != 0) {
+          rounds = MAX(ROUNDS_MIN, MIN(srounds, ROUNDS_MAX));
+          custom_rounds = B_TRUE;
+          p = strchr(salt, '$');
+          if (p != NULL)
+                  salt = p + 1;
+  }
+
+  salt_len = MIN(strcspn(salt, "$"), CRYPT_SALT_LENGTH);
+  //plaintext_len = strlen(plaintext);
+
+  /* 1. */
+  DIGESTInit(&ctxA);
+
+  /* 2. The password first, since that is what is most unknown */
+  DIGESTUpdate(&ctxA, plaintext, plaintext_len);
+
+  /* 3. Then the raw salt */
+  DIGESTUpdate(&ctxA, salt, salt_len);
+
+  /* 4. - 8. */
+  DIGESTInit(&ctxB);
+  DIGESTUpdate(&ctxB, plaintext, plaintext_len);
+  DIGESTUpdate(&ctxB, salt, salt_len);
+  DIGESTUpdate(&ctxB, plaintext, plaintext_len);
+  DIGESTFinal(B, &ctxB);
+
+  /* 9. - 10. */
+  for (i= plaintext_len; i > MIXCHARS; i -= MIXCHARS)
+    DIGESTUpdate(&ctxA, B, MIXCHARS);
+  DIGESTUpdate(&ctxA, B, i);
+
+  /* 11. */
+  for (i= plaintext_len; i > 0; i >>= 1) {
+    if ((i & 1) != 0)
+    {
+      DIGESTUpdate(&ctxA, B, MIXCHARS);
+    }
+    else
+    {
+      DIGESTUpdate(&ctxA, plaintext, plaintext_len);
+    }
+  }
+
+  /* 12. */
+  DIGESTFinal(A, &ctxA);
+
+  /* 13. - 15. */
+  DIGESTInit(&ctxDP);
+  for (i= 0; i < plaintext_len; i++)
+          DIGESTUpdate(&ctxDP, plaintext, plaintext_len);
+  DIGESTFinal(DP, &ctxDP);
+
+  /* 16. */
+  Pp= P= (char *)alloca(plaintext_len);
+  for (i= plaintext_len; i >= MIXCHARS; i -= MIXCHARS)
+  {
+          Pp= (char *)(memcpy(Pp, DP, MIXCHARS)) + MIXCHARS;
+  }
+  (void) memcpy(Pp, DP, i);
+
+  /* 17. - 19. */
+  DIGESTInit(&ctxDS);
+  for (i= 0; i < 16 + (uint8_t)A[0]; i++)
+          DIGESTUpdate(&ctxDS, salt, salt_len);
+  DIGESTFinal(DS, &ctxDS);
+
+  /* 20. */
+  Sp= S= (char *)alloca(salt_len);
+  for (i= salt_len; i >= MIXCHARS; i -= MIXCHARS)
+  {
+          Sp= (char *)(memcpy(Sp, DS, MIXCHARS)) + MIXCHARS;
+  }
+  (void) memcpy(Sp, DS, i);
+
+  /*  21. */
+  for (i= 0; i < rounds; i++)
+  {
+  DIGESTInit(&ctxC);
+
+    if ((i & 1) != 0)
+    {
+      DIGESTUpdate(&ctxC, P, plaintext_len);
+    }
+    else
+    {
+      if (i == 0)
+        DIGESTUpdate(&ctxC, A, MIXCHARS);
+      else
+        DIGESTUpdate(&ctxC, DP, MIXCHARS);
+    }
+
+    if (i % 3 != 0) {
+      DIGESTUpdate(&ctxC, S, salt_len);
+    }
+
+    if (i % 7 != 0) {
+      DIGESTUpdate(&ctxC, P, plaintext_len);
+    }
+
+    if ((i & 1) != 0)
+    {
+      if (i == 0)
+        DIGESTUpdate(&ctxC, A, MIXCHARS);
+      else
+        DIGESTUpdate(&ctxC, DP, MIXCHARS);
+    }
+    else
+    {
+        DIGESTUpdate(&ctxC, P, plaintext_len);
+    }
+    DIGESTFinal(DP, &ctxC);
+  }
+
+  /* 22. Now make the output string */
+  if (custom_rounds)
+  {
+    (void) snprintf(ctbuffer, ctbufflen,
+                    "%s$rounds=%zu$", crypt_alg_magic, (size_t)rounds);
+  }
+  else
+  {
+    (void) snprintf(ctbuffer, ctbufflen,
+                    "%s$", crypt_alg_magic);
+  }
+  (void) strncat(ctbuffer, (const char *)salt, salt_len);
+  (void) strlcat(ctbuffer, "$", ctbufflen);
+
+  p= ctbuffer + strlen(ctbuffer);
+  ctbufflen -= strlen(ctbuffer);
+
+  b64_from_24bit(DP[ 0], DP[10], DP[20], 4);
+  b64_from_24bit(DP[21], DP[ 1], DP[11], 4);
+  b64_from_24bit(DP[12], DP[22], DP[ 2], 4);
+  b64_from_24bit(DP[ 3], DP[13], DP[23], 4);
+  b64_from_24bit(DP[24], DP[ 4], DP[14], 4);
+  b64_from_24bit(DP[15], DP[25], DP[ 5], 4);
+  b64_from_24bit(DP[ 6], DP[16], DP[26], 4);
+  b64_from_24bit(DP[27], DP[ 7], DP[17], 4);
+  b64_from_24bit(DP[18], DP[28], DP[ 8], 4);
+  b64_from_24bit(DP[ 9], DP[19], DP[29], 4);
+  b64_from_24bit(0, DP[31], DP[30], 3);
+  *p= '\0';
+
+  (void) memset(A, 0, sizeof (A));
+  (void) memset(B, 0, sizeof (B));
+  (void) memset(DP, 0, sizeof (DP));
+  (void) memset(DS, 0, sizeof (DS));
+
+  return (ctbuffer);
+}
+
+
+/**
+  Generate a random string using ASCII characters but avoid seperator character.
+  Stdlib rand and srand are used to produce pseudo random numbers between 
+  33 and 126 which corresponds to the following characters:
+  !"#%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
+*/
+extern "C"
+void generate_user_salt(char *buffer, int buffer_len)
+{
+  srand((unsigned)time(NULL));
+  char *end= buffer + buffer_len;
+  /* Use pointer arithmetics as it is faster way to do so. */
+  for (; buffer < end; buffer++)
+  {
+    do
+    {
+      int ch= 33 + (int) (93.0 * (rand() / (RAND_MAX + 1.0)));
+      *buffer= (char) ch;
+    } while (*buffer == '$');
+  }
+  *buffer= '\0';
+}
+

=== modified file 'sql/CMakeLists.txt'
--- a/sql/CMakeLists.txt	2011-02-02 08:30:13 +0000
+++ b/sql/CMakeLists.txt	2011-05-27 14:40:44 +0000
@@ -77,6 +77,7 @@ SET(SQL_SHARED_SOURCES
   parse_file.cc
   partition_info.cc
   password.c
+  ../sql-common/crypt_genhash_impl.cc
   procedure.cc 
   protocol.cc
   records.cc

=== modified file 'sql/item_strfunc.cc'
--- a/sql/item_strfunc.cc	2011-04-08 13:41:38 +0000
+++ b/sql/item_strfunc.cc	2011-05-27 14:40:44 +0000
@@ -43,6 +43,7 @@
 #include "des_key_file.h"       // st_des_keyschedule, st_des_keyblock
 #include "password.h"           // my_make_scrambled_password,
                                 // my_make_scrambled_password_323
+#include "crypt_genhash_impl.h"
 #include <m_ctype.h>
 #include <base64.h>
 #include "my_md5.h"
@@ -1920,22 +1921,69 @@ void Item_func_trim::print(String *str, 
 String *Item_func_password::val_str_ascii(String *str)
 {
   DBUG_ASSERT(fixed == 1);
+  
+  /* args[0] is the clear text password */
   String *res= args[0]->val_str(str); 
   if ((null_value=args[0]->null_value))
     return 0;
   if (res->length() == 0)
     return make_empty_result();
-  my_make_scrambled_password(tmp_value, res->ptr(), res->length());
-  str->set(tmp_value, SCRAMBLED_PASSWORD_CHAR_LENGTH, &my_charset_latin1);
+  /*
+   The value of an Item my be invariant and thus the value cannot change 
+   after consequtive calls to this method. This is guaranteed by only
+   hashing the password once and then saving it in a buffer.
+   
+   The hashing algorithm is chosen based on the @@old_passwords variable.
+  */
+  if (m_hashed_password_buffer_len == 0 )
+  {
+    THD *thd= current_thd;
+    if (thd->variables.old_passwords == 2)
+    {
+      my_make_scrambled_password(m_hashed_password_buffer, res->ptr(),
+                                 res->length());
+      m_hashed_password_buffer_len= strlen(m_hashed_password_buffer)+1;
+    }
+    else
+    if (thd->variables.old_passwords == 0)
+    {
+      my_make_scrambled_password_sha1(m_hashed_password_buffer, res->ptr(),
+                                      res->length());
+      m_hashed_password_buffer_len= SCRAMBLED_PASSWORD_CHAR_LENGTH;
+    }
+    else
+    if (thd->variables.old_passwords == 1)
+    {
+      my_make_scrambled_password_323(m_hashed_password_buffer, res->ptr(),
+                                     res->length());
+      m_hashed_password_buffer_len= SCRAMBLED_PASSWORD_CHAR_LENGTH_323;
+    }
+    
+    /* remove the clear text password */
+    res->fill(CRYPT_MAX_PASSWORD_SIZE, 'X');
+  }
+
+  str->set(m_hashed_password_buffer, m_hashed_password_buffer_len,
+           &my_charset_latin1);
+
   return str;
 }
 
-char *Item_func_password::alloc(THD *thd, const char *password,
-                                size_t pass_len)
+char *Item_func_password::
+  create_password_hash_buffer(THD *thd, const char *password,  size_t pass_len)
 {
-  char *buff= (char *) thd->alloc(SCRAMBLED_PASSWORD_CHAR_LENGTH+1);
-  if (buff)
+  char *buff= NULL;
+  if (thd->variables.old_passwords == 0)
+  {
+    buff= (char *) thd->alloc(SCRAMBLED_PASSWORD_CHAR_LENGTH);
+    my_make_scrambled_password_sha1(buff, password, pass_len);
+  }
+  else
+  {
+    buff= (char *) thd->alloc(CRYPT_MAX_PASSWORD_SIZE+1);
     my_make_scrambled_password(buff, password, pass_len);
+  }
+  
   return buff;
 }
 

=== modified file 'sql/item_strfunc.h'
--- a/sql/item_strfunc.h	2011-03-22 11:44:40 +0000
+++ b/sql/item_strfunc.h	2011-05-27 14:40:44 +0000
@@ -18,6 +18,7 @@
 
 
 /* This file defines all string functions */
+#include "crypt_genhash_impl.h"
 
 class MY_LOCALE;
 
@@ -319,16 +320,26 @@ public:
 
 class Item_func_password :public Item_str_ascii_func
 {
-  char tmp_value[SCRAMBLED_PASSWORD_CHAR_LENGTH+1]; 
+  char m_hashed_password_buffer[CRYPT_MAX_PASSWORD_SIZE+1];
+  unsigned int m_hashed_password_buffer_len;
 public:
-  Item_func_password(Item *a) :Item_str_ascii_func(a) {}
+  Item_func_password(Item *a) :Item_str_ascii_func(a)
+  {
+    m_hashed_password_buffer_len= 0;
+  }
   String *val_str_ascii(String *str);
   void fix_length_and_dec()
   {
-    fix_length_and_charset(SCRAMBLED_PASSWORD_CHAR_LENGTH, default_charset());
+    /*
+      The Item_func_password is an AST component for clear text passwords.
+      The item representation is a result of a hash transformation and the 
+      original untransformed value is censored for security reasons.
+    */
+    fix_length_and_charset(MAX_PASSWORD_LENGTH, default_charset());
   }
   const char *func_name() const { return "password"; }
-  static char *alloc(THD *thd, const char *password, size_t pass_len);
+  static char *create_password_hash_buffer(THD *thd, const char *password,
+                                           size_t pass_len);
 };
 
 

=== modified file 'sql/password.c'
--- a/sql/password.c	2010-08-09 08:32:50 +0000
+++ b/sql/password.c	2011-05-27 14:40:44 +0000
@@ -64,6 +64,7 @@
 #include <m_string.h>
 #include <sha1.h>
 #include "mysql.h"
+#include "crypt_genhash_impl.h"
 
 /************ MySQL 3.23-4.0 authentication routines: untouched ***********/
 
@@ -395,6 +396,19 @@ my_crypt(char *to, const uchar *s1, cons
     *to++= *s1++ ^ *s2++;
 }
 
+void my_make_scrambled_password(char *to, const char *password,
+                                size_t pass_len)
+{
+  char salt[CRYPT_SALT_LENGTH+1];
+  
+  generate_user_salt(salt, CRYPT_SALT_LENGTH+1);
+  crypt_genhash_impl(to,
+                     CRYPT_MAX_PASSWORD_SIZE,
+                     password,
+                     pass_len,
+                     salt,
+                     0);
+}
 
 /*
     MySQL 4.1.1 password hashing: SHA conversion (see RFC 2289, 3174) twice
@@ -403,14 +417,14 @@ my_crypt(char *to, const uchar *s1, cons
     The result of this function is used as return value from PASSWORD() and
     is stored in the database.
   SYNOPSIS
-    my_make_scrambled_password()
+    my_make_scrambled_password_sha1()
     buf       OUT buffer of size 2*SHA1_HASH_SIZE + 2 to store hex string
     password  IN  password string
     pass_len  IN  length of password string
 */
 
-void my_make_scrambled_password(char *to, const char *password,
-                                size_t pass_len)
+void my_make_scrambled_password_sha1(char *to, const char *password,
+                                     size_t pass_len)
 {
   SHA1_CONTEXT sha1_context;
   uint8 hash_stage2[SHA1_HASH_SIZE];
@@ -496,7 +510,7 @@ scramble(char *to, const char *message, 
     null-terminated, reply and hash_stage2 must be at least SHA1_HASH_SIZE
     long (if not, something fishy is going on).
   SYNOPSIS
-    check_scramble()
+    check_scramble_sha1()
     scramble     clients' reply, presumably produced by scramble()
     message      original random string, previously sent to client
                  (presumably second argument of scramble()), must be 
@@ -510,8 +524,8 @@ scramble(char *to, const char *message, 
 */
 
 my_bool
-check_scramble(const uchar *scramble_arg, const char *message,
-               const uint8 *hash_stage2)
+check_scramble_sha1(const uchar *scramble_arg, const char *message,
+                    const uint8 *hash_stage2)
 {
   SHA1_CONTEXT sha1_context;
   uint8 buf[SHA1_HASH_SIZE];
@@ -531,6 +545,12 @@ check_scramble(const uchar *scramble_arg
   return memcmp(hash_stage2, hash_stage2_reassured, SHA1_HASH_SIZE);
 }
 
+my_bool
+check_scramble(const uchar *scramble_arg, const char *message,
+               const uint8 *hash_stage2)
+{
+  return check_scramble_sha1(scramble_arg, message, hash_stage2);
+}
 
 /*
   Convert scrambled password from asciiz hex string to binary form.
@@ -560,3 +580,4 @@ void make_password_from_salt(char *to, c
   *to++= PVERSION41_CHAR;
   octet2hex(to, (const char*) hash_stage2, SHA1_HASH_SIZE);
 }
+

=== modified file 'sql/set_var.cc'
--- a/sql/set_var.cc	2011-03-25 14:35:13 +0000
+++ b/sql/set_var.cc	2011-05-27 14:40:44 +0000
@@ -738,7 +738,7 @@ int set_var_password::check(THD *thd)
       user->host.length= 1;
     }
   }
-  if (!user->user.str)
+  if (user->user.length == 0)
   {
     DBUG_ASSERT(thd->security_ctx->user);
     user->user.str= (char *) thd->security_ctx->user;

=== modified file 'sql/sql_acl.cc'
--- a/sql/sql_acl.cc	2011-04-07 12:04:22 +0000
+++ b/sql/sql_acl.cc	2011-05-27 14:40:44 +0000
@@ -49,8 +49,12 @@
 #include "sql_connect.h"
 #include "hostname.h"
 #include "sql_db.h"
+#include "password.h"
+#include "crypt_genhash_impl.h"
 
 bool mysql_user_table_is_in_short_password_format= false;
+inline bool auth_plugin_is_built_in(const char *plugin_name);
+void optimize_plugin_compare_by_pointer(LEX_STRING *plugin_name);
 
 static const
 TABLE_FIELD_TYPE mysql_db_table_fields[MYSQL_DB_FIELD_COUNT] = {
@@ -166,9 +170,226 @@ TABLE_FIELD_TYPE mysql_db_table_fields[M
   }
 };
 
+static const
+TABLE_FIELD_TYPE mysql_user_table_fields[MYSQL_USER_FIELD_COUNT] = {
+  {
+    { C_STRING_WITH_LEN("Host") },            
+    { C_STRING_WITH_LEN("char(60)") },
+    { NULL, 0 }
+  },
+  {
+    { C_STRING_WITH_LEN("User") },            
+    { C_STRING_WITH_LEN("char(16)") },
+    { NULL, 0 }
+  },
+  {
+    { C_STRING_WITH_LEN("Password") },            
+    { C_STRING_WITH_LEN("char(41)") },
+    { C_STRING_WITH_LEN("latin1") }
+  }, 
+  {
+    { C_STRING_WITH_LEN("Select_priv") },
+    { C_STRING_WITH_LEN("enum('N','Y')") },
+    { C_STRING_WITH_LEN("utf8") }
+  },
+  {
+    { C_STRING_WITH_LEN("Insert_priv") },
+    { C_STRING_WITH_LEN("enum('N','Y')") },
+    { C_STRING_WITH_LEN("utf8") }
+  },
+  {
+    { C_STRING_WITH_LEN("Update_priv") },
+    { C_STRING_WITH_LEN("enum('N','Y')") },
+    { C_STRING_WITH_LEN("utf8") }
+  },
+  {
+    { C_STRING_WITH_LEN("Delete_priv") },
+    { C_STRING_WITH_LEN("enum('N','Y')") },
+    { C_STRING_WITH_LEN("utf8") }
+  },
+  {
+    { C_STRING_WITH_LEN("Create_priv") },
+    { C_STRING_WITH_LEN("enum('N','Y')") },
+    { C_STRING_WITH_LEN("utf8") }
+  },
+  {
+    { C_STRING_WITH_LEN("Drop_priv") },
+    { C_STRING_WITH_LEN("enum('N','Y')") },
+    { C_STRING_WITH_LEN("utf8") }
+  },
+  {
+    { C_STRING_WITH_LEN("Reload_priv") },
+    { C_STRING_WITH_LEN("enum('N','Y')") },
+    { C_STRING_WITH_LEN("utf8") }
+  },
+  {
+    { C_STRING_WITH_LEN("Shutdown_priv") },
+    { C_STRING_WITH_LEN("enum('N','Y')") },
+    { C_STRING_WITH_LEN("utf8") }
+  },
+  { 
+    { C_STRING_WITH_LEN("Process_priv") },
+    { C_STRING_WITH_LEN("enum('N','Y')") },
+    { C_STRING_WITH_LEN("utf8") }
+  },
+  { 
+    { C_STRING_WITH_LEN("File_priv") },
+    { C_STRING_WITH_LEN("enum('N','Y')") },
+    { C_STRING_WITH_LEN("utf8") }
+  },
+  { 
+    { C_STRING_WITH_LEN("Grant_priv") },
+    { C_STRING_WITH_LEN("enum('N','Y')") },
+    { C_STRING_WITH_LEN("utf8") }
+  },
+  { 
+    { C_STRING_WITH_LEN("References_priv") },
+    { C_STRING_WITH_LEN("enum('N','Y')") },
+    { C_STRING_WITH_LEN("utf8") }
+  },
+  { 
+    { C_STRING_WITH_LEN("Index_priv") },
+    { C_STRING_WITH_LEN("enum('N','Y')") },
+    { C_STRING_WITH_LEN("utf8") }
+  },
+  { 
+    { C_STRING_WITH_LEN("Alter_priv") },
+    { C_STRING_WITH_LEN("enum('N','Y')") },
+    { C_STRING_WITH_LEN("utf8") }
+  },
+  { 
+    { C_STRING_WITH_LEN("Show_db_priv") },
+    { C_STRING_WITH_LEN("enum('N','Y')") },
+    { C_STRING_WITH_LEN("utf8") }
+  },
+  { 
+    { C_STRING_WITH_LEN("Super_priv") },
+    { C_STRING_WITH_LEN("enum('N','Y')") },
+    { C_STRING_WITH_LEN("utf8") }
+  },
+  { 
+    { C_STRING_WITH_LEN("Create_tmp_table_priv") },
+    { C_STRING_WITH_LEN("enum('N','Y')") },
+    { C_STRING_WITH_LEN("utf8") }
+  },
+  { 
+    { C_STRING_WITH_LEN("Lock_tables_priv") },
+    { C_STRING_WITH_LEN("enum('N','Y')") },
+    { C_STRING_WITH_LEN("utf8") }
+  },
+  { 
+    { C_STRING_WITH_LEN("Execute_priv") },
+    { C_STRING_WITH_LEN("enum('N','Y')") },
+    { C_STRING_WITH_LEN("utf8") }
+  },
+  { 
+    { C_STRING_WITH_LEN("Repl_slave_priv") },
+    { C_STRING_WITH_LEN("enum('N','Y')") },
+    { C_STRING_WITH_LEN("utf8") }
+  },
+  { 
+    { C_STRING_WITH_LEN("Repl_client_priv") },
+    { C_STRING_WITH_LEN("enum('N','Y')") },
+    { C_STRING_WITH_LEN("utf8") }
+  },
+  { 
+    { C_STRING_WITH_LEN("Create_view_priv") },
+    { C_STRING_WITH_LEN("enum('N','Y')") },
+    { C_STRING_WITH_LEN("utf8") }
+  },
+  { 
+    { C_STRING_WITH_LEN("Show_view_priv") },
+    { C_STRING_WITH_LEN("enum('N','Y')") },
+    { C_STRING_WITH_LEN("utf8") }
+  },
+  { 
+    { C_STRING_WITH_LEN("Create_routine_priv") },
+    { C_STRING_WITH_LEN("enum('N','Y')") },
+    { C_STRING_WITH_LEN("utf8") }
+  },
+  { 
+    { C_STRING_WITH_LEN("Alter_routine_priv") },
+    { C_STRING_WITH_LEN("enum('N','Y')") },
+    { C_STRING_WITH_LEN("utf8") }
+  },
+  { 
+    { C_STRING_WITH_LEN("Create_user_priv") },
+    { C_STRING_WITH_LEN("enum('N','Y')") },
+    { C_STRING_WITH_LEN("utf8") }
+  },
+  { 
+    { C_STRING_WITH_LEN("Event_priv") },
+    { C_STRING_WITH_LEN("enum('N','Y')") },
+    { C_STRING_WITH_LEN("utf8") }
+  },
+  { 
+    { C_STRING_WITH_LEN("Trigger_priv") },
+    { C_STRING_WITH_LEN("enum('N','Y')") },
+    { C_STRING_WITH_LEN("utf8") }
+  },
+  { 
+    { C_STRING_WITH_LEN("Create_tablespace_priv") },
+    { C_STRING_WITH_LEN("enum('N','Y')") },
+    { C_STRING_WITH_LEN("utf8") }
+  },
+  { 
+    { C_STRING_WITH_LEN("ssl_type") },
+    { C_STRING_WITH_LEN("enum('','ANY','X509','SPECIFIED')") },
+    { C_STRING_WITH_LEN("utf8") }
+  },
+  { 
+    { C_STRING_WITH_LEN("ssl_cipher") },
+    { C_STRING_WITH_LEN("blob") },
+    { NULL, 0 }
+  },
+  { 
+    { C_STRING_WITH_LEN("x509_issuer") },
+    { C_STRING_WITH_LEN("blob") },
+    { NULL, 0 }
+  },
+  { 
+    { C_STRING_WITH_LEN("x509_subject") },
+    { C_STRING_WITH_LEN("blob") },
+    { NULL, 0 }
+  },
+  { 
+    { C_STRING_WITH_LEN("max_questions") },
+    { C_STRING_WITH_LEN("int(11)") },
+    { NULL, 0 }
+  },
+  { 
+    { C_STRING_WITH_LEN("max_updates") },
+    { C_STRING_WITH_LEN("int(11)") },
+    { NULL, 0 }
+  },
+  { 
+    { C_STRING_WITH_LEN("max_connections") },
+    { C_STRING_WITH_LEN("int(11)") },
+    { NULL, 0 }
+  },
+  { 
+    { C_STRING_WITH_LEN("plugin") },
+    { C_STRING_WITH_LEN("char(64)") },
+    { NULL, 0 }
+  },
+  { 
+    { C_STRING_WITH_LEN("authentication_string") },
+    { C_STRING_WITH_LEN("text") },
+    { NULL, 0 }
+  },
+  { 
+    { C_STRING_WITH_LEN("Password2") },
+    { C_STRING_WITH_LEN("varchar(80)") },
+    { NULL, 0 }
+  }  
+};
+
 const TABLE_FIELD_DEF
   mysql_db_table_def= {MYSQL_DB_FIELD_COUNT, mysql_db_table_fields};
 
+const TABLE_FIELD_DEF
+  mysql_user_table_def= {MYSQL_USER_FIELD_COUNT, mysql_user_table_fields};
+
 static LEX_STRING native_password_plugin_name= {
   C_STRING_WITH_LEN("mysql_native_password")
 };
@@ -176,9 +397,14 @@ static LEX_STRING native_password_plugin
 static LEX_STRING old_password_plugin_name= {
   C_STRING_WITH_LEN("mysql_old_password")
 };
+
+LEX_STRING sha256_password_plugin_name= {
+  C_STRING_WITH_LEN("sha256_password")
+};
   
 /// @todo make it configurable
 LEX_STRING *default_auth_plugin_name= &native_password_plugin_name;
+//LEX_STRING *default_auth_plugin_name= &sha256_password_plugin_name;
 
 #ifndef NO_EMBEDDED_ACCESS_CHECKS
 static plugin_ref old_password_plugin;
@@ -215,8 +441,17 @@ public:
   uint hostname_length;
   USER_RESOURCES user_resource;
   char *user;
+  /**
+    The salt variable is used as the password hash for
+    native_password_authetication and old_password_authentication.
+  */
   uint8 salt[SCRAMBLE_LENGTH + 1];       // scrambled password in binary form
-  uint8 salt_len;        // 0 - no password, 4 - 3.20, 8 - 4.0,  20 - 4.1.1 
+  /**
+    In the old protocol the salt_len indicated what type of autnetication
+    protocol was used: 0 - no password, 4 - 3.20, 8 - 4.0,  20 - 4.1.1
+  */
+  uint8 salt_len;
+  uint8 sha2_hash[CRYPT_MAX_PASSWORD_SIZE+1];
   enum SSL_type ssl_type;
   const char *ssl_cipher, *x509_issuer, *x509_subject;
   LEX_STRING plugin;
@@ -232,11 +467,17 @@ public:
     dst->ssl_cipher= safe_strdup_root(root, ssl_cipher);
     dst->x509_issuer= safe_strdup_root(root, x509_issuer);
     dst->x509_subject= safe_strdup_root(root, x509_subject);
-    if (plugin.str == native_password_plugin_name.str ||
-        plugin.str == old_password_plugin_name.str)
+    /*
+      If the plugin is built in we don't need to reallocate the name of the
+      plugin.
+    */
+    if (auth_plugin_is_built_in(dst->plugin.str))
       dst->plugin= plugin;
     else
+    {
       dst->plugin.str= strmake_root(root, plugin.str, plugin.length);
+      dst->plugin.length= plugin.length;
+    }
     dst->auth_string.str= safe_strdup_root(root, auth_string.str);
     dst->host.hostname= safe_strdup_root(root, host.hostname);
     return dst;
@@ -259,6 +500,7 @@ static bool compare_hostname(const acl_h
 static bool show_proxy_grants (THD *thd, LEX_USER *user,
                                char *buff, size_t buffsize);
 
+
 class ACL_PROXY_USER :public ACL_ACCESS
 {
   acl_host_and_ip host;
@@ -553,22 +795,30 @@ static void init_check_host(void);
 static void rebuild_check_host(void);
 static ACL_USER *find_acl_user(const char *host, const char *user,
                                my_bool exact);
-static bool update_user_table(THD *thd, TABLE *table,
-                              const char *host, const char *user,
-			      const char *new_password, uint new_password_len);
+static bool update_user_table(TABLE *table, const char *host, const char *user,
+                              const char *new_password, uint new_password_len,
+                              enum mysql_user_table_field password_field);
 static my_bool acl_load(THD *thd, TABLE_LIST *tables);
 static my_bool grant_load(THD *thd, TABLE_LIST *tables);
 static inline void get_grantor(THD *thd, char* grantor);
 
-/*
+/**
   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.
 */
 
 static
 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);
@@ -655,7 +905,8 @@ my_bool acl_init(bool dont_read_acl_tabl
 static bool
 set_user_plugin (ACL_USER *user, int password_len)
 {
-  switch (password_len) 
+  /* using old password authentication protocol */
+  switch (password_len)
   {
   case 0: /* no password */
   case SCRAMBLED_PASSWORD_CHAR_LENGTH:
@@ -719,9 +970,11 @@ static my_bool acl_load(THD *thd, TABLE_
   (void) my_init_dynamic_array(&acl_hosts,sizeof(ACL_HOST),20,50);
   while (!(read_record_info.read_record(&read_record_info)))
   {
+    /* Reading record from mysql.host table */
     ACL_HOST host;
-    update_hostname(&host.host,get_field(&mem, table->field[0]));
-    host.db=	 get_field(&mem, table->field[1]);
+    update_hostname(&host.host,
+                    get_field(&mem, table->field[0]));
+    host.db= get_field(&mem, table->field[1]);
     if (lower_case_table_names && host.db)
     {
       /*
@@ -757,63 +1010,29 @@ static my_bool acl_load(THD *thd, TABLE_
     }
 #endif
     (void) push_dynamic(&acl_hosts,(uchar*) &host);
-  }
+  } // END reading records from mysql.host
+  
   my_qsort((uchar*) dynamic_element(&acl_hosts,0,ACL_HOST*),acl_hosts.elements,
 	   sizeof(ACL_HOST),(qsort_cmp) acl_compare);
   end_read_record(&read_record_info);
   freeze_size(&acl_hosts);
 
+  /*
+    Prepare reading from the mysql.user table
+  */
   init_read_record(&read_record_info,thd,table=tables[1].table,NULL,1,0,FALSE);
   table->use_all_columns();
   (void) my_init_dynamic_array(&acl_users,sizeof(ACL_USER),50,100);
-  password_length= table->field[2]->field_length /
-    table->field[2]->charset()->mbmaxlen;
-  if (password_length < SCRAMBLED_PASSWORD_CHAR_LENGTH_323)
-  {
-    sql_print_error("Fatal error: mysql.user table is damaged or in "
-                    "unsupported 3.20 format.");
-    goto end;
-  }
-
-  DBUG_PRINT("info",("user table fields: %d, password length: %d",
-		     table->s->fields, password_length));
-
-  mysql_mutex_lock(&LOCK_global_system_variables);
-  if (password_length < SCRAMBLED_PASSWORD_CHAR_LENGTH)
-  {
-    if (opt_secure_auth)
-    {
-      mysql_mutex_unlock(&LOCK_global_system_variables);
-      sql_print_error("Fatal error: mysql.user table is in old format, "
-                      "but server started with --secure-auth option.");
-      goto end;
-    }
-    mysql_user_table_is_in_short_password_format= true;
-    if (global_system_variables.old_passwords)
-      mysql_mutex_unlock(&LOCK_global_system_variables);
-    else
-    {
-      global_system_variables.old_passwords= 1;
-      mysql_mutex_unlock(&LOCK_global_system_variables);
-      sql_print_warning("mysql.user table is not updated to new password format; "
-                        "Disabling new password usage until "
-                        "mysql_fix_privilege_tables is run");
-    }
-    thd->variables.old_passwords= 1;
-  }
-  else
-  {
-    mysql_user_table_is_in_short_password_format= false;
-    mysql_mutex_unlock(&LOCK_global_system_variables);
-  }
-
+  
   allow_all_hosts=0;
   while (!(read_record_info.read_record(&read_record_info)))
   {
+    /* Reading record from mysql.user */
     ACL_USER user;
     bzero(&user, sizeof(user));
-    update_hostname(&user.host, get_field(&mem, table->field[0]));
-    user.user= get_field(&mem, table->field[1]);
+    update_hostname(&user.host,
+                    get_field(&mem, table->field[MYSQL_USER_FIELD_HOST]));
+    user.user= get_field(&mem, table->field[MYSQL_USER_FIELD_USER]);
     if (check_no_resolve && hostname_requires_resolving(user.host.hostname))
     {
       sql_print_warning("'user' entry '%s@%s' "
@@ -823,15 +1042,26 @@ static my_bool acl_load(THD *thd, TABLE_
       continue;
     }
 
-    char *password= get_field(&mem, table->field[2]);
-    uint password_len= password ? strlen(password) : 0;
-    user.auth_string.str= password ? password : const_cast<char*>("");
-    user.auth_string.length= password_len;
-    set_user_salt(&user, password, password_len);
+    /* Read legacy password */
+    {
+      char *password= get_field(&mem, 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;
+      /*
+         Transform hex to octets and adjust the format.
+       */
+      set_user_salt(&user, 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;
+    } 
 
-    if (set_user_plugin(&user, password_len))
-      continue;
-    
     {
       uint next_field;
       user.access= get_access(table,3,&next_field) & GLOBAL_ACLS;
@@ -878,7 +1108,8 @@ static my_bool acl_load(THD *thd, TABLE_
       /* Starting from 4.0.2 we have more fields */
       if (table->s->fields >= 31)
       {
-        char *ssl_type=get_field(thd->mem_root, table->field[next_field++]);
+        char *ssl_type=
+          get_field(thd->mem_root, table->field[MYSQL_USER_FIELD_SSL_TYPE]);
         if (!ssl_type)
           user.ssl_type=SSL_TYPE_NONE;
         else if (!strcmp(ssl_type, "ANY"))
@@ -888,15 +1119,21 @@ static my_bool acl_load(THD *thd, TABLE_
         else  /* !strcmp(ssl_type, "SPECIFIED") */
           user.ssl_type=SSL_TYPE_SPECIFIED;
 
-        user.ssl_cipher=   get_field(&mem, table->field[next_field++]);
-        user.x509_issuer=  get_field(&mem, table->field[next_field++]);
-        user.x509_subject= get_field(&mem, table->field[next_field++]);
+        user.ssl_cipher= 
+          get_field(&mem, table->field[MYSQL_USER_FIELD_SSL_CIPHER]);
+        user.x509_issuer=
+          get_field(&mem, table->field[MYSQL_USER_FIELD_X509_ISSUER]);
+        user.x509_subject=
+          get_field(&mem, table->field[MYSQL_USER_FIELD_X509_SUBJECT]);
 
-        char *ptr = get_field(thd->mem_root, table->field[next_field++]);
+        char *ptr= get_field(thd->mem_root,
+                             table->field[MYSQL_USER_FIELD_MAX_QUESTIONS]);
         user.user_resource.questions=ptr ? atoi(ptr) : 0;
-        ptr = get_field(thd->mem_root, table->field[next_field++]);
+        ptr= get_field(thd->mem_root,
+                       table->field[MYSQL_USER_FIELD_MAX_UPDATES]);
         user.user_resource.updates=ptr ? atoi(ptr) : 0;
-        ptr = get_field(thd->mem_root, table->field[next_field++]);
+        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)
@@ -905,24 +1142,21 @@ static my_bool acl_load(THD *thd, TABLE_
         if (table->s->fields >= 36)
         {
           /* Starting from 5.0.3 we have max_user_connections field */
-          ptr= get_field(thd->mem_root, table->field[next_field++]);
+          ptr= get_field(thd->mem_root,
+                         table->field[MYSQL_USER_FIELD_MAX_USER_CONNECTIONS]);
           user.user_resource.user_conn= ptr ? atoi(ptr) : 0;
         }
 
         if (table->s->fields >= 41)
         {
           /* We may have plugin & auth_String fields */
-          char *tmpstr= get_field(&mem, table->field[next_field++]);
+          char *tmpstr= get_field(&mem, table->field[MYSQL_USER_FIELD_PLUGIN]);
           if (tmpstr)
           {
-            if (user.auth_string.length)
-            {
-              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.hostname ? user.host.hostname : "");
-            }
+            /*
+              By comparing the plugin with the built in plugins it is possible
+              to optimize the string allocation and comparision.
+            */
             if (my_strcasecmp(system_charset_info, tmpstr,
                               native_password_plugin_name.str) == 0)
               user.plugin= native_password_plugin_name;
@@ -930,18 +1164,47 @@ static my_bool acl_load(THD *thd, TABLE_
               if (my_strcasecmp(system_charset_info, tmpstr,
                                 old_password_plugin_name.str) == 0)
                 user.plugin= old_password_plugin_name;
-              else
+            else
+              if (my_strcasecmp(system_charset_info, tmpstr,
+                                sha256_password_plugin_name.str) == 0)
+                user.plugin= sha256_password_plugin_name;
+            else
               {
                 user.plugin.str= tmpstr;
                 user.plugin.length= strlen(tmpstr);
               }
-            user.auth_string.str= get_field(&mem, table->field[next_field++]);
+            if (user.auth_string.length &&
+                user.plugin.str != sha256_password_plugin_name.str &&
+                user.plugin.str != native_password_plugin_name.str &&
+                user.plugin.str != old_password_plugin_name.str)
+            {
+              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.hostname ? user.host.hostname : "");
+            }
+            user.auth_string.str=
+              get_field(&mem,
+                        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 (table->s->fields >= 42)
+        {
+          /* We have a new password field */
+          char *password= get_field(&mem,
+            table->field[MYSQL_USER_FIELD_PASSWORD2]);
+          int password_len= 0;
+          if (password)
+          {
+            password_len= strlen(password)+1;
+            memcpy(user.sha2_hash, password, password_len);
+          }
+        }
+      } // end if (table->s->fields >= 31)
       else
       {
         user.ssl_type=SSL_TYPE_NONE;
@@ -964,17 +1227,66 @@ static my_bool acl_load(THD *thd, TABLE_
 	  (user.host.hostname[0] == wild_many && !user.host.hostname[1]))
         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);
   end_read_record(&read_record_info);
   freeze_size(&acl_users);
 
+  /* Legacy password integrity checks ----------------------------------------*/
+  { 
+    password_length= table->field[MYSQL_USER_FIELD_PASSWORD]->field_length /
+      table->field[MYSQL_USER_FIELD_PASSWORD]->charset()->mbmaxlen;
+    if (password_length < SCRAMBLED_PASSWORD_CHAR_LENGTH_323)
+    {
+      sql_print_error("Fatal error: mysql.user table is damaged or in "
+                      "unsupported 3.20 format.");
+      goto end;
+    }
+  
+    DBUG_PRINT("info",("user table fields: %d, password length: %d",
+  		     table->s->fields, password_length));
+
+    mysql_mutex_lock(&LOCK_global_system_variables);
+    if (password_length < SCRAMBLED_PASSWORD_CHAR_LENGTH)
+    { 
+      if (opt_secure_auth)
+      {
+        mysql_mutex_unlock(&LOCK_global_system_variables);
+        sql_print_error("Fatal error: mysql.user table is in old format, "
+                        "but server started with --secure-auth option.");
+        goto end;
+      }
+      mysql_user_table_is_in_short_password_format= true;
+      if (global_system_variables.old_passwords)
+        mysql_mutex_unlock(&LOCK_global_system_variables);
+      else
+      {
+        global_system_variables.old_passwords= 1;
+        mysql_mutex_unlock(&LOCK_global_system_variables);
+        sql_print_warning("mysql.user table is not updated to new password format; "
+                          "Disabling new password usage until "
+                          "mysql_fix_privilege_tables is run");
+      }
+      thd->variables.old_passwords= 1;
+    }
+    else
+    {
+      mysql_user_table_is_in_short_password_format= false;
+      mysql_mutex_unlock(&LOCK_global_system_variables);
+    }
+  } /* End legacy password integrity checks ----------------------------------*/
+  
+  /*
+    Prepare reading from the mysql.db table
+  */
   init_read_record(&read_record_info,thd,table=tables[2].table,NULL,1,0,FALSE);
   table->use_all_columns();
   (void) my_init_dynamic_array(&acl_dbs,sizeof(ACL_DB),50,100);
   while (!(read_record_info.read_record(&read_record_info)))
   {
+    /* Reading record in mysql.db */
     ACL_DB db;
     update_hostname(&db.host,get_field(&mem, table->field[MYSQL_DB_FIELD_HOST]));
     db.db=get_field(&mem, table->field[MYSQL_DB_FIELD_DB]);
@@ -1023,12 +1335,14 @@ static my_bool acl_load(THD *thd, TABLE_
     }
 #endif
     (void) push_dynamic(&acl_dbs,(uchar*) &db);
-  }
+  } // END reading records from mysql.db tables
+  
   my_qsort((uchar*) dynamic_element(&acl_dbs,0,ACL_DB*),acl_dbs.elements,
 	   sizeof(ACL_DB),(qsort_cmp) acl_compare);
   end_read_record(&read_record_info);
   freeze_size(&acl_dbs);
 
+  /* Prepare to read records from the mysql.proxies_priv table */
   (void) my_init_dynamic_array(&acl_proxy_users, sizeof(ACL_PROXY_USER), 
                                50, 100);
   if (tables[3].table)
@@ -1038,6 +1352,7 @@ static my_bool acl_load(THD *thd, TABLE_
     table->use_all_columns();
     while (!(read_record_info.read_record(&read_record_info)))
     {
+      /* Reading record in mysql.proxies_priv */
       ACL_PROXY_USER proxy;
       proxy.init(table, &mem);
       if (proxy.check_validity(check_no_resolve))
@@ -1047,7 +1362,8 @@ static my_bool acl_load(THD *thd, TABLE_
         end_read_record(&read_record_info);
         goto end;
       }
-    }
+    } // END reading records from the mysql.proxies_priv table
+
     my_qsort((uchar*) dynamic_element(&acl_proxy_users, 0, ACL_PROXY_USER*),
              acl_proxy_users.elements,
              sizeof(ACL_PROXY_USER), (qsort_cmp) acl_compare);
@@ -1405,8 +1721,8 @@ static void acl_update_user(const char *
 			    const LEX_STRING *plugin,
 			    const LEX_STRING *auth)
 {
+  DBUG_ENTER("acl_update_user");
   mysql_mutex_assert_owner(&acl_cache->lock);
-
   for (uint i=0 ; i < acl_users.elements ; i++)
   {
     ACL_USER *acl_user=dynamic_element(&acl_users,i,ACL_USER*);
@@ -1417,7 +1733,7 @@ static void acl_update_user(const char *
 	  (acl_user->host.hostname &&
 	  !my_strcasecmp(system_charset_info, host, acl_user->host.hostname)))
       {
-        if (plugin->str[0])
+        if (plugin->length > 0)
         {
           acl_user->plugin.str= strmake_root(&mem, plugin->str, plugin->length);
           acl_user->plugin.length= plugin->length;
@@ -1444,13 +1760,19 @@ static void acl_update_user(const char *
 	  acl_user->x509_subject= (x509_subject ?
 				   strdup_root(&mem,x509_subject) : 0);
 	}
-	if (password)
+  if (plugin->str == sha256_password_plugin_name.str)
+  {
+    memcpy(acl_user->sha2_hash, password, password_len);
+  }
+  else
+  if (password)
 	  set_user_salt(acl_user, password, password_len);
         /* search complete: */
 	break;
       }
     }
   }
+  DBUG_VOID_RETURN;
 }
 
 
@@ -1465,6 +1787,7 @@ static void acl_insert_user(const char *
 			    const LEX_STRING *plugin,
 			    const LEX_STRING *auth)
 {
+  DBUG_ENTER("acl_insert_user");
   ACL_USER acl_user;
 
   mysql_mutex_assert_owner(&acl_cache->lock);
@@ -1486,7 +1809,6 @@ static void acl_insert_user(const char *
     acl_user.auth_string.str= strmake_root(&mem, password, password_len);
     acl_user.auth_string.length= password_len;
   }
-
   acl_user.access=privileges;
   acl_user.user_resource = *mqh;
   acl_user.sort=get_sort(2,acl_user.host.hostname,acl_user.user);
@@ -1497,7 +1819,16 @@ static void acl_insert_user(const char *
   acl_user.x509_issuer= x509_issuer  ? strdup_root(&mem,x509_issuer) : 0;
   acl_user.x509_subject=x509_subject ? strdup_root(&mem,x509_subject) : 0;
 
-  set_user_salt(&acl_user, password, password_len);
+  /*
+    If the plugin is sha256 based authentication then we use the sha2_hash
+    as a password store. For other plugins we fall back on the old storage.
+  */
+  if (plugin->str == sha256_password_plugin_name.str)
+  {
+    memcpy(acl_user.sha2_hash, password, password_len);
+  }
+  else
+    set_user_salt(&acl_user, password, password_len);
 
   (void) push_dynamic(&acl_users,(uchar*) &acl_user);
   if (!acl_user.host.hostname ||
@@ -1508,6 +1839,7 @@ static void acl_insert_user(const char *
 
   /* Rebuild 'acl_check_hosts' since 'acl_users' has been modified */
   rebuild_check_host();
+  DBUG_VOID_RETURN;
 }
 
 
@@ -1759,22 +2091,19 @@ bool acl_check_host(const char *host, co
 }
 
 
-/*
+/**
   Check if the user is allowed to change password
 
-  SYNOPSIS:
-    check_change_password()
-    thd		THD
-    host	hostname for the user
-    user	user name
-    new_password new password
-
-  NOTE:
-    new_password cannot be NULL
-
-    RETURN VALUE
-      0		OK
-      1		ERROR  ; In this case the error is sent to the client.
+ @param thd THD
+ @param host Hostname for the user
+ @param user User name
+ @param new_password new password
+
+ new_password cannot be NULL
+
+ @return Error status
+   @retval 0 OK
+   @retval 1 ERROR; In this case the error is sent to the client.
 */
 
 int check_change_password(THD *thd, const char *host, const char *user,
@@ -1799,30 +2128,24 @@ int check_change_password(THD *thd, cons
                MYF(0));
     return(1);
   }
-  size_t len= strlen(new_password);
-  if (len && len != SCRAMBLED_PASSWORD_CHAR_LENGTH &&
-      len != SCRAMBLED_PASSWORD_CHAR_LENGTH_323)
-  {
-    my_error(ER_PASSWD_LENGTH, MYF(0), SCRAMBLED_PASSWORD_CHAR_LENGTH);
-    return -1;
-  }
+
   return(0);
 }
 
 
-/*
-  Change a password for a user
-
-  SYNOPSIS
-    change_password()
-    thd			Thread handle
-    host		Hostname
-    user		User name
-    new_password	New password for host@user
+/**
+  Change a password hash for a user.
 
-  RETURN VALUES
-    0	ok
-    1	ERROR; In this case the error is sent to the client.
+  @param thd Thread handle
+  @param host Hostname
+  @param user User name
+  @param new_password New password hash for host@user
+
+  @see set_var_password::update(THD *thd)
+
+  @return Error code
+   @retval 0 ok
+   @retval 1 ERROR; In this case the error is sent to the client.
 */
 
 bool change_password(THD *thd, const char *host, const char *user,
@@ -1836,6 +2159,7 @@ bool change_password(THD *thd, const cha
   bool save_binlog_row_based;
   uint new_password_len= (uint) strlen(new_password);
   bool result= 1;
+  enum mysql_user_table_field password_field= MYSQL_USER_FIELD_PASSWORD;
   DBUG_ENTER("change_password");
   DBUG_PRINT("enter",("host: '%s'  user: '%s'  new_password: '%s'",
 		      host,user,new_password));
@@ -1883,22 +2207,56 @@ bool change_password(THD *thd, const cha
     goto end;
   }
 
+  if (acl_user->plugin.length == 0)
+  {
+    acl_user->plugin.length= default_auth_plugin_name->length;
+    acl_user->plugin.str= default_auth_plugin_name->str;
+  }
+  
+  /*
+    update loaded acl entry:
+    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,
+                    sha256_password_plugin_name.str) == 0)
+  {
+    password_field= MYSQL_USER_FIELD_PASSWORD2;
+    if (new_password_len < CRYPT_MAX_PASSWORD_SIZE+1)
+      memcpy(acl_user->sha2_hash, new_password, new_password_len+1);
+  }
+  else
   if (my_strcasecmp(system_charset_info, acl_user->plugin.str,
-                    native_password_plugin_name.str) &&
+                    native_password_plugin_name.str) == 0 ||
       my_strcasecmp(system_charset_info, acl_user->plugin.str,
-                    old_password_plugin_name.str))
+                    old_password_plugin_name.str) == 0)
   {
-    push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
-                 ER_SET_PASSWORD_AUTH_PLUGIN, ER(ER_SET_PASSWORD_AUTH_PLUGIN));
+    acl_user->plugin= native_password_plugin_name;
+    password_field= MYSQL_USER_FIELD_PASSWORD;
+    /*
+      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).
+      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);
+    set_user_plugin(acl_user, new_password_len);
+  } else
+  {
+     push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
+                  ER_SET_PASSWORD_AUTH_PLUGIN, ER(ER_SET_PASSWORD_AUTH_PLUGIN));
+     /*
+       An undefined password factory could very well mean that the password
+       field is empty.
+     */
+     new_password_len= 0;
   }
-  /* update loaded acl entry: */
-  set_user_salt(acl_user, new_password, new_password_len);
-  set_user_plugin(acl_user, new_password_len);
-
-  if (update_user_table(thd, table,
-			acl_user->host.hostname ? acl_user->host.hostname : "",
-			acl_user->user ? acl_user->user : "",
-			new_password, new_password_len))
+
+  if (update_user_table(table,
+                        acl_user->host.hostname ? acl_user->host.hostname : "",
+                        acl_user->user ? acl_user->user : "",
+                        new_password, new_password_len, password_field))
   {
     mysql_mutex_unlock(&acl_cache->lock); /* purecov: deadcode */
     goto end;
@@ -2130,22 +2488,25 @@ bool hostname_requires_resolving(const c
 }
 
 
-/*
+/**
   Update record for user in mysql.user privilege table with new password.
 
-  SYNOPSIS
-    update_user_table()
-      thd               Thread handle
-      table             Pointer to TABLE object for open mysql.user table
-      host/user         Hostname/username pair identifying user for which
-                        new password should be set
-      new_password      New password
-      new_password_len  Length of new password
+  @param table Pointer to TABLE object for open mysql.user table
+  @param host Hostname
+  @param user Username
+  @param new_password New password hash
+  @param new_password_len Length of new password hash
+  @param password_field The password field to use 
+ 
+  @see change_password
+ 
 */
 
-static bool update_user_table(THD *thd, TABLE *table,
-                              const char *host, const char *user,
-			      const char *new_password, uint new_password_len)
+static bool
+update_user_table(TABLE *table,
+                  const char *host, const char *user,
+                  const char *new_password, uint new_password_len,
+                  enum mysql_user_table_field password_field)
 {
   char user_key[MAX_KEY_LENGTH];
   int error;
@@ -2153,8 +2514,11 @@ static bool update_user_table(THD *thd, 
   DBUG_PRINT("enter",("user: %s  host: %s",user,host));
 
   table->use_all_columns();
-  table->field[0]->store(host,(uint) strlen(host), system_charset_info);
-  table->field[1]->store(user,(uint) strlen(user), system_charset_info);
+  DBUG_ASSERT(host != '\0');
+  table->field[MYSQL_USER_FIELD_HOST]->store(host,(uint) strlen(host),
+                                             system_charset_info);
+  table->field[MYSQL_USER_FIELD_USER]->store(user,(uint) strlen(user),
+                                             system_charset_info);
   key_copy((uchar *) user_key, table->record[0], table->key_info,
            table->key_info->key_length);
 
@@ -2167,13 +2531,17 @@ static bool update_user_table(THD *thd, 
     DBUG_RETURN(1);				/* purecov: deadcode */
   }
   store_record(table,record[1]);
-  table->field[2]->store(new_password, new_password_len, system_charset_info);
+  
+  table->field[(int)password_field]->store(new_password, new_password_len,
+                                           system_charset_info);
+
   if ((error=table->file->ha_update_row(table->record[1],table->record[0])) &&
-      error != HA_ERR_RECORD_IS_THE_SAME)
+       error != HA_ERR_RECORD_IS_THE_SAME)
   {
     table->file->print_error(error,MYF(0));	/* purecov: deadcode */
     DBUG_RETURN(1);
   }
+
   DBUG_RETURN(0);
 }
 
@@ -2210,12 +2578,44 @@ static bool test_if_create_new_users(THD
   return create_new_users;
 }
 
+inline bool auth_plugin_is_built_in(const char *plugin_name)
+{
+ return (plugin_name == native_password_plugin_name.str ||
+         plugin_name == sha256_password_plugin_name.str ||
+         plugin_name == old_password_plugin_name.str);
+}
+
+void optimize_plugin_compare_by_pointer(LEX_STRING *plugin_name)
+{
+  if (my_strcasecmp(system_charset_info, sha256_password_plugin_name.str,
+                    plugin_name->str) == 0)
+  {
+    plugin_name->str= sha256_password_plugin_name.str;
+    plugin_name->length= sha256_password_plugin_name.length;
+  }
+  else
+  if (my_strcasecmp(system_charset_info, native_password_plugin_name.str,
+                    plugin_name->str) == 0)
+  {
+    plugin_name->str= native_password_plugin_name.str;
+    plugin_name->length= native_password_plugin_name.length;
+  }
+  else
+  if (my_strcasecmp(system_charset_info, old_password_plugin_name.str,
+                    plugin_name->str) == 0)
+  {
+    plugin_name->str= old_password_plugin_name.str;
+    plugin_name->length= old_password_plugin_name.length;
+  }
+
+  DBUG_ASSERT(auth_plugin_is_built_in(native_password_plugin_name.str));
+}
 
 /****************************************************************************
   Handle GRANT commands
 ****************************************************************************/
 
-static int replace_user_table(THD *thd, TABLE *table, const LEX_USER &combo,
+static int replace_user_table(THD *thd, TABLE *table, LEX_USER *combo,
 			      ulong rights, bool revoke_grant,
 			      bool can_create_user, bool no_auto_create)
 {
@@ -2226,27 +2626,17 @@ static int replace_user_table(THD *thd, 
   char what= (revoke_grant) ? 'N' : 'Y';
   uchar user_key[MAX_KEY_LENGTH];
   LEX *lex= thd->lex;
+  bool sha2_plugin= false;
   DBUG_ENTER("replace_user_table");
 
   mysql_mutex_assert_owner(&acl_cache->lock);
-
-  if (combo.password.str && combo.password.str[0])
-  {
-    if (combo.password.length != SCRAMBLED_PASSWORD_CHAR_LENGTH &&
-        combo.password.length != SCRAMBLED_PASSWORD_CHAR_LENGTH_323)
-    {
-      my_error(ER_PASSWD_LENGTH, MYF(0), SCRAMBLED_PASSWORD_CHAR_LENGTH);
-      DBUG_RETURN(-1);
-    }
-    password_len= combo.password.length;
-    password=combo.password.str;
-  }
-
+ 
   table->use_all_columns();
-  table->field[0]->store(combo.host.str,combo.host.length,
-                         system_charset_info);
-  table->field[1]->store(combo.user.str,combo.user.length,
-                         system_charset_info);
+  DBUG_ASSERT(combo->host.str != '\0');
+  table->field[MYSQL_USER_FIELD_HOST]->store(combo->host.str,combo->host.length,
+                                             system_charset_info);
+  table->field[MYSQL_USER_FIELD_USER]->store(combo->user.str,combo->user.length,
+                                             system_charset_info);
   key_copy(user_key, table->record[0], table->key_info,
            table->key_info->key_length);
 
@@ -2254,12 +2644,35 @@ static int replace_user_table(THD *thd, 
                                          HA_WHOLE_KEY,
                                          HA_READ_KEY_EXACT))
   {
-    /* what == 'N' means revoke */
+    /*
+      The user record wasn't found; if the intention was to revoke privileges
+      (indicated by what == 'N') then execution must fail now.
+    */
     if (what == 'N')
     {
-      my_error(ER_NONEXISTING_GRANT, MYF(0), combo.user.str, combo.host.str);
+      my_error(ER_NONEXISTING_GRANT, MYF(0), combo->user.str, combo->host.str);
       goto end;
     }
+    
+    /* 1. Unresolved plugins become default plugin */
+    if (!combo->uses_identified_with_clause)
+    {
+      combo->plugin.str= default_auth_plugin_name->str;
+      combo->plugin.length= default_auth_plugin_name->length;
+      combo->uses_identified_with_clause= false;
+    }
+    /* 2. Digest password if needed (plugin must have been resolved) */
+    if (combo->uses_identified_by_clause)
+    {
+      if (digest_password(thd, combo))
+      {
+        // TODO issue error
+        error= 1;
+        goto end;
+      }
+    }
+    password= combo->password.str;
+    password_len= combo->password.length;
     /*
       There are four options which affect the process of creation of
       a new user (mysqld option --safe-create-user, 'insert' privilege
@@ -2273,9 +2686,11 @@ static int replace_user_table(THD *thd, 
 
       see also test_if_create_new_users()
     */
-    else if (!password_len && !combo.plugin.length && no_auto_create)
+    if (!password_len &&
+        auth_plugin_is_built_in(combo->plugin.str) && 
+        no_auto_create)
     {
-      my_error(ER_PASSWORD_NO_MATCH, MYF(0), combo.user.str, combo.host.str);
+      my_error(ER_PASSWORD_NO_MATCH, MYF(0), combo->user.str, combo->host.str);
       goto end;
     }
     else if (!can_create_user)
@@ -2284,41 +2699,157 @@ static int replace_user_table(THD *thd, 
                thd->security_ctx->user, thd->security_ctx->host_or_ip);
       goto end;
     }
-    else if (combo.plugin.str[0])
+    else if (combo->plugin.str[0])
     {
-      if (!plugin_is_ready(&combo.plugin, MYSQL_AUTHENTICATION_PLUGIN))
+      if (!plugin_is_ready(&combo->plugin, MYSQL_AUTHENTICATION_PLUGIN))
       {
-        my_error(ER_PLUGIN_IS_NOT_LOADED, MYF(0), combo.plugin.str);
+        my_error(ER_PLUGIN_IS_NOT_LOADED, MYF(0), combo->plugin.str);
         goto end;
       }
     }
 
     old_row_exists = 0;
     restore_record(table,s->default_values);
-    table->field[0]->store(combo.host.str,combo.host.length,
-                           system_charset_info);
-    table->field[1]->store(combo.user.str,combo.user.length,
-                           system_charset_info);
-    table->field[2]->store(password, password_len,
-                           system_charset_info);
+    DBUG_ASSERT(combo->host.str != '\0');
+    table->field[MYSQL_USER_FIELD_HOST]->store(combo->host.str,combo->host.length,
+                                               system_charset_info);
+    table->field[MYSQL_USER_FIELD_USER]->store(combo->user.str,combo->user.length,
+                                               system_charset_info);
+    /*
+      Examine the password hash to determine which field to use when storing it.
+    */
+    if (combo->plugin.str == sha256_password_plugin_name.str)
+    {
+      /* Use the Password2 field */
+      if (password_len > 0)
+        table->
+          field[MYSQL_USER_FIELD_PASSWORD2]->store(password, password_len+1,
+                                                   system_charset_info);
+      /* Assert that the proper plugin is set */
+      table->
+        field[MYSQL_USER_FIELD_PLUGIN]->
+          store(sha256_password_plugin_name.str,
+                sha256_password_plugin_name.length,
+                system_charset_info);
+
+    }
+    else
+    {
+      /* Use the legacy Password field */
+      table->field[MYSQL_USER_FIELD_PASSWORD]->store(password, password_len,
+                                                     system_charset_info);
+      table->field[MYSQL_USER_FIELD_PASSWORD2]->store("\0", 1,
+                                                      system_charset_info);
+    }
   }
-  else
+  else // if (table->file->ha_index_read_idx_map [..]
   {
+    /*
+      There is a matching user record ------------------------------------------
+     */
+
     old_row_exists = 1;
     store_record(table,record[1]);			// Save copy for update
-    /* what == 'N' means revoke */
-    if (combo.plugin.length && what != 'N')
+    
+    /* 1. resolve plugins in the LEX_USER struct if needed */
+    if (!combo->uses_identified_with_clause)
+    {
+      /*
+        Get old plugin value from storage.
+      */
+      combo->plugin.str=
+        get_field(thd->mem_root, table->field[MYSQL_USER_FIELD_PLUGIN]);
+
+      /* 
+        It is important not to include the trailing '\0' in the string length 
+        because otherwise the plugin hash search will fail.
+      */
+      if (combo->plugin.str)
+      {
+        combo->plugin.length= strlen(combo->plugin.str);
+
+        /*
+          Optimize for pointer comparision of built-in plugin name
+        */
+
+        optimize_plugin_compare_by_pointer(&combo->plugin);
+      }
+    }    
+    
+    /* No value for plugin field means default plugin is used */
+    if (combo->plugin.str == NULL || combo->plugin.str == '\0')
+    {
+      combo->plugin.str= default_auth_plugin_name->str;
+      combo->plugin.length= default_auth_plugin_name->length;
+    }
+    
+    if (combo->uses_identified_with_clause)
+    {
+      /*
+        Don't allow old plugin fields to change.
+      */
+      char *old_plugin= get_field(thd->mem_root,
+                                  table->field[MYSQL_USER_FIELD_PLUGIN]);
+      if (old_plugin != NULL &&
+          my_strcasecmp(system_charset_info, combo->plugin.str, old_plugin))
+      {
+        error= 1;
+        my_error(ER_GRANT_PLUGIN_USER_EXISTS, MYF(0), combo->user.length,
+                 combo->user.str);
+        goto end;
+      }
+    }
+
+    if (!combo->uses_authentication_string_clause)
+    {
+      combo->auth.str= get_field(thd->mem_root,
+        table->field[MYSQL_USER_FIELD_AUTHENTICATION_STRING]);
+      if (combo->auth.str)
+        combo->auth.length= strlen(combo->auth.str);
+      else
+        combo->auth.length= 0;
+    }
+    
+    /* 2. Digest password if needed (plugin must have been resolved */
+    if (combo->uses_identified_by_clause)
     {
-        my_error(ER_GRANT_PLUGIN_USER_EXISTS, MYF(0), combo.user.length, 
-                 combo.user.str);
+      if (digest_password(thd, combo))
+      {
+        // TODO issue error
+        error= 1;
         goto end;
+      }
+    }
+    password= combo->password.str;
+    password_len= combo->password.length;
+
+    if (password_len > 0)
+    {
+      /*
+        Examine the password hash to determine which field to use when storing
+        it.
+      */
+      if (combo->plugin.str == sha256_password_plugin_name.str)
+      {
+        sha2_plugin= true;
+        table->field[MYSQL_USER_FIELD_PASSWORD2]->
+          store(password, password_len, system_charset_info);       
+      }
+      else
+      {
+        /* The legacy Password field is used */
+        table->field[MYSQL_USER_FIELD_PASSWORD]->
+          store(password, password_len, system_charset_info);
+        table->field[MYSQL_USER_FIELD_PASSWORD2]->
+          store("\0", 1, system_charset_info);
+      }
     }
-    if (combo.password.str)                             // If password given
-      table->field[2]->store(password, password_len, system_charset_info);
     else if (!rights && !revoke_grant &&
              lex->ssl_type == SSL_TYPE_NOT_SPECIFIED &&
              !lex->mqh.specified_limits)
     {
+     
+      DBUG_PRINT("info",("Proxy user exit path"));
       DBUG_RETURN(0);
     }
   }
@@ -2343,69 +2874,75 @@ static int replace_user_table(THD *thd, 
     /* We write down SSL related ACL stuff */
     switch (lex->ssl_type) {
     case SSL_TYPE_ANY:
-      table->field[next_field]->store(STRING_WITH_LEN("ANY"),
+      table->field[MYSQL_USER_FIELD_SSL_TYPE]->store(STRING_WITH_LEN("ANY"),
                                       &my_charset_latin1);
-      table->field[next_field+1]->store("", 0, &my_charset_latin1);
-      table->field[next_field+2]->store("", 0, &my_charset_latin1);
-      table->field[next_field+3]->store("", 0, &my_charset_latin1);
+      table->field[MYSQL_USER_FIELD_SSL_CIPHER]->
+        store("", 0, &my_charset_latin1);
+      table->field[MYSQL_USER_FIELD_X509_ISSUER]->store("", 0, &my_charset_latin1);
+      table->field[MYSQL_USER_FIELD_X509_SUBJECT]->store("", 0, &my_charset_latin1);
       break;
     case SSL_TYPE_X509:
-      table->field[next_field]->store(STRING_WITH_LEN("X509"),
+      table->field[MYSQL_USER_FIELD_SSL_TYPE]->store(STRING_WITH_LEN("X509"),
                                       &my_charset_latin1);
-      table->field[next_field+1]->store("", 0, &my_charset_latin1);
-      table->field[next_field+2]->store("", 0, &my_charset_latin1);
-      table->field[next_field+3]->store("", 0, &my_charset_latin1);
+      table->field[MYSQL_USER_FIELD_SSL_CIPHER]->
+        store("", 0, &my_charset_latin1);
+      table->field[MYSQL_USER_FIELD_X509_ISSUER]->store("", 0, &my_charset_latin1);
+      table->field[MYSQL_USER_FIELD_X509_SUBJECT]->store("", 0, &my_charset_latin1);
       break;
     case SSL_TYPE_SPECIFIED:
-      table->field[next_field]->store(STRING_WITH_LEN("SPECIFIED"),
+      table->field[MYSQL_USER_FIELD_SSL_TYPE]->store(STRING_WITH_LEN("SPECIFIED"),
                                       &my_charset_latin1);
-      table->field[next_field+1]->store("", 0, &my_charset_latin1);
-      table->field[next_field+2]->store("", 0, &my_charset_latin1);
-      table->field[next_field+3]->store("", 0, &my_charset_latin1);
+      table->field[MYSQL_USER_FIELD_SSL_CIPHER]->store("", 0, &my_charset_latin1);
+      table->field[MYSQL_USER_FIELD_X509_ISSUER]->store("", 0, &my_charset_latin1);
+      table->field[MYSQL_USER_FIELD_X509_SUBJECT]->store("", 0, &my_charset_latin1);
       if (lex->ssl_cipher)
-        table->field[next_field+1]->store(lex->ssl_cipher,
+        table->field[MYSQL_USER_FIELD_SSL_CIPHER]->store(lex->ssl_cipher,
                                 strlen(lex->ssl_cipher), system_charset_info);
       if (lex->x509_issuer)
-        table->field[next_field+2]->store(lex->x509_issuer,
+        table->field[MYSQL_USER_FIELD_X509_ISSUER]->store(lex->x509_issuer,
                                 strlen(lex->x509_issuer), system_charset_info);
       if (lex->x509_subject)
-        table->field[next_field+3]->store(lex->x509_subject,
+        table->field[MYSQL_USER_FIELD_X509_SUBJECT]->store(lex->x509_subject,
                                 strlen(lex->x509_subject), system_charset_info);
       break;
     case SSL_TYPE_NOT_SPECIFIED:
       break;
     case SSL_TYPE_NONE:
-      table->field[next_field]->store("", 0, &my_charset_latin1);
-      table->field[next_field+1]->store("", 0, &my_charset_latin1);
-      table->field[next_field+2]->store("", 0, &my_charset_latin1);
-      table->field[next_field+3]->store("", 0, &my_charset_latin1);
+      table->field[MYSQL_USER_FIELD_SSL_TYPE]->store("", 0, &my_charset_latin1);
+      table->field[MYSQL_USER_FIELD_SSL_CIPHER]->store("", 0, &my_charset_latin1);
+      table->field[MYSQL_USER_FIELD_X509_ISSUER]->store("", 0, &my_charset_latin1);
+      table->field[MYSQL_USER_FIELD_X509_SUBJECT]->store("", 0, &my_charset_latin1);
       break;
     }
     next_field+=4;
 
     USER_RESOURCES mqh= lex->mqh;
     if (mqh.specified_limits & USER_RESOURCES::QUERIES_PER_HOUR)
-      table->field[next_field]->store((longlong) mqh.questions, TRUE);
+      table->field[MYSQL_USER_FIELD_MAX_QUESTIONS]->
+        store((longlong) mqh.questions, TRUE);
     if (mqh.specified_limits & USER_RESOURCES::UPDATES_PER_HOUR)
-      table->field[next_field+1]->store((longlong) mqh.updates, TRUE);
+      table->field[MYSQL_USER_FIELD_MAX_UPDATES]->
+        store((longlong) mqh.updates, TRUE);
     if (mqh.specified_limits & USER_RESOURCES::CONNECTIONS_PER_HOUR)
-      table->field[next_field+2]->store((longlong) mqh.conn_per_hour, TRUE);
+      table->field[MYSQL_USER_FIELD_MAX_CONNECTIONS]->
+        store((longlong) mqh.conn_per_hour, TRUE);
     if (table->s->fields >= 36 &&
         (mqh.specified_limits & USER_RESOURCES::USER_CONNECTIONS))
-      table->field[next_field+3]->store((longlong) mqh.user_conn, TRUE);
+      table->field[MYSQL_USER_FIELD_MAX_USER_CONNECTIONS]->
+        store((longlong) mqh.user_conn, TRUE);
     mqh_used= mqh_used || mqh.questions || mqh.updates || mqh.conn_per_hour;
 
     next_field+= 4;
-    if (combo.plugin.str[0])
+    if (combo->plugin.length > 0 && !old_row_exists)
     {
-      if (table->s->fields >= 41 && combo.plugin.str[0])
+      if (table->s->fields >= 41)
       {
-        table->field[next_field]->store(combo.plugin.str, combo.plugin.length,
-                                        system_charset_info);
-        table->field[next_field]->set_notnull();
-        table->field[next_field + 1]->store(combo.auth.str, combo.auth.length,
-                                            system_charset_info);
-        table->field[next_field + 1]->set_notnull();
+        table->field[MYSQL_USER_FIELD_PLUGIN]->
+          store(combo->plugin.str, combo->plugin.length, system_charset_info);
+        table->field[MYSQL_USER_FIELD_PLUGIN]->set_notnull();
+        table->field[MYSQL_USER_FIELD_AUTHENTICATION_STRING]->
+          store(combo->auth.str, combo->auth.length, system_charset_info);
+        table->field[MYSQL_USER_FIELD_AUTHENTICATION_STRING]->set_notnull();
       }
       else
       {
@@ -2416,7 +2953,7 @@ static int replace_user_table(THD *thd, 
   }
 
   if (old_row_exists)
-  {
+  {   
     /*
       We should NEVER delete from the user table, as a uses can still
       use mysqld even if he doesn't have any privileges in the user table!
@@ -2451,26 +2988,26 @@ end:
   {
     acl_cache->clear(1);			// Clear privilege cache
     if (old_row_exists)
-      acl_update_user(combo.user.str, combo.host.str,
-                      combo.password.str, password_len,
+      acl_update_user(combo->user.str, combo->host.str,
+                      combo->password.str, password_len,
 		      lex->ssl_type,
 		      lex->ssl_cipher,
 		      lex->x509_issuer,
 		      lex->x509_subject,
 		      &lex->mqh,
 		      rights,
-		      &combo.plugin,
-		      &combo.auth);
+		      &combo->plugin,
+		      &combo->auth);
     else
-      acl_insert_user(combo.user.str, combo.host.str, password, password_len,
+      acl_insert_user(combo->user.str, combo->host.str, password, password_len,
 		      lex->ssl_type,
 		      lex->ssl_cipher,
 		      lex->x509_issuer,
 		      lex->x509_subject,
 		      &lex->mqh,
 		      rights,
-		      &combo.plugin,
-		      &combo.auth);
+		      &combo->plugin,
+		      &combo->auth);
   }
   DBUG_RETURN(error);
 }
@@ -3667,9 +4204,18 @@ int mysql_table_grant(THD *thd, TABLE_LI
     {
       result= TRUE;
       continue;
-    }  
+    }
+
+    /*
+      No User, but a password?
+      They did GRANT ... TO CURRENT_USER() IDENTIFIED BY ... !
+      Get the current user, and shallow-copy the new password to them!
+    */
+    if (!tmp_Str->user.str && tmp_Str->password.str)
+      Str->password= tmp_Str->password;
+    
     /* Create user if needed */
-    error=replace_user_table(thd, tables[0].table, *Str,
+    error=replace_user_table(thd, tables[0].table, Str,
 			     0, revoke_grant, create_new_users,
                              test(thd->variables.sql_mode &
                                   MODE_NO_AUTO_CREATE_USER));
@@ -3900,8 +4446,9 @@ bool mysql_routine_grant(THD *thd, TABLE
       result= TRUE;
       continue;
     }  
+    
     /* Create user if needed */
-    error=replace_user_table(thd, tables[0].table, *Str,
+    error=replace_user_table(thd, tables[0].table, Str,
 			     0, revoke_grant, create_new_users,
                              test(thd->variables.sql_mode &
                                   MODE_NO_AUTO_CREATE_USER));
@@ -3971,6 +4518,79 @@ bool mysql_routine_grant(THD *thd, TABLE
 }
 
 
+/**
+  Allocates a new buffer and calculates digested password hash based on plugin
+  and old_passwords. The old buffer containing the clear text password is
+  simply discarded as this memory belongs to the LEX will be freed when the
+  session ends.
+ 
+  @param THD the tread handler used for allocating memory
+  @param user_record[in, out] The user record
+ 
+  @return Failure state
+  @retval 0 OK
+  @retval 1 ERROR
+*/
+
+int digest_password(THD *thd, LEX_USER *user_record)
+{
+  /*
+    Transform password into a password hash 
+  */
+  if (user_record->plugin.str == sha256_password_plugin_name.str)
+  {
+    char *buff=  (char *) thd->alloc(CRYPT_MAX_PASSWORD_SIZE+1);
+    if (buff == NULL)
+    {
+      //TODO issue OOM error
+      return 1;
+    }
+    my_make_scrambled_password(buff, user_record->password.str,
+                               user_record->password.length);
+    user_record->password.str= buff;
+    user_record->password.length= strlen(buff)+1;
+  }
+  else
+  if (user_record->plugin.str == native_password_plugin_name.str ||
+      user_record->plugin.str == old_password_plugin_name.str)
+  {
+    if (thd->variables.old_passwords == 1)
+    {
+      char *buff= 
+        (char *) thd->alloc(SCRAMBLED_PASSWORD_CHAR_LENGTH_323+1);
+      if (buff == NULL)
+      {
+        // TODO issue OOM error
+        return 1;
+      }
+      my_make_scrambled_password_323(buff, user_record->password.str,
+                                     user_record->password.length);
+      user_record->password.str= buff;
+      user_record->password.length= SCRAMBLED_PASSWORD_CHAR_LENGTH_323;
+    }
+    else
+    {
+      char *buff= 
+        (char *) thd->alloc(SCRAMBLED_PASSWORD_CHAR_LENGTH+1);
+      if (buff == NULL)
+      {
+        // TODO issue OOM error
+        return 1;
+      }
+      my_make_scrambled_password_sha1(buff, user_record->password.str,
+                                      user_record->password.length);
+      user_record->password.str= buff;
+      user_record->password.length= SCRAMBLED_PASSWORD_CHAR_LENGTH;
+    }
+  } // end if native_password_plugin_name || old_password_plugin_name
+  else
+  {
+    user_record->password.str= 0;
+    user_record->password.length= 0;
+  }
+  return 0;
+}
+
 bool mysql_grant(THD *thd, const char *db, List <LEX_USER> &list,
                  ulong rights, bool revoke_grant, bool is_proxy)
 {
@@ -4081,7 +4701,8 @@ bool mysql_grant(THD *thd, const char *d
     */
     if (!tmp_Str->user.str && tmp_Str->password.str)
       Str->password= tmp_Str->password;
-    if (replace_user_table(thd, tables[0].table, *Str,
+ 
+    if (replace_user_table(thd, tables[0].table, Str,
                            (!db ? rights : 0), revoke_grant, create_new_users,
                            test(thd->variables.sql_mode &
                                 MODE_NO_AUTO_CREATE_USER)))
@@ -5275,6 +5896,14 @@ bool mysql_show_grants(THD *thd,LEX_USER
     global.append(lex_user->host.str,lex_user->host.length,
 		  system_charset_info);
     global.append ('\'');
+    if (acl_user->plugin.str == sha256_password_plugin_name.str)
+    {
+      global.append(STRING_WITH_LEN(" IDENTIFIED BY PASSWORD '"));
+      //global.append((const char *)&acl_user->sha2_hash[0]);
+      global.append("{$5}");
+      global.append('\'');
+    }
+    else
     if (acl_user->salt_len)
     {
       char passwd_buff[SCRAMBLED_PASSWORD_CHAR_LENGTH+1];
@@ -6492,12 +7121,27 @@ bool mysql_create_user(THD *thd, List <L
   log_query.append(STRING_WITH_LEN("CREATE USER"));
   while ((tmp_user_name= user_list++))
   {
+    /*
+      If tmp_user_name.user.str is == NULL then
+      user_name := tmp_user_name.
+      Else user_name.user := sctx->user
+      TODO and all else is turned to NULL !! Why?
+    */
     if (!(user_name= get_current_user(thd, tmp_user_name)))
     {
       result= TRUE;
       continue;
     }
 
+    /*
+      If no plugin is given, set a default plugin (sha256_password_plugin)
+    */
+    if (user_name->plugin.length == 0 && user_name->uses_identified_with_clause)
+    {
+      user_name->plugin.str= default_auth_plugin_name->str;
+      user_name->plugin.length= default_auth_plugin_name->length;
+    }
+
     log_query.append(' ');
     append_user(&log_query, user_name, FALSE, TRUE);
     log_query.append(',');
@@ -6513,7 +7157,7 @@ bool mysql_create_user(THD *thd, List <L
       continue;
     }
 
-    if (replace_user_table(thd, tables[0].table, *user_name, 0, 0, 1, 0))
+    if (replace_user_table(thd, tables[0].table, user_name, 0, 0, 1, 0))
     {
       append_user(&wrong_users, user_name, wrong_users.length() > 0);
       result= TRUE;
@@ -6521,7 +7165,7 @@ bool mysql_create_user(THD *thd, List <L
     }
 
     some_users_created= TRUE;
-  }
+  } // END while tmp_user_name= user_lists++
 
   mysql_mutex_unlock(&acl_cache->lock);
 
@@ -6783,7 +7427,7 @@ bool mysql_revoke_all(THD *thd,  List <L
     }
 
     if (replace_user_table(thd, tables[0].table,
-			   *lex_user, ~(ulong)0, 1, 0, 0))
+			   lex_user, ~(ulong)0, 1, 0, 0))
     {
       result= -1;
       continue;
@@ -7100,7 +7744,6 @@ bool sp_grant_privileges(THD *thd, const
   List<LEX_USER> user_list;
   bool result;
   ACL_USER *au;
-  char passwd_buff[SCRAMBLED_PASSWORD_CHAR_LENGTH+1];
   Dummy_error_handler error_handler;
   DBUG_ENTER("sp_grant_privileges");
 
@@ -7140,37 +7783,10 @@ bool sp_grant_privileges(THD *thd, const
   combo->password= empty_lex_str;
   combo->plugin= empty_lex_str;
   combo->auth= empty_lex_str;
-
-  if(au)
-  {
-    if (au->salt_len)
-    {
-      if (au->salt_len == SCRAMBLE_LENGTH)
-      {
-        make_password_from_salt(passwd_buff, au->salt);
-        combo->password.length= SCRAMBLED_PASSWORD_CHAR_LENGTH;
-      }
-      else if (au->salt_len == SCRAMBLE_LENGTH_323)
-      {
-        make_password_from_salt_323(passwd_buff, (ulong *) au->salt);
-        combo->password.length= SCRAMBLED_PASSWORD_CHAR_LENGTH_323;
-      }
-      else
-      {
-        push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_PASSWD_LENGTH,
-                            ER(ER_PASSWD_LENGTH), SCRAMBLED_PASSWORD_CHAR_LENGTH);
-        return TRUE;
-      }
-      combo->password.str= passwd_buff;
-    }
-
-    if (au->plugin.str != native_password_plugin_name.str &&
-        au->plugin.str != old_password_plugin_name.str)
-    {
-      combo->plugin= au->plugin;
-      combo->auth= au->auth_string;
-    }
-  }
+  combo->uses_identified_by_clause= false;
+  combo->uses_identified_with_clause= false;
+  combo->uses_identified_by_password_clause= false;
+  combo->uses_authentication_string_clause= false;
 
   if (user_list.push_back(combo))
     DBUG_RETURN(TRUE);
@@ -8284,9 +8900,14 @@ static bool find_mpvio_user(MPVIO_EXT *m
         compare_hostname(&acl_user_tmp->host, mpvio->host, mpvio->ip))
     {
       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;
+
+      /*
+        When setting mpvio->acl_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;
       else
         make_lex_string_root(mpvio->mem_root, 
                              &mpvio->acl_user_plugin, 
@@ -8303,11 +8924,11 @@ static bool find_mpvio_user(MPVIO_EXT *m
     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->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,
                               native_password_plugin_name.str));
     DBUG_ASSERT(my_strcasecmp(system_charset_info, mpvio->acl_user->plugin.str,
@@ -8323,7 +8944,7 @@ static bool find_mpvio_user(MPVIO_EXT *m
   strmake(mpvio->auth_info.authenticated_as, mpvio->acl_user->user ?
           mpvio->acl_user->user : "", USERNAME_LENGTH);
   DBUG_PRINT("info", ("exit: user=%s, auth_string=%s, authenticated as=%s"
-                      "plugin=%s",
+                      ", plugin=%s",
                       mpvio->auth_info.user_name,
                       mpvio->auth_info.auth_string,
                       mpvio->auth_info.authenticated_as,
@@ -9094,22 +9715,27 @@ static bool acl_check_ssl(THD *thd, cons
 static int do_auth_once(THD *thd, const LEX_STRING *auth_plugin_name,
                         MPVIO_EXT *mpvio)
 {
+  DBUG_ENTER("do_auth_once");
   int res= CR_OK, old_status= MPVIO_EXT::FAILURE;
   bool unlock_plugin= false;
-  plugin_ref plugin;
+  plugin_ref plugin= NULL;
 
   if (auth_plugin_name->str == native_password_plugin_name.str)
     plugin= native_password_plugin;
-  else
 #ifndef EMBEDDED_LIBRARY
+  else
   if (auth_plugin_name->str == old_password_plugin_name.str)
     plugin= old_password_plugin;
-  else if ((plugin= my_plugin_lock_by_name(thd, auth_plugin_name,
-                                           MYSQL_AUTHENTICATION_PLUGIN)))
-    unlock_plugin= true;
   else
+  {
+    if (auth_plugin_name->length == 0)
+      auth_plugin_name= default_auth_plugin_name;
+    if ((plugin= my_plugin_lock_by_name(thd, auth_plugin_name,
+                                        MYSQL_AUTHENTICATION_PLUGIN)))
+      unlock_plugin= true;
+  }
 #endif
-    plugin= NULL;
+
     
   mpvio->plugin= plugin;
   old_status= mpvio->status;
@@ -9140,7 +9766,7 @@ static int do_auth_once(THD *thd, const 
   if (old_status == MPVIO_EXT::RESTART && mpvio->status == MPVIO_EXT::RESTART)
     mpvio->status= MPVIO_EXT::FAILURE; // reset to the default
 
-  return res;
+  DBUG_RETURN(res);
 }
 
 
@@ -9349,6 +9975,8 @@ acl_authenticate(THD *thd, uint connect_
         DBUG_RETURN(1);
       }
       acl_user= acl_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));
       mysql_mutex_unlock(&acl_cache->lock);
     }
 #endif
@@ -9621,6 +10249,124 @@ static int old_password_authenticate(MYS
   return CR_ERROR;
 }
 
+static int sha256_password_authenticate(MYSQL_PLUGIN_VIO *vio,
+                                        MYSQL_SERVER_AUTH_INFO *info)
+{
+  uchar *pkt;
+  int pkt_len;
+  MPVIO_EXT *mpvio= (MPVIO_EXT *) vio;
+  char  *user_salt_begin;
+  char  *user_salt_end;
+  uint user_salt_length= 0;
+  char user_salt[CRYPT_SALT_LENGTH+1];
+  char stage2[CRYPT_MAX_PASSWORD_SIZE+1];
+  bool has_error= false;
+  const char *one_round_param[2]= {"rounds=1", 0};
+
+  DBUG_ENTER("sha256_password_authenticate");
+
+  /* generate the scramble. */
+  generate_user_salt(mpvio->scramble, SCRAMBLE_LENGTH);
+  mpvio->scramble[SCRAMBLE_LENGTH]= '\0';
+
+  /* send it to the client */
+  if (mpvio->write_packet(mpvio, (uchar*) mpvio->scramble, SCRAMBLE_LENGTH + 1))
+    DBUG_RETURN(CR_ERROR);
+
+  /*
+    To complete the handshake the authentication API demands that read_packet()
+    is called. After the call to read_packet() the user name will appear in
+    mpvio->acl_user.
+
+    Get request for user salt (1 byte). This is used to find out if user
+    supplied a password.
+  */
+  if ((pkt_len= mpvio->read_packet(mpvio, &pkt)) < 0)
+    DBUG_RETURN(CR_ERROR);
+
+  if(pkt_len == 1 && pkt[0] == 1)
+    info->password_used= PASSWORD_USED_YES;
+  else
+    info->password_used= PASSWORD_USED_NO;
+
+  /*
+     Client might have reported wrong plugin so we might need to restart the
+     handshake with a new plugin.
+     NOTE this check must happen after mpvio->read_packet()
+   */
+  if (mpvio->status == MPVIO_EXT::RESTART || has_error)
+    DBUG_RETURN(CR_ERROR);
+
+  if (mpvio->acl_user->sha2_hash[0] == 0) /* no password */
+  {
+    if (info->password_used == PASSWORD_USED_NO)
+    {
+      DBUG_PRINT("info",("Client didn't use a password. Authentication plugin "
+                         " short cut path."));
+      DBUG_RETURN(CR_OK); /* Authentication can still fail because of host */
+    }
+  }
+  
+  if (mpvio->acl_user && mpvio->acl_user->sha2_hash)
+  {
+    user_salt_begin= (char *)mpvio->acl_user->sha2_hash;
+    if (extract_user_salt(&user_salt_begin,
+                          &user_salt_end) == CRYPT_SALT_LENGTH)
+    {
+      memcpy(user_salt, user_salt_begin, CRYPT_SALT_LENGTH);
+      user_salt_length= CRYPT_SALT_LENGTH;
+    }
+  }
+  else
+  {
+    has_error= true;
+    /*
+      Generate fake random salt; TODO should be a hash of the client
+      supplied user name and a random salt generated at server boot time.
+     */
+    create_random_string(user_salt, CRYPT_SALT_LENGTH, mpvio->rand);
+    user_salt_length= strlen(user_salt); // null terminated?
+  }
+
+  /* send user salt to the client */
+  if (mpvio->write_packet(mpvio, (uchar*) user_salt, strlen(user_salt)))
+    DBUG_RETURN(CR_ERROR);
+
+
+  /* read the reply with the encrypted password */
+  if ((pkt_len= mpvio->read_packet(mpvio, &pkt)) < 0)
+    DBUG_RETURN(CR_ERROR);
+
+#ifdef NO_EMBEDDED_ACCESS_CHECKS
+  DBUG_RETURN(CR_OK);
+#endif
+
+  if (mpvio->acl_user && user_salt_length == 0)
+  {
+    DBUG_PRINT("info",("Server plugin SHA256 has error's; exiting"));
+    DBUG_RETURN(CR_ERROR);
+  }
+
+  if (pkt_len > CRYPT_MAX_PASSWORD_SIZE+1)
+    DBUG_RETURN(CR_ERROR);
+    
+  crypt_genhash_impl(stage2,
+                     CRYPT_MAX_PASSWORD_SIZE,
+                     (const char *)mpvio->acl_user->sha2_hash,
+                     strlen((const char*)mpvio->acl_user->sha2_hash),
+                     (const char *)mpvio->scramble,
+                     one_round_param);
+
+  int result= memcmp(stage2,
+                     pkt,
+                     pkt_len);
+  
+  if (result == 0 && !has_error)
+    DBUG_RETURN(CR_OK);
+  else
+    DBUG_RETURN(CR_ERROR);
+}
+
 static struct st_mysql_auth native_password_handler=
 {
   MYSQL_AUTHENTICATION_INTERFACE_VERSION,
@@ -9635,6 +10381,13 @@ static struct st_mysql_auth old_password
   old_password_authenticate
 };
 
+static struct st_mysql_auth sha256_password_handler=
+{
+  MYSQL_AUTHENTICATION_INTERFACE_VERSION,
+  sha256_password_plugin_name.str,
+  sha256_password_authenticate
+};
+
 mysql_declare_plugin(mysql_password)
 {
   MYSQL_AUTHENTICATION_PLUGIN,                  /* type constant    */
@@ -9663,6 +10416,20 @@ mysql_declare_plugin(mysql_password)
   NULL,                                         /* status variables */
   NULL,                                         /* system variables */
   NULL                                          /* config options   */
+},
+{
+  MYSQL_AUTHENTICATION_PLUGIN,                  /* type constant    */
+  &sha256_password_handler,                     /* type descriptor  */
+  sha256_password_plugin_name.str,              /* Name             */
+  "Oracle",                                     /* Author           */
+  "SHA256 password authentication",             /* Description      */
+  PLUGIN_LICENSE_GPL,                           /* License          */
+  NULL,                                         /* Init function    */
+  NULL,                                         /* Deinit function  */
+  0x0100,                                       /* Version (1.0)    */
+  NULL,                                         /* status variables */
+  NULL,                                         /* system variables */
+  NULL                                          /* config options   */
 }
 mysql_declare_plugin_end;
 

=== modified file 'sql/sql_acl.h'
--- a/sql/sql_acl.h	2010-10-21 09:49:16 +0000
+++ b/sql/sql_acl.h	2011-05-27 14:40:44 +0000
@@ -170,6 +170,54 @@ enum mysql_db_table_field
   MYSQL_DB_FIELD_COUNT
 };
 
+enum mysql_user_table_field
+{
+  MYSQL_USER_FIELD_HOST= 0,
+  MYSQL_USER_FIELD_USER,
+  MYSQL_USER_FIELD_PASSWORD,
+  MYSQL_USER_FIELD_SELECT_PRIV,
+  MYSQL_USER_FIELD_INSERT_PRIV,
+  MYSQL_USER_FIELD_UPDATE_PRIV,
+  MYSQL_USER_FIELD_DELETE_PRIV,
+  MYSQL_USER_FIELD_CREATE_PRIV,
+  MYSQL_USER_FIELD_DROP_PRIV,
+  MYSQL_USER_FIELD_RELOAD_PRIV,
+  MYSQL_USER_FIELD_SHUTDOWN_PRIV,
+  MYSQL_USER_FIELD_PROCESS_PRIV,
+  MYSQL_USER_FIELD_FILE_PRIV,
+  MYSQL_USER_FIELD_GRANT_PRIV,
+  MYSQL_USER_FIELD_REFERENCES_PRIV,
+  MYSQL_USER_FIELD_INDEX_PRIV,
+  MYSQL_USER_FIELD_ALTER_PRIV,
+  MYSQL_USER_FIELD_SHOW_DB_PRIV,
+  MYSQL_USER_FIELD_SUPER_PRIV,
+  MYSQL_USER_FIELD_CREATE_TMP_TABLE_PRIV,
+  MYSQL_USER_FIELD_LOCK_TABLES_PRIV,
+  MYSQL_USER_FIELD_EXECUTE_PRIV,
+  MYSQL_USER_FIELD_REPL_SLAVE_PRIV,
+  MYSQL_USER_FIELD_REPL_CLIENT_PRIV,
+  MYSQL_USER_FIELD_CREATE_VIEW_PRIV,
+  MYSQL_USER_FIELD_SHOW_VIEW_PRIV,
+  MYSQL_USER_FIELD_CREATE_ROUTINE_PRIV,
+  MYSQL_USER_FIELD_ALTER_ROUTINE_PRIV,
+  MYSQL_USER_FIELD_CREATE_USER_PRIV,
+  MYSQL_USER_FIELD_EVENT_PRIV,
+  MYSQL_USER_FIELD_TRIGGER_PRIV,
+  MYSQL_USER_FIELD_CREATE_TABLESPACE_PRIV,
+  MYSQL_USER_FIELD_SSL_TYPE,
+  MYSQL_USER_FIELD_SSL_CIPHER,
+  MYSQL_USER_FIELD_X509_ISSUER,
+  MYSQL_USER_FIELD_X509_SUBJECT,
+  MYSQL_USER_FIELD_MAX_QUESTIONS,
+  MYSQL_USER_FIELD_MAX_UPDATES,
+  MYSQL_USER_FIELD_MAX_CONNECTIONS,
+  MYSQL_USER_FIELD_MAX_USER_CONNECTIONS,
+  MYSQL_USER_FIELD_PLUGIN,
+  MYSQL_USER_FIELD_AUTHENTICATION_STRING,
+  MYSQL_USER_FIELD_PASSWORD2,
+  MYSQL_USER_FIELD_COUNT
+};
+
 extern const TABLE_FIELD_DEF mysql_db_table_def;
 extern bool mysql_user_table_is_in_short_password_format;
 
@@ -237,6 +285,7 @@ int fill_schema_schema_privileges(THD *t
 int fill_schema_table_privileges(THD *thd, TABLE_LIST *tables, Item *cond);
 int fill_schema_column_privileges(THD *thd, TABLE_LIST *tables, Item *cond);
 int wild_case_compare(CHARSET_INFO *cs, const char *str,const char *wildstr);
+int digest_password(THD *thd, LEX_USER *user_record);
 
 #ifdef NO_EMBEDDED_ACCESS_CHECKS
 #define check_grant(A,B,C,D,E,F) 0

=== modified file 'sql/sql_class.h'
--- a/sql/sql_class.h	2011-04-04 10:06:13 +0000
+++ b/sql/sql_class.h	2011-05-27 14:40:44 +0000
@@ -486,7 +486,7 @@ typedef struct system_variables
   my_bool keep_files_on_create;
 
   my_bool old_alter_table;
-  my_bool old_passwords;
+  uint old_passwords;
   my_bool big_tables;
 
   plugin_ref table_plugin;

=== modified file 'sql/sql_parse.cc'
--- a/sql/sql_parse.cc	2011-04-07 12:04:22 +0000
+++ b/sql/sql_parse.cc	2011-05-27 14:40:44 +0000
@@ -7069,6 +7069,10 @@ void get_default_definer(THD *thd, LEX_U
   definer->password= null_lex_str;
   definer->plugin= empty_lex_str;
   definer->auth= empty_lex_str;
+  definer->uses_identified_with_clause= false;
+  definer->uses_identified_by_clause= false;
+  definer->uses_authentication_string_clause= false;
+  definer->uses_identified_by_password_clause= false;
 }
 
 
@@ -7122,7 +7126,10 @@ LEX_USER *create_definer(THD *thd, LEX_S
   definer->host= *host_name;
   definer->password.str= NULL;
   definer->password.length= 0;
-
+  definer->uses_authentication_string_clause= false;
+  definer->uses_identified_by_clause= false;
+  definer->uses_identified_by_password_clause= false;
+  definer->uses_identified_with_clause= false;
   return definer;
 }
 
@@ -7142,7 +7149,31 @@ LEX_USER *create_definer(THD *thd, LEX_S
 LEX_USER *get_current_user(THD *thd, LEX_USER *user)
 {
   if (!user->user.str)  // current_user
-    return create_default_definer(thd);
+  {
+    LEX_USER *default_definer= create_default_definer(thd);
+    if (default_definer)
+    {
+      /*
+        Inherit parser semantics from the statement in which the user parameter
+        was used.
+        This is needed because a st_lex_user is both used as a component in an
+        AST and as a specifier for a particular user in the ACL subsystem.
+      */
+      default_definer->uses_authentication_string_clause=
+        user->uses_authentication_string_clause;
+      default_definer->uses_identified_by_clause=
+        user->uses_identified_by_clause;
+      default_definer->uses_identified_by_password_clause=
+        user->uses_identified_by_password_clause;
+      default_definer->uses_identified_with_clause=
+        user->uses_identified_with_clause;
+      default_definer->plugin.str= user->plugin.str;
+      default_definer->plugin.length= user->plugin.length;
+      default_definer->auth.str= user->auth.str;
+      default_definer->auth.length= user->auth.length;
+      return default_definer;
+    }
+  }
 
   return user;
 }

=== modified file 'sql/sql_yacc.yy'
--- a/sql/sql_yacc.yy	2011-03-09 20:54:55 +0000
+++ b/sql/sql_yacc.yy	2011-05-27 14:40:44 +0000
@@ -8574,7 +8574,7 @@ function_call_conflict:
           {
             THD *thd= YYTHD;
             Item* i1;
-            if (thd->variables.old_passwords)
+            if (thd->variables.old_passwords == 1)
               i1= new (thd->mem_root) Item_func_old_password($3);
             else
               i1= new (thd->mem_root) Item_func_password($3);
@@ -12465,12 +12465,16 @@ user:
             THD *thd= YYTHD;
             if (!($$=(LEX_USER*) thd->alloc(sizeof(st_lex_user))))
               MYSQL_YYABORT;
-            $$->user = $1;
+            $$->user= $1;
             $$->host.str= (char *) "%";
             $$->host.length= 1;
             $$->password= null_lex_str; 
             $$->plugin= empty_lex_str;
             $$->auth= empty_lex_str;
+            $$->uses_identified_by_clause= false;
+            $$->uses_identified_with_clause= false;
+            $$->uses_identified_by_password_clause= false;
+            $$->uses_authentication_string_clause= false;
 
             if (check_string_char_length(&$$->user, ER(ER_USERNAME),
                                          USERNAME_CHAR_LENGTH,
@@ -12482,10 +12486,15 @@ user:
             THD *thd= YYTHD;
             if (!($$=(LEX_USER*) thd->alloc(sizeof(st_lex_user))))
               MYSQL_YYABORT;
-            $$->user = $1; $$->host=$3;
+            $$->user= $1;
+            $$->host= $3;
             $$->password= null_lex_str; 
             $$->plugin= empty_lex_str;
             $$->auth= empty_lex_str;
+            $$->uses_identified_by_clause= false;
+            $$->uses_identified_with_clause= false;
+            $$->uses_identified_by_password_clause= false;
+            $$->uses_authentication_string_clause= false;
 
             if (check_string_char_length(&$$->user, ER(ER_USERNAME),
                                          USERNAME_CHAR_LENGTH,
@@ -13263,17 +13272,25 @@ text_or_password:
           TEXT_STRING { $$=$1.str;}
         | PASSWORD '(' TEXT_STRING ')'
           {
-            $$= $3.length ? YYTHD->variables.old_passwords ?
-              Item_func_old_password::alloc(YYTHD, $3.str, $3.length) :
-              Item_func_password::alloc(YYTHD, $3.str, $3.length) :
-              $3.str;
+            if ($3.length == 0)
+             $$= $3.str;
+            else
+            switch (YYTHD->variables.old_passwords) {
+              case 1: $$= Item_func_old_password::
+                alloc(YYTHD, $3.str, $3.length);
+                break;
+              case 0:
+              case 2: $$= Item_func_password::
+                create_password_hash_buffer(YYTHD, $3.str, $3.length);
+                break;
+            }
             if ($$ == NULL)
               MYSQL_YYABORT;
           }
         | OLD_PASSWORD '(' TEXT_STRING ')'
           {
-            $$= $3.length ? Item_func_old_password::alloc(YYTHD, $3.str,
-                                                          $3.length) :
+            $$= $3.length ? Item_func_old_password::
+              alloc(YYTHD, $3.str, $3.length) :
               $3.str;
             if ($$ == NULL)
               MYSQL_YYABORT;
@@ -13752,29 +13769,11 @@ grant_user:
             $$=$1; $1->password=$4;
             if (Lex->sql_command == SQLCOM_REVOKE)
               MYSQL_YYABORT;
-            if ($4.length)
-            {
-              if (YYTHD->variables.old_passwords)
-              {
-                char *buff= 
-                  (char *) YYTHD->alloc(SCRAMBLED_PASSWORD_CHAR_LENGTH_323+1);
-                if (buff == NULL)
-                  MYSQL_YYABORT;
-                my_make_scrambled_password_323(buff, $4.str, $4.length);
-                $1->password.str= buff;
-                $1->password.length= SCRAMBLED_PASSWORD_CHAR_LENGTH_323;
-              }
-              else
-              {
-                char *buff= 
-                  (char *) YYTHD->alloc(SCRAMBLED_PASSWORD_CHAR_LENGTH+1);
-                if (buff == NULL)
-                  MYSQL_YYABORT;
-                my_make_scrambled_password(buff, $4.str, $4.length);
-                $1->password.str= buff;
-                $1->password.length= SCRAMBLED_PASSWORD_CHAR_LENGTH;
-              }
-            }
+            /*
+              1. Plugin must be resolved
+              2. Password must be digested
+            */
+            $1->uses_identified_by_clause= true;
           }
         | user IDENTIFIED_SYM BY PASSWORD TEXT_STRING
           { 
@@ -13782,6 +13781,10 @@ grant_user:
               MYSQL_YYABORT;
             $$= $1; 
             $1->password= $5; 
+            /*
+              1. Plugin must be resolved
+            */
+            $1->uses_identified_by_password_clause= true;
           }
         | user IDENTIFIED_SYM WITH ident_or_text
           {
@@ -13789,7 +13792,7 @@ grant_user:
               MYSQL_YYABORT;
             $$= $1;
             $1->plugin= $4;
-            $1->auth= empty_lex_str;
+            $1->uses_identified_with_clause= true;
           }
         | user IDENTIFIED_SYM WITH ident_or_text AS TEXT_STRING_sys
           {
@@ -13798,9 +13801,14 @@ grant_user:
             $$= $1;
             $1->plugin= $4;
             $1->auth= $6;
+            $1->uses_identified_with_clause= true;
+            $1->uses_authentication_string_clause= true;
           }
         | user
-          { $$= $1; $1->password= null_lex_str; }
+          {
+            $$= $1;
+            $1->password= null_lex_str;
+          }
         ;
 
 opt_column_list:

=== modified file 'sql/structs.h'
--- a/sql/structs.h	2010-10-21 09:49:16 +0000
+++ b/sql/structs.h	2011-05-27 14:40:44 +0000
@@ -157,6 +157,10 @@ typedef int *(*update_var)(THD *, struct
 
 typedef struct	st_lex_user {
   LEX_STRING user, host, password, plugin, auth;
+  bool uses_identified_by_clause;
+  bool uses_identified_with_clause;
+  bool uses_authentication_string_clause;
+  bool uses_identified_by_password_clause;
 } LEX_USER;
 
 /*

=== modified file 'sql/sys_vars.cc'
--- a/sql/sys_vars.cc	2011-04-04 10:06:13 +0000
+++ b/sql/sys_vars.cc	2011-05-27 14:40:44 +0000
@@ -10,7 +10,7 @@
    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
+   along with this program; if noldot, write to the Free Software
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA */
 
 /*
@@ -1586,15 +1586,12 @@ static Sys_var_mybool Sys_old_alter_tabl
        "old_alter_table", "Use old, non-optimized alter table",
        SESSION_VAR(old_alter_table), CMD_LINE(OPT_ARG), DEFAULT(FALSE));
 
-static bool check_old_passwords(sys_var *self, THD *thd, set_var *var)
-{
-  return mysql_user_table_is_in_short_password_format;
-}
-static Sys_var_mybool Sys_old_passwords(
+static Sys_var_uint Sys_old_passwords(
        "old_passwords",
-       "Use old password encryption method (needed for 4.0 and older clients)",
-       SESSION_VAR(old_passwords), CMD_LINE(OPT_ARG), DEFAULT(FALSE),
-       NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(check_old_passwords));
+       "Determine which hash algorithm to use when generating passwords using "
+       "the PASSWORD() function",
+       SESSION_VAR(old_passwords), CMD_LINE(REQUIRED_ARG),
+       VALID_RANGE(0, 2), DEFAULT(0), BLOCK_SIZE(1));
 
 static Sys_var_ulong Sys_open_files_limit(
        "open_files_limit",

Attachment: [text/bzr-bundle] bzr/kristofer.pettersson@oracle.com-20110527144044-ritnjipvidfy1j2l.bundle
Thread
bzr commit into mysql-trunk-wl5602 branch (kristofer.pettersson:3311) Kristofer Pettersson27 May