summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.bzrignore5
-rw-r--r--include/mysql_com.h2
-rw-r--r--libmysql/libmysql.c18
-rw-r--r--sql-common/client.c24
-rw-r--r--sql/item_create.cc12
-rw-r--r--sql/item_create.h2
-rw-r--r--sql/item_strfunc.cc16
-rw-r--r--sql/item_strfunc.h3
-rw-r--r--sql/lex.h2
-rw-r--r--sql/password.c12
-rw-r--r--sql/sql_acl.cc9
-rw-r--r--sql/sql_parse.cc250
-rw-r--r--sql/sql_yacc.yy37
13 files changed, 201 insertions, 191 deletions
diff --git a/.bzrignore b/.bzrignore
index a23384d4170..7c0a871a951 100644
--- a/.bzrignore
+++ b/.bzrignore
@@ -624,3 +624,8 @@ vio/test-sslserver
vio/viotest-ssl
start_mysqld.sh
mysys/main.cc
+BitKeeper/post-commit
+BitKeeper/post-commit-manual
+build_tags.sh
+tests/connect_test
+BUILD/compile-pentium-maintainer
diff --git a/include/mysql_com.h b/include/mysql_com.h
index c1f18160667..784a7782855 100644
--- a/include/mysql_com.h
+++ b/include/mysql_com.h
@@ -327,7 +327,7 @@ void get_salt_from_password_323(unsigned long *res, const char *password);
void make_password_from_salt_323(char *to, const unsigned long *salt);
void make_scrambled_password(char *to, const char *password);
-char *scramble(char *to, const char *message, const char *password);
+void scramble(char *to, const char *message, const char *password);
my_bool check_scramble(const char *reply, const char *message,
const unsigned char *hash_stage2);
void get_salt_from_password(unsigned char *res, const char *password);
diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c
index 6bc38abb060..8b83343df8f 100644
--- a/libmysql/libmysql.c
+++ b/libmysql/libmysql.c
@@ -619,16 +619,20 @@ my_bool STDCALL mysql_change_user(MYSQL *mysql, const char *user,
/* write scrambled password according to server capabilities */
if (passwd[0])
{
- /* Write NULL-terminated scrambled password: */
- end= mysql->server_capabilities & CLIENT_SECURE_CONNECTION ?
- scramble(end, mysql->scramble, passwd) :
- scramble_323(end, mysql->scramble_323, passwd,
- (my_bool) (mysql->protocol_version == 9));
+ if (mysql->server_capabilities & CLIENT_SECURE_CONNECTION)
+ {
+ *end++= SCRAMBLE_LENGTH;
+ scramble(end, mysql->scramble, passwd);
+ end+= SCRAMBLE_LENGTH;
+ }
+ else
+ end= scramble_323(end, mysql->scramble_323, passwd,
+ (my_bool) (mysql->protocol_version == 9)) + 1;
}
else
- *end= '\0'; // empty password
+ *end++= '\0'; // empty password
/* Add database if needed */
- end=strmov(end+1,db ? db : "");
+ end= strmov(end, db ? db : "") + 1;
/* Write authentication package */
simple_command(mysql,COM_CHANGE_USER, buff,(ulong) (end-buff),1);
diff --git a/sql-common/client.c b/sql-common/client.c
index 35dea62edc3..efb71021f8d 100644
--- a/sql-common/client.c
+++ b/sql-common/client.c
@@ -1823,7 +1823,7 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user,
mysql->server_status, client_flag));
/* This needs to be changed as it's not useful with big packets */
if (user && user[0])
- strmake(end,user,32); /* Max user name */
+ strmake(end,user,USERNAME_LENGTH); /* Max user name */
else
read_user_name((char*) end);
@@ -1835,21 +1835,25 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user,
end= strend(end) + 1;
if (passwd[0])
{
- /* Write NULL-terminated scrambled password: */
- end= mysql->server_capabilities & CLIENT_SECURE_CONNECTION ?
- scramble(end, mysql->scramble, passwd) :
- scramble_323(end, mysql->scramble_323, passwd,
- (my_bool) (mysql->protocol_version == 9));
+ if (mysql->server_capabilities & CLIENT_SECURE_CONNECTION)
+ {
+ *end++= SCRAMBLE_LENGTH;
+ scramble(end, mysql->scramble, passwd);
+ end+= SCRAMBLE_LENGTH;
+ }
+ else
+ end= scramble_323(end, mysql->scramble_323, passwd,
+ (my_bool) (mysql->protocol_version == 9)) + 1;
}
else
- *end= '\0'; /* empty password */
+ *end++= '\0'; /* empty password */
/* Add database if needed */
if (db && (mysql->server_capabilities & CLIENT_CONNECT_WITH_DB))
{
- end=strmake(end+1,db,NAME_LEN);
- mysql->db=my_strdup(db,MYF(MY_WME));
- db=0;
+ end= strmake(end, db, NAME_LEN) + 1;
+ mysql->db= my_strdup(db,MYF(MY_WME));
+ db= 0;
}
/* Write authentication package */
if (my_net_write(net,buff,(ulong) (end-buff)) || net_flush(net))
diff --git a/sql/item_create.cc b/sql/item_create.cc
index 90f42cee959..fbb26e83dfd 100644
--- a/sql/item_create.cc
+++ b/sql/item_create.cc
@@ -52,13 +52,6 @@ Item *create_func_ord(Item* 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)
{
return new Item_func_asin(a);
@@ -332,11 +325,6 @@ Item *create_func_quarter(Item* 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)
{
return new Item_func_units((char*) "radians",a,M_PI/180,0.0);
diff --git a/sql/item_create.h b/sql/item_create.h
index 4151f59a87f..2872451c034 100644
--- a/sql/item_create.h
+++ b/sql/item_create.h
@@ -69,14 +69,12 @@ Item *create_func_monthname(Item* a);
Item *create_func_nullif(Item* a, Item *b);
Item *create_func_oct(Item *);
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_diff(Item* a, Item *b);
Item *create_func_pi(void);
Item *create_func_pow(Item* a, Item *b);
Item *create_func_current_user(void);
Item *create_func_quarter(Item* a);
-Item *create_func_password(Item* a);
Item *create_func_radians(Item *a);
Item *create_func_release_lock(Item* a);
Item *create_func_repeat(Item* a, Item *b);
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index f8488565b75..def465363fe 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -1360,6 +1360,14 @@ String *Item_func_password::val_str(String *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)
@@ -1374,6 +1382,14 @@ String *Item_func_old_password::val_str(String *str)
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)+'.')
diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h
index 11f5a66b3d1..3e0239cf76a 100644
--- a/sql/item_strfunc.h
+++ b/sql/item_strfunc.h
@@ -270,6 +270,7 @@ public:
String *val_str(String *str);
void fix_length_and_dec() { max_length= SCRAMBLED_PASSWORD_CHAR_LENGTH; }
const char *func_name() const { return "password"; }
+ static char *alloc(THD *thd, const char *password);
};
@@ -288,7 +289,7 @@ public:
String *val_str(String *str);
void fix_length_and_dec() { max_length= SCRAMBLED_PASSWORD_CHAR_LENGTH_323; }
const char *func_name() const { return "old_password"; }
- unsigned int size_of() { return sizeof(*this);}
+ static char *alloc(THD *thd, const char *password);
};
diff --git a/sql/lex.h b/sql/lex.h
index bb6e7a81ab4..f105fd4d9c8 100644
--- a/sql/lex.h
+++ b/sql/lex.h
@@ -284,6 +284,7 @@ static SYMBOL symbols[] = {
{ "NULL", SYM(NULL_SYM),0,0},
{ "NUMERIC", SYM(NUMERIC_SYM),0,0},
{ "OFFSET", SYM(OFFSET_SYM),0,0},
+ { "OLD_PASSWORD", SYM(OLD_PASSWORD),0,0},
{ "ON", SYM(ON),0,0},
{ "OPEN", SYM(OPEN_SYM),0,0},
{ "OPTIMIZE", SYM(OPTIMIZE),0,0},
@@ -577,7 +578,6 @@ static SYMBOL sql_functions[] = {
{ "NUMPOINTS", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_numpoints)},
{ "OCTET_LENGTH", SYM(FUNC_ARG1),0,CREATE_FUNC(create_func_length)},
{ "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)},
{ "OVERLAPS", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_overlaps)},
{ "PERIOD_ADD", SYM(FUNC_ARG2),0,CREATE_FUNC(create_func_period_add)},
diff --git a/sql/password.c b/sql/password.c
index be6514d89c6..bfdb453af01 100644
--- a/sql/password.c
+++ b/sql/password.c
@@ -446,22 +446,20 @@ make_scrambled_password(char *to, const char *password)
Produce an obscure octet sequence from password and random
string, recieved from the server. This sequence corresponds to the
password, but password can not be easily restored from it. The sequence
- is then sent to the server for validation. Trailing zero is stored in
- the buf.
+ is then sent to the server for validation. Trailing zero is not stored
+ in the buf as it is not needed.
This function is used by client to create authenticated reply to the
server's greeting.
SYNOPSIS
scramble()
buf OUT store scrambled string here. The buf must be at least
- SHA1_HASH_SIZE+1 bytes long.
+ SHA1_HASH_SIZE bytes long.
message IN random message, must be exactly SCRAMBLE_LENGTH long and
NULL-terminated.
password IN users' password
- RETURN VALUE
- end of scrambled string
*/
-char *
+void
scramble(char *to, const char *message, const char *password)
{
SHA1_CONTEXT sha1_context;
@@ -483,8 +481,6 @@ scramble(char *to, const char *message, const char *password)
/* xor allows 'from' and 'to' overlap: lets take advantage of it */
sha1_result(&sha1_context, (uint8 *) to);
my_crypt(to, (const uint8 *) to, hash_stage1, SCRAMBLE_LENGTH);
- to[SHA1_HASH_SIZE]= '\0';
- return to + SHA1_HASH_SIZE;
}
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index bbc6b74c3a9..f88799c2843 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -51,7 +51,7 @@ static byte* acl_entry_get_key(acl_entry *entry,uint *length,
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 MEM_ROOT mem, memex;
@@ -208,7 +208,8 @@ my_bool acl_init(THD *org_thd, bool dont_read_acl_tables)
DBUG_PRINT("info",("user table fields: %d, password length: %d",
table->fields, table->field[2]->field_length));
- if (table->field[2]->field_length < 41 && !use_old_passwords)
+ if (table->field[2]->field_length < SCRAMBLED_PASSWORD_CHAR_LENGTH &&
+ !use_old_passwords)
{
sql_print_error("mysql.user table is not updated to new password format; "
"Disabling new password usage until "
@@ -516,6 +517,7 @@ static int acl_compare(ACL_ACCESS *a,ACL_ACCESS *b)
RETURN VALUE
0 success: thread data and 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.
*/
@@ -564,6 +566,9 @@ acl_getroot(THD *thd, USER_RESOURCES *mqh,
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;
}
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 384ec2bd4dd..a6d3121158c 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -195,11 +195,8 @@ end:
RETURN VALUE
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 internal error; error is sent to client
- Note, that this return semantics differs from check_connection,
- which returns -1 if message was already sent.
- -1 acl entry for this user contains old scramble, but passwd contains
- new one, error is not 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 enum_server_command command,
@@ -208,87 +205,129 @@ static int check_user(THD *thd, enum enum_server_command command,
{
DBUG_ENTER("check_user");
+ if (passwd_len != 0 &&
+ passwd_len != SCRAMBLE_LENGTH &&
+ passwd_len != SCRAMBLE_LENGTH_323)
+ DBUG_RETURN(ER_HANDSHAKE_ERROR);
+
/*
Why this is set here? - probably to reset current DB to 'no database
selected' in case of 'change user' failure.
*/
thd->db= 0;
thd->db_length= 0;
-
+
+ char buff[NAME_LEN + 1]; /* to conditionally save db */
+
USER_RESOURCES ur;
int res= acl_getroot(thd, &ur, passwd, passwd_len,
protocol_version == 9 ||
!(thd->client_capabilities & CLIENT_LONG_PASSWORD));
- if (res == 0 && !(thd->master_access & NO_ACCESS)) // authentification is OK
+ if (res == -1)
{
- 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)
+ /*
+ 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.
+ */
+ /* save db because network buffer is to hold new packet */
+ if (db)
{
- VOID(pthread_mutex_lock(&LOCK_thread_count));
- 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);
- }
+ strmake(buff, db, NAME_LEN);
+ db= buff;
+ }
+ NET *net= &thd->net;
+ if (my_net_write(net, thd->scramble_323, SCRAMBLE_LENGTH_323 + 1) ||
+ net_flush(net) ||
+ 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,
+ false);
+ }
+ /* 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)
+ {
+ VOID(pthread_mutex_lock(&LOCK_thread_count));
+ 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*) "");
+ /* 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*) "");
- /* Why is it set here? */
- thd->db_access=0;
+ /* Why is it set here? */
+ thd->db_access=0;
- /* Don't allow user to connect if he has done too many queries */
- if ((ur.questions || ur.updates || ur.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);
+ /* Don't allow user to connect if he has done too many queries */
+ if ((ur.questions || ur.updates || ur.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))
+ /* Change database if necessary: OK or FAIL is sent in mysql_change_db */
+ if (db && db[0])
{
- if (thd->user_connect)
- decrease_user_connections(thd->user_connect);
- DBUG_RETURN(1);
+ if (mysql_change_db(thd, db))
+ {
+ if (thd->user_connect)
+ decrease_user_connections(thd->user_connect);
+ DBUG_RETURN(-1);
+ }
}
+ else
+ send_ok(thd);
+ thd->password= test(passwd_len); // remember for error messages
+ /* Ready to handle queries */
+ DBUG_RETURN(0);
}
- else
- send_ok(thd);
- thd->password= test(passwd_len); // remember for error messages
- /* Ready to handle queries */
}
- else if (res != -1) // authentication failure
+ else if (res == 2) // client gave short hash, server has long hash
{
- net_printf(thd, ER_ACCESS_DENIED_ERROR,
- thd->user,
- 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));
+ net_printf(thd, ER_NOT_SUPPORTED_AUTH_MODE);
+ mysql_log.write(thd,COM_CONNECT,ER(ER_NOT_SUPPORTED_AUTH_MODE));
+ DBUG_RETURN(-1);
}
- DBUG_RETURN(res);
+ net_printf(thd, ER_ACCESS_DENIED_ERROR,
+ thd->user,
+ 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);
}
/*
@@ -492,60 +531,6 @@ static void reset_mqh(THD *thd, LEX_USER *lu, bool get_them= 0)
/*
- Perform check for scrambled password, re-request scrambled password
- from client if necessary. See also help for check_user.
- SYNOPSIS
- authenticate()
- RETURN VALUE
- 0 success, OK sent to client
- -1 error, sent to client
- > 0 error, not sent to client
-*/
-
-static
-int
-authenticate(THD *thd, enum enum_server_command command,
- const char *passwd, uint passwd_len, const char *db,
- bool check_count)
-{
- if (passwd_len != 0 &&
- passwd_len != SCRAMBLE_LENGTH &&
- passwd_len != SCRAMBLE_LENGTH_323)
- return 1;
- int res= check_user(thd, COM_CONNECT, passwd, passwd_len, db, check_count);
- if (res < 0)
- {
- /*
- 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.
- */
- char buff[NAME_LEN + 1];
- /* save db because network buffer is to hold new packet */
- if (db)
- {
- strmake(buff, db, NAME_LEN);
- db= buff;
- }
- NET *net= &thd->net;
- if (my_net_write(net, thd->scramble_323, SCRAMBLE_LENGTH_323 + 1) ||
- net_flush(net) ||
- my_net_read(net) != SCRAMBLE_LENGTH_323 + 1) // We have to read very
- { // specific packet size
- inc_host_errors(&thd->remote.sin_addr);
- return ER_HANDSHAKE_ERROR;
- }
- /* Final attempt to check the user based on reply */
- /* So as passwd is short, errcode is always sent to user and res >= 0 */
- res= check_user(thd, COM_CONNECT, (char *) net->read_pos,
- SCRAMBLE_LENGTH_323, db, check_count);
- }
- return res > 0 ? -1 : 0;
-}
-
-
-/*
Perform handshake, authorize client and update thd ACL variables.
SYNOPSIS
check_connection()
@@ -643,7 +628,7 @@ check_connection(THD *thd)
/*
Old clients does not understand long scrambles, but can ignore packet
- tail: that's why first part of scramble is placed here, and second
+ 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_323, SCRAMBLE_LENGTH_323) + 1;
@@ -760,17 +745,23 @@ check_connection(THD *thd)
char *user= end;
char *passwd= strend(user)+1;
- uint passwd_len= strlen(passwd);
-
- char *db= thd->client_capabilities & CLIENT_CONNECT_WITH_DB ?
- passwd+passwd_len+1 : 0;
+ char *db= passwd;
+ /*
+ 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;
if (thd->user)
x_free(thd->user);
thd->user= my_strdup(user, MYF(0));
if (!thd->user)
return(ER_OUT_OF_RESOURCES);
- return authenticate(thd, COM_CONNECT, passwd, passwd_len, db, true);
+ return check_user(thd, COM_CONNECT, passwd, passwd_len, db, true);
}
@@ -1137,8 +1128,15 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
statistic_increment(com_other, &LOCK_status);
char *user= (char*) packet;
char *passwd= strend(user)+1;
- uint passwd_len= strlen(passwd);
- char *db= passwd + passwd_len + 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;
/* Small check for incomming packet */
if ((uint) ((uchar*) db - net->read_pos) > packet_length)
@@ -1163,7 +1161,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
break;
}
- int res= authenticate(thd, COM_CHANGE_USER, passwd, passwd_len, db, false);
+ int res= check_user(thd, COM_CHANGE_USER, passwd, passwd_len, db, false);
if (res)
{
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index c8c9eb97a6a..ddf4b71e891 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -493,6 +493,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize);
%token MULTIPOINT
%token MULTIPOLYGON
%token NOW_SYM
+%token OLD_PASSWORD
%token PASSWORD
%token POINTFROMTEXT
%token POINT_SYM
@@ -2516,9 +2517,11 @@ simple_expr:
{ $$= new Item_func_now($3); Lex->safe_to_cache_query=0;}
| PASSWORD '(' expr ')'
{
- $$= use_old_passwords ? (Item *) new Item_func_old_password($3) :
- (Item *) new Item_func_password($3);
- }
+ $$= use_old_passwords ? (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 ')'
{ $$= new Item_func_point($3,$5); }
| POINTFROMTEXT '(' expr ')'
@@ -4412,6 +4415,7 @@ keyword:
| NO_SYM {}
| NONE_SYM {}
| OFFSET_SYM {}
+ | OLD_PASSWORD {}
| OPEN_SYM {}
| PACK_KEYS_SYM {}
| PARTIAL {}
@@ -4603,24 +4607,15 @@ text_or_password:
TEXT_STRING { $$=$1.str;}
| PASSWORD '(' TEXT_STRING ')'
{
- if (!$3.length)
- $$=$3.str;
- else if (use_old_passwords)
- {
- char *buff= (char *)
- YYTHD->alloc(SCRAMBLED_PASSWORD_CHAR_LENGTH_323+1);
- if (buff)
- make_scrambled_password_323(buff, $3.str);
- $$=buff;
- }
- else
- {
- char *buff= (char *)
- YYTHD->alloc(SCRAMBLED_PASSWORD_CHAR_LENGTH+1);
- if (buff)
- make_scrambled_password(buff, $3.str);
- $$=buff;
- }
+ $$= $3.length ? use_old_passwords ?
+ Item_func_old_password::alloc(YYTHD, $3.str) :
+ Item_func_password::alloc(YYTHD, $3.str) :
+ $3.str;
+ }
+ | OLD_PASSWORD '(' TEXT_STRING ')'
+ {
+ $$= $3.length ? Item_func_old_password::alloc(YYTHD, $3.str) :
+ $3.str;
}
;