List:Commits« Previous MessageNext Message »
From:Alfranio Correia Date:April 18 2011 6:30am
Subject:bzr commit into mysql-trunk branch (alfranio.correia:3345) WL#4143
View as plain text  
#At file:///home/acorreia/workspace.oracle/repository.mysql/bzrwork/wl-4143/mysql-trunk/ based on revid:alexander.barkov@stripped

 3345 Alfranio Correia	2011-04-18
      WL#4143
     @ mysql-test/suite/funcs_1/r/is_columns_mysql.result
        Updated test case due to change in slave_master_info.
     @ mysql-test/suite/rpl/r/rpl_master_connection.result
        Created a new test case. Plugins are not enabled yet.
     @ mysql-test/suite/rpl/t/rpl_master_connection-master.opt
        Created a new test case. Plugins are not enabled yet.
     @ mysql-test/suite/rpl/t/rpl_master_connection-slave.opt
        Created a new test case. Plugins are not enabled yet.
     @ mysql-test/suite/rpl/t/rpl_master_connection.test
        Created a new test case. Plugins are not enabled yet.
     @ scripts/mysql_system_tables.sql
        Changed password's definition to store encrypted passwords.
     @ sql/CMakeLists.txt
        Added secure_store to cmake lists.
     @ sql/lex.h
        Changed the parser to allow:
        
        . START SLAVE USER=<xxxx> PASSWORD=<yyyy> DEFAULT_AUTH=<zzzz> PLUGIN_DIR=<wwww>
     @ sql/rpl_handler.cc
        User is now private and there is a function to retrieve it.
     @ sql/rpl_info_file.cc
        Defined methods to store and retrieve binary data from replication files.
     @ sql/rpl_info_file.h
        Defined methods to store and retrieve binary data from replication files.
     @ sql/rpl_info_handler.h
        Defined methods to store and retrieve binary data from replication repository.
     @ sql/rpl_info_table.cc
        Defined methods to store and retrieve binary data from replication tables.
     @ sql/rpl_info_table.h
        Defined methods to store and retrieve binary data from replication tables.
     @ sql/rpl_mi.cc
        Added information to process the new START SLAVE syntax and to use the
        secure store to retrieve and store passwords.
        
        In this WL, we provide a sketch of the secure store passowrd and in
        fact the password is stored in the master.info repository. Currently
        , the secure store is used to keep an encrypted password in memory
        and to decrypt it if necessary.
     @ sql/rpl_mi.h
        Added information to process the new START SLAVE syntax. Note that the
        password is not kept in the Master_info anymore.
     @ sql/rpl_rli.cc
        Updated this due to changes in the rpl_info_handler.h.
     @ sql/rpl_slave.cc
        Before connecting the password is decrypted and if authentication
        plugins were provide, they are used.
     @ sql/secure_store.cc
        Sketch of the secure store. See WL#5769.
     @ sql/secure_store.h
        Sketch of the secure store. See WL#5769.
     @ sql/sql_lex.h
        Added a structure to carry on the new information:
        
        . START SLAVE USER=<xxxx> PASSWORD=<yyyy> DEFAULT_AUTH=<zzzz> PLUGIN_DIR=<wwww>
     @ sql/sql_parse.cc
        Set information in in-memory master.info.
     @ sql/sql_yacc.yy
        Changed the parser to allow:
        
        . START SLAVE USER=<xxxx> PASSWORD=<yyyy> DEFAULT_AUTH=<zzzz> PLUGIN_DIR=<wwww>

    added:
      mysql-test/suite/rpl/r/rpl_master_connection.result
      mysql-test/suite/rpl/t/rpl_master_connection-master.opt
      mysql-test/suite/rpl/t/rpl_master_connection-slave.opt
      mysql-test/suite/rpl/t/rpl_master_connection.test
      sql/secure_store.cc
      sql/secure_store.h
    modified:
      mysql-test/suite/funcs_1/r/is_columns_mysql.result
      scripts/mysql_system_tables.sql
      sql/CMakeLists.txt
      sql/lex.h
      sql/rpl_handler.cc
      sql/rpl_info_file.cc
      sql/rpl_info_file.h
      sql/rpl_info_handler.h
      sql/rpl_info_table.cc
      sql/rpl_info_table.h
      sql/rpl_mi.cc
      sql/rpl_mi.h
      sql/rpl_rli.cc
      sql/rpl_slave.cc
      sql/sql_lex.h
      sql/sql_parse.cc
      sql/sql_yacc.yy
=== modified file 'mysql-test/suite/funcs_1/r/is_columns_mysql.result'
--- a/mysql-test/suite/funcs_1/r/is_columns_mysql.result	2011-03-18 14:58:27 +0000
+++ b/mysql-test/suite/funcs_1/r/is_columns_mysql.result	2011-04-18 06:30:30 +0000
@@ -169,7 +169,7 @@ def	mysql	slave_master_info	Ssl_cipher	1
 def	mysql	slave_master_info	Ssl_key	15	NULL	YES	text	65535	65535	NULL	NULL	utf8	utf8_bin	text			select,insert,update,references	
 def	mysql	slave_master_info	Ssl_verify_servert_cert	16	NULL	NO	tinyint	NULL	NULL	3	0	NULL	NULL	tinyint(1)			select,insert,update,references	
 def	mysql	slave_master_info	User_name	6	NULL	YES	text	65535	65535	NULL	NULL	utf8	utf8_bin	text			select,insert,update,references	
-def	mysql	slave_master_info	User_password	7	NULL	YES	text	65535	65535	NULL	NULL	utf8	utf8_bin	text			select,insert,update,references	
+def	mysql	slave_master_info	User_password	7	NULL	NO	blob	65535	65535	NULL	NULL	NULL	NULL	blob			select,insert,update,references	
 def	mysql	slave_master_info	Uuid	20	NULL	YES	text	65535	65535	NULL	NULL	utf8	utf8_bin	text			select,insert,update,references	
 def	mysql	slave_relay_log_info	Master_id	1	NULL	NO	int	NULL	NULL	10	0	NULL	NULL	int(10) unsigned	PRI		select,insert,update,references	
 def	mysql	slave_relay_log_info	Master_log_name	5	NULL	NO	text	65535	65535	NULL	NULL	utf8	utf8_bin	text			select,insert,update,references	
@@ -479,7 +479,7 @@ NULL	mysql	slave_master_info	Number_of_l
 NULL	mysql	slave_master_info	Master_log_pos	bigint	NULL	NULL	NULL	NULL	bigint(20) unsigned
 1.0000	mysql	slave_master_info	Host	text	65535	65535	utf8	utf8_bin	text
 1.0000	mysql	slave_master_info	User_name	text	65535	65535	utf8	utf8_bin	text
-1.0000	mysql	slave_master_info	User_password	text	65535	65535	utf8	utf8_bin	text
+1.0000	mysql	slave_master_info	User_password	blob	65535	65535	NULL	NULL	blob
 NULL	mysql	slave_master_info	Port	int	NULL	NULL	NULL	NULL	int(10) unsigned
 NULL	mysql	slave_master_info	Connect_retry	int	NULL	NULL	NULL	NULL	int(10) unsigned
 NULL	mysql	slave_master_info	Enabled_ssl	tinyint	NULL	NULL	NULL	NULL	tinyint(1)

=== added file 'mysql-test/suite/rpl/r/rpl_master_connection.result'
--- a/mysql-test/suite/rpl/r/rpl_master_connection.result	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/rpl/r/rpl_master_connection.result	2011-04-18 06:30:30 +0000
@@ -0,0 +1,104 @@
+include/master-slave.inc
+[connection master]
+SET SQL_LOG_BIN=0;
+SELECT user, plugin, authentication_string FROM mysql.user WHERE user != 'root';
+user	plugin	authentication_string
+CREATE USER plug_user_p IDENTIFIED WITH test_plugin_server AS 'password';
+CREATE USER plug_user_wp IDENTIFIED WITH test_plugin_server AS '';
+CREATE USER regular_user_p IDENTIFIED BY 'password';
+CREATE USER regular_user_wp IDENTIFIED BY '';
+SELECT user, plugin, authentication_string FROM mysql.user WHERE user != 'root';
+user	plugin	authentication_string
+plug_user_p	test_plugin_server	password
+plug_user_wp	test_plugin_server	
+regular_user_p		NULL
+regular_user_wp		NULL
+GRANT REPLICATION SLAVE ON *.* TO plug_user_p;
+GRANT REPLICATION SLAVE ON *.* TO plug_user_wp;
+GRANT REPLICATION SLAVE ON *.* TO regular_user_p;
+GRANT REPLICATION SLAVE ON *.* TO regular_user_wp;
+SET SQL_LOG_BIN=1;
+include/stop_slave.inc
+SET @@GLOBAL.master_info_repository= "TABLE";
+include/stop_slave.inc
+Warnings:
+Note	1255	Slave already has been stopped
+CHANGE MASTER TO MASTER_USER= 'DOES NOT EXIST', MASTER_PASSWORD = 'DOES NOT EXIST';
+START SLAVE USER= 'regular_user_p' PASSWORD= 'password';
+include/wait_for_slave_to_start.inc
+include/check_slave_is_running.inc
+include/stop_slave.inc
+CHANGE MASTER TO MASTER_USER= 'DOES NOT EXIST', MASTER_PASSWORD = 'DOES NOT EXIST';
+START SLAVE USER= 'regular_user_wp' PASSWORD= '';
+include/wait_for_slave_to_start.inc
+include/check_slave_is_running.inc
+include/stop_slave.inc
+CHANGE MASTER TO MASTER_USER= 'regular_user_p', MASTER_PASSWORD= 'password';
+START SLAVE;
+include/wait_for_slave_io_to_start.inc
+include/check_slave_is_running.inc
+include/rpl_restart_server.inc [server_number=2]
+include/start_slave.inc
+include/check_slave_is_running.inc
+include/stop_slave.inc
+CHANGE MASTER TO MASTER_USER= 'regular_user_wp', MASTER_PASSWORD= '';
+START SLAVE;
+include/wait_for_slave_io_to_start.inc
+include/check_slave_is_running.inc
+include/rpl_restart_server.inc [server_number=2]
+include/start_slave.inc
+include/check_slave_is_running.inc
+include/stop_slave.inc
+CHANGE MASTER TO MASTER_USER= 'plug_user_p', MASTER_PASSWORD= 'password';
+START SLAVE;
+include/wait_for_slave_io_error.inc [errno=1251]
+include/stop_slave.inc
+CHANGE MASTER TO MASTER_USER= 'plug_user_wp', MASTER_PASSWORD= '';
+START SLAVE;
+include/wait_for_slave_io_error.inc [errno=1251]
+include/stop_slave.inc
+SET @@GLOBAL.master_info_repository= "FILE";
+include/stop_slave.inc
+Warnings:
+Note	1255	Slave already has been stopped
+CHANGE MASTER TO MASTER_USER= 'DOES NOT EXIST', MASTER_PASSWORD = 'DOES NOT EXIST';
+START SLAVE USER= 'regular_user_p' PASSWORD= 'password';
+include/wait_for_slave_to_start.inc
+include/check_slave_is_running.inc
+include/stop_slave.inc
+CHANGE MASTER TO MASTER_USER= 'DOES NOT EXIST', MASTER_PASSWORD = 'DOES NOT EXIST';
+START SLAVE USER= 'regular_user_wp' PASSWORD= '';
+include/wait_for_slave_to_start.inc
+include/check_slave_is_running.inc
+include/stop_slave.inc
+CHANGE MASTER TO MASTER_USER= 'regular_user_p', MASTER_PASSWORD= 'password';
+START SLAVE;
+include/wait_for_slave_io_to_start.inc
+include/check_slave_is_running.inc
+include/rpl_restart_server.inc [server_number=2]
+include/start_slave.inc
+include/check_slave_is_running.inc
+include/stop_slave.inc
+CHANGE MASTER TO MASTER_USER= 'regular_user_wp', MASTER_PASSWORD= '';
+START SLAVE;
+include/wait_for_slave_io_to_start.inc
+include/check_slave_is_running.inc
+include/rpl_restart_server.inc [server_number=2]
+include/start_slave.inc
+include/check_slave_is_running.inc
+include/stop_slave.inc
+CHANGE MASTER TO MASTER_USER= 'plug_user_p', MASTER_PASSWORD= 'password';
+START SLAVE;
+include/wait_for_slave_io_error.inc [errno=1251]
+include/stop_slave.inc
+CHANGE MASTER TO MASTER_USER= 'plug_user_wp', MASTER_PASSWORD= '';
+START SLAVE;
+include/wait_for_slave_io_error.inc [errno=1251]
+SET SQL_LOG_BIN=0;
+DROP USER plug_user_p, plug_user_wp, regular_user_p, regular_user_wp;
+SET SQL_LOG_BIN=1;
+include/stop_slave.inc
+CHANGE MASTER TO MASTER_USER= 'root', MASTER_PASSWORD = '';
+SET @@GLOBAL.master_info_repository="FILE";
+include/start_slave.inc
+include/rpl_end.inc

=== added file 'mysql-test/suite/rpl/t/rpl_master_connection-master.opt'
--- a/mysql-test/suite/rpl/t/rpl_master_connection-master.opt	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/rpl/t/rpl_master_connection-master.opt	2011-04-18 06:30:30 +0000
@@ -0,0 +1,2 @@
+$PLUGIN_AUTH_OPT
+$PLUGIN_AUTH_LOAD

