1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-30 16:24:05 +03:00
This commit is contained in:
Arun Kuruvila
2016-11-28 11:55:36 +05:30
parent 07fb5cffb0
commit 3a37745ca0
4 changed files with 618 additions and 26 deletions

View File

@ -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. */