diff options
-rw-r--r-- | sql/mysqld.cc | 1 | ||||
-rw-r--r-- | sql/sp_head.cc | 5 | ||||
-rw-r--r-- | sql/sql_acl.cc | 144 | ||||
-rw-r--r-- | sql/sql_acl.h | 2 | ||||
-rw-r--r-- | sql/sql_lex.h | 1 | ||||
-rw-r--r-- | sql/sql_parse.cc | 6 | ||||
-rw-r--r-- | sql/sql_yacc.yy | 2 |
7 files changed, 136 insertions, 25 deletions
diff --git a/sql/mysqld.cc b/sql/mysqld.cc index a758280490d..dbaf9113dd1 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -3517,6 +3517,7 @@ SHOW_VAR com_status_vars[]= { #endif {"show_function_status", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_STATUS_FUNC]), SHOW_LONG_STATUS}, {"show_grants", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_GRANTS]), SHOW_LONG_STATUS}, + {"show_grants_self", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_GRANTS_SELF]), SHOW_LONG_STATUS}, {"show_keys", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_KEYS]), SHOW_LONG_STATUS}, {"show_index_statistics", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_INDEX_STATS]), SHOW_LONG_STATUS}, {"show_master_status", (char*) offsetof(STATUS_VAR, com_stat[(uint) SQLCOM_SHOW_MASTER_STAT]), SHOW_LONG_STATUS}, diff --git a/sql/sp_head.cc b/sql/sp_head.cc index 0c887c5e157..8ea0fa5e579 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -223,6 +223,7 @@ sp_get_flags_for_command(LEX *lex) case SQLCOM_SHOW_FIELDS: case SQLCOM_SHOW_FUNC_CODE: case SQLCOM_SHOW_GRANTS: + case SQLCOM_SHOW_GRANTS_SELF: case SQLCOM_SHOW_ENGINE_STATUS: case SQLCOM_SHOW_ENGINE_LOGS: case SQLCOM_SHOW_ENGINE_MUTEX: @@ -282,9 +283,12 @@ sp_get_flags_for_command(LEX *lex) case SQLCOM_CREATE_VIEW: case SQLCOM_CREATE_TRIGGER: case SQLCOM_CREATE_USER: + case SQLCOM_CREATE_ROLE: case SQLCOM_ALTER_TABLE: case SQLCOM_GRANT: + case SQLCOM_GRANT_ROLE: case SQLCOM_REVOKE: + case SQLCOM_REVOKE_ROLE: case SQLCOM_BEGIN: case SQLCOM_RENAME_TABLE: case SQLCOM_RENAME_USER: @@ -292,6 +296,7 @@ sp_get_flags_for_command(LEX *lex) case SQLCOM_DROP_DB: case SQLCOM_REVOKE_ALL: case SQLCOM_DROP_USER: + case SQLCOM_DROP_ROLE: case SQLCOM_DROP_VIEW: case SQLCOM_DROP_TRIGGER: case SQLCOM_TRUNCATE: diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 6d3d4052258..b14bad9b600 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -316,8 +316,10 @@ static bool show_global_privileges(THD *thd, LEX_USER *lex_user, ACL_USER_BASE *acl_entry, bool handle_as_role, char *buff, size_t buffsize); static bool show_database_privileges(THD *thd, LEX_USER *lex_user, + bool handle_as_role, char *buff, size_t buffsize); static bool show_table_and_column_privileges(THD *thd, LEX_USER *lex_user, + bool handle_as_role, char *buff, size_t buffsize); class ACL_PROXY_USER :public ACL_ACCESS @@ -3884,6 +3886,7 @@ public: acl_host_and_ip host; char *db, *user, *tname, *hash_key; ulong privs; + ulong init_privs; /* privileges found in physical table */ ulong sort; size_t key_length; GRANT_NAME(const char *h, const char *d,const char *u, @@ -3901,7 +3904,9 @@ class GRANT_TABLE :public GRANT_NAME { public: ulong cols; + ulong init_cols; /* privileges found in physical table */ HASH hash_columns; + HASH init_hash_columns; GRANT_TABLE(const char *h, const char *d,const char *u, const char *t, ulong p, ulong c); @@ -6354,6 +6359,7 @@ static uint command_lengths[]= static int show_routine_grants(THD *thd, LEX_USER *lex_user, HASH *hash, const char *type, int typelen, + bool handle_as_role, char *buff, int buffsize); @@ -6364,7 +6370,32 @@ static int show_routine_grants(THD *thd, LEX_USER *lex_user, HASH *hash, Send to client grant-like strings depicting user@host privileges */ -bool mysql_show_grants(THD *thd,LEX_USER *lex_user) +bool print_grants_for_role(THD *thd, ACL_ROLE * role, + char *buff, size_t buffsize) +{ + LEX_USER lex_user; + lex_user.user= role->user; + if (show_global_privileges(thd, &lex_user, role, TRUE, buff, buffsize)) + return TRUE; + + if (show_database_privileges(thd, &lex_user, TRUE, buff, buffsize)) + return TRUE; + + if (show_table_and_column_privileges(thd, &lex_user, TRUE, buff, buffsize)) + return TRUE; + + if (show_routine_grants(thd, &lex_user, &proc_priv_hash, + STRING_WITH_LEN("PROCEDURE"), TRUE, buff, buffsize)) + return TRUE; + + if (show_routine_grants(thd, &lex_user, &func_priv_hash, + STRING_WITH_LEN("FUNCTION"), TRUE, buff, buffsize)) + return TRUE; + + return FALSE; + +} +bool mysql_show_grants(THD *thd, LEX_USER *lex_user, bool print_current_role) { int error = 0; ACL_USER *acl_user; @@ -6424,28 +6455,28 @@ bool mysql_show_grants(THD *thd,LEX_USER *lex_user) }; /* Add database access */ - if (show_database_privileges(thd, lex_user, buff, sizeof(buff))) + if (show_database_privileges(thd, lex_user, FALSE, buff, sizeof(buff))) { error= -1; goto end; } /* Add table & column access */ - if (show_table_and_column_privileges(thd, lex_user, buff, sizeof(buff))) + if (show_table_and_column_privileges(thd, lex_user, FALSE, buff, sizeof(buff))) { error= -1; goto end; } if (show_routine_grants(thd, lex_user, &proc_priv_hash, - STRING_WITH_LEN("PROCEDURE"), buff, sizeof(buff))) + STRING_WITH_LEN("PROCEDURE"), FALSE, buff, sizeof(buff))) { error= -1; goto end; } if (show_routine_grants(thd, lex_user, &func_priv_hash, - STRING_WITH_LEN("FUNCTION"), buff, sizeof(buff))) + STRING_WITH_LEN("FUNCTION"), FALSE, buff, sizeof(buff))) { error= -1; goto end; @@ -6457,6 +6488,32 @@ bool mysql_show_grants(THD *thd,LEX_USER *lex_user) goto end; } + if (print_current_role) + { + ACL_ROLE *role= find_acl_role(thd->security_ctx->priv_role); + if (role) + { + DYNAMIC_ARRAY role_list; + (void) my_init_dynamic_array(&role_list,sizeof(ACL_ROLE *), + 50, 100, MYF(0)); + /* get a list of all inherited roles */ + traverse_role_graph(role, + &role_list, NULL, NULL, NULL, + role_explore_create_list); + for (uint i= 0; i < role_list.elements; i++) + { + if (print_grants_for_role(thd, + *dynamic_element(&role_list, i, ACL_ROLE **), + buff, sizeof(buff))) + { + error= -1; + goto end; + } + } + delete_dynamic(&role_list); + } + } + end: mysql_mutex_unlock(&acl_cache->lock); mysql_rwlock_unlock(&LOCK_grant); @@ -6513,7 +6570,10 @@ static bool show_global_privileges(THD *thd, LEX_USER *lex_user, global.length(0); global.append(STRING_WITH_LEN("GRANT ")); - want_access= acl_entry->access; + if (handle_as_role) + want_access= ((ACL_ROLE *)acl_entry)->initial_role_access; + else + want_access= acl_entry->access; if (test_all_bits(want_access, (GLOBAL_ACLS & ~ GRANT_ACL))) global.append(STRING_WITH_LEN("ALL PRIVILEGES")); else if (!(want_access & ~GRANT_ACL)) @@ -6632,6 +6692,7 @@ static bool show_global_privileges(THD *thd, LEX_USER *lex_user, } static bool show_database_privileges(THD *thd, LEX_USER *lex_user, + bool handle_as_role, char *buff, size_t buffsize) { ACL_DB *acl_db; @@ -6659,7 +6720,12 @@ static bool show_database_privileges(THD *thd, LEX_USER *lex_user, if (!strcmp(lex_user->user.str,user) && !my_strcasecmp(system_charset_info, lex_user->host.str, host)) { - want_access=acl_db->access; + /* do not print inherited access bits, the role bits present in the + table are what matters */ + if (handle_as_role) + want_access=acl_db->initial_access; + else + want_access=acl_db->access; if (want_access) { String db(buff,sizeof(buff),system_charset_info); @@ -6690,9 +6756,12 @@ static bool show_database_privileges(THD *thd, LEX_USER *lex_user, db.append (STRING_WITH_LEN(".* TO '")); db.append(lex_user->user.str, lex_user->user.length, system_charset_info); - db.append (STRING_WITH_LEN("'@'")); - // host and lex_user->host are equal except for case - db.append(host, strlen(host), system_charset_info); + if (!handle_as_role) + { + db.append (STRING_WITH_LEN("'@'")); + // host and lex_user->host are equal except for case + db.append(host, strlen(host), system_charset_info); + } db.append ('\''); if (want_access & GRANT_ACL) db.append(STRING_WITH_LEN(" WITH GRANT OPTION")); @@ -6710,6 +6779,7 @@ static bool show_database_privileges(THD *thd, LEX_USER *lex_user, } static bool show_table_and_column_privileges(THD *thd, LEX_USER *lex_user, + bool handle_as_role, char *buff, size_t buffsize) { uint counter, index; @@ -6736,11 +6806,23 @@ static bool show_table_and_column_privileges(THD *thd, LEX_USER *lex_user, if (!strcmp(lex_user->user.str,user) && !my_strcasecmp(system_charset_info, lex_user->host.str, host)) { - ulong table_access= grant_table->privs; - if ((table_access | grant_table->cols) != 0) + ulong table_access; + ulong cols_access; + if (handle_as_role) + { + table_access= grant_table->init_privs; + cols_access= grant_table->init_cols; + } + else + { + table_access= grant_table->privs; + cols_access= grant_table->cols; + } + + if ((table_access | cols_access) != 0) { String global(buff, sizeof(buff), system_charset_info); - ulong test_access= (table_access | grant_table->cols) & ~GRANT_ACL; + ulong test_access= (table_access | cols_access) & ~GRANT_ACL; global.length(0); global.append(STRING_WITH_LEN("GRANT ")); @@ -6767,12 +6849,18 @@ static bool show_table_and_column_privileges(THD *thd, LEX_USER *lex_user, if (grant_table->cols) { uint found_col= 0; + HASH *hash_columns; + if (handle_as_role) + hash_columns= &grant_table->init_hash_columns; + else + hash_columns= &grant_table->hash_columns; + for (uint col_index=0 ; - col_index < grant_table->hash_columns.records ; + col_index < hash_columns->records ; col_index++) { GRANT_COLUMN *grant_column = (GRANT_COLUMN*) - my_hash_element(&grant_table->hash_columns,col_index); + my_hash_element(hash_columns,col_index); if (grant_column->rights & j) { if (!found_col) @@ -6812,9 +6900,12 @@ static bool show_table_and_column_privileges(THD *thd, LEX_USER *lex_user, global.append(STRING_WITH_LEN(" TO '")); global.append(lex_user->user.str, lex_user->user.length, system_charset_info); - global.append(STRING_WITH_LEN("'@'")); - // host and lex_user->host are equal except for case - global.append(host, strlen(host), system_charset_info); + if (!handle_as_role) + { + global.append(STRING_WITH_LEN("'@'")); + // host and lex_user->host are equal except for case + global.append(host, strlen(host), system_charset_info); + } global.append('\''); if (table_access & GRANT_ACL) global.append(STRING_WITH_LEN(" WITH GRANT OPTION")); @@ -6833,6 +6924,7 @@ static bool show_table_and_column_privileges(THD *thd, LEX_USER *lex_user, static int show_routine_grants(THD* thd, LEX_USER *lex_user, HASH *hash, const char *type, int typelen, + bool handle_as_role, char *buff, int buffsize) { uint counter, index; @@ -6859,7 +6951,12 @@ static int show_routine_grants(THD* thd, LEX_USER *lex_user, HASH *hash, if (!strcmp(lex_user->user.str,user) && !my_strcasecmp(system_charset_info, lex_user->host.str, host)) { - ulong proc_access= grant_proc->privs; + ulong proc_access; + if (handle_as_role) + proc_access= grant_proc->init_privs; + else + proc_access= grant_proc->privs; + if (proc_access != 0) { String global(buff, buffsize, system_charset_info); @@ -6898,9 +6995,12 @@ static int show_routine_grants(THD* thd, LEX_USER *lex_user, HASH *hash, global.append(STRING_WITH_LEN(" TO '")); global.append(lex_user->user.str, lex_user->user.length, system_charset_info); - global.append(STRING_WITH_LEN("'@'")); - // host and lex_user->host are equal except for case - global.append(host, strlen(host), system_charset_info); + if (!handle_as_role) + { + global.append(STRING_WITH_LEN("'@'")); + // host and lex_user->host are equal except for case + global.append(host, strlen(host), system_charset_info); + } global.append('\''); if (proc_access & GRANT_ACL) global.append(STRING_WITH_LEN(" WITH GRANT OPTION")); diff --git a/sql/sql_acl.h b/sql/sql_acl.h index cace79cb441..4a7e83f12df 100644 --- a/sql/sql_acl.h +++ b/sql/sql_acl.h @@ -227,7 +227,7 @@ ulong get_table_grant(THD *thd, TABLE_LIST *table); ulong get_column_grant(THD *thd, GRANT_INFO *grant, const char *db_name, const char *table_name, const char *field_name); -bool mysql_show_grants(THD *thd, LEX_USER *user); +bool mysql_show_grants(THD *thd, LEX_USER *user, bool print_current_role); void get_privilege_desc(char *to, uint max_length, ulong access); void get_mqh(const char *user, const char *host, USER_CONN *uc); bool mysql_create_user(THD *thd, List <LEX_USER> &list, bool handle_as_role); diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 293081c21db..1c1e5520a4f 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -146,6 +146,7 @@ enum enum_sql_command { SQLCOM_SHOW_GRANTS, SQLCOM_SHOW_CREATE, SQLCOM_SHOW_CHARSETS, SQLCOM_SHOW_COLLATIONS, SQLCOM_SHOW_CREATE_DB, SQLCOM_SHOW_TABLE_STATUS, SQLCOM_SHOW_TRIGGERS, + SQLCOM_SHOW_GRANTS_SELF, SQLCOM_LOAD,SQLCOM_SET_OPTION,SQLCOM_LOCK_TABLES,SQLCOM_UNLOCK_TABLES, SQLCOM_GRANT, SQLCOM_GRANT_ROLE, diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 7b24973a6e5..f0da666ad1b 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -341,6 +341,7 @@ void init_update_queries(void) sql_command_flags[SQLCOM_SHOW_EXPLAIN]= CF_STATUS_COMMAND; sql_command_flags[SQLCOM_SHOW_PROCESSLIST]= CF_STATUS_COMMAND; sql_command_flags[SQLCOM_SHOW_GRANTS]= CF_STATUS_COMMAND; + sql_command_flags[SQLCOM_SHOW_GRANTS_SELF]= CF_STATUS_COMMAND; sql_command_flags[SQLCOM_SHOW_CREATE_DB]= CF_STATUS_COMMAND; sql_command_flags[SQLCOM_SHOW_CREATE]= CF_STATUS_COMMAND; sql_command_flags[SQLCOM_SHOW_MASTER_STAT]= CF_STATUS_COMMAND; @@ -3990,6 +3991,7 @@ end_with_restore_list: #ifndef NO_EMBEDDED_ACCESS_CHECKS case SQLCOM_SHOW_GRANTS: + case SQLCOM_SHOW_GRANTS_SELF: { LEX_USER *grant_user= get_current_user(thd, lex->grant_user); if (!grant_user) @@ -3998,7 +4000,9 @@ end_with_restore_list: !strcmp(thd->security_ctx->priv_user, grant_user->user.str)) || !check_access(thd, SELECT_ACL, "mysql", NULL, NULL, 1, 0)) { - res = mysql_show_grants(thd, grant_user); + res = mysql_show_grants(thd, grant_user, + (lex->sql_command == SQLCOM_SHOW_GRANTS_SELF) ? + TRUE : FALSE); } break; } diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 43e0194948c..9ea07f34a3f 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -11757,7 +11757,7 @@ show_param: | GRANTS { LEX *lex=Lex; - lex->sql_command= SQLCOM_SHOW_GRANTS; + lex->sql_command= SQLCOM_SHOW_GRANTS_SELF; LEX_USER *curr_user; if (!(curr_user= (LEX_USER*) lex->thd->alloc(sizeof(st_lex_user)))) MYSQL_YYABORT; |