summaryrefslogtreecommitdiff
path: root/sql/sql_acl.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/sql_acl.cc')
-rw-r--r--sql/sql_acl.cc1106
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;