diff options
-rw-r--r-- | libmysqld/lib_sql.cc | 7 | ||||
-rw-r--r-- | mysql-test/r/rpl_sp.result | 2 | ||||
-rw-r--r-- | sql/ha_innodb.cc | 16 | ||||
-rw-r--r-- | sql/item.cc | 4 | ||||
-rw-r--r-- | sql/item_func.cc | 12 | ||||
-rw-r--r-- | sql/item_strfunc.cc | 13 | ||||
-rw-r--r-- | sql/log.cc | 12 | ||||
-rw-r--r-- | sql/mysql_priv.h | 3 | ||||
-rw-r--r-- | sql/mysqld.cc | 8 | ||||
-rw-r--r-- | sql/repl_failsafe.cc | 4 | ||||
-rw-r--r-- | sql/set_var.cc | 17 | ||||
-rw-r--r-- | sql/slave.cc | 9 | ||||
-rw-r--r-- | sql/sp.cc | 5 | ||||
-rw-r--r-- | sql/sp_head.cc | 68 | ||||
-rw-r--r-- | sql/sp_head.h | 22 | ||||
-rw-r--r-- | sql/sql_acl.cc | 187 | ||||
-rw-r--r-- | sql/sql_acl.h | 3 | ||||
-rw-r--r-- | sql/sql_base.cc | 3 | ||||
-rw-r--r-- | sql/sql_class.cc | 48 | ||||
-rw-r--r-- | sql/sql_class.h | 41 | ||||
-rw-r--r-- | sql/sql_db.cc | 19 | ||||
-rw-r--r-- | sql/sql_insert.cc | 11 | ||||
-rw-r--r-- | sql/sql_parse.cc | 218 | ||||
-rw-r--r-- | sql/sql_show.cc | 49 | ||||
-rw-r--r-- | sql/sql_trigger.cc | 2 | ||||
-rw-r--r-- | sql/sql_view.cc | 15 | ||||
-rw-r--r-- | sql/sql_yacc.yy | 30 |
27 files changed, 449 insertions, 379 deletions
diff --git a/libmysqld/lib_sql.cc b/libmysqld/lib_sql.cc index a86d467299c..d6f41fda5f6 100644 --- a/libmysqld/lib_sql.cc +++ b/libmysqld/lib_sql.cc @@ -532,10 +532,9 @@ err: int check_embedded_connection(MYSQL *mysql) { THD *thd= (THD*)mysql->thd; - thd->host= (char*)my_localhost; - thd->host_or_ip= thd->host; - thd->user= my_strdup(mysql->user, MYF(0)); - thd->priv_user= thd->user; + st_security_context *sctx= thd->security_ctx; + sctx->host_or_ip= sctx->host= (char*)my_localhost; + sctx->priv_user= sctx->user= my_strdup(mysql->user, MYF(0)); return check_user(thd, COM_CONNECT, NULL, 0, thd->db, true); } diff --git a/mysql-test/r/rpl_sp.result b/mysql-test/r/rpl_sp.result index 394f93f2ea0..b1f564a0791 100644 --- a/mysql-test/r/rpl_sp.result +++ b/mysql-test/r/rpl_sp.result @@ -121,7 +121,7 @@ call foo4(); Got one of the listed errors show warnings; Level Code Message -Error 1142 INSERT command denied to user 'zedjzlcsjhd'@'localhost' for table 't1' +Error 1142 INSERT command denied to user 'zedjzlcsjhd'@'127.0.0.1' for table 't1' Warning 1417 A routine failed and has neither NO SQL nor READS SQL DATA in its declaration and binary logging is enabled; if non-transactional tables were updated, the binary log will miss their changes alter procedure foo4 sql security invoker; call foo4(); diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index 4ed5fadb603..fd5db6da722 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -563,25 +563,29 @@ innobase_mysql_print_thd( use the default max length */ { const THD* thd; + const st_security_context *sctx; const char* s; thd = (const THD*) input_thd; + /* We probably want to have original user as part of debug output. */ + sctx = &thd->main_security_ctx; + fprintf(f, "MySQL thread id %lu, query id %lu", thd->thread_id, (ulong) thd->query_id); - if (thd->host) { + if (sctx->host) { putc(' ', f); - fputs(thd->host, f); + fputs(sctx->host, f); } - if (thd->ip) { + if (sctx->ip) { putc(' ', f); - fputs(thd->ip, f); + fputs(sctx->ip, f); } - if (thd->user) { + if (sctx->user) { putc(' ', f); - fputs(thd->user, f); + fputs(sctx->user, f); } if ((s = thd->proc_info)) { diff --git a/sql/item.cc b/sql/item.cc index df57c301327..45c12d3840f 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -3443,8 +3443,8 @@ bool Item_field::fix_fields(THD *thd, Item **reference) VIEW_ANY_ACL))) { my_error(ER_COLUMNACCESS_DENIED_ERROR, MYF(0), - "ANY", thd->priv_user, thd->host_or_ip, - field_name, tab); + "ANY", thd->security_ctx->priv_user, + thd->security_ctx->host_or_ip, field_name, tab); goto error; } } diff --git a/sql/item_func.cc b/sql/item_func.cc index 518fb011e0f..338bb4db4fe 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -4713,7 +4713,7 @@ Item_func_sp::execute(Item **itp) Sub_statement_state statement_state; #ifndef NO_EMBEDDED_ACCESS_CHECKS - st_sp_security_context save_ctx; + st_security_context *save_ctx; #endif if (! m_sp && ! (m_sp= sp_find_function(thd, m_name, TRUE))) @@ -4723,11 +4723,11 @@ Item_func_sp::execute(Item **itp) } #ifndef NO_EMBEDDED_ACCESS_CHECKS - if (check_routine_access(thd, EXECUTE_ACL, - m_sp->m_db.str, m_sp->m_name.str, 0, 0)) + if (check_routine_access(thd, EXECUTE_ACL, + m_sp->m_db.str, m_sp->m_name.str, 0, 0) || + sp_change_security_context(thd, m_sp, &save_ctx)) goto error; - sp_change_security_context(thd, m_sp, &save_ctx); - if (save_ctx.changed && + if (save_ctx && check_routine_access(thd, EXECUTE_ACL, m_sp->m_db.str, m_sp->m_name.str, 0, 0)) goto error_check_ctx; @@ -4750,7 +4750,7 @@ Item_func_sp::execute(Item **itp) #ifndef NO_EMBEDDED_ACCESS_CHECKS error_check_ctx: - sp_restore_security_context(thd, m_sp, &save_ctx); + sp_restore_security_context(thd, save_ctx); #endif error: diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 4fd33c06095..6a51ecd307d 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -473,7 +473,8 @@ String *Item_func_des_decrypt::val_str(String *str) { uint key_number=(uint) (*res)[0] & 127; // Check if automatic key and that we have privilege to uncompress using it - if (!(current_thd->master_access & SUPER_ACL) || key_number > 9) + if (!(current_thd->security_ctx->master_access & SUPER_ACL) || + key_number > 9) goto error; VOID(pthread_mutex_lock(&LOCK_des_key_file)); @@ -1601,13 +1602,13 @@ String *Item_func_user::val_str(String *str) if (is_current) { - user= thd->priv_user; - host= thd->priv_host; + user= thd->security_ctx->priv_user; + host= thd->security_ctx->priv_host; } else { - user= thd->user; - host= thd->host_or_ip; + user= thd->main_security_ctx.user; + host= thd->main_security_ctx.priv_host; } // For system threads (e.g. replication SQL thread) user may be empty @@ -2518,7 +2519,7 @@ String *Item_load_file::val_str(String *str) if (!(file_name= args[0]->val_str(str)) #ifndef NO_EMBEDDED_ACCESS_CHECKS - || !(current_thd->master_access & FILE_ACL) + || !(current_thd->security_ctx->master_access & FILE_ACL) #endif ) goto err; diff --git a/sql/log.cc b/sql/log.cc index 920a3fcff42..032ac392c00 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -1476,7 +1476,7 @@ bool MYSQL_LOG::write(THD *thd,enum enum_server_command command, { // Normal thread if ((thd->options & OPTION_LOG_OFF) #ifndef NO_EMBEDDED_ACCESS_CHECKS - && (thd->master_access & SUPER_ACL) + && (thd->security_ctx->master_access & SUPER_ACL) #endif ) { @@ -1935,10 +1935,12 @@ bool MYSQL_LOG::write(THD *thd,const char *query, uint query_length, tmp_errno=errno; } if (my_b_printf(&log_file, "# User@Host: %s[%s] @ %s [%s]\n", - thd->priv_user ? thd->priv_user : "", - thd->user ? thd->user : "", - thd->host ? thd->host : "", - thd->ip ? thd->ip : "") == (uint) -1) + thd->security_ctx->priv_user ? + thd->security_ctx->priv_user : "", + thd->security_ctx->user ? thd->security_ctx->user : "", + thd->security_ctx->host ? thd->security_ctx->host : "", + thd->security_ctx->ip ? thd->security_ctx->ip : "") == + (uint) -1) tmp_errno=errno; } if (query_start_arg) diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 2d45360ab64..059b9cca48e 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -484,6 +484,7 @@ typedef my_bool (*qc_engine_callback)(THD *thd, char *table_key, #include "protocol.h" #include "sql_udf.h" class user_var_entry; +class st_security_context; enum enum_var_type { OPT_DEFAULT= 0, OPT_SESSION, OPT_GLOBAL @@ -515,7 +516,7 @@ bool delete_precheck(THD *thd, TABLE_LIST *tables); bool insert_precheck(THD *thd, TABLE_LIST *tables); bool create_table_precheck(THD *thd, TABLE_LIST *tables, TABLE_LIST *create_table); -bool default_view_definer(THD *thd, st_lex_user *definer); +bool default_view_definer(st_security_context *sctx, st_lex_user *definer); enum enum_mysql_completiontype { diff --git a/sql/mysqld.cc b/sql/mysqld.cc index a28ae38c675..daabb53a39d 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -776,7 +776,9 @@ static void close_connections(void) { if (global_system_variables.log_warnings) sql_print_warning(ER(ER_FORCING_CLOSE),my_progname, - tmp->thread_id,tmp->user ? tmp->user : ""); + tmp->thread_id, + (tmp->security_ctx->user ? + tmp->security_ctx->user : "")); close_connection(tmp,0,0); } #endif @@ -3582,7 +3584,7 @@ static void bootstrap(FILE *file) thd->client_capabilities=0; my_net_init(&thd->net,(st_vio*) 0); thd->max_client_packet_length= thd->net.max_packet; - thd->master_access= ~(ulong)0; + thd->security_ctx->master_access= ~(ulong)0; thd->thread_id=thread_id++; thread_count++; @@ -3922,7 +3924,7 @@ extern "C" pthread_handler_decl(handle_connections_sockets, continue; } if (sock == unix_sock) - thd->host=(char*) my_localhost; + thd->security_ctx->host=(char*) my_localhost; #ifdef __WIN__ /* Set default wait_timeout */ ulong wait_timeout= global_system_variables.net_wait_timeout * 1000; diff --git a/sql/repl_failsafe.cc b/sql/repl_failsafe.cc index 59e29d1d80c..d4d26c2ccf1 100644 --- a/sql/repl_failsafe.cc +++ b/sql/repl_failsafe.cc @@ -66,13 +66,11 @@ static int init_failsafe_rpl_thread(THD* thd) this thread has no other error reporting method). */ thd->system_thread = thd->bootstrap = 1; - thd->host_or_ip= ""; + thd->security_ctx->skip_grants(); thd->client_capabilities = 0; my_net_init(&thd->net, 0); thd->net.read_timeout = slave_net_timeout; thd->max_client_packet_length=thd->net.max_packet; - thd->master_access= ~(ulong)0; - thd->priv_user = 0; pthread_mutex_lock(&LOCK_thread_count); thd->thread_id = thread_id++; pthread_mutex_unlock(&LOCK_thread_count); diff --git a/sql/set_var.cc b/sql/set_var.cc index ff997158941..853f3570003 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -1092,9 +1092,10 @@ static void sys_default_init_slave(THD* thd, enum_var_type type) static int sys_check_ftb_syntax(THD *thd, set_var *var) { - if (thd->master_access & SUPER_ACL) - return ft_boolean_check_syntax_string((byte*) var->value->str_value.c_ptr()) ? - -1 : 0; + if (thd->security_ctx->master_access & SUPER_ACL) + return (ft_boolean_check_syntax_string((byte*) + var->value->str_value.c_ptr()) ? + -1 : 0); else { my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0), "SUPER"); @@ -2689,7 +2690,7 @@ static bool set_option_autocommit(THD *thd, set_var *var) static int check_log_update(THD *thd, set_var *var) { #ifndef NO_EMBEDDED_ACCESS_CHECKS - if (!(thd->master_access & SUPER_ACL)) + if (!(thd->security_ctx->master_access & SUPER_ACL)) { my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0), "SUPER"); return 1; @@ -2735,7 +2736,7 @@ static int check_pseudo_thread_id(THD *thd, set_var *var) { var->save_result.ulonglong_value= var->value->val_int(); #ifndef NO_EMBEDDED_ACCESS_CHECKS - if (thd->master_access & SUPER_ACL) + if (thd->security_ctx->master_access & SUPER_ACL) return 0; else { @@ -3100,10 +3101,10 @@ int set_var_password::check(THD *thd) #ifndef NO_EMBEDDED_ACCESS_CHECKS if (!user->host.str) { - if (thd->priv_host != 0) + if (*thd->security_ctx->priv_host != 0) { - user->host.str= (char *) thd->priv_host; - user->host.length= strlen(thd->priv_host); + user->host.str= (char *) thd->security_ctx->priv_host; + user->host.length= strlen(thd->security_ctx->priv_host); } else { diff --git a/sql/slave.cc b/sql/slave.cc index d2a60076cef..7bbad84debb 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -2809,17 +2809,10 @@ static int init_slave_thread(THD* thd, SLAVE_THD_TYPE thd_type) DBUG_ENTER("init_slave_thread"); thd->system_thread = (thd_type == SLAVE_THD_SQL) ? SYSTEM_THREAD_SLAVE_SQL : SYSTEM_THREAD_SLAVE_IO; - /* - The two next lines are needed for replication of SP (CREATE PROCEDURE - needs a valid user to store in mysql.proc). - */ - thd->priv_user= (char *) ""; - thd->priv_host[0]= '\0'; - thd->host_or_ip= ""; + thd->security_ctx->skip_grants(); thd->client_capabilities = 0; my_net_init(&thd->net, 0); thd->net.read_timeout = slave_net_timeout; - thd->master_access= ~(ulong)0; thd->slave_thread = 1; set_slave_thread_options(thd); /* diff --git a/sql/sp.cc b/sql/sp.cc index 80b18571d7d..4f7b544f5c7 100644 --- a/sql/sp.cc +++ b/sql/sp.cc @@ -494,7 +494,8 @@ db_create_routine(THD *thd, int type, sp_head *sp) else { restore_record(table, s->default_values); // Get default values for fields - strxmov(definer, thd->priv_user, "@", thd->priv_host, NullS); + strxmov(definer, thd->security_ctx->priv_user, "@", + thd->security_ctx->priv_host, NullS); if (table->s->fields != MYSQL_PROC_FIELD_COUNT) { @@ -569,7 +570,7 @@ db_create_routine(THD *thd, int type, sp_head *sp) goto done; } } - if (!(thd->master_access & SUPER_ACL)) + if (!(thd->security_ctx->master_access & SUPER_ACL)) { my_message(ER_BINLOG_CREATE_ROUTINE_NEED_SUPER, ER(ER_BINLOG_CREATE_ROUTINE_NEED_SUPER), MYF(0)); diff --git a/sql/sp_head.cc b/sql/sp_head.cc index 1a7599d7bbc..0d481047849 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -1636,8 +1636,10 @@ bool check_show_routine_access(THD *thd, sp_head *sp, bool *full_access) tables.db= (char*) "mysql"; tables.table_name= tables.alias= (char*) "proc"; *full_access= (!check_table_access(thd, SELECT_ACL, &tables, 1) || - (!strcmp(sp->m_definer_user.str, thd->priv_user) && - !strcmp(sp->m_definer_host.str, thd->priv_host))); + (!strcmp(sp->m_definer_user.str, + thd->security_ctx->priv_user) && + !strcmp(sp->m_definer_host.str, + thd->security_ctx->priv_host))); if (!*full_access) return check_some_routine_access(thd, sp->m_db.str, sp->m_name.str, sp->m_type == TYPE_ENUM_PROCEDURE); @@ -2645,54 +2647,38 @@ sp_instr_error::print(String *str) */ #ifndef NO_EMBEDDED_ACCESS_CHECKS -void -sp_change_security_context(THD *thd, sp_head *sp, st_sp_security_context *ctxp) +bool +sp_change_security_context(THD *thd, sp_head *sp, st_security_context **backup) { - ctxp->changed= (sp->m_chistics->suid != SP_IS_NOT_SUID && - (strcmp(sp->m_definer_user.str, thd->priv_user) || - strcmp(sp->m_definer_host.str, thd->priv_host))); + bool changed= (sp->m_chistics->suid != SP_IS_NOT_SUID && + (strcmp(sp->m_definer_user.str, + thd->security_ctx->priv_user) || + my_strcasecmp(system_charset_info, sp->m_definer_host.str, + thd->security_ctx->priv_host))); - if (ctxp->changed) + *backup= 0; + if (changed) { - ctxp->master_access= thd->master_access; - ctxp->db_access= thd->db_access; - ctxp->priv_user= thd->priv_user; - strncpy(ctxp->priv_host, thd->priv_host, sizeof(ctxp->priv_host)); - ctxp->user= thd->user; - ctxp->host= thd->host; - ctxp->ip= thd->ip; - - /* Change thise just to do the acl_getroot_no_password */ - thd->user= sp->m_definer_user.str; - thd->host= thd->ip = sp->m_definer_host.str; - - if (acl_getroot_no_password(thd)) - { // Failed, run as invoker for now - ctxp->changed= FALSE; - thd->master_access= ctxp->master_access; - thd->db_access= ctxp->db_access; - thd->priv_user= ctxp->priv_user; - strncpy(thd->priv_host, ctxp->priv_host, sizeof(thd->priv_host)); + if (acl_getroot_no_password(&sp->m_security_ctx, sp->m_definer_user.str, + sp->m_definer_host.str, + sp->m_definer_host.str, + sp->m_db.str)) + { + my_error(ER_NO_SUCH_USER, MYF(0), sp->m_definer_user.str, + sp->m_definer_host.str); + return TRUE; } - - /* Restore these immiediately */ - thd->user= ctxp->user; - thd->host= ctxp->host; - thd->ip= ctxp->ip; + *backup= thd->security_ctx; + thd->security_ctx= &sp->m_security_ctx; } + return FALSE; } void -sp_restore_security_context(THD *thd, sp_head *sp, st_sp_security_context *ctxp) +sp_restore_security_context(THD *thd, st_security_context *backup) { - if (ctxp->changed) - { - ctxp->changed= FALSE; - thd->master_access= ctxp->master_access; - thd->db_access= ctxp->db_access; - thd->priv_user= ctxp->priv_user; - strncpy(thd->priv_host, ctxp->priv_host, sizeof(thd->priv_host)); - } + if (backup) + thd->security_ctx= backup; } #endif /* NO_EMBEDDED_ACCESS_CHECKS */ diff --git a/sql/sp_head.h b/sql/sp_head.h index 9888fe74149..ccf8c48a5eb 100644 --- a/sql/sp_head.h +++ b/sql/sp_head.h @@ -151,6 +151,9 @@ public: // Pointers set during parsing uchar *m_param_begin, *m_param_end, *m_body_begin; + /* security context for SP procedure/function in case we switch it*/ + st_security_context m_security_ctx; + static void * operator new(size_t size); @@ -1017,23 +1020,12 @@ private: }; // class sp_instr_error : public sp_instr -struct st_sp_security_context -{ - bool changed; - uint master_access; - uint db_access; - char *priv_user; - char priv_host[MAX_HOSTNAME]; - char *user; - char *host; - char *ip; -}; - #ifndef NO_EMBEDDED_ACCESS_CHECKS +bool +sp_change_security_context(THD *thd, sp_head *sp, + st_security_context **backup); void -sp_change_security_context(THD *thd, sp_head *sp, st_sp_security_context *ctxp); -void -sp_restore_security_context(THD *thd, sp_head *sp,st_sp_security_context *ctxp); +sp_restore_security_context(THD *thd, st_security_context *backup); #endif /* NO_EMBEDDED_ACCESS_CHECKS */ TABLE_LIST * diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 5e2fd17377a..95f7fed358d 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -719,6 +719,7 @@ int acl_getroot(THD *thd, USER_RESOURCES *mqh, ulong user_access= NO_ACCESS; int res= 1; ACL_USER *acl_user= 0; + st_security_context *sctx= thd->security_ctx; DBUG_ENTER("acl_getroot"); if (!initialized) @@ -726,10 +727,7 @@ int acl_getroot(THD *thd, USER_RESOURCES *mqh, /* here if mysqld's been started with --skip-grant-tables option. */ - thd->priv_user= (char *) ""; // privileges for - *thd->priv_host= '\0'; // the user are unknown - thd->master_access= ~NO_ACCESS; // everything is allowed - bzero((char*) mqh, sizeof(*mqh)); + sctx->skip_grants(); DBUG_RETURN(0); } @@ -744,9 +742,9 @@ int acl_getroot(THD *thd, USER_RESOURCES *mqh, for (uint i=0 ; i < acl_users.elements ; i++) { ACL_USER *acl_user_tmp= dynamic_element(&acl_users,i,ACL_USER*); - if (!acl_user_tmp->user || !strcmp(thd->user, acl_user_tmp->user)) + if (!acl_user_tmp->user || !strcmp(sctx->user, acl_user_tmp->user)) { - if (compare_hostname(&acl_user_tmp->host, thd->host, thd->ip)) + if (compare_hostname(&acl_user_tmp->host, sctx->host, sctx->ip)) { /* check password: it should be empty or valid */ if (passwd_len == acl_user_tmp->salt_len) @@ -893,14 +891,14 @@ int acl_getroot(THD *thd, USER_RESOURCES *mqh, break; #endif /* HAVE_OPENSSL */ } - thd->master_access= user_access; - thd->priv_user= acl_user->user ? thd->user : (char *) ""; + sctx->master_access= user_access; + sctx->priv_user= acl_user->user ? sctx->user : (char *) ""; *mqh= acl_user->user_resource; if (acl_user->host.hostname) - strmake(thd->priv_host, acl_user->host.hostname, MAX_HOSTNAME); + strmake(sctx->priv_host, acl_user->host.hostname, MAX_HOSTNAME); else - *thd->priv_host= 0; + *sctx->priv_host= 0; } VOID(pthread_mutex_unlock(&acl_cache->lock)); DBUG_RETURN(res); @@ -913,42 +911,46 @@ int acl_getroot(THD *thd, USER_RESOURCES *mqh, * Used to get access rights for SQL SECURITY DEFINER invocation of * stored procedures. */ -int acl_getroot_no_password(THD *thd) +int acl_getroot_no_password(st_security_context *sctx, char *user, char *host, + char *ip, char *db) { int res= 1; uint i; ACL_USER *acl_user= 0; DBUG_ENTER("acl_getroot_no_password"); + sctx->user= user; + sctx->host= host; + sctx->ip= ip; + sctx->host_or_ip= host ? host : (ip ? ip : ""); + if (!initialized) { - /* + /* here if mysqld's been started with --skip-grant-tables option. */ - thd->priv_user= (char *) ""; // privileges for - *thd->priv_host= '\0'; // the user are unknown - thd->master_access= ~NO_ACCESS; // everything is allowed + sctx->skip_grants(); DBUG_RETURN(0); } VOID(pthread_mutex_lock(&acl_cache->lock)); - thd->master_access= 0; - thd->db_access= 0; + sctx->master_access= 0; + sctx->db_access= 0; /* Find acl entry in user database. This is specially tailored to suit the check we do for CALL of - a stored procedure; thd->user is set to what is actually a + a stored procedure; user is set to what is actually a priv_user, which can be ''. */ for (i=0 ; i < acl_users.elements ; i++) { acl_user= dynamic_element(&acl_users,i,ACL_USER*); - if ((!acl_user->user && (!thd->user || !thd->user[0])) || - (acl_user->user && strcmp(thd->user, acl_user->user) == 0)) + if ((!acl_user->user && (!user || !user[0])) || + (acl_user->user && strcmp(user, acl_user->user) == 0)) { - if (compare_hostname(&acl_user->host, thd->host, thd->ip)) + if (compare_hostname(&acl_user->host, host, ip)) { res= 0; break; @@ -962,25 +964,25 @@ int acl_getroot_no_password(THD *thd) { ACL_DB *acl_db= dynamic_element(&acl_dbs, i, ACL_DB*); if (!acl_db->user || - (thd->user && thd->user[0] && !strcmp(thd->user, acl_db->user))) + (user && user[0] && !strcmp(user, acl_db->user))) { - if (compare_hostname(&acl_db->host, thd->host, thd->ip)) + if (compare_hostname(&acl_db->host, host, ip)) { - if (!acl_db->db || (thd->db && !strcmp(acl_db->db, thd->db))) + if (!acl_db->db || (db && !strcmp(acl_db->db, db))) { - thd->db_access= acl_db->access; + sctx->db_access= acl_db->access; break; } } } } - thd->master_access= acl_user->access; - thd->priv_user= acl_user->user ? thd->user : (char *) ""; + sctx->master_access= acl_user->access; + sctx->priv_user= acl_user->user ? user : (char *) ""; if (acl_user->host.hostname) - strmake(thd->priv_host, acl_user->host.hostname, MAX_HOSTNAME); + strmake(sctx->priv_host, acl_user->host.hostname, MAX_HOSTNAME); else - *thd->priv_host= 0; + *sctx->priv_host= 0; } VOID(pthread_mutex_unlock(&acl_cache->lock)); DBUG_RETURN(res); @@ -1334,13 +1336,14 @@ bool check_change_password(THD *thd, const char *host, const char *user, return(1); } if (!thd->slave_thread && - (strcmp(thd->user,user) || - my_strcasecmp(system_charset_info, host, thd->priv_host))) + (strcmp(thd->security_ctx->user, user) || + my_strcasecmp(system_charset_info, host, + thd->security_ctx->priv_host))) { if (check_access(thd, UPDATE_ACL, "mysql",0,1,0,0)) return(1); } - if (!thd->slave_thread && !thd->user[0]) + if (!thd->slave_thread && !thd->security_ctx->user[0]) { my_message(ER_PASSWORD_ANONYMOUS_USER, ER(ER_PASSWORD_ANONYMOUS_USER), MYF(0)); @@ -1646,9 +1649,10 @@ static bool update_user_table(THD *thd, TABLE *table, static bool test_if_create_new_users(THD *thd) { - bool create_new_users= test(thd->master_access & INSERT_ACL) || + st_security_context *sctx= thd->security_ctx; + bool create_new_users= test(sctx->master_access & INSERT_ACL) || (!opt_safe_user_create && - test(thd->master_access & CREATE_USER_ACL)); + test(sctx->master_access & CREATE_USER_ACL)); if (!create_new_users) { TABLE_LIST tl; @@ -1658,8 +1662,8 @@ static bool test_if_create_new_users(THD *thd) tl.table_name= (char*) "user"; create_new_users= 1; - db_access=acl_get(thd->host, thd->ip, - thd->priv_user, tl.db, 0); + db_access=acl_get(sctx->host, sctx->ip, + sctx->priv_user, tl.db, 0); if (!(db_access & INSERT_ACL)) { if (check_grant(thd, INSERT_ACL, &tl, 0, UINT_MAX, 1)) @@ -1738,7 +1742,7 @@ static int replace_user_table(THD *thd, TABLE *table, const LEX_USER &combo, else if (!can_create_user) { my_error(ER_CANT_CREATE_USER_WITH_GRANT, MYF(0), - thd->user, thd->host_or_ip); + thd->security_ctx->user, thd->security_ctx->host_or_ip); goto end; } old_row_exists = 0; @@ -2450,7 +2454,8 @@ static int replace_table_table(THD *thd, GRANT_TABLE *grant_table, byte user_key[MAX_KEY_LENGTH]; DBUG_ENTER("replace_table_table"); - strxmov(grantor, thd->user, "@", thd->host_or_ip, NullS); + strxmov(grantor, thd->security_ctx->user, "@", + thd->security_ctx->host_or_ip, NullS); /* The following should always succeed as new users are created before @@ -2572,7 +2577,8 @@ static int replace_routine_table(THD *thd, GRANT_NAME *grant_name, DBUG_RETURN(-1); } - strxmov(grantor, thd->user, "@", thd->host_or_ip, NullS); + strxmov(grantor, thd->security_ctx->user, "@", + thd->security_ctx->host_or_ip, NullS); /* The following should always succeed as new users are created before @@ -2763,7 +2769,8 @@ bool mysql_table_grant(THD *thd, TABLE_LIST *table_list, get_privilege_desc(command, sizeof(command), table_list->grant.want_privilege); my_error(ER_TABLEACCESS_DENIED_ERROR, MYF(0), - command, thd->priv_user, thd->host_or_ip, table_list->alias); + command, thd->security_ctx->priv_user, + thd->security_ctx->host_or_ip, table_list->alias); DBUG_RETURN(-1); } } @@ -3486,11 +3493,11 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables, uint show_table, uint number, bool no_errors) { TABLE_LIST *table; - char *user = thd->priv_user; + st_security_context *sctx= thd->security_ctx; DBUG_ENTER("check_grant"); DBUG_ASSERT(number > 0); - want_access&= ~thd->master_access; + want_access&= ~sctx->master_access; if (!want_access) DBUG_RETURN(0); // ok @@ -3508,8 +3515,9 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables, table->grant.want_privilege= 0; continue; // Already checked } - if (!(grant_table= table_hash_search(thd->host,thd->ip, - table->db,user, table->table_name,0))) + if (!(grant_table= table_hash_search(sctx->host, sctx->ip, + table->db, sctx->priv_user, + table->table_name,0))) { want_access &= ~table->grant.privilege; goto err; // No grants @@ -3543,8 +3551,8 @@ err: get_privilege_desc(command, sizeof(command), want_access); my_error(ER_TABLEACCESS_DENIED_ERROR, MYF(0), command, - thd->priv_user, - thd->host_or_ip, + sctx->priv_user, + sctx->host_or_ip, table ? table->table_name : "unknown"); } DBUG_RETURN(1); @@ -3555,6 +3563,7 @@ bool check_grant_column(THD *thd, GRANT_INFO *grant, const char *db_name, const char *table_name, const char *name, uint length, uint show_tables) { + st_security_context *sctx= thd->security_ctx; GRANT_TABLE *grant_table; GRANT_COLUMN *grant_column; ulong want_access= grant->want_privilege & ~grant->privilege; @@ -3571,8 +3580,8 @@ bool check_grant_column(THD *thd, GRANT_INFO *grant, if (grant->version != grant_version) { grant->grant_table= - table_hash_search(thd->host, thd->ip, db_name, - thd->priv_user, + table_hash_search(sctx->host, sctx->ip, db_name, + sctx->priv_user, table_name, 0); /* purecov: inspected */ grant->version= grant_version; /* purecov: inspected */ } @@ -3601,8 +3610,8 @@ err: get_privilege_desc(command, sizeof(command), want_access); my_error(ER_COLUMNACCESS_DENIED_ERROR, MYF(0), command, - thd->priv_user, - thd->host_or_ip, + sctx->priv_user, + sctx->host_or_ip, name, table_name); } @@ -3614,6 +3623,7 @@ bool check_grant_all_columns(THD *thd, ulong want_access, GRANT_INFO *grant, const char* db_name, const char *table_name, Field_iterator *fields) { + st_security_context *sctx= thd->security_ctx; GRANT_TABLE *grant_table; GRANT_COLUMN *grant_column; @@ -3630,8 +3640,8 @@ bool check_grant_all_columns(THD *thd, ulong want_access, GRANT_INFO *grant, if (grant->version != grant_version) { grant->grant_table= - table_hash_search(thd->host, thd->ip, db_name, - thd->priv_user, + table_hash_search(sctx->host, sctx->ip, db_name, + sctx->priv_user, table_name, 0); /* purecov: inspected */ grant->version= grant_version; /* purecov: inspected */ } @@ -3657,8 +3667,8 @@ err2: get_privilege_desc(command, sizeof(command), want_access); my_error(ER_COLUMNACCESS_DENIED_ERROR, MYF(0), command, - thd->priv_user, - thd->host_or_ip, + sctx->priv_user, + sctx->host_or_ip, fields->name(), table_name); return 1; @@ -3673,11 +3683,12 @@ err2: bool check_grant_db(THD *thd,const char *db) { + st_security_context *sctx= thd->security_ctx; char helping [NAME_LEN+USERNAME_LENGTH+2]; uint len; bool error= 1; - len= (uint) (strmov(strmov(helping,thd->priv_user)+1,db)-helping)+ 1; + len= (uint) (strmov(strmov(helping, sctx->priv_user) + 1, db) - helping) + 1; rw_rdlock(&LOCK_grant); for (uint idx=0 ; idx < column_priv_hash.records ; idx++) @@ -3686,7 +3697,7 @@ bool check_grant_db(THD *thd,const char *db) idx); if (len < grant_table->key_length && !memcmp(grant_table->hash_key,helping,len) && - compare_hostname(&grant_table->host, thd->host, thd->ip)) + compare_hostname(&grant_table->host, sctx->host, sctx->ip)) { error=0; // Found match break; @@ -3714,15 +3725,16 @@ bool check_grant_db(THD *thd,const char *db) 1 Error: User did not have the requested privielges ****************************************************************************/ -bool check_grant_routine(THD *thd, ulong want_access, +bool check_grant_routine(THD *thd, ulong want_access, TABLE_LIST *procs, bool is_proc, bool no_errors) { TABLE_LIST *table; - char *user= thd->priv_user; - char *host= thd->priv_host; + st_security_context *sctx= thd->security_ctx; + char *user= sctx->priv_user; + char *host= sctx->priv_host; DBUG_ENTER("check_grant_routine"); - want_access&= ~thd->master_access; + want_access&= ~sctx->master_access; if (!want_access) DBUG_RETURN(0); // ok @@ -3730,7 +3742,7 @@ 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,thd->ip, table->db, user, + if ((grant_proc= routine_hash_search(host, sctx->ip, table->db, user, table->table_name, is_proc, 0))) table->grant.privilege|= grant_proc->privs; @@ -3786,8 +3798,10 @@ bool check_routine_level_acl(THD *thd, const char *db, const char *name, { GRANT_NAME *grant_proc; rw_rdlock(&LOCK_grant); - if ((grant_proc= routine_hash_search(thd->priv_host, thd->ip, db, - thd->priv_user, name, is_proc, 0))) + if ((grant_proc= routine_hash_search(thd->security_ctx->priv_host, + thd->security_ctx->ip, db, + thd->security_ctx->priv_user, + name, is_proc, 0))) no_routine_acl= !(grant_proc->privs & SHOW_PROC_ACLS); rw_unlock(&LOCK_grant); } @@ -3802,7 +3816,7 @@ bool check_routine_level_acl(THD *thd, const char *db, const char *name, ulong get_table_grant(THD *thd, TABLE_LIST *table) { ulong privilege; - char *user = thd->priv_user; + st_security_context *sctx= thd->security_ctx; const char *db = table->db ? table->db : thd->db; GRANT_TABLE *grant_table; @@ -3810,7 +3824,7 @@ ulong get_table_grant(THD *thd, TABLE_LIST *table) #ifdef EMBEDDED_LIBRARY grant_table= NULL; #else - grant_table= table_hash_search(thd->host, thd->ip, db, user, + grant_table= table_hash_search(sctx->host, sctx->ip, db, sctx->priv_user, table->table_name, 0); #endif table->grant.grant_table=grant_table; // Remember for column test @@ -3854,8 +3868,8 @@ ulong get_column_grant(THD *thd, GRANT_INFO *grant, if (grant->version != grant_version) { grant->grant_table= - table_hash_search(thd->host, thd->ip, db_name, - thd->priv_user, + table_hash_search(thd->security_ctx->host, thd->security_ctx->ip, + db_name, thd->security_ctx->priv_user, table_name, 0); /* purecov: inspected */ grant->version= grant_version; /* purecov: inspected */ } @@ -5425,22 +5439,24 @@ 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) { + st_security_context *sctx= thd->security_ctx; LEX_USER *combo; TABLE_LIST tables[1]; List<LEX_USER> user_list; bool result; - DBUG_ENTER("sp_grant_privileges"); + DBUG_ENTER("sp_grant_privileges"); if (!(combo=(LEX_USER*) thd->alloc(sizeof(st_lex_user)))) DBUG_RETURN(TRUE); - combo->user.str= thd->user; + combo->user.str= sctx->user; - if (!find_acl_user(combo->host.str=(char*)thd->host_or_ip, combo->user.str, + if (!find_acl_user(combo->host.str=(char*)sctx->host_or_ip, combo->user.str, + FALSE) && + !find_acl_user(combo->host.str=(char*)sctx->host, combo->user.str, FALSE) && - !find_acl_user(combo->host.str=(char*)thd->host, combo->user.str, + !find_acl_user(combo->host.str=(char*)sctx->ip, combo->user.str, FALSE) && - !find_acl_user(combo->host.str=(char*)thd->ip, combo->user.str, FALSE) && !find_acl_user(combo->host.str=(char*)"%", combo->user.str, FALSE)) DBUG_RETURN(TRUE); @@ -5557,7 +5573,7 @@ int fill_schema_user_privileges(THD *thd, TABLE_LIST *tables, COND *cond) char buff[100]; TABLE *table= tables->table; bool no_global_access= check_access(thd, SELECT_ACL, "mysql",0,1,1,0); - char *curr_host= thd->priv_host ? thd->priv_host : (char *) "%"; + char *curr_host= thd->security_ctx->get_priv_host(); DBUG_ENTER("fill_schema_user_privileges"); for (counter=0 ; counter < acl_users.elements ; counter++) @@ -5570,7 +5586,7 @@ int fill_schema_user_privileges(THD *thd, TABLE_LIST *tables, COND *cond) host= ""; if (no_global_access && - (strcmp(thd->priv_user, user) || + (strcmp(thd->security_ctx->priv_user, user) || my_strcasecmp(system_charset_info, curr_host, host))) continue; @@ -5610,7 +5626,7 @@ int fill_schema_schema_privileges(THD *thd, TABLE_LIST *tables, COND *cond) char buff[100]; TABLE *table= tables->table; bool no_global_access= check_access(thd, SELECT_ACL, "mysql",0,1,1,0); - char *curr_host= thd->priv_host ? thd->priv_host : (char *) "%"; + char *curr_host= thd->security_ctx->get_priv_host(); DBUG_ENTER("fill_schema_schema_privileges"); for (counter=0 ; counter < acl_dbs.elements ; counter++) @@ -5624,7 +5640,7 @@ int fill_schema_schema_privileges(THD *thd, TABLE_LIST *tables, COND *cond) host= ""; if (no_global_access && - (strcmp(thd->priv_user, user) || + (strcmp(thd->security_ctx->priv_user, user) || my_strcasecmp(system_charset_info, curr_host, host))) continue; @@ -5665,7 +5681,7 @@ int fill_schema_table_privileges(THD *thd, TABLE_LIST *tables, COND *cond) char buff[100]; TABLE *table= tables->table; bool no_global_access= check_access(thd, SELECT_ACL, "mysql",0,1,1,0); - char *curr_host= thd->priv_host ? thd->priv_host : (char *) "%"; + char *curr_host= thd->security_ctx->get_priv_host(); DBUG_ENTER("fill_schema_table_privileges"); for (index=0 ; index < column_priv_hash.records ; index++) @@ -5677,7 +5693,7 @@ int fill_schema_table_privileges(THD *thd, TABLE_LIST *tables, COND *cond) user= ""; if (no_global_access && - (strcmp(thd->priv_user, user) || + (strcmp(thd->security_ctx->priv_user, user) || my_strcasecmp(system_charset_info, curr_host, grant_table->host.hostname))) continue; @@ -5727,7 +5743,7 @@ int fill_schema_column_privileges(THD *thd, TABLE_LIST *tables, COND *cond) char buff[100]; TABLE *table= tables->table; bool no_global_access= check_access(thd, SELECT_ACL, "mysql",0,1,1,0); - char *curr_host= thd->priv_host ? thd->priv_host : (char *) "%"; + char *curr_host= thd->security_ctx->get_priv_host(); DBUG_ENTER("fill_schema_table_privileges"); for (index=0 ; index < column_priv_hash.records ; index++) @@ -5739,7 +5755,7 @@ int fill_schema_column_privileges(THD *thd, TABLE_LIST *tables, COND *cond) user= ""; if (no_global_access && - (strcmp(thd->priv_user, user) || + (strcmp(thd->security_ctx->priv_user, user) || my_strcasecmp(system_charset_info, curr_host, grant_table->host.hostname))) continue; @@ -5803,6 +5819,7 @@ int fill_schema_column_privileges(THD *thd, TABLE_LIST *tables, COND *cond) void fill_effective_table_privileges(THD *thd, GRANT_INFO *grant, const char *db, const char *table) { + st_security_context *sctx= thd->security_ctx; /* --skip-grants */ if (!initialized) { @@ -5811,13 +5828,13 @@ void fill_effective_table_privileges(THD *thd, GRANT_INFO *grant, } /* global privileges */ - grant->privilege= thd->master_access; + grant->privilege= sctx->master_access; - if (!thd->priv_user) + if (!sctx->priv_user) return; // it is slave /* db privileges */ - grant->privilege|= acl_get(thd->host, thd->ip, thd->priv_user, db, 0); + grant->privilege|= acl_get(sctx->host, sctx->ip, sctx->priv_user, db, 0); if (!grant_option) return; @@ -5827,8 +5844,8 @@ void fill_effective_table_privileges(THD *thd, GRANT_INFO *grant, { rw_rdlock(&LOCK_grant); grant->grant_table= - table_hash_search(thd->host, thd->ip, db, - thd->priv_user, + table_hash_search(sctx->host, sctx->ip, db, + sctx->priv_user, table, 0); /* purecov: inspected */ grant->version= grant_version; /* purecov: inspected */ rw_unlock(&LOCK_grant); diff --git a/sql/sql_acl.h b/sql/sql_acl.h index 344302de9be..f62f3c12b28 100644 --- a/sql/sql_acl.h +++ b/sql/sql_acl.h @@ -181,7 +181,8 @@ ulong acl_get(const char *host, const char *ip, const char *user, const char *db, my_bool db_is_pattern); int acl_getroot(THD *thd, USER_RESOURCES *mqh, const char *passwd, uint passwd_len); -int acl_getroot_no_password(THD *thd); +int acl_getroot_no_password(st_security_context *sctx, char *user, char *host, + char *ip, char *db); bool acl_check_host(const char *host, const char *ip); bool check_change_password(THD *thd, const char *host, const char *user, char *password, uint password_len); diff --git a/sql/sql_base.cc b/sql/sql_base.cc index fb23093731a..1b8d65e21f0 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -4572,7 +4572,8 @@ insert_fields(THD *thd, Name_resolution_context *context, const char *db_name, VIEW_ANY_ACL))) { my_error(ER_COLUMNACCESS_DENIED_ERROR, MYF(0), "ANY", - thd->priv_user, thd->host_or_ip, + thd->security_ctx->priv_user, + thd->security_ctx->host_or_ip, fld->field_name, field_table_name); DBUG_RETURN(TRUE); } diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 2699a4fa628..85bf520b56e 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -181,9 +181,10 @@ THD::THD() spcont(NULL) { stmt_arena= this; - host= user= priv_user= db= ip= 0; + db= 0; catalog= (char*)"std"; // the only catalog we have for now - host_or_ip= "connecting host"; + main_security_ctx.init(); + security_ctx= &main_security_ctx; locked=some_tables_deleted=no_errors=password= 0; query_start_used= 0; count_cuted_fields= CHECK_FIELD_IGNORE; @@ -236,9 +237,6 @@ THD::THD() server_id = ::server_id; slave_net = 0; command=COM_CONNECT; -#ifndef NO_EMBEDDED_ACCESS_CHECKS - db_access=NO_ACCESS; -#endif *scramble= '\0'; init(); @@ -426,12 +424,8 @@ THD::~THD() ha_close_connection(this); - DBUG_PRINT("info", ("freeing host")); - if (host != my_localhost) // If not pointer to constant - safeFree(host); - if (user != delayed_user) - safeFree(user); - safeFree(ip); + DBUG_PRINT("info", ("freeing security context")); + main_security_ctx.destroy(); safeFree(db); free_root(&warn_root,MYF(0)); #ifdef USING_TRANSACTIONS @@ -1827,6 +1821,38 @@ void THD::set_status_var_init() bzero((char*) &status_var, sizeof(status_var)); } + +void st_security_context::init() +{ + host= user= priv_user= ip= 0; + host_or_ip= "connecting host"; +#ifndef NO_EMBEDDED_ACCESS_CHECKS + db_access= NO_ACCESS; +#endif +} + + +void st_security_context::destroy() +{ + // If not pointer to constant + if (host != my_localhost) + safeFree(host); + if (user != delayed_user) + safeFree(user); + safeFree(ip); +} + + +void st_security_context::skip_grants() +{ + /* privileges for the user are unknown everything is allowed */ + host_or_ip= (char *)""; + master_access= ~NO_ACCESS; + priv_user= (char *)""; + *priv_host= '\0'; +} + + /**************************************************************************** Handling of open and locked tables states. diff --git a/sql/sql_class.h b/sql/sql_class.h index 1a215d39841..ddc8b092311 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -941,6 +941,32 @@ bool xid_cache_insert(XID *xid, enum xa_states xa_state); bool xid_cache_insert(XID_STATE *xid_state); void xid_cache_delete(XID_STATE *xid_state); + +struct st_security_context { + /* + host - host of the client + user - user of the client, set to NULL until the user has been read from + the connection + priv_user - The user privilege we are using. May be '' for anonymous user. + ip - client IP + */ + char *host, *user, *priv_user, *ip; + char priv_host[MAX_HOSTNAME]; + /* points to host if host is available, otherwise points to ip */ + const char *host_or_ip; + ulong master_access; /* Global privileges from mysql.user */ + ulong db_access; /* Privileges for current db */ + + void init(); + void destroy(); + void skip_grants(); + inline char *get_priv_host() + { + return (*priv_host ? priv_host : (char *)"%"); + } +}; + + /* A registry for item tree transformations performed during query optimization. We register only those changes which require @@ -1113,13 +1139,8 @@ public: char *thread_stack; /* - host - host of the client - user - user of the client, set to NULL until the user has been read from - the connection - priv_user - The user privilege we are using. May be '' for anonymous user. db - currently selected database catalog - currently selected catalog - ip - client IP WARNING: some members of THD (currently 'db', 'catalog' and 'query') are set and alloced by the slave SQL thread (for the THD of that thread); that thread is (and must remain, for now) the only responsible for freeing these @@ -1128,8 +1149,10 @@ public: properly. For details see the 'err:' label of the pthread_handler_decl of the slave SQL thread, in sql/slave.cc. */ - char *host,*user,*priv_user,*db,*catalog,*ip; - char priv_host[MAX_HOSTNAME]; + char *db, *catalog; + st_security_context main_security_ctx; + st_security_context *security_ctx; + /* remote (peer) port */ uint16 peer_port; /* @@ -1138,13 +1161,9 @@ public: a time-consuming piece that MySQL can get stuck in for a long time. */ const char *proc_info; - /* points to host if host is available, otherwise points to ip */ - const char *host_or_ip; ulong client_capabilities; /* What the client supports */ ulong max_client_packet_length; - ulong master_access; /* Global privileges from mysql.user */ - ulong db_access; /* Privileges for current db */ HASH handler_tables_hash; /* diff --git a/sql/sql_db.cc b/sql/sql_db.cc index 69ccbe690db..e4d8c1b8164 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -1093,6 +1093,7 @@ bool mysql_change_db(THD *thd, const char *name, bool no_access_check) bool system_db= 0; #ifndef NO_EMBEDDED_ACCESS_CHECKS ulong db_access; + st_security_context *sctx= thd->security_ctx; #endif DBUG_ENTER("mysql_change_db"); DBUG_PRINT("enter",("name: '%s'",name)); @@ -1130,22 +1131,20 @@ bool mysql_change_db(THD *thd, const char *name, bool no_access_check) #ifndef NO_EMBEDDED_ACCESS_CHECKS if (!no_access_check) { - if (test_all_bits(thd->master_access,DB_ACLS)) + if (test_all_bits(sctx->master_access,DB_ACLS)) db_access=DB_ACLS; else - db_access= (acl_get(thd->host,thd->ip, thd->priv_user,dbname,0) | - thd->master_access); + db_access= (acl_get(sctx->host, sctx->ip, sctx->priv_user, dbname, 0) | + sctx->master_access); if (!(db_access & DB_ACLS) && (!grant_option || check_grant_db(thd,dbname))) { my_error(ER_DBACCESS_DENIED_ERROR, MYF(0), - thd->priv_user, - thd->priv_host, + sctx->priv_user, + sctx->priv_host, dbname); - mysql_log.write(thd,COM_INIT_DB,ER(ER_DBACCESS_DENIED_ERROR), - thd->priv_user, - thd->priv_host, - dbname); + mysql_log.write(thd, COM_INIT_DB, ER(ER_DBACCESS_DENIED_ERROR), + sctx->priv_user, sctx->priv_host, dbname); my_free(dbname,MYF(0)); DBUG_RETURN(1); } @@ -1167,7 +1166,7 @@ end: thd->db_length=db_length; #ifndef NO_EMBEDDED_ACCESS_CHECKS if (!no_access_check) - thd->db_access=db_access; + sctx->db_access=db_access; #endif if (system_db) { diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index f548a917bf8..cc4b291b5d1 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -272,7 +272,8 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, By default, both logs are enabled (this won't cause problems if the server runs without --log-update or --log-bin). */ - bool log_on= (thd->options & OPTION_BIN_LOG) || (!(thd->master_access & SUPER_ACL)); + bool log_on= (thd->options & OPTION_BIN_LOG) || + (!(thd->security_ctx->master_access & SUPER_ACL)); bool transactional_table; uint value_count; ulong counter = 1; @@ -1264,8 +1265,8 @@ public: table(0),tables_in_use(0),stacked_inserts(0), status(0), dead(0), group_count(0) { - thd.user=thd.priv_user=(char*) delayed_user; - thd.host=(char*) my_localhost; + thd.security_ctx->user=thd.security_ctx->priv_user=(char*) delayed_user; + thd.security_ctx->host=(char*) my_localhost; thd.current_tablenr=0; thd.version=refresh_version; thd.command=COM_DELAYED_INSERT; @@ -1275,7 +1276,7 @@ public: bzero((char*) &thd.net, sizeof(thd.net)); // Safety bzero((char*) &table_list, sizeof(table_list)); // Safety thd.system_thread= SYSTEM_THREAD_DELAYED_INSERT; - thd.host_or_ip= ""; + thd.security_ctx->host_or_ip= ""; bzero((char*) &info,sizeof(info)); pthread_mutex_init(&mutex,MY_MUTEX_INIT_FAST); pthread_cond_init(&cond,NULL); @@ -1298,7 +1299,7 @@ public: pthread_cond_destroy(&cond_client); thd.unlink(); // Must be unlinked under lock x_free(thd.query); - thd.user=thd.host=0; + thd.security_ctx->user= thd.security_ctx->host=0; thread_count--; delayed_insert_threads--; VOID(pthread_mutex_unlock(&LOCK_thread_count)); diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index e83530b7239..d056215c19b 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -270,10 +270,11 @@ int check_user(THD *thd, enum enum_server_command command, const char *passwd, uint passwd_len, const char *db, bool check_count) { + st_security_context *sctx= thd->security_ctx; DBUG_ENTER("check_user"); #ifdef NO_EMBEDDED_ACCESS_CHECKS - thd->master_access= GLOBAL_ACLS; // Full rights + sctx->master_access= GLOBAL_ACLS; // Full rights /* Change database if necessary */ if (db && db[0]) { @@ -340,9 +341,9 @@ int check_user(THD *thd, enum enum_server_command command, if (opt_secure_auth_local) { net_printf_error(thd, ER_SERVER_IS_IN_SECURE_AUTH_MODE, - thd->user, thd->host_or_ip); + sctx->user, sctx->host_or_ip); mysql_log.write(thd, COM_CONNECT, ER(ER_SERVER_IS_IN_SECURE_AUTH_MODE), - thd->user, thd->host_or_ip); + sctx->user, sctx->host_or_ip); DBUG_RETURN(-1); } /* We have to read very specific packet size */ @@ -360,22 +361,22 @@ int check_user(THD *thd, enum enum_server_command command, /* here res is always >= 0 */ if (res == 0) { - if (!(thd->master_access & NO_ACCESS)) // authentication is OK + if (!(sctx->master_access & NO_ACCESS)) // authentication is OK { DBUG_PRINT("info", ("Capabilities: %d packet_length: %ld Host: '%s' " "Login user: '%s' Priv_user: '%s' Using password: %s " "Access: %u db: '%s'", thd->client_capabilities, thd->max_client_packet_length, - thd->host_or_ip, thd->user, thd->priv_user, + sctx->host_or_ip, sctx->user, sctx->priv_user, passwd_len ? "yes": "no", - thd->master_access, thd->db ? thd->db : "*none*")); + sctx->master_access, thd->db ? thd->db : "*none*")); if (check_count) { VOID(pthread_mutex_lock(&LOCK_thread_count)); bool count_ok= thread_count <= max_connections + delayed_insert_threads - || (thd->master_access & SUPER_ACL); + || (sctx->master_access & SUPER_ACL); VOID(pthread_mutex_unlock(&LOCK_thread_count)); if (!count_ok) { // too many connections @@ -385,11 +386,11 @@ int check_user(THD *thd, enum enum_server_command command, } /* Why logging is performed before all checks've passed? */ - mysql_log.write(thd,command, - (thd->priv_user == thd->user ? + mysql_log.write(thd, command, + (sctx->priv_user == sctx->user ? (char*) "%s@%s on %s" : (char*) "%s@%s as anonymous on %s"), - thd->user, thd->host_or_ip, + sctx->user, sctx->host_or_ip, db ? db : (char*) ""); /* @@ -397,14 +398,14 @@ int check_user(THD *thd, enum enum_server_command command, set to 0 here because we don't have an active database yet (and we may not have an active database to set. */ - thd->db_access=0; + sctx->db_access=0; /* Don't allow user to connect if he has done too many queries */ if ((ur.questions || ur.updates || ur.conn_per_hour || ur.user_conn || max_user_connections) && get_or_create_user_conn(thd, - opt_old_style_user_limits ? thd->user : thd->priv_user, - opt_old_style_user_limits ? thd->host_or_ip : thd->priv_host, + (opt_old_style_user_limits ? sctx->user : sctx->priv_user), + (opt_old_style_user_limits ? sctx->host_or_ip : sctx->priv_host), &ur)) DBUG_RETURN(-1); if (thd->user_connect && @@ -439,12 +440,12 @@ int check_user(THD *thd, enum enum_server_command command, DBUG_RETURN(-1); } net_printf_error(thd, ER_ACCESS_DENIED_ERROR, - thd->user, - thd->host_or_ip, + sctx->user, + sctx->host_or_ip, passwd_len ? ER(ER_YES) : ER(ER_NO)); mysql_log.write(thd, COM_CONNECT, ER(ER_ACCESS_DENIED_ERROR), - thd->user, - thd->host_or_ip, + sctx->user, + sctx->host_or_ip, passwd_len ? ER(ER_YES) : ER(ER_NO)); DBUG_RETURN(-1); #endif /* NO_EMBEDDED_ACCESS_CHECKS */ @@ -764,45 +765,46 @@ static int check_connection(THD *thd) NET *net= &thd->net; ulong pkt_len= 0; char *end; + st_security_context *sctx= thd->security_ctx; DBUG_PRINT("info", ("New connection received on %s", vio_description(net->vio))); - if (!thd->host) // If TCP/IP connection + if (!sctx->host) // If TCP/IP connection { char ip[30]; if (vio_peer_addr(net->vio, ip, &thd->peer_port)) return (ER_BAD_HOST_ERROR); - if (!(thd->ip= my_strdup(ip,MYF(0)))) + if (!(sctx->ip= my_strdup(ip,MYF(0)))) return (ER_OUT_OF_RESOURCES); - thd->host_or_ip= thd->ip; + sctx->host_or_ip= sctx->ip; vio_in_addr(net->vio,&thd->remote.sin_addr); if (!(specialflag & SPECIAL_NO_RESOLVE)) { vio_in_addr(net->vio,&thd->remote.sin_addr); - thd->host=ip_to_hostname(&thd->remote.sin_addr,&connect_errors); + sctx->host=ip_to_hostname(&thd->remote.sin_addr,&connect_errors); /* Cut very long hostnames to avoid possible overflows */ - if (thd->host) + if (sctx->host) { - if (thd->host != my_localhost) - thd->host[min(strlen(thd->host), HOSTNAME_LENGTH)]= 0; - thd->host_or_ip= thd->host; + if (sctx->host != my_localhost) + sctx->host[min(strlen(sctx->host), HOSTNAME_LENGTH)]= 0; + sctx->host_or_ip= sctx->host; } if (connect_errors > max_connect_errors) return(ER_HOST_IS_BLOCKED); } DBUG_PRINT("info",("Host: %s ip: %s", - thd->host ? thd->host : "unknown host", - thd->ip ? thd->ip : "unknown ip")); - if (acl_check_host(thd->host,thd->ip)) + sctx->host ? sctx->host : "unknown host", + sctx->ip ? sctx->ip : "unknown ip")); + if (acl_check_host(sctx->host, sctx->ip)) return(ER_HOST_NOT_PRIVILEGED); } else /* Hostname given means that the connection was on a socket */ { - DBUG_PRINT("info",("Host: %s",thd->host)); - thd->host_or_ip= thd->host; - thd->ip= 0; + DBUG_PRINT("info",("Host: %s", sctx->host)); + sctx->host_or_ip= sctx->host; + sctx->ip= 0; /* Reset sin_addr */ bzero((char*) &thd->remote, sizeof(thd->remote)); } @@ -985,9 +987,9 @@ static int check_connection(THD *thd) thd->charset(), &dummy_errors)]= '\0'; user= user_buff; - if (thd->user) - x_free(thd->user); - if (!(thd->user= my_strdup(user, MYF(0)))) + if (sctx->user) + x_free(sctx->user); + if (!(sctx->user= my_strdup(user, MYF(0)))) return (ER_OUT_OF_RESOURCES); return check_user(thd, COM_CONNECT, passwd, passwd_len, db, TRUE); } @@ -1075,13 +1077,14 @@ pthread_handler_decl(handle_one_connection,arg) { int error; NET *net= &thd->net; + st_security_context *sctx= thd->security_ctx; thd->thread_stack= (char*) &thd; net->no_send_error= 0; if ((error=check_connection(thd))) { // Wrong permissions if (error > 0) - net_printf_error(thd, error, thd->host_or_ip); + net_printf_error(thd, error, sctx->host_or_ip); #ifdef __NT__ if (vio_type(net->vio) == VIO_TYPE_NAMEDPIPE) my_sleep(1000); /* must wait after eof() */ @@ -1090,7 +1093,7 @@ pthread_handler_decl(handle_one_connection,arg) goto end_thread; } #ifdef __NETWARE__ - netware_reg_user(thd->ip, thd->user, "MySQL"); + netware_reg_user(sctx->ip, sctx->user, "MySQL"); #endif if (thd->variables.max_join_size == HA_POS_ERROR) thd->options |= OPTION_BIG_SELECTS; @@ -1103,7 +1106,7 @@ pthread_handler_decl(handle_one_connection,arg) thd->set_time(); thd->init_for_queries(); - if (sys_init_connect.value_length && !(thd->master_access & SUPER_ACL)) + if (sys_init_connect.value_length && !(sctx->master_access & SUPER_ACL)) { execute_init_command(thd, &sys_init_connect, &LOCK_sys_init_connect); if (thd->query_error) @@ -1127,8 +1130,8 @@ pthread_handler_decl(handle_one_connection,arg) if (!thd->killed && thd->variables.log_warnings > 1) sql_print_warning(ER(ER_NEW_ABORTING_CONNECTION), thd->thread_id,(thd->db ? thd->db : "unconnected"), - thd->user ? thd->user : "unauthenticated", - thd->host_or_ip, + sctx->user ? sctx->user : "unauthenticated", + sctx->host_or_ip, (net->last_errno ? ER(net->last_errno) : ER(ER_UNKNOWN_ERROR))); net_send_error(thd, net->last_errno, NullS); @@ -1191,7 +1194,8 @@ extern "C" pthread_handler_decl(handle_bootstrap,arg) thd->proc_info=0; thd->version=refresh_version; - thd->priv_user=thd->user=(char*) my_strdup("boot", MYF(MY_WME)); + thd->security_ctx->priv_user= + thd->security_ctx->user= (char*) my_strdup("boot", MYF(MY_WME)); buff= (char*) thd->net.buff; thd->init_for_queries(); @@ -1586,17 +1590,14 @@ bool dispatch_command(enum enum_server_command command, THD *thd, db= db_buff; /* Save user and privileges */ - uint save_master_access= thd->master_access; - uint save_db_access= thd->db_access; uint save_db_length= thd->db_length; - char *save_user= thd->user; - char *save_priv_user= thd->priv_user; char *save_db= thd->db; + st_security_context save_security_ctx= *thd->security_ctx; USER_CONN *save_user_connect= thd->user_connect; - - if (!(thd->user= my_strdup(user, MYF(0)))) + + if (!(thd->security_ctx->user= my_strdup(user, MYF(0)))) { - thd->user= save_user; + thd->security_ctx->user= save_security_ctx.user; my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0)); break; } @@ -1610,12 +1611,9 @@ bool dispatch_command(enum enum_server_command command, THD *thd, /* authentication failure, we shall restore old user */ if (res > 0) my_message(ER_UNKNOWN_COM_ERROR, ER(ER_UNKNOWN_COM_ERROR), MYF(0)); - x_free(thd->user); - thd->user= save_user; - thd->priv_user= save_priv_user; + x_free(thd->security_ctx->user); + *thd->security_ctx= save_security_ctx; thd->user_connect= save_user_connect; - thd->master_access= save_master_access; - thd->db_access= save_db_access; thd->db= save_db; thd->db_length= save_db_length; } @@ -1625,7 +1623,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, if (save_user_connect) decrease_user_connections(save_user_connect); x_free((gptr) save_db); - x_free((gptr) save_user); + x_free((gptr) save_security_ctx.user); } break; } @@ -1967,12 +1965,13 @@ bool dispatch_command(enum enum_server_command command, THD *thd, case COM_PROCESS_INFO: statistic_increment(thd->status_var.com_stat[SQLCOM_SHOW_PROCESSLIST], &LOCK_status); - if (!thd->priv_user[0] && check_global_access(thd,PROCESS_ACL)) + if (!thd->security_ctx->priv_user[0] && + check_global_access(thd, PROCESS_ACL)) break; mysql_log.write(thd,command,NullS); mysqld_list_processes(thd, - thd->master_access & PROCESS_ACL ? - NullS : thd->priv_user, 0); + thd->security_ctx->master_access & PROCESS_ACL ? + NullS : thd->security_ctx->priv_user, 0); break; case COM_PROCESS_KILL: { @@ -2140,7 +2139,8 @@ int prepare_schema_table(THD *thd, LEX *lex, Table_ident *table_ident, if (!thd->col_access && check_grant_db(thd,db)) { my_error(ER_DBACCESS_DENIED_ERROR, MYF(0), - thd->priv_user, thd->priv_host, db); + thd->security_ctx->priv_user, thd->security_ctx->priv_host, + db); DBUG_RETURN(1); } /* @@ -2398,7 +2398,8 @@ mysql_execute_command(THD *thd) Except for the replication thread and the 'super' users. */ if (opt_readonly && - !(thd->slave_thread || (thd->master_access & SUPER_ACL)) && + !(thd->slave_thread || + (thd->security_ctx->master_access & SUPER_ACL)) && uc_update_queries[lex->sql_command]) { my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--read-only"); @@ -3377,11 +3378,14 @@ end_with_restore_list: res = mysql_drop_index(thd, first_table, &lex->alter_info); break; case SQLCOM_SHOW_PROCESSLIST: - if (!thd->priv_user[0] && check_global_access(thd,PROCESS_ACL)) + if (!thd->security_ctx->priv_user[0] && + check_global_access(thd,PROCESS_ACL)) break; mysqld_list_processes(thd, - thd->master_access & PROCESS_ACL ? NullS : - thd->priv_user,lex->verbose); + (thd->security_ctx->master_access & PROCESS_ACL ? + NullS : + thd->security_ctx->priv_user), + lex->verbose); break; case SQLCOM_SHOW_STORAGE_ENGINES: res= mysqld_show_storage_engines(thd); @@ -3719,7 +3723,7 @@ end_with_restore_list: select_lex->db ? is_schema_db(select_lex->db) : 0)) goto error; - if (thd->user) // If not replication + if (thd->security_ctx->user) // If not replication { LEX_USER *user; uint counter; @@ -3735,9 +3739,9 @@ end_with_restore_list: user->host.str); // Are we trying to change a password of another user DBUG_ASSERT(user->host.str != 0); - if (strcmp(thd->user, user->user.str) || + if (strcmp(thd->security_ctx->user, user->user.str) || my_strcasecmp(system_charset_info, - user->host.str, thd->host_or_ip)) + user->host.str, thd->security_ctx->host_or_ip)) { // TODO: use check_change_password() if (check_acl_user(user, &counter) && user->password.str && @@ -3864,8 +3868,8 @@ end_with_restore_list: } #ifndef NO_EMBEDDED_ACCESS_CHECKS case SQLCOM_SHOW_GRANTS: - if ((thd->priv_user && - !strcmp(thd->priv_user,lex->grant_user->user.str)) || + if ((thd->security_ctx->priv_user && + !strcmp(thd->security_ctx->priv_user, lex->grant_user->user.str)) || !check_access(thd, SELECT_ACL, "mysql",0,1,0,0)) { res = mysql_show_grants(thd,lex->grant_user); @@ -4139,7 +4143,7 @@ end_with_restore_list: else { #ifndef NO_EMBEDDED_ACCESS_CHECKS - st_sp_security_context save_ctx; + st_security_context *save_ctx; #endif ha_rows select_limit; /* bits that should be cleared in thd->server_status */ @@ -4185,23 +4189,23 @@ end_with_restore_list: } #ifndef NO_EMBEDDED_ACCESS_CHECKS - if (check_routine_access(thd, EXECUTE_ACL, - sp->m_db.str, sp->m_name.str, TRUE, 0)) + if (check_routine_access(thd, EXECUTE_ACL, + sp->m_db.str, sp->m_name.str, TRUE, 0) || + sp_change_security_context(thd, sp, &save_ctx)) { #ifndef EMBEDDED_LIBRARY thd->net.no_send_ok= nsok; #endif goto error; } - sp_change_security_context(thd, sp, &save_ctx); - if (save_ctx.changed && - check_routine_access(thd, EXECUTE_ACL, - sp->m_db.str, sp->m_name.str, TRUE, 0)) + if (save_ctx && + check_routine_access(thd, EXECUTE_ACL, + sp->m_db.str, sp->m_name.str, TRUE, 0)) { #ifndef EMBEDDED_LIBRARY thd->net.no_send_ok= nsok; #endif - sp_restore_security_context(thd, sp, &save_ctx); + sp_restore_security_context(thd, save_ctx); goto error; } @@ -4241,7 +4245,7 @@ end_with_restore_list: thd->variables.select_limit= select_limit; #ifndef NO_EMBEDDED_ACCESS_CHECKS - sp_restore_security_context(thd, sp, &save_ctx); + sp_restore_security_context(thd, save_ctx); #endif #ifndef EMBEDDED_LIBRARY @@ -4803,6 +4807,7 @@ bool check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv, bool dont_check_global_grants, bool no_errors, bool schema_db) { + st_security_context *sctx= thd->security_ctx; #ifndef NO_EMBEDDED_ACCESS_CHECKS ulong db_access; bool db_is_pattern= test(want_access & GRANT_ACL); @@ -4811,7 +4816,7 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv, const char *db_name; DBUG_ENTER("check_access"); DBUG_PRINT("enter",("db: %s want_access: %lu master_access: %lu", - db ? db : "", want_access, thd->master_access)); + db ? db : "", want_access, sctx->master_access)); if (save_priv) *save_priv=0; else @@ -4833,7 +4838,8 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv, { if (!no_errors) my_error(ER_DBACCESS_DENIED_ERROR, MYF(0), - thd->priv_user, thd->priv_host, db_name); + thd->security_ctx->priv_user, + thd->security_ctx->priv_host, db_name); DBUG_RETURN(TRUE); } else @@ -4846,28 +4852,29 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv, #ifdef NO_EMBEDDED_ACCESS_CHECKS DBUG_RETURN(0); #else - if ((thd->master_access & want_access) == want_access) + if ((sctx->master_access & want_access) == want_access) { /* If we don't have a global SELECT privilege, we have to get the database specific access rights to be able to handle queries of type UPDATE t1 SET a=1 WHERE b > 0 */ - db_access= thd->db_access; - if (!(thd->master_access & SELECT_ACL) && + db_access= sctx->db_access; + if (!(sctx->master_access & SELECT_ACL) && (db && (!thd->db || db_is_pattern || strcmp(db,thd->db)))) - db_access=acl_get(thd->host, thd->ip, thd->priv_user, db, db_is_pattern); - *save_priv=thd->master_access | db_access; + db_access=acl_get(sctx->host, sctx->ip, sctx->priv_user, db, + db_is_pattern); + *save_priv=sctx->master_access | db_access; DBUG_RETURN(FALSE); } - if (((want_access & ~thd->master_access) & ~(DB_ACLS | EXTRA_ACL)) || + if (((want_access & ~sctx->master_access) & ~(DB_ACLS | EXTRA_ACL)) || ! db && dont_check_global_grants) { // We can never grant this DBUG_PRINT("error",("No possible access")); if (!no_errors) my_error(ER_ACCESS_DENIED_ERROR, MYF(0), - thd->priv_user, - thd->priv_host, + sctx->priv_user, + sctx->priv_host, (thd->password ? ER(ER_YES) : ER(ER_NO))); /* purecov: tested */ @@ -4878,15 +4885,16 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv, DBUG_RETURN(FALSE); // Allow select on anything if (db && (!thd->db || db_is_pattern || strcmp(db,thd->db))) - db_access=acl_get(thd->host, thd->ip, thd->priv_user, db, db_is_pattern); + db_access= acl_get(sctx->host, sctx->ip, sctx->priv_user, db, + db_is_pattern); else - db_access=thd->db_access; + db_access= sctx->db_access; DBUG_PRINT("info",("db_access: %lu", db_access)); /* Remove SHOW attribute and access rights we already have */ - want_access &= ~(thd->master_access | EXTRA_ACL); + want_access &= ~(sctx->master_access | EXTRA_ACL); DBUG_PRINT("info",("db_access: %lu want_access: %lu", db_access, want_access)); - db_access= ((*save_priv=(db_access | thd->master_access)) & want_access); + db_access= ((*save_priv=(db_access | sctx->master_access)) & want_access); /* grant_option is set if there exists a single table or column grant */ if (db_access == want_access || @@ -4897,8 +4905,7 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv, DBUG_PRINT("error",("Access denied")); if (!no_errors) my_error(ER_DBACCESS_DENIED_ERROR, MYF(0), - thd->priv_user, - thd->priv_host, + sctx->priv_user, sctx->priv_host, (db ? db : (thd->db ? thd->db : "unknown"))); /* purecov: tested */ @@ -4932,7 +4939,7 @@ bool check_global_access(THD *thd, ulong want_access) return 0; #else char command[128]; - if ((thd->master_access & want_access)) + if ((thd->security_ctx->master_access & want_access)) return 0; get_privilege_desc(command, sizeof(command), want_access); my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0), command); @@ -4960,7 +4967,7 @@ check_table_access(THD *thd, ulong want_access,TABLE_LIST *tables, { if (!no_errors) my_error(ER_DBACCESS_DENIED_ERROR, MYF(0), - thd->priv_user, thd->priv_host, + thd->security_ctx->priv_user, thd->security_ctx->priv_host, information_schema_name.str); return TRUE; } @@ -4969,7 +4976,8 @@ check_table_access(THD *thd, ulong want_access,TABLE_LIST *tables, my_tz_check_n_skip_implicit_tables(&tables, thd->lex->time_zone_tables_used)) continue; - if ((thd->master_access & want_access) == (want_access & ~EXTRA_ACL) && + if ((thd->security_ctx->master_access & want_access) == + (want_access & ~EXTRA_ACL) && thd->db) tables->grant.privilege= want_access; else if (tables->db && tables->db == thd->db) @@ -5006,7 +5014,8 @@ check_routine_access(THD *thd, ulong want_access,char *db, char *name, tables->db= db; tables->table_name= tables->alias= name; - if ((thd->master_access & want_access) == want_access && !thd->db) + if ((thd->security_ctx->master_access & want_access) == want_access && + !thd->db) tables->grant.privilege= want_access; else if (check_access(thd,want_access,db,&tables->grant.privilege, 0, no_errors, test(tables->schema_table))) @@ -5039,7 +5048,7 @@ bool check_some_routine_access(THD *thd, const char *db, const char *name, bool is_proc) { ulong save_priv; - if (thd->master_access & SHOW_PROC_ACLS) + if (thd->security_ctx->master_access & SHOW_PROC_ACLS) return FALSE; /* There are no routines in information_schema db. So we can safely @@ -5236,6 +5245,7 @@ void mysql_reset_thd_for_next_command(THD *thd) thd->server_status&= ~ (SERVER_MORE_RESULTS_EXISTS | SERVER_QUERY_NO_INDEX_USED | SERVER_QUERY_NO_GOOD_INDEX_USED); + thd->security_ctx= &thd->main_security_ctx; thd->tmp_table_used= 0; if (!thd->in_sub_stmt) { @@ -6760,8 +6770,8 @@ void kill_one_thread(THD *thd, ulong id, bool only_kill_query) VOID(pthread_mutex_unlock(&LOCK_thread_count)); if (tmp) { - if ((thd->master_access & SUPER_ACL) || - !strcmp(thd->user,tmp->user)) + if ((thd->security_ctx->master_access & SUPER_ACL) || + !strcmp(thd->security_ctx->user, tmp->security_ctx->user)) { tmp->awake(only_kill_query ? THD::KILL_QUERY : THD::KILL_CONNECTION); error=0; @@ -7394,14 +7404,14 @@ Item *negate_expression(THD *thd, Item *expr) TRUE Error */ -bool default_view_definer(THD *thd, st_lex_user *definer) +bool default_view_definer(st_security_context *sctx, st_lex_user *definer) { - definer->user.str= thd->priv_user; - definer->user.length= strlen(thd->priv_user); - if (*thd->priv_host != 0) + definer->user.str= sctx->priv_user; + definer->user.length= strlen(sctx->priv_user); + if (*sctx->priv_host != 0) { - definer->host.str= thd->priv_host; - definer->host.length= strlen(thd->priv_host); + definer->host.str= sctx->priv_host; + definer->host.length= strlen(sctx->priv_host); } else { diff --git a/sql/sql_show.cc b/sql/sql_show.cc index e6a81538d90..528876a6bbb 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -415,8 +415,9 @@ mysqld_show_create(THD *thd, TABLE_LIST *table_list) bool mysqld_show_create_db(THD *thd, char *dbname, HA_CREATE_INFO *create_info) { + st_security_context *sctx= thd->security_ctx; int length; - char path[FN_REFLEN]; + char path[FN_REFLEN]; char buff[2048]; String buffer(buff, sizeof(buff), system_charset_info); #ifndef NO_EMBEDDED_ACCESS_CHECKS @@ -435,17 +436,17 @@ bool mysqld_show_create_db(THD *thd, char *dbname, } #ifndef NO_EMBEDDED_ACCESS_CHECKS - if (test_all_bits(thd->master_access,DB_ACLS)) + if (test_all_bits(sctx->master_access,DB_ACLS)) db_access=DB_ACLS; else - db_access= (acl_get(thd->host,thd->ip, thd->priv_user,dbname,0) | - thd->master_access); + db_access= (acl_get(sctx->host, sctx->ip, sctx->priv_user, dbname, 0) | + sctx->master_access); if (!(db_access & DB_ACLS) && (!grant_option || check_grant_db(thd,dbname))) { my_error(ER_DBACCESS_DENIED_ERROR, MYF(0), - thd->priv_user, thd->host_or_ip, dbname); + sctx->priv_user, sctx->host_or_ip, dbname); mysql_log.write(thd,COM_INIT_DB,ER(ER_DBACCESS_DENIED_ERROR), - thd->priv_user, thd->host_or_ip, dbname); + sctx->priv_user, sctx->host_or_ip, dbname); DBUG_RETURN(TRUE); } #endif @@ -1185,24 +1186,26 @@ void mysqld_list_processes(THD *thd,const char *user, bool verbose) THD *tmp; while ((tmp=it++)) { + st_security_context *tmp_sctx= tmp->security_ctx; struct st_my_thread_var *mysys_var; if ((tmp->vio_ok() || tmp->system_thread) && - (!user || (tmp->user && !strcmp(tmp->user,user)))) + (!user || (tmp_sctx->user && !strcmp(tmp_sctx->user, user)))) { - thread_info *thd_info=new thread_info; + thread_info *thd_info= new thread_info; thd_info->thread_id=tmp->thread_id; - thd_info->user=thd->strdup(tmp->user ? tmp->user : - (tmp->system_thread ? - "system user" : "unauthenticated user")); - if (tmp->peer_port && (tmp->host || tmp->ip) && thd->host_or_ip[0]) + thd_info->user= thd->strdup(tmp_sctx->user ? tmp_sctx->user : + (tmp->system_thread ? + "system user" : "unauthenticated user")); + if (tmp->peer_port && (tmp_sctx->host || tmp_sctx->ip) && + thd->security_ctx->host_or_ip[0]) { if ((thd_info->host= thd->alloc(LIST_PROCESS_HOST_LEN+1))) my_snprintf((char *) thd_info->host, LIST_PROCESS_HOST_LEN, - "%s:%u", tmp->host_or_ip, tmp->peer_port); + "%s:%u", tmp_sctx->host_or_ip, tmp->peer_port); } else - thd_info->host= thd->strdup(tmp->host_or_ip); + thd_info->host= thd->strdup(tmp_sctx->host_or_ip); if ((thd_info->db=tmp->db)) // Safe test thd_info->db=thd->strdup(thd_info->db); thd_info->command=(int) tmp->command; @@ -1253,6 +1256,9 @@ void mysqld_list_processes(THD *thd,const char *user, bool verbose) VOID(pthread_mutex_unlock(&LOCK_thread_count)); thread_info *thd_info; +#ifndef NO_EMBEDDED_ACCESS_CHECKS + st_security_context *sctx; +#endif time_t now= time(0); while ((thd_info=thread_infos.get())) { @@ -1989,7 +1995,8 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond) enum enum_schema_tables schema_table_idx; List<char> bases; List_iterator_fast<char> it(bases); - COND *partial_cond; + COND *partial_cond; + st_security_context *sctx= thd->security_ctx; uint derived_tables= lex->derived_tables; int error= 1; Open_tables_state open_tables_state_backup; @@ -2061,8 +2068,8 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond) #ifndef NO_EMBEDDED_ACCESS_CHECKS if (!check_access(thd,SELECT_ACL, base_name, &thd->col_access, 0, 1, with_i_schema) || - thd->master_access & (DB_ACLS | SHOW_DB_ACL) || - acl_get(thd->host, thd->ip, thd->priv_user, base_name,0) || + sctx->master_access & (DB_ACLS | SHOW_DB_ACL) || + acl_get(sctx->host, sctx->ip, sctx->priv_user, base_name,0) || (grant_option && !check_grant_db(thd, base_name))) #endif { @@ -2194,6 +2201,7 @@ int fill_schema_shemata(THD *thd, TABLE_LIST *tables, COND *cond) bool with_i_schema; HA_CREATE_INFO create; TABLE *table= tables->table; + st_security_context *sctx= thd->security_ctx; DBUG_ENTER("fill_schema_shemata"); if (make_db_list(thd, &files, &idx_field_vals, @@ -2212,8 +2220,8 @@ int fill_schema_shemata(THD *thd, TABLE_LIST *tables, COND *cond) continue; } #ifndef NO_EMBEDDED_ACCESS_CHECKS - if (thd->master_access & (DB_ACLS | SHOW_DB_ACL) || - acl_get(thd->host, thd->ip, thd->priv_user, file_name,0) || + if (sctx->master_access & (DB_ACLS | SHOW_DB_ACL) || + acl_get(sctx->host, sctx->ip, sctx->priv_user, file_name,0) || (grant_option && !check_grant_db(thd, file_name))) #endif { @@ -2814,7 +2822,8 @@ int fill_schema_proc(THD *thd, TABLE_LIST *tables, COND *cond) Open_tables_state open_tables_state_backup; DBUG_ENTER("fill_schema_proc"); - strxmov(definer, thd->priv_user, "@", thd->priv_host, NullS); + strxmov(definer, thd->security_ctx->priv_user, "@", + thd->security_ctx->priv_host, NullS); /* We use this TABLE_LIST instance only for checking of privileges. */ bzero((char*) &proc_tables,sizeof(proc_tables)); proc_tables.db= (char*) "mysql"; diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc index 7342c146045..df8de59508d 100644 --- a/sql/sql_trigger.cc +++ b/sql/sql_trigger.cc @@ -172,7 +172,7 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create) stronger test will be removed, the test below will hold. */ if (!trust_routine_creators && mysql_bin_log.is_open() && - !(thd->master_access & SUPER_ACL)) + !(thd->security_ctx->master_access & SUPER_ACL)) { my_message(ER_BINLOG_CREATE_ROUTINE_NEED_SUPER, ER(ER_BINLOG_CREATE_ROUTINE_NEED_SUPER), MYF(0)); diff --git a/sql/sql_view.cc b/sql/sql_view.cc index 5155e605ce0..62b5169a781 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -214,12 +214,13 @@ bool mysql_create_view(THD *thd, - same as current user - current user has SUPER_ACL */ - if (strcmp(lex->create_view_definer->user.str, thd->priv_user) != 0 || + if (strcmp(lex->create_view_definer->user.str, + thd->security_ctx->priv_user) != 0 || my_strcasecmp(system_charset_info, lex->create_view_definer->host.str, - thd->priv_host) != 0) + thd->security_ctx->priv_host) != 0) { - if (!(thd->master_access & SUPER_ACL)) + if (!(thd->security_ctx->master_access & SUPER_ACL)) { my_error(ER_VIEW_OTHER_USER, MYF(0), lex->create_view_definer->user.str, lex->create_view_definer->host.str); @@ -275,7 +276,8 @@ bool mysql_create_view(THD *thd, if (check_some_access(thd, VIEW_ANY_ACL, tbl)) { my_error(ER_TABLEACCESS_DENIED_ERROR, MYF(0), - "ANY", thd->priv_user, thd->host_or_ip, tbl->table_name); + "ANY", thd->security_ctx->priv_user, + thd->security_ctx->priv_host, tbl->table_name); res= TRUE; goto err; } @@ -441,7 +443,8 @@ bool mysql_create_view(THD *thd, { /* VIEW column has more privileges */ my_error(ER_COLUMNACCESS_DENIED_ERROR, MYF(0), - "create view", thd->priv_user, thd->host_or_ip, item->name, + "create view", thd->security_ctx->priv_user, + thd->security_ctx->priv_host, item->name, view->table_name); res= TRUE; goto err; @@ -786,7 +789,7 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table) push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_VIEW_FRM_NO_USER, ER(ER_VIEW_FRM_NO_USER), table->db, table->table_name); - if (default_view_definer(thd, &table->definer)) + if (default_view_definer(thd->security_ctx, &table->definer)) goto err; } diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 20a9d945a87..26f8e0dfbd9 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -6554,15 +6554,16 @@ show_param: LEX *lex=Lex; lex->sql_command= SQLCOM_SHOW_GRANTS; THD *thd= lex->thd; + st_security_context *sctx= thd->security_ctx; LEX_USER *curr_user; if (!(curr_user= (LEX_USER*) thd->alloc(sizeof(st_lex_user)))) YYABORT; - curr_user->user.str= thd->priv_user; - curr_user->user.length= strlen(thd->priv_user); - if (*thd->priv_host != 0) + curr_user->user.str= sctx->priv_user; + curr_user->user.length= strlen(sctx->priv_user); + if (*sctx->priv_host != 0) { - curr_user->host.str= thd->priv_host; - curr_user->host.length= strlen(thd->priv_host); + curr_user->host.str= sctx->priv_host; + curr_user->host.length= strlen(sctx->priv_host); } else { @@ -7463,14 +7464,15 @@ user: | CURRENT_USER optional_braces { THD *thd= YYTHD; + st_security_context *sctx= thd->security_ctx; if (!($$=(LEX_USER*) thd->alloc(sizeof(st_lex_user)))) YYABORT; - $$->user.str= thd->priv_user; - $$->user.length= strlen(thd->priv_user); - if (*thd->priv_host != 0) + $$->user.str= sctx->priv_user; + $$->user.length= strlen(sctx->priv_user); + if (*sctx->priv_host != 0) { - $$->host.str= thd->priv_host; - $$->host.length= strlen(thd->priv_host); + $$->host.str= sctx->priv_host; + $$->host.length= strlen(sctx->priv_host); } else { @@ -7986,7 +7988,7 @@ option_value: if (!(user=(LEX_USER*) thd->alloc(sizeof(LEX_USER)))) YYABORT; user->host=null_lex_str; - user->user.str=thd->priv_user; + user->user.str=thd->security_ctx->priv_user; thd->lex->var_list.push_back(new set_var_password(user, $3)); } | PASSWORD FOR_SYM user equal text_or_password @@ -8919,7 +8921,8 @@ view_user: if (!(thd->lex->create_view_definer= (LEX_USER*) thd->alloc(sizeof(st_lex_user)))) YYABORT; - if (default_view_definer(thd, thd->lex->create_view_definer)) + if (default_view_definer(thd->security_ctx, + thd->lex->create_view_definer)) YYABORT; } | CURRENT_USER optional_braces @@ -8928,7 +8931,8 @@ view_user: if (!(thd->lex->create_view_definer= (LEX_USER*) thd->alloc(sizeof(st_lex_user)))) YYABORT; - if (default_view_definer(thd, thd->lex->create_view_definer)) + if (default_view_definer(thd->security_ctx, + thd->lex->create_view_definer)) YYABORT; } | DEFINER_SYM EQ ident_or_text '@' ident_or_text |