← Back to team overview

maria-developers team mailing list archive

Re: [Commits] c204e9b: MDEV-9610 Trigger on normal table can't insert into CONNECT engine table - Access Denied

 

Hi Sergei,


On 04/25/2016 08:42 PM, serg@xxxxxxxxxxx wrote:
revision-id: c204e9bd63e7f6ce40e83b1f7fc0b4607a131009 (mariadb-10.0.24-43-gc204e9b)
parent(s): ce38adddfa91949b30956abd0e4cab201effcdef
author: Sergei Golubchik
committer: Sergei Golubchik
timestamp: 2016-04-25 18:41:31 +0200
message:

MDEV-9610 Trigger on normal table can't insert into CONNECT engine table - Access Denied

in case of prelocking, don't check table->grant.privilege
in handler::external_lock(), do it in
handler::start_stmt().

---
  storage/connect/ha_connect.cc                      | 58 ++++++++++++++++++++--
  storage/connect/ha_connect.h                       |  1 +
  storage/connect/mysql-test/connect/r/grant3.result |  5 ++
  storage/connect/mysql-test/connect/t/grant3.test   | 11 ++++
  4 files changed, 70 insertions(+), 5 deletions(-)

diff --git a/storage/connect/ha_connect.cc b/storage/connect/ha_connect.cc
index 645d000..1032567 100644
--- a/storage/connect/ha_connect.cc
+++ b/storage/connect/ha_connect.cc
@@ -4054,6 +4054,14 @@ int ha_connect::delete_all_rows()
  } // end of delete_all_rows


+static void issue_access_denied_error(THD *thd)
+{
+  status_var_increment(thd->status_var.access_denied_errors);
+  my_error(access_denied_error_code(thd->password), MYF(0),
+           thd->security_ctx->priv_user, thd->security_ctx->priv_host,
+           (thd->password ?  ER(ER_YES) : ER(ER_NO)));
+}
+
  bool ha_connect::check_privileges(THD *thd, PTOS options, char *dbn)
  {
    const char *db= (dbn && *dbn) ? dbn : NULL;
@@ -4124,12 +4132,9 @@ bool ha_connect::check_privileges(THD *thd, PTOS options, char *dbn)
        */
        if (!table || !table->mdl_ticket || table->mdl_ticket->get_type() == MDL_EXCLUSIVE)
          return check_access(thd, FILE_ACL, db, NULL, NULL, 0, 0);
-      if (table->grant.privilege & FILE_ACL)
+      if (thd->lex->requires_prelocking() || table->grant.privilege & FILE_ACL)
          return false;
-      status_var_increment(thd->status_var.access_denied_errors);
-      my_error(access_denied_error_code(thd->password), MYF(0),
-               thd->security_ctx->priv_user, thd->security_ctx->priv_host,
-               (thd->password ?  ER(ER_YES) : ER(ER_NO)));
+      issue_access_denied_error(thd);
        return true;

      // This is temporary until a solution is found
@@ -4146,6 +4151,46 @@ bool ha_connect::check_privileges(THD *thd, PTOS options, char *dbn)
    return true;
  } // end of check_privileges

