Bug #13064 | short password column - GRANT generate long (broken) hash | ||
---|---|---|---|
Submitted: | 8 Sep 2005 12:54 | Modified: | 20 Oct 2005 18:32 |
Reporter: | Carsten Wiedmann | Email Updates: | |
Status: | Closed | Impact on me: | |
Category: | MySQL Server | Severity: | S3 (Non-critical) |
Version: | 4.1.14 | OS: | Windows (Windows) |
Assigned to: | Jim Winstead | CPU Architecture: | Any |
[8 Sep 2005 12:54]
Carsten Wiedmann
[8 Sep 2005 15:16]
Valeriy Kravchuk
I tried to repeat the bug you described on a fresh installation of 4.1.14, but was unable (column is varchar(41) with old_passwods ON or OFF): Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 1 to server version: 4.1.14-nt Type 'help;' or '\h' for help. Type '\c' to clear the buffer. mysql> use mysql Database changed mysql> select `User`, `Password` from `user` where `User`='foo'; +------+-------------------------------------------+ | User | Password | +------+-------------------------------------------+ | foo | *E8D46CE25265E545D225A8A6F1BAF642FEBEE5CB | +------+-------------------------------------------+ 1 row in set (0.01 sec) mysql> show variables like 'old%'; +---------------+-------+ | Variable_name | Value | +---------------+-------+ | old_passwords | ON | +---------------+-------+ 1 row in set (0.00 sec) mysql> grant all privileges on *.* to 'foo2'@'localhost' identified by 'bar'; Query OK, 0 rows affected (0.00 sec) mysql> select `User`, `Password` from `user` where `User` LIKE 'foo%'; +------+-------------------------------------------+ | User | Password | +------+-------------------------------------------+ | foo | *E8D46CE25265E545D225A8A6F1BAF642FEBEE5CB | | foo2 | 7c9e0a41222752fa | +------+-------------------------------------------+ 2 rows in set (0.06 sec) mysql> exit Bye So, yes, the shorter password is generated ans stored, but... C:\Documents and Settings\openxs>net stop MySQL41 ... I had changed old_passwords value, and: C:\Documents and Settings\openxs>net start MySQL41 ... C:\Documents and Settings\openxs>mysql -ufoo2 -pbar Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 2 to server version: 4.1.14-nt Type 'help;' or '\h' for help. Type '\c' to clear the buffer. mysql> show variables like 'old%'; +---------------+-------+ | Variable_name | Value | +---------------+-------+ | old_passwords | OFF | +---------------+-------+ 1 row in set (0.00 sec) I was able to log in with the passwod bar for user foo2, as you can see.
[8 Sep 2005 15:26]
Carsten Wiedmann
> , but was unable (column is varchar(41) with old_passwods ON or OFF): Yes, with a column width of 41 all is correct. But with a column width of 16 the server must (like the documentation descripe) create short hashe, regardless of the "old-password" setting. Please retest again with a short password column.
[11 Sep 2005 18:45]
Axel Schwenke
How to repeat Prerequisites: - 4.1 server with short (varchar(16)) `Password` column in mysql.user - old-passwords=false According to the manual (http://dev.mysql.com/doc/mysql/en/password-hashing.html, Scenario 1) MySQL should create short password hashes regardless of the old-passwords variable. However it doesn't: ~ $mysql -u root mysql Your MySQL connection id is 5 to server version: 4.1.13a mysql> show create table user\g ... `Password` varchar(16) collate utf8_bin NOT NULL default '', ... mysql> grant all on test.* to foo@localhost identified by 'bar'; Query OK, 0 rows affected (0.03 sec) mysql> select user, password from user where user='foo'; +------+------------------+ | user | password | +------+------------------+ | foo | *E8D46CE25265E54 | +------+------------------+ mysql> select password('bar'), old_password('bar'); +-------------------------------------------+---------------------+ | password('bar') | old_password('bar') | +-------------------------------------------+---------------------+ | *E8D46CE25265E545D225A8A6F1BAF642FEBEE5CB | 7c9e0a41222752fa | +-------------------------------------------+---------------------+ As you can see, MySQL creates a new password hash and truncates it while inserting into the `user` table. Consequence: the created account does not work. Note: you have to FLUSH PRIVILEGES or mysqld will used cached credentials. IMHO there are two bugs here: 1. The manual and the real behaviour differ. The manual says "short password column" -> "old_password() hash" but the server uses new password() hash instead. 2. When writing the created hash into the short password column there should be a warning about truncation. In fact I get a warning if I update the password column manually: mysql> update user set password=password('bar') where user='foo'; Query OK, 1 row affected, 1 warning (0.00 sec) Rows matched: 1 Changed: 1 Warnings: 1 mysql> show warnings; +---------+------+-----------------------------------------------+ | Level | Code | Message | +---------+------+-----------------------------------------------+ | Warning | 1265 | Data truncated for column 'Password' at row 5 | +---------+------+-----------------------------------------------+
[12 Sep 2005 12:45]
Axel Schwenke
After some more discussion with the user the following turned out: mysqld does not use the length of the `Password` column in mysql.user to detect an unconverted mysql database. If one tries to simulate an unconverted database by just truncating the `Password` column to 16 characters, the result is as documented in earlier comments. To get the expected behaviour (mysqld uses pre-4.1 password hashes without explicitly setting old_passwords=1) one has to alter the Password column in the following way: ALTER TABLE mysql.user CHANGE password password CHAR(16) CHARACTER SET binary NOT NULL However it is *strongly* discouraged to alter any table in the mysql database anyway. Conclusion: there is no bug in the code. However the documentation should be changed to not longer suggest that the length of the Password column is is the one and only distinctive feature for the server to spot an unconverted user database. I would suggest to completely omit the discussion about "short" and "long" Password columns and instead refer to new-or-converted vs. unconverted user database (i.e. "MySQL can detect an unconverted user database. In this case old password hashes will be used, regardless of the setting of the old-passwords configuration option.")
[13 Sep 2005 20:38]
Paul DuBois
The manual is correct in stating that the server uses the length of the Password column in the user table to determine whether to generate short hashes. This can be verified by examination of sql_acl.cc. However, it is possible to trigger the bug described in this report as follows (in none of the steps should the server be started with --old-passwords): - Start a 4.1 server with 4.0 grant tables. Note that SHOW VARIABLES LIKE '%pass%' shows old_passwords to have a value of ON. Furthermore, SET old_passwords = 0 is ineffective. The server will not allow it to be set to OFF. Nor will it generate long password hashes. (So this is okay, and it's what is to be expected.) - Upgrade the grant tables. Then use ALTER TABLE to modify the Password column back to 16 characters. Stop the server and restart it. At this point, something is strange, because SHOW VARIABLES LIKE '%pass%' shows old_passwords to be OFF, which is different than before. It's also wrong, because it should have detected from the 16-character Password column that only old password hashes can be used. Using GRANT or SET PASSWORD at this point will also generate a long password hash, which gets truncated when stored in the user table. So it appears that somehow, altering the Password column of a converted-to-4.1-format user table causes some problem that the server doesn't recognize that it needs to use short password hashes. Note that it's not really a good idea to use ALTER TABLE with the grant tables. But neither should the server generate password hashes that get truncated when stored. So this is an actual bug. Note for bug reporter: It appears this problem can be triggered only after manually altering a converted grant table with ALTER TABLE. That's a piece of information that would well have been included in the original report, because it's important for triggering the bug. Thanks. (If there is another way that you know of to trigger the problem, please report it.)
[15 Sep 2005 12:29]
Carsten Wiedmann
> Note that it's not really a good idea to use ALTER TABLE with the > grant tables. I know. It's not the normal way. Let me descripe my situation: I want guarantee that all clients (4.1 and pre4.1) can work with the server, even if "old-passwords" is not set. Because after installation the server or "my.cnf/ini" is not under my control and the customer have no idea about server administration/configuration. They want only use the server. > Note for bug reporter: It appears this problem can be triggered only > after manually altering a converted grant table with ALTER TABLE. I should have referred better to this precondition. > (If there is another way that you know of to trigger the problem, please > report it.) Ok, after some more tests I get these results. After a clean new server installation (MySQL 4.1.x and 5.0.x) I make each test with the same steps: - install the system db with "mysql_create_system_tables" - start the server (without old-passwords) - shorten the password column with "ALTER TABLE..." (see tests below) - restart the server (without old-passwords) - add a new user with: GRANT ALL PRIVILEGES ON *.* TO 'foo'@'localhost' IDENTIFIED BY 'bar'; - selections of the password field to get the test result with: SELECT `User`, `Password` FROM `user` WHERE `User`='foo'; - stop the server - delete the system db Test 1: ------- | USE `mysql`; | ALTER TABLE `user` | CHANGE `Password` `Password` CHAR(16) | BINARY | DEFAULT '' NOT NULL; Result: truncate long hash Test 2: ------- | USE `mysql`; | ALTER TABLE `user` | CHANGE `Password` `Password` VARBINARY(16) | DEFAULT '' NOT NULL; Result: correct short hash Test 3: ------- | USE `mysql`; | ALTER TABLE `user` | CHANGE `Password` `Password` VARCHAR(16) | CHARACTER SET utf8 COLLATE utf8_bin | DEFAULT '' NOT NULL; Result: truncate long hash Test 4: ------- | USE `mysql`; | ALTER TABLE `user` | CHANGE `Password` `Password` VARCHAR(16) | CHARACTER SET latin1 COLLATE latin1_bin | DEFAULT '' NOT NULL; Result: correct short hash These tests I can verify with all versions from 4.1.10 to 5.0.7 except of 4.1.1 (with 4.1.1 I can write and read a long hash in a short column?). As I can see, the test result depends on the charset of the column. So, I don't know what's correct and what's not. Is the server behavior wrong or is somewhat missing in the manual? Thats your turn. If is still somewhat unclear, please ask me.
[17 Sep 2005 2:43]
Paul DuBois
Thanks for the additional feedback. There is a bug here. The server checks the length of the Password column when it starts, so it should not generate long hashes when the column is short, and it should not try to store them, resulting in truncated hash values. Resetting from Docs category to Server.
[20 Sep 2005 23:54]
Bugs System
A patch for this bug has been committed. After review, it may be pushed to the relevant source trees for release in the next version. You can access the patch from: http://lists.mysql.com/internals/30127
[19 Oct 2005 1:56]
Jim Winstead
Fixed in 4.1.16 and 5.0.16.
[20 Oct 2005 18:32]
Paul DuBois
Noted in 4.1.16, 5.0.16 changelogs.