Merge kosipov@bk-internal.mysql.com:/home/bk/mysql-4.1

into oak.local:/home/kostja/mysql/mysql-4.1-root
This commit is contained in:
kostja@oak.local 2003-09-03 16:44:40 +04:00
commit 711a3f6806
56 changed files with 1404 additions and 1548 deletions

View file

@ -23,6 +23,7 @@
.vimrc .vimrc
50 50
=6 =6
BUILD/compile-pentium-maintainer
BitKeeper/etc/config BitKeeper/etc/config
BitKeeper/etc/csets BitKeeper/etc/csets
BitKeeper/etc/csets-in BitKeeper/etc/csets-in
@ -30,6 +31,8 @@ BitKeeper/etc/csets-out
BitKeeper/etc/gone BitKeeper/etc/gone
BitKeeper/etc/level BitKeeper/etc/level
BitKeeper/etc/pushed BitKeeper/etc/pushed
BitKeeper/post-commit
BitKeeper/post-commit-manual
BitKeeper/tmp/* BitKeeper/tmp/*
BitKeeper/tmp/bkr3sAHD BitKeeper/tmp/bkr3sAHD
BitKeeper/tmp/gone BitKeeper/tmp/gone
@ -223,6 +226,7 @@ bkpull.log.5
bkpull.log.6 bkpull.log.6
bkpush.log bkpush.log
build.log build.log
build_tags.sh
client/insert_test client/insert_test
client/log_event.cc client/log_event.cc
client/log_event.h client/log_event.h
@ -311,6 +315,8 @@ libmysql_r/conf_to_src
libmysql_r/my_static.h libmysql_r/my_static.h
libmysql_r/mysys_priv.h libmysql_r/mysys_priv.h
libmysqld/backup_dir libmysqld/backup_dir
libmysqld/client.c
libmysqld/client_settings.h
libmysqld/convert.cc libmysqld/convert.cc
libmysqld/derror.cc libmysqld/derror.cc
libmysqld/errmsg.c libmysqld/errmsg.c
@ -355,6 +361,7 @@ libmysqld/item_sum.cc
libmysqld/item_timefunc.cc libmysqld/item_timefunc.cc
libmysqld/item_uniq.cc libmysqld/item_uniq.cc
libmysqld/key.cc libmysqld/key.cc
libmysqld/libmysql.c
libmysqld/lock.cc libmysqld/lock.cc
libmysqld/log.cc libmysqld/log.cc
libmysqld/log_event.cc libmysqld/log_event.cc
@ -366,6 +373,7 @@ libmysqld/net_serv.cc
libmysqld/opt_ft.cc libmysqld/opt_ft.cc
libmysqld/opt_range.cc libmysqld/opt_range.cc
libmysqld/opt_sum.cc libmysqld/opt_sum.cc
libmysqld/pack.c
libmysqld/password.c libmysqld/password.c
libmysqld/procedure.cc libmysqld/procedure.cc
libmysqld/protocol.cc libmysqld/protocol.cc
@ -483,6 +491,7 @@ mysys/#mf_iocache.c#
mysys/charset2html mysys/charset2html
mysys/getopt.c mysys/getopt.c
mysys/getopt1.c mysys/getopt1.c
mysys/main.cc
mysys/ste5KbMa mysys/ste5KbMa
mysys/test_charset mysys/test_charset
mysys/test_dir mysys/test_dir
@ -586,6 +595,7 @@ stamp-h1
stamp-h2 stamp-h2
stamp-h3 stamp-h3
stamp-h4 stamp-h4
start_mysqld.sh
strings/conf_to_src strings/conf_to_src
strings/ctype_autoconf.c strings/ctype_autoconf.c
strings/ctype_extra_sources.c strings/ctype_extra_sources.c
@ -612,6 +622,7 @@ support-files/mysql.spec
tags tags
test_xml test_xml
tests/client_test tests/client_test
tests/connect_test
thread_test thread_test
tmp/* tmp/*
tools/my_vsnprintf.c tools/my_vsnprintf.c
@ -623,7 +634,3 @@ vio/test-ssl
vio/test-sslclient vio/test-sslclient
vio/test-sslserver vio/test-sslserver
vio/viotest-ssl vio/viotest-ssl
libmysqld/client.c
libmysqld/client_settings.h
libmysqld/libmysql.c
libmysqld/pack.c

View file

@ -769,9 +769,12 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
return 1; return 1;
} }
if (argv[1][0]) if (argv[1][0])
make_scrambled_password(crypted_pw,argv[1], {
(find_type(argv[0], &command_typelib, 2) == if (find_type(argv[0], &command_typelib, 2) == ADMIN_OLD_PASSWORD)
ADMIN_OLD_PASSWORD), &rand_st); make_scrambled_password_323(crypted_pw, argv[1]);
else
make_scrambled_password(crypted_pw, argv[1]);
}
else else
crypted_pw[0]=0; /* No password */ crypted_pw[0]=0; /* No password */
sprintf(buff,"set password='%s',sql_log_off=0",crypted_pw); sprintf(buff,"set password='%s',sql_log_off=0",crypted_pw);

View file

