Loading mysql-test/r/events_bugs.result +53 −0 Original line number Diff line number Diff line Loading @@ -325,4 +325,57 @@ drop event e22830_3; drop event e22830_4; drop table t1; drop table t2; DROP USER mysqltest_u1@localhost; CREATE USER mysqltest_u1@localhost; GRANT EVENT ON events_test.* TO mysqltest_u1@localhost; CREATE EVENT e1 ON SCHEDULE EVERY 1 DAY DO SELECT 1; SELECT event_name, definer FROM INFORMATION_SCHEMA.EVENTS; event_name definer e1 root@localhost DROP EVENT e1; CREATE DEFINER=CURRENT_USER EVENT e1 ON SCHEDULE EVERY 1 DAY DO SELECT 1; SELECT event_name, definer FROM INFORMATION_SCHEMA.EVENTS; event_name definer e1 root@localhost ALTER DEFINER=mysqltest_u1@localhost EVENT e1 ON SCHEDULE EVERY 1 HOUR; SELECT event_name, definer FROM INFORMATION_SCHEMA.EVENTS; event_name definer e1 mysqltest_u1@localhost DROP EVENT e1; CREATE DEFINER=CURRENT_USER() EVENT e1 ON SCHEDULE EVERY 1 DAY DO SELECT 1; SELECT event_name, definer FROM INFORMATION_SCHEMA.EVENTS; event_name definer e1 root@localhost DROP EVENT e1; CREATE DEFINER=mysqltest_u1@localhost EVENT e1 ON SCHEDULE EVERY 1 DAY DO SELECT 1; SELECT event_name, definer FROM INFORMATION_SCHEMA.EVENTS; event_name definer e1 mysqltest_u1@localhost DROP EVENT e1; CREATE EVENT e1 ON SCHEDULE EVERY 1 DAY DO SELECT 1; SELECT event_name, definer FROM INFORMATION_SCHEMA.EVENTS; event_name definer e1 mysqltest_u1@localhost DROP EVENT e1; CREATE DEFINER=CURRENT_USER EVENT e1 ON SCHEDULE EVERY 1 DAY DO SELECT 1; SELECT event_name, definer FROM INFORMATION_SCHEMA.EVENTS; event_name definer e1 mysqltest_u1@localhost ALTER DEFINER=root@localhost EVENT e1 ON SCHEDULE EVERY 1 HOUR; ERROR 42000: Access denied; you need the SUPER privilege for this operation SELECT event_name, definer FROM INFORMATION_SCHEMA.EVENTS; event_name definer e1 mysqltest_u1@localhost DROP EVENT e1; CREATE DEFINER=CURRENT_USER() EVENT e1 ON SCHEDULE EVERY 1 DAY DO SELECT 1; SELECT event_name, definer FROM INFORMATION_SCHEMA.EVENTS; event_name definer e1 mysqltest_u1@localhost DROP EVENT e1; CREATE DEFINER=root@localhost EVENT e1 ON SCHEDULE EVERY 1 DAY DO SELECT 1; ERROR 42000: Access denied; you need the SUPER privilege for this operation DROP EVENT e1; ERROR HY000: Unknown event 'e1' DROP USER mysqltest_u1@localhost; drop database events_test; mysql-test/t/events_bugs.test +57 −0 Original line number Diff line number Diff line Loading @@ -364,6 +364,63 @@ drop event e22830_4; drop table t1; drop table t2; # # BUG#16425: Events: no DEFINER clause # --error 0,ER_CANNOT_USER DROP USER mysqltest_u1@localhost; CREATE USER mysqltest_u1@localhost; GRANT EVENT ON events_test.* TO mysqltest_u1@localhost; CREATE EVENT e1 ON SCHEDULE EVERY 1 DAY DO SELECT 1; SELECT event_name, definer FROM INFORMATION_SCHEMA.EVENTS; DROP EVENT e1; CREATE DEFINER=CURRENT_USER EVENT e1 ON SCHEDULE EVERY 1 DAY DO SELECT 1; SELECT event_name, definer FROM INFORMATION_SCHEMA.EVENTS; ALTER DEFINER=mysqltest_u1@localhost EVENT e1 ON SCHEDULE EVERY 1 HOUR; SELECT event_name, definer FROM INFORMATION_SCHEMA.EVENTS; DROP EVENT e1; CREATE DEFINER=CURRENT_USER() EVENT e1 ON SCHEDULE EVERY 1 DAY DO SELECT 1; SELECT event_name, definer FROM INFORMATION_SCHEMA.EVENTS; DROP EVENT e1; CREATE DEFINER=mysqltest_u1@localhost EVENT e1 ON SCHEDULE EVERY 1 DAY DO SELECT 1; SELECT event_name, definer FROM INFORMATION_SCHEMA.EVENTS; DROP EVENT e1; connect (conn1, localhost, mysqltest_u1, , events_test); CREATE EVENT e1 ON SCHEDULE EVERY 1 DAY DO SELECT 1; SELECT event_name, definer FROM INFORMATION_SCHEMA.EVENTS; DROP EVENT e1; CREATE DEFINER=CURRENT_USER EVENT e1 ON SCHEDULE EVERY 1 DAY DO SELECT 1; SELECT event_name, definer FROM INFORMATION_SCHEMA.EVENTS; --error ER_SPECIFIC_ACCESS_DENIED_ERROR ALTER DEFINER=root@localhost EVENT e1 ON SCHEDULE EVERY 1 HOUR; SELECT event_name, definer FROM INFORMATION_SCHEMA.EVENTS; DROP EVENT e1; CREATE DEFINER=CURRENT_USER() EVENT e1 ON SCHEDULE EVERY 1 DAY DO SELECT 1; SELECT event_name, definer FROM INFORMATION_SCHEMA.EVENTS; DROP EVENT e1; --error ER_SPECIFIC_ACCESS_DENIED_ERROR CREATE DEFINER=root@localhost EVENT e1 ON SCHEDULE EVERY 1 DAY DO SELECT 1; --error ER_EVENT_DOES_NOT_EXIST DROP EVENT e1; disconnect conn1; connection default; DROP USER mysqltest_u1@localhost; # # End of tests # Loading sql/event_data_objects.cc +11 −10 Original line number Diff line number Diff line Loading @@ -611,16 +611,18 @@ Event_parse_data::check_parse_data(THD *thd) void Event_parse_data::init_definer(THD *thd) { int definer_user_len; int definer_host_len; DBUG_ENTER("Event_parse_data::init_definer"); DBUG_PRINT("info",("init definer_user thd->mem_root: 0x%lx " "thd->sec_ctx->priv_user: 0x%lx", (long) thd->mem_root, (long) thd->security_ctx->priv_user)); DBUG_ASSERT(thd->lex->definer); const char *definer_user= thd->lex->definer->user.str; const char *definer_host= thd->lex->definer->host.str; int definer_user_len= thd->lex->definer->user.length; int definer_host_len= thd->lex->definer->host.length; definer_user_len= strlen(thd->security_ctx->priv_user); definer_host_len= strlen(thd->security_ctx->priv_host); DBUG_PRINT("info",("init definer_user thd->mem_root: 0x%lx " "definer_user: 0x%lx", (long) thd->mem_root, (long) definer_user)); /* + 1 for @ */ DBUG_PRINT("info",("init definer as whole")); Loading @@ -628,12 +630,11 @@ Event_parse_data::init_definer(THD *thd) definer.str= thd->alloc(definer.length + 1); DBUG_PRINT("info",("copy the user")); memcpy(definer.str, thd->security_ctx->priv_user, definer_user_len); memcpy(definer.str, definer_user, definer_user_len); definer.str[definer_user_len]= '@'; DBUG_PRINT("info",("copy the host")); memcpy(definer.str + definer_user_len + 1, thd->security_ctx->priv_host, definer_host_len); memcpy(definer.str + definer_user_len + 1, definer_host, definer_host_len); definer.str[definer.length]= '\0'; DBUG_PRINT("info",("definer [%s] initted", definer.str)); Loading sql/sql_parse.cc +92 −77 Original line number Diff line number Diff line Loading @@ -2492,6 +2492,91 @@ static void reset_one_shot_variables(THD *thd) } static bool sp_process_definer(THD *thd) { DBUG_ENTER("sp_process_definer"); LEX *lex= thd->lex; /* If the definer is not specified, this means that CREATE-statement missed DEFINER-clause. DEFINER-clause can be missed in two cases: - The user submitted a statement w/o the clause. This is a normal case, we should assign CURRENT_USER as definer. - Our slave received an updated from the master, that does not replicate definer for stored rountines. We should also assign CURRENT_USER as definer here, but also we should mark this routine as NON-SUID. This is essential for the sake of backward compatibility. The problem is the slave thread is running under "special" user (@), that actually does not exist. In the older versions we do not fail execution of a stored routine if its definer does not exist and continue the execution under the authorization of the invoker (BUG#13198). And now if we try to switch to slave-current-user (@), we will fail. Actually, this leads to the inconsistent state of master and slave (different definers, different SUID behaviour), but it seems, this is the best we can do. */ if (!lex->definer) { Query_arena original_arena; Query_arena *ps_arena= thd->activate_stmt_arena_if_needed(&original_arena); lex->definer= create_default_definer(thd); if (ps_arena) thd->restore_active_arena(ps_arena, &original_arena); /* Error has been already reported. */ if (lex->definer == NULL) DBUG_RETURN(TRUE); if (thd->slave_thread) lex->sphead->m_chistics->suid= SP_IS_NOT_SUID; } else { /* If the specified definer differs from the current user, we should check that the current user has SUPER privilege (in order to create a stored routine under another user one must have SUPER privilege). */ if ((strcmp(lex->definer->user.str, thd->security_ctx->priv_user) || my_strcasecmp(system_charset_info, lex->definer->host.str, thd->security_ctx->priv_host)) && check_global_access(thd, SUPER_ACL)) { my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0), "SUPER"); DBUG_RETURN(TRUE); } } /* Check that the specified definer exists. Emit a warning if not. */ #ifndef NO_EMBEDDED_ACCESS_CHECKS if (!is_acl_user(lex->definer->host.str, lex->definer->user.str)) { push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, ER_NO_SUCH_USER, ER(ER_NO_SUCH_USER), lex->definer->user.str, lex->definer->host.str); } #endif /* NO_EMBEDDED_ACCESS_CHECKS */ DBUG_RETURN(FALSE); } /* Execute command saved in thd and lex->sql_command Loading Loading @@ -3992,6 +4077,11 @@ mysql_execute_command(THD *thd) "function calls as part of this statement"); break; } res= sp_process_definer(thd); if (res) break; switch (lex->sql_command) { case SQLCOM_CREATE_EVENT: res= Events::get_instance()-> Loading Loading @@ -4487,84 +4577,9 @@ mysql_execute_command(THD *thd) } #endif /* If the definer is not specified, this means that CREATE-statement missed DEFINER-clause. DEFINER-clause can be missed in two cases: - The user submitted a statement w/o the clause. This is a normal case, we should assign CURRENT_USER as definer. - Our slave received an updated from the master, that does not replicate definer for stored rountines. We should also assign CURRENT_USER as definer here, but also we should mark this routine as NON-SUID. This is essential for the sake of backward compatibility. The problem is the slave thread is running under "special" user (@), that actually does not exist. In the older versions we do not fail execution of a stored routine if its definer does not exist and continue the execution under the authorization of the invoker (BUG#13198). And now if we try to switch to slave-current-user (@), we will fail. Actually, this leads to the inconsistent state of master and slave (different definers, different SUID behaviour), but it seems, this is the best we can do. */ if (!lex->definer) { bool res= FALSE; Query_arena original_arena; Query_arena *ps_arena = thd->activate_stmt_arena_if_needed(&original_arena); if (!(lex->definer= create_default_definer(thd))) res= TRUE; if (ps_arena) thd->restore_active_arena(ps_arena, &original_arena); /* Error has been already reported. */ if (res) if (sp_process_definer(thd)) goto create_sp_error; if (thd->slave_thread) lex->sphead->m_chistics->suid= SP_IS_NOT_SUID; } /* If the specified definer differs from the current user, we should check that the current user has SUPER privilege (in order to create a stored routine under another user one must have SUPER privilege). */ else if (strcmp(lex->definer->user.str, thd->security_ctx->priv_user) || my_strcasecmp(system_charset_info, lex->definer->host.str, thd->security_ctx->priv_host)) { if (check_global_access(thd, SUPER_ACL)) { my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0), "SUPER"); goto create_sp_error; } } /* Check that the specified definer exists. Emit a warning if not. */ #ifndef NO_EMBEDDED_ACCESS_CHECKS if (!is_acl_user(lex->definer->host.str, lex->definer->user.str)) { push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, ER_NO_SUCH_USER, ER(ER_NO_SUCH_USER), lex->definer->user.str, lex->definer->host.str); } #endif /* NO_EMBEDDED_ACCESS_CHECKS */ res= (result= lex->sphead->create(thd)); switch (result) { case SP_OK: Loading sql/sql_yacc.yy +8 −7 Original line number Diff line number Diff line Loading @@ -5104,7 +5104,7 @@ alter: } view_list_opt AS view_select view_check_option {} | ALTER EVENT_SYM sp_name | ALTER definer EVENT_SYM sp_name /* BE CAREFUL when you add a new rule to update the block where YYTHD->client_capabilities is set back to original value Loading @@ -5120,7 +5120,7 @@ alter: if (!(Lex->event_parse_data= Event_parse_data::new_instance(YYTHD))) YYABORT; Lex->event_parse_data->identifier= $3; Lex->event_parse_data->identifier= $4; /* We have to turn off CLIENT_MULTI_QUERIES while parsing a Loading @@ -5140,13 +5140,14 @@ alter: { /* $1 - ALTER $2 - EVENT_SYM $3 - sp_name $4 - the block above $2 - definer $3 - EVENT_SYM $4 - sp_name $5 - the block above */ YYTHD->client_capabilities |= $<ulong_num>4; YYTHD->client_capabilities |= $<ulong_num>5; if (!($5 || $6 || $7 || $8 || $9)) if (!($6 || $7 || $8 || $9 || $10)) { yyerror(ER(ER_SYNTAX_ERROR)); YYABORT; Loading Loading
mysql-test/r/events_bugs.result +53 −0 Original line number Diff line number Diff line Loading @@ -325,4 +325,57 @@ drop event e22830_3; drop event e22830_4; drop table t1; drop table t2; DROP USER mysqltest_u1@localhost; CREATE USER mysqltest_u1@localhost; GRANT EVENT ON events_test.* TO mysqltest_u1@localhost; CREATE EVENT e1 ON SCHEDULE EVERY 1 DAY DO SELECT 1; SELECT event_name, definer FROM INFORMATION_SCHEMA.EVENTS; event_name definer e1 root@localhost DROP EVENT e1; CREATE DEFINER=CURRENT_USER EVENT e1 ON SCHEDULE EVERY 1 DAY DO SELECT 1; SELECT event_name, definer FROM INFORMATION_SCHEMA.EVENTS; event_name definer e1 root@localhost ALTER DEFINER=mysqltest_u1@localhost EVENT e1 ON SCHEDULE EVERY 1 HOUR; SELECT event_name, definer FROM INFORMATION_SCHEMA.EVENTS; event_name definer e1 mysqltest_u1@localhost DROP EVENT e1; CREATE DEFINER=CURRENT_USER() EVENT e1 ON SCHEDULE EVERY 1 DAY DO SELECT 1; SELECT event_name, definer FROM INFORMATION_SCHEMA.EVENTS; event_name definer e1 root@localhost DROP EVENT e1; CREATE DEFINER=mysqltest_u1@localhost EVENT e1 ON SCHEDULE EVERY 1 DAY DO SELECT 1; SELECT event_name, definer FROM INFORMATION_SCHEMA.EVENTS; event_name definer e1 mysqltest_u1@localhost DROP EVENT e1; CREATE EVENT e1 ON SCHEDULE EVERY 1 DAY DO SELECT 1; SELECT event_name, definer FROM INFORMATION_SCHEMA.EVENTS; event_name definer e1 mysqltest_u1@localhost DROP EVENT e1; CREATE DEFINER=CURRENT_USER EVENT e1 ON SCHEDULE EVERY 1 DAY DO SELECT 1; SELECT event_name, definer FROM INFORMATION_SCHEMA.EVENTS; event_name definer e1 mysqltest_u1@localhost ALTER DEFINER=root@localhost EVENT e1 ON SCHEDULE EVERY 1 HOUR; ERROR 42000: Access denied; you need the SUPER privilege for this operation SELECT event_name, definer FROM INFORMATION_SCHEMA.EVENTS; event_name definer e1 mysqltest_u1@localhost DROP EVENT e1; CREATE DEFINER=CURRENT_USER() EVENT e1 ON SCHEDULE EVERY 1 DAY DO SELECT 1; SELECT event_name, definer FROM INFORMATION_SCHEMA.EVENTS; event_name definer e1 mysqltest_u1@localhost DROP EVENT e1; CREATE DEFINER=root@localhost EVENT e1 ON SCHEDULE EVERY 1 DAY DO SELECT 1; ERROR 42000: Access denied; you need the SUPER privilege for this operation DROP EVENT e1; ERROR HY000: Unknown event 'e1' DROP USER mysqltest_u1@localhost; drop database events_test;
mysql-test/t/events_bugs.test +57 −0 Original line number Diff line number Diff line Loading @@ -364,6 +364,63 @@ drop event e22830_4; drop table t1; drop table t2; # # BUG#16425: Events: no DEFINER clause # --error 0,ER_CANNOT_USER DROP USER mysqltest_u1@localhost; CREATE USER mysqltest_u1@localhost; GRANT EVENT ON events_test.* TO mysqltest_u1@localhost; CREATE EVENT e1 ON SCHEDULE EVERY 1 DAY DO SELECT 1; SELECT event_name, definer FROM INFORMATION_SCHEMA.EVENTS; DROP EVENT e1; CREATE DEFINER=CURRENT_USER EVENT e1 ON SCHEDULE EVERY 1 DAY DO SELECT 1; SELECT event_name, definer FROM INFORMATION_SCHEMA.EVENTS; ALTER DEFINER=mysqltest_u1@localhost EVENT e1 ON SCHEDULE EVERY 1 HOUR; SELECT event_name, definer FROM INFORMATION_SCHEMA.EVENTS; DROP EVENT e1; CREATE DEFINER=CURRENT_USER() EVENT e1 ON SCHEDULE EVERY 1 DAY DO SELECT 1; SELECT event_name, definer FROM INFORMATION_SCHEMA.EVENTS; DROP EVENT e1; CREATE DEFINER=mysqltest_u1@localhost EVENT e1 ON SCHEDULE EVERY 1 DAY DO SELECT 1; SELECT event_name, definer FROM INFORMATION_SCHEMA.EVENTS; DROP EVENT e1; connect (conn1, localhost, mysqltest_u1, , events_test); CREATE EVENT e1 ON SCHEDULE EVERY 1 DAY DO SELECT 1; SELECT event_name, definer FROM INFORMATION_SCHEMA.EVENTS; DROP EVENT e1; CREATE DEFINER=CURRENT_USER EVENT e1 ON SCHEDULE EVERY 1 DAY DO SELECT 1; SELECT event_name, definer FROM INFORMATION_SCHEMA.EVENTS; --error ER_SPECIFIC_ACCESS_DENIED_ERROR ALTER DEFINER=root@localhost EVENT e1 ON SCHEDULE EVERY 1 HOUR; SELECT event_name, definer FROM INFORMATION_SCHEMA.EVENTS; DROP EVENT e1; CREATE DEFINER=CURRENT_USER() EVENT e1 ON SCHEDULE EVERY 1 DAY DO SELECT 1; SELECT event_name, definer FROM INFORMATION_SCHEMA.EVENTS; DROP EVENT e1; --error ER_SPECIFIC_ACCESS_DENIED_ERROR CREATE DEFINER=root@localhost EVENT e1 ON SCHEDULE EVERY 1 DAY DO SELECT 1; --error ER_EVENT_DOES_NOT_EXIST DROP EVENT e1; disconnect conn1; connection default; DROP USER mysqltest_u1@localhost; # # End of tests # Loading
sql/event_data_objects.cc +11 −10 Original line number Diff line number Diff line Loading @@ -611,16 +611,18 @@ Event_parse_data::check_parse_data(THD *thd) void Event_parse_data::init_definer(THD *thd) { int definer_user_len; int definer_host_len; DBUG_ENTER("Event_parse_data::init_definer"); DBUG_PRINT("info",("init definer_user thd->mem_root: 0x%lx " "thd->sec_ctx->priv_user: 0x%lx", (long) thd->mem_root, (long) thd->security_ctx->priv_user)); DBUG_ASSERT(thd->lex->definer); const char *definer_user= thd->lex->definer->user.str; const char *definer_host= thd->lex->definer->host.str; int definer_user_len= thd->lex->definer->user.length; int definer_host_len= thd->lex->definer->host.length; definer_user_len= strlen(thd->security_ctx->priv_user); definer_host_len= strlen(thd->security_ctx->priv_host); DBUG_PRINT("info",("init definer_user thd->mem_root: 0x%lx " "definer_user: 0x%lx", (long) thd->mem_root, (long) definer_user)); /* + 1 for @ */ DBUG_PRINT("info",("init definer as whole")); Loading @@ -628,12 +630,11 @@ Event_parse_data::init_definer(THD *thd) definer.str= thd->alloc(definer.length + 1); DBUG_PRINT("info",("copy the user")); memcpy(definer.str, thd->security_ctx->priv_user, definer_user_len); memcpy(definer.str, definer_user, definer_user_len); definer.str[definer_user_len]= '@'; DBUG_PRINT("info",("copy the host")); memcpy(definer.str + definer_user_len + 1, thd->security_ctx->priv_host, definer_host_len); memcpy(definer.str + definer_user_len + 1, definer_host, definer_host_len); definer.str[definer.length]= '\0'; DBUG_PRINT("info",("definer [%s] initted", definer.str)); Loading
sql/sql_parse.cc +92 −77 Original line number Diff line number Diff line Loading @@ -2492,6 +2492,91 @@ static void reset_one_shot_variables(THD *thd) } static bool sp_process_definer(THD *thd) { DBUG_ENTER("sp_process_definer"); LEX *lex= thd->lex; /* If the definer is not specified, this means that CREATE-statement missed DEFINER-clause. DEFINER-clause can be missed in two cases: - The user submitted a statement w/o the clause. This is a normal case, we should assign CURRENT_USER as definer. - Our slave received an updated from the master, that does not replicate definer for stored rountines. We should also assign CURRENT_USER as definer here, but also we should mark this routine as NON-SUID. This is essential for the sake of backward compatibility. The problem is the slave thread is running under "special" user (@), that actually does not exist. In the older versions we do not fail execution of a stored routine if its definer does not exist and continue the execution under the authorization of the invoker (BUG#13198). And now if we try to switch to slave-current-user (@), we will fail. Actually, this leads to the inconsistent state of master and slave (different definers, different SUID behaviour), but it seems, this is the best we can do. */ if (!lex->definer) { Query_arena original_arena; Query_arena *ps_arena= thd->activate_stmt_arena_if_needed(&original_arena); lex->definer= create_default_definer(thd); if (ps_arena) thd->restore_active_arena(ps_arena, &original_arena); /* Error has been already reported. */ if (lex->definer == NULL) DBUG_RETURN(TRUE); if (thd->slave_thread) lex->sphead->m_chistics->suid= SP_IS_NOT_SUID; } else { /* If the specified definer differs from the current user, we should check that the current user has SUPER privilege (in order to create a stored routine under another user one must have SUPER privilege). */ if ((strcmp(lex->definer->user.str, thd->security_ctx->priv_user) || my_strcasecmp(system_charset_info, lex->definer->host.str, thd->security_ctx->priv_host)) && check_global_access(thd, SUPER_ACL)) { my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0), "SUPER"); DBUG_RETURN(TRUE); } } /* Check that the specified definer exists. Emit a warning if not. */ #ifndef NO_EMBEDDED_ACCESS_CHECKS if (!is_acl_user(lex->definer->host.str, lex->definer->user.str)) { push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, ER_NO_SUCH_USER, ER(ER_NO_SUCH_USER), lex->definer->user.str, lex->definer->host.str); } #endif /* NO_EMBEDDED_ACCESS_CHECKS */ DBUG_RETURN(FALSE); } /* Execute command saved in thd and lex->sql_command Loading Loading @@ -3992,6 +4077,11 @@ mysql_execute_command(THD *thd) "function calls as part of this statement"); break; } res= sp_process_definer(thd); if (res) break; switch (lex->sql_command) { case SQLCOM_CREATE_EVENT: res= Events::get_instance()-> Loading Loading @@ -4487,84 +4577,9 @@ mysql_execute_command(THD *thd) } #endif /* If the definer is not specified, this means that CREATE-statement missed DEFINER-clause. DEFINER-clause can be missed in two cases: - The user submitted a statement w/o the clause. This is a normal case, we should assign CURRENT_USER as definer. - Our slave received an updated from the master, that does not replicate definer for stored rountines. We should also assign CURRENT_USER as definer here, but also we should mark this routine as NON-SUID. This is essential for the sake of backward compatibility. The problem is the slave thread is running under "special" user (@), that actually does not exist. In the older versions we do not fail execution of a stored routine if its definer does not exist and continue the execution under the authorization of the invoker (BUG#13198). And now if we try to switch to slave-current-user (@), we will fail. Actually, this leads to the inconsistent state of master and slave (different definers, different SUID behaviour), but it seems, this is the best we can do. */ if (!lex->definer) { bool res= FALSE; Query_arena original_arena; Query_arena *ps_arena = thd->activate_stmt_arena_if_needed(&original_arena); if (!(lex->definer= create_default_definer(thd))) res= TRUE; if (ps_arena) thd->restore_active_arena(ps_arena, &original_arena); /* Error has been already reported. */ if (res) if (sp_process_definer(thd)) goto create_sp_error; if (thd->slave_thread) lex->sphead->m_chistics->suid= SP_IS_NOT_SUID; } /* If the specified definer differs from the current user, we should check that the current user has SUPER privilege (in order to create a stored routine under another user one must have SUPER privilege). */ else if (strcmp(lex->definer->user.str, thd->security_ctx->priv_user) || my_strcasecmp(system_charset_info, lex->definer->host.str, thd->security_ctx->priv_host)) { if (check_global_access(thd, SUPER_ACL)) { my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0), "SUPER"); goto create_sp_error; } } /* Check that the specified definer exists. Emit a warning if not. */ #ifndef NO_EMBEDDED_ACCESS_CHECKS if (!is_acl_user(lex->definer->host.str, lex->definer->user.str)) { push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, ER_NO_SUCH_USER, ER(ER_NO_SUCH_USER), lex->definer->user.str, lex->definer->host.str); } #endif /* NO_EMBEDDED_ACCESS_CHECKS */ res= (result= lex->sphead->create(thd)); switch (result) { case SP_OK: Loading
sql/sql_yacc.yy +8 −7 Original line number Diff line number Diff line Loading @@ -5104,7 +5104,7 @@ alter: } view_list_opt AS view_select view_check_option {} | ALTER EVENT_SYM sp_name | ALTER definer EVENT_SYM sp_name /* BE CAREFUL when you add a new rule to update the block where YYTHD->client_capabilities is set back to original value Loading @@ -5120,7 +5120,7 @@ alter: if (!(Lex->event_parse_data= Event_parse_data::new_instance(YYTHD))) YYABORT; Lex->event_parse_data->identifier= $3; Lex->event_parse_data->identifier= $4; /* We have to turn off CLIENT_MULTI_QUERIES while parsing a Loading @@ -5140,13 +5140,14 @@ alter: { /* $1 - ALTER $2 - EVENT_SYM $3 - sp_name $4 - the block above $2 - definer $3 - EVENT_SYM $4 - sp_name $5 - the block above */ YYTHD->client_capabilities |= $<ulong_num>4; YYTHD->client_capabilities |= $<ulong_num>5; if (!($5 || $6 || $7 || $8 || $9)) if (!($6 || $7 || $8 || $9 || $10)) { yyerror(ER(ER_SYNTAX_ERROR)); YYABORT; Loading