diff options
Diffstat (limited to 'sql/sql_acl.cc')
-rw-r--r-- | sql/sql_acl.cc | 161 |
1 files changed, 86 insertions, 75 deletions
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 91bdb174d51..cd7ad3f8665 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -727,7 +727,7 @@ static bool initialized=0; static bool allow_all_hosts=1; static HASH acl_check_hosts, column_priv_hash, proc_priv_hash, func_priv_hash; static DYNAMIC_ARRAY acl_wild_hosts; -static hash_filo *acl_cache; +static Hash_filo<acl_entry> *acl_cache; static uint grant_version=0; /* Version of priv tables. incremented by acl_load */ static ulong get_access(TABLE *form,uint fieldnr, uint *next_field=0); static bool check_is_role(TABLE *form); @@ -924,7 +924,7 @@ my_bool acl_init(bool dont_read_acl_tables) my_bool return_val; DBUG_ENTER("acl_init"); - acl_cache= new hash_filo(ACL_CACHE_SIZE, 0, 0, + acl_cache= new Hash_filo<acl_entry>(ACL_CACHE_SIZE, 0, 0, (my_hash_get_key) acl_entry_get_key, (my_hash_free_key) free, &my_charset_utf8_bin); @@ -2182,8 +2182,7 @@ ulong acl_get(const char *host, const char *ip, key_length= (size_t) (end-key); mysql_mutex_lock(&acl_cache->lock); - if (!db_is_pattern && (entry=(acl_entry*) acl_cache->search((uchar*) key, - key_length))) + if (!db_is_pattern && (entry=acl_cache->search((uchar*) key, key_length))) { db_access=entry->access; mysql_mutex_unlock(&acl_cache->lock); @@ -4568,7 +4567,7 @@ static int merge_role_privileges(ACL_ROLE *, ACL_ROLE *, void *); */ static void propagate_role_grants(ACL_ROLE *role, enum PRIVS_TO_MERGE::what what, - const char *db, const char *name) + const char *db= 0, const char *name= 0) { mysql_mutex_assert_owner(&acl_cache->lock); @@ -5221,6 +5220,8 @@ static int update_role_routines(GRANT_NAME *merged, GRANT_NAME **first, if (!first) return 0; + DBUG_EXECUTE_IF("role_merge_stats", role_routine_merges++;); + if (merged == NULL) { /* @@ -5267,8 +5268,6 @@ static bool merge_role_routine_grant_privileges(ACL_ROLE *grantee, DBUG_ASSERT(MY_TEST(db) == MY_TEST(tname)); // both must be set, or neither - DBUG_EXECUTE_IF("role_merge_stats", role_routine_merges++;); - Dynamic_array<GRANT_NAME *> grants; /* first, collect routine privileges granted to roles in question */ @@ -5354,6 +5353,13 @@ static int merge_role_privileges(ACL_ROLE *role __attribute__((unused)), return !changed; // don't recurse into the subgraph if privs didn't change } +static bool merge_one_role_privileges(ACL_ROLE *grantee) +{ + PRIVS_TO_MERGE data= { PRIVS_TO_MERGE::ALL, 0, 0 }; + grantee->counter= 1; + return merge_role_privileges(0, grantee, &data); +} + /***************************************************************** End of the role privilege propagation and graph traversal code ******************************************************************/ @@ -5831,19 +5837,42 @@ bool mysql_routine_grant(THD *thd, TABLE_LIST *table_list, bool is_proc, DBUG_RETURN(result); } -static void append_user(String *str, const char *u, const char *h) +/** + append a user or role name to a buffer that will be later used as an error message +*/ +static void append_user(THD *thd, String *str, + const LEX_STRING *u, const LEX_STRING *h) { if (str->length()) str->append(','); - str->append('\''); - str->append(u); + append_query_string(system_charset_info, str, u->str, u->length, + thd->variables.sql_mode & MODE_NO_BACKSLASH_ESCAPES); /* hostname part is not relevant for roles, it is always empty */ - if (*h) + if (u->length == 0 || h->length != 0) { - str->append(STRING_WITH_LEN("'@'")); - str->append(h); + str->append('@'); + append_query_string(system_charset_info, str, h->str, h->length, + thd->variables.sql_mode & MODE_NO_BACKSLASH_ESCAPES); } - str->append('\''); +} + +static void append_user(THD *thd, String *str, LEX_USER *user) +{ + append_user(thd, str, & user->user, & user->host); +} + +/** + append a string to a buffer that will be later used as an error message + + @note + a string can be either CURRENT_USER or CURRENT_ROLE or NONE, it should be + neither quoted nor escaped. +*/ +static void append_str(String *str, const char *s, size_t l) +{ + if (str->length()) + str->append(','); + str->append(s, l); } static int can_grant_role_callback(ACL_USER_BASE *grantee, @@ -5961,13 +5990,15 @@ bool mysql_grant_role(THD *thd, List <LEX_USER> &list, bool revoke) if (!thd->security_ctx->priv_role[0]) { my_error(ER_INVALID_ROLE, MYF(0), "NONE"); - append_user(&wrong_users, "NONE", ""); + append_str(&wrong_users, STRING_WITH_LEN("NONE")); result= 1; continue; } if (!(role_as_user= find_acl_role(thd->security_ctx->priv_role))) { - append_user(&wrong_users, thd->security_ctx->priv_role, ""); + LEX_STRING ls= { thd->security_ctx->priv_role, + strlen(thd->security_ctx->priv_role) }; + append_user(thd, &wrong_users, &ls, &empty_lex_str); result= 1; continue; } @@ -5975,7 +6006,7 @@ bool mysql_grant_role(THD *thd, List <LEX_USER> &list, bool revoke) /* can not grant current_role to current_role */ if (granted_role->user.str == current_role.str) { - append_user(&wrong_users, thd->security_ctx->priv_role, ""); + append_user(thd, &wrong_users, &role_as_user->user, &empty_lex_str); result= 1; continue; } @@ -6002,7 +6033,7 @@ bool mysql_grant_role(THD *thd, List <LEX_USER> &list, bool revoke) { if (is_invalid_role_name(username.str)) { - append_user(&wrong_users, username.str, ""); + append_user(thd, &wrong_users, &username, &empty_lex_str); result= 1; continue; } @@ -6028,7 +6059,7 @@ bool mysql_grant_role(THD *thd, List <LEX_USER> &list, bool revoke) false, create_new_user, no_auto_create_user)) { - append_user(&wrong_users, username.str, hostname.str); + append_user(thd, &wrong_users, &username, &hostname); result= 1; continue; } @@ -6040,7 +6071,7 @@ bool mysql_grant_role(THD *thd, List <LEX_USER> &list, bool revoke) if (!grantee) { - append_user(&wrong_users, username.str, hostname.str); + append_user(thd, &wrong_users, &username, &hostname); result= 1; continue; } @@ -6062,7 +6093,7 @@ bool mysql_grant_role(THD *thd, List <LEX_USER> &list, bool revoke) if (role_as_user && traverse_role_graph_down(role, 0, 0, 0) == ROLE_CYCLE_FOUND) { - append_user(&wrong_users, username.str, ""); + append_user(thd, &wrong_users, &username, &empty_lex_str); result= 1; undo_add_role_user_mapping(grantee, role); continue; @@ -6074,7 +6105,7 @@ bool mysql_grant_role(THD *thd, List <LEX_USER> &list, bool revoke) /* grant was already removed or never existed */ if (!hash_entry) { - append_user(&wrong_users, username.str, hostname.str); + append_user(thd, &wrong_users, &username, &hostname); result= 1; continue; } @@ -6095,7 +6126,7 @@ bool mysql_grant_role(THD *thd, List <LEX_USER> &list, bool revoke) thd->lex->with_admin_option, hash_entry, revoke)) { - append_user(&wrong_users, username.str, ""); + append_user(thd, &wrong_users, &username, &empty_lex_str); result= 1; if (!revoke) { @@ -6116,8 +6147,8 @@ bool mysql_grant_role(THD *thd, List <LEX_USER> &list, bool revoke) Only need to propagate grants when granting/revoking a role to/from a role */ - if (role_as_user) - propagate_role_grants(role_as_user, PRIVS_TO_MERGE::ALL, 0, 0); + if (role_as_user && merge_one_role_privileges(role_as_user) == 0) + propagate_role_grants(role_as_user, PRIVS_TO_MERGE::ALL); } mysql_mutex_unlock(&acl_cache->lock); @@ -6265,7 +6296,7 @@ bool mysql_grant(THD *thd, const char *db, List <LEX_USER> &list, if (Str->is_role()) propagate_role_grants(find_acl_role(Str->user.str), db ? PRIVS_TO_MERGE::DB : PRIVS_TO_MERGE::GLOBAL, - db, 0); + db); } mysql_mutex_unlock(&acl_cache->lock); @@ -7119,16 +7150,22 @@ bool check_grant_db(THD *thd, const char *db) { Security_context *sctx= thd->security_ctx; char helping [SAFE_NAME_LEN + USERNAME_LENGTH+2], *end; - char helping2 [SAFE_NAME_LEN + USERNAME_LENGTH+2]; + char helping2 [SAFE_NAME_LEN + USERNAME_LENGTH+2], *tmp_db; uint len, UNINIT_VAR(len2); bool error= TRUE; - end= strmov(helping, sctx->priv_user) + 1; - end= strnmov(end, db, helping + sizeof(helping) - end); + tmp_db= strmov(helping, sctx->priv_user) + 1; + end= strnmov(tmp_db, db, helping + sizeof(helping) - tmp_db); if (end >= helping + sizeof(helping)) // db name was truncated return 1; // no privileges for an invalid db name + if (lower_case_table_names) + { + end = tmp_db + my_casedn_str(files_charset_info, tmp_db); + db=tmp_db; + } + len= (uint) (end - helping) + 1; /* @@ -8671,7 +8708,7 @@ static int handle_grant_struct(enum enum_acl_lists struct_no, bool drop, if (drop) { /* all grants must be revoked from this role by now. propagate this */ - propagate_role_grants(acl_role, PRIVS_TO_MERGE::ALL, 0, 0); + propagate_role_grants(acl_role, PRIVS_TO_MERGE::ALL); // delete the role from cross-reference arrays for (uint i=0; i < acl_role->role_grants.elements; i++) @@ -9137,28 +9174,6 @@ end: DBUG_RETURN(result); } -static void append_user(String *str, LEX_USER *user) -{ - if (str->length()) - str->append(','); - str->append('\''); - str->append(user->user.str); - /* hostname part is not relevant for roles, it is always empty */ - if (!user->is_role()) - { - str->append(STRING_WITH_LEN("'@'")); - str->append(user->host.str); - } - str->append('\''); -} - -static void append_str(String *str, const char *s, size_t l) -{ - if (str->length()) - str->append(','); - str->append(s, l); -} - /* Create a list of users. @@ -9212,7 +9227,7 @@ bool mysql_create_user(THD *thd, List <LEX_USER> &list, bool handle_as_role) if (handle_as_role && is_invalid_role_name(user_name->user.str)) { - append_user(&wrong_users, user_name); + append_user(thd, &wrong_users, user_name); result= TRUE; continue; } @@ -9226,7 +9241,7 @@ bool mysql_create_user(THD *thd, List <LEX_USER> &list, bool handle_as_role) */ if (handle_grant_data(tables, 0, user_name, NULL)) { - append_user(&wrong_users, user_name); + append_user(thd, &wrong_users, user_name); result= TRUE; continue; @@ -9235,7 +9250,7 @@ bool mysql_create_user(THD *thd, List <LEX_USER> &list, bool handle_as_role) some_users_created= TRUE; if (replace_user_table(thd, tables[0].table, *user_name, 0, 0, 1, 0)) { - append_user(&wrong_users, user_name); + append_user(thd, &wrong_users, user_name); result= TRUE; continue; } @@ -9260,7 +9275,7 @@ bool mysql_create_user(THD *thd, List <LEX_USER> &list, bool handle_as_role) &user_name->user, true, NULL, false)) { - append_user(&wrong_users, user_name); + append_user(thd, &wrong_users, user_name); if (grantee) undo_add_role_user_mapping(grantee, role); result= TRUE; @@ -9333,14 +9348,14 @@ bool mysql_drop_user(THD *thd, List <LEX_USER> &list, bool handle_as_role) if (handle_as_role != user_name->is_role()) { - append_user(&wrong_users, user_name); + append_user(thd, &wrong_users, user_name); result= TRUE; continue; } if (handle_grant_data(tables, 1, user_name, NULL) <= 0) { - append_user(&wrong_users, user_name); + append_user(thd, &wrong_users, user_name); result= TRUE; continue; } @@ -9413,13 +9428,13 @@ bool mysql_rename_user(THD *thd, List <LEX_USER> &list) tmp_user_to= user_list++; if (!(user_from= get_current_user(thd, tmp_user_from, false))) { - append_user(&wrong_users, user_from); + append_user(thd, &wrong_users, user_from); result= TRUE; continue; } if (!(user_to= get_current_user(thd, tmp_user_to, false))) { - append_user(&wrong_users, user_to); + append_user(thd, &wrong_users, user_to); result= TRUE; continue; } @@ -9434,7 +9449,7 @@ bool mysql_rename_user(THD *thd, List <LEX_USER> &list) handle_grant_data(tables, 0, user_from, user_to) <= 0) { /* NOTE TODO renaming roles is not yet implemented */ - append_user(&wrong_users, user_from); + append_user(thd, &wrong_users, user_from); result= TRUE; continue; } @@ -9678,7 +9693,7 @@ bool mysql_revoke_all(THD *thd, List <LEX_USER> &list) */ if (lex_user->is_role()) { - propagate_role_grants((ACL_ROLE *)user_or_role, PRIVS_TO_MERGE::ALL, 0, 0); + propagate_role_grants((ACL_ROLE *)user_or_role, PRIVS_TO_MERGE::ALL); } } @@ -11751,9 +11766,6 @@ static int server_mpvio_read_packet(MYSQL_PLUGIN_VIO *param, uchar **buf) mpvio->cached_client_reply.pkt= 0; mpvio->packets_read++; - if (mpvio->make_it_fail) - goto err; - DBUG_RETURN ((int) mpvio->cached_client_reply.pkt_len); } @@ -11788,21 +11800,13 @@ static int server_mpvio_read_packet(MYSQL_PLUGIN_VIO *param, uchar **buf) else *buf= mpvio->thd->net.read_pos; - if (mpvio->make_it_fail) - goto err; - DBUG_RETURN((int)pkt_len); err: if (mpvio->status == MPVIO_EXT::FAILURE) { if (!mpvio->thd->is_error()) - { - if (mpvio->make_it_fail) - login_failed_error(mpvio->thd); - else - my_error(ER_HANDSHAKE_ERROR, MYF(0)); - } + my_error(ER_HANDSHAKE_ERROR, MYF(0)); } DBUG_RETURN(-1); } @@ -12067,7 +12071,12 @@ bool acl_authenticate(THD *thd, uint connect_errors, auth_plugin_name= &mpvio.acl_user->plugin; res= do_auth_once(thd, auth_plugin_name, &mpvio); } - + if (mpvio.make_it_fail && res == CR_OK) + { + mpvio.status= MPVIO_EXT::FAILURE; + res= CR_ERROR; + } + Security_context *sctx= thd->security_ctx; const ACL_USER *acl_user= mpvio.acl_user; @@ -12360,6 +12369,8 @@ static int native_password_authenticate(MYSQL_PLUGIN_VIO *vio, DBUG_RETURN(CR_OK); #endif + DBUG_EXECUTE_IF("native_password_bad_reply", { pkt_len= 12; }); + if (pkt_len == 0) /* no password */ DBUG_RETURN(mpvio->acl_user->salt_len != 0 ? CR_AUTH_USER_CREDENTIALS : CR_OK); |