summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGeorgi Kodinov <Georgi.Kodinov@Oracle.com>2012-07-05 09:55:20 +0300
committerGeorgi Kodinov <Georgi.Kodinov@Oracle.com>2012-07-05 09:55:20 +0300
commit06f6e4fe957c6edd7b3655d4987d0fbd67cdb9d6 (patch)
tree79bc42ec937ff1b148e0a6b66924d7a3d796b805
parent9ce35ffc8677ff3c7171576497ed6c7330000b72 (diff)
downloadmariadb-git-06f6e4fe957c6edd7b3655d4987d0fbd67cdb9d6.tar.gz
Bug #12998841: libmysql divulges plaintext password upon request in 5.5
1. Clear text password client plugin disabled by default. 2. Added an environment variable LIBMYSQL_ENABLE_CLEARTEXT_PLUGIN, that when set to something starting with '1', 'Y' or 'y' will enable the clear text plugin for all connections. 3. Added a new mysql_options() option : MYSQL_ENABLE_CLEARTEXT_PLUGIN that takes an my_bool argument. When the value of the argument is non-zero the clear text plugin is enabled for this connection only. 4. Added an enable-cleartext-plugin config file option that takes a numeric argument. If the numeric value of the numeric argument is non-zero the clear text plugin is enabled for the connection 5. Added a boolean command line option "--enable_cleartext_plugin" to mysql, mysqlslap and mysqladmin. When specified it will call mysql_options with the effect of #3 6. Added a new CLEARTEXT option to the connect command in mysqltest. When specified it will enable the cleartext plugin for usage. 7. Added test cases and updated existing ones that need the clear text plugin.
-rw-r--r--client/client_priv.h1
-rw-r--r--client/mysql.cc13
-rw-r--r--client/mysqladmin.cc13
-rw-r--r--client/mysqlslap.c12
-rw-r--r--client/mysqltest.cc8
-rw-r--r--include/mysql.h3
-rw-r--r--include/mysql.h.pp3
-rw-r--r--include/sql_common.h2
-rw-r--r--mysql-test/t/plugin_auth.test4
-rw-r--r--sql-common/client.c69
-rw-r--r--sql-common/client_plugin.c5
11 files changed, 119 insertions, 14 deletions
diff --git a/client/client_priv.h b/client/client_priv.h
index b776dcf8014..2362811d2b3 100644
--- a/client/client_priv.h
+++ b/client/client_priv.h
@@ -87,6 +87,7 @@ enum options_client
OPT_PLUGIN_DIR,
OPT_DEFAULT_AUTH,
OPT_DEFAULT_PLUGIN,
+ OPT_ENABLE_CLEARTEXT_PLUGIN,
OPT_MAX_CLIENT_OPTION
};
diff --git a/client/mysql.cc b/client/mysql.cc
index b6bc2f4b68f..630c6215603 100644
--- a/client/mysql.cc
+++ b/client/mysql.cc
@@ -148,6 +148,8 @@ static my_bool column_types_flag;
static my_bool preserve_comments= 0;
static ulong opt_max_allowed_packet, opt_net_buffer_length;
static uint verbose=0,opt_silent=0,opt_mysql_port=0, opt_local_infile=0;
+static uint opt_enable_cleartext_plugin= 0;
+static my_bool using_opt_enable_cleartext_plugin= 0;
static uint my_end_arg;
static char * opt_mysql_unix_port=0;
static int connect_flag=CLIENT_INTERACTIVE;
@@ -1409,6 +1411,10 @@ static struct my_option my_long_options[] =
&default_charset, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"delimiter", OPT_DELIMITER, "Delimiter to be used.", &delimiter_str,
&delimiter_str, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ {"enable_cleartext_plugin", OPT_ENABLE_CLEARTEXT_PLUGIN,
+ "Enable/disable the clear text authentication plugin.",
+ &opt_enable_cleartext_plugin, &opt_enable_cleartext_plugin,
+ 0, GET_BOOL, OPT_ARG, 0, 0, 0, 0, 0, 0},
{"execute", 'e', "Execute command and quit. (Disables --force and history file.)", 0,
0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"vertical", 'E', "Print the output of a query (rows) vertically.",
@@ -1636,6 +1642,9 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
case OPT_LOCAL_INFILE:
using_opt_local_infile=1;
break;
+ case OPT_ENABLE_CLEARTEXT_PLUGIN:
+ using_opt_enable_cleartext_plugin= TRUE;
+ break;
case OPT_TEE:
if (argument == disabled_my_option)
{
@@ -4321,6 +4330,10 @@ sql_real_connect(char *host,char *database,char *user,char *password,
if (opt_default_auth && *opt_default_auth)
mysql_options(&mysql, MYSQL_DEFAULT_AUTH, opt_default_auth);
+ if (using_opt_enable_cleartext_plugin)
+ mysql_options(&mysql, MYSQL_ENABLE_CLEARTEXT_PLUGIN,
+ (char*) &opt_enable_cleartext_plugin);
+
if (!mysql_real_connect(&mysql, host, user, password,
database, opt_mysql_port, opt_mysql_unix_port,
connect_flag | CLIENT_MULTI_STATEMENTS))
diff --git a/client/mysqladmin.cc b/client/mysqladmin.cc
index 3f33c25e664..321efd36642 100644
--- a/client/mysqladmin.cc
+++ b/client/mysqladmin.cc
@@ -43,6 +43,8 @@ static uint opt_count_iterations= 0, my_end_arg;
static ulong opt_connect_timeout, opt_shutdown_timeout;
static char * unix_port=0;
static char *opt_plugin_dir= 0, *opt_default_auth= 0;
+static uint opt_enable_cleartext_plugin= 0;
+static my_bool using_opt_enable_cleartext_plugin= 0;
#ifdef HAVE_SMEM
static char *shared_memory_base_name=0;
@@ -212,6 +214,10 @@ static struct my_option my_long_options[] =
"Default authentication client-side plugin to use.",
&opt_default_auth, &opt_default_auth, 0,
GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ {"enable_cleartext_plugin", OPT_ENABLE_CLEARTEXT_PLUGIN,
+ "Enable/disable the clear text authentication plugin.",
+ &opt_enable_cleartext_plugin, &opt_enable_cleartext_plugin,
+ 0, GET_BOOL, OPT_ARG, 0, 0, 0, 0, 0, 0},
{ 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
};
@@ -282,6 +288,9 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
opt_protocol= find_type_or_exit(argument, &sql_protocol_typelib,
opt->name);
break;
+ case OPT_ENABLE_CLEARTEXT_PLUGIN:
+ using_opt_enable_cleartext_plugin= TRUE;
+ break;
}
if (error)
{
@@ -354,6 +363,10 @@ int main(int argc,char *argv[])
if (opt_default_auth && *opt_default_auth)
mysql_options(&mysql, MYSQL_DEFAULT_AUTH, opt_default_auth);
+ if (using_opt_enable_cleartext_plugin)
+ mysql_options(&mysql, MYSQL_ENABLE_CLEARTEXT_PLUGIN,
+ (char*) &opt_enable_cleartext_plugin);
+
if (sql_connect(&mysql, option_wait))
{
/*
diff --git a/client/mysqlslap.c b/client/mysqlslap.c
index a2c01b85b5a..ac1cc31733c 100644
--- a/client/mysqlslap.c
+++ b/client/mysqlslap.c
@@ -125,6 +125,8 @@ static char *host= NULL, *opt_password= NULL, *user= NULL,
*post_system= NULL,
*opt_mysql_unix_port= NULL;
static char *opt_plugin_dir= 0, *opt_default_auth= 0;
+static uint opt_enable_cleartext_plugin= 0;
+static my_bool using_opt_enable_cleartext_plugin= 0;
const char *delimiter= "\n";
@@ -348,6 +350,9 @@ int main(int argc, char **argv)
if (opt_default_auth && *opt_default_auth)
mysql_options(&mysql, MYSQL_DEFAULT_AUTH, opt_default_auth);
+ if (using_opt_enable_cleartext_plugin)
+ mysql_options(&mysql, MYSQL_ENABLE_CLEARTEXT_PLUGIN,
+ (char*) &opt_enable_cleartext_plugin);
if (!opt_only_print)
{
if (!(mysql_real_connect(&mysql, host, user, opt_password,
@@ -603,6 +608,10 @@ static struct my_option my_long_options[] =
"Detach (close and reopen) connections after X number of requests.",
&detach_rate, &detach_rate, 0, GET_UINT, REQUIRED_ARG,
0, 0, 0, 0, 0, 0},
+ {"enable_cleartext_plugin", OPT_ENABLE_CLEARTEXT_PLUGIN,
+ "Enable/disable the clear text authentication plugin.",
+ &opt_enable_cleartext_plugin, &opt_enable_cleartext_plugin,
+ 0, GET_BOOL, OPT_ARG, 0, 0, 0, 0, 0, 0},
{"engine", 'e', "Storage engine to use for creating the table.",
&default_engine, &default_engine, 0,
GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
@@ -761,6 +770,9 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
case 'I': /* Info */
usage();
exit(0);
+ case OPT_ENABLE_CLEARTEXT_PLUGIN:
+ using_opt_enable_cleartext_plugin= TRUE;
+ break;
}
DBUG_RETURN(0);
}
diff --git a/client/mysqltest.cc b/client/mysqltest.cc
index b1784fdc7b6..34d8edcbe0b 100644
--- a/client/mysqltest.cc
+++ b/client/mysqltest.cc
@@ -5456,7 +5456,7 @@ void do_connect(struct st_command *command)
int con_port= opt_port;
char *con_options;
my_bool con_ssl= 0, con_compress= 0;
- my_bool con_pipe= 0, con_shm= 0;
+ my_bool con_pipe= 0, con_shm= 0, con_cleartext_enable= 0;
struct st_connection* con_slot;
static DYNAMIC_STRING ds_connection_name;
@@ -5546,6 +5546,8 @@ void do_connect(struct st_command *command)
con_pipe= 1;
else if (!strncmp(con_options, "SHM", 3))
con_shm= 1;
+ else if (!strncmp(con_options, "CLEARTEXT", 9))
+ con_cleartext_enable= 1;
else
die("Illegal option to connect: %.*s",
(int) (end - con_options), con_options);
@@ -5642,6 +5644,10 @@ void do_connect(struct st_command *command)
if (ds_default_auth.length)
mysql_options(&con_slot->mysql, MYSQL_DEFAULT_AUTH, ds_default_auth.str);
+
+ if (con_cleartext_enable)
+ mysql_options(&con_slot->mysql, MYSQL_ENABLE_CLEARTEXT_PLUGIN,
+ (char*) &con_cleartext_enable);
/* Special database to allow one to connect without a database name */
if (ds_database.length && !strcmp(ds_database.str,"*NO-ONE*"))
dynstr_set(&ds_database, "");
diff --git a/include/mysql.h b/include/mysql.h
index cff8c647152..0ed35413a1c 100644
--- a/include/mysql.h
+++ b/include/mysql.h
@@ -166,7 +166,8 @@ enum mysql_option
MYSQL_OPT_USE_REMOTE_CONNECTION, MYSQL_OPT_USE_EMBEDDED_CONNECTION,
MYSQL_OPT_GUESS_CONNECTION, MYSQL_SET_CLIENT_IP, MYSQL_SECURE_AUTH,
MYSQL_REPORT_DATA_TRUNCATION, MYSQL_OPT_RECONNECT,
- MYSQL_OPT_SSL_VERIFY_SERVER_CERT, MYSQL_PLUGIN_DIR, MYSQL_DEFAULT_AUTH
+ MYSQL_OPT_SSL_VERIFY_SERVER_CERT, MYSQL_PLUGIN_DIR, MYSQL_DEFAULT_AUTH,
+ MYSQL_ENABLE_CLEARTEXT_PLUGIN
};
/**
diff --git a/include/mysql.h.pp b/include/mysql.h.pp
index 15ec563dfc2..c2c5ba35044 100644
--- a/include/mysql.h.pp
+++ b/include/mysql.h.pp
@@ -262,7 +262,8 @@ enum mysql_option
MYSQL_OPT_USE_REMOTE_CONNECTION, MYSQL_OPT_USE_EMBEDDED_CONNECTION,
MYSQL_OPT_GUESS_CONNECTION, MYSQL_SET_CLIENT_IP, MYSQL_SECURE_AUTH,
MYSQL_REPORT_DATA_TRUNCATION, MYSQL_OPT_RECONNECT,
- MYSQL_OPT_SSL_VERIFY_SERVER_CERT, MYSQL_PLUGIN_DIR, MYSQL_DEFAULT_AUTH
+ MYSQL_OPT_SSL_VERIFY_SERVER_CERT, MYSQL_PLUGIN_DIR, MYSQL_DEFAULT_AUTH,
+ MYSQL_ENABLE_CLEARTEXT_PLUGIN
};
struct st_mysql_options_extention;
struct st_mysql_options {
diff --git a/include/sql_common.h b/include/sql_common.h
index 307b443d6d6..a2ea3ac45e7 100644
--- a/include/sql_common.h
+++ b/include/sql_common.h
@@ -31,6 +31,7 @@ extern const char *not_error_sqlstate;
struct st_mysql_options_extention {
char *plugin_dir;
char *default_auth;
+ my_bool enable_cleartext_plugin;
};
typedef struct st_mysql_methods
@@ -104,6 +105,7 @@ int mysql_client_plugin_init();
void mysql_client_plugin_deinit();
struct st_mysql_client_plugin;
extern struct st_mysql_client_plugin *mysql_client_builtins[];
+extern my_bool libmysql_cleartext_plugin_enabled;
#ifdef __cplusplus
}
diff --git a/mysql-test/t/plugin_auth.test b/mysql-test/t/plugin_auth.test
index f169360cf2e..75d3ef3e807 100644
--- a/mysql-test/t/plugin_auth.test
+++ b/mysql-test/t/plugin_auth.test
@@ -422,10 +422,10 @@ CREATE USER uplain@localhost IDENTIFIED WITH 'cleartext_plugin_server'
--echo ## test plugin auth
--disable_query_log
--error ER_ACCESS_DENIED_ERROR : this should fail : no grant
-connect(cleartext_fail_con,localhost,uplain,cleartext_test2);
+connect(cleartext_fail_con,localhost,uplain,cleartext_test2,,,,CLEARTEXT);
--enable_query_log
-connect(cleartext_con,localhost,uplain,cleartext_test);
+connect(cleartext_con,localhost,uplain,cleartext_test,,,,CLEARTEXT);
connection cleartext_con;
select USER(),CURRENT_USER();
diff --git a/sql-common/client.c b/sql-common/client.c
index 08f4bfb1151..381768834cd 100644
--- a/sql-common/client.c
+++ b/sql-common/client.c
@@ -1136,7 +1136,8 @@ static const char *default_options[]=
"connect-timeout", "local-infile", "disable-local-infile",
"ssl-cipher", "max-allowed-packet", "protocol", "shared-memory-base-name",
"multi-results", "multi-statements", "multi-queries", "secure-auth",
- "report-data-truncation", "plugin-dir", "default-auth",
+ "report-data-truncation", "plugin-dir", "default-auth",
+ "enable-cleartext-plugin",
NullS
};
enum option_id {
@@ -1148,6 +1149,7 @@ enum option_id {
OPT_ssl_cipher, OPT_max_allowed_packet, OPT_protocol, OPT_shared_memory_base_name,
OPT_multi_results, OPT_multi_statements, OPT_multi_queries, OPT_secure_auth,
OPT_report_data_truncation, OPT_plugin_dir, OPT_default_auth,
+ OPT_enable_cleartext_plugin,
OPT_keep_this_one_last
};
@@ -1180,14 +1182,27 @@ static int add_init_command(struct st_mysql_options *options, const char *cmd)
return 0;
}
-#define EXTENSION_SET_STRING(OPTS, X, STR) \
- if ((OPTS)->extension) \
- my_free((OPTS)->extension->X); \
- else \
+#define ALLOCATE_EXTENSIONS(OPTS) \
(OPTS)->extension= (struct st_mysql_options_extention *) \
my_malloc(sizeof(struct st_mysql_options_extention), \
- MYF(MY_WME | MY_ZEROFILL)); \
- (OPTS)->extension->X= my_strdup((STR), MYF(MY_WME));
+ MYF(MY_WME | MY_ZEROFILL)) \
+
+#define ENSURE_EXTENSIONS_PRESENT(OPTS) \
+ do { \
+ if (!(OPTS)->extension) \
+ ALLOCATE_EXTENSIONS(OPTS); \
+ } while (0)
+
+
+#define EXTENSION_SET_STRING(OPTS, X, STR) \
+ do { \
+ if ((OPTS)->extension) \
+ my_free((OPTS)->extension->X); \
+ else \
+ ALLOCATE_EXTENSIONS(OPTS); \
+ (OPTS)->extension->X= ((STR) != NULL) ? \
+ my_strdup((STR), MYF(MY_WME)) : NULL; \
+ } while (0)
void mysql_read_default_options(struct st_mysql_options *options,
const char *filename,const char *group)
@@ -1386,6 +1401,12 @@ void mysql_read_default_options(struct st_mysql_options *options,
case OPT_default_auth:
EXTENSION_SET_STRING(options, default_auth, opt_arg);
break;
+
+ case OPT_enable_cleartext_plugin:
+ ENSURE_EXTENSIONS_PRESENT(options);
+ options->extension->enable_cleartext_plugin=
+ (!opt_arg || atoi(opt_arg) != 0) ? TRUE : FALSE;
+
default:
DBUG_PRINT("warning",("unknown option: %s",option[0]));
}
@@ -2782,6 +2803,27 @@ static void client_mpvio_info(MYSQL_PLUGIN_VIO *vio,
mpvio_info(mpvio->mysql->net.vio, info);
}
+
+my_bool libmysql_cleartext_plugin_enabled= 0;
+
+static my_bool check_plugin_enabled(MYSQL *mysql, auth_plugin_t *plugin)
+{
+ if (plugin == &clear_password_client_plugin &&
+ (!libmysql_cleartext_plugin_enabled &&
+ (!mysql->options.extension ||
+ !mysql->options.extension->enable_cleartext_plugin)))
+ {
+ set_mysql_extended_error(mysql, CR_AUTH_PLUGIN_CANNOT_LOAD,
+ unknown_sqlstate,
+ ER(CR_AUTH_PLUGIN_CANNOT_LOAD),
+ clear_password_client_plugin.name,
+ "plugin not enabled");
+ return TRUE;
+ }
+ return FALSE;
+}
+
+
/**
Client side of the plugin driver authentication.
@@ -2824,6 +2866,9 @@ int run_plugin_auth(MYSQL *mysql, char *data, uint data_len,
auth_plugin_name= auth_plugin->name;
}
+ if (check_plugin_enabled(mysql, auth_plugin))
+ DBUG_RETURN(1);
+
DBUG_PRINT ("info", ("using plugin %s", auth_plugin_name));
mysql->net.last_errno= 0; /* just in case */
@@ -2915,6 +2960,9 @@ int run_plugin_auth(MYSQL *mysql, char *data, uint data_len,
auth_plugin_name, MYSQL_CLIENT_AUTHENTICATION_PLUGIN)))
DBUG_RETURN (1);
+ if (check_plugin_enabled(mysql, auth_plugin))
+ DBUG_RETURN(1);
+
mpvio.plugin= auth_plugin;
res= auth_plugin->authenticate_user((struct st_plugin_vio *)&mpvio, mysql);
@@ -4117,6 +4165,11 @@ mysql_options(MYSQL *mysql,enum mysql_option option, const void *arg)
case MYSQL_DEFAULT_AUTH:
EXTENSION_SET_STRING(&mysql->options, default_auth, arg);
break;
+ case MYSQL_ENABLE_CLEARTEXT_PLUGIN:
+ ENSURE_EXTENSIONS_PRESENT(&mysql->options);
+ mysql->options.extension->enable_cleartext_plugin=
+ (*(my_bool*) arg) ? TRUE : FALSE;
+ break;
default:
DBUG_RETURN(1);
}
@@ -4336,5 +4389,3 @@ static int clear_password_auth_client(MYSQL_PLUGIN_VIO *vio, MYSQL *mysql)
return res ? CR_ERROR : CR_OK;
}
-
-
diff --git a/sql-common/client_plugin.c b/sql-common/client_plugin.c
index 4016f0744be..75faeb7ee97 100644
--- a/sql-common/client_plugin.c
+++ b/sql-common/client_plugin.c
@@ -197,6 +197,10 @@ err1:
static void load_env_plugins(MYSQL *mysql)
{
char *plugs, *free_env, *s= getenv("LIBMYSQL_PLUGINS");
+ char *enable_cleartext_plugin= getenv("LIBMYSQL_ENABLE_CLEARTEXT_PLUGIN");
+
+ if (enable_cleartext_plugin && strchr("1Yy", enable_cleartext_plugin[0]))
+ libmysql_cleartext_plugin_enabled= 1;
/* no plugins to load */
if(!s)
@@ -212,6 +216,7 @@ static void load_env_plugins(MYSQL *mysql)
} while (s);
my_free(free_env);
+
}
/********** extern functions to be used by libmysql *********************/