@ -229,7 +229,9 @@ typedef struct st_mysql
enum mysql_status status; enum mysql_status status;
my_bool free_me; /* If free in mysql_close */ my_bool free_me; /* If free in mysql_close */
my_bool reconnect; /* set to 1 if automatic reconnect */ my_bool reconnect; /* set to 1 if automatic reconnect */
char scramble_buff[21]; /* New protocol requires longer scramble*/
/* session-wide random string */
char scramble[SCRAMBLE_LENGTH+1];
/* /*
Set if this is the original connection, not a master or a slave we have Set if this is the original connection, not a master or a slave we have

View file

@ -49,8 +49,15 @@ enum enum_server_command
}; };
#define SCRAMBLE_LENGTH 8 /*
#define SCRAMBLE41_LENGTH 20 Length of random string sent by server on handshake; this is also length of
obfuscated password, recieved from client
*/
#define SCRAMBLE_LENGTH 20
#define SCRAMBLE_LENGTH_323 8
/* length of password stored in the db: new passwords are preceeded with '*' */
#define SCRAMBLED_PASSWORD_CHAR_LENGTH (SCRAMBLE_LENGTH*2+1)
#define SCRAMBLED_PASSWORD_CHAR_LENGTH_323 (SCRAMBLE_LENGTH_323*2)
#define NOT_NULL_FLAG 1 /* Field can't be NULL */ #define NOT_NULL_FLAG 1 /* Field can't be NULL */
@ -302,31 +309,34 @@ extern "C" {
extern unsigned long max_allowed_packet; extern unsigned long max_allowed_packet;
extern unsigned long net_buffer_length; extern unsigned long net_buffer_length;
void randominit(struct rand_struct *,unsigned long seed1, /*
unsigned long seed2); These functions are used for authentication by client and server and
implemented in sql/password.c
*/
void randominit(struct rand_struct *, unsigned long seed1,
unsigned long seed2);
double my_rnd(struct rand_struct *); double my_rnd(struct rand_struct *);
void make_scrambled_password(char *to,const char *password, void create_random_string(char *to, uint length, struct rand_struct *rand_st);
my_bool force_old_scramble,struct rand_struct *rand_st);
int get_password_length(my_bool force_old_scramble); void hash_password(ulong *to, const char *password, uint password_len);
char get_password_version(const char* password); void make_scrambled_password_323(char *to, const char *password);
void create_random_string(int length,struct rand_struct *rand_st,char* target); void scramble_323(char *to, const char *message, const char *password);
my_bool validate_password(const char* password, const char* message, my_bool check_scramble_323(const char *, const char *message,
unsigned long* salt); unsigned long *salt);
void password_hash_stage1(char *to, const char *password); void get_salt_from_password_323(unsigned long *res, const char *password);
void password_hash_stage2(char *to,const char *salt); void make_password_from_salt_323(char *to, const unsigned long *salt);
void password_crypt(const char* from,char* to, const char* password,int length);
void get_hash_and_password(unsigned long* salt, unsigned char pversion,char* hash, void make_scrambled_password(char *to, const char *password);
unsigned char* bin_password); void scramble(char *to, const char *message, const char *password);
void get_salt_from_password(unsigned long *res,const char *password); my_bool check_scramble(const char *reply, const char *message,
void create_key_from_old_password(const char* password,char* key); const unsigned char *hash_stage2);
void make_password_from_salt(char *to, unsigned long *hash_res, void get_salt_from_password(unsigned char *res, const char *password);
unsigned char password_version); void make_password_from_salt(char *to, const unsigned char *hash_stage2);
char *scramble(char *to,const char *message,const char *password,
my_bool old_ver); /* end of password.c */
my_bool check_scramble(const char *, const char *message,
unsigned long *salt,my_bool old_ver);
char *get_tty_password(char *opt_message); char *get_tty_password(char *opt_message);
void hash_password(unsigned long *result, const char *password);
const char *mysql_errno_to_sqlstate(unsigned int mysql_errno); const char *mysql_errno_to_sqlstate(unsigned int mysql_errno);
/* Some other useful functions */ /* Some other useful functions */

View file

@ -290,4 +290,5 @@
#define ER_VARIABLE_IS_NOT_STRUCT 1271 #define ER_VARIABLE_IS_NOT_STRUCT 1271
#define ER_UNKNOWN_COLLATION 1272 #define ER_UNKNOWN_COLLATION 1272
#define ER_SLAVE_IGNORED_SSL_PARAMS 1273 #define ER_SLAVE_IGNORED_SSL_PARAMS 1273
#define ER_ERROR_MESSAGES 274 #define ER_SERVER_IS_IN_SECURE_AUTH_MODE 1274
#define ER_ERROR_MESSAGES 275

View file

@ -604,41 +604,55 @@ my_bool STDCALL mysql_change_user(MYSQL *mysql, const char *user,
/* Store user into the buffer */ /* Store user into the buffer */
end=strmov(end,user)+1; end=strmov(end,user)+1;
/* /* write scrambled password according to server capabilities */
We always start with old type handshake the only difference is message sent if (passwd[0])
If server handles secure connection type we'll not send the real scramble
*/
if (mysql->server_capabilities & CLIENT_SECURE_CONNECTION)
{ {
if (passwd[0]) if (mysql->server_capabilities & CLIENT_SECURE_CONNECTION)
{ {
/* Prepare false scramble */ *end++= SCRAMBLE_LENGTH;
bfill(end, SCRAMBLE_LENGTH, 'x'); scramble(end, mysql->scramble, passwd);
end+=SCRAMBLE_LENGTH; end+= SCRAMBLE_LENGTH;
*end=0; }
else
{
scramble_323(end, mysql->scramble, passwd);
end+= SCRAMBLE_LENGTH_323 + 1;
} }
else /* For empty password */
*end=0; /* zero length scramble */
} }
else else
{ *end++= '\0'; // empty password
/*
Real scramble is only sent to old servers. This can be blocked
by calling mysql_options(MYSQL *, MYSQL_SECURE_CONNECT, (char*) &1);
*/
end=scramble(end, mysql->scramble_buff, passwd,
(my_bool) (mysql->protocol_version == 9));
}
/* Add database if needed */ /* Add database if needed */
end=strmov(end+1,db ? db : ""); end= strmov(end, db ? db : "") + 1;
/* Write authentication package */ /* Write authentication package */
simple_command(mysql,COM_CHANGE_USER, buff,(ulong) (end-buff),1); simple_command(mysql,COM_CHANGE_USER, buff,(ulong) (end-buff),1);
if (mysql_autenticate(mysql, passwd)) NET *net= &mysql->net;
ulong pkt_length= net_safe_read(mysql);
if (pkt_length == packet_error)
goto error; goto error;
if (pkt_length == 1 && net->read_pos[0] == 254 &&
mysql->server_capabilities & CLIENT_SECURE_CONNECTION)
{
/*
By sending this very specific reply server asks us to send scrambled
password in old format. The reply contains scramble_323.
*/
scramble_323(buff, mysql->scramble, passwd);
if (my_net_write(net, buff, SCRAMBLE_LENGTH_323 + 1) || net_flush(net))
{
net->last_errno= CR_SERVER_LOST;
strmov(net->sqlstate, unknown_sqlstate);
strmov(net->last_error,ER(net->last_errno));
goto error;
}
/* Read what server thinks about out new auth message report */
if (net_safe_read(mysql) == packet_error)
goto error;
}
/* Free old connect information */ /* Free old connect information */
my_free(mysql->user,MYF(MY_ALLOW_ZERO_PTR)); my_free(mysql->user,MYF(MY_ALLOW_ZERO_PTR));
my_free(mysql->passwd,MYF(MY_ALLOW_ZERO_PTR)); my_free(mysql->passwd,MYF(MY_ALLOW_ZERO_PTR));

View file

@ -30,6 +30,7 @@ show tables;
Tables_in_test Tables_in_test
update mysql.user set password=old_password("gambling2") where user="test"; update mysql.user set password=old_password("gambling2") where user="test";
flush privileges; flush privileges;
set password=old_password('gambling3');
show tables; show tables;
Tables_in_mysql Tables_in_mysql
columns_priv columns_priv

View file

@ -1,15 +1,79 @@
select length(encrypt('foo', 'ff')) <> 0; select length(encrypt('foo', 'ff')) <> 0;
length(encrypt('foo', 'ff')) <> 0 length(encrypt('foo', 'ff')) <> 0
1 1
select password("a",""), password("a",NULL), password("","a"), password(NULL,"a"); select password('abc');
password("a","") password("a",NULL) password("","a") password(NULL,"a") password('abc')
*2517f7235d68d4ba2e5019c93420523101157a792c01 NULL NULL *0D3CED9BEC10A777AEC23CCC353A8C08A633045E
select password("aaaaaaaaaaaaaaaa","a"), password("a","aaaaaaaaaaaaaaaa"); select password('');
password("aaaaaaaaaaaaaaaa","a") password("a","aaaaaaaaaaaaaaaa") password('')
*2cd3b9a44e9a9994789a30f935c92f45a96c5472f381 *37c7c5c794ff144819f2531bf03c57772cd84e40db09
select old_password('test'), length(password("1")), length(encrypt('test')), encrypt('test','aa'); select old_password('abc');
old_password('test') length(password("1")) length(encrypt('test')) encrypt('test','aa') old_password('abc')
378b243e220ca493 45 13 aaqPiZY5xR5l. 7cd2b5942be28759
select old_password(""), old_password(NULL), password(""), password(NULL); select old_password('');
old_password("") old_password(NULL) password("") password(NULL) old_password('')
NULL NULL
select password('gabbagabbahey');
password('gabbagabbahey')
*B0F99D2963660DD7E16B751EC9EE2F17B6A68FA6
select old_password('idkfa');
old_password('idkfa')
5c078dc54ca0fcca
select length(password('1'));
length(password('1'))
41
select length(encrypt('test'));
length(encrypt('test'))
13
select encrypt('test','aa');
encrypt('test','aa')
aaqPiZY5xR5l.
select old_password(NULL);
old_password(NULL)
NULL
select password(NULL);
password(NULL)
NULL
set global old_passwords=on;
select password('');
password('')
select old_password('');
old_password('')
select password('idkfa');
password('idkfa')
*B669C9DAC3AA6F2254B03CDEF8DFDD6B2D1054BA
select old_password('idkfa');
old_password('idkfa')
5c078dc54ca0fcca
set old_passwords=on;
select password('idkfa');
password('idkfa')
5c078dc54ca0fcca
select old_password('idkfa');
old_password('idkfa')
5c078dc54ca0fcca
set global old_passwords=off;
select password('idkfa');
password('idkfa')
5c078dc54ca0fcca
select old_password('idkfa');
old_password('idkfa')
5c078dc54ca0fcca
set old_passwords=off;
select password('idkfa ');
password('idkfa ')
*2DC31D90647B4C1ABC9231563D2236E96C9A2DB2
select password('idkfa');
password('idkfa')
*B669C9DAC3AA6F2254B03CDEF8DFDD6B2D1054BA
select password(' idkfa');
password(' idkfa')
*12B099E56BB7FE8D43C78FD834A9D1D11178D045
select old_password('idkfa');
old_password('idkfa')
5c078dc54ca0fcca
select old_password(' i d k f a ');
old_password(' i d k f a ')
5c078dc54ca0fcca

View file

@ -48,8 +48,9 @@ flush privileges;
#connect (con1,localhost,test,gambling2,""); #connect (con1,localhost,test,gambling2,"");
#show tables; #show tables;
connect (con1,localhost,test,gambling2,mysql); connect (con1,localhost,test,gambling2,mysql);
set password=old_password('gambling3');
show tables; show tables;
connect (con1,localhost,test,gambling2,test); connect (con1,localhost,test,gambling3,test);
show tables; show tables;
# Re enable this one day if error handling on connect will take place # Re enable this one day if error handling on connect will take place
@ -63,7 +64,9 @@ show tables;
#connect (con1,localhost,test,zorro,); #connect (con1,localhost,test,zorro,);
#--error 1045 #--error 1045
# remove user 'test' so that other tests which may use 'test' # remove user 'test' so that other tests which may use 'test'
# do not depend on this test. # do not depend on this test.
delete from mysql.user where user="test"; delete from mysql.user where user="test";
flush privileges; flush privileges;

View file

@ -4,7 +4,33 @@ select length(encrypt('foo', 'ff')) <> 0;
--replace_result $1$aa$4OSUA5cjdx0RUQ08opV27/ aaqPiZY5xR5l. --replace_result $1$aa$4OSUA5cjdx0RUQ08opV27/ aaqPiZY5xR5l.
# Test new and old password handling functions # Test new and old password handling functions
select password("a",""), password("a",NULL), password("","a"), password(NULL,"a"); select password('abc');
select password("aaaaaaaaaaaaaaaa","a"), password("a","aaaaaaaaaaaaaaaa"); select password('');
select old_password('test'), length(password("1")), length(encrypt('test')), encrypt('test','aa'); select old_password('abc');
select old_password(""), old_password(NULL), password(""), password(NULL); select old_password('');
select password('gabbagabbahey');
select old_password('idkfa');
select length(password('1'));
select length(encrypt('test'));
select encrypt('test','aa');
select old_password(NULL);
select password(NULL);
set global old_passwords=on;
select password('');
select old_password('');
select password('idkfa');
select old_password('idkfa');
set old_passwords=on;
select password('idkfa');
select old_password('idkfa');
set global old_passwords=off;
select password('idkfa');
select old_password('idkfa');
# this test shows that new scrambles honor spaces in passwords:
set old_passwords=off;
select password('idkfa ');
select password('idkfa');
select password(' idkfa');
select old_password('idkfa');
select old_password(' i d k f a ');

View file

@ -108,7 +108,7 @@ then
c_u="$c_u CREATE TABLE user (" c_u="$c_u CREATE TABLE user ("
c_u="$c_u Host char(60) binary DEFAULT '' NOT NULL," c_u="$c_u Host char(60) binary DEFAULT '' NOT NULL,"
c_u="$c_u User char(16) binary DEFAULT '' NOT NULL," c_u="$c_u User char(16) binary DEFAULT '' NOT NULL,"
c_u="$c_u Password char(45) binary DEFAULT '' NOT NULL," c_u="$c_u Password char(41) binary DEFAULT '' NOT NULL,"
c_u="$c_u Select_priv enum('N','Y') DEFAULT 'N' NOT NULL," c_u="$c_u Select_priv enum('N','Y') DEFAULT 'N' NOT NULL,"
c_u="$c_u Insert_priv enum('N','Y') DEFAULT 'N' NOT NULL," c_u="$c_u Insert_priv enum('N','Y') DEFAULT 'N' NOT NULL,"
c_u="$c_u Update_priv enum('N','Y') DEFAULT 'N' NOT NULL," c_u="$c_u Update_priv enum('N','Y') DEFAULT 'N' NOT NULL,"

View file

@ -16,7 +16,7 @@ ALTER TABLE host type=MyISAM;
ALTER TABLE func type=MyISAM; ALTER TABLE func type=MyISAM;
ALTER TABLE columns_priv type=MyISAM; ALTER TABLE columns_priv type=MyISAM;
ALTER TABLE tables_priv type=MyISAM; ALTER TABLE tables_priv type=MyISAM;
ALTER TABLE user change Password Password char(45) not null; ALTER TABLE user change Password Password char(41) not null;
ALTER TABLE user add File_priv enum('N','Y') NOT NULL; ALTER TABLE user add File_priv enum('N','Y') NOT NULL;
CREATE TABLE IF NOT EXISTS func ( CREATE TABLE IF NOT EXISTS func (
name char(64) DEFAULT '' NOT NULL, name char(64) DEFAULT '' NOT NULL,

View file

@ -1391,76 +1391,6 @@ mysql_ssl_free(MYSQL *mysql __attribute__((unused)))
#endif /* HAVE_OPENSSL */ #endif /* HAVE_OPENSSL */
/*
Handle password authentication
*/
my_bool mysql_autenticate(MYSQL *mysql, const char *passwd)
{
ulong pkt_length;
NET *net= &mysql->net;
char buff[SCRAMBLE41_LENGTH];
char password_hash[SCRAMBLE41_LENGTH]; /* Used for storage of stage1 hash */
/* We shall only query server if it expect us to do so */
if ((pkt_length=net_safe_read(mysql)) == packet_error)
goto error;
if (mysql->server_capabilities & CLIENT_SECURE_CONNECTION)
{
/*
This should always happen with new server unless empty password
OK/Error packets have zero as the first char
*/
if (pkt_length == 24 && net->read_pos[0])
{
/* Old passwords will have '*' at the first byte of hash */
if (net->read_pos[0] != '*')
{
/* Build full password hash as it is required to decode scramble */
password_hash_stage1(buff, passwd);
/* Store copy as we'll need it later */
memcpy(password_hash,buff,SCRAMBLE41_LENGTH);
/* Finally hash complete password using hash we got from server */
password_hash_stage2(password_hash,(const char*) net->read_pos);
/* Decypt and store scramble 4 = hash for stage2 */
password_crypt((const char*) net->read_pos+4,mysql->scramble_buff,
password_hash, SCRAMBLE41_LENGTH);
mysql->scramble_buff[SCRAMBLE41_LENGTH]=0;
/* Encode scramble with password. Recycle buffer */
password_crypt(mysql->scramble_buff,buff,buff,SCRAMBLE41_LENGTH);
}
else
{
/* Create password to decode scramble */
create_key_from_old_password(passwd,password_hash);
/* Decypt and store scramble 4 = hash for stage2 */
password_crypt((const char*) net->read_pos+4,mysql->scramble_buff,
password_hash, SCRAMBLE41_LENGTH);
mysql->scramble_buff[SCRAMBLE41_LENGTH]=0;
/* Finally scramble decoded scramble with password */
scramble(buff, mysql->scramble_buff, passwd,0);
}
/* Write second package of authentication */
if (my_net_write(net,buff,SCRAMBLE41_LENGTH) || net_flush(net))
{
net->last_errno= CR_SERVER_LOST;
strmov(net->sqlstate, unknown_sqlstate);
strmov(net->last_error,ER(net->last_errno));
goto error;
}
/* Read what server thinks about out new auth message report */
if (net_safe_read(mysql) == packet_error)
goto error;
}
}
return 0;
error:
return 1;
}
/* /*
Note that the mysql argument must be initialized with mysql_init() Note that the mysql argument must be initialized with mysql_init()
before calling mysql_real_connect ! before calling mysql_real_connect !
@ -1553,7 +1483,7 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
mysql->server_status=SERVER_STATUS_AUTOCOMMIT; mysql->server_status=SERVER_STATUS_AUTOCOMMIT;
/* /*
Grab a socket and connect it to the server Part 0: Grab a socket and connect it to the server
*/ */
#if defined(HAVE_SMEM) #if defined(HAVE_SMEM)
if ((!mysql->options.protocol || if ((!mysql->options.protocol ||
@ -1754,6 +1684,11 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
strmov(net->last_error,ER(net->last_errno)); strmov(net->last_error,ER(net->last_errno));
goto error; goto error;
} }
/*
Part 1: Connection established, read and parse first packet
*/
if ((pkt_length=net_safe_read(mysql)) == packet_error) if ((pkt_length=net_safe_read(mysql)) == packet_error)
goto error; goto error;
@ -1774,8 +1709,13 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
end=strend((char*) net->read_pos+1); end=strend((char*) net->read_pos+1);
mysql->thread_id=uint4korr(end+1); mysql->thread_id=uint4korr(end+1);
end+=5; end+=5;
strmake(mysql->scramble_buff,end,8); /*
end+=9; Scramble is split into two parts because old clients does not understand
long scrambles; here goes the first part.
*/
strmake(mysql->scramble, end, SCRAMBLE_LENGTH_323);
end+= SCRAMBLE_LENGTH_323+1;
if (pkt_length >= (uint) (end+1 - (char*) net->read_pos)) if (pkt_length >= (uint) (end+1 - (char*) net->read_pos))
mysql->server_capabilities=uint2korr(end); mysql->server_capabilities=uint2korr(end);
if (pkt_length >= (uint) (end+18 - (char*) net->read_pos)) if (pkt_length >= (uint) (end+18 - (char*) net->read_pos))
@ -1784,6 +1724,14 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
mysql->server_language=end[2]; mysql->server_language=end[2];
mysql->server_status=uint2korr(end+3); mysql->server_status=uint2korr(end+3);
} }
end+= 18;
if (pkt_length >= (uint) (end + SCRAMBLE_LENGTH - SCRAMBLE_LENGTH_323 + 1 -
(char *) net->read_pos))
strmake(mysql->scramble+SCRAMBLE_LENGTH_323, end,
SCRAMBLE_LENGTH-SCRAMBLE_LENGTH_323);
else
mysql->server_capabilities&= ~CLIENT_SECURE_CONNECTION;
charset_number= mysql->server_language; charset_number= mysql->server_language;
/* Set character set */ /* Set character set */
@ -1860,9 +1808,12 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
mysql->unix_socket=0; mysql->unix_socket=0;
strmov(mysql->server_version,(char*) net->read_pos+1); strmov(mysql->server_version,(char*) net->read_pos+1);
mysql->port=port; mysql->port=port;
client_flag|=mysql->options.client_flag;
/* Send client information for access check */ /*
Part 2: format and send client info to the server for access check
*/
client_flag|=mysql->options.client_flag;
client_flag|=CLIENT_CAPABILITIES; client_flag|=CLIENT_CAPABILITIES;
if (client_flag & CLIENT_MULTI_QUERIES) if (client_flag & CLIENT_MULTI_QUERIES)
client_flag|= CLIENT_MULTI_RESULTS; client_flag|= CLIENT_MULTI_RESULTS;
@ -1949,7 +1900,7 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
mysql->server_status, client_flag)); mysql->server_status, client_flag));
/* This needs to be changed as it's not useful with big packets */ /* This needs to be changed as it's not useful with big packets */
if (user && user[0]) if (user && user[0])
strmake(end,user,32); /* Max user name */ strmake(end,user,USERNAME_LENGTH); /* Max user name */
else else
read_user_name((char*) end); read_user_name((char*) end);
@ -1958,41 +1909,30 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
#include "_cust_libmysql.h" #include "_cust_libmysql.h"
#endif #endif
DBUG_PRINT("info",("user: %s",end)); DBUG_PRINT("info",("user: %s",end));
/* end= strend(end) + 1;
We always start with old type handshake the only difference is message sent if (passwd[0])
If server handles secure connection type we'll not send the real scramble
*/
if (mysql->server_capabilities & CLIENT_SECURE_CONNECTION)
{ {
if (passwd[0]) if (mysql->server_capabilities & CLIENT_SECURE_CONNECTION)
{ {
/* Prepare false scramble */ *end++= SCRAMBLE_LENGTH;
end=strend(end)+1; scramble(end, mysql->scramble, passwd);
bfill(end, SCRAMBLE_LENGTH, 'x'); end+= SCRAMBLE_LENGTH;
end+=SCRAMBLE_LENGTH;
*end=0;
} }
else /* For empty password*/ else
{ {
end=strend(end)+1; scramble_323(end, mysql->scramble, passwd);
*end=0; /* Store zero length scramble */ end+= SCRAMBLE_LENGTH_323 + 1;
} }
} }
else else
{ *end++= '\0'; /* empty password */
/*
Real scramble is only sent to old servers. This can be blocked
by calling mysql_options(MYSQL *, MYSQL_SECURE_CONNECT, (char*) &1);
*/
end=scramble(strend(end)+1, mysql->scramble_buff, passwd,
(my_bool) (mysql->protocol_version == 9));
}
/* Add database if needed */ /* Add database if needed */
if (db && (mysql->server_capabilities & CLIENT_CONNECT_WITH_DB)) if (db && (mysql->server_capabilities & CLIENT_CONNECT_WITH_DB))
{ {
end=strmake(end+1,db,NAME_LEN); end= strmake(end, db, NAME_LEN) + 1;
mysql->db=my_strdup(db,MYF(MY_WME)); mysql->db= my_strdup(db,MYF(MY_WME));
db=0; db= 0;
} }
/* Write authentication package */ /* Write authentication package */
if (my_net_write(net,buff,(ulong) (end-buff)) || net_flush(net)) if (my_net_write(net,buff,(ulong) (end-buff)) || net_flush(net))
@ -2002,10 +1942,36 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
strmov(net->last_error,ER(net->last_errno)); strmov(net->last_error,ER(net->last_errno));
goto error; goto error;
} }
/*
Part 3: Authorization data's been sent. Now server can reply with
OK-packet, or re-request scrambled password.
*/
if (mysql_autenticate(mysql, passwd)) if ((pkt_length=net_safe_read(mysql)) == packet_error)
goto error; goto error;
if (pkt_length == 1 && net->read_pos[0] == 254 &&
mysql->server_capabilities & CLIENT_SECURE_CONNECTION)
{
/*
By sending this very specific reply server asks us to send scrambled
password in old format.
*/
scramble_323(buff, mysql->scramble, passwd);
if (my_net_write(net, buff, SCRAMBLE_LENGTH_323 + 1) || net_flush(net))
{
net->last_errno= CR_SERVER_LOST;
strmov(net->sqlstate, unknown_sqlstate);
strmov(net->last_error,ER(net->last_errno));
goto error;
}
/* Read what server thinks about out new auth message report */
if (net_safe_read(mysql) == packet_error)
goto error;
}
if (client_flag & CLIENT_COMPRESS) /* We will use compression */ if (client_flag & CLIENT_COMPRESS) /* We will use compression */
net->compress=1; net->compress=1;

View file

@ -52,13 +52,6 @@ Item *create_func_ord(Item* a)
return new Item_func_ord(a); return new Item_func_ord(a);
} }
Item *create_func_old_password(Item* a)
{
return new Item_func_old_password(a);
}
Item *create_func_asin(Item* a) Item *create_func_asin(Item* a)
{ {
return new Item_func_asin(a); return new Item_func_asin(a);
@ -332,11 +325,6 @@ Item *create_func_quarter(Item* a)
return new Item_func_quarter(a); return new Item_func_quarter(a);
} }
Item *create_func_password(Item* a)
{
return new Item_func_password(a);
}
Item *create_func_radians(Item *a) Item *create_func_radians(Item *a)
{ {
return new Item_func_units((char*) "radians",a,M_PI/180,0.0); return new Item_func_units((char*) "radians",a,M_PI/180,0.0);

View file

@ -69,14 +69,12 @@ Item *create_func_monthname(Item* a);
Item *create_func_nullif(Item* a, Item *b); Item *create_func_nullif(Item* a, Item *b);
Item *create_func_oct(Item *); Item *create_func_oct(Item *);
Item *create_func_ord(Item* a); Item *create_func_ord(Item* a);
Item *create_func_old_password(Item* a);
Item *create_func_period_add(Item* a, Item *b); Item *create_func_period_add(Item* a, Item *b);
Item *create_func_period_diff(Item* a, Item *b); Item *create_func_period_diff(Item* a, Item *b);
Item *create_func_pi(void); Item *create_func_pi(void);
Item *create_func_pow(Item* a, Item *b); Item *create_func_pow(Item* a, Item *b);
Item *create_func_current_user(void); Item *create_func_current_user(void);
Item *create_func_quarter(Item* a); Item *create_func_quarter(Item* a);
Item *create_func_password(Item* a);
Item *create_func_radians(Item *a); Item *create_func_radians(Item *a);
Item *create_func_release_lock(Item* a); Item *create_func_release_lock(Item* a);
Item *create_func_repeat(Item* a, Item *b); Item *create_func_repeat(Item* a, Item *b);

View file

@ -1327,95 +1327,49 @@ void Item_func_trim::fix_length_and_dec()
} }
/* Item_func_password */
void Item_func_password::fix_length_and_dec()
{
/*
If PASSWORD() was called with only one argument, it depends on a random
number so we need to save this random number into the binary log.
If called with two arguments, it is repeatable.
*/
if (arg_count == 1)
{
THD *thd= current_thd;
thd->rand_used= 1;
thd->rand_saved_seed1= thd->rand.seed1;
thd->rand_saved_seed2= thd->rand.seed2;
}
max_length= get_password_length(use_old_passwords);
}
/*
Password() function has 2 arguments. Second argument can be used
to make results repeatable
*/
String *Item_func_password::val_str(String *str) String *Item_func_password::val_str(String *str)
{ {
struct rand_struct rand_st; // local structure for 2 param version String *res= args[0]->val_str(str);
ulong seed=0; // seed to initialise random generator to
String *res =args[0]->val_str(str);
if ((null_value=args[0]->null_value))
return 0;
if (arg_count == 1)
{
if (res->length() == 0)
return &empty_string;
make_scrambled_password(tmp_value,res->c_ptr(),use_old_passwords,
&current_thd->rand);
str->set(tmp_value,get_password_length(use_old_passwords),res->charset());
return str;
}
else
{
/* We'll need the buffer to get second parameter */
char key_buff[80];
String tmp_key_value(key_buff, sizeof(key_buff), system_charset_info);
String *key =args[1]->val_str(&tmp_key_value);
/* Check second argument for NULL value. First one is already checked */
if ((null_value=args[1]->null_value))
return 0;
/* This shall be done after checking for null for proper results */
if (res->length() == 0)
return &empty_string;
/* Generate the seed first this allows to avoid double allocation */
char* seed_ptr=key->c_ptr();
while (*seed_ptr)
{
seed=(seed*211+*seed_ptr) & 0xffffffffL; /* Use simple hashing */
seed_ptr++;
}
/* Use constants which allow nice random values even with small seed */
randominit(&rand_st,
(ulong) ((ulonglong) seed*111111+33333333L) & (ulong) 0xffffffff,
(ulong) ((ulonglong) seed*1111+55555555L) & (ulong) 0xffffffff);
make_scrambled_password(tmp_value,res->c_ptr(),use_old_passwords,
&rand_st);
str->set(tmp_value,get_password_length(use_old_passwords),res->charset());
return str;
}
}
String *Item_func_old_password::val_str(String *str)
{
String *res =args[0]->val_str(str);
if ((null_value=args[0]->null_value)) if ((null_value=args[0]->null_value))
return 0; return 0;
if (res->length() == 0) if (res->length() == 0)
return &empty_string; return &empty_string;
make_scrambled_password(tmp_value,res->c_ptr(),1,&current_thd->rand); make_scrambled_password(tmp_value, res->c_ptr());
str->set(tmp_value,16,res->charset()); str->set(tmp_value, SCRAMBLED_PASSWORD_CHAR_LENGTH, res->charset());
return str; return str;
} }
char *Item_func_password::alloc(THD *thd, const char *password)
{
char *buff= (char *) thd->alloc(SCRAMBLED_PASSWORD_CHAR_LENGTH+1);
if (buff)
make_scrambled_password(buff, password);
return buff;
}
/* Item_func_old_password */
String *Item_func_old_password::val_str(String *str)
{
String *res= args[0]->val_str(str);
if ((null_value=args[0]->null_value))
return 0;
if (res->length() == 0)
return &empty_string;
make_scrambled_password_323(tmp_value, res->c_ptr());
str->set(tmp_value, SCRAMBLED_PASSWORD_CHAR_LENGTH_323, res->charset());
return str;
}
char *Item_func_old_password::alloc(THD *thd, const char *password)
{
char *buff= (char *) thd->alloc(SCRAMBLED_PASSWORD_CHAR_LENGTH_323+1);
if (buff)
make_scrambled_password_323(buff, password);
return buff;
}
#define bin_to_ascii(c) ((c)>=38?((c)-38+'a'):(c)>=12?((c)-12+'A'):(c)+'.') #define bin_to_ascii(c) ((c)>=38?((c)-38+'a'):(c)>=12?((c)-12+'A'):(c)+'.')