+bool ha_connect::check_cached_privileges(THD *thd)
+{
+  PTOS  options= GetTableOptionStruct();
+  TABTYPE     type=GetRealType(options);
+
+#ifdef NO_EMBEDDED_ACCESS_CHECKS
+    return false;
+#endif
+
+  switch (type) {
+    case TAB_DOS:
+    case TAB_FIX:
+    case TAB_BIN:
+    case TAB_CSV:
+    case TAB_FMT:
+    case TAB_DBF:
+    case TAB_XML:
+    case TAB_INI:
+    case TAB_VEC:
+    case TAB_JSON:
+      if (!options->filename || !*options->filename)
+        return false;
+      /* Fall through to check FILE_ACL */
+    case TAB_ODBC:
+    case TAB_MYSQL:
+    case TAB_DIR:
+    case TAB_MAC:
+    case TAB_WMI:
+    case TAB_OEM:
+      if (table->grant.privilege & FILE_ACL)
+        return false;
+      issue_access_denied_error(thd);
+      return true;
+    default:

The patch looks fine.

I'd suggest two things.

1. Don't use "default"
Can you please list all possible type value instead of "default"?
Otherwise, when a new table type is added the next time, it will be
easier to forget to update check_cached_privileges() accordingly.


2. Try to avoid duplicate code.


Btw, I'd probably try to remove the duplicate switch,
by adding a new method like this:


enum Extra_acl
{
  CONNECT_SECURE_FILE_PATH= 1,
  CONNECT_FILE_ACL=         1<<1;
}

int ha_connect::extra_acl_needed(THD *thd, PTOS options)
{
  ...
  switch (GetRealType(options)) {
  ...
  case TAB_DOS:
  case TAB_FIX:
  case TAB_BIN:
  case TAB_CSV:
  case TAB_FMT:
  case TAB_DBF:
  case TAB_XML:
  case TAB_INI:
  case TAB_VEC:
  case TAB_JSON:
    return (options->filename && *options->filename) ?
            CONNECT_SECURE_FILE_PATH : 0;
  case TAB_ODBC:
  case TAB_MYSQL:
  case TAB_DIR:
  case TAB_MAC:
  case TAB_WMI:
  case TAB_OEM:
#ifdef NO_EMBEDDED_ACCESS_CHECKS
    return 0;
#endif
    return CONNECT_FILE_ACL;
  ...
  }
  ...
}


And then reuse it in both ha_connect::check_privilege()
and ha_connect::check_cached_privileges().

The latter would look about like this:


bool ha_connect::check_cached_privileges(THD *thd)
{
  PTOS  options= GetTableOptionStruct();
  if (!(extra_acl_needed(options) & CONNECT_FILE_ACL) ||
      (table->grant.privilege & FILE_ACL))
    return false;
  issue_access_denied_error(thd);
  return true;
}


+      return false;
+  }
+  return false;
+
+} // end of check_cached_privileges
+
  // Check that two indexes are equivalent
  bool ha_connect::IsSameIndex(PIXDEF xp1, PIXDEF xp2)
  {
@@ -4308,6 +4353,9 @@ int ha_connect::start_stmt(THD *thd, thr_lock_type lock_type)
    PGLOBAL g= GetPlug(thd, xp);
    DBUG_ENTER("ha_connect::start_stmt");

+  if (check_cached_privileges(thd))
+    DBUG_RETURN(HA_ERR_INTERNAL_ERROR);
+
    // Action will depend on lock_type
    switch (lock_type) {
      case TL_WRITE_ALLOW_WRITE:
diff --git a/storage/connect/ha_connect.h b/storage/connect/ha_connect.h
index 05cc872..fae804b 100644
--- a/storage/connect/ha_connect.h
+++ b/storage/connect/ha_connect.h
@@ -537,6 +537,7 @@ int index_prev(uchar *buf);

  protected:
    bool check_privileges(THD *thd, PTOS options, char *dbn);
+  bool check_cached_privileges(THD *thd);

It looks like the number of leading spaces is wrong here.


    MODE CheckMode(PGLOBAL g, THD *thd, MODE newmode, bool *chk, bool *cras);
    char *GetDBfromName(const char *name);

diff --git a/storage/connect/mysql-test/connect/r/grant3.result b/storage/connect/mysql-test/connect/r/grant3.result
new file mode 100644
index 0000000..2f9d37b
--- /dev/null
+++ b/storage/connect/mysql-test/connect/r/grant3.result
@@ -0,0 +1,5 @@
+create table tcon (i int) engine=Connect table_type=DOS file_name='tcon.dos';
+create table tin (i int);
+create trigger tr after insert on tin for each row insert into tcon values (new.i);
+insert into tin values (1);
+drop table tin,tcon;
diff --git a/storage/connect/mysql-test/connect/t/grant3.test b/storage/connect/mysql-test/connect/t/grant3.test
new file mode 100644
index 0000000..9f05ca7
--- /dev/null
+++ b/storage/connect/mysql-test/connect/t/grant3.test
@@ -0,0 +1,11 @@
+#
+# MDEV-9610 Trigger on normal table can't insert into CONNECT engine table - Access Denied
+#
+create table tcon (i int) engine=Connect table_type=DOS file_name='tcon.dos';
+create table tin (i int);
+create trigger tr after insert on tin for each row insert into tcon values (new.i);
+insert into tin values (1);
+drop table tin,tcon;
+
+let datadir=`select @@datadir`;
+remove_file $datadir/test/tcon.dos;
_______________________________________________
commits mailing list
commits@xxxxxxxxxxx
https://lists.askmonty.org/cgi-bin/mailman/listinfo/commits



Follow ups