Commit 58cfdc20 authored by unknown's avatar unknown
Browse files

Merge moonlight.home:/home/tomash/src/mysql_ab/mysql-5.1

into  moonlight.home:/home/tomash/src/mysql_ab/mysql-5.1-bug16425


sql/sql_yacc.yy:
  Auto merged
parents 22f242cd 2b48825b
Loading
Loading
Loading
Loading
+53 −0
Original line number Diff line number Diff line
@@ -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;
+57 −0
Original line number Diff line number Diff line
@@ -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
#
+11 −10
Original line number Diff line number Diff line
@@ -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"));
@@ -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));

+92 −77
Original line number Diff line number Diff line
@@ -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

@@ -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()->
@@ -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:
+8 −7
Original line number Diff line number Diff line
@@ -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
@@ -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
@@ -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;