View file

@ -254,30 +254,45 @@ public:
}; };
/*
Item_func_password -- new (4.1.1) PASSWORD() function implementation.
Returns strcat('*', octet2hex(sha1(sha1(password)))). '*' stands for new
password format, sha1(sha1(password) is so-called hash_stage2 value.
Length of returned string is always 41 byte. To find out how entire
authentification procedure works, see comments in password.c.
*/
class Item_func_password :public Item_str_func class Item_func_password :public Item_str_func
{ {
char tmp_value[64]; /* This should be enough for new password format */ char tmp_value[SCRAMBLED_PASSWORD_CHAR_LENGTH+1];
public: public:
Item_func_password(Item *a) :Item_str_func(a) {} Item_func_password(Item *a) :Item_str_func(a) {}
Item_func_password(Item *a, Item *b) :Item_str_func(a,b) {} String *val_str(String *str);
String *val_str(String *); void fix_length_and_dec() { max_length= SCRAMBLED_PASSWORD_CHAR_LENGTH; }
void fix_length_and_dec();
const char *func_name() const { return "password"; } const char *func_name() const { return "password"; }
static char *alloc(THD *thd, const char *password);
}; };
/*
Item_func_old_password -- PASSWORD() implementation used in MySQL 3.21 - 4.0
compatibility mode. This item is created in sql_yacc.yy when
'old_passwords' session variable is set, and to handle OLD_PASSWORD()
function.
*/
class Item_func_old_password :public Item_str_func class Item_func_old_password :public Item_str_func
{ {
char tmp_value[17]; /* old password length +1 */ char tmp_value[SCRAMBLED_PASSWORD_CHAR_LENGTH_323+1];
public: public:
Item_func_old_password(Item *a) :Item_str_func(a) {} Item_func_old_password(Item *a) :Item_str_func(a) {}
String *val_str(String *); String *val_str(String *str);
void fix_length_and_dec() { max_length = get_password_length(1); } void fix_length_and_dec() { max_length= SCRAMBLED_PASSWORD_CHAR_LENGTH_323; }
const char *func_name() const { return "old_password"; } const char *func_name() const { return "old_password"; }
static char *alloc(THD *thd, const char *password);
}; };
class Item_func_des_encrypt :public Item_str_func class Item_func_des_encrypt :public Item_str_func
{ {
String tmp_value; String tmp_value;

View file

@ -294,6 +294,7 @@ static SYMBOL symbols[] = {
{ "NULL", SYM(NULL_SYM),0,0}, { "NULL", SYM(NULL_SYM),0,0},
{ "NUMERIC", SYM(NUMERIC_SYM),0,0}, { "NUMERIC", SYM(NUMERIC_SYM),0,0},
{ "OFFSET", SYM(OFFSET_SYM),0,0}, { "OFFSET", SYM(OFFSET_SYM),0,0},
{ "OLD_PASSWORD", SYM(OLD_PASSWORD),0,0},
{ "ON", SYM(ON),0,0}, { "ON", SYM(ON),0,0},
{ "OPEN", SYM(OPEN_SYM),0,0}, { "OPEN", SYM(OPEN_SYM),0,0},
{ "OPTIMIZE", SYM(OPTIMIZE),0,0}, { "OPTIMIZE", SYM(OPTIMIZE),0,0},
@ -596,7 +597,6 @@ static SYMBOL sql_functions[] = {
{ "NUMPOINTS", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_numpoints)}, { "NUMPOINTS", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_numpoints)},
{ "OCTET_LENGTH", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_length)}, { "OCTET_LENGTH", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_length)},
{ "OCT", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_oct)}, { "OCT", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_oct)},
{ "OLD_PASSWORD", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_old_password)},
{ "ORD", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_ord)}, { "ORD", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_ord)},
{ "OVERLAPS", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_overlaps)}, { "OVERLAPS", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_overlaps)},
{ "PERIOD_ADD", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_period_add)}, { "PERIOD_ADD", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_period_add)},

View file

@ -74,9 +74,6 @@ extern CHARSET_INFO *national_charset_info, *table_alias_charset;
****************************************************************************/ ****************************************************************************/
#define ACL_CACHE_SIZE 256 #define ACL_CACHE_SIZE 256
/* Password lengh for 4.1 version previous versions had 16 bytes password hash */
#define HASH_PASSWORD_LENGTH 45
#define HASH_OLD_PASSWORD_LENGTH 16
#define MAX_PASSWORD_LENGTH 32 #define MAX_PASSWORD_LENGTH 32
#define HOST_CACHE_SIZE 128 #define HOST_CACHE_SIZE 128
#define MAX_ACCEPT_RETRY 10 // Test accept this many times #define MAX_ACCEPT_RETRY 10 // Test accept this many times
@ -771,7 +768,7 @@ extern my_bool opt_safe_show_db, opt_local_infile, lower_case_table_names;
extern my_bool opt_slave_compressed_protocol, use_temp_pool; extern my_bool opt_slave_compressed_protocol, use_temp_pool;
extern my_bool opt_readonly; extern my_bool opt_readonly;
extern my_bool opt_enable_named_pipe; extern my_bool opt_enable_named_pipe;
extern my_bool opt_old_passwords, use_old_passwords; extern my_bool opt_secure_auth;
extern char *shared_memory_base_name, *mysqld_unix_port; extern char *shared_memory_base_name, *mysqld_unix_port;
extern bool opt_enable_shared_memory; extern bool opt_enable_shared_memory;

View file

@ -257,9 +257,10 @@ my_bool opt_local_infile, opt_external_locking, opt_slave_compressed_protocol;
my_bool opt_safe_user_create = 0, opt_no_mix_types = 0; my_bool opt_safe_user_create = 0, opt_no_mix_types = 0;
my_bool lower_case_table_names, opt_old_rpl_compat; my_bool lower_case_table_names, opt_old_rpl_compat;
my_bool opt_show_slave_auth_info, opt_sql_bin_update = 0; my_bool opt_show_slave_auth_info, opt_sql_bin_update = 0;
my_bool opt_log_slave_updates= 0, opt_old_passwords=0, use_old_passwords=0; my_bool opt_log_slave_updates= 0;
my_bool opt_console= 0, opt_bdb, opt_innodb, opt_isam; my_bool opt_console= 0, opt_bdb, opt_innodb, opt_isam;
my_bool opt_readonly, use_temp_pool, relay_log_purge; my_bool opt_readonly, use_temp_pool, relay_log_purge;
my_bool opt_secure_auth= 0;
volatile bool mqh_used = 0; volatile bool mqh_used = 0;
uint mysqld_port, test_flags, select_errors, dropping_tables, ha_open_options; uint mysqld_port, test_flags, select_errors, dropping_tables, ha_open_options;
@ -2819,12 +2820,6 @@ static void create_new_thread(THD *thd)
if (thread_count-delayed_insert_threads > max_used_connections) if (thread_count-delayed_insert_threads > max_used_connections)
max_used_connections=thread_count-delayed_insert_threads; max_used_connections=thread_count-delayed_insert_threads;
thd->thread_id=thread_id++; thd->thread_id=thread_id++;
for (uint i=0; i < 8 ; i++) // Generate password teststring
thd->scramble[i]= (char) (my_rnd(&sql_rand)*94+33);
thd->scramble[8]=0;
// Back it up as old clients may need it
memcpy(thd->old_scramble,thd->scramble,9);
thd->real_id=pthread_self(); // Keep purify happy thd->real_id=pthread_self(); // Keep purify happy
@ -3535,7 +3530,8 @@ enum options
OPT_EXPIRE_LOGS_DAYS, OPT_EXPIRE_LOGS_DAYS,
OPT_DEFAULT_WEEK_FORMAT, OPT_DEFAULT_WEEK_FORMAT,
OPT_GROUP_CONCAT_MAX_LEN, OPT_GROUP_CONCAT_MAX_LEN,
OPT_DEFAULT_COLLATION OPT_DEFAULT_COLLATION,
OPT_SECURE_AUTH
}; };
@ -3845,9 +3841,10 @@ master-ssl",
(gptr*) &opt_no_mix_types, (gptr*) &opt_no_mix_types, 0, GET_BOOL, NO_ARG, (gptr*) &opt_no_mix_types, (gptr*) &opt_no_mix_types, 0, GET_BOOL, NO_ARG,
0, 0, 0, 0, 0, 0}, 0, 0, 0, 0, 0, 0},
#endif #endif
{"old-protocol", 'o', "Use the old (3.20) protocol client/server protocol.", {"old-passwords", OPT_OLD_PASSWORDS, "Use old password encryption method (needed for 4.0 and older clients).",
(gptr*) &protocol_version, (gptr*) &protocol_version, 0, GET_UINT, NO_ARG, (gptr*) &global_system_variables.old_passwords,
PROTOCOL_VERSION, 0, 0, 0, 0, 0}, (gptr*) &max_system_variables.old_passwords, 0, GET_BOOL, NO_ARG,
0, 0, 0, 0, 0, 0},
{"old-rpl-compat", OPT_OLD_RPL_COMPAT, {"old-rpl-compat", OPT_OLD_RPL_COMPAT,
"Use old LOAD DATA format in the binary log (don't save data in file).", "Use old LOAD DATA format in the binary log (don't save data in file).",
(gptr*) &opt_old_rpl_compat, (gptr*) &opt_old_rpl_compat, 0, GET_BOOL, (gptr*) &opt_old_rpl_compat, (gptr*) &opt_old_rpl_compat, 0, GET_BOOL,
@ -3914,8 +3911,6 @@ relay logs.",
GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"safe-mode", OPT_SAFE, "Skip some optimize stages (for testing).", {"safe-mode", OPT_SAFE, "Skip some optimize stages (for testing).",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
{"old-passwords", OPT_OLD_PASSWORDS, "Use old password encryption method (needed for 4.0 and older clients).",
(gptr*) &opt_old_passwords, (gptr*) &opt_old_passwords, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
#ifndef TO_BE_DELETED #ifndef TO_BE_DELETED
{"safe-show-database", OPT_SAFE_SHOW_DB, {"safe-show-database", OPT_SAFE_SHOW_DB,
"Deprecated option; One should use GRANT SHOW DATABASES instead...", "Deprecated option; One should use GRANT SHOW DATABASES instead...",
@ -3925,6 +3920,9 @@ relay logs.",
"Don't allow new user creation by the user who has no write privileges to the mysql.user table.", "Don't allow new user creation by the user who has no write privileges to the mysql.user table.",
(gptr*) &opt_safe_user_create, (gptr*) &opt_safe_user_create, 0, GET_BOOL, (gptr*) &opt_safe_user_create, (gptr*) &opt_safe_user_create, 0, GET_BOOL,
NO_ARG, 0, 0, 0, 0, 0, 0}, NO_ARG, 0, 0, 0, 0, 0, 0},
{"secure-auth", OPT_SECURE_AUTH, "Disallow authentication for accounts that have old (pre-4.1) passwords.",
(gptr*) &opt_secure_auth, (gptr*) &opt_secure_auth, 0, GET_BOOL, NO_ARG,
my_bool(0), 0, 0, 0, 0, 0},
{"server-id", OPT_SERVER_ID, {"server-id", OPT_SERVER_ID,
"Uniquely identifies the server instance in the community of replication partners.", "Uniquely identifies the server instance in the community of replication partners.",
(gptr*) &server_id, (gptr*) &server_id, 0, GET_ULONG, REQUIRED_ARG, 0, 0, 0, (gptr*) &server_id, (gptr*) &server_id, 0, GET_ULONG, REQUIRED_ARG, 0, 0, 0,
@ -4709,7 +4707,8 @@ static void mysql_init_variables(void)
opt_log= opt_update_log= opt_bin_log= opt_slow_log= 0; opt_log= opt_update_log= opt_bin_log= opt_slow_log= 0;
opt_disable_networking= opt_skip_show_db=0; opt_disable_networking= opt_skip_show_db=0;
opt_logname= opt_update_logname= opt_binlog_index_name= opt_slow_logname=0; opt_logname= opt_update_logname= opt_binlog_index_name= opt_slow_logname=0;
opt_bootstrap= opt_myisam_log= use_old_passwords= 0; opt_secure_auth= 0;
opt_bootstrap= opt_myisam_log= 0;
mqh_used= 0; mqh_used= 0;
segfaulted= kill_in_progress= 0; segfaulted= kill_in_progress= 0;
cleanup_done= 0; cleanup_done= 0;
@ -4813,6 +4812,7 @@ static void mysql_init_variables(void)
max_system_variables.select_limit= (ulonglong) HA_POS_ERROR; max_system_variables.select_limit= (ulonglong) HA_POS_ERROR;
global_system_variables.max_join_size= (ulonglong) HA_POS_ERROR; global_system_variables.max_join_size= (ulonglong) HA_POS_ERROR;
max_system_variables.max_join_size= (ulonglong) HA_POS_ERROR; max_system_variables.max_join_size= (ulonglong) HA_POS_ERROR;
global_system_variables.old_passwords= 0;
/* Variables that depends on compile options */ /* Variables that depends on compile options */
#ifndef DBUG_OFF #ifndef DBUG_OFF
@ -4934,9 +4934,6 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
case 'L': case 'L':
strmake(language, argument, sizeof(language)-1); strmake(language, argument, sizeof(language)-1);
break; break;
case 'o':
protocol_version=PROTOCOL_VERSION-1;
break;
#ifdef HAVE_REPLICATION #ifdef HAVE_REPLICATION
case OPT_SLAVE_SKIP_ERRORS: case OPT_SLAVE_SKIP_ERRORS:
init_slave_skip_errors(argument); init_slave_skip_errors(argument);

File diff suppressed because it is too large Load diff

View file

@ -349,6 +349,25 @@ send_eof(THD *thd, bool no_flush)
} }
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
/*
Please client to send scrambled_password in old format.
SYNOPSYS
send_old_password_request()
thd thread handle
RETURN VALUE
0 ok
!0 error
*/
bool send_old_password_request(THD *thd)
{
static char buff[1]= { (char) 254 };
NET *net= &thd->net;
return my_net_write(net, buff, 1) || net_flush(net);
}
#endif /* EMBEDDED_LIBRARY */ #endif /* EMBEDDED_LIBRARY */
/* /*

View file

@ -164,6 +164,7 @@ void net_printf(THD *thd,uint sql_errno, ...);
void send_ok(THD *thd, ha_rows affected_rows=0L, ulonglong id=0L, void send_ok(THD *thd, ha_rows affected_rows=0L, ulonglong id=0L,
const char *info=0); const char *info=0);
void send_eof(THD *thd, bool no_flush=0); void send_eof(THD *thd, bool no_flush=0);
bool send_old_password_request(THD *thd);
char *net_store_length(char *packet,ulonglong length); char *net_store_length(char *packet,ulonglong length);
char *net_store_length(char *packet,uint length); char *net_store_length(char *packet,uint length);
char *net_store_data(char *to,const char *from, uint length); char *net_store_data(char *to,const char *from, uint length);

View file

@ -216,6 +216,7 @@ sys_var_thd_ulong sys_net_retry_count("net_retry_count",
&SV::net_retry_count, &SV::net_retry_count,
fix_net_retry_count); fix_net_retry_count);
sys_var_thd_bool sys_new_mode("new", &SV::new_mode); sys_var_thd_bool sys_new_mode("new", &SV::new_mode);
sys_var_thd_bool sys_old_passwords("old_passwords", &SV::old_passwords);
sys_var_thd_ulong sys_preload_buff_size("preload_buffer_size", sys_var_thd_ulong sys_preload_buff_size("preload_buffer_size",
&SV::preload_buff_size); &SV::preload_buff_size);
sys_var_thd_ulong sys_read_buff_size("read_buffer_size", sys_var_thd_ulong sys_read_buff_size("read_buffer_size",
@ -242,6 +243,7 @@ sys_var_thd_enum sys_query_cache_type("query_cache_type",
&SV::query_cache_type, &SV::query_cache_type,
&query_cache_type_typelib); &query_cache_type_typelib);
#endif /* HAVE_QUERY_CACHE */ #endif /* HAVE_QUERY_CACHE */
sys_var_bool_ptr sys_secure_auth("secure_auth", &opt_secure_auth);
sys_var_long_ptr sys_server_id("server_id",&server_id); sys_var_long_ptr sys_server_id("server_id",&server_id);
sys_var_bool_ptr sys_slave_compressed_protocol("slave_compressed_protocol", sys_var_bool_ptr sys_slave_compressed_protocol("slave_compressed_protocol",
&opt_slave_compressed_protocol); &opt_slave_compressed_protocol);
@ -432,6 +434,7 @@ sys_var *sys_variables[]=
&sys_net_wait_timeout, &sys_net_wait_timeout,
&sys_net_write_timeout, &sys_net_write_timeout,
&sys_new_mode, &sys_new_mode,
&sys_old_passwords,
&sys_preload_buff_size, &sys_preload_buff_size,
&sys_pseudo_thread_id, &sys_pseudo_thread_id,
&sys_query_cache_size, &sys_query_cache_size,
@ -450,6 +453,7 @@ sys_var *sys_variables[]=
#endif #endif
&sys_rpl_recovery_rank, &sys_rpl_recovery_rank,
&sys_safe_updates, &sys_safe_updates,
&sys_secure_auth,
&sys_select_limit, &sys_select_limit,
&sys_server_id, &sys_server_id,
#ifdef HAVE_REPLICATION #ifdef HAVE_REPLICATION
@ -608,6 +612,7 @@ struct show_var_st init_vars[]= {
{sys_net_retry_count.name, (char*) &sys_net_retry_count, SHOW_SYS}, {sys_net_retry_count.name, (char*) &sys_net_retry_count, SHOW_SYS},
{sys_net_write_timeout.name,(char*) &sys_net_write_timeout, SHOW_SYS}, {sys_net_write_timeout.name,(char*) &sys_net_write_timeout, SHOW_SYS},
{sys_new_mode.name, (char*) &sys_new_mode, SHOW_SYS}, {sys_new_mode.name, (char*) &sys_new_mode, SHOW_SYS},
{sys_old_passwords.name, (char*) &sys_old_passwords, SHOW_SYS},
{"open_files_limit", (char*) &open_files_limit, SHOW_LONG}, {"open_files_limit", (char*) &open_files_limit, SHOW_LONG},
{"pid_file", (char*) pidfile_name, SHOW_CHAR}, {"pid_file", (char*) pidfile_name, SHOW_CHAR},
{"log_error", (char*) log_error_file, SHOW_CHAR}, {"log_error", (char*) log_error_file, SHOW_CHAR},
@ -628,6 +633,7 @@ struct show_var_st init_vars[]= {
SHOW_SYS}, SHOW_SYS},
{sys_query_cache_size.name, (char*) &sys_query_cache_size, SHOW_SYS}, {sys_query_cache_size.name, (char*) &sys_query_cache_size, SHOW_SYS},
{sys_query_cache_type.name, (char*) &sys_query_cache_type, SHOW_SYS}, {sys_query_cache_type.name, (char*) &sys_query_cache_type, SHOW_SYS},
{"secure_auth", (char*) &sys_secure_auth, SHOW_SYS},
#endif /* HAVE_QUERY_CACHE */ #endif /* HAVE_QUERY_CACHE */
#ifdef HAVE_SMEM #ifdef HAVE_SMEM
{"shared_memory", (char*) &opt_enable_shared_memory, SHOW_MY_BOOL}, {"shared_memory", (char*) &opt_enable_shared_memory, SHOW_MY_BOOL},

View file

@ -689,6 +689,9 @@ public:
} }
}; };
/* updated in sql_acl.cc */
extern sys_var_thd_bool sys_old_passwords;
/* For sql_yacc */ /* For sql_yacc */
struct sys_var_with_base struct sys_var_with_base

