diff options
Diffstat (limited to 'sql/sql_acl.cc')
-rw-r--r-- | sql/sql_acl.cc | 1106 |
1 files changed, 570 insertions, 536 deletions
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 894988c4931..d8a81cea53c 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -25,7 +25,7 @@ in the relevant fields. Empty strings comes last. */ -#include <my_global.h> /* NO_EMBEDDED_ACCESS_CHECKS */ +#include "mariadb.h" /* NO_EMBEDDED_ACCESS_CHECKS */ #include "sql_priv.h" #include "sql_acl.h" // MYSQL_DB_FIELD_COUNT, ACL_ACCESS #include "sql_base.h" // close_mysql_tables @@ -59,147 +59,30 @@ bool mysql_user_table_is_in_short_password_format= false; -static const -TABLE_FIELD_TYPE mysql_db_table_fields[MYSQL_DB_FIELD_COUNT] = { - { - { C_STRING_WITH_LEN("Host") }, - { C_STRING_WITH_LEN("char(60)") }, - {NULL, 0} - }, - { - { C_STRING_WITH_LEN("Db") }, - { C_STRING_WITH_LEN("char(64)") }, - {NULL, 0} - }, - { - { C_STRING_WITH_LEN("User") }, - { C_STRING_WITH_LEN("char(") }, - {NULL, 0} - }, - { - { C_STRING_WITH_LEN("Select_priv") }, - { C_STRING_WITH_LEN("enum('N','Y')") }, - { C_STRING_WITH_LEN("utf8") } - }, - { - { C_STRING_WITH_LEN("Insert_priv") }, - { C_STRING_WITH_LEN("enum('N','Y')") }, - { C_STRING_WITH_LEN("utf8") } - }, - { - { C_STRING_WITH_LEN("Update_priv") }, - { C_STRING_WITH_LEN("enum('N','Y')") }, - { C_STRING_WITH_LEN("utf8") } - }, - { - { C_STRING_WITH_LEN("Delete_priv") }, - { C_STRING_WITH_LEN("enum('N','Y')") }, - { C_STRING_WITH_LEN("utf8") } - }, - { - { C_STRING_WITH_LEN("Create_priv") }, - { C_STRING_WITH_LEN("enum('N','Y')") }, - { C_STRING_WITH_LEN("utf8") } - }, - { - { C_STRING_WITH_LEN("Drop_priv") }, - { C_STRING_WITH_LEN("enum('N','Y')") }, - { C_STRING_WITH_LEN("utf8") } - }, - { - { C_STRING_WITH_LEN("Grant_priv") }, - { C_STRING_WITH_LEN("enum('N','Y')") }, - { C_STRING_WITH_LEN("utf8") } - }, - { - { C_STRING_WITH_LEN("References_priv") }, - { C_STRING_WITH_LEN("enum('N','Y')") }, - { C_STRING_WITH_LEN("utf8") } - }, - { - { C_STRING_WITH_LEN("Index_priv") }, - { C_STRING_WITH_LEN("enum('N','Y')") }, - { C_STRING_WITH_LEN("utf8") } - }, - { - { C_STRING_WITH_LEN("Alter_priv") }, - { C_STRING_WITH_LEN("enum('N','Y')") }, - { C_STRING_WITH_LEN("utf8") } - }, - { - { C_STRING_WITH_LEN("Create_tmp_table_priv") }, - { C_STRING_WITH_LEN("enum('N','Y')") }, - { C_STRING_WITH_LEN("utf8") } - }, - { - { C_STRING_WITH_LEN("Lock_tables_priv") }, - { C_STRING_WITH_LEN("enum('N','Y')") }, - { C_STRING_WITH_LEN("utf8") } - }, - { - { C_STRING_WITH_LEN("Create_view_priv") }, - { C_STRING_WITH_LEN("enum('N','Y')") }, - { C_STRING_WITH_LEN("utf8") } - }, - { - { C_STRING_WITH_LEN("Show_view_priv") }, - { C_STRING_WITH_LEN("enum('N','Y')") }, - { C_STRING_WITH_LEN("utf8") } - }, - { - { C_STRING_WITH_LEN("Create_routine_priv") }, - { C_STRING_WITH_LEN("enum('N','Y')") }, - { C_STRING_WITH_LEN("utf8") } - }, - { - { C_STRING_WITH_LEN("Alter_routine_priv") }, - { C_STRING_WITH_LEN("enum('N','Y')") }, - { C_STRING_WITH_LEN("utf8") } - }, - { - { C_STRING_WITH_LEN("Execute_priv") }, - { C_STRING_WITH_LEN("enum('N','Y')") }, - { C_STRING_WITH_LEN("utf8") } - }, - { - { C_STRING_WITH_LEN("Event_priv") }, - { C_STRING_WITH_LEN("enum('N','Y')") }, - { C_STRING_WITH_LEN("utf8") } - }, - { - { C_STRING_WITH_LEN("Trigger_priv") }, - { C_STRING_WITH_LEN("enum('N','Y')") }, - { C_STRING_WITH_LEN("utf8") } - } +static LEX_CSTRING native_password_plugin_name= { + STRING_WITH_LEN("mysql_native_password") }; -const TABLE_FIELD_DEF -mysql_db_table_def= {MYSQL_DB_FIELD_COUNT, mysql_db_table_fields, 0, (uint*) 0 }; - -static LEX_STRING native_password_plugin_name= { - C_STRING_WITH_LEN("mysql_native_password") -}; - -static LEX_STRING old_password_plugin_name= { - C_STRING_WITH_LEN("mysql_old_password") +static LEX_CSTRING old_password_plugin_name= { + STRING_WITH_LEN("mysql_old_password") }; /// @todo make it configurable -LEX_STRING *default_auth_plugin_name= &native_password_plugin_name; +LEX_CSTRING *default_auth_plugin_name= &native_password_plugin_name; /* Wildcard host, matches any hostname */ -LEX_STRING host_not_specified= { C_STRING_WITH_LEN("%") }; +LEX_CSTRING host_not_specified= { STRING_WITH_LEN("%") }; /* Constants, used in the SHOW GRANTS command. Their actual string values are irrelevant, they're always compared as pointers to these string constants. */ -LEX_STRING current_user= { C_STRING_WITH_LEN("*current_user") }; -LEX_STRING current_role= { C_STRING_WITH_LEN("*current_role") }; -LEX_STRING current_user_and_current_role= { C_STRING_WITH_LEN("*current_user_and_current_role") }; +LEX_CSTRING current_user= { STRING_WITH_LEN("*current_user") }; +LEX_CSTRING current_role= { STRING_WITH_LEN("*current_role") }; +LEX_CSTRING current_user_and_current_role= { STRING_WITH_LEN("*current_user_and_current_role") }; #ifndef NO_EMBEDDED_ACCESS_CHECKS static plugin_ref old_password_plugin; @@ -241,9 +124,9 @@ class ACL_USER_BASE :public ACL_ACCESS public: static void *operator new(size_t size, MEM_ROOT *mem_root) { return (void*) alloc_root(mem_root, size); } - + static void operator delete(void *, MEM_ROOT *){} uchar flags; // field used to store various state information - LEX_STRING user; + LEX_CSTRING user; /* list to hold references to granted roles (ACL_ROLE instances) */ DYNAMIC_ARRAY role_grants; }; @@ -252,15 +135,15 @@ class ACL_USER :public ACL_USER_BASE { public: acl_host_and_ip host; - uint hostname_length; + size_t hostname_length; USER_RESOURCES user_resource; uint8 salt[SCRAMBLE_LENGTH + 1]; // scrambled password in binary form uint8 salt_len; // 0 - no password, 4 - 3.20, 8 - 4.0, 20 - 4.1.1 enum SSL_type ssl_type; const char *ssl_cipher, *x509_issuer, *x509_subject; - LEX_STRING plugin; - LEX_STRING auth_string; - LEX_STRING default_rolename; + LEX_CSTRING plugin; + LEX_CSTRING auth_string; + LEX_CSTRING default_rolename; ACL_USER *copy(MEM_ROOT *root) { @@ -337,7 +220,7 @@ class ACL_DB :public ACL_ACCESS { public: acl_host_and_ip host; - char *user,*db; + const char *user,*db; ulong initial_access; /* access bits present in the table */ }; @@ -361,8 +244,8 @@ static bool show_database_privileges(THD *, const char *, const char *, char *, size_t); static bool show_table_and_column_privileges(THD *, const char *, const char *, char *, size_t); -static int show_routine_grants(THD *, const char *, const char *, HASH *, - const char *, int, char *, int); +static int show_routine_grants(THD *, const char *, const char *, + const Sp_handler *sph, char *, int); class Grant_tables; class User_table; @@ -529,10 +412,10 @@ public: } static int store_pk(TABLE *table, - const LEX_STRING *host, - const LEX_STRING *user, - const LEX_STRING *proxied_host, - const LEX_STRING *proxied_user) + const LEX_CSTRING *host, + const LEX_CSTRING *user, + const LEX_CSTRING *proxied_host, + const LEX_CSTRING *proxied_user) { DBUG_ENTER("ACL_PROXY_USER::store_pk"); DBUG_PRINT("info", ("host=%s, user=%s, proxied_host=%s, proxied_user=%s", @@ -559,10 +442,10 @@ public: } static int store_data_record(TABLE *table, - const LEX_STRING *host, - const LEX_STRING *user, - const LEX_STRING *proxied_host, - const LEX_STRING *proxied_user, + const LEX_CSTRING *host, + const LEX_CSTRING *user, + const LEX_CSTRING *proxied_host, + const LEX_CSTRING *proxied_user, bool with_grant, const char *grantor) { @@ -615,8 +498,8 @@ struct ROLE_GRANT_PAIR : public Sql_alloc LEX_STRING hashkey; bool with_admin; - bool init(MEM_ROOT *mem, char *username, char *hostname, char *rolename, - bool with_admin_option); + bool init(MEM_ROOT *mem, const char *username, const char *hostname, + const char *rolename, bool with_admin_option); }; static uchar* acl_role_map_get_key(ROLE_GRANT_PAIR *entry, size_t *length, @@ -626,8 +509,8 @@ static uchar* acl_role_map_get_key(ROLE_GRANT_PAIR *entry, size_t *length, return (uchar*) entry->hashkey.str; } -bool ROLE_GRANT_PAIR::init(MEM_ROOT *mem, char *username, - char *hostname, char *rolename, +bool ROLE_GRANT_PAIR::init(MEM_ROOT *mem, const char *username, + const char *hostname, const char *rolename, bool with_admin_option) { size_t uname_l = safe_strlen(username); @@ -694,9 +577,9 @@ bool ROLE_GRANT_PAIR::init(MEM_ROOT *mem, char *username, #endif /* HAVE_OPENSSL && !EMBEDDED_LIBRARY */ #define NORMAL_HANDSHAKE_SIZE 6 -#define ROLE_ASSIGN_COLUMN_IDX 43 -#define DEFAULT_ROLE_COLUMN_IDX 44 -#define MAX_STATEMENT_TIME_COLUMN_IDX 45 +#define ROLE_ASSIGN_COLUMN_IDX 44 +#define DEFAULT_ROLE_COLUMN_IDX 45 +#define MAX_STATEMENT_TIME_COLUMN_IDX 46 /* various flags valid for ACL_USER */ #define IS_ROLE (1L << 0) @@ -725,6 +608,7 @@ static MEM_ROOT acl_memroot, grant_memroot; 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 HASH package_spec_priv_hash, package_body_priv_hash; static DYNAMIC_ARRAY acl_wild_hosts; static Hash_filo<acl_entry> *acl_cache; static uint grant_version=0; /* Version of priv tables. incremented by acl_load */ @@ -737,10 +621,10 @@ static void rebuild_role_grants(void); static ACL_USER *find_user_exact(const char *host, const char *user); static ACL_USER *find_user_wild(const char *host, const char *user, const char *ip= 0); static ACL_ROLE *find_acl_role(const char *user); -static ROLE_GRANT_PAIR *find_role_grant_pair(const LEX_STRING *u, const LEX_STRING *h, const LEX_STRING *r); +static ROLE_GRANT_PAIR *find_role_grant_pair(const LEX_CSTRING *u, const LEX_CSTRING *h, const LEX_CSTRING *r); static ACL_USER_BASE *find_acl_user_base(const char *user, const char *host); static bool update_user_table(THD *, const User_table &, const char *, const char *, const - char *, uint); + char *, size_t new_password_len); static bool acl_load(THD *thd, const Grant_tables& grant_tables); static inline void get_grantor(THD *thd, char* grantor); static bool add_role_user_mapping(const char *uname, const char *hname, const char *rname); @@ -755,6 +639,31 @@ static int traverse_role_graph_down(ACL_USER_BASE *, void *, int (*) (ACL_USER_BASE *, void *), int (*) (ACL_USER_BASE *, ACL_ROLE *, void *)); + +HASH *Sp_handler_procedure::get_priv_hash() const +{ + return &proc_priv_hash; +} + + +HASH *Sp_handler_function::get_priv_hash() const +{ + return &func_priv_hash; +} + + +HASH *Sp_handler_package_spec::get_priv_hash() const +{ + return &package_spec_priv_hash; +} + + +HASH *Sp_handler_package_body::get_priv_hash() const +{ + return &package_body_priv_hash; +} + + /* Enumeration of ACL/GRANT tables in the mysql database */ @@ -842,7 +751,7 @@ class Grant_table_base if (table_exists()) return 0; - my_error(ER_NO_SUCH_TABLE, MYF(0), tl.db, tl.alias); + my_error(ER_NO_SUCH_TABLE, MYF(0), tl.db.str, tl.alias.str); return 1; } @@ -996,6 +905,7 @@ class User_table: public Grant_table_base return get_YN_as_bool(is_role()); } + ulong get_access() const { ulong access= Grant_table_base::get_access(); @@ -1044,6 +954,9 @@ class User_table: public Grant_table_base if (num_fields() <= 38 && (access & SUPER_ACL)) access|= TRIGGER_ACL; + if (num_fields() <= 46 && (access & DELETE_ACL)) + access|= DELETE_HISTORY_ACL; + return access & GLOBAL_ACLS; } @@ -1056,9 +969,7 @@ class User_table: public Grant_table_base void init(enum thr_lock_type lock_type) { /* We are relying on init_one_table zeroing out the TABLE_LIST structure. */ - tl.init_one_table(C_STRING_WITH_LEN("mysql"), - C_STRING_WITH_LEN("user"), - NULL, lock_type); + tl.init_one_table(&MYSQL_SCHEMA_NAME, &MYSQL_USER_NAME, NULL, lock_type); Grant_table_base::init(lock_type, false); } @@ -1102,9 +1013,7 @@ class Db_table: public Grant_table_base void init(enum thr_lock_type lock_type) { /* We are relying on init_one_table zeroing out the TABLE_LIST structure. */ - tl.init_one_table(C_STRING_WITH_LEN("mysql"), - C_STRING_WITH_LEN("db"), - NULL, lock_type); + tl.init_one_table(&MYSQL_SCHEMA_NAME, &MYSQL_DB_NAME, NULL, lock_type); Grant_table_base::init(lock_type, false); } }; @@ -1129,9 +1038,8 @@ class Tables_priv_table: public Grant_table_base void init(enum thr_lock_type lock_type, Grant_table_base *next_table= NULL) { /* We are relying on init_one_table zeroing out the TABLE_LIST structure. */ - tl.init_one_table(C_STRING_WITH_LEN("mysql"), - C_STRING_WITH_LEN("tables_priv"), - NULL, lock_type); + LEX_CSTRING MYSQL_TABLES_PRIV_NAME={STRING_WITH_LEN("tables_priv") }; + tl.init_one_table(&MYSQL_SCHEMA_NAME, &MYSQL_TABLES_PRIV_NAME, NULL, lock_type); Grant_table_base::init(lock_type, false); } }; @@ -1155,9 +1063,8 @@ class Columns_priv_table: public Grant_table_base void init(enum thr_lock_type lock_type) { /* We are relying on init_one_table zeroing out the TABLE_LIST structure. */ - tl.init_one_table(C_STRING_WITH_LEN("mysql"), - C_STRING_WITH_LEN("columns_priv"), - NULL, lock_type); + LEX_CSTRING MYSQL_COLUMNS_PRIV_NAME={ STRING_WITH_LEN("columns_priv") }; + tl.init_one_table(&MYSQL_SCHEMA_NAME, &MYSQL_COLUMNS_PRIV_NAME, NULL, lock_type); Grant_table_base::init(lock_type, false); } }; @@ -1176,9 +1083,8 @@ class Host_table: public Grant_table_base void init(enum thr_lock_type lock_type) { /* We are relying on init_one_table zeroing out the TABLE_LIST structure. */ - tl.init_one_table(C_STRING_WITH_LEN("mysql"), - C_STRING_WITH_LEN("host"), - NULL, lock_type); + LEX_CSTRING MYSQL_HOST_NAME={STRING_WITH_LEN("host") }; + tl.init_one_table(&MYSQL_SCHEMA_NAME, &MYSQL_HOST_NAME, NULL, lock_type); Grant_table_base::init(lock_type, true); } }; @@ -1203,9 +1109,8 @@ class Procs_priv_table: public Grant_table_base void init(enum thr_lock_type lock_type) { /* We are relying on init_one_table zeroing out the TABLE_LIST structure. */ - tl.init_one_table(C_STRING_WITH_LEN("mysql"), - C_STRING_WITH_LEN("procs_priv"), - NULL, lock_type); + LEX_CSTRING MYSQL_PROCS_PRIV_NAME={STRING_WITH_LEN("procs_priv") }; + tl.init_one_table(&MYSQL_SCHEMA_NAME, &MYSQL_PROCS_PRIV_NAME, NULL, lock_type); Grant_table_base::init(lock_type, true); } }; @@ -1229,9 +1134,8 @@ class Proxies_priv_table: public Grant_table_base void init(enum thr_lock_type lock_type) { /* We are relying on init_one_table zeroing out the TABLE_LIST structure. */ - tl.init_one_table(C_STRING_WITH_LEN("mysql"), - C_STRING_WITH_LEN("proxies_priv"), - NULL, lock_type); + LEX_CSTRING MYSQL_PROXIES_PRIV_NAME={STRING_WITH_LEN("proxies_priv") }; + tl.init_one_table(&MYSQL_SCHEMA_NAME, &MYSQL_PROXIES_PRIV_NAME, NULL, lock_type); Grant_table_base::init(lock_type, true); } }; @@ -1252,9 +1156,8 @@ class Roles_mapping_table: public Grant_table_base void init(enum thr_lock_type lock_type) { /* We are relying on init_one_table zeroing out the TABLE_LIST structure. */ - tl.init_one_table(C_STRING_WITH_LEN("mysql"), - C_STRING_WITH_LEN("roles_mapping"), - NULL, lock_type); + LEX_CSTRING MYSQL_ROLES_MAPPING_NAME={STRING_WITH_LEN("roles_mapping") }; + tl.init_one_table(&MYSQL_SCHEMA_NAME, &MYSQL_ROLES_MAPPING_NAME, NULL, lock_type); Grant_table_base::init(lock_type, true); } }; @@ -1476,6 +1379,8 @@ enum enum_acl_lists COLUMN_PRIVILEGES_HASH, PROC_PRIVILEGES_HASH, FUNC_PRIVILEGES_HASH, + PACKAGE_SPEC_PRIVILEGES_HASH, + PACKAGE_BODY_PRIVILEGES_HASH, PROXY_USERS_ACL, ROLES_MAPPINGS_HASH }; @@ -1537,7 +1442,7 @@ static bool has_validation_plugins() MariaDB_PASSWORD_VALIDATION_PLUGIN, NULL); } -struct validation_data { LEX_STRING *user, *password; }; +struct validation_data { LEX_CSTRING *user, *password; }; static my_bool do_validate(THD *, plugin_ref plugin, void *arg) { @@ -1554,7 +1459,7 @@ static bool validate_password(LEX_USER *user, THD *thd) { struct validation_data data= { &user->user, user->pwtext.str ? &user->pwtext : - const_cast<LEX_STRING *>(&empty_lex_str) }; + const_cast<LEX_CSTRING *>(&empty_clex_str) }; if (plugin_foreach(NULL, do_validate, MariaDB_PASSWORD_VALIDATION_PLUGIN, &data)) { @@ -1587,7 +1492,7 @@ static bool validate_password(LEX_USER *user, THD *thd) */ static void -set_user_salt(ACL_USER *acl_user, const char *password, uint password_len) +set_user_salt(ACL_USER *acl_user, const char *password, size_t password_len) { if (password_len == SCRAMBLED_PASSWORD_CHAR_LENGTH) { @@ -1603,7 +1508,7 @@ set_user_salt(ACL_USER *acl_user, const char *password, uint password_len) acl_user->salt_len= 0; } -static char *fix_plugin_ptr(char *name) +static const char *fix_plugin_ptr(const char *name) { if (my_strcasecmp(system_charset_info, name, native_password_plugin_name.str) == 0) @@ -1631,12 +1536,10 @@ static char *fix_plugin_ptr(char *name) */ static bool fix_user_plugin_ptr(ACL_USER *user) { - if (my_strcasecmp(system_charset_info, user->plugin.str, - native_password_plugin_name.str) == 0) + if (lex_string_eq(&user->plugin, &native_password_plugin_name)) user->plugin= native_password_plugin_name; else - if (my_strcasecmp(system_charset_info, user->plugin.str, - old_password_plugin_name.str) == 0) + if (lex_string_eq(&user->plugin, &old_password_plugin_name)) user->plugin= old_password_plugin_name; else return true; @@ -1675,12 +1578,10 @@ static bool fix_lex_user(THD *thd, LEX_USER *user) DBUG_ASSERT(user->plugin.length || !user->auth.length); DBUG_ASSERT(!(user->plugin.length && (user->pwtext.length || user->pwhash.length))); - if (my_strcasecmp(system_charset_info, user->plugin.str, - native_password_plugin_name.str) == 0) + if (lex_string_eq(&user->plugin, &native_password_plugin_name)) check_length= SCRAMBLED_PASSWORD_CHAR_LENGTH; else - if (my_strcasecmp(system_charset_info, user->plugin.str, - old_password_plugin_name.str) == 0) + if (lex_string_eq(&user->plugin, &old_password_plugin_name)) check_length= SCRAMBLED_PASSWORD_CHAR_LENGTH_323; else if (user->plugin.length) @@ -1694,8 +1595,8 @@ static bool fix_lex_user(THD *thd, LEX_USER *user) if (user->plugin.length) { user->pwhash= user->auth; - user->plugin= empty_lex_str; - user->auth= empty_lex_str; + user->plugin= empty_clex_str; + user->auth= empty_clex_str; } if (user->pwhash.length && user->pwhash.length != check_length) @@ -1813,7 +1714,7 @@ bool acl_init(bool dont_read_acl_tables) Choose from either native or old password plugins when assigning a password */ -static bool set_user_plugin (ACL_USER *user, int password_len) +static bool set_user_plugin (ACL_USER *user, size_t password_len) { switch (password_len) { @@ -1863,12 +1764,12 @@ static bool acl_load(THD *thd, const Grant_tables& tables) grant_version++; /* Privileges updated */ const Host_table& host_table= tables.host_table(); - init_sql_alloc(&acl_memroot, ACL_ALLOC_BLOCK_SIZE, 0, MYF(0)); + init_sql_alloc(&acl_memroot, "ACL", ACL_ALLOC_BLOCK_SIZE, 0, MYF(0)); if (host_table.table_exists()) // "host" table may not exist (e.g. in MySQL 5.6.7+) { if (host_table.init_read_record(&read_record_info, thd)) DBUG_RETURN(true); - while (!(read_record_info.read_record(&read_record_info))) + while (!(read_record_info.read_record())) { ACL_HOST host; update_hostname(&host.host, get_field(&acl_memroot, host_table.host())); @@ -1978,7 +1879,7 @@ static bool acl_load(THD *thd, const Grant_tables& tables) } allow_all_hosts=0; - while (!(read_record_info.read_record(&read_record_info))) + while (!(read_record_info.read_record())) { ACL_USER user; bool is_role= FALSE; @@ -2013,7 +1914,7 @@ static bool acl_load(THD *thd, const Grant_tables& tables) char *password= const_cast<char*>(""); if (user_table.password()) password= get_field(&acl_memroot, user_table.password()); - uint password_len= safe_strlen(password); + size_t password_len= safe_strlen(password); user.auth_string.str= safe_str(password); user.auth_string.length= password_len; set_user_salt(&user, password, password_len); @@ -2022,7 +1923,7 @@ static bool acl_load(THD *thd, const Grant_tables& tables) continue; { - user.access= user_table.get_access() & GLOBAL_ACLS; + user.access= user_table.get_access(); user.sort= get_sort(2, user.host.hostname, user.user.str); user.hostname_length= safe_strlen(user.host.hostname); user.user_resource.user_conn= 0; @@ -2161,15 +2062,16 @@ static bool acl_load(THD *thd, const Grant_tables& tables) const Db_table& db_table= tables.db_table(); if (db_table.init_read_record(&read_record_info, thd)) DBUG_RETURN(TRUE); - while (!(read_record_info.read_record(&read_record_info))) + while (!(read_record_info.read_record())) { ACL_DB db; + char *db_name; db.user=get_field(&acl_memroot, db_table.user()); const char *hostname= get_field(&acl_memroot, db_table.host()); if (!hostname && find_acl_role(db.user)) hostname= ""; update_hostname(&db.host, hostname); - db.db=get_field(&acl_memroot, db_table.db()); + db.db= db_name= get_field(&acl_memroot, db_table.db()); if (!db.db) { sql_print_warning("Found an entry in the 'db' table with empty database name; Skipped"); @@ -2197,8 +2099,8 @@ static bool acl_load(THD *thd, const Grant_tables& tables) sql_print_warning(ER_THD(thd, ER_WRONG_DB_NAME), db.db); continue; } - my_casedn_str(files_charset_info, db.db); - if (strcmp(db.db, tmp_name) != 0) + my_casedn_str(files_charset_info, db_name); + if (strcmp(db_name, tmp_name) != 0) { sql_print_warning("'db' entry '%s %s@%s' had database in mixed " "case that has been forced to lowercase because " @@ -2226,7 +2128,7 @@ static bool acl_load(THD *thd, const Grant_tables& tables) { if (proxies_priv_table.init_read_record(&read_record_info, thd)) DBUG_RETURN(TRUE); - while (!(read_record_info.read_record(&read_record_info))) + while (!(read_record_info.read_record())) { ACL_PROXY_USER proxy; proxy.init(proxies_priv_table, &acl_memroot); @@ -2254,8 +2156,8 @@ static bool acl_load(THD *thd, const Grant_tables& tables) DBUG_RETURN(TRUE); MEM_ROOT temp_root; - init_alloc_root(&temp_root, ACL_ALLOC_BLOCK_SIZE, 0, MYF(0)); - while (!(read_record_info.read_record(&read_record_info))) + init_alloc_root(&temp_root, "ACL_tmp", ACL_ALLOC_BLOCK_SIZE, 0, MYF(0)); + while (!(read_record_info.read_record())) { char *hostname= safe_str(get_field(&temp_root, roles_mapping_table.host())); char *username= safe_str(get_field(&temp_root, roles_mapping_table.user())); @@ -2349,7 +2251,7 @@ bool acl_reload(THD *thd) To avoid deadlocks we should obtain table locks before obtaining acl_cache->lock mutex. */ - if ((result= tables.open_and_lock(thd))) + if (unlikely((result= tables.open_and_lock(thd)))) { DBUG_ASSERT(result <= 0); /* @@ -2522,8 +2424,8 @@ static int acl_compare(ACL_ACCESS *a,ACL_ACCESS *b) TRUE Error */ -bool acl_getroot(Security_context *sctx, char *user, char *host, - char *ip, char *db) +bool acl_getroot(Security_context *sctx, const char *user, const char *host, + const char *ip, const char *db) { int res= 1; uint i; @@ -2767,20 +2669,20 @@ end: } -int acl_check_setrole(THD *thd, char *rolename, ulonglong *access) +int acl_check_setrole(THD *thd, const char *rolename, ulonglong *access) { return check_user_can_set_role(thd, thd->security_ctx->priv_user, thd->security_ctx->host, thd->security_ctx->ip, rolename, access); } -int acl_setrole(THD *thd, char *rolename, ulonglong access) +int acl_setrole(THD *thd, const char *rolename, ulonglong access) { /* merge the privileges */ Security_context *sctx= thd->security_ctx; sctx->master_access= static_cast<ulong>(access); - if (thd->db) - sctx->db_access= acl_get(sctx->host, sctx->ip, sctx->user, thd->db, FALSE); + if (thd->db.str) + sctx->db_access= acl_get(sctx->host, sctx->ip, sctx->user, thd->db.str, FALSE); if (!strcasecmp(rolename, "NONE")) { @@ -2788,8 +2690,8 @@ int acl_setrole(THD *thd, char *rolename, ulonglong access) } else { - if (thd->db) - sctx->db_access|= acl_get("", "", rolename, thd->db, FALSE); + if (thd->db.str) + sctx->db_access|= acl_get("", "", rolename, thd->db.str, FALSE); /* mark the current role */ strmake_buf(thd->security_ctx->priv_role, rolename); } @@ -2813,15 +2715,15 @@ static void acl_update_role(const char *rolename, ulong privileges) static void acl_update_user(const char *user, const char *host, - const char *password, uint password_len, + const char *password, size_t password_len, enum SSL_type ssl_type, const char *ssl_cipher, const char *x509_issuer, const char *x509_subject, USER_RESOURCES *mqh, ulong privileges, - const LEX_STRING *plugin, - const LEX_STRING *auth) + const LEX_CSTRING *plugin, + const LEX_CSTRING *auth) { mysql_mutex_assert_owner(&acl_cache->lock); @@ -2891,15 +2793,15 @@ static void acl_insert_role(const char *rolename, ulong privileges) static void acl_insert_user(const char *user, const char *host, - const char *password, uint password_len, + const char *password, size_t password_len, enum SSL_type ssl_type, const char *ssl_cipher, const char *x509_issuer, const char *x509_subject, USER_RESOURCES *mqh, ulong privileges, - const LEX_STRING *plugin, - const LEX_STRING *auth) + const LEX_CSTRING *plugin, + const LEX_CSTRING *auth) { ACL_USER acl_user; @@ -3272,7 +3174,7 @@ static void remove_ptr_from_dynarray(DYNAMIC_ARRAY *array, void *ptr) { DBUG_ASSERT(!found); delete_dynamic_element(array, i); - IF_DBUG(found= true, break); + IF_DBUG_ASSERT(found= true, break); } } DBUG_ASSERT(found); @@ -3506,6 +3408,7 @@ bool change_password(THD *thd, LEX_USER *user) acl_user->auth_string.str= strmake_root(&acl_memroot, user->pwhash.str, user->pwhash.length); acl_user->auth_string.length= user->pwhash.length; set_user_salt(acl_user, user->pwhash.str, user->pwhash.length); + set_user_plugin(acl_user, user->pwhash.length); } else @@ -3530,7 +3433,7 @@ bool change_password(THD *thd, LEX_USER *user) DBUG_ASSERT(query_length); thd->clear_error(); result= thd->binlog_query(THD::STMT_QUERY_TYPE, buff, query_length, - FALSE, FALSE, FALSE, 0); + FALSE, FALSE, FALSE, 0) > 0; } end: close_mysql_tables(thd); @@ -3668,7 +3571,8 @@ int acl_set_default_role(THD *thd, const char *host, const char *user, user_table.default_role()->store(acl_user->default_rolename.str, acl_user->default_rolename.length, system_charset_info); - if ((error=table->file->ha_update_row(table->record[1],table->record[0])) && + if (unlikely(error= table->file->ha_update_row(table->record[1], + table->record[0])) && error != HA_ERR_RECORD_IS_THE_SAME) { mysql_mutex_unlock(&acl_cache->lock); @@ -3684,7 +3588,7 @@ int acl_set_default_role(THD *thd, const char *host, const char *user, DBUG_ASSERT(query_length); thd->clear_error(); result= thd->binlog_query(THD::STMT_QUERY_TYPE, buff, query_length, - FALSE, FALSE, FALSE, 0); + FALSE, FALSE, FALSE, 0) > 0; } end: close_mysql_tables(thd); @@ -3936,8 +3840,7 @@ bool hostname_requires_resolving(const char *hostname) void set_authentication_plugin_from_password(const User_table& user_table, - const char* password, - uint password_length) + const char* password, size_t password_length) { if (password_length == SCRAMBLED_PASSWORD_CHAR_LENGTH || password_length == 0) @@ -3972,7 +3875,7 @@ void set_authentication_plugin_from_password(const User_table& user_table, static bool update_user_table(THD *thd, const User_table& user_table, const char *host, const char *user, - const char *new_password, uint new_password_len) + const char *new_password, size_t new_password_len) { char user_key[MAX_KEY_LENGTH]; int error; @@ -4006,7 +3909,8 @@ static bool update_user_table(THD *thd, const User_table& user_table, user_table.password()->store(new_password, new_password_len, system_charset_info); - if ((error=table->file->ha_update_row(table->record[1],table->record[0])) && + if (unlikely(error= table->file->ha_update_row(table->record[1], + table->record[0])) && error != HA_ERR_RECORD_IS_THE_SAME) { table->file->print_error(error,MYF(0)); /* purecov: deadcode */ @@ -4033,14 +3937,13 @@ static bool test_if_create_new_users(THD *thd) { TABLE_LIST tl; ulong db_access; - tl.init_one_table(C_STRING_WITH_LEN("mysql"), - C_STRING_WITH_LEN("user"), "user", TL_WRITE); + tl.init_one_table(&MYSQL_SCHEMA_NAME, &MYSQL_USER_NAME, NULL, TL_WRITE); create_new_users= 1; db_access=acl_get(sctx->host, sctx->ip, - sctx->priv_user, tl.db, 0); + sctx->priv_user, tl.db.str, 0); if (sctx->priv_role[0]) - db_access|= acl_get("", "", sctx->priv_role, tl.db, 0); + db_access|= acl_get("", "", sctx->priv_role, tl.db.str, 0); if (!(db_access & INSERT_ACL)) { if (check_grant(thd, INSERT_ACL, &tl, FALSE, UINT_MAX, TRUE)) @@ -4082,7 +3985,7 @@ static int replace_user_table(THD *thd, const User_table &user_table, } } else - combo.pwhash= empty_lex_str; + combo.pwhash= empty_clex_str; /* if the user table is not up to date, we can't handle role updates */ if (!user_table.is_role() && handle_as_role) @@ -4301,8 +4204,8 @@ static int replace_user_table(THD *thd, const User_table &user_table, */ if (cmp_record(table, record[1])) { - if ((error= - table->file->ha_update_row(table->record[1],table->record[0])) && + if (unlikely(error= table->file->ha_update_row(table->record[1], + table->record[0])) && error != HA_ERR_RECORD_IS_THE_SAME) { // This should never happen table->file->print_error(error,MYF(0)); /* purecov: deadcode */ @@ -4313,8 +4216,9 @@ static int replace_user_table(THD *thd, const User_table &user_table, error= 0; } } - else if ((error=table->file->ha_write_row(table->record[0]))) // insert - { // This should never happen + else if (unlikely(error=table->file->ha_write_row(table->record[0]))) + { + // This should never happen if (table->file->is_fatal_error(error, HA_CHECK_DUP)) { table->file->print_error(error,MYF(0)); /* purecov: deadcode */ @@ -4325,7 +4229,7 @@ static int replace_user_table(THD *thd, const User_table &user_table, error=0; // Privileges granted / revoked end: - if (!error) + if (likely(!error)) { acl_cache->clear(1); // Clear privilege cache if (old_row_exists) @@ -4439,18 +4343,19 @@ static int replace_db_table(TABLE *table, const char *db, /* update old existing row */ if (rights) { - if ((error= table->file->ha_update_row(table->record[1], - table->record[0])) && + if (unlikely((error= table->file->ha_update_row(table->record[1], + table->record[0]))) && error != HA_ERR_RECORD_IS_THE_SAME) goto table_error; /* purecov: deadcode */ } else /* must have been a revoke of all privileges */ { - if ((error= table->file->ha_delete_row(table->record[1]))) + if (unlikely((error= table->file->ha_delete_row(table->record[1])))) goto table_error; /* purecov: deadcode */ } } - else if (rights && (error= table->file->ha_write_row(table->record[0]))) + else if (rights && + (unlikely(error= table->file->ha_write_row(table->record[0])))) { if (table->file->is_fatal_error(error, HA_CHECK_DUP_KEY)) goto table_error; /* purecov: deadcode */ @@ -4499,8 +4404,8 @@ abort: @param revoke_grant true for REVOKE, false for GRANT */ static int -replace_roles_mapping_table(TABLE *table, LEX_STRING *user, LEX_STRING *host, - LEX_STRING *role, bool with_admin, +replace_roles_mapping_table(TABLE *table, LEX_CSTRING *user, LEX_CSTRING *host, + LEX_CSTRING *role, bool with_admin, ROLE_GRANT_PAIR *existing, bool revoke_grant) { DBUG_ENTER("replace_roles_mapping_table"); @@ -4527,7 +4432,7 @@ replace_roles_mapping_table(TABLE *table, LEX_STRING *user, LEX_STRING *host, } if (revoke_grant && !with_admin) { - if ((error= table->file->ha_delete_row(table->record[1]))) + if (unlikely((error= table->file->ha_delete_row(table->record[1])))) { DBUG_PRINT("info", ("error deleting row '%s' '%s' '%s'", host->str, user->str, role->str)); @@ -4538,7 +4443,8 @@ replace_roles_mapping_table(TABLE *table, LEX_STRING *user, LEX_STRING *host, { table->field[3]->store(!revoke_grant + 1); - if ((error= table->file->ha_update_row(table->record[1], table->record[0]))) + if (unlikely((error= table->file->ha_update_row(table->record[1], + table->record[0])))) { DBUG_PRINT("info", ("error updating row '%s' '%s' '%s'", host->str, user->str, role->str)); @@ -4550,7 +4456,7 @@ replace_roles_mapping_table(TABLE *table, LEX_STRING *user, LEX_STRING *host, table->field[3]->store(with_admin + 1); - if ((error= table->file->ha_write_row(table->record[0]))) + if (unlikely((error= table->file->ha_write_row(table->record[0])))) { DBUG_PRINT("info", ("error inserting row '%s' '%s' '%s'", host->str, user->str, role->str)); @@ -4581,7 +4487,7 @@ table_error: @param revoke_grant true for REVOKE, false for GRANT */ static int -update_role_mapping(LEX_STRING *user, LEX_STRING *host, LEX_STRING *role, +update_role_mapping(LEX_CSTRING *user, LEX_CSTRING *host, LEX_CSTRING *role, bool with_admin, ROLE_GRANT_PAIR *existing, bool revoke_grant) { if (revoke_grant) @@ -4681,7 +4587,7 @@ replace_proxies_priv_table(THD *thd, TABLE *table, const LEX_USER *user, get_grantor(thd, grantor); - if ((error= table->file->ha_index_init(0, 1))) + if (unlikely((error= table->file->ha_index_init(0, 1)))) { table->file->print_error(error, MYF(0)); DBUG_PRINT("info", ("ha_index_init error")); @@ -4718,18 +4624,18 @@ replace_proxies_priv_table(THD *thd, TABLE *table, const LEX_USER *user, /* update old existing row */ if (!revoke_grant) { - if ((error= table->file->ha_update_row(table->record[1], - table->record[0])) && + if (unlikely(error= table->file->ha_update_row(table->record[1], + table->record[0])) && error != HA_ERR_RECORD_IS_THE_SAME) goto table_error; /* purecov: inspected */ } else { - if ((error= table->file->ha_delete_row(table->record[1]))) + if (unlikely((error= table->file->ha_delete_row(table->record[1])))) goto table_error; /* purecov: inspected */ } } - else if ((error= table->file->ha_write_row(table->record[0]))) + else if (unlikely((error= table->file->ha_write_row(table->record[0])))) { DBUG_PRINT("info", ("error inserting the row")); if (table->file->is_fatal_error(error, HA_CHECK_DUP_KEY)) @@ -5070,10 +4976,11 @@ static GRANT_NAME *name_hash_search(HASH *name_hash, static GRANT_NAME * routine_hash_search(const char *host, const char *ip, const char *db, - const char *user, const char *tname, bool proc, bool exact) + const char *user, const char *tname, const Sp_handler *sph, + bool exact) { return (GRANT_TABLE*) - name_hash_search(proc ? &proc_priv_hash : &func_priv_hash, + name_hash_search(sph->get_priv_hash(), host, ip, db, user, tname, exact, TRUE); } @@ -5088,7 +4995,7 @@ table_hash_search(const char *host, const char *ip, const char *db, static GRANT_COLUMN * -column_hash_search(GRANT_TABLE *t, const char *cname, uint length) +column_hash_search(GRANT_TABLE *t, const char *cname, size_t length) { if (!my_hash_inited(&t->hash_columns)) return (GRANT_COLUMN*) 0; @@ -5131,7 +5038,7 @@ static int replace_column_table(GRANT_TABLE *g_t, List_iterator <LEX_COLUMN> iter(columns); class LEX_COLUMN *column; int error= table->file->ha_index_init(0, 1); - if (error) + if (unlikely(error)) { table->file->print_error(error, MYF(0)); DBUG_RETURN(-1); @@ -5191,7 +5098,7 @@ static int replace_column_table(GRANT_TABLE *g_t, error=table->file->ha_update_row(table->record[1],table->record[0]); else error=table->file->ha_delete_row(table->record[1]); - if (error && error != HA_ERR_RECORD_IS_THE_SAME) + if (unlikely(error) && error != HA_ERR_RECORD_IS_THE_SAME) { table->file->print_error(error,MYF(0)); /* purecov: inspected */ result= -1; /* purecov: inspected */ @@ -5207,7 +5114,7 @@ static int replace_column_table(GRANT_TABLE *g_t, else // new grant { GRANT_COLUMN *grant_column; - if ((error=table->file->ha_write_row(table->record[0]))) + if (unlikely((error=table->file->ha_write_row(table->record[0])))) { table->file->print_error(error,MYF(0)); /* purecov: inspected */ result= -1; /* purecov: inspected */ @@ -5262,8 +5169,9 @@ static int replace_column_table(GRANT_TABLE *g_t, if (privileges) { int tmp_error; - if ((tmp_error=table->file->ha_update_row(table->record[1], - table->record[0])) && + if (unlikely(tmp_error= + table->file->ha_update_row(table->record[1], + table->record[0])) && tmp_error != HA_ERR_RECORD_IS_THE_SAME) { /* purecov: deadcode */ table->file->print_error(tmp_error,MYF(0)); /* purecov: deadcode */ @@ -5279,7 +5187,8 @@ static int replace_column_table(GRANT_TABLE *g_t, else { int tmp_error; - if ((tmp_error = table->file->ha_delete_row(table->record[1]))) + if (unlikely((tmp_error= + table->file->ha_delete_row(table->record[1])))) { /* purecov: deadcode */ table->file->print_error(tmp_error,MYF(0)); /* purecov: deadcode */ result= -1; /* purecov: deadcode */ @@ -5405,18 +5314,18 @@ static int replace_table_table(THD *thd, GRANT_TABLE *grant_table, { if (store_table_rights || store_col_rights) { - if ((error=table->file->ha_update_row(table->record[1], - table->record[0])) && + if (unlikely(error=table->file->ha_update_row(table->record[1], + table->record[0])) && error != HA_ERR_RECORD_IS_THE_SAME) goto table_error; /* purecov: deadcode */ } - else if ((error = table->file->ha_delete_row(table->record[1]))) + else if (unlikely((error = table->file->ha_delete_row(table->record[1])))) goto table_error; /* purecov: deadcode */ } else { error=table->file->ha_write_row(table->record[0]); - if (table->file->is_fatal_error(error, HA_CHECK_DUP_KEY)) + if (unlikely(table->file->is_fatal_error(error, HA_CHECK_DUP_KEY))) goto table_error; /* purecov: deadcode */ } @@ -5448,13 +5357,14 @@ table_error: static int replace_routine_table(THD *thd, GRANT_NAME *grant_name, TABLE *table, const LEX_USER &combo, const char *db, const char *routine_name, - bool is_proc, ulong rights, bool revoke_grant) + const Sp_handler *sph, + ulong rights, bool revoke_grant) { char grantor[USER_HOST_BUFF_SIZE]; int old_row_exists= 1; int error=0; ulong store_proc_rights; - HASH *hash= is_proc ? &proc_priv_hash : &func_priv_hash; + HASH *hash= sph->get_priv_hash(); DBUG_ENTER("replace_routine_table"); if (revoke_grant && !grant_name->init_privs) // only inherited role privs @@ -5478,9 +5388,7 @@ static int replace_routine_table(THD *thd, GRANT_NAME *grant_name, table->field[2]->store(combo.user.str,combo.user.length, &my_charset_latin1); table->field[3]->store(routine_name,(uint) strlen(routine_name), &my_charset_latin1); - table->field[4]->store((longlong)(is_proc ? - TYPE_ENUM_PROCEDURE : TYPE_ENUM_FUNCTION), - TRUE); + table->field[4]->store((longlong) sph->type(), true); store_record(table,record[1]); // store at pos 1 if (table->file->ha_index_read_idx_map(table->record[0], 0, @@ -5532,18 +5440,18 @@ static int replace_routine_table(THD *thd, GRANT_NAME *grant_name, { if (store_proc_rights) { - if ((error=table->file->ha_update_row(table->record[1], - table->record[0])) && - error != HA_ERR_RECORD_IS_THE_SAME) + if (unlikely(error=table->file->ha_update_row(table->record[1], + table->record[0])) && + error != HA_ERR_RECORD_IS_THE_SAME) goto table_error; } - else if ((error= table->file->ha_delete_row(table->record[1]))) + else if (unlikely((error= table->file->ha_delete_row(table->record[1])))) goto table_error; } else { error=table->file->ha_write_row(table->record[0]); - if (table->file->is_fatal_error(error, HA_CHECK_DUP_KEY)) + if (unlikely(table->file->is_fatal_error(error, HA_CHECK_DUP_KEY))) goto table_error; } @@ -5596,10 +5504,34 @@ table_error: ******************************************************************/ struct PRIVS_TO_MERGE { - enum what { ALL, GLOBAL, DB, TABLE_COLUMN, PROC, FUNC } what; + enum what + { + ALL, GLOBAL, DB, TABLE_COLUMN, PROC, FUNC, PACKAGE_SPEC, PACKAGE_BODY + } what; const char *db, *name; }; + +static enum PRIVS_TO_MERGE::what sp_privs_to_merge(stored_procedure_type type) +{ + switch (type) { + case TYPE_ENUM_FUNCTION: + return PRIVS_TO_MERGE::FUNC; + case TYPE_ENUM_PROCEDURE: + return PRIVS_TO_MERGE::PROC; + case TYPE_ENUM_PACKAGE: + return PRIVS_TO_MERGE::PACKAGE_SPEC; + case TYPE_ENUM_PACKAGE_BODY: + return PRIVS_TO_MERGE::PACKAGE_BODY; + case TYPE_ENUM_TRIGGER: + case TYPE_ENUM_PROXY: + break; + } + DBUG_ASSERT(0); + return PRIVS_TO_MERGE::PROC; +} + + static int init_role_for_merging(ACL_ROLE *role, void *context) { role->counter= 0; @@ -5913,7 +5845,7 @@ static int db_name_sort(const int *db1, const int *db2) /** update ACL_DB for given database and a given role with merged privileges - @param merged ACL_DB of the role in question (or NULL if it wasn't found) + @param merged ACL_DB of the role in question (or -1 if it wasn't found) @param first first ACL_DB in an array for the database in question @param access new privileges for the given role on the gived database @param role the name of the given role @@ -5923,7 +5855,8 @@ static int db_name_sort(const int *db1, const int *db2) 2 - ACL_DB was added 4 - ACL_DB was deleted */ -static int update_role_db(int merged, int first, ulong access, char *role) +static int update_role_db(int merged, int first, ulong access, + const char *role) { if (first < 0) return 0; @@ -6141,8 +6074,8 @@ static int update_role_columns(GRANT_TABLE *merged, 4 - GRANT_TABLE was deleted */ static int update_role_table_columns(GRANT_TABLE *merged, - GRANT_TABLE **first, GRANT_TABLE **last, - ulong privs, ulong cols, char *role) + GRANT_TABLE **first, GRANT_TABLE **last, + ulong privs, ulong cols, const char *role) { if (!first) return 0; @@ -6271,7 +6204,7 @@ static int routine_name_sort(GRANT_NAME * const *r1, GRANT_NAME * const *r2) 4 - GRANT_NAME was deleted */ static int update_role_routines(GRANT_NAME *merged, GRANT_NAME **first, - ulong privs, char *role, HASH *hash) + ulong privs, const char *role, HASH *hash) { if (!first) return 0; @@ -6408,7 +6341,14 @@ static int merge_role_privileges(ACL_ROLE *role __attribute__((unused)), if (all || data->what == PRIVS_TO_MERGE::FUNC) changed|= merge_role_routine_grant_privileges(grantee, data->db, data->name, &role_hash, &func_priv_hash); - + if (all || data->what == PRIVS_TO_MERGE::PACKAGE_SPEC) + changed|= merge_role_routine_grant_privileges(grantee, + data->db, data->name, &role_hash, + &package_spec_priv_hash); + if (all || data->what == PRIVS_TO_MERGE::PACKAGE_BODY) + changed|= merge_role_routine_grant_privileges(grantee, + data->db, data->name, &role_hash, + &package_body_priv_hash); return !changed; // don't recurse into the subgraph if privs didn't change } @@ -6493,7 +6433,7 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list, List_iterator <LEX_USER> str_list (user_list); LEX_USER *Str, *tmp_Str; bool create_new_users=0; - char *db_name, *table_name; + const char *db_name, *table_name; DBUG_ENTER("mysql_table_grant"); if (rights & ~TABLE_ACLS) @@ -6523,13 +6463,13 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list, column->column.ptr(), NULL, NULL, NULL, TRUE, FALSE, &unused_field_idx, FALSE, &dummy); - if (f == (Field*)0) + if (unlikely(f == (Field*)0)) { my_error(ER_BAD_FIELD_ERROR, MYF(0), - column->column.c_ptr(), table_list->alias); + column->column.c_ptr(), table_list->alias.str); DBUG_RETURN(TRUE); } - if (f == (Field *)-1) + if (unlikely(f == (Field *)-1)) DBUG_RETURN(TRUE); column_priv|= column->rights; } @@ -6539,9 +6479,10 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list, { if (!(rights & CREATE_ACL)) { - if (!ha_table_exists(thd, table_list->db, table_list->table_name, 0)) + if (!ha_table_exists(thd, &table_list->db, &table_list->table_name)) { - my_error(ER_NO_SUCH_TABLE, MYF(0), table_list->db, table_list->alias); + my_error(ER_NO_SUCH_TABLE, MYF(0), table_list->db.str, + table_list->alias.str); DBUG_RETURN(TRUE); } } @@ -6552,7 +6493,7 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list, table_list->grant.want_privilege); my_error(ER_TABLEACCESS_DENIED_ERROR, MYF(0), command, thd->security_ctx->priv_user, - thd->security_ctx->host_or_ip, table_list->alias); + thd->security_ctx->host_or_ip, table_list->alias.str); DBUG_RETURN(-1); } } @@ -6611,7 +6552,7 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list, 0, revoke_grant, create_new_users, MY_TEST(thd->variables.sql_mode & MODE_NO_AUTO_CREATE_USER)); - if (error) + if (unlikely(error)) { result= TRUE; // Remember error continue; // Add next user @@ -6628,7 +6569,7 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list, if (revoke_grant) { my_error(ER_NONEXISTING_TABLE_GRANT, MYF(0), - Str->user.str, Str->host.str, table_list->table_name); + Str->user.str, Str->host.str, table_list->table_name.str); result= TRUE; continue; } @@ -6726,7 +6667,7 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list, @param thd Thread handle @param table_list List of routines to give grant - @param is_proc Is this a list of procedures? + @param sph SP handler @param user_list List of users to give grant @param rights Table level grant @param revoke_grant Is this is a REVOKE command? @@ -6736,7 +6677,8 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list, @retval TRUE An error occurred. */ -bool mysql_routine_grant(THD *thd, TABLE_LIST *table_list, bool is_proc, +bool mysql_routine_grant(THD *thd, TABLE_LIST *table_list, + const Sp_handler *sph, List <LEX_USER> &user_list, ulong rights, bool revoke_grant, bool write_to_binlog) { @@ -6744,7 +6686,7 @@ bool mysql_routine_grant(THD *thd, TABLE_LIST *table_list, bool is_proc, LEX_USER *Str, *tmp_Str; bool create_new_users= 0; int result; - char *db_name, *table_name; + const char *db_name, *table_name; DBUG_ENTER("mysql_routine_grant"); if (rights & ~PROC_ACLS) @@ -6757,7 +6699,7 @@ bool mysql_routine_grant(THD *thd, TABLE_LIST *table_list, bool is_proc, if (!revoke_grant) { - if (sp_exist_routines(thd, table_list, is_proc)) + if (sph->sp_exist_routines(thd, table_list)) DBUG_RETURN(TRUE); } @@ -6795,10 +6737,10 @@ bool mysql_routine_grant(THD *thd, TABLE_LIST *table_list, bool is_proc, continue; } - db_name= table_list->db; - table_name= table_list->table_name; + db_name= table_list->db.str; + table_name= table_list->table_name.str; grant_name= routine_hash_search(Str->host.str, NullS, db_name, - Str->user.str, table_name, is_proc, 1); + Str->user.str, table_name, sph, 1); if (!grant_name || !grant_name->init_privs) { if (revoke_grant) @@ -6812,8 +6754,7 @@ bool mysql_routine_grant(THD *thd, TABLE_LIST *table_list, bool is_proc, Str->user.str, table_name, rights, TRUE); if (!grant_name || - my_hash_insert(is_proc ? - &proc_priv_hash : &func_priv_hash,(uchar*) grant_name)) + my_hash_insert(sph->get_priv_hash(), (uchar*) grant_name)) { result= TRUE; continue; @@ -6824,7 +6765,7 @@ bool mysql_routine_grant(THD *thd, TABLE_LIST *table_list, bool is_proc, instead of TABLE directly. */ if (tables.procs_priv_table().no_such_table() || replace_routine_table(thd, grant_name, tables.procs_priv_table().table(), - *Str, db_name, table_name, is_proc, rights, + *Str, db_name, table_name, sph, rights, revoke_grant) != 0) { result= TRUE; @@ -6832,7 +6773,7 @@ bool mysql_routine_grant(THD *thd, TABLE_LIST *table_list, bool is_proc, } if (Str->is_role()) propagate_role_grants(find_acl_role(Str->user.str), - is_proc ? PRIVS_TO_MERGE::PROC : PRIVS_TO_MERGE::FUNC, + sp_privs_to_merge(sph->type()), db_name, table_name); } thd->mem_root= old_root; @@ -6854,7 +6795,7 @@ bool mysql_routine_grant(THD *thd, TABLE_LIST *table_list, bool is_proc, 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) + const LEX_CSTRING *u, const LEX_CSTRING *h) { if (str->length()) str->append(','); @@ -6897,11 +6838,11 @@ static int can_grant_role_callback(ACL_USER_BASE *grantee, return 0; // keep searching if (grantee->flags & IS_ROLE) - pair= find_role_grant_pair(&grantee->user, &empty_lex_str, &role->user); + pair= find_role_grant_pair(&grantee->user, &empty_clex_str, &role->user); else { ACL_USER *user= (ACL_USER *)grantee; - LEX_STRING host= { user->host.hostname, user->hostname_length }; + LEX_CSTRING host= { user->host.hostname, user->hostname_length }; pair= find_role_grant_pair(&user->user, &host, &role->user); } if (!pair->with_admin) @@ -6946,9 +6887,9 @@ bool mysql_grant_role(THD *thd, List <LEX_USER> &list, bool revoke) bool create_new_user, no_auto_create_user; String wrong_users; LEX_USER *user, *granted_role; - LEX_STRING rolename; - LEX_STRING username; - LEX_STRING hostname; + LEX_CSTRING rolename; + LEX_CSTRING username; + LEX_CSTRING hostname; ACL_ROLE *role, *role_as_user; List_iterator <LEX_USER> user_list(list); @@ -7002,9 +6943,9 @@ bool mysql_grant_role(THD *thd, List <LEX_USER> &list, bool revoke) } if (!(role_as_user= find_acl_role(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); + LEX_CSTRING ls= { thd->security_ctx->priv_role, + strlen(thd->security_ctx->priv_role) }; + append_user(thd, &wrong_users, &ls, &empty_clex_str); result= 1; continue; } @@ -7012,13 +6953,13 @@ 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(thd, &wrong_users, &role_as_user->user, &empty_lex_str); + append_user(thd, &wrong_users, &role_as_user->user, &empty_clex_str); result= 1; continue; } username.str= thd->security_ctx->priv_role; username.length= strlen(username.str); - hostname= empty_lex_str; + hostname= empty_clex_str; } else if (user->user.str == current_user.str) { @@ -7034,12 +6975,12 @@ bool mysql_grant_role(THD *thd, List <LEX_USER> &list, bool revoke) hostname= user->host; else if ((role_as_user= find_acl_role(user->user.str))) - hostname= empty_lex_str; + hostname= empty_clex_str; else { if (is_invalid_role_name(username.str)) { - append_user(thd, &wrong_users, &username, &empty_lex_str); + append_user(thd, &wrong_users, &username, &empty_clex_str); result= 1; continue; } @@ -7101,7 +7042,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(thd, &wrong_users, &username, &empty_lex_str); + append_user(thd, &wrong_users, &username, &empty_clex_str); result= 1; undo_add_role_user_mapping(grantee, role); continue; @@ -7136,7 +7077,7 @@ bool mysql_grant_role(THD *thd, List <LEX_USER> &list, bool revoke) thd->lex->with_admin_option, hash_entry, revoke)) { - append_user(thd, &wrong_users, &username, &empty_lex_str); + append_user(thd, &wrong_users, &username, &empty_clex_str); result= 1; if (!revoke) { @@ -7294,6 +7235,8 @@ void grant_free(void) my_hash_free(&column_priv_hash); my_hash_free(&proc_priv_hash); my_hash_free(&func_priv_hash); + my_hash_free(&package_spec_priv_hash); + my_hash_free(&package_body_priv_hash); free_root(&grant_memroot,MYF(0)); DBUG_VOID_RETURN; } @@ -7360,7 +7303,11 @@ static bool grant_load(THD *thd, 0,0,0, (my_hash_get_key) get_grant_table, 0,0); (void) my_hash_init(&func_priv_hash, &my_charset_utf8_bin, 0,0,0, (my_hash_get_key) get_grant_table, 0,0); - init_sql_alloc(&grant_memroot, ACL_ALLOC_BLOCK_SIZE, 0, MYF(0)); + (void) my_hash_init(&package_spec_priv_hash, &my_charset_utf8_bin, + 0,0,0, (my_hash_get_key) get_grant_table, 0,0); + (void) my_hash_init(&package_body_priv_hash, &my_charset_utf8_bin, + 0,0,0, (my_hash_get_key) get_grant_table, 0,0); + init_sql_alloc(&grant_memroot, "GRANT", ACL_ALLOC_BLOCK_SIZE, 0, MYF(0)); t_table= tables_priv.table(); c_table= columns_priv.table(); @@ -7442,16 +7389,9 @@ static bool grant_load(THD *thd, continue; } } - if (procs_priv.routine_type()->val_int() == TYPE_ENUM_PROCEDURE) - { - hash= &proc_priv_hash; - } - else - if (procs_priv.routine_type()->val_int() == TYPE_ENUM_FUNCTION) - { - hash= &func_priv_hash; - } - else + stored_procedure_type type= (stored_procedure_type)procs_priv.routine_type()->val_int(); + const Sp_handler *sph= Sp_handler::handler(type); + if (!sph || !(hash= sph->get_priv_hash())) { sql_print_warning("'procs_priv' entry '%s' " "ignored, bad routine type", @@ -7516,6 +7456,7 @@ static my_bool propagate_role_grants_action(void *role_ptr, bool grant_reload(THD *thd) { HASH old_column_priv_hash, old_proc_priv_hash, old_func_priv_hash; + HASH old_package_spec_priv_hash, old_package_body_priv_hash; MEM_ROOT old_mem; int result; DBUG_ENTER("grant_reload"); @@ -7535,6 +7476,8 @@ bool grant_reload(THD *thd) old_column_priv_hash= column_priv_hash; old_proc_priv_hash= proc_priv_hash; old_func_priv_hash= func_priv_hash; + old_package_spec_priv_hash= package_spec_priv_hash; + old_package_body_priv_hash= package_body_priv_hash; /* Create a new memory pool but save the current memory pool to make an undo @@ -7552,6 +7495,8 @@ bool grant_reload(THD *thd) column_priv_hash= old_column_priv_hash; /* purecov: deadcode */ proc_priv_hash= old_proc_priv_hash; func_priv_hash= old_func_priv_hash; + package_spec_priv_hash= old_package_spec_priv_hash; + package_body_priv_hash= old_package_body_priv_hash; grant_memroot= old_mem; /* purecov: deadcode */ } else @@ -7559,6 +7504,8 @@ bool grant_reload(THD *thd) my_hash_free(&old_column_priv_hash); my_hash_free(&old_proc_priv_hash); my_hash_free(&old_func_priv_hash); + my_hash_free(&old_package_spec_priv_hash); + my_hash_free(&old_package_body_priv_hash); free_root(&old_mem,MYF(0)); } @@ -7624,7 +7571,7 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables, TABLE_LIST *first_not_own_table= thd->lex->first_not_own_table(); Security_context *sctx= thd->security_ctx; uint i; - ulong orig_want_access= want_access; + ulong original_want_access= want_access; bool locked= 0; GRANT_TABLE *grant_table; GRANT_TABLE *grant_table_role= NULL; @@ -7658,8 +7605,25 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables, TABLE_LIST *const t_ref= tl->correspondent_table ? tl->correspondent_table : tl; sctx= t_ref->security_ctx ? t_ref->security_ctx : thd->security_ctx; + ulong orig_want_access= original_want_access; + + /* + If sequence is used as part of NEXT VALUE, PREVIOUS VALUE or SELECT, + we need to modify the requested access rights depending on how the + sequence is used. + */ + if (t_ref->sequence && + !(want_access & ~(SELECT_ACL | INSERT_ACL | UPDATE_ACL | DELETE_ACL))) + { + /* + We want to have either SELECT or INSERT rights to sequences depending + on how they are accessed + */ + orig_want_access= ((t_ref->lock_type == TL_WRITE_ALLOW_WRITE) ? + INSERT_ACL : SELECT_ACL); + } - if (tl->with || !tl->db || + if (tl->with || !tl->db.str || (tl->select_lex && (tl->with= tl->select_lex->find_table_def_in_with_clauses(tl)))) continue; @@ -7835,7 +7799,7 @@ static void check_grant_column_int(GRANT_TABLE *grant_table, const char *name, bool check_grant_column(THD *thd, GRANT_INFO *grant, const char *db_name, const char *table_name, - const char *name, uint length, Security_context *sctx) + const char *name, size_t length, Security_context *sctx) { ulong want_access= grant->want_privilege & ~grant->privilege; DBUG_ENTER("check_grant_column"); @@ -7861,8 +7825,10 @@ bool check_grant_column(THD *thd, GRANT_INFO *grant, grant->version= grant_version; /* purecov: inspected */ } - check_grant_column_int(grant->grant_table_user, name, length, &want_access); - check_grant_column_int(grant->grant_table_role, name, length, &want_access); + check_grant_column_int(grant->grant_table_user, name, (uint)length, + &want_access); + check_grant_column_int(grant->grant_table_role, name, (uint)length, + &want_access); mysql_rwlock_unlock(&LOCK_grant); if (!want_access) @@ -7886,6 +7852,8 @@ bool check_grant_column(THD *thd, GRANT_INFO *grant, table_ref table reference where to check the field name name of field to check length length of name + fld use fld object to check invisibility when it is + not 0, not_found_field, view_ref_found DESCRIPTION Check the access rights to a column depending on the type of table @@ -7900,13 +7868,17 @@ bool check_grant_column(THD *thd, GRANT_INFO *grant, */ bool check_column_grant_in_table_ref(THD *thd, TABLE_LIST * table_ref, - const char *name, uint length) + const char *name, size_t length, + Field *fld) { GRANT_INFO *grant; const char *db_name; const char *table_name; Security_context *sctx= table_ref->security_ctx ? table_ref->security_ctx : thd->security_ctx; + if (fld && fld != not_found_field && fld != view_ref_found + && fld->invisible >= INVISIBLE_SYSTEM) + return false; if (table_ref->view || table_ref->field_translation) { @@ -7982,7 +7954,10 @@ bool check_grant_all_columns(THD *thd, ulong want_access_arg, for (; !fields->end_of_fields(); fields->next()) { - const char *field_name= fields->name(); + if (fields->field() && + fields->field()->invisible >= INVISIBLE_SYSTEM) + continue; + LEX_CSTRING *field_name= fields->name(); if (table_name != fields->get_table_name()) { @@ -8019,16 +7994,15 @@ bool check_grant_all_columns(THD *thd, ulong want_access_arg, if (grant_table) { GRANT_COLUMN *grant_column= - column_hash_search(grant_table, field_name, - (uint) strlen(field_name)); + column_hash_search(grant_table, field_name->str, field_name->length); if (grant_column) have_access= grant_column->rights; } if (grant_table_role) { GRANT_COLUMN *grant_column= - column_hash_search(grant_table_role, field_name, - (uint) strlen(field_name)); + column_hash_search(grant_table_role, field_name->str, + field_name->length); if (grant_column) have_access|= grant_column->rights; } @@ -8060,7 +8034,7 @@ err: command, sctx->priv_user, sctx->host_or_ip, - fields->name(), + fields->name()->str, table_name); return 1; } @@ -8156,7 +8130,9 @@ bool check_grant_db(THD *thd, const char *db) if (error) error= check_grant_db_routine(thd, db, &proc_priv_hash) && - check_grant_db_routine(thd, db, &func_priv_hash); + check_grant_db_routine(thd, db, &func_priv_hash) && + check_grant_db_routine(thd, db, &package_spec_priv_hash) && + check_grant_db_routine(thd, db, &package_body_priv_hash); mysql_rwlock_unlock(&LOCK_grant); @@ -8172,7 +8148,7 @@ bool check_grant_db(THD *thd, const char *db) thd Thread handler want_access Bits of privileges user needs to have procs List of routines to check. The user should have 'want_access' - is_proc True if the list is all procedures, else functions + sph SP handler no_errors If 0 then we write an error. The error is sent directly to the client @@ -8182,7 +8158,8 @@ bool check_grant_db(THD *thd, const char *db) ****************************************************************************/ bool check_grant_routine(THD *thd, ulong want_access, - TABLE_LIST *procs, bool is_proc, bool no_errors) + TABLE_LIST *procs, const Sp_handler *sph, + bool no_errors) { TABLE_LIST *table; Security_context *sctx= thd->security_ctx; @@ -8199,13 +8176,13 @@ bool check_grant_routine(THD *thd, ulong want_access, for (table= procs; table; table= table->next_global) { GRANT_NAME *grant_proc; - if ((grant_proc= routine_hash_search(host, sctx->ip, table->db, user, - table->table_name, is_proc, 0))) + if ((grant_proc= routine_hash_search(host, sctx->ip, table->db.str, user, + table->table_name.str, sph, 0))) table->grant.privilege|= grant_proc->privs; if (role[0]) /* current role set check */ { - if ((grant_proc= routine_hash_search("", NULL, table->db, role, - table->table_name, is_proc, 0))) + if ((grant_proc= routine_hash_search("", NULL, table->db.str, role, + table->table_name.str, sph, 0))) table->grant.privilege|= grant_proc->privs; } @@ -8224,7 +8201,7 @@ err: char buff[1024]; const char *command=""; if (table) - strxmov(buff, table->db, ".", table->table_name, NullS); + strxmov(buff, table->db.str, ".", table->table_name.str, NullS); if (want_access & EXECUTE_ACL) command= "execute"; else if (want_access & ALTER_PROC_ACL) @@ -8254,7 +8231,7 @@ err: */ bool check_routine_level_acl(THD *thd, const char *db, const char *name, - bool is_proc) + const Sp_handler *sph) { bool no_routine_acl= 1; GRANT_NAME *grant_proc; @@ -8263,7 +8240,7 @@ bool check_routine_level_acl(THD *thd, const char *db, const char *name, if ((grant_proc= routine_hash_search(sctx->priv_host, sctx->ip, db, sctx->priv_user, - name, is_proc, 0))) + name, sph, 0))) no_routine_acl= !(grant_proc->privs & SHOW_PROC_ACLS); if (no_routine_acl && sctx->priv_role[0]) /* current set role check */ @@ -8271,7 +8248,7 @@ bool check_routine_level_acl(THD *thd, const char *db, const char *name, if ((grant_proc= routine_hash_search("", NULL, db, sctx->priv_role, - name, is_proc, 0))) + name, sph, 0))) no_routine_acl= !(grant_proc->privs & SHOW_PROC_ACLS); } mysql_rwlock_unlock(&LOCK_grant); @@ -8287,7 +8264,7 @@ ulong get_table_grant(THD *thd, TABLE_LIST *table) { ulong privilege; Security_context *sctx= thd->security_ctx; - const char *db = table->db ? table->db : thd->db; + const char *db = table->db.str ? table->db.str : thd->db.str; GRANT_TABLE *grant_table; GRANT_TABLE *grant_table_role= NULL; @@ -8297,10 +8274,10 @@ ulong get_table_grant(THD *thd, TABLE_LIST *table) grant_table_role= NULL; #else grant_table= table_hash_search(sctx->host, sctx->ip, db, sctx->priv_user, - table->table_name, 0); + table->table_name.str, 0); if (sctx->priv_role[0]) grant_table_role= table_hash_search("", "", db, sctx->priv_role, - table->table_name, 0); + table->table_name.str, 0); #endif table->grant.grant_table_user= grant_table; // Remember for column test table->grant.grant_table_role= grant_table_role; @@ -8422,13 +8399,12 @@ static void add_user_option(String *grant, double value, const char *name) } } -static void add_user_parameters(String *result, ACL_USER* acl_user, +static void add_user_parameters(THD *thd, String *result, ACL_USER* acl_user, bool with_grant) { - result->append(STRING_WITH_LEN("@'")); - result->append(acl_user->host.hostname, acl_user->hostname_length, - system_charset_info); - result->append('\''); + result->append('@'); + append_identifier(thd, result, acl_user->host.hostname, + acl_user->hostname_length); if (acl_user->plugin.str == native_password_plugin_name.str || acl_user->plugin.str == old_password_plugin_name.str) @@ -8437,18 +8413,18 @@ static void add_user_parameters(String *result, ACL_USER* acl_user, { DBUG_ASSERT(acl_user->salt_len); result->append(STRING_WITH_LEN(" IDENTIFIED BY PASSWORD '")); - result->append(acl_user->auth_string.str, acl_user->auth_string.length); + result->append(&acl_user->auth_string); result->append('\''); } } else { result->append(STRING_WITH_LEN(" IDENTIFIED VIA ")); - result->append(acl_user->plugin.str, acl_user->plugin.length); + result->append(&acl_user->plugin); if (acl_user->auth_string.length) { result->append(STRING_WITH_LEN(" USING '")); - result->append(acl_user->auth_string.str, acl_user->auth_string.length); + result->append(&acl_user->auth_string); result->append('\''); } } @@ -8517,13 +8493,14 @@ static const char *command_array[]= "ALTER", "SHOW DATABASES", "SUPER", "CREATE TEMPORARY TABLES", "LOCK TABLES", "EXECUTE", "REPLICATION SLAVE", "REPLICATION CLIENT", "CREATE VIEW", "SHOW VIEW", "CREATE ROUTINE", "ALTER ROUTINE", - "CREATE USER", "EVENT", "TRIGGER", "CREATE TABLESPACE" + "CREATE USER", "EVENT", "TRIGGER", "CREATE TABLESPACE", + "DELETE HISTORY" }; static uint command_lengths[]= { 6, 6, 6, 6, 6, 4, 6, 8, 7, 4, 5, 10, 5, 5, 14, 5, 23, 11, 7, 17, 18, 11, 9, - 14, 13, 11, 5, 7, 17 + 14, 13, 11, 5, 7, 17, 14, }; @@ -8543,12 +8520,20 @@ static bool print_grants_for_role(THD *thd, ACL_ROLE * role) if (show_table_and_column_privileges(thd, role->user.str, "", buff, sizeof(buff))) return TRUE; - if (show_routine_grants(thd, role->user.str, "", &proc_priv_hash, - STRING_WITH_LEN("PROCEDURE"), buff, sizeof(buff))) + if (show_routine_grants(thd, role->user.str, "", &sp_handler_procedure, + buff, sizeof(buff))) + return TRUE; + + if (show_routine_grants(thd, role->user.str, "", &sp_handler_function, + buff, sizeof(buff))) + return TRUE; + + if (show_routine_grants(thd, role->user.str, "", &sp_handler_package_spec, + buff, sizeof(buff))) return TRUE; - if (show_routine_grants(thd, role->user.str, "", &func_priv_hash, - STRING_WITH_LEN("FUNCTION"), buff, sizeof(buff))) + if (show_routine_grants(thd, role->user.str, "", &sp_handler_package_body, + buff, sizeof(buff))) return TRUE; return FALSE; @@ -8563,18 +8548,21 @@ bool mysql_show_create_user(THD *thd, LEX_USER *lex_user) Protocol *protocol= thd->protocol; bool error= false; ACL_USER *acl_user; + uint head_length; DBUG_ENTER("mysql_show_create_user"); if (get_show_user(thd, lex_user, &username, &hostname, NULL)) DBUG_RETURN(TRUE); List<Item> field_list; - strxmov(buff, "CREATE USER for ", username, "@", hostname, NullS); + head_length= (uint) (strxmov(buff, "CREATE USER for ", username, "@", + hostname, NullS) - buff); Item_string *field = new (thd->mem_root) Item_string_ascii(thd, "", 0); if (!field) DBUG_RETURN(true); // Error given my my_alloc() - field->name= buff; + field->name.str= buff; + field->name.length= head_length; field->max_length= sizeof(buff); field_list.push_back(field, thd->mem_root); if (protocol->send_result_set_metadata(&field_list, @@ -8597,11 +8585,9 @@ bool mysql_show_create_user(THD *thd, LEX_USER *lex_user) goto end; } - result.append("CREATE USER '"); - result.append(username); - result.append('\''); - - add_user_parameters(&result, acl_user, false); + result.append("CREATE USER "); + append_identifier(thd, &result, username, strlen(username)); + add_user_parameters(thd, &result, acl_user, false); protocol->prepare_for_resend(); protocol->store(result.ptr(), result.length(), result.charset()); @@ -8629,10 +8615,12 @@ static int show_grants_callback(ACL_USER_BASE *role, void *data) } void mysql_show_grants_get_fields(THD *thd, List<Item> *fields, - const char *name) + const char *name, size_t length) { Item_string *field=new (thd->mem_root) Item_string_ascii(thd, "", 0); - field->name= (char *) name; + /* Set name explicit to avoid character set conversions */ + field->name.str= name; + field->name.length= length; field->max_length=1024; fields->push_back(field, thd->mem_root); } @@ -8703,7 +8691,7 @@ bool mysql_show_grants(THD *thd, LEX_USER *lex_user) ACL_ROLE *acl_role= NULL; char buff[1024]; Protocol *protocol= thd->protocol; - const char *username= NULL, *hostname= NULL, *rolename= NULL; + const char *username= NULL, *hostname= NULL, *rolename= NULL, *end; DBUG_ENTER("mysql_show_grants"); if (!initialized) @@ -8718,12 +8706,12 @@ bool mysql_show_grants(THD *thd, LEX_USER *lex_user) DBUG_ASSERT(rolename || username); List<Item> field_list; - if (!username) - strxmov(buff,"Grants for ",rolename, NullS); + if (username) + end= strxmov(buff,"Grants for ",username,"@",hostname, NullS); else - strxmov(buff,"Grants for ",username,"@",hostname, NullS); + end= strxmov(buff,"Grants for ",rolename, NullS); - mysql_show_grants_get_fields(thd, &field_list, buff); + mysql_show_grants_get_fields(thd, &field_list, buff, (uint) (end-buff)); if (protocol->send_result_set_metadata(&field_list, Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF)) @@ -8761,12 +8749,20 @@ bool mysql_show_grants(THD *thd, LEX_USER *lex_user) if (show_table_and_column_privileges(thd, username, hostname, buff, sizeof(buff))) goto end; - if (show_routine_grants(thd, username, hostname, &proc_priv_hash, - STRING_WITH_LEN("PROCEDURE"), buff, sizeof(buff))) + if (show_routine_grants(thd, username, hostname, &sp_handler_procedure, + buff, sizeof(buff))) goto end; - if (show_routine_grants(thd, username, hostname, &func_priv_hash, - STRING_WITH_LEN("FUNCTION"), buff, sizeof(buff))) + if (show_routine_grants(thd, username, hostname, &sp_handler_function, + buff, sizeof(buff))) + goto end; + + if (show_routine_grants(thd, username, hostname, &sp_handler_package_spec, + buff, sizeof(buff))) + goto end; + + if (show_routine_grants(thd, username, hostname, &sp_handler_package_body, + buff, sizeof(buff))) goto end; if (show_proxy_grants(thd, username, hostname, buff, sizeof(buff))) @@ -8804,9 +8800,9 @@ end: DBUG_RETURN(error); } -static ROLE_GRANT_PAIR *find_role_grant_pair(const LEX_STRING *u, - const LEX_STRING *h, - const LEX_STRING *r) +static ROLE_GRANT_PAIR *find_role_grant_pair(const LEX_CSTRING *u, + const LEX_CSTRING *h, + const LEX_CSTRING *r) { char buf[1024]; String pair_key(buf, sizeof(buf), &my_charset_bin); @@ -8827,7 +8823,7 @@ static bool show_role_grants(THD *thd, const char *username, { uint counter; Protocol *protocol= thd->protocol; - LEX_STRING host= {const_cast<char*>(hostname), strlen(hostname)}; + LEX_CSTRING host= {const_cast<char*>(hostname), strlen(hostname)}; String grant(buff,sizeof(buff),system_charset_info); for (counter= 0; counter < acl_entry->role_grants.elements; counter++) @@ -8836,17 +8832,14 @@ static bool show_role_grants(THD *thd, const char *username, grant.append(STRING_WITH_LEN("GRANT ")); ACL_ROLE *acl_role= *(dynamic_element(&acl_entry->role_grants, counter, ACL_ROLE**)); - grant.append(acl_role->user.str, acl_role->user.length, - system_charset_info); - grant.append(STRING_WITH_LEN(" TO '")); - grant.append(acl_entry->user.str, acl_entry->user.length, - system_charset_info); + append_identifier(thd, &grant, acl_role->user.str, acl_role->user.length); + grant.append(STRING_WITH_LEN(" TO ")); + append_identifier(thd, &grant, acl_entry->user.str, acl_entry->user.length); if (!(acl_entry->flags & IS_ROLE)) { - grant.append(STRING_WITH_LEN("'@'")); - grant.append(&host); + grant.append('@'); + append_identifier(thd, &grant, host.str, host.length); } - grant.append('\''); ROLE_GRANT_PAIR *pair= find_role_grant_pair(&acl_entry->user, &host, &acl_role->user); @@ -8900,13 +8893,12 @@ static bool show_global_privileges(THD *thd, ACL_USER_BASE *acl_entry, } } } - global.append (STRING_WITH_LEN(" ON *.* TO '")); - global.append(acl_entry->user.str, acl_entry->user.length, - system_charset_info); - global.append('\''); + global.append (STRING_WITH_LEN(" ON *.* TO ")); + append_identifier(thd, &global, acl_entry->user.str, acl_entry->user.length); if (!handle_as_role) - add_user_parameters(&global, (ACL_USER *)acl_entry, (want_access & GRANT_ACL)); + add_user_parameters(thd, &global, (ACL_USER *)acl_entry, + (want_access & GRANT_ACL)); protocol->prepare_for_resend(); protocol->store(global.ptr(),global.length(),global.charset()); @@ -8917,6 +8909,21 @@ static bool show_global_privileges(THD *thd, ACL_USER_BASE *acl_entry, } + +static void add_to_user(THD *thd, String *result, const char *user, + bool is_user, const char *host) +{ + result->append(STRING_WITH_LEN(" TO ")); + append_identifier(thd, result, user, strlen(user)); + if (is_user) + { + result->append('@'); + // host and lex_user->host are equal except for case + append_identifier(thd, result, host, strlen(host)); + } +} + + static bool show_database_privileges(THD *thd, const char *username, const char *hostname, char *buff, size_t buffsize) @@ -8977,16 +8984,8 @@ static bool show_database_privileges(THD *thd, const char *username, } db.append (STRING_WITH_LEN(" ON ")); append_identifier(thd, &db, acl_db->db, strlen(acl_db->db)); - db.append (STRING_WITH_LEN(".* TO '")); - db.append(username, strlen(username), - system_charset_info); - if (*hostname) - { - 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 ('\''); + db.append (STRING_WITH_LEN(".*")); + add_to_user(thd, &db, username, (*hostname), host); if (want_access & GRANT_ACL) db.append(STRING_WITH_LEN(" WITH GRANT OPTION")); protocol->prepare_for_resend(); @@ -9117,16 +9116,7 @@ static bool show_table_and_column_privileges(THD *thd, const char *username, global.append('.'); append_identifier(thd, &global, grant_table->tname, strlen(grant_table->tname)); - global.append(STRING_WITH_LEN(" TO '")); - global.append(username, strlen(username), - system_charset_info); - if (*hostname) - { - 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('\''); + add_to_user(thd, &global, username, (*hostname), host); if (table_access & GRANT_ACL) global.append(STRING_WITH_LEN(" WITH GRANT OPTION")); protocol->prepare_for_resend(); @@ -9144,12 +9134,13 @@ static bool show_table_and_column_privileges(THD *thd, const char *username, static int show_routine_grants(THD* thd, const char *username, const char *hostname, - HASH *hash, const char *type, int typelen, + const Sp_handler *sph, char *buff, int buffsize) { uint counter, index; int error= 0; Protocol *protocol= thd->protocol; + HASH *hash= sph->get_priv_hash(); /* Add routine access */ for (index=0 ; index < hash->records ; index++) { @@ -9203,23 +9194,15 @@ static int show_routine_grants(THD* thd, } } global.append(STRING_WITH_LEN(" ON ")); - global.append(type,typelen); + LEX_CSTRING tmp= sph->type_lex_cstring(); + global.append(&tmp); global.append(' '); append_identifier(thd, &global, grant_proc->db, strlen(grant_proc->db)); global.append('.'); append_identifier(thd, &global, grant_proc->tname, strlen(grant_proc->tname)); - global.append(STRING_WITH_LEN(" TO '")); - global.append(username, strlen(username), - system_charset_info); - if (*hostname) - { - 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('\''); + add_to_user(thd, &global, username, (*hostname), host); if (proc_access & GRANT_ACL) global.append(STRING_WITH_LEN(" WITH GRANT OPTION")); protocol->prepare_for_resend(); @@ -9314,8 +9297,8 @@ static int modify_grant_table(TABLE *table, Field *host_field, system_charset_info); user_field->store(user_to->user.str, user_to->user.length, system_charset_info); - if ((error= table->file->ha_update_row(table->record[1], - table->record[0])) && + if (unlikely(error= table->file->ha_update_row(table->record[1], + table->record[0])) && error != HA_ERR_RECORD_IS_THE_SAME) table->file->print_error(error, MYF(0)); else @@ -9324,7 +9307,7 @@ static int modify_grant_table(TABLE *table, Field *host_field, else { /* delete */ - if ((error=table->file->ha_delete_row(table->record[0]))) + if (unlikely((error=table->file->ha_delete_row(table->record[0])))) table->file->print_error(error, MYF(0)); } @@ -9356,11 +9339,9 @@ static int handle_roles_mappings_table(TABLE *table, bool drop, DBUG_PRINT("info", ("Rewriting entry in roles_mapping table: %s@%s", user_from->user.str, user_from->host.str)); table->use_all_columns(); - if ((error= table->file->ha_rnd_init(1))) - { - table->file->print_error(error, MYF(0)); + + if (unlikely(table->file->ha_rnd_init_with_error(1))) result= -1; - } else { while((error= table->file->ha_rnd_next(table->record[0])) != @@ -9391,7 +9372,7 @@ static int handle_roles_mappings_table(TABLE *table, bool drop, if (drop) /* drop if requested */ { - if ((error= table->file->ha_delete_row(table->record[0]))) + if (unlikely((error= table->file->ha_delete_row(table->record[0])))) table->file->print_error(error, MYF(0)); } else if (user_to) @@ -9399,8 +9380,8 @@ static int handle_roles_mappings_table(TABLE *table, bool drop, store_record(table, record[1]); role_field->store(user_to->user.str, user_to->user.length, system_charset_info); - if ((error= table->file->ha_update_row(table->record[1], - table->record[0])) && + if (unlikely(error= table->file->ha_update_row(table->record[1], + table->record[0])) && error != HA_ERR_RECORD_IS_THE_SAME) table->file->print_error(error, MYF(0)); } @@ -9491,13 +9472,14 @@ static int handle_grant_table(THD *thd, const Grant_table_base& grant_table, error= table->file->ha_index_read_idx_map(table->record[0], 0, user_key, (key_part_map)3, HA_READ_KEY_EXACT); - if (!error && !*host_str) - { // verify that we got a role or a user, as needed + if (!unlikely(error) && !*host_str) + { + // verify that we got a role or a user, as needed if (static_cast<const User_table&>(grant_table).check_is_role() != user_from->is_role()) error= HA_ERR_KEY_NOT_FOUND; } - if (error) + if (unlikely(error)) { if (error != HA_ERR_KEY_NOT_FOUND && error != HA_ERR_END_OF_FILE) { @@ -9521,11 +9503,8 @@ static int handle_grant_table(THD *thd, const Grant_table_base& grant_table, And their host- and user fields are not consecutive. Thus, we need to do a table scan to find all matching records. */ - if ((error= table->file->ha_rnd_init(1))) - { - table->file->print_error(error, MYF(0)); + if (unlikely(table->file->ha_rnd_init_with_error(1))) result= -1; - } else { #ifdef EXTRA_DEBUG @@ -9635,7 +9614,7 @@ static int handle_grant_struct(enum enum_acl_lists struct_no, bool drop, DBUG_RETURN(1); /* this calls for a role update */ - char *old_key= acl_role->user.str; + const char *old_key= acl_role->user.str; size_t old_key_length= acl_role->user.length; if (drop) { @@ -9675,7 +9654,7 @@ static int handle_grant_struct(enum enum_acl_lists struct_no, bool drop, elements= acl_users.elements; break; case DB_ACL: - elements= acl_dbs.elements(); + elements= int(acl_dbs.elements()); break; case COLUMN_PRIVILEGES_HASH: grant_name_hash= &column_priv_hash; @@ -9689,6 +9668,14 @@ static int handle_grant_struct(enum enum_acl_lists struct_no, bool drop, grant_name_hash= &func_priv_hash; elements= grant_name_hash->records; break; + case PACKAGE_SPEC_PRIVILEGES_HASH: + grant_name_hash= &package_spec_priv_hash; + elements= grant_name_hash->records; + break; + case PACKAGE_BODY_PRIVILEGES_HASH: + grant_name_hash= &package_body_priv_hash; + elements= grant_name_hash->records; + break; case PROXY_USERS_ACL: elements= acl_proxy_users.elements; break; @@ -9727,6 +9714,8 @@ static int handle_grant_struct(enum enum_acl_lists struct_no, bool drop, case COLUMN_PRIVILEGES_HASH: case PROC_PRIVILEGES_HASH: case FUNC_PRIVILEGES_HASH: + case PACKAGE_SPEC_PRIVILEGES_HASH: + case PACKAGE_BODY_PRIVILEGES_HASH: grant_name= (GRANT_NAME*) my_hash_element(grant_name_hash, idx); user= grant_name->user; host= grant_name->host.hostname; @@ -9809,6 +9798,8 @@ static int handle_grant_struct(enum enum_acl_lists struct_no, bool drop, case COLUMN_PRIVILEGES_HASH: case PROC_PRIVILEGES_HASH: case FUNC_PRIVILEGES_HASH: + case PACKAGE_SPEC_PRIVILEGES_HASH: + case PACKAGE_BODY_PRIVILEGES_HASH: my_hash_delete(grant_name_hash, (uchar*) grant_name); /* In our HASH implementation on deletion one elements @@ -9854,6 +9845,8 @@ static int handle_grant_struct(enum enum_acl_lists struct_no, bool drop, case COLUMN_PRIVILEGES_HASH: case PROC_PRIVILEGES_HASH: case FUNC_PRIVILEGES_HASH: + case PACKAGE_SPEC_PRIVILEGES_HASH: + case PACKAGE_BODY_PRIVILEGES_HASH: { /* Save old hash key and its length to be able to properly update @@ -10036,6 +10029,26 @@ static int handle_grant_data(THD *thd, Grant_tables& tables, bool drop, if (search_only) goto end; } + /* Handle package spec array. */ + if ((handle_grant_struct(PACKAGE_SPEC_PRIVILEGES_HASH, + drop, user_from, user_to) || found) + && ! result) + { + result= 1; /* At least one record/element found. */ + /* If search is requested, we do not need to search further. */ + if (search_only) + goto end; + } + /* Handle package body array. */ + if ((handle_grant_struct(PACKAGE_BODY_PRIVILEGES_HASH, + drop, user_from, user_to) || found) + && ! result) + { + result= 1; /* At least one record/element found. */ + /* If search is requested, we do not need to search further. */ + if (search_only) + goto end; + } } /* Handle tables table. */ @@ -10595,6 +10608,45 @@ int mysql_alter_user(THD* thd, List<LEX_USER> &users_list) DBUG_RETURN(result); } + +static bool +mysql_revoke_sp_privs(THD *thd, + Grant_tables *tables, + const Sp_handler *sph, + const LEX_USER *lex_user) +{ + bool rc= false; + uint counter, revoked; + do { + HASH *hash= sph->get_priv_hash(); + for (counter= 0, revoked= 0 ; counter < hash->records ; ) + { + const char *user,*host; + GRANT_NAME *grant_proc= (GRANT_NAME*) my_hash_element(hash, counter); + user= safe_str(grant_proc->user); + host= safe_str(grant_proc->host.hostname); + + if (!strcmp(lex_user->user.str, user) && + !strcmp(lex_user->host.str, host)) + { + if (replace_routine_table(thd, grant_proc, + tables->procs_priv_table().table(), + *lex_user, + grant_proc->db, grant_proc->tname, + sph, ~(ulong)0, 1) == 0) + { + revoked= 1; + continue; + } + rc= true; // Something went wrong + } + counter++; + } + } while (revoked); + return rc; +} + + /* Revoke all privileges from a list of users. @@ -10611,7 +10663,7 @@ int mysql_alter_user(THD* thd, List<LEX_USER> &users_list) bool mysql_revoke_all(THD *thd, List <LEX_USER> &list) { - uint counter, revoked, is_proc; + uint counter, revoked; int result; ACL_DB *acl_db; DBUG_ENTER("mysql_revoke_all"); @@ -10740,32 +10792,11 @@ bool mysql_revoke_all(THD *thd, List <LEX_USER> &list) } while (revoked); /* Remove procedure access */ - for (is_proc=0; is_proc<2; is_proc++) do { - HASH *hash= is_proc ? &proc_priv_hash : &func_priv_hash; - for (counter= 0, revoked= 0 ; counter < hash->records ; ) - { - const char *user,*host; - GRANT_NAME *grant_proc= (GRANT_NAME*) my_hash_element(hash, counter); - user= safe_str(grant_proc->user); - host= safe_str(grant_proc->host.hostname); - - if (!strcmp(lex_user->user.str,user) && - !strcmp(lex_user->host.str, host)) - { - if (replace_routine_table(thd, grant_proc, - tables.procs_priv_table().table(), - *lex_user, - grant_proc->db, grant_proc->tname, - is_proc, ~(ulong)0, 1) == 0) - { - revoked= 1; - continue; - } - result= -1; // Something went wrong - } - counter++; - } - } while (revoked); + if (mysql_revoke_sp_privs(thd, &tables, &sp_handler_function, lex_user) || + mysql_revoke_sp_privs(thd, &tables, &sp_handler_procedure, lex_user) || + mysql_revoke_sp_privs(thd, &tables, &sp_handler_package_spec, lex_user) || + mysql_revoke_sp_privs(thd, &tables, &sp_handler_package_body, lex_user)) + result= -1; ACL_USER_BASE *user_or_role; /* remove role grants */ @@ -10917,11 +10948,11 @@ Silence_routine_definer_errors::handle_condition( */ bool sp_revoke_privileges(THD *thd, const char *sp_db, const char *sp_name, - bool is_proc) + const Sp_handler *sph) { uint counter, revoked; int result; - HASH *hash= is_proc ? &proc_priv_hash : &func_priv_hash; + HASH *hash= sph->get_priv_hash(); Silence_routine_definer_errors error_handler; DBUG_ENTER("sp_revoke_privileges"); @@ -10957,7 +10988,7 @@ bool sp_revoke_privileges(THD *thd, const char *sp_db, const char *sp_name, if (replace_routine_table(thd, grant_proc, tables.procs_priv_table().table(), lex_user, grant_proc->db, grant_proc->tname, - is_proc, ~(ulong)0, 1) == 0) + sph, ~(ulong)0, 1) == 0) { revoked= 1; continue; @@ -10982,7 +11013,7 @@ bool sp_revoke_privileges(THD *thd, const char *sp_db, const char *sp_name, @param thd The current thread. @param sp_db @param sp_name - @param is_proc + @param sph @return @retval FALSE Success @@ -10990,7 +11021,7 @@ bool sp_revoke_privileges(THD *thd, const char *sp_db, const char *sp_name, */ bool sp_grant_privileges(THD *thd, const char *sp_db, const char *sp_name, - bool is_proc) + const Sp_handler *sph) { Security_context *sctx= thd->security_ctx; LEX_USER *combo; @@ -11001,7 +11032,7 @@ bool sp_grant_privileges(THD *thd, const char *sp_db, const char *sp_name, Dummy_error_handler error_handler; DBUG_ENTER("sp_grant_privileges"); - if (!(combo=(LEX_USER*) thd->alloc(sizeof(st_lex_user)))) + if (!(combo=(LEX_USER*) thd->alloc(sizeof(LEX_USER)))) DBUG_RETURN(TRUE); combo->user.str= (char *) sctx->priv_user; @@ -11020,8 +11051,10 @@ bool sp_grant_privileges(THD *thd, const char *sp_db, const char *sp_name, bzero((char*)tables, sizeof(TABLE_LIST)); user_list.empty(); - tables->db= (char*)sp_db; - tables->table_name= tables->alias= (char*)sp_name; + tables->db.str= sp_db; + tables->db.length= sp_db ? strlen(sp_db) : 0; + tables->table_name.str= tables->alias.str= sp_name; + tables->table_name.length= tables->alias.length= sp_name ? strlen(sp_name) : 0; thd->make_lex_string(&combo->user, combo->user.str, strlen(combo->user.str)); thd->make_lex_string(&combo->host, combo->host.str, strlen(combo->host.str)); @@ -11046,7 +11079,7 @@ bool sp_grant_privileges(THD *thd, const char *sp_db, const char *sp_name, as all errors will be handled later. */ thd->push_internal_handler(&error_handler); - result= mysql_routine_grant(thd, tables, is_proc, user_list, + result= mysql_routine_grant(thd, tables, sph, user_list, DEFAULT_CREATE_PROC_ACLS, FALSE, FALSE); thd->pop_internal_handler(); DBUG_RETURN(result); @@ -11208,8 +11241,8 @@ static int enabled_roles_insert(ACL_USER_BASE *role, void *context_data) struct APPLICABLE_ROLES_DATA { TABLE *table; - const LEX_STRING host; - const LEX_STRING user_and_host; + const LEX_CSTRING host; + const LEX_CSTRING user_and_host; ACL_USER *user; }; @@ -11220,9 +11253,9 @@ applicable_roles_insert(ACL_USER_BASE *grantee, ACL_ROLE *role, void *ptr) CHARSET_INFO *cs= system_charset_info; TABLE *table= data->table; bool is_role= grantee != data->user; - const LEX_STRING *user_and_host= is_role ? &grantee->user + const LEX_CSTRING *user_and_host= is_role ? &grantee->user : &data->user_and_host; - const LEX_STRING *host= is_role ? &empty_lex_str : &data->host; + const LEX_CSTRING *host= is_role ? &empty_clex_str : &data->host; restore_record(table, s->default_values); table->field[0]->store(user_and_host->str, user_and_host->length, cs); @@ -11241,7 +11274,7 @@ applicable_roles_insert(ACL_USER_BASE *grantee, ACL_ROLE *role, void *ptr) if (!is_role) { if (data->user->default_rolename.length && - !strcmp(data->user->default_rolename.str, role->user.str)) + lex_string_eq(&data->user->default_rolename, &role->user)) table->field[3]->store(STRING_WITH_LEN("YES"), cs); else table->field[3]->store(STRING_WITH_LEN("NO"), cs); @@ -11292,7 +11325,7 @@ static int show_database_grants(THD *thd, SHOW_VAR *var, char *buff, { var->type= SHOW_UINT; var->value= buff; - *(uint *)buff= acl_dbs.elements(); + *(uint *)buff= uint(acl_dbs.elements()); return 0; } @@ -11309,6 +11342,8 @@ SHOW_VAR acl_statistics[] = { {"database_grants", (char*)show_database_grants, SHOW_SIMPLE_FUNC}, {"function_grants", (char*)&func_priv_hash.records, SHOW_ULONG}, {"procedure_grants", (char*)&proc_priv_hash.records, SHOW_ULONG}, + {"package_spec_grants", (char*)&package_spec_priv_hash.records, SHOW_ULONG}, + {"package_body_grants", (char*)&package_body_priv_hash.records, SHOW_ULONG}, {"proxy_users", (char*)&acl_proxy_users.elements, SHOW_UINT}, {"role_grants", (char*)&acl_roles_mappings.records, SHOW_ULONG}, {"roles", (char*)&acl_roles.records, SHOW_ULONG}, @@ -11844,7 +11879,7 @@ void fill_effective_table_privileges(THD *thd, GRANT_INFO *grant, /* global privileges */ grant->privilege= sctx->master_access; - if (!thd->db || strcmp(db, thd->db)) + if (!thd->db.str || strcmp(db, thd->db.str)) { /* db privileges */ grant->privilege|= acl_get(sctx->host, sctx->ip, sctx->priv_user, db, 0); @@ -11892,7 +11927,7 @@ void fill_effective_table_privileges(THD *thd, GRANT_INFO *grant, ****************************************************************************/ bool check_routine_level_acl(THD *thd, const char *db, const char *name, - bool is_proc) + const Sp_handler *sph) { return FALSE; } @@ -11940,7 +11975,7 @@ LEX_USER *get_current_user(THD *thd, LEX_USER *user, bool lock) if (lock) mysql_mutex_lock(&acl_cache->lock); if (find_acl_role(dup->user.str)) - dup->host= empty_lex_str; + dup->host= empty_clex_str; else dup->host= host_not_specified; if (lock) @@ -11955,7 +11990,7 @@ LEX_USER *get_current_user(THD *thd, LEX_USER *user, bool lock) struct ACL_internal_schema_registry_entry { - const LEX_STRING *m_name; + const LEX_CSTRING *m_name; const ACL_internal_schema_access *m_access; }; @@ -11976,7 +12011,7 @@ static uint m_registry_array_size= 0; @param access the schema ACL specific rules */ void ACL_internal_schema_registry::register_schema - (const LEX_STRING *name, const ACL_internal_schema_access *access) + (const LEX_CSTRING *name, const ACL_internal_schema_access *access) { DBUG_ASSERT(m_registry_array_size < array_elements(registry_array)); @@ -12083,10 +12118,11 @@ struct MPVIO_EXT :public MYSQL_PLUGIN_VIO MYSQL_SERVER_AUTH_INFO auth_info; ACL_USER *acl_user; ///< a copy, independent from acl_users array plugin_ref plugin; ///< what plugin we're under - LEX_STRING db; ///< db name from the handshake packet + LEX_CSTRING db; ///< db name from the handshake packet /** when restarting a plugin this caches the last client reply */ struct { - char *plugin, *pkt; ///< pointers into NET::buff + const char *plugin; + char *pkt; ///< pointer into NET::buff uint pkt_len; } cached_client_reply; /** this caches the first plugin packet for restart request on the client */ @@ -12441,7 +12477,7 @@ static bool find_mpvio_user(MPVIO_EXT *mpvio) } mpvio->auth_info.user_name= sctx->user; - mpvio->auth_info.user_name_length= strlen(sctx->user); + mpvio->auth_info.user_name_length= (uint)strlen(sctx->user); mpvio->auth_info.auth_string= mpvio->acl_user->auth_string.str; mpvio->auth_info.auth_string_length= (unsigned long) mpvio->acl_user->auth_string.length; strmake_buf(mpvio->auth_info.authenticated_as, safe_str(mpvio->acl_user->user.str)); @@ -12479,12 +12515,10 @@ read_client_connect_attrs(char **ptr, char *end, CHARSET_INFO *from_cs) if (length > 65535) return true; -#ifdef HAVE_PSI_THREAD_INTERFACE - if (PSI_THREAD_CALL(set_thread_connect_attrs)(*ptr, (size_t)length, from_cs) && + if (PSI_CALL_set_thread_connect_attrs(*ptr, (uint)length, from_cs) && current_thd->variables.log_warnings) sql_print_warning("Connection attributes of length %llu were truncated", length); -#endif return false; } @@ -12526,7 +12560,7 @@ static bool parse_com_change_user_packet(MPVIO_EXT *mpvio, uint packet_length) *passwd > 127 and become 2**32-127+ after casting to uint. */ uint passwd_len= (thd->client_capabilities & CLIENT_SECURE_CONNECTION ? - (uchar) (*passwd++) : strlen(passwd)); + (uchar) (*passwd++) : (uint)strlen(passwd)); db+= passwd_len + 1; /* @@ -12540,7 +12574,7 @@ static bool parse_com_change_user_packet(MPVIO_EXT *mpvio, uint packet_length) DBUG_RETURN (1); } - uint db_len= strlen(db); + size_t db_len= strlen(db); char *next_field= db + db_len + 1; @@ -12574,7 +12608,7 @@ static bool parse_com_change_user_packet(MPVIO_EXT *mpvio, uint packet_length) connection is closed. We don't want to accidentally free a wrong pointer if connect failed. */ - thd->reset_db(NULL, 0); + thd->reset_db(&null_clex_str); if (!initialized) { @@ -12588,7 +12622,7 @@ static bool parse_com_change_user_packet(MPVIO_EXT *mpvio, uint packet_length) if (find_mpvio_user(mpvio)) DBUG_RETURN(1); - char *client_plugin; + const char *client_plugin; if (thd->client_capabilities & CLIENT_PLUGIN_AUTH) { if (next_field >= end) @@ -12699,7 +12733,7 @@ static ulong parse_client_handshake_packet(MPVIO_EXT *mpvio, DBUG_PRINT("info", ("Reading user information over SSL layer")); pkt_len= my_net_read(net); - if (pkt_len == packet_error || pkt_len < NORMAL_HANDSHAKE_SIZE) + if (unlikely(pkt_len == packet_error || pkt_len < NORMAL_HANDSHAKE_SIZE)) { DBUG_PRINT("error", ("Failed to read user information (pkt_len= %lu)", pkt_len)); @@ -12740,7 +12774,7 @@ static ulong parse_client_handshake_packet(MPVIO_EXT *mpvio, char *user= end; char *passwd= strend(user)+1; - uint user_len= (uint)(passwd - user - 1), db_len; + size_t user_len= (size_t)(passwd - user - 1), db_len; char *db= passwd; char user_buff[USERNAME_LENGTH + 1]; // buffer to store user in utf8 uint dummy_errors; @@ -12782,11 +12816,15 @@ static ulong parse_client_handshake_packet(MPVIO_EXT *mpvio, db_len= safe_strlen(db); char *next_field; - char *client_plugin= next_field= passwd + passwd_len + (db ? db_len + 1 : 0); + const char *client_plugin= next_field= passwd + passwd_len + (db ? db_len + 1 : 0); - /* Since 4.1 all database names are stored in utf8 */ - if (thd->copy_with_error(system_charset_info, &mpvio->db, - thd->charset(), db, db_len)) + /* + Since 4.1 all database names are stored in utf8 + The cast is ok as copy_with_error will create a new area for db + */ + if (unlikely(thd->copy_with_error(system_charset_info, + (LEX_STRING*) &mpvio->db, + thd->charset(), db, db_len))) return packet_error; user_len= copy_and_convert(user_buff, sizeof(user_buff) - 1, @@ -12812,7 +12850,7 @@ static ulong parse_client_handshake_packet(MPVIO_EXT *mpvio, Security_context *sctx= thd->security_ctx; - my_free(sctx->user); + my_free((char*) sctx->user); if (!(sctx->user= my_strndup(user, user_len, MYF(MY_WME)))) return packet_error; /* The error is set by my_strdup(). */ @@ -12822,7 +12860,7 @@ static ulong parse_client_handshake_packet(MPVIO_EXT *mpvio, connection is closed. We don't want to accidentally free a wrong pointer if connect failed. */ - thd->reset_db(NULL, 0); + thd->reset_db(&null_clex_str); if (!initialized) { @@ -12876,11 +12914,10 @@ static ulong parse_client_handshake_packet(MPVIO_EXT *mpvio, restarted and a server auth plugin will read the data that the client has just send. Cache them to return in the next server_mpvio_read_packet(). */ - if (my_strcasecmp(system_charset_info, mpvio->acl_user->plugin.str, - plugin_name(mpvio->plugin)->str) != 0) + if (!lex_string_eq(&mpvio->acl_user->plugin, plugin_name(mpvio->plugin))) { mpvio->cached_client_reply.pkt= passwd; - mpvio->cached_client_reply.pkt_len= passwd_len; + mpvio->cached_client_reply.pkt_len= (uint)passwd_len; mpvio->cached_client_reply.plugin= client_plugin; mpvio->status= MPVIO_EXT::RESTART; return packet_error; @@ -12909,7 +12946,7 @@ static ulong parse_client_handshake_packet(MPVIO_EXT *mpvio, } *buff= (uchar*) passwd; - return passwd_len; + return (ulong)passwd_len; #else return 0; #endif @@ -13024,7 +13061,7 @@ static int server_mpvio_read_packet(MYSQL_PLUGIN_VIO *param, uchar **buf) else pkt_len= my_net_read(&mpvio->auth_info.thd->net); - if (pkt_len == packet_error) + if (unlikely(pkt_len == packet_error)) goto err; mpvio->packets_read++; @@ -13036,7 +13073,7 @@ static int server_mpvio_read_packet(MYSQL_PLUGIN_VIO *param, uchar **buf) if (mpvio->packets_read == 1) { pkt_len= parse_client_handshake_packet(mpvio, buf, pkt_len); - if (pkt_len == packet_error) + if (unlikely(pkt_len == packet_error)) goto err; } else @@ -13173,7 +13210,7 @@ static bool acl_check_ssl(THD *thd, const ACL_USER *acl_user) } -static int do_auth_once(THD *thd, const LEX_STRING *auth_plugin_name, +static int do_auth_once(THD *thd, const LEX_CSTRING *auth_plugin_name, MPVIO_EXT *mpvio) { int res= CR_OK, old_status= MPVIO_EXT::FAILURE; @@ -13255,7 +13292,7 @@ bool acl_authenticate(THD *thd, uint com_change_user_pkt_len) { int res= CR_OK; MPVIO_EXT mpvio; - const LEX_STRING *auth_plugin_name= default_auth_plugin_name; + const LEX_CSTRING *auth_plugin_name= default_auth_plugin_name; enum enum_server_command command= com_change_user_pkt_len ? COM_CHANGE_USER : COM_CONNECT; DBUG_ENTER("acl_authenticate"); @@ -13307,8 +13344,7 @@ bool acl_authenticate(THD *thd, uint com_change_user_pkt_len) { DBUG_ASSERT(mpvio.acl_user); DBUG_ASSERT(command == COM_CHANGE_USER || - my_strcasecmp(system_charset_info, auth_plugin_name->str, - mpvio.acl_user->plugin.str)); + !lex_string_eq(auth_plugin_name, &mpvio.acl_user->plugin)); auth_plugin_name= &mpvio.acl_user->plugin; res= do_auth_once(thd, auth_plugin_name, &mpvio); } @@ -13571,11 +13607,9 @@ bool acl_authenticate(THD *thd, uint com_change_user_pkt_len) else my_ok(thd); -#ifdef HAVE_PSI_THREAD_INTERFACE - PSI_THREAD_CALL(set_thread_user_host) - (thd->main_security_ctx.user, strlen(thd->main_security_ctx.user), - thd->main_security_ctx.host_or_ip, strlen(thd->main_security_ctx.host_or_ip)); -#endif + PSI_CALL_set_thread_user_host + (thd->main_security_ctx.user, (uint)strlen(thd->main_security_ctx.user), + thd->main_security_ctx.host_or_ip, (uint)strlen(thd->main_security_ctx.host_or_ip)); /* Ready to handle queries */ DBUG_RETURN(0); @@ -13705,7 +13739,7 @@ static int old_password_authenticate(MYSQL_PLUGIN_VIO *vio, We need to figure out the correct scramble length here. */ if (pkt_len == SCRAMBLE_LENGTH_323 + 1) - pkt_len= strnlen((char*)pkt, pkt_len); + pkt_len= (int)strnlen((char*)pkt, pkt_len); if (pkt_len == 0) /* no password */ return info->auth_string[0] ? CR_AUTH_USER_CREDENTIALS : CR_OK; |