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.cc228
1 files changed, 144 insertions, 84 deletions
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index 810312dea16..fcd51eb2273 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -36,6 +36,8 @@
#ifndef NO_EMBEDDED_ACCESS_CHECKS
+#define FIRST_NON_YN_FIELD 26
+
class acl_entry :public hash_filo_element
{
public:
@@ -168,8 +170,8 @@ my_bool acl_init(THD *org_thd, bool dont_read_acl_tables)
tables[0].alias=tables[0].real_name=(char*) "host";
tables[1].alias=tables[1].real_name=(char*) "user";
tables[2].alias=tables[2].real_name=(char*) "db";
- tables[0].next=tables+1;
- tables[1].next=tables+2;
+ tables[0].next_local= tables[0].next_global= tables+1;
+ tables[1].next_local= tables[1].next_global= tables+2;
tables[0].lock_type=tables[1].lock_type=tables[2].lock_type=TL_READ;
tables[0].db=tables[1].db=tables[2].db=thd->db;
@@ -303,9 +305,14 @@ my_bool acl_init(THD *org_thd, bool dont_read_acl_tables)
user.sort= get_sort(2,user.host.hostname,user.user);
user.hostname_length= (user.host.hostname ?
(uint) strlen(user.host.hostname) : 0);
+
if (table->fields >= 31) /* Starting from 4.0.2 we have more fields */
{
- char *ssl_type=get_field(&mem, table->field[24]);
+ uint base_field= 24;
+ if (table->fields > 31) /* Starting from 5.1 we have more privileges */
+ base_field= 26;
+
+ char *ssl_type=get_field(&mem, table->field[base_field]);
if (!ssl_type)
user.ssl_type=SSL_TYPE_NONE;
else if (!strcmp(ssl_type, "ANY"))
@@ -315,15 +322,15 @@ my_bool acl_init(THD *org_thd, bool dont_read_acl_tables)
else /* !strcmp(ssl_type, "SPECIFIED") */
user.ssl_type=SSL_TYPE_SPECIFIED;
- user.ssl_cipher= get_field(&mem, table->field[25]);
- user.x509_issuer= get_field(&mem, table->field[26]);
- user.x509_subject= get_field(&mem, table->field[27]);
+ user.ssl_cipher= get_field(&mem, table->field[base_field+1]);
+ user.x509_issuer= get_field(&mem, table->field[base_field+2]);
+ user.x509_subject= get_field(&mem, table->field[base_field+3]);
- char *ptr = get_field(&mem, table->field[28]);
+ char *ptr = get_field(&mem, table->field[base_field+4]);
user.user_resource.questions=atoi(ptr);
- ptr = get_field(&mem, table->field[29]);
+ ptr = get_field(&mem, table->field[base_field+5]);
user.user_resource.updates=atoi(ptr);
- ptr = get_field(&mem, table->field[30]);
+ ptr = get_field(&mem, table->field[base_field+6]);
user.user_resource.connections=atoi(ptr);
if (user.user_resource.questions || user.user_resource.updates ||
user.user_resource.connections)
@@ -2265,6 +2272,7 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list,
LEX_USER *Str;
TABLE_LIST tables[3];
bool create_new_users=0;
+ char *db_name, *real_name;
DBUG_ENTER("mysql_table_grant");
if (!initialized)
@@ -2281,17 +2289,18 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list,
if (columns.elements && !revoke_grant)
{
- TABLE *table;
class LEX_COLUMN *column;
List_iterator <LEX_COLUMN> column_iter(columns);
+ int res;
- if (!(table=open_ltable(thd,table_list,TL_READ)))
- DBUG_RETURN(-1);
+ if ((res= open_and_lock_tables(thd, table_list)))
+ DBUG_RETURN(res);
+
while ((column = column_iter++))
{
uint unused_field_idx= NO_CACHED_FIELD_INDEX;
- if (!find_field_in_table(thd,table,column->column.ptr(),
- column->column.length(),0,0,
+ if (!find_field_in_table(thd, table_list, column->column.ptr(),
+ column->column.length(), 0, 0, 0, 0,
&unused_field_idx))
{
my_error(ER_BAD_FIELD_ERROR, MYF(0),
@@ -2321,11 +2330,13 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list,
tables[0].alias=tables[0].real_name= (char*) "user";
tables[1].alias=tables[1].real_name= (char*) "tables_priv";
tables[2].alias=tables[2].real_name= (char*) "columns_priv";
- tables[0].next=tables+1;
+ tables[0].next_local= tables[0].next_global= tables+1;
/* Don't open column table if we don't need it ! */
- tables[1].next=((column_priv ||
- (revoke_grant && ((rights & COL_ACLS) || columns.elements)))
- ? tables+2 : 0);
+ tables[1].next_local=
+ tables[1].next_global= ((column_priv ||
+ (revoke_grant &&
+ ((rights & COL_ACLS) || columns.elements)))
+ ? tables+2 : 0);
tables[0].lock_type=tables[1].lock_type=tables[2].lock_type=TL_WRITE;
tables[0].db=tables[1].db=tables[2].db=(char*) "mysql";
@@ -2381,10 +2392,16 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list,
continue; // Add next user
}
+ db_name= (table_list->view_db.length ?
+ table_list->view_db.str :
+ table_list->db);
+ real_name= (table_list->view_name.length ?
+ table_list->view_name.str :
+ table_list->real_name);
+
/* Find/create cached table grant */
- grant_table= table_hash_search(Str->host.str,NullS,table_list->db,
- Str->user.str,
- table_list->real_name,1);
+ grant_table= table_hash_search(Str->host.str, NullS, db_name,
+ Str->user.str, real_name, 1);
if (!grant_table)
{
if (revoke_grant)
@@ -2394,9 +2411,8 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list,
result= -1;
continue;
}
- grant_table = new GRANT_TABLE (Str->host.str,table_list->db,
- Str->user.str,
- table_list->real_name,
+ grant_table = new GRANT_TABLE (Str->host.str, db_name,
+ Str->user.str, real_name,
rights,
column_priv);
if (!grant_table) // end of memory
@@ -2441,19 +2457,17 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list,
/* update table and columns */
- if (replace_table_table(thd,grant_table,tables[1].table,*Str,
- table_list->db,
- table_list->real_name,
+ if (replace_table_table(thd, grant_table, tables[1].table, *Str,
+ db_name, real_name,
rights, column_priv, revoke_grant))
{ // Crashend table ??
result= -1; /* purecov: deadcode */
}
else if (tables[2].table)
{
- if ((replace_column_table(grant_table,tables[2].table, *Str,
+ if ((replace_column_table(grant_table, tables[2].table, *Str,
columns,
- table_list->db,
- table_list->real_name,
+ db_name, real_name,
rights, revoke_grant)))
{
result= -1;
@@ -2497,11 +2511,9 @@ int mysql_grant(THD *thd, const char *db, List <LEX_USER> &list,
bzero((char*) &tables,sizeof(tables));
tables[0].alias=tables[0].real_name=(char*) "user";
tables[1].alias=tables[1].real_name=(char*) "db";
- tables[0].next=tables+1;
- tables[1].next=0;
+ tables[0].next_local= tables[0].next_global= tables+1;
tables[0].lock_type=tables[1].lock_type=TL_WRITE;
tables[0].db=tables[1].db=(char*) "mysql";
- tables[0].table=tables[1].table=0;
#ifdef HAVE_REPLICATION
/*
@@ -2618,7 +2630,7 @@ my_bool grant_init(THD *org_thd)
bzero((char*) &tables, sizeof(tables));
tables[0].alias=tables[0].real_name= (char*) "tables_priv";
tables[1].alias=tables[1].real_name= (char*) "columns_priv";
- tables[0].next=tables+1;
+ tables[0].next_local= tables[0].next_global= tables+1;
tables[0].lock_type=tables[1].lock_type=TL_READ;
tables[0].db=tables[1].db=thd->db;
@@ -2752,11 +2764,15 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables,
return 0; // ok
rw_rdlock(&LOCK_grant);
- for (table= tables; table && number--; table= table->next)
+ for (table= tables; table && number--; table= table->next_global)
{
if (!(~table->grant.privilege & want_access) || table->derived)
{
- table->grant.want_privilege=0;
+ /*
+ It is subquery in the FROM clause. VIEW set table->derived after
+ table opening, but this function always called before table opening.
+ */
+ table->grant.want_privilege= 0;
continue; // Already checked
}
GRANT_TABLE *grant_table = table_hash_search(thd->host,thd->ip,
@@ -2811,6 +2827,10 @@ err:
command= "index";
else if (want_access & GRANT_ACL)
command= "grant";
+ else if (want_access & CREATE_VIEW_ACL)
+ command= "create view";
+ else if (want_access & SHOW_VIEW_ACL)
+ command= "show view";
net_printf(thd,ER_TABLEACCESS_DENIED_ERROR,
command,
thd->priv_user,
@@ -2821,13 +2841,14 @@ err:
}
-bool check_grant_column(THD *thd,TABLE *table, const char *name,
- uint length, uint show_tables)
+bool check_grant_column(THD *thd, GRANT_INFO *grant,
+ char*db_name, char *table_name,
+ const char *name, uint length, uint show_tables)
{
GRANT_TABLE *grant_table;
GRANT_COLUMN *grant_column;
- ulong want_access=table->grant.want_privilege;
+ ulong want_access= grant->want_privilege & ~grant->privilege;
if (!want_access)
return 0; // Already checked
@@ -2835,15 +2856,15 @@ bool check_grant_column(THD *thd,TABLE *table, const char *name,
/* reload table if someone has modified any grants */
- if (table->grant.version != grant_version)
+ if (grant->version != grant_version)
{
- table->grant.grant_table=
- table_hash_search(thd->host, thd->ip, table->table_cache_key,
+ grant->grant_table=
+ table_hash_search(thd->host, thd->ip, db_name,
thd->priv_user,
- table->real_name, 0); /* purecov: inspected */
- table->grant.version=grant_version; /* purecov: inspected */
+ table_name, 0); /* purecov: inspected */
+ grant->version= grant_version; /* purecov: inspected */
}
- if (!(grant_table=table->grant.grant_table))
+ if (!(grant_table= grant->grant_table))
goto err; /* purecov: deadcode */
grant_column=column_hash_search(grant_table, name, length);
@@ -2853,7 +2874,7 @@ bool check_grant_column(THD *thd,TABLE *table, const char *name,
return 0;
}
#ifdef NOT_USED
- if (show_tables && (grant_column || table->grant.privilege & COL_ACLS))
+ if (show_tables && (grant_column || grant->privilege & COL_ACLS))
{
rw_unlock(&LOCK_grant); /* purecov: deadcode */
return 0; /* purecov: deadcode */
@@ -2874,47 +2895,47 @@ err:
thd->priv_user,
thd->host_or_ip,
name,
- table ? table->real_name : "unknown");
+ table_name);
}
return 1;
}
-bool check_grant_all_columns(THD *thd, ulong want_access, TABLE *table)
+bool check_grant_all_columns(THD *thd, ulong want_access, GRANT_INFO *grant,
+ char* db_name, char *table_name,
+ Field_iterator *fields)
{
GRANT_TABLE *grant_table;
GRANT_COLUMN *grant_column;
Field *field=0,**ptr;
- want_access &= ~table->grant.privilege;
+ want_access &= ~grant->privilege;
if (!want_access)
return 0; // Already checked
if (!grant_option)
- {
- field= table->field[0]; // To give a meaningful error message
goto err2;
- }
rw_rdlock(&LOCK_grant);
/* reload table if someone has modified any grants */
- if (table->grant.version != grant_version)
+ if (grant->version != grant_version)
{
- table->grant.grant_table=
- table_hash_search(thd->host, thd->ip, table->table_cache_key,
+ grant->grant_table=
+ table_hash_search(thd->host, thd->ip, db_name,
thd->priv_user,
- table->real_name,0); /* purecov: inspected */
- table->grant.version=grant_version; /* purecov: inspected */
+ table_name, 0); /* purecov: inspected */
+ grant->version= grant_version; /* purecov: inspected */
}
/* The following should always be true */
- if (!(grant_table=table->grant.grant_table))
+ if (!(grant_table= grant->grant_table))
goto err; /* purecov: inspected */
- for (ptr=table->field; (field= *ptr) ; ptr++)
+ for (; fields->end(); fields->next())
{
- grant_column=column_hash_search(grant_table, field->field_name,
- (uint) strlen(field->field_name));
+ const char *field_name= fields->name();
+ grant_column= column_hash_search(grant_table, field_name,
+ (uint) strlen(field_name));
if (!grant_column || (~grant_column->rights & want_access))
goto err;
}
@@ -2936,8 +2957,8 @@ err2:
command,
thd->priv_user,
thd->host_or_ip,
- field ? field->field_name : "unknown",
- table->real_name);
+ fields->name(),
+ table_name);
return 1;
}
@@ -3004,7 +3025,9 @@ ulong get_table_grant(THD *thd, TABLE_LIST *table)
}
-ulong get_column_grant(THD *thd, TABLE_LIST *table, Field *field)
+ulong get_column_grant(THD *thd, GRANT_INFO *grant,
+ const char *db_name, const char *table_name,
+ const char *field_name)
{
GRANT_TABLE *grant_table;
GRANT_COLUMN *grant_column;
@@ -3012,30 +3035,31 @@ ulong get_column_grant(THD *thd, TABLE_LIST *table, Field *field)
rw_rdlock(&LOCK_grant);
/* reload table if someone has modified any grants */
- if (table->grant.version != grant_version)
+ if (grant->version != grant_version)
{
- table->grant.grant_table=
- table_hash_search(thd->host, thd->ip, table->db,
+ grant->grant_table=
+ table_hash_search(thd->host, thd->ip, db_name,
thd->priv_user,
- table->real_name,0); /* purecov: inspected */
- table->grant.version=grant_version; /* purecov: inspected */
+ table_name, 0); /* purecov: inspected */
+ grant->version= grant_version; /* purecov: inspected */
}
- if (!(grant_table=table->grant.grant_table))
- priv=table->grant.privilege;
+ if (!(grant_table= grant->grant_table))
+ priv= grant->privilege;
else
{
- grant_column=column_hash_search(grant_table, field->field_name,
- (uint) strlen(field->field_name));
+ grant_column= column_hash_search(grant_table, field_name,
+ (uint) strlen(field_name));
if (!grant_column)
- priv=table->grant.privilege;
+ priv= grant->privilege;
else
- priv=table->grant.privilege | grant_column->rights;
+ priv= grant->privilege | grant_column->rights;
}
rw_unlock(&LOCK_grant);
return priv;
}
+
/* Help function for mysql_show_grants */
static void add_user_option(String *grant, ulong value, const char *name)
@@ -3053,15 +3077,16 @@ static void add_user_option(String *grant, ulong value, const char *name)
static const char *command_array[]=
{
- "SELECT", "INSERT","UPDATE","DELETE","CREATE", "DROP", "RELOAD","SHUTDOWN",
- "PROCESS","FILE","GRANT","REFERENCES","INDEX", "ALTER", "SHOW DATABASES",
- "SUPER", "CREATE TEMPORARY TABLES", "LOCK TABLES", "EXECUTE",
- "REPLICATION SLAVE", "REPLICATION CLIENT",
+ "SELECT", "INSERT", "UPDATE", "DELETE", "CREATE", "DROP", "RELOAD",
+ "SHUTDOWN", "PROCESS","FILE", "GRANT", "REFERENCES", "INDEX",
+ "ALTER", "SHOW DATABASES", "SUPER", "CREATE TEMPORARY TABLES",
+ "LOCK TABLES", "EXECUTE", "REPLICATION SLAVE", "REPLICATION CLIENT",
+ "CREATE VIEW", "SHOW VIEW"
};
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
+ 6, 6, 6, 6, 6, 4, 6, 8, 7, 4, 5, 10, 5, 5, 14, 5, 23, 11, 7, 17, 18, 11, 9
};
@@ -3460,10 +3485,9 @@ int open_grant_tables(THD *thd, TABLE_LIST *tables)
(tables+1)->alias= (tables+1)->real_name= (char*) "db";
(tables+2)->alias= (tables+2)->real_name= (char*) "tables_priv";
(tables+3)->alias= (tables+3)->real_name= (char*) "columns_priv";
- tables->next= tables+1;
- (tables+1)->next= tables+2;
- (tables+2)->next= tables+3;
- (tables+3)->next= 0;
+ tables->next_local= tables->next_global= tables+1;
+ (tables+1)->next_local= (tables+1)->next_global= tables+2;
+ (tables+2)->next_local= (tables+2)->next_global= tables+3;
tables->lock_type= (tables+1)->lock_type=
(tables+2)->lock_type= (tables+3)->lock_type= TL_WRITE;
tables->db= (tables+1)->db= (tables+2)->db= (tables+3)->db=(char*) "mysql";
@@ -3797,3 +3821,39 @@ int wild_case_compare(CHARSET_INFO *cs, const char *str,const char *wildstr)
DBUG_RETURN (*str != '\0');
}
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
+/*
+ fill effective privileges for table
+
+ SYNOPSIS
+ get_effectlige_privileges()
+ thd thread handleg
+ grant grants table descriptor
+ db db name
+ table table name
+*/
+
+void fill_effective_table_privileges(THD *thd, GRANT_INFO *grant,
+ const char *db, const char *table)
+{
+ /* global privileges */
+ grant->privilege= thd->master_access;
+ /* db privileges */
+ grant->privilege|= acl_get(thd->host, thd->ip, thd->priv_user, db, 0);
+ /* table privileges */
+ rw_rdlock(&LOCK_grant);
+ if (grant->version != grant_version)
+ {
+ grant->grant_table=
+ table_hash_search(thd->host, thd->ip, db,
+ thd->priv_user,
+ table, 0); /* purecov: inspected */
+ grant->version= grant_version; /* purecov: inspected */
+ }
+ if (grant->grant_table != 0)
+ {
+ grant->privilege|= grant->grant_table->privs;
+ }
+ rw_unlock(&LOCK_grant);
+}
+#endif