View file

@ -279,3 +279,4 @@ v/*
"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)", "Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Unknown collation: '%-.64s'", "Unknown collation: '%-.64s'",
"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started." "SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started."
"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format"

View file

@ -273,3 +273,4 @@
"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)", "Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Unknown collation: '%-.64s'", "Unknown collation: '%-.64s'",
"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started." "SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started."
"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format"

View file

@ -281,3 +281,4 @@
"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)", "Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Unknown collation: '%-.64s'", "Unknown collation: '%-.64s'",
"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started." "SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started."
"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format"

View file

@ -275,3 +275,4 @@
"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)", "Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Unknown collation: '%-.64s'", "Unknown collation: '%-.64s'",
"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started." "SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started."
"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format"

View file

@ -275,3 +275,4 @@
"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)", "Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Unknown collation: '%-.64s'", "Unknown collation: '%-.64s'",
"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started." "SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started."
"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format"

View file

@ -270,3 +270,4 @@
"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)", "Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Unknown collation: '%-.64s'", "Unknown collation: '%-.64s'",
"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started." "SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started."
"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format"

View file

@ -279,3 +279,4 @@
"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)", "Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Unknown collation: '%-.64s'", "Unknown collation: '%-.64s'",
"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started." "SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started."
"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format"

View file

@ -270,3 +270,4 @@
"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)", "Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Unknown collation: '%-.64s'", "Unknown collation: '%-.64s'",
"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started." "SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started."
"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format"

View file

@ -272,3 +272,4 @@
"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)", "Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Unknown collation: '%-.64s'", "Unknown collation: '%-.64s'",
"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started." "SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started."
"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format"

View file

@ -270,3 +270,4 @@
"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)", "Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Unknown collation: '%-.64s'", "Unknown collation: '%-.64s'",
"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started." "SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started."
"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format"

View file

@ -272,3 +272,4 @@
"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)", "Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Unknown collation: '%-.64s'", "Unknown collation: '%-.64s'",
"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started." "SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started."
"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format"

View file

@ -270,3 +270,4 @@
"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)", "Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Unknown collation: '%-.64s'", "Unknown collation: '%-.64s'",
"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started." "SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started."
"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format"

View file

@ -272,3 +272,4 @@
"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)", "Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Unknown collation: '%-.64s'", "Unknown collation: '%-.64s'",
"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started." "SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started."
"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format"

View file

@ -272,3 +272,4 @@
"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)", "Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Unknown collation: '%-.64s'", "Unknown collation: '%-.64s'",
"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started." "SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started."
"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format"

View file

@ -274,3 +274,4 @@
"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)", "Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Unknown collation: '%-.64s'", "Unknown collation: '%-.64s'",
"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started." "SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started."
"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format"

View file

@ -270,3 +270,4 @@
"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)", "Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Unknown collation: '%-.64s'", "Unknown collation: '%-.64s'",
"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started." "SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started."
"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format"

View file

@ -274,3 +274,4 @@
"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)", "Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Unknown collation: '%-.64s'", "Unknown collation: '%-.64s'",
"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started." "SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started."
"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format"

View file

@ -272,3 +272,4 @@
"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)", "Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Unknown collation: '%-.64s'", "Unknown collation: '%-.64s'",
"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started." "SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started."
"Сервер запущен в режиме --secure-auth (безопасной авторизации), но для пользователя '%s@%s' пароль сохранён в старом формате; необходимо обновить формат пароля"

View file

@ -265,3 +265,4 @@
"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)", "Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Unknown collation: '%-.64s'", "Unknown collation: '%-.64s'",
"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started." "SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started."
"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format"

View file

@ -278,3 +278,4 @@
"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)", "Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Unknown collation: '%-.64s'", "Unknown collation: '%-.64s'",
"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started." "SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started."
"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format"

View file

@ -271,3 +271,4 @@
"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)", "Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Unknown collation: '%-.64s'", "Unknown collation: '%-.64s'",
"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started." "SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started."
"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format"

View file

@ -270,3 +270,4 @@
"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)", "Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Unknown collation: '%-.64s'", "Unknown collation: '%-.64s'",
"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started." "SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started."
"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format"

View file

@ -275,3 +275,4 @@
"Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)", "Variable '%-.64s' is not a variable component (Can't be used as XXXX.variable_name)",
"Unknown collation: '%-.64s'", "Unknown collation: '%-.64s'",
"SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started." "SSL parameters in CHANGE MASTER are ignored because this MySQL slave was compiled without SSL support. They can be used later when MySQL slave with SSL will be started."
"Server is running in --secure-auth mode, but '%s@%s' has a password in the old format; please change the password to the new format"

View file

@ -1554,7 +1554,7 @@ void init_master_info_with_options(MASTER_INFO* mi)
if (master_user) if (master_user)
strmake(mi->user, master_user, sizeof(mi->user) - 1); strmake(mi->user, master_user, sizeof(mi->user) - 1);
if (master_password) if (master_password)
strmake(mi->password, master_password, HASH_PASSWORD_LENGTH); strmake(mi->password, master_password, MAX_PASSWORD_LENGTH);
mi->port = master_port; mi->port = master_port;
mi->connect_retry = master_connect_retry; mi->connect_retry = master_connect_retry;
@ -1707,8 +1707,8 @@ file '%s')", fname);
master_host) || master_host) ||
init_strvar_from_file(mi->user, sizeof(mi->user), &mi->file, init_strvar_from_file(mi->user, sizeof(mi->user), &mi->file,
master_user) || master_user) ||
init_strvar_from_file(mi->password, HASH_PASSWORD_LENGTH+1, &mi->file, init_strvar_from_file(mi->password, SCRAMBLED_PASSWORD_CHAR_LENGTH+1,
master_password) || &mi->file, master_password) ||
init_intvar_from_file(&port, &mi->file, master_port) || init_intvar_from_file(&port, &mi->file, master_port) ||
init_intvar_from_file(&connect_retry, &mi->file, init_intvar_from_file(&connect_retry, &mi->file,
master_connect_retry)) master_connect_retry))

View file

@ -51,7 +51,7 @@ static byte* acl_entry_get_key(acl_entry *entry,uint *length,
return (byte*) entry->key; return (byte*) entry->key;
} }
#define ACL_KEY_LENGTH (sizeof(long)+NAME_LEN+17) #define ACL_KEY_LENGTH (sizeof(long)+NAME_LEN+USERNAME_LENGTH+1)
static DYNAMIC_ARRAY acl_hosts,acl_users,acl_dbs; static DYNAMIC_ARRAY acl_hosts,acl_users,acl_dbs;
static MEM_ROOT mem, memex; static MEM_ROOT mem, memex;
@ -68,11 +68,53 @@ static ulong get_sort(uint count,...);
static void init_check_host(void); static void init_check_host(void);
static ACL_USER *find_acl_user(const char *host, const char *user); static ACL_USER *find_acl_user(const char *host, const char *user);
static bool update_user_table(THD *thd, const char *host, const char *user, static bool update_user_table(THD *thd, const char *host, const char *user,
const char *new_password); const char *new_password, uint new_password_len);
static void update_hostname(acl_host_and_ip *host, const char *hostname); static void update_hostname(acl_host_and_ip *host, const char *hostname);
static bool compare_hostname(const acl_host_and_ip *host,const char *hostname, static bool compare_hostname(const acl_host_and_ip *host,const char *hostname,
const char *ip); const char *ip);
/*
Convert scrambled password to binary form, according to scramble type,
Binary form is stored in user.salt.
*/
static
void
set_user_salt(ACL_USER *acl_user, const char *password, uint password_len)
{
if (password_len == SCRAMBLED_PASSWORD_CHAR_LENGTH)
{
get_salt_from_password(acl_user->salt, password);
acl_user->salt_len= SCRAMBLE_LENGTH;
}
else if (password_len == SCRAMBLED_PASSWORD_CHAR_LENGTH_323)
{
get_salt_from_password_323((ulong *) acl_user->salt, password);
acl_user->salt_len= SCRAMBLE_LENGTH_323;
}
else
acl_user->salt_len= 0;
}
/*
This after_update function is used when user.password is less than
SCRAMBLE_LENGTH bytes.
*/
static void restrict_update_of_old_passwords_var(THD *thd,
enum_var_type var_type)
{
if (var_type == OPT_GLOBAL)
{
pthread_mutex_lock(&LOCK_global_system_variables);
global_system_variables.old_passwords= 1;
pthread_mutex_unlock(&LOCK_global_system_variables);
}
else
thd->variables.old_passwords= 1;
}
/* /*
Read grant privileges from the privilege tables in the 'mysql' database. Read grant privileges from the privilege tables in the 'mysql' database.
@ -114,8 +156,6 @@ my_bool acl_init(THD *org_thd, bool dont_read_acl_tables)
if (!(thd=new THD)) if (!(thd=new THD))
DBUG_RETURN(1); /* purecov: inspected */ DBUG_RETURN(1); /* purecov: inspected */
thd->store_globals(); thd->store_globals();
/* Use passwords according to command line option */
use_old_passwords= opt_old_passwords;
acl_cache->clear(1); // Clear locked hostname cache acl_cache->clear(1); // Clear locked hostname cache
thd->db= my_strdup("mysql",MYF(0)); thd->db= my_strdup("mysql",MYF(0));
@ -172,103 +212,126 @@ my_bool acl_init(THD *org_thd, bool dont_read_acl_tables)
init_read_record(&read_record_info,thd,table=tables[1].table,NULL,1,0); init_read_record(&read_record_info,thd,table=tables[1].table,NULL,1,0);
VOID(my_init_dynamic_array(&acl_users,sizeof(ACL_USER),50,100)); VOID(my_init_dynamic_array(&acl_users,sizeof(ACL_USER),50,100));
if (table->field[2]->field_length == 8 && if (table->field[2]->field_length < SCRAMBLED_PASSWORD_CHAR_LENGTH_323)
protocol_version == PROTOCOL_VERSION)
{ {
sql_print_error("Old 'user' table. (Check README or the Reference manual). Continuing --old-protocol"); /* purecov: tested */ sql_print_error("Fatal error: mysql.user table is damaged or in "
protocol_version=9; /* purecov: tested */ "unsupported 3.20 format.");
goto end;
} }
DBUG_PRINT("info",("user table fields: %d, password length: %d", DBUG_PRINT("info",("user table fields: %d, password length: %d",
table->fields, table->field[2]->field_length)); table->fields, table->field[2]->field_length));
if (table->field[2]->field_length < 45 && !use_old_passwords)
pthread_mutex_lock(&LOCK_global_system_variables);
if (table->field[2]->field_length < SCRAMBLED_PASSWORD_CHAR_LENGTH)
{ {
sql_print_error("mysql.user table is not updated to new password format; Disabling new password usage until mysql_fix_privilege_tables is run"); if (opt_secure_auth)
use_old_passwords= 1; {
pthread_mutex_unlock(&LOCK_global_system_variables);
sql_print_error("Fatal error: mysql.user table is in old format, "
"but server started with --secure-auth option.");
goto end;
}
sys_old_passwords.after_update= restrict_update_of_old_passwords_var;
if (global_system_variables.old_passwords)
pthread_mutex_unlock(&LOCK_global_system_variables);
else
{
global_system_variables.old_passwords= 1;
pthread_mutex_unlock(&LOCK_global_system_variables);
sql_print_error("mysql.user table is not updated to new password format; "
"Disabling new password usage until "
"mysql_fix_privilege_tables is run");
}
thd->variables.old_passwords= 1;
}
else
{
sys_old_passwords.after_update= 0;
pthread_mutex_unlock(&LOCK_global_system_variables);
} }
allow_all_hosts=0; allow_all_hosts=0;
while (!(read_record_info.read_record(&read_record_info))) while (!(read_record_info.read_record(&read_record_info)))
{ {
ACL_USER user; ACL_USER user;
uint length=0; update_hostname(&user.host, get_field(&mem, table->field[0]));
update_hostname(&user.host,get_field(&mem, table->field[0])); user.user= get_field(&mem, table->field[1]);
user.user=get_field(&mem, table->field[1]); const char *password= get_field(&mem, table->field[2]);
user.password=get_field(&mem, table->field[2]); uint password_len= password ? strlen(password) : 0;
if (user.password && (length=(uint) strlen(user.password)) == 8 && set_user_salt(&user, password, password_len);
protocol_version == PROTOCOL_VERSION) if (user.salt_len == 0 && password_len != 0)
{ {
sql_print_error( switch (password_len) {
"Found old style password for user '%s'. Ignoring user. (You may want to restart mysqld using --old-protocol)", case 45: /* 4.1: to be removed */
user.user ? user.user : ""); /* purecov: tested */ sql_print_error("Found 4.1 style password for user '%s@%s'. "
"Ignoring user. "
"You should change password for this user.",
user.user ? user.user : "",
user.host.hostname ? user.host.hostname : "");
break;
default:
sql_print_error("Found invalid password for user: '%s@%s'; "
"Ignoring user", user.user ? user.user : "",
user.host.hostname ? user.host.hostname : "");
break;
}
} }
else /* non empty and not short passwords */ else // password is correct
{ {
user.pversion=get_password_version(user.password); user.access= get_access(table,3) & GLOBAL_ACLS;
/* Only passwords of specific lengths depending on version are allowed */ user.sort= get_sort(2,user.host.hostname,user.user);
if ((!user.pversion && (length % 8 || length > 16)) || user.hostname_length= (user.host.hostname ?
(user.pversion && length != 45)) (uint) strlen(user.host.hostname) : 0);
if (table->fields >= 31) /* Starting from 4.0.2 we have more fields */
{ {
sql_print_error( char *ssl_type=get_field(&mem, table->field[24]);
"Found invalid password for user: '%s'@'%s'; Ignoring user", if (!ssl_type)
user.user ? user.user : "", user.ssl_type=SSL_TYPE_NONE;
user.host.hostname ? user.host.hostname : ""); /* purecov: tested */ else if (!strcmp(ssl_type, "ANY"))
continue; /* purecov: tested */ user.ssl_type=SSL_TYPE_ANY;
else if (!strcmp(ssl_type, "X509"))
user.ssl_type=SSL_TYPE_X509;
else /* !strcmp(ssl_type, "SPECIFIED") */
user.ssl_type=SSL_TYPE_SPECIFIED;
user.ssl_cipher= get_field(&mem, table->field[25]);
user.x509_issuer= get_field(&mem, table->field[26]);
user.x509_subject= get_field(&mem, table->field[27]);
char *ptr = get_field(&mem, table->field[28]);
user.user_resource.questions=atoi(ptr);
ptr = get_field(&mem, table->field[29]);
user.user_resource.updates=atoi(ptr);
ptr = get_field(&mem, table->field[30]);
user.user_resource.connections=atoi(ptr);
if (user.user_resource.questions || user.user_resource.updates ||
user.user_resource.connections)
mqh_used=1;
} }
} else
get_salt_from_password(user.salt,user.password); {
user.access=get_access(table,3) & GLOBAL_ACLS; user.ssl_type=SSL_TYPE_NONE;
user.sort=get_sort(2,user.host.hostname,user.user); bzero((char *)&(user.user_resource),sizeof(user.user_resource));
user.hostname_length= (user.host.hostname ?
(uint) strlen(user.host.hostname) : 0);
if (table->fields >= 31) /* Starting from 4.0.2 we have more fields */
{
char *ssl_type=get_field(&mem, table->field[24]);
if (!ssl_type)
user.ssl_type=SSL_TYPE_NONE;
else if (!strcmp(ssl_type, "ANY"))
user.ssl_type=SSL_TYPE_ANY;
else if (!strcmp(ssl_type, "X509"))
user.ssl_type=SSL_TYPE_X509;
else /* !strcmp(ssl_type, "SPECIFIED") */
user.ssl_type=SSL_TYPE_SPECIFIED;
user.ssl_cipher= get_field(&mem, table->field[25]);
user.x509_issuer= get_field(&mem, table->field[26]);
user.x509_subject= get_field(&mem, table->field[27]);
char *ptr = get_field(&mem, table->field[28]);
user.user_resource.questions=atoi(ptr);
ptr = get_field(&mem, table->field[29]);
user.user_resource.updates=atoi(ptr);
ptr = get_field(&mem, table->field[30]);
user.user_resource.connections=atoi(ptr);
if (user.user_resource.questions || user.user_resource.updates ||
user.user_resource.connections)
mqh_used=1;
}
else
{
user.ssl_type=SSL_TYPE_NONE;
bzero((char *)&(user.user_resource),sizeof(user.user_resource));
#ifndef TO_BE_REMOVED #ifndef TO_BE_REMOVED
if (table->fields <= 13) if (table->fields <= 13)
{ // Without grant { // Without grant
if (user.access & CREATE_ACL) if (user.access & CREATE_ACL)
user.access|=REFERENCES_ACL | INDEX_ACL | ALTER_ACL; user.access|=REFERENCES_ACL | INDEX_ACL | ALTER_ACL;
} }
/* Convert old privileges */ /* Convert old privileges */
user.access|= LOCK_TABLES_ACL | CREATE_TMP_ACL | SHOW_DB_ACL; user.access|= LOCK_TABLES_ACL | CREATE_TMP_ACL | SHOW_DB_ACL;
if (user.access & FILE_ACL) if (user.access & FILE_ACL)
user.access|= REPL_CLIENT_ACL | REPL_SLAVE_ACL; user.access|= REPL_CLIENT_ACL | REPL_SLAVE_ACL;
if (user.access & PROCESS_ACL) if (user.access & PROCESS_ACL)
user.access|= SUPER_ACL | EXECUTE_ACL; user.access|= SUPER_ACL | EXECUTE_ACL;
#endif #endif
}
VOID(push_dynamic(&acl_users,(gptr) &user));
if (!user.host.hostname || user.host.hostname[0] == wild_many &&
!user.host.hostname[1])
allow_all_hosts=1; // Anyone can connect
} }
VOID(push_dynamic(&acl_users,(gptr) &user));
if (!user.host.hostname || user.host.hostname[0] == wild_many &&
!user.host.hostname[1])
allow_all_hosts=1; // Anyone can connect
} }
qsort((gptr) dynamic_element(&acl_users,0,ACL_USER*),acl_users.elements, qsort((gptr) dynamic_element(&acl_users,0,ACL_USER*),acl_users.elements,
sizeof(ACL_USER),(qsort_cmp) acl_compare); sizeof(ACL_USER),(qsort_cmp) acl_compare);
@ -469,135 +532,105 @@ static int acl_compare(ACL_ACCESS *a,ACL_ACCESS *b)
/* /*
Prepare crypted scramble to be sent to the client Seek ACL entry for a user, check password, SSL cypher, and if
everything is OK, update THD user data and USER_RESOURCES struct.
IMPLEMENTATION
This function does not check if the user has any sensible privileges:
only user's existence and validity is checked.
Note, that entire operation is protected by acl_cache_lock.
SYNOPSIS
acl_getroot()
thd thread handle. If all checks are OK,
thd->priv_user, thd->master_access are updated.
thd->host, thd->ip, thd->user are used for checks.
mqh user resources; on success mqh is reset, else
unchanged
passwd scrambled & crypted password, recieved from client
(to check): thd->scramble or thd->scramble_323 is
used to decrypt passwd, so they must contain
original random string,
passwd_len length of passwd, must be one of 0, 8,
SCRAMBLE_LENGTH_323, SCRAMBLE_LENGTH
'thd' and 'mqh' are updated on success; other params are IN.
RETURN VALUE
0 success: thd->priv_user, thd->priv_host, thd->master_access, mqh are
updated
1 user not found or authentification failure
2 user found, has long (4.1.1) salt, but passwd is in old (3.23) format.
-1 user found, has short (3.23) salt, but passwd is in new (4.1.1) format.
*/ */
void prepare_scramble(THD *thd, ACL_USER *acl_user,char* prepared_scramble) int acl_getroot(THD *thd, USER_RESOURCES *mqh,
const char *passwd, uint passwd_len)
{ {
/* Binary password format to be used for generation*/
char bin_password[SCRAMBLE41_LENGTH];
/* Generate new long scramble for the thread */
create_random_string(SCRAMBLE41_LENGTH,&thd->rand,thd->scramble);
thd->scramble[SCRAMBLE41_LENGTH]=0;
/* Get binary form, First 4 bytes of prepared scramble is salt */
get_hash_and_password(acl_user->salt,acl_user->pversion,prepared_scramble,
(unsigned char*) bin_password);
/* Store "*" as identifier for old passwords */
if (!acl_user->pversion)
prepared_scramble[0]='*';
/* Finally encrypt password to get prepared scramble */
password_crypt(thd->scramble, prepared_scramble+4, bin_password,
SCRAMBLE41_LENGTH);
}
/*
Get master privilges for user (priviliges for all tables).
Required before connecting to MySQL
As we have 2 stage handshake now we cache user not to lookup
it second time. At the second stage we do not lookup user in case
we already know it;
*/
ulong acl_getroot(THD *thd, const char *host, const char *ip, const char *user,
const char *password,const char *message,char **priv_user,
char *priv_host, bool old_ver, USER_RESOURCES *mqh,
char *prepared_scramble, uint *cur_priv_version,
ACL_USER **cached_user)
{
ulong user_access=NO_ACCESS;
*priv_user= (char*) user;
bool password_correct= 0;
int stage= (*cached_user != NULL); /* NULL passed as first stage */
ACL_USER *acl_user= NULL;
DBUG_ENTER("acl_getroot"); DBUG_ENTER("acl_getroot");
bzero((char*) mqh, sizeof(USER_RESOURCES));
if (!initialized) if (!initialized)
{ {
// If no data allow anything /*
DBUG_RETURN((ulong) ~NO_ACCESS); /* purecov: tested */ here if mysqld's been started with --skip-grant-tables option.
*/
thd->priv_user= (char *) ""; // privileges for
*thd->priv_host= '\0'; // the user are unknown
thd->master_access= ~NO_ACCESS; // everything is allowed
bzero(mqh, sizeof(*mqh));
DBUG_RETURN(0);
} }
int res= 1;
VOID(pthread_mutex_lock(&acl_cache->lock)); VOID(pthread_mutex_lock(&acl_cache->lock));
/* /*
Get possible access from user_list. This is or'ed to others not Find acl entry in user database. Note, that find_acl_user is not the same,
fully specified because it doesn't take into account the case when user is not empty,
but acl_user->user is empty
If we have cached user use it, in other case look it up.
*/ */
if (stage && (*cur_priv_version == priv_version)) ACL_USER *acl_user= 0;
acl_user= *cached_user; for (uint i=0 ; i < acl_users.elements ; i++)
else
{ {
for (uint i=0 ; i < acl_users.elements ; i++) ACL_USER *user_i = dynamic_element(&acl_users,i,ACL_USER*);
if (!user_i->user || !strcmp(thd->user, user_i->user))
{ {
ACL_USER *acl_user_search=dynamic_element(&acl_users,i,ACL_USER*); if (compare_hostname(&user_i->host, thd->host, thd->ip))
if (!acl_user_search->user || !strcmp(user,acl_user_search->user))
{ {
if (compare_hostname(&acl_user_search->host,host,ip)) /* check password: it should be empty or valid */
if (passwd_len == user_i->salt_len)
{ {
/* Found mathing user */ if (user_i->salt_len == 0 ||
acl_user= acl_user_search; user_i->salt_len == SCRAMBLE_LENGTH &&
/* Store it as a cache */ check_scramble(passwd, thd->scramble, user_i->salt) == 0 ||
*cached_user= acl_user; check_scramble_323(passwd, thd->scramble,
*cur_priv_version= priv_version; (ulong *) user_i->salt) == 0)
break; {
acl_user= user_i;
res= 0;
}
} }
else if (passwd_len == SCRAMBLE_LENGTH &&
user_i->salt_len == SCRAMBLE_LENGTH_323)
res= -1;
else if (passwd_len == SCRAMBLE_LENGTH_323 &&
user_i->salt_len == SCRAMBLE_LENGTH)
res= 2;
/* linear search complete: */
break;
} }
} }
} }
/*
/* Now we have acl_user found and may start our checks */ This was moved to separate tree because of heavy HAVE_OPENSSL case.
If acl_user is not null, res is 0.
*/
if (acl_user) if (acl_user)
{ {
/* Password should present for both or absend for both */ /* OK. User found and password checked continue validation */
if (!acl_user->password && !*password) thd->master_access= NO_ACCESS;
password_correct=1;
else if (!acl_user->password || !*password)
{
*cached_user= 0; // Impossible to connect
}
else
{
/* New version password is checked differently */
if (acl_user->pversion)
{
if (stage) /* We check password only on the second stage */
{
if (!validate_password(password,message,acl_user->salt))
password_correct=1;
}
else /* First stage - just prepare scramble */
prepare_scramble(thd,acl_user,prepared_scramble);
}
/* Old way to check password */
else
{
/* Checking the scramble at any stage. First - old clients */
if (!check_scramble(password,message,acl_user->salt,
(my_bool) old_ver))
password_correct=1;
else if (!stage) /* Here if password incorrect */
{
/* At the first stage - prepare scramble */
prepare_scramble(thd,acl_user,prepared_scramble);
}
}
}
}
/* If user not found password_correct will also be zero */
if (!password_correct)
goto unlock_and_exit;
/* OK. User found and password checked continue validation */
{
Vio *vio=thd->net.vio; Vio *vio=thd->net.vio;
/* /*
At this point we know that user is allowed to connect At this point we know that user is allowed to connect
@ -608,32 +641,32 @@ ulong acl_getroot(THD *thd, const char *host, const char *ip, const char *user,
switch (acl_user->ssl_type) { switch (acl_user->ssl_type) {
case SSL_TYPE_NOT_SPECIFIED: // Impossible case SSL_TYPE_NOT_SPECIFIED: // Impossible
case SSL_TYPE_NONE: /* SSL is not required to connect */ case SSL_TYPE_NONE: /* SSL is not required to connect */
user_access=acl_user->access; thd->master_access= acl_user->access;
break; break;
#ifdef HAVE_OPENSSL #ifdef HAVE_OPENSSL
case SSL_TYPE_ANY: /* Any kind of SSL is good enough */ case SSL_TYPE_ANY: /* Any kind of SSL is good enough */
if (vio_type(vio) == VIO_TYPE_SSL) if (vio_type(vio) == VIO_TYPE_SSL)
user_access=acl_user->access; thd->master_access= acl_user->access;
break; break;
case SSL_TYPE_X509: /* Client should have any valid certificate. */ case SSL_TYPE_X509: /* Client should have any valid certificate. */
/* /*
Connections with non-valid certificates are dropped already Connections with non-valid certificates are dropped already
in sslaccept() anyway, so we do not check validity here. in sslaccept() anyway, so we do not check validity here.
We need to check for absence of SSL because without SSL We need to check for absence of SSL because without SSL
we should reject connection. we should reject connection.
*/ */
if (vio_type(vio) == VIO_TYPE_SSL && if (vio_type(vio) == VIO_TYPE_SSL &&
SSL_get_verify_result(vio->ssl_) == X509_V_OK && SSL_get_verify_result(vio->ssl_) == X509_V_OK &&
SSL_get_peer_certificate(vio->ssl_)) SSL_get_peer_certificate(vio->ssl_))
user_access=acl_user->access; thd->master_access= acl_user->access;
break; break;
case SSL_TYPE_SPECIFIED: /* Client should have specified attrib */ case SSL_TYPE_SPECIFIED: /* Client should have specified attrib */
/* /*
We do not check for absence of SSL because without SSL it does We do not check for absence of SSL because without SSL it does
not pass all checks here anyway. not pass all checks here anyway.
If cipher name is specified, we compare it to actual cipher in If cipher name is specified, we compare it to actual cipher in
use. use.
*/ */
if (vio_type(vio) != VIO_TYPE_SSL || if (vio_type(vio) != VIO_TYPE_SSL ||
SSL_get_verify_result(vio->ssl_) != X509_V_OK) SSL_get_verify_result(vio->ssl_) != X509_V_OK)
@ -643,14 +676,13 @@ ulong acl_getroot(THD *thd, const char *host, const char *ip, const char *user,
DBUG_PRINT("info",("comparing ciphers: '%s' and '%s'", DBUG_PRINT("info",("comparing ciphers: '%s' and '%s'",
acl_user->ssl_cipher,SSL_get_cipher(vio->ssl_))); acl_user->ssl_cipher,SSL_get_cipher(vio->ssl_)));
if (!strcmp(acl_user->ssl_cipher,SSL_get_cipher(vio->ssl_))) if (!strcmp(acl_user->ssl_cipher,SSL_get_cipher(vio->ssl_)))
user_access=acl_user->access; thd->master_access= acl_user->access;
else else
{ {
if (global_system_variables.log_warnings) if (global_system_variables.log_warnings)
sql_print_error("X509 ciphers mismatch: should be '%s' but is '%s'", sql_print_error("X509 ciphers mismatch: should be '%s' but is '%s'",
acl_user->ssl_cipher, acl_user->ssl_cipher,
SSL_get_cipher(vio->ssl_)); SSL_get_cipher(vio->ssl_));
user_access=NO_ACCESS;
break; break;
} }
} }
@ -661,64 +693,58 @@ ulong acl_getroot(THD *thd, const char *host, const char *ip, const char *user,
/* If X509 issuer is speified, we check it... */ /* If X509 issuer is speified, we check it... */
if (acl_user->x509_issuer) if (acl_user->x509_issuer)
{ {
DBUG_PRINT("info",("checkpoint 3")); DBUG_PRINT("info",("checkpoint 3"));
char *ptr = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0); char *ptr = X509_NAME_oneline(X509_get_issuer_name(cert), 0, 0);
DBUG_PRINT("info",("comparing issuers: '%s' and '%s'", DBUG_PRINT("info",("comparing issuers: '%s' and '%s'",
acl_user->x509_issuer, ptr)); acl_user->x509_issuer, ptr));
if (strcmp(acl_user->x509_issuer, ptr)) if (strcmp(acl_user->x509_issuer, ptr))
{ {
if (global_system_variables.log_warnings) if (global_system_variables.log_warnings)
sql_print_error("X509 issuer mismatch: should be '%s' but is '%s'", sql_print_error("X509 issuer mismatch: should be '%s' "
acl_user->x509_issuer, ptr); "but is '%s'", acl_user->x509_issuer, ptr);
user_access=NO_ACCESS; free(ptr);
free(ptr); break;
break; }
} thd->master_access= acl_user->access;
user_access=acl_user->access; free(ptr);
free(ptr);
} }
DBUG_PRINT("info",("checkpoint 4")); DBUG_PRINT("info",("checkpoint 4"));
/* X509 subject is specified, we check it .. */ /* X509 subject is specified, we check it .. */
if (acl_user->x509_subject) if (acl_user->x509_subject)
{ {
char *ptr= X509_NAME_oneline(X509_get_subject_name(cert), 0, 0); char *ptr= X509_NAME_oneline(X509_get_subject_name(cert), 0, 0);
DBUG_PRINT("info",("comparing subjects: '%s' and '%s'", DBUG_PRINT("info",("comparing subjects: '%s' and '%s'",
acl_user->x509_subject, ptr)); acl_user->x509_subject, ptr));
if (strcmp(acl_user->x509_subject,ptr)) if (strcmp(acl_user->x509_subject,ptr))
{ {
if (global_system_variables.log_warnings) if (global_system_variables.log_warnings)
sql_print_error("X509 subject mismatch: '%s' vs '%s'", sql_print_error("X509 subject mismatch: '%s' vs '%s'",
acl_user->x509_subject, ptr); acl_user->x509_subject, ptr);
user_access=NO_ACCESS; }
} else
else thd->master_access= acl_user->access;
user_access=acl_user->access; free(ptr);
free(ptr);
} }
break; break;
#else /* HAVE_OPENSSL */ #else /* HAVE_OPENSSL */
default: default:
/* /*
If we don't have SSL but SSL is required for this user the If we don't have SSL but SSL is required for this user the
authentication should fail. authentication should fail.
*/ */
break; break;
#endif /* HAVE_OPENSSL */ #endif /* HAVE_OPENSSL */
} }
thd->priv_user= acl_user->user ? thd->user : (char *) "";
*mqh= acl_user->user_resource;
if (acl_user->host.hostname)
strmake(thd->priv_host, acl_user->host.hostname, MAX_HOSTNAME);
else
*thd->priv_host= 0;
} }
*mqh=acl_user->user_resource;
if (!acl_user->user)
*priv_user=(char*) ""; // Change to anonymous user /* purecov: inspected */
if (acl_user->host.hostname)
strmake(priv_host, acl_user->host.hostname, MAX_HOSTNAME);
else
*priv_host= 0;
unlock_and_exit:
VOID(pthread_mutex_unlock(&acl_cache->lock)); VOID(pthread_mutex_unlock(&acl_cache->lock));
DBUG_RETURN(user_access); DBUG_RETURN(res);
} }
@ -729,8 +755,9 @@ static byte* check_get_key(ACL_USER *buff,uint *length,
return (byte*) buff->host.hostname; return (byte*) buff->host.hostname;
} }
static void acl_update_user(const char *user, const char *host, static void acl_update_user(const char *user, const char *host,
const char *password, const char *password, uint password_len,
enum SSL_type ssl_type, enum SSL_type ssl_type,
const char *ssl_cipher, const char *ssl_cipher,
const char *x509_issuer, const char *x509_issuer,
@ -766,20 +793,9 @@ static void acl_update_user(const char *user, const char *host,
acl_user->x509_subject= (x509_subject ? acl_user->x509_subject= (x509_subject ?
strdup_root(&mem,x509_subject) : 0); strdup_root(&mem,x509_subject) : 0);
} }
if (password)
{ set_user_salt(acl_user, password, password_len);
if (!password[0]) /* If password is empty set it to null */ /* search complete: */
{
acl_user->password=0;
acl_user->pversion=0; // just initialize
}
else
{
acl_user->password=(char*) ""; // Just point at something
get_salt_from_password(acl_user->salt,password);
acl_user->pversion=get_password_version(acl_user->password);
}
}
break; break;
} }
} }
@ -788,7 +804,7 @@ static void acl_update_user(const char *user, const char *host,
static void acl_insert_user(const char *user, const char *host, static void acl_insert_user(const char *user, const char *host,
const char *password, const char *password, uint password_len,
enum SSL_type ssl_type, enum SSL_type ssl_type,
const char *ssl_cipher, const char *ssl_cipher,
const char *x509_issuer, const char *x509_issuer,
@ -799,7 +815,6 @@ static void acl_insert_user(const char *user, const char *host,
ACL_USER acl_user; ACL_USER acl_user;
acl_user.user=*user ? strdup_root(&mem,user) : 0; acl_user.user=*user ? strdup_root(&mem,user) : 0;
update_hostname(&acl_user.host,strdup_root(&mem,host)); update_hostname(&acl_user.host,strdup_root(&mem,host));
acl_user.password=0;
acl_user.access=privileges; acl_user.access=privileges;
acl_user.user_resource = *mqh; acl_user.user_resource = *mqh;
acl_user.sort=get_sort(2,acl_user.host.hostname,acl_user.user); acl_user.sort=get_sort(2,acl_user.host.hostname,acl_user.user);
@ -809,12 +824,8 @@ static void acl_insert_user(const char *user, const char *host,
acl_user.ssl_cipher= ssl_cipher ? strdup_root(&mem,ssl_cipher) : 0; acl_user.ssl_cipher= ssl_cipher ? strdup_root(&mem,ssl_cipher) : 0;
acl_user.x509_issuer= x509_issuer ? strdup_root(&mem,x509_issuer) : 0; acl_user.x509_issuer= x509_issuer ? strdup_root(&mem,x509_issuer) : 0;
acl_user.x509_subject=x509_subject ? strdup_root(&mem,x509_subject) : 0; acl_user.x509_subject=x509_subject ? strdup_root(&mem,x509_subject) : 0;
if (password)
{ set_user_salt(&acl_user, password, password_len);
acl_user.password=(char*) ""; // Just point at something
get_salt_from_password(acl_user.salt,password);
acl_user.pversion=get_password_version(password);
}
VOID(push_dynamic(&acl_users,(gptr) &acl_user)); VOID(push_dynamic(&acl_users,(gptr) &acl_user));
if (!acl_user.host.hostname || acl_user.host.hostname[0] == wild_many if (!acl_user.host.hostname || acl_user.host.hostname[0] == wild_many
@ -1151,7 +1162,6 @@ bool check_change_password(THD *thd, const char *host, const char *user)
bool change_password(THD *thd, const char *host, const char *user, bool change_password(THD *thd, const char *host, const char *user,
char *new_password) char *new_password)
{ {
uint length=0;
DBUG_ENTER("change_password"); DBUG_ENTER("change_password");
DBUG_PRINT("enter",("host: '%s' user: '%s' new_password: '%s'", DBUG_PRINT("enter",("host: '%s' user: '%s' new_password: '%s'",
host,user,new_password)); host,user,new_password));
@ -1160,37 +1170,27 @@ bool change_password(THD *thd, const char *host, const char *user,
if (check_change_password(thd, host, user)) if (check_change_password(thd, host, user))
DBUG_RETURN(1); DBUG_RETURN(1);
/*
password should always be 0,16 or 45 chars;
Simple hack to avoid cracking
*/
length=(uint) strlen(new_password);
if (length != 45)
new_password[length & 16]=0;
VOID(pthread_mutex_lock(&acl_cache->lock)); VOID(pthread_mutex_lock(&acl_cache->lock));
ACL_USER *acl_user; ACL_USER *acl_user;
if (!(acl_user= find_acl_user(host,user))) if (!(acl_user= find_acl_user(host, user)))
{ {
send_error(thd, ER_PASSWORD_NO_MATCH);
VOID(pthread_mutex_unlock(&acl_cache->lock)); VOID(pthread_mutex_unlock(&acl_cache->lock));
send_error(thd, ER_PASSWORD_NO_MATCH);
DBUG_RETURN(1); DBUG_RETURN(1);
} }
/* update loaded acl entry: */
uint new_password_len= new_password ? strlen(new_password) : 0;
set_user_salt(acl_user, new_password, new_password_len);
if (update_user_table(thd, if (update_user_table(thd,
acl_user->host.hostname ? acl_user->host.hostname : "", acl_user->host.hostname ? acl_user->host.hostname : "",
acl_user->user ? acl_user->user : "", acl_user->user ? acl_user->user : "",
new_password)) new_password, new_password_len))
{ {
VOID(pthread_mutex_unlock(&acl_cache->lock)); /* purecov: deadcode */ VOID(pthread_mutex_unlock(&acl_cache->lock)); /* purecov: deadcode */
send_error(thd,0); /* purecov: deadcode */ send_error(thd,0); /* purecov: deadcode */
DBUG_RETURN(1); /* purecov: deadcode */ DBUG_RETURN(1); /* purecov: deadcode */
} }
get_salt_from_password(acl_user->salt,new_password);
acl_user->pversion=get_password_version(new_password);
if (!new_password[0])
acl_user->password=0;
else
acl_user->password=(char*) ""; // Point at something
acl_cache->clear(1); // Clear locked hostname cache acl_cache->clear(1); // Clear locked hostname cache
VOID(pthread_mutex_unlock(&acl_cache->lock)); VOID(pthread_mutex_unlock(&acl_cache->lock));
@ -1230,7 +1230,7 @@ find_acl_user(const char *host, const char *user)
if (!acl_user->user && !user[0] || if (!acl_user->user && !user[0] ||
acl_user->user && !strcmp(user,acl_user->user)) acl_user->user && !strcmp(user,acl_user->user))
{ {
if (compare_hostname(&(acl_user->host),host,host)) if (compare_hostname(&acl_user->host,host,host))
{ {
DBUG_RETURN(acl_user); DBUG_RETURN(acl_user);
} }
@ -1303,7 +1303,7 @@ static bool compare_hostname(const acl_host_and_ip *host, const char *hostname,
*/ */
static bool update_user_table(THD *thd, const char *host, const char *user, static bool update_user_table(THD *thd, const char *host, const char *user,
const char *new_password) const char *new_password, uint new_password_len)
{ {
TABLE_LIST tables; TABLE_LIST tables;
TABLE *table; TABLE *table;
@ -1345,7 +1345,7 @@ static bool update_user_table(THD *thd, const char *host, const char *user,
DBUG_RETURN(1); /* purecov: deadcode */ DBUG_RETURN(1); /* purecov: deadcode */
} }
store_record(table,record[1]); store_record(table,record[1]);
table->field[2]->store(new_password,(uint) strlen(new_password), &my_charset_latin1); table->field[2]->store(new_password, new_password_len, &my_charset_latin1);
if ((error=table->file->update_row(table->record[1],table->record[0]))) if ((error=table->file->update_row(table->record[1],table->record[0])))
{ {
table->file->print_error(error,MYF(0)); /* purecov: deadcode */ table->file->print_error(error,MYF(0)); /* purecov: deadcode */
@ -1393,24 +1393,23 @@ static int replace_user_table(THD *thd, TABLE *table, const LEX_USER &combo,
{ {
int error = -1; int error = -1;
bool old_row_exists=0; bool old_row_exists=0;
char *password,empty_string[1]; const char *password= "";
uint password_len= 0;
char what= (revoke_grant) ? 'N' : 'Y'; char what= (revoke_grant) ? 'N' : 'Y';
DBUG_ENTER("replace_user_table"); DBUG_ENTER("replace_user_table");
safe_mutex_assert_owner(&acl_cache->lock); safe_mutex_assert_owner(&acl_cache->lock);
password=empty_string;
empty_string[0]=0;
if (combo.password.str && combo.password.str[0]) if (combo.password.str && combo.password.str[0])
{ {
if ((combo.password.length != HASH_PASSWORD_LENGTH) if (combo.password.length != SCRAMBLED_PASSWORD_CHAR_LENGTH &&
&& combo.password.length != HASH_OLD_PASSWORD_LENGTH) combo.password.length != SCRAMBLED_PASSWORD_CHAR_LENGTH_323)
{ {
my_printf_error(ER_PASSWORD_NO_MATCH, my_printf_error(ER_PASSWORD_NO_MATCH,
"Password hash should be a %d-digit hexadecimal number", "Password hash should be a %d-digit hexadecimal number",
MYF(0),HASH_PASSWORD_LENGTH); MYF(0), SCRAMBLED_PASSWORD_CHAR_LENGTH);
DBUG_RETURN(-1); DBUG_RETURN(-1);
} }
password_len= combo.password.length;
password=combo.password.str; password=combo.password.str;
} }
@ -1435,17 +1434,20 @@ static int replace_user_table(THD *thd, TABLE *table, const LEX_USER &combo,
goto end; goto end;
} }
old_row_exists = 0; old_row_exists = 0;
restore_record(table,default_values); // cp empty row from default_values restore_record(table,default_values); // cp empty row from default_values
table->field[0]->store(combo.host.str,combo.host.length, &my_charset_latin1); table->field[0]->store(combo.host.str,combo.host.length,
table->field[1]->store(combo.user.str,combo.user.length, &my_charset_latin1); &my_charset_latin1);
table->field[2]->store(password,(uint) strlen(password), &my_charset_latin1); table->field[1]->store(combo.user.str,combo.user.length,
&my_charset_latin1);
table->field[2]->store(password, password_len,
&my_charset_latin1);
} }
else else
{ {
old_row_exists = 1; old_row_exists = 1;
store_record(table,record[1]); // Save copy for update store_record(table,record[1]); // Save copy for update
if (combo.password.str) // If password given if (combo.password.str) // If password given
table->field[2]->store(password,(uint) strlen(password), &my_charset_latin1); table->field[2]->store(password, password_len, &my_charset_latin1);
} }
/* Update table columns with new privileges */ /* Update table columns with new privileges */
@ -1542,10 +1544,8 @@ end:
if (!error) if (!error)
{ {
acl_cache->clear(1); // Clear privilege cache acl_cache->clear(1); // Clear privilege cache
if (!combo.password.str)
password=0; // No password given on command
if (old_row_exists) if (old_row_exists)
acl_update_user(combo.user.str,combo.host.str,password, acl_update_user(combo.user.str, combo.host.str, password, password_len,
thd->lex.ssl_type, thd->lex.ssl_type,
thd->lex.ssl_cipher, thd->lex.ssl_cipher,
thd->lex.x509_issuer, thd->lex.x509_issuer,
@ -1553,7 +1553,7 @@ end:
&thd->lex.mqh, &thd->lex.mqh,
rights); rights);
else else
acl_insert_user(combo.user.str,combo.host.str,password, acl_insert_user(combo.user.str, combo.host.str, password, password_len,
thd->lex.ssl_type, thd->lex.ssl_type,
thd->lex.ssl_cipher, thd->lex.ssl_cipher,
thd->lex.x509_issuer, thd->lex.x509_issuer,
@ -3024,12 +3024,15 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user)
global.append ("'@'",3); global.append ("'@'",3);
global.append(lex_user->host.str,lex_user->host.length); global.append(lex_user->host.str,lex_user->host.length);
global.append ('\''); global.append ('\'');
if (acl_user->password) if (acl_user->salt_len)
{ {
char passd_buff[HASH_PASSWORD_LENGTH+1]; char passwd_buff[SCRAMBLED_PASSWORD_CHAR_LENGTH+1];
make_password_from_salt(passd_buff,acl_user->salt,acl_user->pversion); if (acl_user->salt_len == SCRAMBLE_LENGTH)
make_password_from_salt(passwd_buff, acl_user->salt);
else
make_password_from_salt_323(passwd_buff, (ulong *) acl_user->salt);
global.append(" IDENTIFIED BY PASSWORD '",25); global.append(" IDENTIFIED BY PASSWORD '",25);
global.append(passd_buff); global.append(passwd_buff);
global.append('\''); global.append('\'');
} }
/* "show grants" SSL related stuff */ /* "show grants" SSL related stuff */

View file

@ -111,9 +111,9 @@ public:
acl_host_and_ip host; acl_host_and_ip host;
uint hostname_length; uint hostname_length;
USER_RESOURCES user_resource; USER_RESOURCES user_resource;
char *user,*password; char *user;
ulong salt[6]; // New password has longer length uint8 salt[SCRAMBLE_LENGTH+1]; // scrambled password in binary form
uint8 pversion; // password version uint8 salt_len; // 0 - no password, 4 - 3.20, 8 - 3.23, 20 - 4.1.1
enum SSL_type ssl_type; enum SSL_type ssl_type;
const char *ssl_cipher, *x509_issuer, *x509_subject; const char *ssl_cipher, *x509_issuer, *x509_subject;
}; };
@ -135,11 +135,8 @@ void acl_reload(THD *thd);
void acl_free(bool end=0); void acl_free(bool end=0);
ulong acl_get(const char *host, const char *ip, const char *bin_ip, ulong acl_get(const char *host, const char *ip, const char *bin_ip,
const char *user, const char *db, my_bool db_is_pattern); const char *user, const char *db, my_bool db_is_pattern);
ulong acl_getroot(THD *thd, const char *host, const char *ip, const char *user, int acl_getroot(THD *thd, USER_RESOURCES *mqh, const char *passwd,
const char *password,const char *scramble, uint passwd_len);
char **priv_user, char *priv_host,
bool old_ver, USER_RESOURCES *max,char* prepared_scramble,
uint *cur_priv_version, ACL_USER **cached_user);
bool acl_check_host(const char *host, const char *ip); bool acl_check_host(const char *host, const char *ip);
bool check_change_password(THD *thd, const char *host, const char *user); bool check_change_password(THD *thd, const char *host, const char *user);
bool change_password(THD *thd, const char *host, const char *user, bool change_password(THD *thd, const char *host, const char *user,

View file

@ -138,6 +138,7 @@ THD::THD():user_time(0), is_fatal_error(0),
set_query_id=1; set_query_id=1;
db_access=NO_ACCESS; db_access=NO_ACCESS;
version=refresh_version; // For boot version=refresh_version; // For boot
*scramble= '\0';
init(); init();
/* Initialize sub structures */ /* Initialize sub structures */

View file

@ -399,6 +399,7 @@ struct system_variables
my_bool log_warnings; my_bool log_warnings;
my_bool low_priority_updates; my_bool low_priority_updates;
my_bool new_mode; my_bool new_mode;
my_bool old_passwords;
CHARSET_INFO *character_set_server; CHARSET_INFO *character_set_server;
CHARSET_INFO *character_set_database; CHARSET_INFO *character_set_database;
@ -556,10 +557,10 @@ public:
enum_tx_isolation session_tx_isolation; enum_tx_isolation session_tx_isolation;
/* for user variables replication*/ /* for user variables replication*/
DYNAMIC_ARRAY user_var_events; DYNAMIC_ARRAY user_var_events;
// extend scramble to handle new auth
char scramble[SCRAMBLE41_LENGTH+1]; /* scramble - random string sent to client on handshake */
// old scramble is needed to handle old clients char scramble[SCRAMBLE_LENGTH+1];
char old_scramble[SCRAMBLE_LENGTH+1];
uint8 query_cache_type; // type of query cache processing uint8 query_cache_type; // type of query cache processing
bool slave_thread; bool slave_thread;
bool set_query_id,locked,count_cuted_fields,some_tables_deleted; bool set_query_id,locked,count_cuted_fields,some_tables_deleted;

View file

@ -32,7 +32,7 @@
SQL_CRYPT::SQL_CRYPT(const char *password) SQL_CRYPT::SQL_CRYPT(const char *password)
{ {
ulong rand_nr[2]; ulong rand_nr[2];
hash_password(rand_nr,password); hash_password(rand_nr,password, strlen(password));
crypt_init(rand_nr); crypt_init(rand_nr);
} }

View file

@ -178,153 +178,179 @@ end:
/* /*
Check if user is ok Check if user exist and password supplied is correct.
SYNOPSIS SYNOPSIS
check_user() check_user()
thd Thread handle thd thread handle, thd->{host,user,ip} are used
command Command for connection (for log) command originator of the check: now check_user is called
user Name of user trying to connect during connect and change user procedures; used for
passwd Scrambled password sent from client logging.
db Database to connect to passwd scrambled password recieved from client
check_count If set to 1, don't allow too many connection passwd_len length of scrambled password
simple_connect If 1 then client is of old type and we should connect db database name to connect to, may be NULL
using the old method (no challange) check_count dont know exactly
do_send_error Set to 1 if we should send error to user
prepared_scramble Buffer to store hash password of new connection
had_password Set to 1 if the user gave a password
cur_priv_version Check flag to know if someone flushed the privileges
since last code
hint_user Pointer used by acl_getroot() to remmeber user for
next call
RETURN Note, that host, user and passwd may point to communication buffer.
0 ok Current implementation does not depened on that, but future changes
thd->user, thd->master_access, thd->priv_user, thd->db and should be done with this in mind; 'thd' is INOUT, all other params
thd->db_access are updated are 'IN'.
1 Access denied; Error sent to client
-1 If do_send_error == 1: Failed connect, error sent to client RETURN VALUE
If do_send_error == 0: Prepare for stage of connect 0 OK; thd->user, thd->master_access, thd->priv_user, thd->db and
thd->db_access are updated; OK is sent to client;
-1 access denied or handshake error; error is sent to client;
>0 error, not sent to client
*/ */
static int check_user(THD *thd,enum_server_command command, const char *user, static int check_user(THD *thd, enum enum_server_command command,
const char *passwd, const char *db, bool check_count, const char *passwd, uint passwd_len, const char *db,
bool simple_connect, bool do_send_error, bool check_count)
char *prepared_scramble, bool had_password,
uint *cur_priv_version, ACL_USER** hint_user)
{ {
thd->db=0;
thd->db_length=0;
USER_RESOURCES ur;
char tmp_passwd[SCRAMBLE41_LENGTH+1];
DBUG_ENTER("check_user"); DBUG_ENTER("check_user");
my_bool opt_secure_auth_local;
pthread_mutex_lock(&LOCK_global_system_variables);
opt_secure_auth_local= opt_secure_auth;
pthread_mutex_unlock(&LOCK_global_system_variables);
/* /*
Move password to temporary buffer as it may be stored in communication If the server is running in secure auth mode, short scrambles are
buffer forbidden.
*/ */
strmake(tmp_passwd, passwd, sizeof(tmp_passwd)); if (opt_secure_auth_local && passwd_len == SCRAMBLE_LENGTH_323)
passwd= tmp_passwd; // Use local copy
/* We shall avoid dupplicate user allocations here */
if (!thd->user && !(thd->user = my_strdup(user, MYF(0))))
{ {
send_error(thd,ER_OUT_OF_RESOURCES); net_printf(thd, ER_NOT_SUPPORTED_AUTH_MODE);
DBUG_RETURN(1); mysql_log.write(thd, COM_CONNECT, ER(ER_NOT_SUPPORTED_AUTH_MODE));
DBUG_RETURN(-1);
} }
thd->master_access=acl_getroot(thd, thd->host, thd->ip, thd->user, if (passwd_len != 0 &&
passwd, thd->scramble, passwd_len != SCRAMBLE_LENGTH &&
&thd->priv_user, thd->priv_host, passwd_len != SCRAMBLE_LENGTH_323)
(protocol_version == 9 || DBUG_RETURN(ER_HANDSHAKE_ERROR);
!(thd->client_capabilities &
CLIENT_LONG_PASSWORD)),
&ur,prepared_scramble,
cur_priv_version,hint_user);
DBUG_PRINT("info",
("Capabilities: %d packet_length: %ld Host: '%s' Login user: '%s' Priv_user: '%s' Using password: %s Access: %u db: '%s'",
thd->client_capabilities, thd->max_client_packet_length,
thd->host_or_ip, thd->user, thd->priv_user,
had_password ? "yes": "no",
thd->master_access, thd->db ? thd->db : "*none*"));
/* /*
In case we're going to retry we should not send error message at this Clear thd->db as it points to something, that will be freed when
point connection is closed. We don't want to accidently free a wrong pointer
if connect failed. Also in case of 'CHANGE USER' failure, current
database will be switched to 'no database selected'.
*/ */
if (thd->master_access & NO_ACCESS) thd->db= 0;
thd->db_length= 0;
USER_RESOURCES ur;
int res= acl_getroot(thd, &ur, passwd, passwd_len);
if (res == -1)
{ {
if (do_send_error || !had_password || !*hint_user) /*
This happens when client (new) sends password scrambled with
scramble(), but database holds old value (scrambled with
scramble_323()). Here we please client to send scrambled_password
in old format.
*/
NET *net= &thd->net;
if (opt_secure_auth_local)
{ {
DBUG_PRINT("info",("Access denied")); net_printf(thd, ER_SERVER_IS_IN_SECURE_AUTH_MODE,
/* thd->user, thd->host_or_ip);
Old client should get nicer error message if password version is mysql_log.write(thd, COM_CONNECT, ER(ER_SERVER_IS_IN_SECURE_AUTH_MODE),
not supported thd->user, thd->host_or_ip);
*/ DBUG_RETURN(-1);
if (simple_connect && *hint_user && (*hint_user)->pversion) }
if (send_old_password_request(thd) ||
my_net_read(net) != SCRAMBLE_LENGTH_323 + 1) // We have to read very
{ // specific packet size
inc_host_errors(&thd->remote.sin_addr);
DBUG_RETURN(ER_HANDSHAKE_ERROR);
}
/* Final attempt to check the user based on reply */
/* So as passwd is short, errcode is always >= 0 */
res= acl_getroot(thd, &ur, (char *) net->read_pos, SCRAMBLE_LENGTH_323);
}
/* here res is always >= 0 */
if (res == 0)
{
if (!(thd->master_access & NO_ACCESS)) // authentification is OK
{
DBUG_PRINT("info",
("Capabilities: %d packet_length: %ld Host: '%s' "
"Login user: '%s' Priv_user: '%s' Using password: %s "
"Access: %u db: '%s'",
thd->client_capabilities, thd->max_client_packet_length,
thd->host_or_ip, thd->user, thd->priv_user,
passwd_len ? "yes": "no",
thd->master_access, thd->db ? thd->db : "*none*"));
if (check_count)
{ {
net_printf(thd, ER_NOT_SUPPORTED_AUTH_MODE); VOID(pthread_mutex_lock(&LOCK_thread_count));
mysql_log.write(thd,COM_CONNECT,ER(ER_NOT_SUPPORTED_AUTH_MODE)); bool count_ok= thread_count < max_connections + delayed_insert_threads
|| (thd->master_access & SUPER_ACL);
VOID(pthread_mutex_unlock(&LOCK_thread_count));
if (!count_ok)
{ // too many connections
send_error(thd, ER_CON_COUNT_ERROR);
DBUG_RETURN(-1);
}
}
/* Why logging is performed before all checks've passed? */
mysql_log.write(thd,command,
(thd->priv_user == thd->user ?
(char*) "%s@%s on %s" :
(char*) "%s@%s as anonymous on %s"),
thd->user, thd->host_or_ip,
db ? db : (char*) "");
/*
This is the default access rights for the current database. It's
set to 0 here because we don't have an active database yet (and we
may not have an active database to set.
*/
thd->db_access=0;
/* Don't allow user to connect if he has done too many queries */
if ((ur.questions || ur.updates ||
ur.connections || max_user_connections) &&
get_or_create_user_conn(thd,thd->user,thd->host_or_ip,&ur))
DBUG_RETURN(1);
if (thd->user_connect && thd->user_connect->user_resources.connections &&
check_for_max_user_connections(thd, thd->user_connect))
DBUG_RETURN(1);
/* Change database if necessary: OK or FAIL is sent in mysql_change_db */
if (db && db[0])
{
if (mysql_change_db(thd, db))
{
if (thd->user_connect)
decrease_user_connections(thd->user_connect);
DBUG_RETURN(-1);
}
} }
else else
{ send_ok(thd);
net_printf(thd, ER_ACCESS_DENIED_ERROR, thd->password= test(passwd_len); // remember for error messages
thd->user, /* Ready to handle queries */
thd->host_or_ip, DBUG_RETURN(0);
had_password ? ER(ER_YES) : ER(ER_NO));
mysql_log.write(thd,COM_CONNECT,ER(ER_ACCESS_DENIED_ERROR),
thd->user,
thd->host_or_ip,
had_password ? ER(ER_YES) : ER(ER_NO));
}
DBUG_RETURN(1); // Error already given
}
DBUG_PRINT("info",("Prepare for second part of handshake"));
DBUG_RETURN(-1); // no report error in special handshake
}
if (check_count)
{
VOID(pthread_mutex_lock(&LOCK_thread_count));
bool tmp=(thread_count - delayed_insert_threads >= max_connections &&
!(thd->master_access & SUPER_ACL));
VOID(pthread_mutex_unlock(&LOCK_thread_count));
if (tmp)
{ // Too many connections
send_error(thd, ER_CON_COUNT_ERROR);
DBUG_RETURN(1);
} }
} }
mysql_log.write(thd,command, else if (res == 2) // client gave short hash, server has long hash
(thd->priv_user == thd->user ?
(char*) "%s@%s on %s" :
(char*) "%s@%s as anonymous on %s"),
user,
thd->host_or_ip,
db ? db : (char*) "");
thd->db_access=0;
/* Don't allow user to connect if he has done too many queries */
if ((ur.questions || ur.updates || ur.connections || max_user_connections) &&
get_or_create_user_conn(thd,user,thd->host_or_ip,&ur))
DBUG_RETURN(1);
if (thd->user_connect && ((thd->user_connect->user_resources.connections) ||
max_user_connections) &&
check_for_max_user_connections(thd, thd->user_connect))
DBUG_RETURN(1);
if (db && db[0])
{ {
int error= test(mysql_change_db(thd,db)); net_printf(thd, ER_NOT_SUPPORTED_AUTH_MODE);
if (error && thd->user_connect) mysql_log.write(thd,COM_CONNECT,ER(ER_NOT_SUPPORTED_AUTH_MODE));
decrease_user_connections(thd->user_connect); DBUG_RETURN(-1);
DBUG_RETURN(error);
} }
send_ok(thd); // Ready to handle questions net_printf(thd, ER_ACCESS_DENIED_ERROR,
thd->password= test(passwd[0]); // Remember for error messages thd->user,
DBUG_RETURN(0); // ok thd->host_or_ip,
passwd_len ? ER(ER_YES) : ER(ER_NO));
mysql_log.write(thd, COM_CONNECT, ER(ER_ACCESS_DENIED_ERROR),
thd->user,
thd->host_or_ip,
passwd_len ? ER(ER_YES) : ER(ER_NO));
DBUG_RETURN(-1);
} }
/* /*
Check for maximum allowable user connections, if the mysqld server is Check for maximum allowable user connections, if the mysqld server is
started with corresponding variable that is greater then 0. started with corresponding variable that is greater then 0.
@ -526,45 +552,36 @@ static void reset_mqh(THD *thd, LEX_USER *lu, bool get_them= 0)
/* /*
Check connnectionn and get priviliges Perform handshake, authorize client and update thd ACL variables.
SYNOPSIS SYNOPSIS
check_connections check_connection()
thd Thread handle thd thread handle
RETURN RETURN
0 ok 0 success, OK is sent to user, thd is updated.
-1 Error, which is sent to user -1 error, which is sent to user
> 0 Error code (not sent to user) > 0 error code (not sent to user)
*/ */
#ifndef EMBEDDED_LIBRARY #ifndef EMBEDDED_LIBRARY
static int static int
check_connections(THD *thd) check_connection(THD *thd)
{ {
int res; uint connect_errors= 0;
uint connect_errors=0;
uint cur_priv_version;
bool using_password;
NET *net= &thd->net; NET *net= &thd->net;
char *end, *user, *passwd, *db;
char prepared_scramble[SCRAMBLE41_LENGTH+4]; /* Buffer for scramble&hash */
char db_buff[NAME_LEN+1];
ACL_USER* cached_user=NULL; /* Initialise to NULL for first stage */
DBUG_PRINT("info",("New connection received on %s",
vio_description(net->vio)));
/* Remove warning from valgrind. TODO: Fix it in password.c */ DBUG_PRINT("info",
bzero((char*) &prepared_scramble[0], sizeof(prepared_scramble)); ("New connection received on %s", vio_description(net->vio)));
if (!thd->host) // If TCP/IP connection if (!thd->host) // If TCP/IP connection
{ {
char ip[30]; char ip[30];
if (vio_peer_addr(net->vio, ip, &thd->peer_port)) if (vio_peer_addr(net->vio, ip, &thd->peer_port))
return (ER_BAD_HOST_ERROR); return (ER_BAD_HOST_ERROR);
if (!(thd->ip = my_strdup(ip,MYF(0)))) if (!(thd->ip= my_strdup(ip,MYF(0))))
return (ER_OUT_OF_RESOURCES); return (ER_OUT_OF_RESOURCES);
thd->host_or_ip=thd->ip; thd->host_or_ip= thd->ip;
#if !defined(HAVE_SYS_UN_H) || defined(HAVE_mit_thread) #if !defined(HAVE_SYS_UN_H) || defined(HAVE_mit_thread)
/* Fast local hostname resolve for Win32 */ /* Fast local hostname resolve for Win32 */
if (!strcmp(thd->ip,"127.0.0.1")) if (!strcmp(thd->ip,"127.0.0.1"))
@ -600,15 +617,16 @@ check_connections(THD *thd)
DBUG_PRINT("info",("Host: %s",thd->host)); DBUG_PRINT("info",("Host: %s",thd->host));
thd->host_or_ip= thd->host; thd->host_or_ip= thd->host;
thd->ip= 0; thd->ip= 0;
bzero((char*) &thd->remote,sizeof(struct sockaddr)); bzero((char*) &thd->remote, sizeof(struct sockaddr));
} }
/* Ensure that wrong hostnames doesn't cause buffer overflows */ /* Ensure that wrong hostnames doesn't cause buffer overflows */
vio_keepalive(net->vio, TRUE); vio_keepalive(net->vio, TRUE);
ulong pkt_len=0; ulong pkt_len= 0;
char *end;
{ {
/* buff[] needs to big enough to hold the server_version variable */ /* buff[] needs to big enough to hold the server_version variable */
char buff[SERVER_VERSION_LENGTH + SCRAMBLE_LENGTH+64]; char buff[SERVER_VERSION_LENGTH + SCRAMBLE_LENGTH + 64];
ulong client_flags = (CLIENT_LONG_FLAG | CLIENT_CONNECT_WITH_DB | ulong client_flags = (CLIENT_LONG_FLAG | CLIENT_CONNECT_WITH_DB |
CLIENT_PROTOCOL_41 | CLIENT_SECURE_CONNECTION); CLIENT_PROTOCOL_41 | CLIENT_SECURE_CONNECTION);
@ -622,19 +640,34 @@ check_connections(THD *thd)
client_flags |= CLIENT_SSL; /* Wow, SSL is avalaible! */ client_flags |= CLIENT_SSL; /* Wow, SSL is avalaible! */
#endif /* HAVE_OPENSSL */ #endif /* HAVE_OPENSSL */
end=strnmov(buff,server_version,SERVER_VERSION_LENGTH)+1; end= strnmov(buff, server_version, SERVER_VERSION_LENGTH) + 1;
int4store((uchar*) end,thd->thread_id); int4store((uchar*) end, thd->thread_id);
end+=4; end+= 4;
memcpy(end,thd->scramble,SCRAMBLE_LENGTH+1); /*
end+=SCRAMBLE_LENGTH +1; So as check_connection is the only entry point to authorization
int2store(end,client_flags); procedure, scramble is set here. This gives us new scramble for
each handshake.
*/
create_random_string(thd->scramble, SCRAMBLE_LENGTH, &thd->rand);
/*
Old clients does not understand long scrambles, but can ignore packet
tail: that's why first part of the scramble is placed here, and second
part at the end of packet.
*/
end= strmake(end, thd->scramble, SCRAMBLE_LENGTH_323) + 1;
int2store(end, client_flags);
/* write server characteristics: up to 16 bytes allowed */
end[2]=(char) default_charset_info->number; end[2]=(char) default_charset_info->number;
int2store(end+3,thd->server_status); int2store(end+3, thd->server_status);
bzero(end+5,13); bzero(end+5, 13);
end+=18; end+= 18;
/* write scramble tail */
end= strmake(end, thd->scramble + SCRAMBLE_LENGTH_323,
SCRAMBLE_LENGTH - SCRAMBLE_LENGTH_323) + 1;
// At this point we write connection message and read reply /* At this point we write connection message and read reply */
if (net_write_command(net,(uchar) protocol_version, "", 0, buff, if (net_write_command(net, (uchar) protocol_version, "", 0, buff,
(uint) (end-buff)) || (uint) (end-buff)) ||
(pkt_len= my_net_read(net)) == packet_error || (pkt_len= my_net_read(net)) == packet_error ||
pkt_len < MIN_HANDSHAKE_SIZE) pkt_len < MIN_HANDSHAKE_SIZE)
@ -723,7 +756,7 @@ check_connections(THD *thd)
return(ER_HANDSHAKE_ERROR); return(ER_HANDSHAKE_ERROR);
} }
DBUG_PRINT("info", ("Reading user information over SSL layer")); DBUG_PRINT("info", ("Reading user information over SSL layer"));
if ((pkt_len=my_net_read(net)) == packet_error || if ((pkt_len= my_net_read(net)) == packet_error ||
pkt_len < NORMAL_HANDSHAKE_SIZE) pkt_len < NORMAL_HANDSHAKE_SIZE)
{ {
DBUG_PRINT("error", ("Failed to read user information (pkt_len= %lu)", DBUG_PRINT("error", ("Failed to read user information (pkt_len= %lu)",
@ -740,13 +773,30 @@ check_connections(THD *thd)
return(ER_HANDSHAKE_ERROR); return(ER_HANDSHAKE_ERROR);
} }
user= end; if (thd->client_capabilities & CLIENT_INTERACTIVE)
passwd= strend(user)+1; thd->variables.net_wait_timeout= thd->variables.net_interactive_timeout;
db=0; if ((thd->client_capabilities & CLIENT_TRANSACTIONS) &&
using_password= test(passwd[0]); opt_using_transactions)
if (thd->client_capabilities & CLIENT_CONNECT_WITH_DB) net->return_status= &thd->server_status;
net->read_timeout=(uint) thd->variables.net_read_timeout;
char *user= end;
char *passwd= strend(user)+1;
char *db= passwd;
char db_buff[NAME_LEN+1]; // buffer to store db in utf8
/*
Old clients send null-terminated string as password; new clients send
the size (1 byte) + string (not null-terminated). Hence in case of empty
password both send '\0'.
*/
uint passwd_len= thd->client_capabilities & CLIENT_SECURE_CONNECTION ?
*passwd++ : strlen(passwd);
db= thd->client_capabilities & CLIENT_CONNECT_WITH_DB ?
db + passwd_len + 1 : 0;
/* Since 4.1 all database names are stored in utf8 */
if (db)
{ {
db= strend(passwd)+1;
uint32 length= copy_and_convert(db_buff, sizeof(db_buff)-1, uint32 length= copy_and_convert(db_buff, sizeof(db_buff)-1,
system_charset_info, system_charset_info,
db, strlen(db), db, strlen(db),
@ -755,71 +805,11 @@ check_connections(THD *thd)
db= db_buff; db= db_buff;
} }
/* We can get only old hash at this point */ if (thd->user)
if (using_password && strlen(passwd) != SCRAMBLE_LENGTH) x_free(thd->user);
return ER_HANDSHAKE_ERROR; if (!(thd->user= my_strdup(user, MYF(0))))
return (ER_OUT_OF_RESOURCES);
if (thd->client_capabilities & CLIENT_INTERACTIVE) return check_user(thd, COM_CONNECT, passwd, passwd_len, db, true);
thd->variables.net_wait_timeout= thd->variables.net_interactive_timeout;
if ((thd->client_capabilities & CLIENT_TRANSACTIONS) &&
opt_using_transactions)
net->return_status= &thd->server_status;
net->read_timeout=(uint) thd->variables.net_read_timeout;
/* Simple connect only for old clients. New clients always use secure auth */
bool simple_connect=(!(thd->client_capabilities & CLIENT_SECURE_CONNECTION));
/* Check user permissions. If password failure we'll get scramble back */
if ((res=check_user(thd, COM_CONNECT, user, passwd, db, 1, simple_connect,
simple_connect, prepared_scramble, using_password,
&cur_priv_version,
&cached_user)) < 0)
{
/* Store current used and database as they are erased with next packet */
char tmp_user[USERNAME_LENGTH+1];
char tmp_db[NAME_LEN+1];
/* If the client is old we just have to return error */
if (simple_connect)
return -1;
DBUG_PRINT("info",("password challenge"));
tmp_user[0]= tmp_db[0]= 0;
if (user)
strmake(tmp_user,user,USERNAME_LENGTH);
if (db)
strmake(tmp_db,db,NAME_LEN);
/* Write hash and encrypted scramble to client */
if (my_net_write(net,prepared_scramble,SCRAMBLE41_LENGTH+4) ||
net_flush(net))
{
inc_host_errors(&thd->remote.sin_addr);
return ER_HANDSHAKE_ERROR;
}
/* Reading packet back */
if ((pkt_len= my_net_read(net)) == packet_error)
{
inc_host_errors(&thd->remote.sin_addr);
return ER_HANDSHAKE_ERROR;
}
/* We have to get very specific packet size */
if (pkt_len != SCRAMBLE41_LENGTH)
{
inc_host_errors(&thd->remote.sin_addr);
return ER_HANDSHAKE_ERROR;
}
/* Final attempt to check the user based on reply */
if (check_user(thd,COM_CONNECT, tmp_user, (char*)net->read_pos,
tmp_db, 1, 0, 1, prepared_scramble, using_password,
&cur_priv_version,
&cached_user))
return -1;
}
else if (res)
return -1; // Error sent from check_user()
return 0;
} }
@ -876,7 +866,7 @@ pthread_handler_decl(handle_one_connection,arg)
NET *net= &thd->net; NET *net= &thd->net;
thd->thread_stack= (char*) &thd; thd->thread_stack= (char*) &thd;
if ((error=check_connections(thd))) if ((error=check_connection(thd)))
{ // Wrong permissions { // Wrong permissions
if (error > 0) if (error > 0)
net_printf(thd,error,thd->host_or_ip); net_printf(thd,error,thd->host_or_ip);
@ -1188,116 +1178,74 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
case COM_CHANGE_USER: case COM_CHANGE_USER:
{ {
thd->change_user(); thd->change_user();
thd->clear_error(); // If errors from rollback thd->clear_error(); // if errors from rollback
statistic_increment(com_other,&LOCK_status); statistic_increment(com_other, &LOCK_status);
char *user= (char*) packet; char *user= (char*) packet;
char *passwd= strend(user)+1; char *passwd= strend(user)+1;
char *db= strend(passwd)+1; /*
Old clients send null-terminated string ('\0' for empty string) for
password. New clients send the size (1 byte) + string (not null
terminated, so also '\0' for empty string).
*/
char *db= passwd;
uint passwd_len= thd->client_capabilities & CLIENT_SECURE_CONNECTION ?
*passwd++ : strlen(passwd);
db+= passwd_len + 1;
/* Convert database name to utf8 */
String convdb;
convdb.copy(db, strlen(db), thd->variables.character_set_client,
system_charset_info);
db= convdb.c_ptr();
/* Small check for incomming packet */
if ((uint) ((uchar*) db - net->read_pos) > packet_length)
{
send_error(thd, ER_UNKNOWN_COM_ERROR);
break;
}
/* Save user and privileges */ /* Save user and privileges */
uint save_master_access=thd->master_access; uint save_master_access= thd->master_access;
uint save_db_access= thd->db_access; uint save_db_access= thd->db_access;
uint save_db_length= thd->db_length; uint save_db_length= thd->db_length;
char *save_user= thd->user; char *save_user= thd->user;
thd->user=NULL; /* Needed for check_user to allocate new user */ char *save_priv_user= thd->priv_user;
char *save_priv_user= thd->priv_user; char *save_db= thd->db;
char *save_db= thd->db; USER_CONN *save_uc= thd->user_connect;
USER_CONN *save_uc= thd->user_connect; thd->user= my_strdup(user, MYF(0));
bool simple_connect; if (!thd->user)
bool using_password;
char prepared_scramble[SCRAMBLE41_LENGTH+4];/* Buffer for scramble,hash */
char tmp_user[USERNAME_LENGTH+1];
char tmp_db[NAME_LEN+1];
ACL_USER* cached_user ; /* Cached user */
uint cur_priv_version; /* Cached grant version */
int res;
ulong pkt_len= 0; /* Length of reply packet */
bzero((char*) prepared_scramble, sizeof(prepared_scramble));
/* Small check for incomming packet */
if ((uint) ((uchar*) db - net->read_pos) > packet_length)
goto restore_user_err;
/* Now we shall basically perform authentication again */
/* We can get only old hash at this point */
if (passwd[0] && strlen(passwd)!=SCRAMBLE_LENGTH)
goto restore_user_err;
cached_user= NULL;
/* Simple connect only for old clients. New clients always use sec. auth*/
simple_connect=(!(thd->client_capabilities & CLIENT_SECURE_CONNECTION));
/* Store information if we used password. passwd will be dammaged */
using_password=test(passwd[0]);
if (simple_connect) /* Restore scramble for old clients */
memcpy(thd->scramble,thd->old_scramble,9);
/*
Check user permissions. If password failure we'll get scramble back
Do not retry if we already have sent error (result>0)
*/
if ((res=check_user(thd,COM_CHANGE_USER, user, passwd, db, 0,
simple_connect, simple_connect, prepared_scramble,
using_password, &cur_priv_version, &cached_user)) < 0)
{ {
/* If the client is old we just have to have auth failure */ thd->user= save_user;
if (simple_connect) send_error(thd, ER_OUT_OF_RESOURCES);
goto restore_user; /* Error is already reported */ break;
/* Store current used and database as they are erased with next packet */
tmp_user[0]= tmp_db[0]= 0;
if (user)
strmake(tmp_user,user,USERNAME_LENGTH);
if (db)
strmake(tmp_db,db,NAME_LEN);
/* Write hash and encrypted scramble to client */
if (my_net_write(net,prepared_scramble,SCRAMBLE41_LENGTH+4) ||
net_flush(net))
goto restore_user_err;
/* Reading packet back */
if ((pkt_len=my_net_read(net)) == packet_error)
goto restore_user_err;
/* We have to get very specific packet size */
if (pkt_len != SCRAMBLE41_LENGTH)
goto restore_user;
/* Final attempt to check the user based on reply */
if (check_user(thd,COM_CHANGE_USER, tmp_user, (char*) net->read_pos,
tmp_db, 0, 0, 1, prepared_scramble, using_password,
&cur_priv_version, &cached_user))
goto restore_user;
} }
else if (res)
goto restore_user;
/* Finally we've authenticated new user */ int res= check_user(thd, COM_CHANGE_USER, passwd, passwd_len, db, false);
if (max_connections && save_uc)
decrease_user_connections(save_uc);
x_free((gptr) save_db);
x_free((gptr) save_user);
thd->password=using_password;
break;
/* Bad luck we shall restore old user */ if (res)
restore_user_err: {
send_error(thd, ER_UNKNOWN_COM_ERROR); /* authentification failure, we shall restore old user */
if (res > 0)
restore_user: send_error(thd, ER_UNKNOWN_COM_ERROR);
x_free(thd->user); x_free(thd->user);
thd->master_access=save_master_access; thd->user= save_user;
thd->db_access=save_db_access; thd->priv_user= save_priv_user;
thd->db=save_db; thd->master_access= save_master_access;
thd->db_length=save_db_length; thd->db_access= save_db_access;
thd->user=save_user; thd->db= save_db;
thd->priv_user=save_priv_user; thd->db_length= save_db_length;
}
else
{
/* we've authenticated new user */
if (max_connections && save_uc)
decrease_user_connections(save_uc);
x_free((gptr) save_db);
x_free((gptr) save_user);
}
break; break;
} }
#endif /* EMBEDDED_LIBRARY */ #endif /* EMBEDDED_LIBRARY */
@ -3247,7 +3195,7 @@ error:
Check grants for commands which work only with one table and all other Check grants for commands which work only with one table and all other
tables belong to subselects. tables belong to subselects.
SYNOPSYS SYNOPSIS
single_table_command_access() single_table_command_access()
thd - Thread handler thd - Thread handler
privilege - asked privelage privilege - asked privelage

View file

@ -506,6 +506,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token MULTIPOINT %token MULTIPOINT
%token MULTIPOLYGON %token MULTIPOLYGON
%token NOW_SYM %token NOW_SYM
%token OLD_PASSWORD
%token PASSWORD %token PASSWORD
%token POINTFROMTEXT %token POINTFROMTEXT
%token POINT_SYM %token POINT_SYM
@ -2607,9 +2608,13 @@ simple_expr:
| NOW_SYM '(' expr ')' | NOW_SYM '(' expr ')'
{ $$= new Item_func_now_local($3); Lex->safe_to_cache_query=0;} { $$= new Item_func_now_local($3); Lex->safe_to_cache_query=0;}
| PASSWORD '(' expr ')' | PASSWORD '(' expr ')'
{ $$= new Item_func_password($3); } {
| PASSWORD '(' expr ',' expr ')' $$= YYTHD->variables.old_passwords ?
{ $$= new Item_func_password($3,$5); } (Item *) new Item_func_old_password($3) :
(Item *) new Item_func_password($3);
}
| OLD_PASSWORD '(' expr ')'
{ $$= new Item_func_old_password($3); }
| POINT_SYM '(' expr ',' expr ')' | POINT_SYM '(' expr ',' expr ')'
{ $$= new Item_func_point($3,$5); } { $$= new Item_func_point($3,$5); }
| POINTFROMTEXT '(' expr ')' | POINTFROMTEXT '(' expr ')'
@ -4517,6 +4522,7 @@ keyword:
| NO_SYM {} | NO_SYM {}
| NONE_SYM {} | NONE_SYM {}
| OFFSET_SYM {} | OFFSET_SYM {}
| OLD_PASSWORD {}
| OPEN_SYM {} | OPEN_SYM {}
| PACK_KEYS_SYM {} | PACK_KEYS_SYM {}
| PARTIAL {} | PARTIAL {}
@ -4741,15 +4747,15 @@ text_or_password:
TEXT_STRING { $$=$1.str;} TEXT_STRING { $$=$1.str;}
| PASSWORD '(' TEXT_STRING ')' | PASSWORD '(' TEXT_STRING ')'
{ {
if (!$3.length) $$= $3.length ? YYTHD->variables.old_passwords ?
$$=$3.str; Item_func_old_password::alloc(YYTHD, $3.str) :
else Item_func_password::alloc(YYTHD, $3.str) :
{ $3.str;
char *buff=(char*) YYTHD->alloc(HASH_PASSWORD_LENGTH+1); }
make_scrambled_password(buff,$3.str,use_old_passwords, | OLD_PASSWORD '(' TEXT_STRING ')'
&YYTHD->rand); {
$$=buff; $$= $3.length ? Item_func_old_password::alloc(YYTHD, $3.str) :
} $3.str;
} }
; ;
@ -5057,14 +5063,24 @@ grant_user:
$$=$1; $1->password=$4; $$=$1; $1->password=$4;
if ($4.length) if ($4.length)
{ {
char *buff=(char*) YYTHD->alloc(HASH_PASSWORD_LENGTH+1); if (YYTHD->variables.old_passwords)
if (buff) {
{ char *buff=
make_scrambled_password(buff,$4.str,use_old_passwords, (char *) YYTHD->alloc(SCRAMBLED_PASSWORD_CHAR_LENGTH_323+1);
&YYTHD->rand); if (buff)
$1->password.str=buff; make_scrambled_password_323(buff, $4.str);
$1->password.length=HASH_PASSWORD_LENGTH; $1->password.str= buff;
} $1->password.length= SCRAMBLED_PASSWORD_CHAR_LENGTH_323;
}
else
{
char *buff=
(char *) YYTHD->alloc(SCRAMBLED_PASSWORD_CHAR_LENGTH+1);
if (buff)
make_scrambled_password(buff, $4.str);
$1->password.str= buff;
$1->password.length= SCRAMBLED_PASSWORD_CHAR_LENGTH;
}
} }
} }
| user IDENTIFIED_SYM BY PASSWORD TEXT_STRING | user IDENTIFIED_SYM BY PASSWORD TEXT_STRING