diff options
author | Marko Mäkelä <marko.makela@mariadb.com> | 2019-02-28 23:11:15 +0200 |
---|---|---|
committer | Marko Mäkelä <marko.makela@mariadb.com> | 2019-02-28 23:20:31 +0200 |
commit | e39d6e0c53bccaf0c6b2a0341f8deb420f5e79be (patch) | |
tree | a9b1664661e3164f80b8f1d2737751684b7c2aef | |
parent | 622e9e8a7a5e9babe1dd41e7499c20f396b6ebdf (diff) | |
download | mariadb-git-e39d6e0c53bccaf0c6b2a0341f8deb420f5e79be.tar.gz |
MDEV-18601 Can't create table with ENCRYPTED=DEFAULT when innodb_default_encryption_key_id!=1
The problem with the InnoDB table attribute encryption_key_id is that it is
not being persisted anywhere in InnoDB except if the table attribute
encryption is specified and is something else than encryption=default.
MDEV-17320 made it a hard error if encryption_key_id is specified to be
anything else than 1 in that case.
Ideally, we would always persist encryption_key_id in InnoDB. But, then we
would have to be prepared for the case that when encryption is being enabled
for a table whose encryption_key_id attribute refers to a non-existing key.
In MariaDB Server 10.1, our best option remains to not store anything
inside InnoDB. But, instead of returning the error that MDEV-17320
introduced, we should merely issue a warning that the specified
encryption_key_id is going to be ignored if encryption=default.
To improve the situation a little more, we will issue a warning if
SET [GLOBAL|SESSION] innodb_default_encryption_key_id is being set
to something that does not refer to an available encryption key.
Starting with MariaDB Server 10.2, thanks to MDEV-5800, we could open the
table definition from InnoDB side when the encryption is being enabled,
and actually fix the root cause of what was reported in MDEV-17320.
8 files changed, 182 insertions, 162 deletions
diff --git a/mysql-test/suite/encryption/r/innodb-checksum-algorithm,32k.rdiff b/mysql-test/suite/encryption/r/innodb-checksum-algorithm,32k.rdiff index cd66df7440b..d963cde132a 100644 --- a/mysql-test/suite/encryption/r/innodb-checksum-algorithm,32k.rdiff +++ b/mysql-test/suite/encryption/r/innodb-checksum-algorithm,32k.rdiff @@ -1,5 +1,5 @@ --- suite/encryption/r/innodb-checksum-algorithm.result -+++ suite/encryption/r/innodb-checksum-algorithm,32k.reject ++++ suite/encryption/r/innodb-checksum-algorithm.result @@ -13,9 +13,9 @@ SET GLOBAL innodb_default_encryption_key_id=4; SET GLOBAL innodb_checksum_algorithm=crc32; @@ -9,10 +9,10 @@ create table tc_crc32(a serial, b blob, index(b(10))) engine=innodb -ROW_FORMAT=COMPRESSED encrypted=no; +ROW_FORMAT=DYNAMIC encrypted=no; + Warnings: + Warning 140 InnoDB: ENCRYPTED=NO implies ENCRYPTION_KEY_ID=1 create table te_crc32(a serial, b blob, index(b(10))) engine=innodb - encrypted=yes; - create table t_crc32(a serial, b blob, index(b(10))) engine=innodb -@@ -222,9 +222,9 @@ +@@ -153,9 +153,9 @@ t_crc32, tpe_crc32, tp_crc32; SET GLOBAL innodb_checksum_algorithm=innodb; create table tce_innodb(a serial, b blob, index(b(10))) engine=innodb @@ -21,10 +21,10 @@ create table tc_innodb(a serial, b blob, index(b(10))) engine=innodb -ROW_FORMAT=COMPRESSED encrypted=no; +ROW_FORMAT=DYNAMIC encrypted=no; + Warnings: + Warning 140 InnoDB: ENCRYPTED=NO implies ENCRYPTION_KEY_ID=1 create table te_innodb(a serial, b blob, index(b(10))) engine=innodb - encrypted=yes; - create table t_innodb(a serial, b blob, index(b(10))) engine=innodb -@@ -431,9 +431,9 @@ +@@ -293,9 +293,9 @@ t_innodb, tpe_innodb, tp_innodb; SET GLOBAL innodb_checksum_algorithm=none; create table tce_none(a serial, b blob, index(b(10))) engine=innodb @@ -33,6 +33,6 @@ create table tc_none(a serial, b blob, index(b(10))) engine=innodb -ROW_FORMAT=COMPRESSED encrypted=no; +ROW_FORMAT=DYNAMIC encrypted=no; + Warnings: + Warning 140 InnoDB: ENCRYPTED=NO implies ENCRYPTION_KEY_ID=1 create table te_none(a serial, b blob, index(b(10))) engine=innodb - encrypted=yes; - create table t_none(a serial, b blob, index(b(10))) engine=innodb diff --git a/mysql-test/suite/encryption/r/innodb-checksum-algorithm,64k.rdiff b/mysql-test/suite/encryption/r/innodb-checksum-algorithm,64k.rdiff index 523074297da..d963cde132a 100644 --- a/mysql-test/suite/encryption/r/innodb-checksum-algorithm,64k.rdiff +++ b/mysql-test/suite/encryption/r/innodb-checksum-algorithm,64k.rdiff @@ -1,5 +1,5 @@ --- suite/encryption/r/innodb-checksum-algorithm.result -+++ suite/encryption/r/innodb-checksum-algorithm,64k.reject ++++ suite/encryption/r/innodb-checksum-algorithm.result @@ -13,9 +13,9 @@ SET GLOBAL innodb_default_encryption_key_id=4; SET GLOBAL innodb_checksum_algorithm=crc32; @@ -9,10 +9,10 @@ create table tc_crc32(a serial, b blob, index(b(10))) engine=innodb -ROW_FORMAT=COMPRESSED encrypted=no; +ROW_FORMAT=DYNAMIC encrypted=no; + Warnings: + Warning 140 InnoDB: ENCRYPTED=NO implies ENCRYPTION_KEY_ID=1 create table te_crc32(a serial, b blob, index(b(10))) engine=innodb - encrypted=yes; - create table t_crc32(a serial, b blob, index(b(10))) engine=innodb -@@ -222,9 +222,9 @@ +@@ -153,9 +153,9 @@ t_crc32, tpe_crc32, tp_crc32; SET GLOBAL innodb_checksum_algorithm=innodb; create table tce_innodb(a serial, b blob, index(b(10))) engine=innodb @@ -21,10 +21,10 @@ create table tc_innodb(a serial, b blob, index(b(10))) engine=innodb -ROW_FORMAT=COMPRESSED encrypted=no; +ROW_FORMAT=DYNAMIC encrypted=no; + Warnings: + Warning 140 InnoDB: ENCRYPTED=NO implies ENCRYPTION_KEY_ID=1 create table te_innodb(a serial, b blob, index(b(10))) engine=innodb - encrypted=yes; - create table t_innodb(a serial, b blob, index(b(10))) engine=innodb -@@ -431,9 +431,9 @@ +@@ -293,9 +293,9 @@ t_innodb, tpe_innodb, tp_innodb; SET GLOBAL innodb_checksum_algorithm=none; create table tce_none(a serial, b blob, index(b(10))) engine=innodb @@ -33,6 +33,6 @@ create table tc_none(a serial, b blob, index(b(10))) engine=innodb -ROW_FORMAT=COMPRESSED encrypted=no; +ROW_FORMAT=DYNAMIC encrypted=no; + Warnings: + Warning 140 InnoDB: ENCRYPTED=NO implies ENCRYPTION_KEY_ID=1 create table te_none(a serial, b blob, index(b(10))) engine=innodb - encrypted=yes; - create table t_none(a serial, b blob, index(b(10))) engine=innodb diff --git a/mysql-test/suite/encryption/r/innodb-checksum-algorithm.result b/mysql-test/suite/encryption/r/innodb-checksum-algorithm.result index 7fdea4b67b5..6fa2e7c594f 100644 --- a/mysql-test/suite/encryption/r/innodb-checksum-algorithm.result +++ b/mysql-test/suite/encryption/r/innodb-checksum-algorithm.result @@ -16,14 +16,20 @@ create table tce_crc32(a serial, b blob, index(b(10))) engine=innodb ROW_FORMAT=COMPRESSED encrypted=yes; create table tc_crc32(a serial, b blob, index(b(10))) engine=innodb ROW_FORMAT=COMPRESSED encrypted=no; +Warnings: +Warning 140 InnoDB: ENCRYPTED=NO implies ENCRYPTION_KEY_ID=1 create table te_crc32(a serial, b blob, index(b(10))) engine=innodb encrypted=yes; create table t_crc32(a serial, b blob, index(b(10))) engine=innodb encrypted=no; +Warnings: +Warning 140 InnoDB: ENCRYPTED=NO implies ENCRYPTION_KEY_ID=1 create table tpe_crc32(a serial, b blob, index(b(10))) engine=innodb page_compressed=yes encrypted=yes; create table tp_crc32(a serial, b blob, index(b(10))) engine=innodb page_compressed=yes encrypted=no; +Warnings: +Warning 140 InnoDB: ENCRYPTED=NO implies ENCRYPTION_KEY_ID=1 begin; insert into tce_crc32(b) values (repeat('secret',20)); insert into tc_crc32(b) values (repeat('secret',20)); @@ -150,14 +156,20 @@ create table tce_innodb(a serial, b blob, index(b(10))) engine=innodb ROW_FORMAT=COMPRESSED encrypted=yes; create table tc_innodb(a serial, b blob, index(b(10))) engine=innodb ROW_FORMAT=COMPRESSED encrypted=no; +Warnings: +Warning 140 InnoDB: ENCRYPTED=NO implies ENCRYPTION_KEY_ID=1 create table te_innodb(a serial, b blob, index(b(10))) engine=innodb encrypted=yes; create table t_innodb(a serial, b blob, index(b(10))) engine=innodb encrypted=no; +Warnings: +Warning 140 InnoDB: ENCRYPTED=NO implies ENCRYPTION_KEY_ID=1 create table tpe_innodb(a serial, b blob, index(b(10))) engine=innodb page_compressed=yes encrypted=yes; create table tp_innodb(a serial, b blob, index(b(10))) engine=innodb page_compressed=yes encrypted=no; +Warnings: +Warning 140 InnoDB: ENCRYPTED=NO implies ENCRYPTION_KEY_ID=1 begin; insert into tce_innodb(b) values (repeat('secret',20)); insert into tc_innodb(b) values (repeat('secret',20)); @@ -284,14 +296,20 @@ create table tce_none(a serial, b blob, index(b(10))) engine=innodb ROW_FORMAT=COMPRESSED encrypted=yes; create table tc_none(a serial, b blob, index(b(10))) engine=innodb ROW_FORMAT=COMPRESSED encrypted=no; +Warnings: +Warning 140 InnoDB: ENCRYPTED=NO implies ENCRYPTION_KEY_ID=1 create table te_none(a serial, b blob, index(b(10))) engine=innodb encrypted=yes; create table t_none(a serial, b blob, index(b(10))) engine=innodb encrypted=no; +Warnings: +Warning 140 InnoDB: ENCRYPTED=NO implies ENCRYPTION_KEY_ID=1 create table tpe_none(a serial, b blob, index(b(10))) engine=innodb page_compressed=yes encrypted=yes; create table tp_none(a serial, b blob, index(b(10))) engine=innodb page_compressed=yes encrypted=no; +Warnings: +Warning 140 InnoDB: ENCRYPTED=NO implies ENCRYPTION_KEY_ID=1 begin; insert into tce_none(b) values (repeat('secret',20)); insert into tc_none(b) values (repeat('secret',20)); diff --git a/mysql-test/suite/encryption/r/innodb-compressed-blob.result b/mysql-test/suite/encryption/r/innodb-compressed-blob.result index ce73b80820f..4187877be49 100644 --- a/mysql-test/suite/encryption/r/innodb-compressed-blob.result +++ b/mysql-test/suite/encryption/r/innodb-compressed-blob.result @@ -7,6 +7,8 @@ set GLOBAL innodb_default_encryption_key_id=4; create table t1(a int not null primary key, b blob, index(b(10))) engine=innodb row_format=compressed; create table t2(a int not null primary key, b blob, index(b(10))) engine=innodb row_format=compressed encrypted=yes; create table t3(a int not null primary key, b blob, index(b(10))) engine=innodb row_format=compressed encrypted=no; +Warnings: +Warning 140 InnoDB: ENCRYPTED=NO implies ENCRYPTION_KEY_ID=1 insert into t1 values (1, repeat('secret',6000)); insert into t2 values (1, repeat('secret',6000)); insert into t3 values (1, repeat('secret',6000)); diff --git a/mysql-test/suite/encryption/r/innodb-encryption-alter.result b/mysql-test/suite/encryption/r/innodb-encryption-alter.result index 5245d1da7d0..b2f33b2b24d 100644 --- a/mysql-test/suite/encryption/r/innodb-encryption-alter.result +++ b/mysql-test/suite/encryption/r/innodb-encryption-alter.result @@ -4,9 +4,16 @@ SET GLOBAL innodb_encrypt_tables = ON; SET GLOBAL innodb_encryption_threads = 4; CREATE TABLE t1 (pk INT PRIMARY KEY AUTO_INCREMENT, c VARCHAR(256)) ENGINE=INNODB ENCRYPTED=NO ENCRYPTION_KEY_ID=4; Warnings: -Warning 140 InnoDB: Ignored ENCRYPTION_KEY_ID 4 when encryption is disabled +Warning 140 InnoDB: ENCRYPTED=NO implies ENCRYPTION_KEY_ID=1 DROP TABLE t1; +set @save_global = @@GLOBAL.innodb_default_encryption_key_id; set innodb_default_encryption_key_id = 99; +Warnings: +Warning 1210 innodb_default_encryption_key=99 is not available +set global innodb_default_encryption_key_id = 99; +Warnings: +Warning 1210 innodb_default_encryption_key=99 is not available +set global innodb_default_encryption_key_id = @save_global; CREATE TABLE t1 (pk INT PRIMARY KEY AUTO_INCREMENT, c VARCHAR(256)) ENGINE=INNODB; ERROR HY000: Can't create table `test`.`t1` (errno: 140 "Wrong create options") SHOW WARNINGS; @@ -40,8 +47,6 @@ t1 CREATE TABLE `t1` ( PRIMARY KEY (`pk`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 `ENCRYPTION_KEY_ID`=4 CREATE TABLE t2 (pk INT PRIMARY KEY AUTO_INCREMENT, c VARCHAR(256)) ENGINE=INNODB ENCRYPTED=NO ENCRYPTION_KEY_ID=1; -Warnings: -Warning 140 InnoDB: Ignored ENCRYPTION_KEY_ID 1 when encryption is disabled ALTER TABLE t1 ENCRYPTION_KEY_ID=99; ERROR HY000: Table storage engine 'InnoDB' does not support the create option 'ENCRYPTION_KEY_ID' SHOW WARNINGS; @@ -53,37 +58,29 @@ drop table t1,t2; SET GLOBAL innodb_encrypt_tables=OFF; CREATE TABLE t1 (a int not null primary key) engine=innodb; ALTER TABLE t1 ENCRYPTION_KEY_ID=4; -ERROR HY000: Table storage engine 'InnoDB' does not support the create option 'ENCRYPTION_KEY_ID' -SHOW WARNINGS; -Level Code Message -Warning 140 InnoDB: innodb_encrypt_tables=OFF only allows ENCRYPTION_KEY_ID=1 -Error 1478 Table storage engine 'InnoDB' does not support the create option 'ENCRYPTION_KEY_ID' SHOW CREATE TABLE t1; Table Create Table t1 CREATE TABLE `t1` ( `a` int(11) NOT NULL, PRIMARY KEY (`a`) -) ENGINE=InnoDB DEFAULT CHARSET=latin1 +) ENGINE=InnoDB DEFAULT CHARSET=latin1 `ENCRYPTION_KEY_ID`=4 DROP TABLE t1; CREATE TABLE t2 (a int not null primary key) engine=innodb; ALTER TABLE t2 ENCRYPTION_KEY_ID=4, ALGORITHM=COPY; -ERROR HY000: Can't create table `test`.`#sql-temporary` (errno: 140 "Wrong create options") -SHOW WARNINGS; -Level Code Message -Warning 140 InnoDB: innodb_encrypt_tables=OFF only allows ENCRYPTION_KEY_ID=1 -Error 1005 Can't create table `test`.`#sql-temporary` (errno: 140 "Wrong create options") -Warning 1030 Got error 140 "Wrong create options" from storage engine InnoDB SHOW CREATE TABLE t2; Table Create Table t2 CREATE TABLE `t2` ( `a` int(11) NOT NULL, PRIMARY KEY (`a`) -) ENGINE=InnoDB DEFAULT CHARSET=latin1 +) ENGINE=InnoDB DEFAULT CHARSET=latin1 `ENCRYPTION_KEY_ID`=4 DROP TABLE t2; CREATE TABLE t3 (a int not null primary key) engine=innodb ENCRYPTION_KEY_ID=4; -ERROR HY000: Can't create table `test`.`t3` (errno: 140 "Wrong create options") +DROP TABLE t3; +SET GLOBAL innodb_encrypt_tables='FORCE'; +CREATE TABLE t1 (a int primary key) engine=innodb encrypted=no; +ERROR HY000: Can't create table `test`.`t1` (errno: 140 "Wrong create options") SHOW WARNINGS; Level Code Message -Warning 140 InnoDB: innodb_encrypt_tables=OFF only allows ENCRYPTION_KEY_ID=1 -Error 1005 Can't create table `test`.`t3` (errno: 140 "Wrong create options") +Warning 140 InnoDB: ENCRYPTED=NO cannot be used with innodb_encrypt_tables=FORCE +Error 1005 Can't create table `test`.`t1` (errno: 140 "Wrong create options") Warning 1030 Got error 140 "Wrong create options" from storage engine InnoDB diff --git a/mysql-test/suite/encryption/t/innodb-encryption-alter.test b/mysql-test/suite/encryption/t/innodb-encryption-alter.test index 9465226dd96..711beeef1e1 100644 --- a/mysql-test/suite/encryption/t/innodb-encryption-alter.test +++ b/mysql-test/suite/encryption/t/innodb-encryption-alter.test @@ -19,7 +19,10 @@ SET GLOBAL innodb_encryption_threads = 4; CREATE TABLE t1 (pk INT PRIMARY KEY AUTO_INCREMENT, c VARCHAR(256)) ENGINE=INNODB ENCRYPTED=NO ENCRYPTION_KEY_ID=4; DROP TABLE t1; +set @save_global = @@GLOBAL.innodb_default_encryption_key_id; set innodb_default_encryption_key_id = 99; +set global innodb_default_encryption_key_id = 99; +set global innodb_default_encryption_key_id = @save_global; --error 1005 CREATE TABLE t1 (pk INT PRIMARY KEY AUTO_INCREMENT, c VARCHAR(256)) ENGINE=INNODB; SHOW WARNINGS; @@ -90,25 +93,26 @@ drop table t1,t2; # # MDEV-17230: encryption_key_id from alter is ignored by encryption threads # +--enable_warnings SET GLOBAL innodb_encrypt_tables=OFF; CREATE TABLE t1 (a int not null primary key) engine=innodb; ---error ER_ILLEGAL_HA_CREATE_OPTION ALTER TABLE t1 ENCRYPTION_KEY_ID=4; -SHOW WARNINGS; SHOW CREATE TABLE t1; DROP TABLE t1; CREATE TABLE t2 (a int not null primary key) engine=innodb; --replace_regex /#sql-[0-9a-f_]*`/#sql-temporary`/ ---error ER_CANT_CREATE_TABLE ALTER TABLE t2 ENCRYPTION_KEY_ID=4, ALGORITHM=COPY; --replace_regex /#sql-[0-9a-f_]*`/#sql-temporary`/ -SHOW WARNINGS; SHOW CREATE TABLE t2; DROP TABLE t2; ---error ER_CANT_CREATE_TABLE CREATE TABLE t3 (a int not null primary key) engine=innodb ENCRYPTION_KEY_ID=4; +DROP TABLE t3; + +SET GLOBAL innodb_encrypt_tables='FORCE'; +--error ER_CANT_CREATE_TABLE +CREATE TABLE t1 (a int primary key) engine=innodb encrypted=no; SHOW WARNINGS; # reset system diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 80ff2e02e13..c670839b5cd 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -4,7 +4,7 @@ Copyright (c) 2000, 2018, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2008, 2009 Google Inc. Copyright (c) 2009, Percona Inc. Copyright (c) 2012, Facebook Inc. -Copyright (c) 2013, 2018, MariaDB Corporation. +Copyright (c) 2013, 2019, MariaDB Corporation. Portions of this file contain modifications contributed and copyrighted by Google, Inc. Those modifications are gratefully acknowledged and are described @@ -686,9 +686,25 @@ static int mysql_tmpfile_path(const char *path, const char *prefix) static void innodb_remember_check_sysvar_funcs(); mysql_var_check_func check_sysvar_enum; +/** Update callback for SET [SESSION] innodb_default_encryption_key_id */ +static void +innodb_default_encryption_key_id_update(THD* thd, st_mysql_sys_var* var, + void* var_ptr, const void *save) +{ + uint key_id = *static_cast<const uint*>(save); + if (key_id != FIL_DEFAULT_ENCRYPTION_KEY + && !encryption_key_id_exists(key_id)) { + push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, + ER_WRONG_ARGUMENTS, + "innodb_default_encryption_key=%u" + " is not available", key_id); + } + *static_cast<uint*>(var_ptr) = key_id; +} + static MYSQL_THDVAR_UINT(default_encryption_key_id, PLUGIN_VAR_RQCMDARG, "Default encryption key id used for table encryption.", - NULL, NULL, + NULL, innodb_default_encryption_key_id_update, FIL_DEFAULT_ENCRYPTION_KEY, 1, UINT_MAX32, 0); /** @@ -10862,8 +10878,7 @@ create_table_def( const char* remote_path, /*!< in: Remote path or zero length-string */ ulint flags, /*!< in: table flags */ ulint flags2, /*!< in: table flags2 */ - fil_encryption_t mode, /*!< in: encryption mode */ - ulint key_id) /*!< in: encryption key_id */ + const ha_table_option_struct*options) { THD* thd = trx->mysql_thd; dict_table_t* table; @@ -11053,7 +11068,9 @@ err_col: fts_add_doc_id_column(table, heap); } - err = row_create_table_for_mysql(table, trx, false, mode, key_id); + err = row_create_table_for_mysql(table, trx, false, + fil_encryption_t(options->encryption), + options->encryption_key_id); mem_heap_free(heap); @@ -11887,21 +11904,47 @@ ha_innobase::check_table_options( enum row_type row_format = table->s->row_type; ha_table_option_struct *options= table->s->option_struct; atomic_writes_t awrites = (atomic_writes_t)options->atomic_writes; - fil_encryption_t encrypt = (fil_encryption_t)options->encryption; - if (encrypt != FIL_ENCRYPTION_DEFAULT && !use_tablespace) { + switch (options->encryption) { + case FIL_ENCRYPTION_OFF: + if (options->encryption_key_id != FIL_DEFAULT_ENCRYPTION_KEY) { + push_warning( + thd, Sql_condition::WARN_LEVEL_WARN, + HA_WRONG_CREATE_OPTION, + "InnoDB: ENCRYPTED=NO implies" + " ENCRYPTION_KEY_ID=1"); + compile_time_assert(FIL_DEFAULT_ENCRYPTION_KEY == 1); + } + if (srv_encrypt_tables != 2) { + break; + } push_warning( thd, Sql_condition::WARN_LEVEL_WARN, HA_WRONG_CREATE_OPTION, - "InnoDB: ENCRYPTED requires innodb_file_per_table"); + "InnoDB: ENCRYPTED=NO cannot be used with" + " innodb_encrypt_tables=FORCE"); return "ENCRYPTED"; - } + case FIL_ENCRYPTION_DEFAULT: + if (!srv_encrypt_tables) { + break; + } + /* fall through */ + case FIL_ENCRYPTION_ON: + if (!encryption_key_id_exists(options->encryption_key_id)) { + push_warning_printf( + thd, Sql_condition::WARN_LEVEL_WARN, + HA_WRONG_CREATE_OPTION, + "InnoDB: ENCRYPTION_KEY_ID %u not available", + options->encryption_key_id); + return "ENCRYPTION_KEY_ID"; + } + } - if (encrypt == FIL_ENCRYPTION_OFF && srv_encrypt_tables == 2) { - push_warning( - thd, Sql_condition::WARN_LEVEL_WARN, - HA_WRONG_CREATE_OPTION, - "InnoDB: ENCRYPTED=OFF cannot be used when innodb_encrypt_tables=FORCE"); + if (!use_tablespace && options->encryption != FIL_ENCRYPTION_DEFAULT) { + push_warning(thd, Sql_condition::WARN_LEVEL_WARN, + HA_WRONG_CREATE_OPTION, + "InnoDB: ENCRYPTED requires" + " innodb_file_per_table"); return "ENCRYPTED"; } @@ -11977,46 +12020,6 @@ ha_innobase::check_table_options( } } - /* If encryption is set up make sure that used key_id is found */ - if (encrypt == FIL_ENCRYPTION_ON || - (encrypt == FIL_ENCRYPTION_DEFAULT && srv_encrypt_tables)) { - if (!encryption_key_id_exists((unsigned int)options->encryption_key_id)) { - push_warning_printf( - thd, Sql_condition::WARN_LEVEL_WARN, - HA_WRONG_CREATE_OPTION, - "InnoDB: ENCRYPTION_KEY_ID %u not available", - (uint)options->encryption_key_id - ); - return "ENCRYPTION_KEY_ID"; - } - } - - /* Ignore nondefault key_id if encryption is set off */ - if (encrypt == FIL_ENCRYPTION_OFF && - options->encryption_key_id != THDVAR(thd, default_encryption_key_id)) { - push_warning_printf( - thd, Sql_condition::WARN_LEVEL_WARN, - HA_WRONG_CREATE_OPTION, - "InnoDB: Ignored ENCRYPTION_KEY_ID %u when encryption is disabled", - (uint)options->encryption_key_id - ); - options->encryption_key_id = FIL_DEFAULT_ENCRYPTION_KEY; - } - - /* If default encryption is used and encryption is disabled, you may - not use nondefault encryption_key_id as it is not stored anywhere. */ - if (encrypt == FIL_ENCRYPTION_DEFAULT - && !srv_encrypt_tables - && options->encryption_key_id != FIL_DEFAULT_ENCRYPTION_KEY) { - compile_time_assert(FIL_DEFAULT_ENCRYPTION_KEY == 1); - push_warning_printf( - thd, Sql_condition::WARN_LEVEL_WARN, - HA_WRONG_CREATE_OPTION, - "InnoDB: innodb_encrypt_tables=OFF only allows ENCRYPTION_KEY_ID=1" - ); - return "ENCRYPTION_KEY_ID"; - } - /* Check atomic writes requirements */ if (awrites == ATOMIC_WRITES_ON || (awrites == ATOMIC_WRITES_DEFAULT && srv_use_atomic_writes)) { @@ -12074,10 +12077,6 @@ ha_innobase::create( const char* stmt; size_t stmt_len; - /* Cache table options */ - ha_table_option_struct *options= form->s->option_struct; - fil_encryption_t encrypt = (fil_encryption_t)options->encryption; - uint key_id = (uint)options->encryption_key_id; DBUG_ENTER("ha_innobase::create"); @@ -12100,7 +12099,7 @@ ha_innobase::create( /* Validate create options if innodb_strict_mode is set. */ if (create_options_are_invalid( - thd, form, create_info, use_tablespace)) { + thd, form, create_info, use_tablespace)) { DBUG_RETURN(HA_WRONG_CREATE_OPTION); } @@ -12170,7 +12169,8 @@ ha_innobase::create( row_mysql_lock_data_dictionary(trx); error = create_table_def(trx, form, norm_name, temp_path, - remote_path, flags, flags2, encrypt, key_id); + remote_path, flags, flags2, + form->s->option_struct); if (error) { goto cleanup; } diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc index 4ed9f644b45..d943a87ab78 100644 --- a/storage/xtradb/handler/ha_innodb.cc +++ b/storage/xtradb/handler/ha_innodb.cc @@ -5,7 +5,7 @@ Copyright (c) 2013, 2018, MariaDB Corporation. Copyright (c) 2008, 2009 Google Inc. Copyright (c) 2009, Percona Inc. Copyright (c) 2012, Facebook Inc. -Copyright (c) 2013, 2018, MariaDB Corporation. +Copyright (c) 2013, 2019, MariaDB Corporation. Portions of this file contain modifications contributed and copyrighted by Google, Inc. Those modifications are gratefully acknowledged and are described @@ -687,9 +687,25 @@ ib_cb_t innodb_api_cb[] = { static void innodb_remember_check_sysvar_funcs(); mysql_var_check_func check_sysvar_enum; +/** Update callback for SET [SESSION] innodb_default_encryption_key_id */ +static void +innodb_default_encryption_key_id_update(THD* thd, st_mysql_sys_var* var, + void* var_ptr, const void *save) +{ + uint key_id = *static_cast<const uint*>(save); + if (key_id != FIL_DEFAULT_ENCRYPTION_KEY + && !encryption_key_id_exists(key_id)) { + push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, + ER_WRONG_ARGUMENTS, + "innodb_default_encryption_key=%u" + " is not available", key_id); + } + *static_cast<uint*>(var_ptr) = key_id; +} + static MYSQL_THDVAR_UINT(default_encryption_key_id, PLUGIN_VAR_RQCMDARG, "Default encryption key id used for table encryption.", - NULL, NULL, + NULL, innodb_default_encryption_key_id_update, FIL_DEFAULT_ENCRYPTION_KEY, 1, UINT_MAX32, 0); /** @@ -11430,8 +11446,7 @@ create_table_def( const char* remote_path, /*!< in: Remote path or zero length-string */ ulint flags, /*!< in: table flags */ ulint flags2, /*!< in: table flags2 */ - fil_encryption_t mode, /*!< in: encryption mode */ - ulint key_id) /*!< in: encryption key_id */ + const ha_table_option_struct*options) { THD* thd = trx->mysql_thd; dict_table_t* table; @@ -11622,7 +11637,9 @@ err_col: fts_add_doc_id_column(table, heap); } - err = row_create_table_for_mysql(table, trx, false, mode, key_id); + err = row_create_table_for_mysql(table, trx, false, + fil_encryption_t(options->encryption), + options->encryption_key_id); mem_heap_free(heap); @@ -12453,21 +12470,47 @@ ha_innobase::check_table_options( enum row_type row_format = table->s->row_type; ha_table_option_struct *options= table->s->option_struct; atomic_writes_t awrites = (atomic_writes_t)options->atomic_writes; - fil_encryption_t encrypt = (fil_encryption_t)options->encryption; - if (encrypt != FIL_ENCRYPTION_DEFAULT && !use_tablespace) { + switch (options->encryption) { + case FIL_ENCRYPTION_OFF: + if (options->encryption_key_id != FIL_DEFAULT_ENCRYPTION_KEY) { + push_warning( + thd, Sql_condition::WARN_LEVEL_WARN, + HA_WRONG_CREATE_OPTION, + "InnoDB: ENCRYPTED=NO implies" + " ENCRYPTION_KEY_ID=1"); + compile_time_assert(FIL_DEFAULT_ENCRYPTION_KEY == 1); + } + if (srv_encrypt_tables != 2) { + break; + } push_warning( thd, Sql_condition::WARN_LEVEL_WARN, HA_WRONG_CREATE_OPTION, - "InnoDB: ENCRYPTED requires innodb_file_per_table"); + "InnoDB: ENCRYPTED=NO cannot be used with" + " innodb_encrypt_tables=FORCE"); return "ENCRYPTED"; + case FIL_ENCRYPTION_DEFAULT: + if (!srv_encrypt_tables) { + break; + } + /* fall through */ + case FIL_ENCRYPTION_ON: + if (!encryption_key_id_exists(options->encryption_key_id)) { + push_warning_printf( + thd, Sql_condition::WARN_LEVEL_WARN, + HA_WRONG_CREATE_OPTION, + "InnoDB: ENCRYPTION_KEY_ID %u not available", + options->encryption_key_id); + return "ENCRYPTION_KEY_ID"; + } } - if (encrypt == FIL_ENCRYPTION_OFF && srv_encrypt_tables == 2) { - push_warning( - thd, Sql_condition::WARN_LEVEL_WARN, - HA_WRONG_CREATE_OPTION, - "InnoDB: ENCRYPTED=OFF cannot be used when innodb_encrypt_tables=FORCE"); + if (!use_tablespace && options->encryption != FIL_ENCRYPTION_DEFAULT) { + push_warning(thd, Sql_condition::WARN_LEVEL_WARN, + HA_WRONG_CREATE_OPTION, + "InnoDB: ENCRYPTED requires" + " innodb_file_per_table"); return "ENCRYPTED"; } @@ -12543,47 +12586,6 @@ ha_innobase::check_table_options( } } - /* If encryption is set up make sure that used key_id is found */ - if (encrypt == FIL_ENCRYPTION_ON || - (encrypt == FIL_ENCRYPTION_DEFAULT && srv_encrypt_tables)) { - if (!encryption_key_id_exists((unsigned int)options->encryption_key_id)) { - push_warning_printf( - thd, Sql_condition::WARN_LEVEL_WARN, - HA_WRONG_CREATE_OPTION, - "InnoDB: ENCRYPTION_KEY_ID %u not available", - (uint)options->encryption_key_id - ); - return "ENCRYPTION_KEY_ID"; - - } - } - - /* Ignore nondefault key_id if encryption is set off */ - if (encrypt == FIL_ENCRYPTION_OFF && - options->encryption_key_id != THDVAR(thd, default_encryption_key_id)) { - push_warning_printf( - thd, Sql_condition::WARN_LEVEL_WARN, - HA_WRONG_CREATE_OPTION, - "InnoDB: Ignored ENCRYPTION_KEY_ID %u when encryption is disabled", - (uint)options->encryption_key_id - ); - options->encryption_key_id = FIL_DEFAULT_ENCRYPTION_KEY; - } - - /* If default encryption is used and encryption is disabled, you may - not use nondefault encryption_key_id as it is not stored anywhere. */ - if (encrypt == FIL_ENCRYPTION_DEFAULT - && !srv_encrypt_tables - && options->encryption_key_id != FIL_DEFAULT_ENCRYPTION_KEY) { - compile_time_assert(FIL_DEFAULT_ENCRYPTION_KEY == 1); - push_warning_printf( - thd, Sql_condition::WARN_LEVEL_WARN, - HA_WRONG_CREATE_OPTION, - "InnoDB: innodb_encrypt_tables=OFF only allows ENCRYPTION_KEY_ID=1" - ); - return "ENCRYPTION_KEY_ID"; - } - /* Check atomic writes requirements */ if (awrites == ATOMIC_WRITES_ON || (awrites == ATOMIC_WRITES_DEFAULT && srv_use_atomic_writes)) { @@ -12641,10 +12643,6 @@ ha_innobase::create( const char* stmt; size_t stmt_len; - /* Cache table options */ - ha_table_option_struct *options= form->s->option_struct; - fil_encryption_t encrypt = (fil_encryption_t)options->encryption; - uint key_id = (uint)options->encryption_key_id; DBUG_ENTER("ha_innobase::create"); @@ -12667,7 +12665,7 @@ ha_innobase::create( /* Validate create options if innodb_strict_mode is set. */ if (create_options_are_invalid( - thd, form, create_info, use_tablespace)) { + thd, form, create_info, use_tablespace)) { DBUG_RETURN(HA_WRONG_CREATE_OPTION); } @@ -12743,7 +12741,8 @@ ha_innobase::create( row_mysql_lock_data_dictionary(trx); error = create_table_def(trx, form, norm_name, temp_path, - remote_path, flags, flags2, encrypt, key_id); + remote_path, flags, flags2, + form->s->option_struct); if (error) { goto cleanup; } |