=== added file 'mysql-test/suite/rpl/t/rpl_master_connection-slave.opt'
--- a/mysql-test/suite/rpl/t/rpl_master_connection-slave.opt	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/rpl/t/rpl_master_connection-slave.opt	2011-04-18 06:30:30 +0000
@@ -0,0 +1 @@
+--master-retry-count=1

=== added file 'mysql-test/suite/rpl/t/rpl_master_connection.test'
--- a/mysql-test/suite/rpl/t/rpl_master_connection.test	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/rpl/t/rpl_master_connection.test	2011-04-18 06:30:30 +0000
@@ -0,0 +1,116 @@
+--source include/have_plugin_auth.inc
+--source include/not_embedded.inc
+--source include/master-slave.inc
+
+############################
+
+SET SQL_LOG_BIN=0;
+--sorted_result
+SELECT user, plugin, authentication_string FROM mysql.user WHERE user != 'root';
+
+CREATE USER plug_user_p IDENTIFIED WITH test_plugin_server AS 'password';
+CREATE USER plug_user_wp IDENTIFIED WITH test_plugin_server AS '';
+CREATE USER regular_user_p IDENTIFIED BY 'password';
+CREATE USER regular_user_wp IDENTIFIED BY '';
+
+--sorted_result
+SELECT user, plugin, authentication_string FROM mysql.user WHERE user != 'root';
+
+GRANT REPLICATION SLAVE ON *.* TO plug_user_p;
+GRANT REPLICATION SLAVE ON *.* TO plug_user_wp;
+GRANT REPLICATION SLAVE ON *.* TO regular_user_p;
+GRANT REPLICATION SLAVE ON *.* TO regular_user_wp;
+SET SQL_LOG_BIN=1;
+
+###########################
+--connection slave
+--let $slave_io_errno= 1251
+--let $show_slave_io_error= 0
+--let $master_info_repository_old= `SELECT @@GLOBAL.master_info_repository`
+--let $count= 2
+
+while ($count != 0)
+{
+  --source include/stop_slave.inc
+  if ($count == 1)
+  {
+    SET @@GLOBAL.master_info_repository= "FILE"; 
+  }
+
+  if ($count == 2)
+  {
+    SET @@GLOBAL.master_info_repository= "TABLE"; 
+  }
+
+  --source include/stop_slave.inc
+  CHANGE MASTER TO MASTER_USER= 'DOES NOT EXIST', MASTER_PASSWORD = 'DOES NOT EXIST';
+  --eval START SLAVE USER= 'regular_user_p' PASSWORD= 'password'
+  --source include/wait_for_slave_to_start.inc
+  --source include/check_slave_is_running.inc
+
+  --source include/stop_slave.inc
+  CHANGE MASTER TO MASTER_USER= 'DOES NOT EXIST', MASTER_PASSWORD = 'DOES NOT EXIST';
+  --eval START SLAVE USER= 'regular_user_wp' PASSWORD= ''
+  --source include/wait_for_slave_to_start.inc
+  --source include/check_slave_is_running.inc
+
+  #--source include/stop_slave.inc
+  #CHANGE MASTER TO MASTER_USER= 'DOES NOT EXIST', MASTER_PASSWORD = 'DOES NOT EXIST';
+  #--eval START SLAVE USER= 'plug_user_p' PASSWORD= 'password'
+  #--source include/wait_for_slave_to_start.inc
+  #--source include/check_slave_is_running.inc
+
+  #--source include/stop_slave.inc
+  #CHANGE MASTER TO MASTER_USER= 'DOES NOT EXIST', MASTER_PASSWORD = 'DOES NOT EXIST';
+  #--eval START SLAVE USER= 'plug_user_wp' PASSWORD= ''
+  #--source include/wait_for_slave_to_start.inc
+  #--source include/check_slave_is_running.inc
+
+  --source include/stop_slave.inc
+  CHANGE MASTER TO MASTER_USER= 'regular_user_p', MASTER_PASSWORD= 'password';
+  START SLAVE;
+  --source include/wait_for_slave_io_to_start.inc
+  --source include/check_slave_is_running.inc
+  --let $rpl_server_number= 2
+  --source include/rpl_restart_server.inc
+  --connection slave
+  --source include/start_slave.inc
+  --source include/check_slave_is_running.inc
+
+  --source include/stop_slave.inc
+  CHANGE MASTER TO MASTER_USER= 'regular_user_wp', MASTER_PASSWORD= '';
+  START SLAVE;
+  --source include/wait_for_slave_io_to_start.inc
+  --source include/check_slave_is_running.inc
+  --let $rpl_server_number= 2
+  --source include/rpl_restart_server.inc
+  --connection slave
+  --source include/start_slave.inc
+  --source include/check_slave_is_running.inc
+
+  --source include/stop_slave.inc
+  CHANGE MASTER TO MASTER_USER= 'plug_user_p', MASTER_PASSWORD= 'password';
+  START SLAVE;
+  --source include/wait_for_slave_io_error.inc
+
+  --source include/stop_slave.inc
+  CHANGE MASTER TO MASTER_USER= 'plug_user_wp', MASTER_PASSWORD= '';
+  START SLAVE;
+  --source include/wait_for_slave_io_error.inc
+
+  --dec $count
+}
+
+###########################
+
+--connection master
+SET SQL_LOG_BIN=0;
+DROP USER plug_user_p, plug_user_wp, regular_user_p, regular_user_wp;
+SET SQL_LOG_BIN=1;
+
+--connection slave
+--source include/stop_slave.inc
+CHANGE MASTER TO MASTER_USER= 'root', MASTER_PASSWORD = '';
+--eval SET @@GLOBAL.master_info_repository="$master_info_repository_old"
+--source include/start_slave.inc
+--source include/rpl_end.inc

=== 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-04-18 06:30:30 +0000
@@ -102,7 +102,7 @@ CREATE TABLE IF NOT EXISTS ndb_binlog_in
 
 CREATE TABLE IF NOT EXISTS slave_relay_log_info (Master_id INTEGER UNSIGNED NOT NULL, Number_of_lines INTEGER UNSIGNED NOT NULL, Relay_log_name TEXT CHARACTER SET utf8 COLLATE utf8_bin NOT NULL, Relay_log_pos BIGINT UNSIGNED NOT NULL, Master_log_name TEXT CHARACTER SET utf8 COLLATE utf8_bin NOT NULL, Master_log_pos BIGINT UNSIGNED NOT NULL, Sql_delay INTEGER NOT NULL, PRIMARY KEY(Master_id)) ENGINE=MYISAM DEFAULT CHARSET=utf8 COMMENT 'Relay Log Information';
 
-CREATE TABLE IF NOT EXISTS slave_master_info (Master_id INTEGER UNSIGNED NOT NULL, Number_of_lines INTEGER UNSIGNED NOT NULL, Master_log_name TEXT CHARACTER SET utf8 COLLATE utf8_bin NOT NULL, Master_log_pos BIGINT UNSIGNED NOT NULL, Host TEXT CHARACTER SET utf8 COLLATE utf8_bin, User_name TEXT CHARACTER SET utf8 COLLATE utf8_bin, User_password TEXT CHARACTER SET utf8 COLLATE utf8_bin, Port INTEGER UNSIGNED NOT NULL, Connect_retry INTEGER UNSIGNED NOT NULL, Enabled_ssl BOOLEAN NOT NULL, Ssl_ca TEXT CHARACTER SET utf8 COLLATE utf8_bin, Ssl_capath TEXT CHARACTER SET utf8 COLLATE utf8_bin, Ssl_cert TEXT CHARACTER SET utf8 COLLATE utf8_bin, Ssl_cipher TEXT CHARACTER SET utf8 COLLATE utf8_bin, Ssl_key TEXT CHARACTER SET utf8 COLLATE utf8_bin, Ssl_verify_servert_cert BOOLEAN NOT NULL, Heartbeat FLOAT NOT NULL, Bind TEXT CHARACTER SET utf8 COLLATE utf8_bin, Ignored_server_ids TEXT CHARACTER SET utf8 COLLATE utf8_bin, Uuid TEXT CHARACTER SET utf8 COLLATE utf8_bin, Retry_count BIGIN!
 T UNSIGNED NOT NULL, PRIMARY KEY(Master_id)) ENGINE=MYISAM DEFAULT CHARSET=utf8 COMMENT 'Master Information';
+CREATE TABLE IF NOT EXISTS slave_master_info (Master_id INTEGER UNSIGNED NOT NULL, Number_of_lines INTEGER UNSIGNED NOT NULL, Master_log_name TEXT CHARACTER SET utf8 COLLATE utf8_bin NOT NULL, Master_log_pos BIGINT UNSIGNED NOT NULL, Host TEXT CHARACTER SET utf8 COLLATE utf8_bin, User_name TEXT CHARACTER SET utf8 COLLATE utf8_bin, User_password BLOB NOT NULL, Port INTEGER UNSIGNED NOT NULL, Connect_retry INTEGER UNSIGNED NOT NULL, Enabled_ssl BOOLEAN NOT NULL, Ssl_ca TEXT CHARACTER SET utf8 COLLATE utf8_bin, Ssl_capath TEXT CHARACTER SET utf8 COLLATE utf8_bin, Ssl_cert TEXT CHARACTER SET utf8 COLLATE utf8_bin, Ssl_cipher TEXT CHARACTER SET utf8 COLLATE utf8_bin, Ssl_key TEXT CHARACTER SET utf8 COLLATE utf8_bin, Ssl_verify_servert_cert BOOLEAN NOT NULL, Heartbeat FLOAT NOT NULL, Bind TEXT CHARACTER SET utf8 COLLATE utf8_bin, Ignored_server_ids TEXT CHARACTER SET utf8 COLLATE utf8_bin, Uuid TEXT CHARACTER SET utf8 COLLATE utf8_bin, Retry_count BIGINT UNSIGNED NOT NULL, PRIMAR!
 Y KEY(Master_id)) ENGINE=MYISAM DEFAULT CHARSET=utf8 COMMENT 'Master Information';
 
 --
 -- PERFORMANCE SCHEMA INSTALLATION

=== modified file 'sql/CMakeLists.txt'
--- a/sql/CMakeLists.txt	2011-02-02 08:30:13 +0000
+++ b/sql/CMakeLists.txt	2011-04-18 06:30:30 +0000
@@ -149,6 +149,7 @@ SET(SQL_SHARED_SOURCES
   tztime.cc
   uniques.cc
   unireg.cc
+  secure_store.cc
 )
 
 SET(SQL_EXPORTED_SOURCES ${SQL_SHARED_SOURCES} PARENT_SCOPE)

