diff options
-rw-r--r-- | mysql-test/r/grant2.result | 8 | ||||
-rw-r--r-- | mysql-test/r/sql_mode.result | 2 | ||||
-rw-r--r-- | mysql-test/r/strict.result | 2 | ||||
-rw-r--r-- | mysql-test/t/grant2.test | 9 | ||||
-rw-r--r-- | sql/mysql_priv.h | 1 | ||||
-rw-r--r-- | sql/mysqld.cc | 2 | ||||
-rw-r--r-- | sql/set_var.cc | 6 | ||||
-rw-r--r-- | sql/sql_acl.cc | 38 | ||||
-rw-r--r-- | sql/sql_parse.cc | 23 |
9 files changed, 56 insertions, 35 deletions
diff --git a/mysql-test/r/grant2.result b/mysql-test/r/grant2.result index 31e506d2679..c95b86ea831 100644 --- a/mysql-test/r/grant2.result +++ b/mysql-test/r/grant2.result @@ -12,6 +12,14 @@ mysqltest_1@localhost grant all privileges on `my\_1`.* to mysqltest_2@localhost with grant option; grant all privileges on `my_%`.* to mysqltest_3@localhost with grant option; ERROR 42000: Access denied for user 'mysqltest_1'@'localhost' to database 'my_%' +set @@sql_mode='NO_AUTO_CREATE_USER'; +select @@sql_mode; +@@sql_mode +NO_AUTO_CREATE_USER +grant select on `my\_1`.* to mysqltest_4@localhost with grant option; +ERROR 42000: 'mysqltest_1'@'localhost' is not allowed to create new users +grant select on `my\_1`.* to mysqltest_4@localhost identified by 'mypass' +with grant option; show grants for mysqltest_1@localhost; Grants for mysqltest_1@localhost GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost' diff --git a/mysql-test/r/sql_mode.result b/mysql-test/r/sql_mode.result index c4731b93d2b..d861e3a5926 100644 --- a/mysql-test/r/sql_mode.result +++ b/mysql-test/r/sql_mode.result @@ -74,7 +74,7 @@ t1 CREATE TABLE `t1` ( set sql_mode="postgresql,oracle,mssql,db2,maxdb"; select @@sql_mode; @@sql_mode -PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,POSTGRESQL,ORACLE,MSSQL,DB2,MAXDB,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS +PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,POSTGRESQL,ORACLE,MSSQL,DB2,MAXDB,NO_KEY_OPTIONS,NO_TABLE_OPTIONS,NO_FIELD_OPTIONS,NO_AUTO_CREATE_USER show create table t1; Table Create Table t1 CREATE TABLE "t1" ( diff --git a/mysql-test/r/strict.result b/mysql-test/r/strict.result index 31e3d82d52e..19c4def9b32 100644 --- a/mysql-test/r/strict.result +++ b/mysql-test/r/strict.result @@ -1,7 +1,7 @@ set @@sql_mode='ansi,traditional'; select @@sql_mode; @@sql_mode -REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ONLY_FULL_GROUP_BY,ANSI,STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL +REAL_AS_FLOAT,PIPES_AS_CONCAT,ANSI_QUOTES,IGNORE_SPACE,ONLY_FULL_GROUP_BY,ANSI,STRICT_TRANS_TABLES,STRICT_ALL_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,TRADITIONAL,NO_AUTO_CREATE_USER DROP TABLE IF EXISTS t1; CREATE TABLE t1 (col1 date); INSERT INTO t1 VALUES('2004-01-01'),('0000-10-31'),('2004-02-29'); diff --git a/mysql-test/t/grant2.test b/mysql-test/t/grant2.test index 3a9afa7453b..6aa47a01753 100644 --- a/mysql-test/t/grant2.test +++ b/mysql-test/t/grant2.test @@ -21,6 +21,15 @@ select current_user; grant all privileges on `my\_1`.* to mysqltest_2@localhost with grant option; --error 1044 grant all privileges on `my_%`.* to mysqltest_3@localhost with grant option; +# +# NO_AUTO_CREATE_USER mode +# +set @@sql_mode='NO_AUTO_CREATE_USER'; +select @@sql_mode; +--error 1211 +grant select on `my\_1`.* to mysqltest_4@localhost with grant option; +grant select on `my\_1`.* to mysqltest_4@localhost identified by 'mypass' +with grant option; disconnect user1; connection default; show grants for mysqltest_1@localhost; diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index d8916149b77..02dda86f054 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -280,6 +280,7 @@ extern CHARSET_INFO *national_charset_info, *table_alias_charset; #define MODE_INVALID_DATES (MODE_NO_ZERO_DATE*2) #define MODE_ERROR_FOR_DIVISION_BY_ZERO (MODE_INVALID_DATES*2) #define MODE_TRADITIONAL (MODE_ERROR_FOR_DIVISION_BY_ZERO*2) +#define MODE_NO_AUTO_CREATE_USER (MODE_TRADITIONAL*2) #define RAID_BLOCK_SIZE 1024 diff --git a/sql/mysqld.cc b/sql/mysqld.cc index db81b14c9c9..f2d0dadbc17 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -221,7 +221,7 @@ const char *sql_mode_names[] = "NO_TABLE_OPTIONS", "NO_FIELD_OPTIONS", "MYSQL323", "MYSQL40", "ANSI", "NO_AUTO_VALUE_ON_ZERO", "NO_BACKSLASH_ESCAPES", "STRICT_TRANS_TABLES", "STRICT_ALL_TABLES", "NO_ZERO_IN_DATE", "NO_ZERO_DATE", "ALLOW_INVALID_DATES", "ERROR_FOR_DIVISION_BY_ZERO", - "TRADITIONAL", + "TRADITIONAL", "NO_AUTO_CREATE_USER", NullS }; TYPELIB sql_mode_typelib= { array_elements(sql_mode_names)-1,"", diff --git a/sql/set_var.cc b/sql/set_var.cc index a43a2c13aca..25af3d9c853 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -3077,7 +3077,7 @@ ulong fix_sql_mode(ulong sql_mode) sql_mode|= (MODE_PIPES_AS_CONCAT | MODE_ANSI_QUOTES | MODE_IGNORE_SPACE | MODE_NO_KEY_OPTIONS | MODE_NO_TABLE_OPTIONS | - MODE_NO_FIELD_OPTIONS); + MODE_NO_FIELD_OPTIONS | MODE_NO_AUTO_CREATE_USER); if (sql_mode & MODE_MSSQL) sql_mode|= (MODE_PIPES_AS_CONCAT | MODE_ANSI_QUOTES | MODE_IGNORE_SPACE | @@ -3097,7 +3097,7 @@ ulong fix_sql_mode(ulong sql_mode) sql_mode|= (MODE_PIPES_AS_CONCAT | MODE_ANSI_QUOTES | MODE_IGNORE_SPACE | MODE_NO_KEY_OPTIONS | MODE_NO_TABLE_OPTIONS | - MODE_NO_FIELD_OPTIONS); + MODE_NO_FIELD_OPTIONS | MODE_NO_AUTO_CREATE_USER); if (sql_mode & MODE_MYSQL40) sql_mode|= MODE_NO_FIELD_OPTIONS; if (sql_mode & MODE_MYSQL323) @@ -3105,7 +3105,7 @@ ulong fix_sql_mode(ulong sql_mode) if (sql_mode & MODE_TRADITIONAL) sql_mode|= (MODE_STRICT_TRANS_TABLES | MODE_STRICT_ALL_TABLES | MODE_NO_ZERO_IN_DATE | MODE_NO_ZERO_DATE | - MODE_ERROR_FOR_DIVISION_BY_ZERO); + MODE_ERROR_FOR_DIVISION_BY_ZERO | MODE_NO_AUTO_CREATE_USER); return sql_mode; } diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index df615383ec3..443b925521f 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -1550,13 +1550,28 @@ static int replace_user_table(THD *thd, TABLE *table, const LEX_USER &combo, (byte*) table->field[0]->ptr,0, HA_READ_KEY_EXACT)) { - if (!create_user) + /* what == 'N' means revoke */ + if (what == 'N') { - if (what == 'N') - my_error(ER_NONEXISTING_GRANT, MYF(0), combo.user.str, combo.host.str); - else - my_error(ER_NO_PERMISSION_TO_CREATE_USER, MYF(0), - thd->user, thd->host_or_ip); + my_error(ER_NONEXISTING_GRANT, MYF(0), combo.user.str, combo.host.str); + goto end; + } + /* + There are four options which affect the process of creation of + a new user(mysqld option --safe-create-user, 'insert' privilege + on 'mysql.user' table, using 'GRANT' with 'IDENTIFIED BY' and + SQL_MODE flag NO_AUTO_CREATE_USER). Below is the simplified rule + how it should work. + if (safe-user-create && ! INSERT_priv) => reject + else if (identified_by) => create + else if (no_auto_create_user) => reject + else create + */ + else if (((thd->variables.sql_mode & MODE_NO_AUTO_CREATE_USER) && + !password_len) || !create_user) + { + my_error(ER_NO_PERMISSION_TO_CREATE_USER, MYF(0), + thd->user, thd->host_or_ip); goto end; } old_row_exists = 0; @@ -1570,6 +1585,17 @@ static int replace_user_table(THD *thd, TABLE *table, const LEX_USER &combo, } else { + /* + Check that the user isn't trying to change a password for another + user if he doesn't have UPDATE privilege to the MySQL database + */ + DBUG_ASSERT(combo.host.str); + if (thd->user && combo.password.str && + (strcmp(thd->user,combo.user.str) || + my_strcasecmp(&my_charset_latin1, + combo.host.str, thd->host_or_ip)) && + check_access(thd, UPDATE_ACL, "mysql",0,1,0)) + goto end; old_row_exists = 1; store_record(table,record[1]); // Save copy for update if (combo.password.str) // If password given diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 623c47d4be5..e65c2614a7f 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -3377,29 +3377,6 @@ purposes internal to the MySQL server", MYF(0)); first_table ? 0 : 1, 0)) goto error; - /* - Check that the user isn't trying to change a password for another - user if he doesn't have UPDATE privilege to the MySQL database - */ - - if (thd->user) // If not replication - { - LEX_USER *user; - List_iterator <LEX_USER> user_list(lex->users_list); - while ((user=user_list++)) - { - if (user->password.str && - (strcmp(thd->user,user->user.str) || - user->host.str && - my_strcasecmp(&my_charset_latin1, - user->host.str, thd->host_or_ip))) - { - if (check_access(thd, UPDATE_ACL, "mysql",0,1,0)) - goto error; - break; // We are allowed to do changes - } - } - } if (specialflag & SPECIAL_NO_RESOLVE) { LEX_USER *user; |