diff options
author | Arun Kuruvila <arun.kuruvila@oracle.com> | 2016-11-28 11:55:36 +0530 |
---|---|---|
committer | Arun Kuruvila <arun.kuruvila@oracle.com> | 2016-11-28 11:55:36 +0530 |
commit | 3a37745ca048e7b1faf726a15929ae944d7e25ed (patch) | |
tree | 8c1f3e6ee90424bb210f6b63a5938e2a95bada20 /sql/sql_acl.cc | |
parent | 07fb5cffb035c622927c59188f0f062595eb2847 (diff) | |
download | mariadb-git-3a37745ca048e7b1faf726a15929ae944d7e25ed.tar.gz |
Diffstat (limited to 'sql/sql_acl.cc')
-rw-r--r-- | sql/sql_acl.cc | 501 |
1 files changed, 500 insertions, 1 deletions
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 99394878a55..b48b8562679 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -168,9 +168,411 @@ TABLE_FIELD_TYPE mysql_db_table_fields[MYSQL_DB_FIELD_COUNT] = { } }; +static const +TABLE_FIELD_TYPE mysql_user_table_fields[MYSQL_USER_FIELD_COUNT] = { + { + { C_STRING_WITH_LEN("Host") }, + { C_STRING_WITH_LEN("char(60)") }, + {NULL, 0} + }, + { + { C_STRING_WITH_LEN("User") }, + { C_STRING_WITH_LEN("char(16)") }, + {NULL, 0} + }, + { + { C_STRING_WITH_LEN("Password") }, + { C_STRING_WITH_LEN("char(41)") }, + { C_STRING_WITH_LEN("latin1") } + }, + { + { 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("Reload_priv") }, + { C_STRING_WITH_LEN("enum('N','Y')") }, + { C_STRING_WITH_LEN("utf8") } + }, + { + { C_STRING_WITH_LEN("Shutdown_priv") }, + { C_STRING_WITH_LEN("enum('N','Y')") }, + { C_STRING_WITH_LEN("utf8") } + }, + { + { C_STRING_WITH_LEN("Process_priv") }, + { C_STRING_WITH_LEN("enum('N','Y')") }, + { C_STRING_WITH_LEN("utf8") } + }, + { + { C_STRING_WITH_LEN("File_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("Show_db_priv") }, + { C_STRING_WITH_LEN("enum('N','Y')") }, + { C_STRING_WITH_LEN("utf8") } + }, + { + { C_STRING_WITH_LEN("Super_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("Execute_priv") }, + { C_STRING_WITH_LEN("enum('N','Y')") }, + { C_STRING_WITH_LEN("utf8") } + }, + { + { C_STRING_WITH_LEN("Repl_slave_priv") }, + { C_STRING_WITH_LEN("enum('N','Y')") }, + { C_STRING_WITH_LEN("utf8") } + }, + { + { C_STRING_WITH_LEN("Repl_client_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("Create_user_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") } + }, + { + { C_STRING_WITH_LEN("Create_tablespace_priv") }, + { C_STRING_WITH_LEN("enum('N','Y')") }, + { C_STRING_WITH_LEN("utf8") } + }, + { + { C_STRING_WITH_LEN("ssl_type") }, + { C_STRING_WITH_LEN("enum('','ANY','X509','SPECIFIED')") }, + { C_STRING_WITH_LEN("utf8") } + }, + { + { C_STRING_WITH_LEN("ssl_cipher") }, + { C_STRING_WITH_LEN("blob") }, + {NULL, 0} + }, + { + { C_STRING_WITH_LEN("x509_issuer") }, + { C_STRING_WITH_LEN("blob") }, + {NULL, 0} + }, + { + { C_STRING_WITH_LEN("x509_subject") }, + { C_STRING_WITH_LEN("blob") }, + {NULL, 0} + }, + { + { C_STRING_WITH_LEN("max_questions") }, + { C_STRING_WITH_LEN("int(11)") }, + {NULL, 0} + }, + { + { C_STRING_WITH_LEN("max_updates") }, + { C_STRING_WITH_LEN("int(11)") }, + {NULL, 0} + }, + { + { C_STRING_WITH_LEN("max_connections") }, + { C_STRING_WITH_LEN("int(11)") }, + {NULL, 0} + }, + { + { C_STRING_WITH_LEN("max_user_connections") }, + { C_STRING_WITH_LEN("int(11)") }, + {NULL, 0} + }, + { + { C_STRING_WITH_LEN("plugin") }, + { C_STRING_WITH_LEN("char(64)") }, + {NULL, 0} + }, + { + { C_STRING_WITH_LEN("authentication_string") }, + { C_STRING_WITH_LEN("text") }, + {NULL, 0} + } +}; + +static const +TABLE_FIELD_TYPE mysql_proxies_priv_table_fields[MYSQL_PROXIES_PRIV_FIELD_COUNT] = { + { + { C_STRING_WITH_LEN("Host") }, + { C_STRING_WITH_LEN("char(60)") }, + {NULL, 0} + }, + { + { C_STRING_WITH_LEN("User") }, + { C_STRING_WITH_LEN("char(16)") }, + {NULL, 0} + }, + { + { C_STRING_WITH_LEN("Proxied_host") }, + { C_STRING_WITH_LEN("char(60)") }, + {NULL, 0} + }, + { + { C_STRING_WITH_LEN("Proxied_user") }, + { C_STRING_WITH_LEN("char(16)") }, + {NULL, 0} + }, + { + { C_STRING_WITH_LEN("With_grant") }, + { C_STRING_WITH_LEN("tinyint(1)") }, + {NULL, 0} + }, + { + { C_STRING_WITH_LEN("Grantor") }, + { C_STRING_WITH_LEN("char(77)") }, + {NULL, 0} + }, + { + { C_STRING_WITH_LEN("Timestamp") }, + { C_STRING_WITH_LEN("timestamp") }, + {NULL, 0} + } +}; + +static const +TABLE_FIELD_TYPE mysql_procs_priv_table_fields[MYSQL_PROCS_PRIV_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(16)") }, + {NULL, 0} + }, + { + { C_STRING_WITH_LEN("Routine_name") }, + { C_STRING_WITH_LEN("char(64)") }, + { C_STRING_WITH_LEN("utf8") } + }, + { + { C_STRING_WITH_LEN("Routine_type") }, + { C_STRING_WITH_LEN("enum('FUNCTION','PROCEDURE')") }, + {NULL, 0} + }, + { + { C_STRING_WITH_LEN("Grantor") }, + { C_STRING_WITH_LEN("char(77)") }, + {NULL, 0} + }, + { + { C_STRING_WITH_LEN("Proc_priv") }, + { C_STRING_WITH_LEN("set('Execute','Alter Routine','Grant')") }, + { C_STRING_WITH_LEN("utf8") } + }, + { + { C_STRING_WITH_LEN("Timestamp") }, + { C_STRING_WITH_LEN("timestamp") }, + {NULL, 0} + } +}; + +static const +TABLE_FIELD_TYPE mysql_columns_priv_table_fields[MYSQL_COLUMNS_PRIV_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(16)") }, + {NULL, 0} + }, + { + { C_STRING_WITH_LEN("Table_name") }, + { C_STRING_WITH_LEN("char(64)") }, + {NULL, 0} + }, + { + { C_STRING_WITH_LEN("Column_name") }, + { C_STRING_WITH_LEN("char(64)") }, + {NULL, 0} + }, + { + { C_STRING_WITH_LEN("Timestamp") }, + { C_STRING_WITH_LEN("timestamp") }, + {NULL, 0} + }, + { + { C_STRING_WITH_LEN("Column_priv") }, + { C_STRING_WITH_LEN("set('Select','Insert','Update','References')") }, + { C_STRING_WITH_LEN("utf8") } + } +}; + +static const +TABLE_FIELD_TYPE mysql_tables_priv_table_fields[MYSQL_TABLES_PRIV_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(16)") }, + {NULL, 0} + }, + { + { C_STRING_WITH_LEN("Table_name") }, + { C_STRING_WITH_LEN("char(64)") }, + {NULL, 0} + }, + { + { C_STRING_WITH_LEN("Grantor") }, + { C_STRING_WITH_LEN("char(77)") }, + {NULL, 0} + }, + { + { C_STRING_WITH_LEN("Timestamp") }, + { C_STRING_WITH_LEN("timestamp") }, + {NULL, 0} + }, + { + { C_STRING_WITH_LEN("Table_priv") }, + { C_STRING_WITH_LEN("set('Select','Insert','Update','Delete','Create'," + "'Drop','Grant','References','Index','Alter'," + "'Create View','Show view','Trigger')") }, + { C_STRING_WITH_LEN("utf8") } + }, + { + { C_STRING_WITH_LEN("Column_priv") }, + { C_STRING_WITH_LEN("set('Select','Insert','Update','References')") }, + { C_STRING_WITH_LEN("utf8") } + } +}; + + const TABLE_FIELD_DEF mysql_db_table_def= {MYSQL_DB_FIELD_COUNT, mysql_db_table_fields}; +const TABLE_FIELD_DEF + mysql_user_table_def= {MYSQL_USER_FIELD_COUNT, mysql_user_table_fields}; + +const TABLE_FIELD_DEF + mysql_proxies_priv_table_def= {MYSQL_PROXIES_PRIV_FIELD_COUNT, + mysql_proxies_priv_table_fields}; + +const TABLE_FIELD_DEF + mysql_procs_priv_table_def= {MYSQL_PROCS_PRIV_FIELD_COUNT, + mysql_procs_priv_table_fields}; + +const TABLE_FIELD_DEF + mysql_columns_priv_table_def= {MYSQL_COLUMNS_PRIV_FIELD_COUNT, + mysql_columns_priv_table_fields}; + +const TABLE_FIELD_DEF + mysql_tables_priv_table_def= {MYSQL_TABLES_PRIV_FIELD_COUNT, + mysql_tables_priv_table_fields}; + static LEX_STRING native_password_plugin_name= { C_STRING_WITH_LEN("mysql_native_password") }; @@ -519,6 +921,36 @@ static uchar* acl_entry_get_key(acl_entry *entry, size_t *length, return (uchar*) entry->key; } +/** + Class to validate the flawlessness of ACL table + before performing ACL operations. +*/ +class Acl_table_intact : public Table_check_intact +{ +protected: + void report_error(uint code, const char *fmt, ...) + { + va_list args; + va_start(args, fmt); + error_log_print(ERROR_LEVEL, fmt, args); + va_end(args); + if (code) + { + va_start(args, fmt); + if (code == ER_CANNOT_LOAD_FROM_TABLE) + { + char *table_name; + va_arg(args, char *); + table_name= va_arg(args, char *); + my_error(code, MYF(0), table_name); + } + else + my_printv_error(code, ER(code), MYF(0), args); + va_end(args); + } + } +}; + #define IP_ADDR_STRLEN (3 + 1 + 3 + 1 + 3 + 1 + 3) #define ACL_KEY_LENGTH (IP_ADDR_STRLEN + 1 + NAME_LEN + \ 1 + USERNAME_LENGTH + 1) @@ -548,6 +980,7 @@ static bool update_user_table(THD *thd, TABLE *table, static my_bool acl_load(THD *thd, TABLE_LIST *tables); static my_bool grant_load(THD *thd, TABLE_LIST *tables); static inline void get_grantor(THD *thd, char* grantor); + /* Enumeration of various ACL's and Hashes used in handle_grant_struct() */ @@ -1871,6 +2304,7 @@ bool change_password(THD *thd, const char *host, const char *user, { TABLE_LIST tables; TABLE *table; + Acl_table_intact table_intact; /* Buffer should be extended when password length is extended. */ char buff[512]; ulong query_length; @@ -1907,6 +2341,9 @@ bool change_password(THD *thd, const char *host, const char *user, if (!(table= open_ltable(thd, &tables, TL_WRITE, MYSQL_LOCK_IGNORE_TIMEOUT))) DBUG_RETURN(1); + if (table_intact.check(table, &mysql_user_table_def)) + DBUG_RETURN(1); + /* This statement will be replicated as a statement, even when using row-based replication. The flag will be reset at the end of the @@ -2267,10 +2704,14 @@ static int replace_user_table(THD *thd, TABLE *table, const LEX_USER &combo, char what= (revoke_grant) ? 'N' : 'Y'; uchar user_key[MAX_KEY_LENGTH]; LEX *lex= thd->lex; + Acl_table_intact table_intact; DBUG_ENTER("replace_user_table"); mysql_mutex_assert_owner(&acl_cache->lock); + if (table_intact.check(table, &mysql_user_table_def)) + goto end; + if (combo.password.str && combo.password.str[0]) { if (combo.password.length != SCRAMBLED_PASSWORD_CHAR_LENGTH && @@ -2530,6 +2971,7 @@ static int replace_db_table(TABLE *table, const char *db, int error; char what= (revoke_grant) ? 'N' : 'Y'; uchar user_key[MAX_KEY_LENGTH]; + Acl_table_intact table_intact; DBUG_ENTER("replace_db_table"); if (!initialized) @@ -2538,6 +2980,9 @@ static int replace_db_table(TABLE *table, const char *db, DBUG_RETURN(-1); } + if (table_intact.check(table, &mysql_db_table_def)) + DBUG_RETURN(-1); + /* Check if there is such a user in user table in memory? */ if (!find_acl_user(combo.host.str,combo.user.str, FALSE)) { @@ -2678,6 +3123,7 @@ replace_proxies_priv_table(THD *thd, TABLE *table, const LEX_USER *user, uchar user_key[MAX_KEY_LENGTH]; ACL_PROXY_USER new_grant; char grantor[USER_HOST_BUFF_SIZE]; + Acl_table_intact table_intact; DBUG_ENTER("replace_proxies_priv_table"); @@ -2687,6 +3133,9 @@ replace_proxies_priv_table(THD *thd, TABLE *table, const LEX_USER *user, DBUG_RETURN(-1); } + if (table_intact.check(table, &mysql_proxies_priv_table_def)) + DBUG_RETURN(-1); + /* Check if there is such a user in user table in memory? */ if (!find_acl_user(user->host.str,user->user.str, FALSE)) { @@ -3090,9 +3539,13 @@ static int replace_column_table(GRANT_TABLE *g_t, int result=0; uchar key[MAX_KEY_LENGTH]; uint key_prefix_length; - KEY_PART_INFO *key_part= table->key_info->key_part; + KEY_PART_INFO *key_part; + Acl_table_intact table_intact; DBUG_ENTER("replace_column_table"); + if (table_intact.check(table, &mysql_columns_priv_table_def)) + DBUG_RETURN(-1); + table->use_all_columns(); table->field[0]->store(combo.host.str,combo.host.length, system_charset_info); @@ -3104,6 +3557,7 @@ static int replace_column_table(GRANT_TABLE *g_t, system_charset_info); /* Get length of 4 first key parts */ + key_part= table->key_info->key_part; key_prefix_length= (key_part[0].store_length + key_part[1].store_length + key_part[2].store_length + key_part[3].store_length); key_copy(key, table->record[0], table->key_info, key_prefix_length); @@ -3305,8 +3759,12 @@ static int replace_table_table(THD *thd, GRANT_TABLE *grant_table, int error=0; ulong store_table_rights, store_col_rights; uchar user_key[MAX_KEY_LENGTH]; + Acl_table_intact table_intact; DBUG_ENTER("replace_table_table"); + if (table_intact.check(table, &mysql_tables_priv_table_def)) + DBUG_RETURN(-1); + get_grantor(thd, grantor); /* The following should always succeed as new users are created before @@ -3429,6 +3887,7 @@ static int replace_routine_table(THD *thd, GRANT_NAME *grant_name, int old_row_exists= 1; int error=0; ulong store_proc_rights; + Acl_table_intact table_intact; DBUG_ENTER("replace_routine_table"); if (!initialized) @@ -3437,6 +3896,9 @@ static int replace_routine_table(THD *thd, GRANT_NAME *grant_name, DBUG_RETURN(-1); } + if (table_intact.check(table, &mysql_procs_priv_table_def)) + DBUG_RETURN(-1); + get_grantor(thd, grantor); /* New users are created before this function is called. @@ -6366,9 +6828,16 @@ static int handle_grant_data(TABLE_LIST *tables, bool drop, int result= 0; int found; int ret; + Acl_table_intact table_intact; DBUG_ENTER("handle_grant_data"); /* Handle user table. */ + if (table_intact.check(tables[0].table, &mysql_user_table_def)) + { + result= -1; + goto end; + } + if ((found= handle_grant_table(tables, 0, drop, user_from, user_to)) < 0) { /* Handle of table failed, don't touch the in-memory array. */ @@ -6393,6 +6862,12 @@ static int handle_grant_data(TABLE_LIST *tables, bool drop, } /* Handle db table. */ + if (table_intact.check(tables[1].table, &mysql_db_table_def)) + { + result= -1; + goto end; + } + if ((found= handle_grant_table(tables, 1, drop, user_from, user_to)) < 0) { /* Handle of table failed, don't touch the in-memory array. */ @@ -6417,6 +6892,12 @@ static int handle_grant_data(TABLE_LIST *tables, bool drop, } /* Handle stored routines table. */ + if (table_intact.check(tables[4].table, &mysql_procs_priv_table_def)) + { + result= -1; + goto end; + } + if ((found= handle_grant_table(tables, 4, drop, user_from, user_to)) < 0) { /* Handle of table failed, don't touch in-memory array. */ @@ -6457,6 +6938,12 @@ static int handle_grant_data(TABLE_LIST *tables, bool drop, } /* Handle tables table. */ + if (table_intact.check(tables[2].table, &mysql_tables_priv_table_def)) + { + result= -1; + goto end; + } + if ((found= handle_grant_table(tables, 2, drop, user_from, user_to)) < 0) { /* Handle of table failed, don't touch columns and in-memory array. */ @@ -6473,6 +6960,12 @@ static int handle_grant_data(TABLE_LIST *tables, bool drop, } /* Handle columns table. */ + if (table_intact.check(tables[3].table, &mysql_columns_priv_table_def)) + { + result= -1; + goto end; + } + if ((found= handle_grant_table(tables, 3, drop, user_from, user_to)) < 0) { /* Handle of table failed, don't touch the in-memory array. */ @@ -6493,6 +6986,12 @@ static int handle_grant_data(TABLE_LIST *tables, bool drop, /* Handle proxies_priv table. */ if (tables[5].table) { + if (table_intact.check(tables[5].table, &mysql_proxies_priv_table_def)) + { + result= -1; + goto end; + } + if ((found= handle_grant_table(tables, 5, drop, user_from, user_to)) < 0) { /* Handle of table failed, don't touch the in-memory array. */ |