=== modified file 'sql/lex.h'
--- a/sql/lex.h	2010-11-25 11:20:16 +0000
+++ b/sql/lex.h	2011-04-18 06:30:30 +0000
@@ -164,6 +164,7 @@ static SYMBOL symbols[] = {
   { "DECIMAL",		SYM(DECIMAL_SYM)},
   { "DECLARE",          SYM(DECLARE_SYM)},
   { "DEFAULT",		SYM(DEFAULT)},
+  { "DEFAULT_AUTH",	SYM(DEFAULT_AUTH_SYM)},
   { "DEFINER",          SYM(DEFINER_SYM)},
   { "DELAYED",		SYM(DELAYED_SYM)},
   { "DELAY_KEY_WRITE",	SYM(DELAY_KEY_WRITE_SYM)},
@@ -412,6 +413,7 @@ static SYMBOL symbols[] = {
   { "PHASE",            SYM(PHASE_SYM)},
   { "PLUGIN",           SYM(PLUGIN_SYM)},
   { "PLUGINS",          SYM(PLUGINS_SYM)},
+  { "PLUGIN_DIR",       SYM(PLUGIN_DIR_SYM)},
   { "POINT",		SYM(POINT_SYM)},
   { "POLYGON",		SYM(POLYGON)},
   { "PORT",		SYM(PORT_SYM)},

=== modified file 'sql/rpl_handler.cc'
--- a/sql/rpl_handler.cc	2010-11-05 22:14:29 +0000
+++ b/sql/rpl_handler.cc	2011-04-18 06:30:30 +0000
@@ -429,7 +429,7 @@ void Binlog_relay_IO_delegate::init_para
                                           Master_info *mi)
 {
   param->mysql= mi->mysql;
-  param->user= mi->user;
+  param->user= const_cast<char *>(mi->get_user());
   param->host= mi->host;
   param->port= mi->port;
   param->master_log_name= const_cast<char *>(mi->get_master_log_name());

=== modified file 'sql/rpl_info_file.cc'
--- a/sql/rpl_info_file.cc	2011-04-05 16:46:24 +0000
+++ b/sql/rpl_info_file.cc	2011-04-18 06:30:30 +0000
@@ -304,6 +304,47 @@ bool Rpl_info_file::do_get_info(const in
   return error;
 }
 
+bool Rpl_info_file::do_set_binary_info(const int pos, const char *value,
+                                       const size_t size)
+{
+  uchar buffer[STORE_SIZE_BINARY];
+
+  /*
+    There is only 32 bits to store the size of the binary information.
+    So if size is greater than 2^32 = 4.294.967.295, an error is then
+    returned.
+  */
+  if  (size > 4294967295)
+    return TRUE;
+
+  int4store(buffer, size);
+  if (my_b_write(&info_file, buffer, STORE_SIZE_BINARY) ||
+      my_b_write(&info_file, value, size))
+    return TRUE;
+
+  return FALSE;
+}
+
+bool Rpl_info_file::do_get_binary_info(const int pos, char *value, size_t *size)
+{
+  uint32 length= 0;
+  uchar buffer[STORE_SIZE_BINARY];
+
+  if (my_b_read(&info_file, buffer, STORE_SIZE_BINARY))
+    return TRUE;
+
+  *size= length= uint4korr(buffer);
+  /*
+    There is only 32 bits to store the size of the binary information.
+    So if size is greater than 2^32 = 4.294.967.295, an error is then
+    returned.
+  */
+  if  (*size > 4294967295 || my_b_read(&info_file, (uchar *) value, *size))
+    return TRUE;
+
+  return FALSE;
+}
+
 char* Rpl_info_file::do_get_description_info()
 {
   return info_fname;

=== modified file 'sql/rpl_info_file.h'
--- a/sql/rpl_info_file.h	2011-03-23 23:28:49 +0000
+++ b/sql/rpl_info_file.h	2011-04-18 06:30:30 +0000
@@ -71,6 +71,11 @@ private:
   bool do_is_transactional();
   bool do_update_is_transactional();
 
+  bool do_set_binary_info(const int pos, const char *value,
+                          const size_t size);
+  bool do_get_binary_info(const int pos, char *value,
+                          size_t *size);
+
   Rpl_info_file(int const nparam, const char* param_info_fname);
   Rpl_info_file(const Rpl_info_file& info);
 

=== modified file 'sql/rpl_info_handler.h'
--- a/sql/rpl_info_handler.h	2011-03-23 23:28:49 +0000
+++ b/sql/rpl_info_handler.h	2011-04-18 06:30:30 +0000
@@ -24,6 +24,12 @@ class Rpl_info_handler
 {
 public:
   /**
+    Defines the space reserved to store the size of the binary
+    information.
+  */
+  static const int STORE_SIZE_BINARY= 4;
+
+  /**
     After creating an object and assembling components, this method is
     used to initialize internal structures. Everything that does not
     depend on other components (e.g. mutexes) should be placed in the
@@ -142,6 +148,23 @@ public:
   }
 
   /**
+    Sets the value of a binary field to @c value.
+    Any call must be done in the right order which
+    is defined by the caller that wants to persist
+    the information.
+  */
+  bool set_binary_info(char* const value, const size_t size)
+  {
+    if (cursor >= ninfo || prv_error)
+      return TRUE;
+
+    if (!(prv_error= do_set_binary_info(cursor, value, size)))
+      cursor++;
+
+    return(prv_error);
+  }
+
+  /**
     Returns the value of a field.
     Any call must be done in the right order which
     is defined by the caller that wants to return
@@ -182,8 +205,8 @@ public:
     @retval FALSE No error
     @retval TRUE Failure
   */
-  bool get_info(char *value, const size_t size,
-                const char *default_value)
+  bool get_info(char* value, const size_t size,
+                char* const default_value)
   {
     if (cursor >= ninfo || prv_error)
       return TRUE;
@@ -220,6 +243,32 @@ public:
   }
 
   /**
+    Returns the value of a binary field.
+    Any call must be done in the right order which
+    is defined by the caller that wants to return
+    the information.
+
+    @param[in] value Value to be returned.
+    @param[in] size  Max size of the string to be
+                     returned.
+    @param[in] default_value Returns a default value
+                             if the field is empty.
+
+    @retval FALSE No error
+    @retval TRUE Failure
+  */
+  bool get_binary_info(char* value, size_t *size)
+  {
+    if (cursor >= ninfo || prv_error)
+      return TRUE;
+
+    if (!(prv_error= do_get_binary_info(cursor, value, size)))
+      cursor++;
+
+    return(prv_error);
+  }
+
+  /**
     Returns the number of fields handled by this handler.
 
     @return Number of fields handled by the handler.
@@ -329,12 +378,17 @@ private:
                            const float default_value)= 0;
   virtual bool do_get_info(const int pos, Server_ids *value,
                            const Server_ids *default_value)= 0;
+
+  virtual bool do_set_binary_info(const int pos, const char *value,
+                                  const size_t size)= 0;
+  virtual bool do_get_binary_info(const int pos, char *value,
+                                  size_t *size)= 0;
+
   virtual char* do_get_description_info()= 0;
   virtual bool do_is_transactional()= 0;
   virtual bool do_update_is_transactional()= 0;
 
   Rpl_info_handler(const Rpl_info_handler& handler);
-
   Rpl_info_handler& operator=(const Rpl_info_handler& handler);
 };
 #endif /* RPL_INFO_HANDLER_H */

=== modified file 'sql/rpl_info_table.cc'
--- a/sql/rpl_info_table.cc	2011-04-04 10:06:13 +0000
+++ b/sql/rpl_info_table.cc	2011-04-18 06:30:30 +0000
@@ -289,7 +289,7 @@ int Rpl_info_table::do_check_info()
   }
 
   /*
-    Points the cursor at the row to be deleted where the the master_id
+    Points the cursor at the row to be used where the the master_id
     equals to the server_id. If the row is not found, an error is
     reported.
   */
@@ -441,6 +441,51 @@ bool Rpl_info_table::do_get_info(const i
   return FALSE;
 }
 
+bool Rpl_info_table::do_set_binary_info(const int pos, const char *value,
+                                        const size_t size)
+{
+  char *buffer= NULL;
+  /*
+    There is only 32 bits to store the size of the binary information.
+    So if size is greater than 2^32 = 4.294.967.295, an error is then
+    returned.
+  */
+  if  (size > 4294967295)
+    return TRUE;
+
+  if (field_values->value[pos].alloc(size + STORE_SIZE_BINARY))
+      return TRUE;
+  buffer= field_values->value[pos].c_ptr_safe();
+
+  int4store(buffer, size);
+  memcpy(buffer + STORE_SIZE_BINARY, value, size);
+  field_values->value[pos].length(size + STORE_SIZE_BINARY);
+
+  return FALSE;
+}
+
+bool Rpl_info_table::do_get_binary_info(const int pos, char *value, size_t *size)
+{
+  uint32 length= 0;
+  char* buffer= field_values->value[pos].c_ptr_safe();
+  *size= 0;
+
+  if (field_values->value[pos].length() < (uint32) STORE_SIZE_BINARY)
+    return FALSE;
+
+  *size= length= uint4korr(buffer);
+  /*
+    There is only 32 bits to store the size of the binary information.
+    So if size is greater than 2^32 = 4.294.967.295, an error is then
+    returned.
+  */
+  if  (*size > 4294967295)
+    return TRUE;
+  memcpy(value, buffer + STORE_SIZE_BINARY, *size);
+  
+  return FALSE;
+}
+
 char* Rpl_info_table::do_get_description_info()
 {
   return description;

=== modified file 'sql/rpl_info_table.h'
--- a/sql/rpl_info_table.h	2011-03-23 23:28:49 +0000
+++ b/sql/rpl_info_table.h	2011-04-18 06:30:30 +0000
@@ -87,6 +87,10 @@ private:
                    const float default_value);
   bool do_get_info(const int pos, Server_ids *value,
                    const Server_ids *default_value);
+  bool do_set_binary_info(const int pos, const char *value,
+                          const size_t size);
+  bool do_get_binary_info(const int pos, char *value,
+                          size_t *size);
   char* do_get_description_info();
   bool do_is_transactional();
   bool do_update_is_transactional();

=== modified file 'sql/rpl_mi.cc'
--- a/sql/rpl_mi.cc	2011-04-04 09:42:22 +0000
+++ b/sql/rpl_mi.cc	2011-04-18 06:30:30 +0000
@@ -21,6 +21,19 @@
 #include "rpl_slave.h"                          // SLAVE_MAX_HEARTBEAT_PERIOD
 
 #ifdef HAVE_REPLICATION
+/**
+  Key used to encrypt passwords stored in the master.info. Note that
+  passwords provided through the START SLAVE are encrypted with a
+  random key.
+  If you want to change this behavior, please, check set_password()
+  for further information.
+*/
+char PASSWORD_ENCRYPTION_KEY[]= "005F8976EA0192828877087476617874";
+size_t PASSWORD_ENCRYPTION_KEY_SIZE= strlen(PASSWORD_ENCRYPTION_KEY);
+char PASSWORD_SEARCH_KEY[] = "PASSWORD_SEARCH_KEY";
+size_t PASSWORD_SEARCH_KEY_SIZE= strlen(PASSWORD_SEARCH_KEY);
+char START_PASSWORD_SEARCH_KEY[]= "START_SEARCH_PASSWORD_KEY";
+size_t START_PASSWORD_SEARCH_KEY_SIZE= strlen(START_PASSWORD_SEARCH_KEY);
 
 enum {
   LINES_IN_MASTER_INFO_WITH_SSL= 14,
@@ -92,6 +105,8 @@ Master_info::Master_info(
              param_key_info_stop_cond
 #endif
             ),
+   start_user_configured(0), start_plugin_configured(0),
+   store_password(0), store_start_password(0),
    ssl(0), ssl_verify_server_cert(0),
    port(MYSQL_PORT), connect_retry(DEFAULT_CONNECT_RETRY),
    clock_diff_with_master(0), heartbeat_period(0),
@@ -99,10 +114,13 @@ Master_info::Master_info(
    checksum_alg_before_fd(BINLOG_CHECKSUM_ALG_UNDEF),
    retry_count(master_retry_count)
 {
-  host[0] = 0; user[0] = 0; password[0] = 0; bind_addr[0] = 0;
+  host[0] = 0; user[0] = 0; bind_addr[0] = 0;
   ssl_ca[0]= 0; ssl_capath[0]= 0; ssl_cert[0]= 0;
   ssl_cipher[0]= 0; ssl_key[0]= 0;
   master_uuid[0]= 0;
+  start_plugin_auth[0]= 0; start_plugin_dir[0]= 0;
+  start_user[0]= 0;
+  strcpy(start_command, "START SLAVE");
   ignore_server_ids= new Server_ids();
 }
 
@@ -183,6 +201,14 @@ void Master_info::end_info()
 
   inited = 0;
 
+  /*
+    The structure that encrypts and decrypts the password stored in
+    the master.info is initialized and deinitialized, respectively
+    by secure_store_open and secure_store_close.
+  */
+  secure_store_close(store_password);
+  store_password= NULL;
+
   DBUG_VOID_RETURN;
 }
 
@@ -251,6 +277,21 @@ int Master_info::init_info()
     DBUG_RETURN(0);
 
   /*
+    The structure that encrypts and decrypts the password stored in the
+    master.info is initialized and deinitialized, respectively by
+    secure_store_open and secure_store_close.
+  */
+  if (!(store_password= secure_store_open(PASSWORD_SEARCH_KEY, MYF(0))))
+    DBUG_RETURN(TRUE);
+  if (secure_store_init(store_password, PASSWORD_ENCRYPTION_KEY,
+                                   PASSWORD_ENCRYPTION_KEY_SIZE))
+  {
+    secure_store_close(store_password);
+    store_password= NULL;
+    DBUG_RETURN(TRUE);
+  }
+
+  /*
     The init_info() is used to either create or read information
     from the repository, in order to initialize the Master_info.
   */
@@ -290,6 +331,8 @@ bool Master_info::read_info(Rpl_info_han
   ulong temp_master_log_pos= 0;
   int temp_ssl= 0;
   int temp_ssl_verify_server_cert= 0;
+  char password[MAX_PASSWORD_LENGTH + ENCRYPTION_BLOCK_SIZE + 1];
+  size_t password_size= 0;
 
   DBUG_ENTER("Master_info::read_info");
 
@@ -313,7 +356,7 @@ bool Master_info::read_info(Rpl_info_han
   */
 
   if (from->prepare_info_for_read() || 
-      from->get_info(master_log_name, sizeof(master_log_name), ""))
+      from->get_info(master_log_name, sizeof(master_log_name), (char *) ""))
     DBUG_RETURN(TRUE);
 
   lines= strtoul(master_log_name, &first_non_digit, 10);
@@ -322,20 +365,18 @@ bool Master_info::read_info(Rpl_info_han
       *first_non_digit=='\0' && lines >= LINES_IN_MASTER_INFO_WITH_SSL)
   {
     /* Seems to be new format => read master log name */
-    if (from->get_info(master_log_name,  sizeof(master_log_name), ""))
+    if (from->get_info(master_log_name,  sizeof(master_log_name), (char *) ""))
       DBUG_RETURN(TRUE);
   }
   else 
     lines= 7;
 
-  if (from->get_info(&temp_master_log_pos,
-                        (ulong) BIN_LOG_HEADER_SIZE) ||
-      from->get_info(host, sizeof(host), 0) ||
-      from->get_info(user, sizeof(user), "test") ||
-      from->get_info(password, sizeof(password), 0) ||
+  if (from->get_info(&temp_master_log_pos, (ulong) BIN_LOG_HEADER_SIZE) ||
+      from->get_info(host, sizeof(host), (char *) 0) ||
+      from->get_info(user, sizeof(user), (char *) "test") ||
+      from->get_binary_info(password, (size_t *) &password_size) ||
       from->get_info((int *) &port, (int) MYSQL_PORT) ||
-      from->get_info((int *) &connect_retry,
-                        (int) DEFAULT_CONNECT_RETRY))
+      from->get_info((int *) &connect_retry, (int) DEFAULT_CONNECT_RETRY))
       DBUG_RETURN(TRUE);
 
   /*
@@ -346,12 +387,12 @@ bool Master_info::read_info(Rpl_info_han
   */
   if (lines >= LINES_IN_MASTER_INFO_WITH_SSL)
   {
-    if (from->get_info(&temp_ssl, 0) ||
-        from->get_info(ssl_ca, sizeof(ssl_ca), 0) ||
-        from->get_info(ssl_capath, sizeof(ssl_capath), 0) ||
-        from->get_info(ssl_cert, sizeof(ssl_cert), 0) ||
-        from->get_info(ssl_cipher, sizeof(ssl_cipher), 0) ||
-        from->get_info(ssl_key, sizeof(ssl_key), 0))
+    if (from->get_info(&temp_ssl, (int) 0) ||
+        from->get_info(ssl_ca, sizeof(ssl_ca), (char *) 0) ||
+        from->get_info(ssl_capath, sizeof(ssl_capath), (char *) 0) ||
+        from->get_info(ssl_cert, sizeof(ssl_cert), (char *) 0) ||
+        from->get_info(ssl_cipher, sizeof(ssl_cipher), (char *) 0) ||
+        from->get_info(ssl_key, sizeof(ssl_key), (char *) 0))
       DBUG_RETURN(TRUE);
   }
 
@@ -361,7 +402,7 @@ bool Master_info::read_info(Rpl_info_han
   */
   if (lines >= LINE_FOR_MASTER_SSL_VERIFY_SERVER_CERT)
   { 
-    if (from->get_info(&temp_ssl_verify_server_cert, 0))
+    if (from->get_info(&temp_ssl_verify_server_cert, (int) 0))
       DBUG_RETURN(TRUE);
   }
 
@@ -380,7 +421,7 @@ bool Master_info::read_info(Rpl_info_han
   */
   if (lines >= LINE_FOR_MASTER_BIND)
   {
-    if (from->get_info(bind_addr, sizeof(bind_addr), ""))
+    if (from->get_info(bind_addr, sizeof(bind_addr), (char *) 0))
       DBUG_RETURN(TRUE);
   }
 
@@ -397,7 +438,7 @@ bool Master_info::read_info(Rpl_info_han
   /* Starting from 5.5 the master_uuid may be in the repository. */
   if (lines >= LINE_FOR_MASTER_UUID)
   {
-    if (from->get_info(master_uuid, sizeof(master_uuid), 0))
+    if (from->get_info(master_uuid, sizeof(master_uuid), (char *) 0))
       DBUG_RETURN(TRUE);
   }
 
@@ -409,15 +450,45 @@ bool Master_info::read_info(Rpl_info_han
       DBUG_RETURN(TRUE);
   }
 
+  /*
+    The structure that encrypts and decrypts the password stored in the
+    master.info is initialized and deinitialized, respectively by
+    secure_store_open and secure_store_close.
+  */
+  if (!inited && !(store_password= secure_store_open(PASSWORD_SEARCH_KEY, MYF(0))))
+    DBUG_RETURN(TRUE);
+  if (!inited && secure_store_init(store_password, PASSWORD_ENCRYPTION_KEY,
+                                   PASSWORD_ENCRYPTION_KEY_SIZE))
+  {
+    secure_store_close(store_password);
+    store_password= NULL;
+    DBUG_RETURN(TRUE);
+  }
+
+  /* 
+    Emtpty passwords are not stored in the secure store as there is
+    nothing to be protected.
+  */
+  if (password_size &&
+      !secure_store_check_item(store_password, PASSWORD_SEARCH_KEY,
+                               PASSWORD_SEARCH_KEY_SIZE))
+  {
+    char *key_ptr= PASSWORD_SEARCH_KEY;
+    if (secure_store_put_item(store_password, (void **) &key_ptr,
+                              PASSWORD_SEARCH_KEY_SIZE, password,
+                              password_size, FALSE))
+      DBUG_RETURN(TRUE);
+  }
+
   ssl= (my_bool) test(temp_ssl);
   ssl_verify_server_cert= (my_bool) test(temp_ssl_verify_server_cert);
   master_log_pos= (my_off_t) temp_master_log_pos;
-#ifndef HAVE_OPENSSL
+#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY) && !defined(HAVE_YASSL)
   if (ssl)
     sql_print_warning("SSL information in the master info file "
                       "are ignored because this MySQL slave was "
                       "compiled without SSL support.");
-#endif /* HAVE_OPENSSL */
+#endif /* HAVE_OPENSSL && !EMBEDDED_LIBRARY && !HAVE_YASSL */
 
   DBUG_RETURN(FALSE);
 }
@@ -426,6 +497,24 @@ bool Master_info::write_info(Rpl_info_ha
 {
   DBUG_ENTER("Master_info::write_info");
 
+  char error= TRUE;
+  char *password= NULL;
+  size_t password_size= 0;
+  char empty_password[]= "";
+
+  /* 
+    Emtpty passwords are not stored in the secure store as there is
+    nothing to be protected.
+  */
+  if (!(password= (char *) secure_store_get_item(store_password,
+                                                 (void *) PASSWORD_SEARCH_KEY,
+                                                 PASSWORD_SEARCH_KEY_SIZE,
+                                                 &password_size, FALSE)))
+  {
+    password= empty_password;
+    password_size= 0;
+  }
+
   /*
      In certain cases this code may create master.info files that seems
      corrupted, because of extra lines filled with garbage in the end
@@ -433,14 +522,13 @@ bool Master_info::write_info(Rpl_info_ha
      contents of file). But because of number of lines in the first line
      of file we don't care about this garbage.
   */
-
   if (to->prepare_info_for_write() ||
       to->set_info((int) LINES_IN_MASTER_INFO) ||
       to->set_info(master_log_name) ||
-      to->set_info((ulong)master_log_pos) ||
+      to->set_info((ulong) master_log_pos) ||
       to->set_info(host) ||
       to->set_info(user) ||
-      to->set_info(password) ||
+      to->set_binary_info(password, password_size) ||
       to->set_info((int) port) ||
       to->set_info((int) connect_retry) ||
       to->set_info((int) ssl) ||
@@ -449,17 +537,246 @@ bool Master_info::write_info(Rpl_info_ha
       to->set_info(ssl_cert) ||
       to->set_info(ssl_cipher) ||
       to->set_info(ssl_key) ||
-      to->set_info(ssl_verify_server_cert) ||
+      to->set_info((int) ssl_verify_server_cert) ||
       to->set_info(heartbeat_period) ||
       to->set_info(bind_addr) ||
       to->set_info(ignore_server_ids) ||
       to->set_info(master_uuid) ||
       to->set_info(retry_count))
-    DBUG_RETURN(TRUE);
+    goto err;
 
   if (to->flush_info(force))
-    DBUG_RETURN(TRUE);
+    goto err;
 
-  DBUG_RETURN(FALSE);
+  error= FALSE;
+
+err:
+  DBUG_ASSERT(password != NULL);
+  /*
+    Releases memory allocated to return the encrypted password,
+    if there is any.
+  */
+  if (password != empty_password) my_free(password);
+  DBUG_RETURN(error);
+}
+
+bool Master_info::set_password(const char* password_arg, int password_arg_size)
+{
+  DBUG_ENTER("Master_info::set_password");
+  bool error= TRUE;
+
+#ifndef DBUG_OFF
+  THD* thd= current_thd;
+  DBUG_PRINT("info", ("Command' %s'. Encrypting password '%s' whose size is %d\n",
+             thd->query(), password_arg, password_arg_size));
+#endif
+
+  if (password_arg && start_user_configured)
+  {
+    if (password_arg_size != 0)
+    {
+      if (!(store_start_password= secure_store_open(START_PASSWORD_SEARCH_KEY,
+                                                    MYF(0))))
+        DBUG_RETURN(TRUE);
+      /*
+        In this case, the key is random to avoid security issues and as
+        such the second and third parameter are null.
+      */
+      if (secure_store_init(store_start_password, NULL, 0))
+      {
+        secure_store_close(store_start_password);
+        store_start_password= 0;
+        DBUG_RETURN(TRUE);
+      }
+
+      /*
+        Note that one is added to the size of the password to incorporate
+        the null-terminated character.
+      */
+      char *key_ptr= START_PASSWORD_SEARCH_KEY;
+      error= secure_store_put_item(store_start_password,
+                                   (void **) &key_ptr,
+                                   START_PASSWORD_SEARCH_KEY_SIZE,
+                                   (void *) password_arg,
+                                   password_arg_size + 1, TRUE);
+#ifndef DBUG_OFF
+      if (!error) debug_password(store_start_password,
+                                 START_PASSWORD_SEARCH_KEY,
+                                 START_PASSWORD_SEARCH_KEY_SIZE);
+#endif
+    }
+    else if (password_arg_size == 0 && !error)
+    {
+      error= FALSE;
+      DBUG_PRINT("info", ("SET ENCRYPTED PASSWORD - ENCRYPTED VERSION "
+                 "'' SIZE 0, DECRYPTED VERSION '' SIZE 0\n"));
+    }
+  }
+  else if (password_arg)
+  {
+    /*
+      We assume that the key to encrypt passwords stored in the master.info
+      is not changed after starting the server. In fact, such key is hard
+      coded now.
+      In the future, if we decide to change this behavior and allow users
+      to define this key, we need to call secure_store_open, similar as
+      above.
+    */
+    if (password_arg_size != 0)
+    {
+      /*
+        Note that one is added to the size of the password to incorporate
+        the null-terminated character.
+      */
+      char *key_ptr= PASSWORD_SEARCH_KEY;
+      error= secure_store_put_item(store_password,
+                                   (void **) &key_ptr,
+                                   PASSWORD_SEARCH_KEY_SIZE,
+                                   (void *) password_arg,
+                                   password_arg_size + 1, TRUE);
+#ifndef DBUG_OFF
+      if (!error) debug_password(store_password, PASSWORD_SEARCH_KEY,
+                                 PASSWORD_SEARCH_KEY_SIZE);
+#endif
+    }
+    else if (password_arg_size == 0)
+    {
+      error= FALSE;
+      char* plain_password= NULL;
+      size_t plain_password_size= 0;
+      plain_password= (char *) secure_store_delete_item(store_password,
+                                                        PASSWORD_SEARCH_KEY,
+                                                        PASSWORD_SEARCH_KEY_SIZE,
+                                                        &plain_password_size,
+                                                        TRUE);
+#ifndef DBUG_OFF
+      debug_password(plain_password, plain_password_size);
+#endif
+      my_free(plain_password);
+    }
+  }
+  DBUG_RETURN(error);
 }
+
+void Master_info::get_password(char *password_arg, int *password_arg_size)
+{
+  char *plain_password= NULL;
+  size_t plain_password_size= 0;
+
+  DBUG_ENTER("Master_info::get_password");
+
+  if (password_arg && start_user_configured)
+  {
+    plain_password=
+      (char *) secure_store_get_item(store_start_password,
+                                     (void *) START_PASSWORD_SEARCH_KEY,
+                                     START_PASSWORD_SEARCH_KEY_SIZE,
+                                     &plain_password_size, TRUE);
+    if (plain_password)
+    {
+      strmake(password_arg, plain_password, plain_password_size);
+      *password_arg_size= plain_password_size;
+    }
+    else
+    {
+      *password_arg= 0;
+      *password_arg_size= 0;
+    }
+#ifndef DBUG_OFF
+    debug_password(store_start_password,
+                   START_PASSWORD_SEARCH_KEY,
+                   START_PASSWORD_SEARCH_KEY_SIZE);
+#endif
+  }
+  else if (password_arg)
+  {
+    plain_password= (char *) secure_store_get_item(store_password,
+                                                   (void *) PASSWORD_SEARCH_KEY,
+                                                   PASSWORD_SEARCH_KEY_SIZE,
+                                                   &plain_password_size, TRUE);
+    if (plain_password)
+    {
+      strmake(password_arg, plain_password, plain_password_size);
+      *password_arg_size= plain_password_size;
+    }
+    else
+    {
+      *password_arg= 0;
+      *password_arg_size= 0;
+    }
+#ifndef DBUG_OFF
+    debug_password(store_start_password,
+                   START_PASSWORD_SEARCH_KEY,
+                   START_PASSWORD_SEARCH_KEY_SIZE);
+#endif
+  }
+  my_free(plain_password);
+  DBUG_VOID_RETURN;
+}
+
+void Master_info::clean_start_information()
+{
+  DBUG_ENTER("Master_info::clean_start_information");
+  char* plain_start_password= NULL;
+  size_t plain_start_password_size= 0;
+  start_plugin_configured= FALSE;
+  start_plugin_auth[0]= 0;
+  start_plugin_dir[0]= 0;
+  start_user_configured= FALSE;
+  start_user[0]= 0;
+  /*
+    This makes sure that any information on the password provided through
+    the START SLAVE is erased. However, if we want to reset the key used
+    to encrypt passwords, we need to close the secure store too.
+  */
+  plain_start_password= (char *)
+    secure_store_delete_item(store_start_password,
+                             START_PASSWORD_SEARCH_KEY,
+                             START_PASSWORD_SEARCH_KEY_SIZE,
+                             &plain_start_password_size,
+                             TRUE);
+#ifndef DBUG_OFF
+  debug_password(plain_start_password, plain_start_password_size);
+#endif
+  my_free(plain_start_password);
+  DBUG_VOID_RETURN;
+}
+
+#ifndef DBUG_OFF
+void Master_info::debug_password(const char* password, size_t password_size)
+{
+  DBUG_PRINT("info", ("USER %s DELETING ENCRYPTED PASSWORD - "
+             "DECRYPTED VERSION '%s' SIZE %lu",
+             start_user_configured ? start_user : user,
+             password, password_size));
+}
+
+void Master_info::debug_password(Secure_Store* store, const char* key,
+                                 size_t key_size)
+{
+  char *plain_password= NULL;
+  size_t plain_password_size= 0;
+  char *encrypted_password= NULL;
+  size_t encrypted_password_size= 0;
+
+  plain_password= (char *) secure_store_get_item(store, (void *) key,
+                                                 key_size,
+                                                 &plain_password_size,
+                                                 TRUE);
+
+  encrypted_password= (char *) secure_store_get_item(store, (void *) key,
+                                                     key_size,
+                                                     &encrypted_password_size,
+                                                     FALSE);
+
+  DBUG_PRINT("info", ("USER %s UPDATING ENCRYPTED PASSWORD - ENCRYPTED VERSION "
+             "'%s' SIZE %lu, DECRYPTED VERSION '%s' SIZE %lu",
+             start_user_configured ? start_user : user,
+             encrypted_password, encrypted_password_size,
+             plain_password, plain_password_size));
+
+  my_free(plain_password);
+  my_free(encrypted_password);
+}
+#endif
 #endif /* HAVE_REPLICATION */

=== modified file 'sql/rpl_mi.h'
--- a/sql/rpl_mi.h	2011-03-23 23:28:49 +0000
+++ b/sql/rpl_mi.h	2011-04-18 06:30:30 +0000
@@ -24,6 +24,7 @@
 #define DEFAULT_CONNECT_RETRY 60
 
 #include "rpl_rli.h"
+#include "secure_store.h"
 #include "my_sys.h"
 
 typedef struct st_mysql MYSQL;
@@ -63,13 +64,173 @@ class Rpl_info_factory;
 
 class Master_info : public Rpl_info
 {
+public:
   friend class Rpl_info_factory;
 
+  /**
+    Stores a fake command that replaces thd->query() if START SLAVE was
+    used with USER/PASSWORD.
+  */
+  char start_command[FN_REFLEN + 1];
+  /**
+    The variables below are needed because we can change masters on the
+    fly.
+  */
+  char host[HOSTNAME_LENGTH + 1];
+
+private:
+  /**
+    If true, USER/PASSWORD was specified while running START SLAVE.
+  */
+  bool start_user_configured;
+  /**
+    If true, DEFAULT_AUTH/PLUGIN_DIR was specified while running
+    START SLAVE.
+  */
+  bool start_plugin_configured;
+  /**
+    User's name stored in the master.info.
+  */
+  char user[USERNAME_LENGTH + 1];
+  /**
+    Pointer to a secure store that is used to encrypt and decrypt password
+    stored in the master.info. In the feature, we may choose to store the
+    password in another persistent repository such as a system table.
+  */
+  Secure_Store* store_password;
+  /**
+    USER specified while running START SLAVE.
+  */
+  char start_user[USERNAME_LENGTH + 1];
+  /**
+    Pointer to a secure store that is used to encrypt and decrypt password
+    used while running START SLAVE. This password should not be written to
+    a repository.
+  */
+  Secure_Store* store_start_password;
+  /**
+    Stores the autentication plugin specified while running START SLAVE.
+  */
+  char start_plugin_auth[FN_REFLEN + 1];
+  /**
+    Stores the autentication plugin directory specified while running
+    START SLAVE.
+  */
+  char start_plugin_dir[FN_REFLEN + 1];
+
 public:
-  /* the variables below are needed because we can change masters on the fly */
-  char host[HOSTNAME_LENGTH+1];
-  char user[USERNAME_LENGTH+1];
-  char password[MAX_PASSWORD_LENGTH+1];
+  /**
+    Returns if USER/PASSWORD was specified while running
+    START SLAVE.
+
+    @return true or false.
+  */
+  bool is_start_user_configured()
+  {
+    return start_user_configured;
+  }
+  /**
+    Returns if DEFAULT_AUTH/PLUGIN_DIR was specified while running
+    START SLAVE.
+
+    @return true or false.
+  */
+  bool is_start_plugin_configured()
+  {
+    return start_plugin_configured;
+  }
+  /**
+    Defines that USER/PASSWORD was specified or not while running
+    START SLAVE.
+
+    @param config is true or false.
+  */
+  void set_start_user_configured(bool config)
+  {
+    start_user_configured= config;
+  }
+  /**
+    Defines that DEFAULT_AUTH/PLUGIN_DIR was specified or not while
+    running START SLAVE.
+
+    @param config is true or false.
+  */
+  void set_start_plugin_configured(bool config)
+  {
+    start_plugin_configured= config;
+  }
+  /**
+    Sets either user's name in the master.info repository when CHANGE
+    MASTER is executed or user's name used in START SLAVE if USER is
+    specified.
+
+    @param user_arg is user's name.
+  */
+  void set_user(const char* user_arg)
+  {
+    if (user_arg && start_user_configured)
+    {
+      strmake(start_user, user_arg, sizeof(start_user) - 1);
+    }
+    else if (user_arg)
+    {
+      strmake(user, user_arg, sizeof(user) - 1);
+    }
+  }
+  size_t get_user_size()
+  {
+    return (start_user_configured ? sizeof(start_user) : sizeof(user));
+  }
+  /**
+    If an user was specified while running START SLAVE, this function returns
+    such user. Otherwise, it returns the user stored in master.info.
+
+    @return user's name.
+  */
+  const char *get_user()
+  {
+    return start_user_configured ? start_user : user;
+  } 
+  /**
+    Sets either user's password in the master.info repository when CHANGE
+    MASTER is executed or user's password used in START SLAVE if PASSWORD
+    is specified.
+
+    @param password_arg is user's password.
+  */
+  bool set_password(const char* password_arg, int password_arg_size);
+  /**
+    Returns either user's password in the master.info repository or
+    user's password used in START SLAVE.
+
+    @param password_arg is user's password.
+  */
+  void get_password(char *password_arg, int *password_arg_size);
+#ifndef DBUG_OFF
+  /**
+    Prints out debug information on encrypted and decrypted passwords.
+  */
+  void debug_password(Secure_Store* store, const char* key,
+                      size_t key_size);
+  void debug_password(const char* password, size_t password_size);
+#endif
+  /*
+    Erase password and key stored in memory when START SLAVE is executed.
+  */
+  void clean_start_information();
+  const char *get_start_plugin_auth() { return start_plugin_auth; } 
+  const char *get_start_plugin_dir() { return start_plugin_dir; } 
+  void set_plugin_auth(const char* src)
+  {
+    if (src)
+      strmake(start_plugin_auth, src, sizeof(start_plugin_auth) - 1);
+  }
+  void set_plugin_dir(const char* src)
+  {
+    if (src)
+      strmake(start_plugin_dir, src, sizeof(start_plugin_dir) - 1);
+  }
+
   my_bool ssl; // enables use of SSL connection if true
   char ssl_ca[FN_REFLEN], ssl_capath[FN_REFLEN], ssl_cert[FN_REFLEN];
   char ssl_cipher[FN_REFLEN], ssl_key[FN_REFLEN];

=== modified file 'sql/rpl_rli.cc'
--- a/sql/rpl_rli.cc	2011-04-04 09:42:22 +0000
+++ b/sql/rpl_rli.cc	2011-04-18 06:30:30 +0000
@@ -1449,7 +1449,7 @@ bool Relay_log_info::read_info(Rpl_info_
     overwritten by the second row later.
   */
   if (from->prepare_info_for_read() ||
-      from->get_info(group_relay_log_name, sizeof(group_relay_log_name), ""))
+      from->get_info(group_relay_log_name, sizeof(group_relay_log_name), (char *) ""))
     DBUG_RETURN(TRUE);
 
   lines= strtoul(group_relay_log_name, &first_non_digit, 10);
@@ -1458,23 +1458,23 @@ bool Relay_log_info::read_info(Rpl_info_
       *first_non_digit=='\0' && lines >= LINES_IN_RELAY_LOG_INFO_WITH_DELAY)
   {
     /* Seems to be new format => read group relay log name */
-    if (from->get_info(group_relay_log_name,  sizeof(group_relay_log_name), ""))
+    if (from->get_info(group_relay_log_name, sizeof(group_relay_log_name), (char *) ""))
       DBUG_RETURN(TRUE);
   }
   else
      DBUG_PRINT("info", ("relay_log_info file is in old format."));
 
   if (from->get_info((ulong *) &temp_group_relay_log_pos,
-                        (ulong) BIN_LOG_HEADER_SIZE) ||
+                     (ulong) BIN_LOG_HEADER_SIZE) ||
       from->get_info(group_master_log_name,
-                        sizeof(group_relay_log_name), "") ||
+                     sizeof(group_relay_log_name), (char *) "") ||
       from->get_info((ulong *) &temp_group_master_log_pos,
-                        (ulong) 0))
+                     (ulong) 0))
     DBUG_RETURN(TRUE);
 
   if (lines >= LINES_IN_RELAY_LOG_INFO_WITH_DELAY)
   {
-    if (from->get_info((int *) &temp_sql_delay,(int) 0))
+    if (from->get_info((int *) &temp_sql_delay, (int) 0))
       DBUG_RETURN(TRUE);
   }
 

=== modified file 'sql/rpl_slave.cc'
--- a/sql/rpl_slave.cc	2011-04-04 10:06:13 +0000
+++ b/sql/rpl_slave.cc	2011-04-18 06:30:30 +0000
@@ -1996,7 +1996,7 @@ bool show_master_info(THD* thd, Master_i
   field_list.push_back(new Item_empty_string("Master_Host",
                                                      sizeof(mi->host)));
   field_list.push_back(new Item_empty_string("Master_User",
-                                                     sizeof(mi->user)));
+                                                     mi->get_user_size()));
   field_list.push_back(new Item_return_int("Master_Port", 7,
                                            MYSQL_TYPE_LONG));
   field_list.push_back(new Item_return_int("Connect_Retry", 10,
@@ -2093,7 +2093,7 @@ bool show_master_info(THD* thd, Master_i
     mysql_mutex_lock(&mi->rli->err_lock);
 
     protocol->store(mi->host, &my_charset_bin);
-    protocol->store(mi->user, &my_charset_bin);
+    protocol->store(mi->get_user(), &my_charset_bin);
     protocol->store((uint32) mi->port);
     protocol->store((uint32) mi->connect_retry);
     protocol->store(mi->get_master_log_name(), &my_charset_bin);
@@ -3165,7 +3165,7 @@ pthread_handler_t handle_slave_io(void *
   {
     sql_print_information("Slave I/O thread: connected to master '%s@%s:%d',"
                           "replication started in log '%s' at position %s",
-                          mi->user, mi->host, mi->port,
+                          mi->get_user(), mi->host, mi->port,
 			  mi->get_io_rpl_log_name(),
 			  llstr(mi->get_master_log_pos(), llbuff));
   /*
@@ -3441,7 +3441,11 @@ err:
   write_ignored_events_info_to_relay_log(thd, mi);
   THD_STAGE_INFO(thd, stage_waiting_for_slave_mutex_on_exit);
   mysql_mutex_lock(&mi->run_lock);
-
+  /*
+    Clean information used to start slave in order to avoid
+    security issues.
+  */
+  mi->clean_start_information();
   /* Forget the relay log's format */
   delete mi->rli->relay_log.description_event_for_queue;
   mi->rli->relay_log.description_event_for_queue= 0;
@@ -4700,6 +4704,8 @@ static int connect_to_master(THD* thd, M
   int last_errno= -2;                           // impossible error
   ulong err_count=0;
   char llbuff[22];
+  char password[MAX_PASSWORD_LENGTH + 1];
+  int password_size= sizeof(password);
   DBUG_ENTER("connect_to_master");
 
 #ifndef DBUG_OFF
@@ -4736,10 +4742,17 @@ static int connect_to_master(THD* thd, M
   /* This one is not strictly needed but we have it here for completeness */
   mysql_options(mysql, MYSQL_SET_CHARSET_DIR, (char *) charsets_dir);
 
-  while (!(slave_was_killed = io_slave_killed(thd,mi)) &&
-         (reconnect ? mysql_reconnect(mysql) != 0 :
-          mysql_real_connect(mysql, mi->host, mi->user, mi->password, 0,
-                             mi->port, 0, client_flag) == 0))
+  if (mi->is_start_plugin_configured())
+    mysql_options(mysql, MYSQL_DEFAULT_AUTH, mi->get_start_plugin_auth());
+
+  if (mi->is_start_plugin_configured())
+    mysql_options(mysql, MYSQL_PLUGIN_DIR, mi->get_start_plugin_dir());
+
+  mi->get_password(password, &password_size);
+  while (!(slave_was_killed = io_slave_killed(thd,mi))
+         && (reconnect ? mysql_reconnect(mysql) != 0 :
+          mysql_real_connect(mysql, mi->host, mi->get_user(),
+                             password, 0, mi->port, 0, client_flag) == 0))
   {
     /*
        SHOW SLAVE STATUS will display the number of retries which
@@ -4752,7 +4765,7 @@ static int connect_to_master(THD* thd, M
                "error %s to master '%s@%s:%d'"
                " - retry-time: %d  retries: %lu",
                (reconnect ? "reconnecting" : "connecting"),
-               mi->user, mi->host, mi->port,
+               mi->get_user(), mi->host, mi->port,
                mi->connect_retry, err_count + 1);
     /*
       By default we try forever. The reason is that failure will trigger
@@ -4776,7 +4789,7 @@ static int connect_to_master(THD* thd, M
     {
       if (!suppress_warnings && global_system_variables.log_warnings)
         sql_print_information("Slave: connected to master '%s@%s:%d',\
-replication resumed in log '%s' at position %s", mi->user,
+replication resumed in log '%s' at position %s", mi->get_user(),
                         mi->host, mi->port,
                         mi->get_io_rpl_log_name(),
                         llstr(mi->get_master_log_pos(),llbuff));
@@ -4784,7 +4797,7 @@ replication resumed in log '%s' at posit
     else
     {
       general_log_print(thd, COM_CONNECT_OUT, "%s@%s:%d",
-                        mi->user, mi->host, mi->port);
+                        mi->get_user(), mi->host, mi->port);
     }
 #ifdef SIGNAL_WITH_VIO_CLOSE
     thd->set_active_vio(mysql->net.vio);
@@ -4812,9 +4825,22 @@ static int safe_reconnect(THD* thd, MYSQ
 }
 
 
+/*
+  We need to refactor this function and get rid of this duplicated code.
+  Howerver, I need to check this with Jasonh in order to understand what
+  was the intentation behind the code because the comments are not clear
+  and the function is not used.
+
+  This is a callback function that is part of the replication interface/
+  library and currently there is no plugin calling it.
+
+  \Alfranio
+*/
 MYSQL *rpl_connect_master(MYSQL *mysql)
 {
   THD *thd= current_thd;
+  char password[MAX_PASSWORD_LENGTH + 1];
+  int password_size= sizeof(password);
   Master_info *mi= my_pthread_getspecific_ptr(Master_info*, RPL_MASTER_INFO);
   if (!mi)
   {
@@ -4868,9 +4894,10 @@ MYSQL *rpl_connect_master(MYSQL *mysql)
   /* This one is not strictly needed but we have it here for completeness */
   mysql_options(mysql, MYSQL_SET_CHARSET_DIR, (char *) charsets_dir);
 
+  mi->get_password(password, &password_size);
   if (io_slave_killed(thd, mi)
-      || !mysql_real_connect(mysql, mi->host, mi->user, mi->password, 0,
-                             mi->port, 0, 0))
+      || !mysql_real_connect(mysql, mi->host, mi->get_user(),
+                             password, 0, mi->port, 0, 0))
   {
     if (!io_slave_killed(thd, mi))
       sql_print_error("rpl_connect_master: error connecting to master: %s (server_error: %d)",
@@ -5861,14 +5888,14 @@ bool change_master(THD* thd, Master_info
   }
   DBUG_PRINT("info", ("master_log_pos: %lu", (ulong) mi->get_master_log_pos()));
 
+  if (lex_mi->user)
+    mi->set_user(lex_mi->user);
+  if (lex_mi->password)
+    mi->set_password(lex_mi->password, strlen(lex_mi->password));
   if (lex_mi->host)
     strmake(mi->host, lex_mi->host, sizeof(mi->host)-1);
   if (lex_mi->bind_addr)
     strmake(mi->bind_addr, lex_mi->bind_addr, sizeof(mi->bind_addr)-1);
-  if (lex_mi->user)
-    strmake(mi->user, lex_mi->user, sizeof(mi->user)-1);
-  if (lex_mi->password)
-    strmake(mi->password, lex_mi->password, sizeof(mi->password)-1);
   if (lex_mi->port)
     mi->port = lex_mi->port;
   if (lex_mi->connect_retry)

=== added file 'sql/secure_store.cc'
--- a/sql/secure_store.cc	1970-01-01 00:00:00 +0000
+++ b/sql/secure_store.cc	2011-04-18 06:30:30 +0000
@@ -0,0 +1,910 @@
+#include "secure_store.h"
+#include "hash.h"
+#include "my_sys.h"
+#include "log.h"
+
+class Crypto_Meta_Info
+{
+private:
+  /*
+    This identifies that the secure meta information was correctly
+    initialized and now can be used to encrypt and decrypt data.
+  */
+  bool inited;
+
+#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY) && !defined(HAVE_YASSL)
+  /**
+    Crypto structure per key that is used to encrypt data stored into
+    the repository.
+  */
+  EVP_CIPHER_CTX e_ctx;
+  /**
+    Crypto structure per key that is used to decrypt data stored into
+    the repository;
+  */
+  EVP_CIPHER_CTX d_ctx;
+#endif /* HAVE_OPENSSL && !EMBEDDED_LIBRARY && !HAVE_YASSL */
+
+public:
+  Crypto_Meta_Info();
+  ~Crypto_Meta_Info();
+
+  bool init(char *key_input, const size_t key_input_size);
+  bool deinit();
+  bool encrypt_data(void *plain_data, const size_t plain_data_size,
+                    void *crypt_data, size_t *crypt_data_size);
+  bool decrypt_data(void *plain_data, size_t *plain_data_size,
+                    void *crypt_data, const size_t crypt_data_size);
+  size_t get_maximum_encrypted_data_size(size_t plain_data_size) const;
+  bool is_inited();
+
+private:
+  Crypto_Meta_Info(const Crypto_Meta_Info& info);
+  Crypto_Meta_Info& operator=(const Crypto_Meta_Info& info);
+};
+
+Crypto_Meta_Info::Crypto_Meta_Info()
+: inited(FALSE)
+{
+}
+
+Crypto_Meta_Info::~Crypto_Meta_Info()
+{
+  if (inited) deinit();
+}
+
+bool Crypto_Meta_Info::is_inited()
+{
+  return inited;
+}
+
+#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY) && !defined(HAVE_YASSL)
+bool Crypto_Meta_Info::init(char *key_input, const size_t key_input_size)
+{
+  int error= 0;
+  int key_size= 0;
+  const int AES_ROUNDS_KEY= 10;
+  uchar key[ENCRYPTION_KEY_SIZE], ini_vector[ENCRYPTION_KEY_SIZE];
+  bool random= false;
+
+  DBUG_ENTER("Crypto_Meta_Info::init");
+
+  if (inited) DBUG_RETURN(FALSE);
+
+  if (key_input == NULL)
+  {
+    key_input= (char *) my_malloc(key_input_size, MYF(MY_WME));
+    if (key_input == NULL ||
+        !(error= RAND_bytes((unsigned char *)(key_input), key_input_size)) ||
+        error == -1)
+    {
+      my_free(key_input);
+      sql_print_warning("Error while generating random input key.");
+      DBUG_RETURN(TRUE);
+    }
+    random= TRUE;
+  }
+
+  /*
+    The input key provided is not directly used to encrypt data but a
+    new key is generated based on the input key and a digest function,
+    in this case, SHA-1.
+  */
+  key_size= EVP_BytesToKey(EVP_aes_256_cbc(), EVP_sha1(), NULL,
+                           (unsigned char *)key_input, key_input_size,
+                           AES_ROUNDS_KEY, key, ini_vector);
+  if (key_size != ENCRYPTION_KEY_SIZE)
+  {
+    if (random) my_free(key_input);
+    sql_print_warning("Error while generating encryption key whose size is %lu.",
+                      key_input_size);
+    DBUG_RETURN(TRUE);
+  }
+
+  /*
+    Initialize the structure that is going to be used to encrypt data.
+  */
+  EVP_CIPHER_CTX_init(&e_ctx);
+  if (!(error= EVP_EncryptInit_ex(&e_ctx, EVP_aes_256_cbc(), NULL, key, ini_vector))
+      || error == -1)
+  {
+    if (random) my_free(key_input);
+    sql_print_warning("Error while initializing encryption structure."); 
+    DBUG_RETURN(TRUE);
+  }
+
+  /*
+    Initialize the structure that is going to be used to decrypt data.
+  */
+  EVP_CIPHER_CTX_init(&d_ctx);
+  if (!(error= EVP_DecryptInit_ex(&d_ctx, EVP_aes_256_cbc(), NULL, key, ini_vector))
+      || error == -1)
+  {
+    if (random) my_free(key_input);
+    sql_print_warning("Error while initializing decryption structure.");
+    DBUG_RETURN(TRUE);
+  }
+
+  inited= TRUE;
+
+  DBUG_RETURN(FALSE);
+}
+
+bool Crypto_Meta_Info::deinit()
+{
+  int error= 0;
+
+  DBUG_ENTER("Crypto_Meta_Info::deinit");
+
+  /*
+    Clean up the structure used to encrypt data.
+  */
+  if (!(error= EVP_CIPHER_CTX_cleanup(&e_ctx)) || error == -1)
+  {
+    sql_print_warning("Error while cleaning encryption information.");
+    DBUG_RETURN(TRUE);
+  }
+
+  /*
+    Clean up the structure used to decrypt data.
+  */
+  if (!(error= EVP_CIPHER_CTX_cleanup(&d_ctx)) || error == -1)
+  {
+    sql_print_warning("Error while cleaning encryption information"); 
+    DBUG_RETURN(TRUE);
+  }
+
+  DBUG_RETURN(FALSE);
+}
+
+size_t Crypto_Meta_Info::get_maximum_encrypted_data_size(const size_t plain_data_size) const
+{
+  return (plain_data_size + AES_BLOCK_SIZE);
+}
+
+bool Crypto_Meta_Info::encrypt_data(void *plain_data, const size_t plain_data_size,
+                                    void *crypt_data, size_t *crypt_data_size)
+{
+  int error= 0;
+  int add_size = 0;
+  unsigned char* uchar_crypt_data= NULL;
+
+  DBUG_ENTER("Crypto_Meta_Info::encrypt_data");
+
+  /*
+    The maximum size of the encrypted data is:
+      . plain_data_size + AES_BLOCK_SIZE.
+  */
+  *crypt_data_size = plain_data_size + AES_BLOCK_SIZE;
+  if (!(error= EVP_EncryptInit_ex(&e_ctx, NULL, NULL, NULL, NULL))
+      || error == -1)
+  {
+    sql_print_warning("Error while initializing encryption function.");
+    DBUG_RETURN(TRUE);
+  }
+  /*
+    Set the encrypted data and its size.
+  */
+  if (!(error= EVP_EncryptUpdate(&e_ctx, (unsigned char *) crypt_data,
+                                 (int *) crypt_data_size,
+                                 (unsigned char *) plain_data,
+                                 (int) plain_data_size))
+      || error == -1)
+  {
+    sql_print_warning("Error while encrypting data.");
+    DBUG_RETURN(TRUE);
+  }
+  /*
+    Set the encrypted data with remaining bytes, if there is any.
+  */
+  uchar_crypt_data= (unsigned char *)crypt_data;
+  if (!(error= EVP_EncryptFinal_ex(&e_ctx,
+                                   (unsigned char *) (uchar_crypt_data + *crypt_data_size),
+                                   &add_size))
+      || error == -1)
+  {
+    sql_print_warning("Error while encrypting data.");
+    DBUG_RETURN(TRUE);
+  }
+  /*
+    Calculate the encrypted data size based on the remaining
+    bytes that were appended.
+  */
+  *crypt_data_size = *crypt_data_size + add_size;
+
+  DBUG_RETURN(FALSE);
+}
+
+bool Crypto_Meta_Info::decrypt_data(void *plain_data, size_t *plain_data_size,
+                                    void *crypt_data, const size_t crypt_data_size)
+{
+  int error= 0;
+  int add_size = 0;
+  unsigned char* uchar_plain_data= NULL;
+
+  DBUG_ENTER("Crypto_Meta_Info::decrypt_data");
+
+  /*
+    The maximum size of the data is:
+      . crypt_data_size
+  */
+  *plain_data_size = crypt_data_size;
+  if (!(error= EVP_DecryptInit_ex(&d_ctx, NULL, NULL, NULL, NULL)) || error == -1)
+  {
+    sql_print_warning("Error while initializing decryption function.");
+    DBUG_RETURN(TRUE);
+  }
+  /*
+    Set the data and its size.
+  */
+  if (!(error= EVP_DecryptUpdate(&d_ctx, (unsigned char *) plain_data,
+                                 (int *) plain_data_size,
+                                 (unsigned char *) crypt_data,
+                                 (int)crypt_data_size)) || error == -1)
+  {
+    sql_print_warning("Error while decrypting data.");
+    DBUG_RETURN(TRUE);
+  }
+  /*
+    Set data with remaining bytes, if there is any.
+  */
+  uchar_plain_data= (unsigned char *)plain_data;
+  if (!(error= EVP_DecryptFinal_ex(&d_ctx,
+      (unsigned char *) (uchar_plain_data + *plain_data_size),
+      &add_size)) || error == -1)
+  {
+    sql_print_warning("Error while decrypting data.");
+    DBUG_RETURN(TRUE);
+  }
+  /*
+    Calculate data size based on the remaining bytes that were
+    appended.
+  */
+  *plain_data_size = *plain_data_size + add_size;
+
+  DBUG_RETURN(FALSE);
+}
+#else
+bool Crypto_Meta_Info::init(char *key_input, const size_t key_input_size)
+{
+  return FALSE;
+}
+
+bool Crypto_Meta_Info::deinit()
+{
+  return FALSE;
+}
+
+size_t Crypto_Meta_Info::get_maximum_encrypted_data_size(const size_t plain_data_size) const
+{
+  return plain_data_size;
+}
+
+bool Crypto_Meta_Info::encrypt_data(void *plain_data, const size_t plain_data_size,
+                                    void *crypt_data, size_t *crypt_data_size)
+{
+  strmake((char *) crypt_data, (char *) plain_data, plain_data_size);
+  *crypt_data_size= plain_data_size;
+  return FALSE;
+}
+
+bool Crypto_Meta_Info::decrypt_data(void *plain_data, size_t *plain_data_size,
+                                    void *crypt_data, const size_t crypt_data_size)
+{
+  strmake((char *) plain_data, (char *) crypt_data, crypt_data_size);
+  *plain_data_size= crypt_data_size;
+  return FALSE;
+}
+#endif /* HAVE_OPENSSL && !EMBEDDED_LIBRARY && !HAVE_YASSL */
+
+class Key_Info
+{
+private:
+  /**
+    Key used to uniquely identify an encrypted data.
+  */
+  void* key;
+  /**
+    Key's size.
+  */
+  size_t key_size;
+
+public:
+  Key_Info()
+  : key(NULL), key_size(0) { }
+
+  ~Key_Info() { }
+
+  void *get_key()
+  {
+    return key;
+  }
+
+  size_t get_key_size()
+  {
+    return key_size;
+  }
+
+  void set_key(void *key_arg, size_t key_size_arg)
+  {
+    key_size= key_size_arg;
+    key= key_arg;
+  }
+};
+
+class Crypto_Info
+{
+private:
+  /**
+    Encrypted data.
+  */
+  void* crypto;
+  /**
+    Encrypted data's size.
+  */
+  size_t crypto_size;
+
+public:
+  Crypto_Info()
+  : crypto(NULL), crypto_size(0) { }
+
+  ~Crypto_Info() {  }
+
+  void *get_crypto()
+  {
+    return crypto;
+  }
+
+  size_t get_crypto_size()
+  {
+    return crypto_size;
+  }
+
+  void set_crypto(void *crypto_arg, size_t crypto_size_arg)
+  {
+    crypto= crypto_arg;
+    crypto_size= crypto_size_arg;
+  }
+};
+
+typedef struct Hash_Secure_Store_Entry
+{
+  Key_Info *key;
+  Crypto_Info *crypto;
+} Hash_Secure_Store_Entry;
+
+extern "C" uchar *get_secure_store_key(const uchar *record, size_t *length,
+                                       my_bool not_used __attribute__((unused)))
+{
+  Hash_Secure_Store_Entry *entry=(Hash_Secure_Store_Entry *) record;
+  *length= entry->key->get_key_size();
+
+  return((uchar*) entry->key->get_key());
+}
+
+extern "C" void free_secure_store_entry(Hash_Secure_Store_Entry *entry)
+{
+  my_free(entry->key->get_key());
+  delete entry->key;
+  my_free(entry->crypto->get_crypto());
+  delete entry->crypto;
+}
+
+/**
+  This class maps an unique key to encrypted data and provides implementation
+  for: secure_store_init(), secure_store_check_item(), secure_store_put_item()
+  , secure_store_get_item(), secure_store_delete_item().
+  The access to the repository is hidden through some methods: search_data(),
+  insert_data() and delete_data().
+*/
+class Secure_Store_Interface: public Secure_Store
+{
+private:
+  /**
+    Uniquely identifies this secure store. So given a store, one can easly
+    find its reference in Secure_Schema.
+  */
+  char schema[FN_REFLEN + 1];
+  /**
+    Defines how to encrypt and decrypt data stored in this
+    secure store.
+  */
+  Crypto_Meta_Info secure_info;
+  /**
+    Maps unique keys to encrypted data: Key_Info --> Crypto_Info.
+    This is a temporary solution that will be used while WL#5769
+    is not ready.
+  */
+  HASH key_store;
+  /**
+    Identifies if the hash structure was properly initialized.
+  */
+  bool inited_hash;
+
+public:
+  Secure_Store_Interface(const char* schema_arg)
+  {
+    strmake(schema, schema_arg, FN_REFLEN);
+    inited_hash=
+      (my_hash_init(&key_store, &my_charset_bin,
+                    0, 0, 0, get_secure_store_key,
+                    (my_hash_free_key) free_secure_store_entry, 0) == 0);
+  }
+
+  ~Secure_Store_Interface()
+  {
+    if (inited_hash) my_hash_free(&key_store); 
+  }
+
+  const char* get_schema() const
+  {
+    return schema;
+  }
+  
+  Crypto_Info *search_data(Key_Info *key_info)
+  {
+    Hash_Secure_Store_Entry *entry= NULL;
+    if (inited_hash && key_info && key_info->get_key() &&
+        key_info->get_key_size())
+    {  
+      entry= (Hash_Secure_Store_Entry *)
+        my_hash_search(&key_store, (uchar *) key_info->get_key(),
+                       key_info->get_key_size());
+    }
+    return (entry ? entry->crypto : NULL);
+  }
+
+  bool insert_data(Key_Info *key_info, Crypto_Info* crypto_info)
+  {
+    
+    bool error= TRUE;
+    if (inited_hash && key_info && crypto_info &&
+        key_info->get_key() && key_info->get_key_size())
+    {
+      Hash_Secure_Store_Entry *entry= (Hash_Secure_Store_Entry *)
+        my_malloc(sizeof(Hash_Secure_Store_Entry), MYF(MY_WME));
+      if (entry)
+      {
+        entry->key= key_info;
+        entry->crypto= crypto_info;
+        if (my_hash_insert(&key_store, (uchar*) entry))
+          my_free(entry);
+        else
+          error= FALSE;
+      }
+    }
+    return error;
+  }
+
+  void delete_data(Key_Info* key_info)
+  {
+    Hash_Secure_Store_Entry *entry= NULL;
+
+    if (inited_hash && key_info && key_info->get_key() &&
+        key_info->get_key_size())
+    {  
+      entry= (Hash_Secure_Store_Entry *)
+        my_hash_search(&key_store, (uchar *) key_info->get_key(),
+                       key_info->get_key_size());
+    }
+    if (entry)
+    {
+      my_hash_delete(&key_store, (uchar*) entry);
+      my_free(entry);
+    }
+  }
+
+  bool init(char *key_input, const size_t key_input_size);
+  bool check_item(void *key, size_t key_size);
+  bool put_item(void **key, size_t key_size, void *plain_data,
+                size_t plain_data_size, bool encrypt);
+  void *get_item(void *key, size_t key_size, size_t *plain_data_size,
+                 bool decrypt);
+  void *delete_item(void *key, size_t key_size, size_t *plain_data_size,
+                    bool decrypt);
+
+private:
+  Secure_Store_Interface(const Secure_Store_Interface& info);
+  Secure_Store_Interface& operator=(const Secure_Store_Interface& info);
+};
+
+bool Secure_Store_Interface::init(char *key_input, const size_t key_input_size)
+{
+  return secure_info.init(key_input, key_input_size);
+}
+
+bool Secure_Store_Interface::check_item(void *key, size_t key_size)
+{
+  /* Structure used to search for encrypted data. */
+  Key_Info key_search;
+  key_search.set_key(key, key_size);
+
+  return (search_data(&key_search) != NULL);
+}
+
+/*
+  In order to ease implementation, we assume that key is always defined
+  and there is no auto-generation for now.
+*/
+bool Secure_Store_Interface::put_item(void **key, size_t key_size,
+                                      void *plain_data, size_t plain_data_size,
+                                      bool encrypt)
+{
+  /* Structure used to search for encrypted data. */
+  Key_Info key_search;
+
+  /* Structures to store key and encrypted data. */
+  Key_Info *key_info= NULL;
+  Crypto_Info *crypto_info= NULL;
+
+  /* Stores the data to be inserted and if everything goes fine, this is
+     copied to Crypto_Info.
+  */
+  void *crypto_data= NULL;
+  size_t crypto_data_size= 0;
+
+  /*
+    Defines a key that will be used to search for encrypted data.
+  */
+  key_search.set_key(*key, key_size);
+  key_info= &key_search;
+
+  /*
+    If encrypted data is not found a new Key_Info and Crypto_Info are
+    created and then inserted.
+  */
+  if ((crypto_info= search_data(key_info)) == NULL)
+  {
+    /*
+      Creates Key_Info and if it is not possible due to memory issues,
+      the execution returns with an error.
+    */
+    if ((key_info= new Key_Info()) == NULL)
+      return TRUE;
+
+    /*
+      Populates Key_Info and if it is not possible due to memory issues,
+      the execution returns with an error.
+    */
+    key_info->set_key(my_malloc(key_size, MYF(MY_WME)), key_size);
+    if (key_info->get_key() == NULL)
+      goto err;
+    memcpy(key_info->get_key(), *key, key_size);
+
+    if ((crypto_info= new Crypto_Info()) == NULL)
+      goto err;
+
+    if (insert_data(key_info, crypto_info))
+      goto err;
+  }
+
+  /*
+    Allocates memory to store the encrypted data, then encrypts the
+    data and stores it.
+  */
+  crypto_data_size= encrypt ?
+    secure_info.get_maximum_encrypted_data_size(plain_data_size) :
+    plain_data_size;
+  if ((crypto_data= my_malloc(crypto_data_size, MYF(MY_WME))))
+  {
+    bool done= FALSE;
+
+    if (encrypt)
+      done= !secure_info.encrypt_data(plain_data, plain_data_size,
+                                      crypto_data, &crypto_data_size);
+    else
+    {
+      done= TRUE;
+      memcpy(crypto_data, plain_data, plain_data_size);
+      crypto_data_size= plain_data_size;
+    }
+
+    if (done)
+    {
+      my_free(crypto_info->get_crypto());
+      crypto_info->set_crypto(crypto_data, crypto_data_size);
+      return FALSE;
+    }
+  }
+  
+err:
+  /*
+    Something bad happens and we need to free memory that was allocated.
+    To ease this task, we ensure that at this point key_info is not null
+    and as such either points to key_search or a new created object.
+
+    If it points to key_search, this means that we are updating an item
+    and just need to free memory allocated for the crypto_data because
+    Key_Info and Crypto_Info were not changed.
+
+    However, if it points to another memory location, this means that we
+    had tried to insert data and as such we need to remove it, free
+    memory allocated for the key and delete Key_Info and Crypto_Info.
+  */
+  assert(key_info != NULL);
+
+  if (key_info != &key_search)
+    delete_data(key_info);
+  /*
+    If something bad happens the cryto_data was not assigned to crypto_info
+    and it was not freed by delete_data(). For that reason, we need to free
+    the memory here.
+  */
+  my_free(crypto_data);
+
+  return TRUE;
+}
+
+void *Secure_Store_Interface::get_item(void *key, size_t key_size,
+                                       size_t *plain_data_size, bool decrypt)
+{
+  /* Structure used to search for encrypted data. */
+  Key_Info key_search;
+  Crypto_Info *crypto_info= NULL;
+  void* plain_data= NULL;
+
+  key_search.set_key(key, key_size);
+  if ((crypto_info= search_data(&key_search)))
+  {
+    /*
+      Maybe we should store the plain data size in order to allocate the exact
+      amount of memory. /Alfranio
+    */
+    if ((plain_data= my_malloc(crypto_info->get_crypto_size(), MYF(MY_WME))))
+    {
+      bool done= FALSE;
+      if (decrypt) 
+        done= !secure_info.decrypt_data(plain_data, plain_data_size,
+                                        crypto_info->get_crypto(),
+                                        crypto_info->get_crypto_size());
+      else
+      {
+        done= TRUE;
+        memcpy(plain_data, crypto_info->get_crypto(),
+               crypto_info->get_crypto_size());
+        *plain_data_size= crypto_info->get_crypto_size();
+      }
+      if (done) return plain_data;
+    }
+  }
+
+  my_free(plain_data);
+  return NULL;
+}
+
+void *Secure_Store_Interface::delete_item(void *key, size_t key_size,
+                                          size_t* plain_data_size, bool decrypt)
+{
+  /* Structure used to search for encrypted data. */
+  Key_Info key_search;
+  void* plain_data= get_item(key, key_size, plain_data_size, decrypt);
+
+  if (plain_data)
+  {
+    key_search.set_key(key, key_size);
+    delete_data(&key_search);
+  }
+
+  return plain_data;
+}
+
+typedef struct Hash_Secure_Schema_Entry
+{
+  char *schema;
+  Secure_Store_Interface *secure_store;
+} Hash_Secure_Schema_Entry;
+
+extern "C" uchar *get_secure_schema_key(const uchar *record, size_t *length,
+                                        my_bool not_used __attribute__((unused)))
+{
+  Hash_Secure_Schema_Entry *entry=(Hash_Secure_Schema_Entry *) record;
+  *length= strlen(entry->schema);
+
+  return((uchar*) entry->schema);
+}
+
+extern "C" void free_secure_schema_entry(Hash_Secure_Schema_Entry *entry)
+{
+  my_free(entry->schema);
+  delete entry->secure_store;
+}
+
+/*
+  This class maps an unique schema to a secure store and provides
+  implementation for: secure_store_open() and secure_store_close().
+  The access to the repository is hidden through some methods:
+  search_data(), insert_data() and delete_data().
+*/
+class Secure_Schema
+{
+private:
+  /**
+    Maps an unique schema to secure store: Schema --> Secure_Store.
+  */
+  HASH key_schema;
+  /**
+    Identifies if the hash structure was properly initialized.
+  */
+  bool inited_hash;
+
+public:
+  Secure_Schema()
+  {
+    inited_hash=
+      (my_hash_init(&key_schema, &my_charset_bin,
+                    0, 0, 0, get_secure_schema_key,
+                    (my_hash_free_key) free_secure_schema_entry, 0) == 0);
+  }
+
+  ~Secure_Schema()
+  {
+    if (inited_hash) my_hash_free(&key_schema); 
+  }
+
+  Secure_Store_Interface *search_data(char* schema)
+  {
+    Hash_Secure_Schema_Entry *entry= NULL;
+    if (inited_hash && schema)
+    {
+      entry = (Hash_Secure_Schema_Entry *)
+        my_hash_search(&key_schema, (uchar *) schema, strlen(schema));
+    }
+    return (entry ? entry->secure_store : NULL);
+  }
+
+  bool insert_data(char* schema, Secure_Store_Interface* secure_store)
+  {
+    bool error= TRUE;
+    if (inited_hash && schema && secure_store)
+    {
+      Hash_Secure_Schema_Entry *entry= (Hash_Secure_Schema_Entry *)
+        my_malloc(sizeof(Hash_Secure_Schema_Entry), MYF(MY_WME));
+      if (entry)
+      {
+        entry->schema= schema;
+        entry->secure_store= secure_store;
+        if (my_hash_insert(&key_schema, (uchar*) entry))
+          my_free(entry);
+        else
+          error= FALSE;
+      }
+    }
+    return error;
+  }
+
+  void delete_data(char* schema)
+  {
+    Hash_Secure_Schema_Entry *entry= NULL;
+    if (inited_hash && schema)
+    {
+      entry = (Hash_Secure_Schema_Entry *)
+        my_hash_search(&key_schema, (uchar *) schema, strlen(schema));
+    }
+
+    if (entry)
+    {
+      my_hash_delete(&key_schema, (uchar*) entry);
+      my_free(entry);
+    }
+  }
+
+  Secure_Store_Interface *open(char *schema);
+  void close(Secure_Store_Interface* store);
+
+private:
+  Secure_Schema(const Secure_Schema& info);
+  Secure_Schema& operator=(const Secure_Schema& info);
+};
+
+Secure_Store_Interface *Secure_Schema::open(char *schema_arg)
+{
+  Secure_Store_Interface *store= NULL;
+  char *schema= NULL;
+  
+  if ((store= search_data(schema_arg)) == NULL)
+  {
+    store= new Secure_Store_Interface(schema_arg);
+    schema= (char *) my_malloc(strlen(schema_arg), MYF(MY_WME));
+    if (store == NULL || schema == NULL)
+      goto err;
+
+    strmake(schema, schema_arg, strlen(schema_arg));
+    if (insert_data(schema, store))
+      goto err;
+  }
+
+  return store;
+
+err:
+  delete store;
+  my_free(schema);
+
+  return NULL;
+}
+
+void Secure_Schema::close(Secure_Store_Interface* store)
+{
+  char* schema= const_cast<char *>(store->get_schema());
+  delete_data(schema);
+}
+
+Secure_Schema secure_schema;
+
+extern "C" {
+Secure_Store *secure_store_open(char *schema,
+                                uint32 flags __attribute__((unused)))
+{
+  if (schema)
+    return secure_schema.open(schema);
+
+  return NULL;
+}
+
+bool secure_store_flush(Secure_Store *store_arg __attribute__((unused)))
+{
+  return FALSE;
+}
+
+bool secure_store_init(Secure_Store *store_arg, char *key_input,
+                       const size_t key_input_size)
+{
+  if (store_arg != NULL)
+  {
+    Secure_Store_Interface *store= static_cast<Secure_Store_Interface *>(store_arg);
+    return store->init(key_input, key_input_size);
+  }
+  return TRUE;
+}
+
+void secure_store_close(Secure_Store *store_arg)
+{
+  if (store_arg != NULL)
+  {
+    Secure_Store_Interface *store= static_cast<Secure_Store_Interface *>(store_arg);
+    secure_schema.close(store);
+  }
+}
+
+bool secure_store_put_item(Secure_Store *store_arg, void **key, size_t key_len,
+                           void *value, size_t value_len, bool encrypt)
+{
+  if (store_arg != NULL && key != NULL && value != NULL && value_len != 0)
+  {
+    Secure_Store_Interface *store= static_cast<Secure_Store_Interface *>(store_arg);
+    return store->put_item(key, key_len, value, value_len, encrypt);
+  }
+  return TRUE;
+}
+
+void *secure_store_get_item(Secure_Store *store_arg, void *key, size_t key_len,
+                            size_t *value_len, bool decrypt)
+{
+  if (store_arg != NULL && key != NULL && key_len != 0 && value_len != NULL)
+  {
+    Secure_Store_Interface *store= static_cast<Secure_Store_Interface *>(store_arg);
+    return store->get_item(key, key_len, value_len, decrypt);
+  }
+  return NULL;
+}
+
+void *secure_store_delete_item(Secure_Store *store_arg, void *key, size_t key_len,
+                               size_t *value_len, bool decrypt)
+{
+  if (store_arg != NULL && key != NULL && key_len != 0 && value_len != NULL)
+  {
+    Secure_Store_Interface *store= static_cast<Secure_Store_Interface *>(store_arg);
+    return store->delete_item(key, key_len, value_len, decrypt);
+  }
+  return NULL;
+}
+
+bool secure_store_check_item(Secure_Store *store_arg, void *key, size_t key_len)
+{
+  if (store_arg != NULL && key != NULL && key_len != 0)
+  {
+    Secure_Store_Interface *store= static_cast<Secure_Store_Interface *>(store_arg);
+    return store->check_item(key, key_len);
+  }
+  return FALSE;
+}
+} /* extern "C" */

=== added file 'sql/secure_store.h'
--- a/sql/secure_store.h	1970-01-01 00:00:00 +0000
+++ b/sql/secure_store.h	2011-04-18 06:30:30 +0000
@@ -0,0 +1,53 @@
+#ifndef SECURE_STORE_H
+
+#define SECURE_STORE_H
+
+#include <my_global.h>
+#include <sql_priv.h>
+
+#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY) && !defined(HAVE_YASSL)
+#include <openssl/evp.h>
+#include <openssl/rand.h>
+#include <openssl/aes.h>
+
+/**
+  Extra space necessary to store encrypted data. Note that this
+  is zero if crypto library is not available.
+*/
+const int ENCRYPTION_BLOCK_SIZE= AES_BLOCK_SIZE;
+/**
+  Size of the key in bytes used to encrypt data.
+*/
+#define ENCRYPTION_KEY_SIZE 32
+
+#else
+const int ENCRYPTION_BLOCK_SIZE= 0;
+
+#endif /* HAVE_OPENSSL && !EMBEDDED_LIBRARY && !HAVE_YASSL */
+
+class Secure_Store
+{
+protected:
+  Secure_Store()
+  {
+  }
+private:
+  Secure_Store(const Secure_Store& info);
+  Secure_Store& operator=(const Secure_Store& info);
+};
+
+extern "C" {
+Secure_Store *secure_store_open(char *schema, uint32 flags);
+bool secure_store_init(Secure_Store *store, char *key_input,
+                       size_t key_input_size);
+bool secure_store_flush(Secure_Store *store);
+void secure_store_close(Secure_Store *store);
+bool secure_store_put_item(Secure_Store *store, void **key, size_t key_len,
+                           void *value, size_t value_len, bool encrypt);
+void *secure_store_get_item(Secure_Store *store, void *key, size_t key_len,
+                            size_t *value_len, bool decrypt);
+void *secure_store_delete_item(Secure_Store *store, void *key, size_t key_len,
+                               size_t *value_len, bool decrypt);
+bool secure_store_check_item(Secure_Store *store, void *key, size_t key_len);
+}
+#endif /* SECURE_STORE_H */

=== modified file 'sql/sql_lex.h'
--- a/sql/sql_lex.h	2011-03-28 10:56:41 +0000
+++ b/sql/sql_lex.h	2011-04-18 06:30:30 +0000
@@ -984,6 +984,14 @@ private:
   Alter_info(const Alter_info &rhs);            // not implemented
 };
 
+typedef struct struct_slave_connection
+{
+  char *user;
+  char *password;
+  char *plugin_auth;
+  char *plugin_dir;
+} LEX_SLAVE_CONNECTION;
+
 struct st_sp_chistics
 {
   LEX_STRING comment;
@@ -2122,6 +2130,7 @@ struct LEX: public Query_tables_list
   HA_CREATE_INFO create_info;
   KEY_CREATE_INFO key_create_info;
   LEX_MASTER_INFO mi;				// used by CHANGE MASTER
+  LEX_SLAVE_CONNECTION slave_connection;
   LEX_SERVER_OPTIONS server_options;
   USER_RESOURCES mqh;
   ulong type;

=== modified file 'sql/sql_parse.cc'
--- a/sql/sql_parse.cc	2011-04-01 14:04:52 +0000
+++ b/sql/sql_parse.cc	2011-04-18 06:30:30 +0000
@@ -2590,7 +2590,40 @@ end_with_restore_list:
   case SQLCOM_SLAVE_START:
   {
     mysql_mutex_lock(&LOCK_active_mi);
-    start_slave(thd,active_mi,1 /* net report*/);
+
+    if (lex->slave_connection.user)
+    {
+      active_mi->set_start_user_configured(TRUE);
+      active_mi->set_user(lex->slave_connection.user);
+    }
+    if (lex->slave_connection.password)
+    {
+      thd->set_query(active_mi->start_command,
+                     strlen(active_mi->start_command));
+      active_mi->set_start_user_configured(TRUE);
+      active_mi->set_password(lex->slave_connection.password,
+                              strlen(lex->slave_connection.password));
+    }
+    if (lex->slave_connection.plugin_auth)
+    {
+      active_mi->set_start_plugin_configured(TRUE);
+      active_mi->set_plugin_auth(lex->slave_connection.plugin_auth);
+    }
+    if (lex->slave_connection.plugin_dir)
+    {
+      active_mi->set_start_plugin_configured(TRUE);
+      active_mi->set_plugin_dir(lex->slave_connection.plugin_dir);
+    }
+
+    if (start_slave(thd, active_mi, 1 /* net report*/))
+    {
+      /*
+        Clean information used to start slave in order to avoid
+        security issues.
+      */
+      active_mi->clean_start_information();
+    }
+
     mysql_mutex_unlock(&LOCK_active_mi);
     break;
   }

=== modified file 'sql/sql_yacc.yy'
--- a/sql/sql_yacc.yy	2011-03-09 20:54:55 +0000
+++ b/sql/sql_yacc.yy	2011-04-18 06:30:30 +0000
@@ -919,6 +919,7 @@ bool my_yyoverflow(short **a, YYSTYPE **
 %token  DECIMAL_SYM                   /* SQL-2003-R */
 %token  DECLARE_SYM                   /* SQL-2003-R */
 %token  DEFAULT                       /* SQL-2003-R */
+%token  DEFAULT_AUTH_SYM              /* INTERNAL */
 %token  DEFINER_SYM
 %token  DELAYED_SYM
 %token  DELAY_KEY_WRITE_SYM
@@ -1176,8 +1177,9 @@ bool my_yyoverflow(short **a, YYSTYPE **
 %token  PARTITIONING_SYM
 %token  PASSWORD
 %token  PHASE_SYM
-%token  PLUGINS_SYM
+%token  PLUGIN_DIR_SYM                /* INTERNAL */
 %token  PLUGIN_SYM
+%token  PLUGINS_SYM
 %token  POINT_SYM
 %token  POLYGON
 %token  PORT_SYM
@@ -6910,6 +6912,8 @@ slave:
           }
           slave_until
           {}
+          slave_connection_opts
+          {}
         | STOP_SYM SLAVE slave_thread_opts
           {
             LEX *lex=Lex;
@@ -6936,6 +6940,50 @@ start_transaction_opts:
           }
         ;
 
+slave_connection_opts:
+          slave_user_name_opt slave_user_pass_opt
+          slave_plugin_auth_opt slave_plugin_dir_opt
+        ;
+
+slave_user_name_opt:
+          {
+            Lex->slave_connection.user= 0;
+          }
+        | USER EQ TEXT_STRING_sys
+          {
+            Lex->slave_connection.user= $3.str;
+          }
+        ;
+
+slave_user_pass_opt:
+          {
+            Lex->slave_connection.password= 0;
+          }
+        | PASSWORD EQ TEXT_STRING_sys
+          {
+            Lex->slave_connection.password= $3.str;
+          }
+
+slave_plugin_auth_opt:
+          {
+            Lex->slave_connection.plugin_auth= 0;
+          }
+        | DEFAULT_AUTH_SYM EQ TEXT_STRING_sys
+          {
+            Lex->slave_connection.plugin_auth= $3.str;
+          }
+        ;
+
+slave_plugin_dir_opt:
+          {
+            Lex->slave_connection.plugin_dir= 0;
+          }
+        | PLUGIN_DIR_SYM EQ TEXT_STRING_sys
+          {
+            Lex->slave_connection.plugin_dir= $3.str;
+          }
+        ;
+
 slave_thread_opts:
           { Lex->slave_thd_opt= 0; }
           slave_thread_opt_list
@@ -12623,6 +12671,7 @@ keyword_sp:
         | DATETIME                 {}
         | DATE_SYM                 {}
         | DAY_SYM                  {}
+        | DEFAULT_AUTH_SYM         {}
         | DEFINER_SYM              {}
         | DELAY_KEY_WRITE_SYM      {}
         | DES_KEY_FILE             {}
@@ -12747,6 +12796,7 @@ keyword_sp:
         | PARTITIONS_SYM           {}
         | PASSWORD                 {}
         | PHASE_SYM                {}
+        | PLUGIN_DIR_SYM           {}
         | PLUGIN_SYM               {}
         | PLUGINS_SYM              {}
         | POINT_SYM                {}


Attachment: [text/bzr-bundle] bzr/alfranio.correia@oracle.com-20110418063030-38o7r2l5fxt0e459.bundle
Thread
bzr commit into mysql-trunk branch (alfranio.correia:3345) WL#4143Alfranio Correia18 Apr