summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/r/func_crypt.result11
-rw-r--r--mysql-test/t/func_crypt.test12
-rw-r--r--sql/item_strfunc.cc14
-rw-r--r--sql/item_strfunc.h4
-rw-r--r--sql/mysql_priv.h6
-rw-r--r--sql/password.c53
-rw-r--r--sql/sql_yacc.yy11
7 files changed, 90 insertions, 21 deletions
diff --git a/mysql-test/r/func_crypt.result b/mysql-test/r/func_crypt.result
index afdec0f4d06..42fa18b17b2 100644
--- a/mysql-test/r/func_crypt.result
+++ b/mysql-test/r/func_crypt.result
@@ -95,3 +95,14 @@ Note 1003 select password(_latin1'idkfa ') AS `password('idkfa ')`,old_password(
select encrypt('1234','_.');
encrypt('1234','_.')
#
+#
+# Bug #44767: invalid memory reads in password() and old_password()
+# functions
+#
+CREATE TABLE t1(c1 MEDIUMBLOB);
+INSERT INTO t1 VALUES (REPEAT('a', 1024));
+SELECT OLD_PASSWORD(c1), PASSWORD(c1) FROM t1;
+OLD_PASSWORD(c1) PASSWORD(c1)
+77023ffe214c04ff *82E58A2C08AAFE72C8EB523069CD8ADB33F78F58
+DROP TABLE t1;
+End of 5.0 tests
diff --git a/mysql-test/t/func_crypt.test b/mysql-test/t/func_crypt.test
index cc3cdb9564d..6dedeaa0fef 100644
--- a/mysql-test/t/func_crypt.test
+++ b/mysql-test/t/func_crypt.test
@@ -56,3 +56,15 @@ explain extended select password('idkfa '), old_password('idkfa');
select encrypt('1234','_.');
# End of 4.1 tests
+
+--echo #
+--echo # Bug #44767: invalid memory reads in password() and old_password()
+--echo # functions
+--echo #
+
+CREATE TABLE t1(c1 MEDIUMBLOB);
+INSERT INTO t1 VALUES (REPEAT('a', 1024));
+SELECT OLD_PASSWORD(c1), PASSWORD(c1) FROM t1;
+DROP TABLE t1;
+
+--echo End of 5.0 tests
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index bc2dcb9c61b..71d3a34cd27 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -1554,16 +1554,17 @@ String *Item_func_password::val_str(String *str)
return 0;
if (res->length() == 0)
return &my_empty_string;
- make_scrambled_password(tmp_value, res->c_ptr());
+ my_make_scrambled_password(tmp_value, res->ptr(), res->length());
str->set(tmp_value, SCRAMBLED_PASSWORD_CHAR_LENGTH, res->charset());
return str;
}
-char *Item_func_password::alloc(THD *thd, const char *password)
+char *Item_func_password::alloc(THD *thd, const char *password,
+ size_t pass_len)
{
char *buff= (char *) thd->alloc(SCRAMBLED_PASSWORD_CHAR_LENGTH+1);
if (buff)
- make_scrambled_password(buff, password);
+ my_make_scrambled_password(buff, password, pass_len);
return buff;
}
@@ -1577,16 +1578,17 @@ String *Item_func_old_password::val_str(String *str)
return 0;
if (res->length() == 0)
return &my_empty_string;
- make_scrambled_password_323(tmp_value, res->c_ptr());
+ my_make_scrambled_password_323(tmp_value, res->ptr(), res->length());
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 *Item_func_old_password::alloc(THD *thd, const char *password,
+ size_t pass_len)
{
char *buff= (char *) thd->alloc(SCRAMBLED_PASSWORD_CHAR_LENGTH_323+1);
if (buff)
- make_scrambled_password_323(buff, password);
+ my_make_scrambled_password_323(buff, password, pass_len);
return buff;
}
diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h
index 1c5346ab074..f2cb4d2d32a 100644
--- a/sql/item_strfunc.h
+++ b/sql/item_strfunc.h
@@ -281,7 +281,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);
+ static char *alloc(THD *thd, const char *password, size_t pass_len);
};
@@ -300,7 +300,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"; }
- static char *alloc(THD *thd, const char *password);
+ static char *alloc(THD *thd, const char *password, size_t pass_len);
};
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index 9768668f103..55bcd30999d 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -1677,6 +1677,12 @@ extern void turn_parser_debug_on();
SQL_CRYPT *get_crypt_for_frm(void);
#endif
+/* password.c */
+extern "C" void my_make_scrambled_password_323(char *to, const char *password,
+ size_t pass_len);
+extern "C" void my_make_scrambled_password(char *to, const char *password,
+ size_t pass_len);
+
#include "sql_view.h"
/* Some inline functions for more speed */
diff --git a/sql/password.c b/sql/password.c
index 57ed3e6ab0f..e12074549a4 100644
--- a/sql/password.c
+++ b/sql/password.c
@@ -137,20 +137,39 @@ void hash_password(ulong *result, const char *password, uint password_len)
Create password to be stored in user database from raw string
Used for pre-4.1 password handling
SYNOPSIS
- make_scrambled_password_323()
+ my_make_scrambled_password_323()
to OUT store scrambled password here
password IN user-supplied password
+ pass_len IN length of password string
*/
-void make_scrambled_password_323(char *to, const char *password)
+void my_make_scrambled_password_323(char *to, const char *password,
+ size_t pass_len)
{
ulong hash_res[2];
- hash_password(hash_res, password, (uint) strlen(password));
+ hash_password(hash_res, password, (uint) pass_len);
sprintf(to, "%08lx%08lx", hash_res[0], hash_res[1]);
}
/*
+ Wrapper around my_make_scrambled_password_323() to maintain client lib ABI
+ compatibility.
+ In server code usage of my_make_scrambled_password_323() is preferred to
+ avoid strlen().
+ SYNOPSIS
+ make_scrambled_password_323()
+ to OUT store scrambled password here
+ password IN NULL-terminated string with user-supplied password
+*/
+
+void make_scrambled_password_323(char *to, const char *password)
+{
+ my_make_scrambled_password_323(to, password, strlen(password));
+}
+
+
+/*
Scramble string with password.
Used in pre 4.1 authentication phase.
SYNOPSIS
@@ -383,20 +402,21 @@ my_crypt(char *to, const uchar *s1, const uchar *s2, uint len)
The result of this function is used as return value from PASSWORD() and
is stored in the database.
SYNOPSIS
- make_scrambled_password()
+ my_make_scrambled_password()
buf OUT buffer of size 2*SHA1_HASH_SIZE + 2 to store hex string
- password IN NULL-terminated password string
+ password IN password string
+ pass_len IN length of password string
*/
-void
-make_scrambled_password(char *to, const char *password)
+void my_make_scrambled_password(char *to, const char *password,
+ size_t pass_len)
{
SHA1_CONTEXT sha1_context;
uint8 hash_stage2[SHA1_HASH_SIZE];
mysql_sha1_reset(&sha1_context);
/* stage 1: hash password */
- mysql_sha1_input(&sha1_context, (uint8 *) password, (uint) strlen(password));
+ mysql_sha1_input(&sha1_context, (uint8 *) password, (uint) pass_len);
mysql_sha1_result(&sha1_context, (uint8 *) to);
/* stage 2: hash stage1 output */
mysql_sha1_reset(&sha1_context);
@@ -410,6 +430,23 @@ make_scrambled_password(char *to, const char *password)
/*
+ Wrapper around my_make_scrambled_password() to maintain client lib ABI
+ compatibility.
+ In server code usage of my_make_scrambled_password() is preferred to
+ avoid strlen().
+ SYNOPSIS
+ make_scrambled_password()
+ buf OUT buffer of size 2*SHA1_HASH_SIZE + 2 to store hex string
+ password IN NULL-terminated password string
+*/
+
+void make_scrambled_password(char *to, const char *password)
+{
+ my_make_scrambled_password(to, password, strlen(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
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 61020a3eed0..b6a215a2306 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -10092,15 +10092,16 @@ text_or_password:
| PASSWORD '(' TEXT_STRING ')'
{
$$= $3.length ? YYTHD->variables.old_passwords ?
- Item_func_old_password::alloc(YYTHD, $3.str) :
- Item_func_password::alloc(YYTHD, $3.str) :
+ Item_func_old_password::alloc(YYTHD, $3.str, $3.length) :
+ Item_func_password::alloc(YYTHD, $3.str, $3.length) :
$3.str;
if ($$ == NULL)
MYSQL_YYABORT;
}
| OLD_PASSWORD '(' TEXT_STRING ')'
{
- $$= $3.length ? Item_func_old_password::alloc(YYTHD, $3.str) :
+ $$= $3.length ? Item_func_old_password::alloc(YYTHD, $3.str,
+ $3.length) :
$3.str;
if ($$ == NULL)
MYSQL_YYABORT;
@@ -10545,7 +10546,7 @@ grant_user:
(char *) YYTHD->alloc(SCRAMBLED_PASSWORD_CHAR_LENGTH_323+1);
if (buff == NULL)
MYSQL_YYABORT;
- make_scrambled_password_323(buff, $4.str);
+ my_make_scrambled_password_323(buff, $4.str, $4.length);
$1->password.str= buff;
$1->password.length= SCRAMBLED_PASSWORD_CHAR_LENGTH_323;
}
@@ -10555,7 +10556,7 @@ grant_user:
(char *) YYTHD->alloc(SCRAMBLED_PASSWORD_CHAR_LENGTH+1);
if (buff == NULL)
MYSQL_YYABORT;
- make_scrambled_password(buff, $4.str);
+ my_make_scrambled_password(buff, $4.str, $4.length);
$1->password.str= buff;
$1->password.length= SCRAMBLED_PASSWORD_CHAR_LENGTH;
}