diff options
-rw-r--r-- | include/my_sys.h | 2 | ||||
-rw-r--r-- | mysql-test/r/grant2.result | 25 | ||||
-rw-r--r-- | mysql-test/t/grant2.test | 18 | ||||
-rw-r--r-- | mysys/mf_wcomp.c | 65 | ||||
-rw-r--r-- | mysys/mf_wfile.c | 4 | ||||
-rw-r--r-- | sql/sql_acl.cc | 10 | ||||
-rw-r--r-- | sql/sql_acl.h | 2 | ||||
-rw-r--r-- | sql/sql_base.cc | 2 | ||||
-rw-r--r-- | sql/sql_db.cc | 14 | ||||
-rw-r--r-- | sql/sql_parse.cc | 4 | ||||
-rw-r--r-- | sql/sql_show.cc | 8 | ||||
-rw-r--r-- | sql/sql_yacc.yy | 1 |
12 files changed, 85 insertions, 70 deletions
diff --git a/include/my_sys.h b/include/my_sys.h index 7ea9f63a50f..e4125a2e7e6 100644 --- a/include/my_sys.h +++ b/include/my_sys.h @@ -627,7 +627,7 @@ extern my_string my_path(my_string to,const char *progname, const char *own_pathname_part); extern my_string my_load_path(my_string to, const char *path, const char *own_path_prefix); -extern int wild_compare(const char *str,const char *wildstr); +extern int wild_compare(const char *str,const char *wildstr,pbool str_is_pattern); extern WF_PACK *wf_comp(my_string str); extern int wf_test(struct wild_file_pack *wf_pack,const char *name); extern void wf_end(struct wild_file_pack *buffer); diff --git a/mysql-test/r/grant2.result b/mysql-test/r/grant2.result index 1586375c7d8..d49b9daee85 100644 --- a/mysql-test/r/grant2.result +++ b/mysql-test/r/grant2.result @@ -5,20 +5,19 @@ grant all privileges on `my\_%`.* to mysqltest_1@localhost with grant option; select current_user(); current_user() mysqltest_1@localhost -grant all privileges on `my\_1`.* to mysqltest_9@localhost with grant option; -ERROR 42000: Access denied for user: 'mysqltest_1@localhost' to database 'my\_1' -grant all privileges on `my_%`.* to mysqltest_2@localhost with grant option; -select current_user(); -current_user() -mysqltest_2@localhost -grant all privileges on `mysql`.* to mysqltest_3@localhost with grant option; -select current_user(); -current_user() -mysqltest_3@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_%' +show grants for mysqltest_1@localhost; +Grants for mysqltest_1@localhost +GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost' +GRANT ALL PRIVILEGES ON `my\_%`.* TO 'mysqltest_1'@'localhost' WITH GRANT OPTION +show grants for mysqltest_2@localhost; +Grants for mysqltest_2@localhost +GRANT USAGE ON *.* TO 'mysqltest_2'@'localhost' +GRANT ALL PRIVILEGES ON `my\_1`.* TO 'mysqltest_2'@'localhost' WITH GRANT OPTION show grants for mysqltest_3@localhost; -Grants for mysqltest_3@localhost -GRANT USAGE ON *.* TO 'mysqltest_3'@'localhost' -GRANT ALL PRIVILEGES ON `mysql`.* TO 'mysqltest_3'@'localhost' WITH GRANT OPTION +ERROR 42000: There is no such grant defined for user 'mysqltest_3' on host 'localhost' delete from mysql.user where user like 'mysqltest\_%'; delete from mysql.db where user like 'mysqltest\_%'; flush privileges; diff --git a/mysql-test/t/grant2.test b/mysql-test/t/grant2.test index d1535fa17a9..3fbe2b0fe58 100644 --- a/mysql-test/t/grant2.test +++ b/mysql-test/t/grant2.test @@ -15,22 +15,16 @@ grant all privileges on `my\_%`.* to mysqltest_1@localhost with grant option; connect (user1,localhost,mysqltest_1,,); connection user1; select current_user(); +grant all privileges on `my\_1`.* to mysqltest_2@localhost with grant option; --error 1044 -grant all privileges on `my\_1`.* to mysqltest_9@localhost with grant option; -grant all privileges on `my_%`.* to mysqltest_2@localhost with grant option; +grant all privileges on `my_%`.* to mysqltest_3@localhost with grant option; disconnect user1; -connect (user2,localhost,mysqltest_2,,); -connection user2; -select current_user(); -grant all privileges on `mysql`.* to mysqltest_3@localhost with grant option; -disconnect user2; -connect (user3,localhost,mysqltest_3,,); -connection user3; -select current_user(); -show grants for mysqltest_3@localhost; -disconnect user3; connect (root,localhost,root,,); connection root; +show grants for mysqltest_1@localhost; +show grants for mysqltest_2@localhost; +--error 1141 +show grants for mysqltest_3@localhost; delete from mysql.user where user like 'mysqltest\_%'; delete from mysql.db where user like 'mysqltest\_%'; flush privileges; diff --git a/mysys/mf_wcomp.c b/mysys/mf_wcomp.c index bdcfb0501d8..62a5a02eaea 100644 --- a/mysys/mf_wcomp.c +++ b/mysys/mf_wcomp.c @@ -23,11 +23,12 @@ char wild_many='*'; char wild_one='?'; -char wild_prefix=0; +char wild_prefix=0; /* QQ this can potentially cause a SIGSEGV */ -int wild_compare(register const char *str, register const char *wildstr) +int wild_compare(register const char *str, register const char *wildstr, + pbool str_is_pattern) { - reg3 int flag; + char cmp; DBUG_ENTER("wild_compare"); while (*wildstr) @@ -35,33 +36,55 @@ int wild_compare(register const char *str, register const char *wildstr) while (*wildstr && *wildstr != wild_many && *wildstr != wild_one) { if (*wildstr == wild_prefix && wildstr[1]) + { wildstr++; - if (*wildstr++ != *str++) DBUG_RETURN(1); + if (str_is_pattern && *str++ != wild_prefix) + DBUG_RETURN(1); + } + if (*wildstr++ != *str++) + DBUG_RETURN(1); } - if (! *wildstr ) DBUG_RETURN (*str != 0); + if (! *wildstr ) + DBUG_RETURN(*str != 0); if (*wildstr++ == wild_one) { - if (! *str++) DBUG_RETURN (1); /* One char; skipp */ + if (! *str || (str_is_pattern && *str == wild_many)) + DBUG_RETURN(1); /* One char; skipp */ + if (*str++ == wild_prefix && str_is_pattern && *str) + str++; } else { /* Found '*' */ - if (!*wildstr) DBUG_RETURN(0); /* '*' as last char: OK */ - flag=(*wildstr != wild_many && *wildstr != wild_one); - do + while (str_is_pattern && *str == wild_many) + str++; + for (; *wildstr == wild_many || *wildstr == wild_one; wildstr++) + if (*wildstr == wild_many) + { + while (str_is_pattern && *str == wild_many) + str++; + } + else + { + if (str_is_pattern && *str == wild_prefix && str[1]) + str+=2; + else if (! *str++) + DBUG_RETURN (1); + } + if (!*wildstr) + DBUG_RETURN(0); /* '*' as last char: OK */ + if ((cmp= *wildstr) == wild_prefix && wildstr[1] && !str_is_pattern) + cmp=wildstr[1]; + for(;;str++) { - if (flag) - { - char cmp; - if ((cmp= *wildstr) == wild_prefix && wildstr[1]) - cmp=wildstr[1]; - while (*str && *str != cmp) - str++; - if (!*str) DBUG_RETURN (1); - } - if (wild_compare(str,wildstr) == 0) DBUG_RETURN (0); - } while (*str++ && wildstr[0] != wild_many); + while (*str && *str != cmp) + str++; + if (!*str) + DBUG_RETURN (1); + if (wild_compare(str,wildstr,str_is_pattern) == 0) + DBUG_RETURN (0); + } DBUG_RETURN(1); } } - DBUG_RETURN (*str != '\0'); + DBUG_RETURN (*str != 0); } /* wild_compare */ diff --git a/mysys/mf_wfile.c b/mysys/mf_wfile.c index 3c10de1f238..b964d7ee494 100644 --- a/mysys/mf_wfile.c +++ b/mysys/mf_wfile.c @@ -99,7 +99,7 @@ int wf_test(register WF_PACK *wf_pack, register const char *name) not_pos=wf_pack->not_pos; for (i=0 ; i < not_pos; i++) - if (wild_compare(name,wf_pack->wild[i]) == 0) + if (wild_compare(name,wf_pack->wild[i],0) == 0) goto found; if (i) DBUG_RETURN(1); /* No-match */ @@ -108,7 +108,7 @@ found: /* Test that it isn't in not-list */ for (i=not_pos ; i < wf_pack->wilds; i++) - if (wild_compare(name,wf_pack->wild[i]) == 0) + if (wild_compare(name,wf_pack->wild[i],0) == 0) DBUG_RETURN(1); DBUG_RETURN(0); } /* wf_test */ diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 1bdca7167e8..5034aaf9bd6 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -877,7 +877,7 @@ static void acl_insert_db(const char *user, const char *host, const char *db, *****************************************************************************/ ulong acl_get(const char *host, const char *ip, const char *bin_ip, - const char *user, const char *db) + const char *user, const char *db, my_bool db_is_pattern) { ulong host_access,db_access; uint i,key_length; @@ -911,7 +911,7 @@ ulong acl_get(const char *host, const char *ip, const char *bin_ip, { if (compare_hostname(&acl_db->host,host,ip)) { - if (!acl_db->db || !wild_compare(db,acl_db->db)) + if (!acl_db->db || !wild_compare(db,acl_db->db,db_is_pattern)) { db_access=acl_db->access; if (acl_db->host.hostname) @@ -933,7 +933,7 @@ ulong acl_get(const char *host, const char *ip, const char *bin_ip, ACL_HOST *acl_host=dynamic_element(&acl_hosts,i,ACL_HOST*); if (compare_hostname(&acl_host->host,host,ip)) { - if (!acl_host->db || !wild_compare(db,acl_host->db)) + if (!acl_host->db || !wild_compare(db,acl_host->db,db_is_pattern)) { host_access=acl_host->access; // Fully specified. Take it break; @@ -1271,7 +1271,7 @@ static bool compare_hostname(const acl_host_and_ip *host, const char *hostname, return (!host->hostname || (hostname && !wild_case_compare(&my_charset_latin1, hostname,host->hostname)) || - (ip && !wild_compare(ip,host->hostname))); + (ip && !wild_compare(ip,host->hostname,0))); } @@ -1331,7 +1331,7 @@ static bool test_if_create_new_users(THD *thd) tl.db= (char*) "mysql"; tl.real_name= (char*) "user"; db_access=acl_get(thd->host, thd->ip, (char*) &thd->remote.sin_addr, - thd->priv_user, tl.db); + thd->priv_user, tl.db, 0); if (!(db_access & INSERT_ACL)) { if (check_grant(thd,INSERT_ACL,&tl,0,1)) diff --git a/sql/sql_acl.h b/sql/sql_acl.h index e6c6771253c..ca976f43999 100644 --- a/sql/sql_acl.h +++ b/sql/sql_acl.h @@ -134,7 +134,7 @@ my_bool acl_init(THD *thd, bool dont_read_acl_tables); void acl_reload(THD *thd); void acl_free(bool end=0); ulong acl_get(const char *host, const char *ip, const char *bin_ip, - const char *user, const char *db); + 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, const char *password,const char *scramble, char **priv_user, char *priv_host, diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 641ab46e5e0..43368fe5433 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -148,7 +148,7 @@ OPEN_TABLE_LIST *list_open_tables(THD *thd, const char *wild) if (wild) { strxmov(name,entry->table_cache_key,".",entry->real_name,NullS); - if (wild_compare(name,wild)) + if (wild_compare(name,wild,0)) continue; } diff --git a/sql/sql_db.cc b/sql/sql_db.cc index f8cf1eee0c5..844fd05aefa 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -591,7 +591,7 @@ bool mysql_change_db(THD *thd, const char *name) db_access=DB_ACLS; else db_access= (acl_get(thd->host,thd->ip,(char*) &thd->remote.sin_addr, - thd->priv_user,dbname) | + thd->priv_user,dbname,0) | thd->master_access); if (!(db_access & DB_ACLS) && (!grant_option || check_grant_db(thd,dbname))) { @@ -625,8 +625,8 @@ bool mysql_change_db(THD *thd, const char *name) strmov(path+unpack_dirname(path,path), MY_DB_OPT_FILE); load_db_opt(thd, path, &create); - thd->db_charset= create.table_charset ? - create.table_charset : + thd->db_charset= create.table_charset ? + create.table_charset : global_system_variables.character_set_database; thd->variables.character_set_database= thd->db_charset; DBUG_RETURN(0); @@ -644,18 +644,18 @@ int mysqld_show_create_db(THD *thd, char *dbname, uint create_options = create_info ? create_info->options : 0; Protocol *protocol=thd->protocol; DBUG_ENTER("mysql_show_create_db"); - + if (check_db_name(dbname)) { net_printf(thd,ER_WRONG_DB_NAME, dbname); DBUG_RETURN(1); } - + if (test_all_bits(thd->master_access,DB_ACLS)) db_access=DB_ACLS; else db_access= (acl_get(thd->host,thd->ip,(char*) &thd->remote.sin_addr, - thd->priv_user,dbname) | + thd->priv_user,dbname,0) | thd->master_access); if (!(db_access & DB_ACLS) && (!grant_option || check_grant_db(thd,dbname))) { @@ -669,7 +669,7 @@ int mysqld_show_create_db(THD *thd, char *dbname, dbname); DBUG_RETURN(1); } - + (void) sprintf(path,"%s/%s",mysql_data_home, dbname); length=unpack_dirname(path,path); // Convert if not unix found_libchar= 0; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 9e670a97e92..820bf3d73cc 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -3254,7 +3254,7 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv, if (!(thd->master_access & SELECT_ACL) && (db && (!thd->db || strcmp(db,thd->db)))) db_access=acl_get(thd->host, thd->ip, (char*) &thd->remote.sin_addr, - thd->priv_user, db); /* purecov: inspected */ + thd->priv_user, db, test(want_access & GRANT_ACL)); *save_priv=thd->master_access | db_access; DBUG_RETURN(FALSE); } @@ -3274,7 +3274,7 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv, if (db && (!thd->db || strcmp(db,thd->db))) db_access=acl_get(thd->host, thd->ip, (char*) &thd->remote.sin_addr, - thd->priv_user, db); /* purecov: inspected */ + thd->priv_user, db, test(want_access & GRANT_ACL)); else db_access=thd->db_access; // Remove SHOW attribute and access rights we already have diff --git a/sql/sql_show.cc b/sql/sql_show.cc index e8cb59e387e..9084269f486 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -75,7 +75,7 @@ mysqld_show_dbs(THD *thd,const char *wild) { if (thd->master_access & (DB_ACLS | SHOW_DB_ACL) || acl_get(thd->host, thd->ip, (char*) &thd->remote.sin_addr, - thd->priv_user, file_name) || + thd->priv_user, file_name,0) || (grant_option && !check_grant_db(thd, file_name))) { protocol->prepare_for_resend(); @@ -415,7 +415,7 @@ mysql_find_files(THD *thd,List<char> *files, const char *db,const char *path, #endif { if (file->name[0] == '.' || !MY_S_ISDIR(file->mystat.st_mode) || - (wild && wild_compare(file->name,wild))) + (wild && wild_compare(file->name,wild,0))) continue; } } @@ -433,7 +433,7 @@ mysql_find_files(THD *thd,List<char> *files, const char *db,const char *path, if (wild_case_compare(system_charset_info,file->name,wild)) continue; } - else if (wild_compare(file->name,wild)) + else if (wild_compare(file->name,wild,0)) continue; } } @@ -1031,7 +1031,7 @@ store_create_info(THD *thd, TABLE *table, String *packet) my_bool limited_mysql_mode= (thd->variables.sql_mode & (MODE_NO_FIELD_OPTIONS | MODE_MYSQL323 | MODE_MYSQL40)) != 0; - + DBUG_ENTER("store_create_info"); DBUG_PRINT("enter",("table: %s",table->real_name)); diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 709181af7fa..a5ac04dc775 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -547,7 +547,6 @@ bool my_yyoverflow(short **a, YYSTYPE **b,int *yystacksize); %token SUBJECT_SYM %token CIPHER_SYM -%token HELP %token BEFORE_SYM %left SET_VAR %left OR_OR_CONCAT OR |