@@ -38,6 +38,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
3838#include " keyring_operations_helper.h"
3939
4040#include " backup_mysql.h"
41+ #include " ddl_tracker.h"
4142#include " keyring_plugins.h"
4243#include " rpl_log_encryption.h"
4344#include " utils.h"
@@ -186,17 +187,6 @@ dberr_t xb_set_encryption(fil_space_t *space) {
186187 return (fil_set_encryption (space->id , Encryption::AES , key, iv));
187188}
188189
189- #define TRANSITION_KEY_PREFIX_STR " XBKey"
190-
191- const char *TRANSITION_KEY_PREFIX = TRANSITION_KEY_PREFIX_STR ;
192- const size_t TRANSITION_KEY_PREFIX_LEN = sizeof (TRANSITION_KEY_PREFIX_STR ) - 1 ;
193- const size_t TRANSITION_KEY_RANDOM_DATA_LEN = 32 ;
194- const size_t TRANSITION_KEY_NAME_MAX_LEN_V1 =
195- Encryption::SERVER_UUID_LEN + 2 + 45 ;
196- const size_t TRANSITION_KEY_NAME_MAX_LEN_V2 =
197- TRANSITION_KEY_PREFIX_LEN + Encryption::SERVER_UUID_LEN +
198- TRANSITION_KEY_RANDOM_DATA_LEN + 1 ;
199-
200190/* * Fetch the key from keyring.
201191@param[in] key_name key name
202192@param[out] key key
@@ -250,9 +240,14 @@ static bool xb_create_transition_key(char *key_name, char *key) {
250240
251241 base64_encode (rand32, 20 , rand64);
252242
243+ std::ostringstream oss;
244+
253245 /* Trasnsition key name is composed of server uuid and random suffix. */
254- snprintf (key_name, TRANSITION_KEY_NAME_MAX_LEN_V2 , " %s-%s-%s" ,
255- TRANSITION_KEY_PREFIX , server_uuid, rand64);
246+ oss << TRANSITION_KEY_PREFIX << ' -' << server_uuid << ' -' << rand64;
247+ std::string s = oss.str ();
248+ memset (key_name, 0 , TRANSITION_KEY_NAME_MAX_LEN_V2 );
249+ std::memcpy (key_name, s.data (),
250+ std::min (s.size (), TRANSITION_KEY_NAME_MAX_LEN_V2 ));
256251
257252 /* Let keyring generate key for us. */
258253 ret = srv_keyring_generator->generate (key_name, nullptr , " AES" ,
@@ -661,120 +656,6 @@ static bool xb_tablespace_keys_write_single(ds_file_t *stream,
661656 return (true );
662657}
663658
664- /* * Dump tablespace keys into encrypted "xtrabackup_keys" file.
665- @param[in] ds_ctxt datasink context to output file into
666- @param[in] transition_key transition key used to encrypt
667- tablespace keys
668- @param[in] transition_key_len transition key length
669- @return true if success */
670- bool xb_tablespace_keys_dump (ds_ctxt_t *ds_ctxt, const char *transition_key,
671- size_t transition_key_len) {
672- byte derived_key[Encryption::KEY_LEN ];
673- byte salt[XB_KDF_SALT_SIZE ];
674- char transition_key_name[TRANSITION_KEY_NAME_MAX_LEN_V2 ];
675- char transition_key_buf[Encryption::KEY_LEN ];
676-
677- xb::info () << " Saving " << XTRABACKUP_KEYS_FILE ;
678-
679- if (my_rand_buffer (salt, sizeof (salt)) != 0 ) {
680- return (false );
681- }
682-
683- memset (transition_key_name, 0 , sizeof (transition_key_name));
684-
685- if (transition_key == NULL ) {
686- if (!xb_create_transition_key (transition_key_name, transition_key_buf)) {
687- return (false );
688- }
689- transition_key = transition_key_buf;
690- transition_key_len = Encryption::KEY_LEN ;
691- }
692-
693- xb_libgcrypt_init ();
694- bool ret = xb_derive_key (transition_key, transition_key_len, salt,
695- sizeof (salt), sizeof (derived_key), derived_key);
696-
697- if (!ret) {
698- xb::error () << " Error writing " << XTRABACKUP_KEYS_FILE
699- << " : failed to derive encryption key." ;
700- return (false );
701- }
702-
703- dberr_t err;
704- MY_STAT stat_info;
705- memset (&stat_info, 0 , sizeof (MY_STAT ));
706-
707- ds_file_t *stream = ds_open (ds_ctxt, XTRABACKUP_KEYS_FILE , &stat_info);
708- if (stream == NULL ) {
709- xb::error () << " Error writing " << XTRABACKUP_KEYS_FILE
710- << " : failed to create file." ;
711- return (false );
712- }
713-
714- if (ds_write (stream, XTRABACKUP_KEYS_MAGIC_V2 , XTRABACKUP_KEYS_MAGIC_SIZE )) {
715- xb::error () << " Error writing " << XTRABACKUP_KEYS_FILE
716- << " : failed to write magic." ;
717- goto error;
718- }
719-
720- if (ds_write (stream, salt, sizeof (salt))) {
721- xb::error () << " Error writing " << XTRABACKUP_KEYS_FILE
722- << " : failed to write salt." ;
723- goto error;
724- }
725-
726- if (ds_write (stream, transition_key_name, sizeof (transition_key_name))) {
727- xb::error () << " Error writing " << XTRABACKUP_KEYS_FILE
728- << " : failed to write transition key name." ;
729- goto error;
730- }
731-
732- err = Fil_space_iterator::for_each_space ([&](fil_space_t *space) {
733- if (space->m_encryption_metadata .m_type == Encryption::NONE ) {
734- return (DB_SUCCESS );
735- }
736- if (!xb_tablespace_keys_write_single (stream, derived_key, space->id ,
737- space->m_encryption_metadata .m_key ,
738- space->m_encryption_metadata .m_iv )) {
739- xb::error () << " Error writing " << XTRABACKUP_KEYS_FILE
740- << " : failed to save tablespace key." ;
741- return (DB_ERROR );
742- }
743- return (DB_SUCCESS );
744- });
745-
746- if (err != DB_SUCCESS ) {
747- goto error;
748- }
749-
750- if (recv_sys->keys != nullptr ) {
751- for (auto &key : *recv_sys->keys ) {
752- if (!xb_tablespace_keys_write_single (stream, derived_key, key.space_id ,
753- key.ptr , key.iv )) {
754- xb::error () << " Error writing " << XTRABACKUP_KEYS_FILE
755- << " : failed to save tablespace key." ;
756- goto error;
757- }
758- }
759- }
760-
761- for (const auto &entry : encryption_info) {
762- if (!xb_tablespace_keys_write_single (stream, derived_key, entry.first ,
763- entry.second .key , entry.second .iv )) {
764- xb::error () << " Error writing " << XTRABACKUP_KEYS_FILE
765- << " : failed to save tablespace key." ;
766- goto error;
767- }
768- }
769-
770- ds_close (stream);
771- return (true );
772-
773- error:
774- ds_close (stream);
775- return (false );
776- }
777-
778659/* *
779660 Read encrypted binlog file header
780661
@@ -896,3 +777,157 @@ void xb_keyring_shutdown() {
896777 free_list (opt_plugin_load_list_ptr);
897778 xtrabackup::components::deinitialize_service_handles ();
898779}
780+
781+ TablespaceKeyDumper::TablespaceKeyDumper (ds_ctxt_t *ds_ctxt,
782+ const char *transition_key,
783+ size_t transition_key_len)
784+ : m_ds_ctxt(ds_ctxt),
785+ m_transition_key(transition_key),
786+ m_transition_key_len(transition_key_len),
787+ m_stream(nullptr ),
788+ m_state(State::Init),
789+ m_finalized(false ) {
790+ memset (m_salt, 0 , sizeof (m_salt));
791+ memset (m_derived_key, 0 , sizeof (m_derived_key));
792+ memset (m_transition_key_name, 0 , sizeof (m_transition_key_name));
793+ }
794+
795+ bool TablespaceKeyDumper::is_initialized () const {
796+ return m_state != State::Init;
797+ }
798+
799+ bool TablespaceKeyDumper::initialize () {
800+ xb::info () << " Saving " << XTRABACKUP_KEYS_FILE ;
801+
802+ if (my_rand_buffer (m_salt, sizeof (m_salt)) != 0 ) return false ;
803+
804+ if (m_transition_key == nullptr ) {
805+ if (!xb_create_transition_key (m_transition_key_name,
806+ m_transition_key_buf)) {
807+ return false ;
808+ }
809+ m_transition_key = m_transition_key_buf;
810+ m_transition_key_len = Encryption::KEY_LEN ;
811+ }
812+
813+ xb_libgcrypt_init ();
814+ if (!xb_derive_key (m_transition_key, m_transition_key_len, m_salt,
815+ sizeof (m_salt), sizeof (m_derived_key), m_derived_key)) {
816+ xb::error () << " Error writing " << XTRABACKUP_KEYS_FILE
817+ << " : failed to derive encryption key." ;
818+ return false ;
819+ }
820+
821+ MY_STAT stat_info;
822+ memset (&stat_info, 0 , sizeof (MY_STAT ));
823+
824+ m_stream = ds_open (m_ds_ctxt, XTRABACKUP_KEYS_FILE , &stat_info);
825+ if (!m_stream) {
826+ xb::error () << " Error writing " << XTRABACKUP_KEYS_FILE
827+ << " : failed to create file." ;
828+ return false ;
829+ }
830+
831+ if (ds_write (m_stream, XTRABACKUP_KEYS_MAGIC_V2 ,
832+ XTRABACKUP_KEYS_MAGIC_SIZE ) ||
833+ ds_write (m_stream, m_salt, sizeof (m_salt)) ||
834+ ds_write (m_stream, m_transition_key_name,
835+ sizeof (m_transition_key_name))) {
836+ xb::error () << " Error writing " << XTRABACKUP_KEYS_FILE
837+ << " : failed to write header." ;
838+ ds_close (m_stream);
839+ m_stream = nullptr ;
840+ return false ;
841+ }
842+
843+ m_state = State::Initialized;
844+ return true ;
845+ }
846+
847+ bool TablespaceKeyDumper::dump_from_spaces (bool use_ddl_tracker) {
848+ if (use_ddl_tracker) {
849+ ut_a (ddl_tracker != nullptr );
850+ }
851+
852+ if (m_state != State::Initialized && m_state != State::SpacesDumpedOnce)
853+ return fail_state (" dump_from_spaces" );
854+
855+ m_state = State::SpacesDumpedOnce;
856+
857+ dberr_t err = Fil_space_iterator::for_each_space ([&](fil_space_t *space) {
858+ if (space->m_encryption_metadata .m_type == Encryption::NONE ) {
859+ return DB_SUCCESS ;
860+ }
861+
862+ if (use_ddl_tracker && ddl_tracker != nullptr ) {
863+ if (ddl_tracker->is_tablespace_dropped (space->id )) {
864+ return DB_SUCCESS ;
865+ }
866+ }
867+
868+ if (!xb_tablespace_keys_write_single (m_stream, m_derived_key, space->id ,
869+ space->m_encryption_metadata .m_key ,
870+ space->m_encryption_metadata .m_iv )) {
871+ xb::error () << " Error writing " << XTRABACKUP_KEYS_FILE
872+ << " : failed to save tablespace key." ;
873+ return DB_ERROR ;
874+ }
875+
876+ return DB_SUCCESS ;
877+ });
878+
879+ return err == DB_SUCCESS ;
880+ }
881+
882+ bool TablespaceKeyDumper::dump_from_redo () {
883+ if (m_state != State::SpacesDumpedOnce) return fail_state (" dump_from_redo" );
884+ m_state = State::RecoveryDumped;
885+
886+ if (!recv_sys || !recv_sys->keys ) return true ;
887+
888+ for (auto &key : *recv_sys->keys ) {
889+ if (!xb_tablespace_keys_write_single (m_stream, m_derived_key, key.space_id ,
890+ key.ptr , key.iv )) {
891+ xb::error () << " Error writing " << XTRABACKUP_KEYS_FILE
892+ << " : failed to save tablespace key." ;
893+ return false ;
894+ }
895+ }
896+
897+ return true ;
898+ }
899+
900+ bool TablespaceKeyDumper::dump_from_encryption_infos () {
901+ if (m_state != State::RecoveryDumped)
902+ return fail_state (" dump_from_encryption_infos" );
903+ m_state = State::EncryptionInfosDumped;
904+
905+ for (const auto &entry : encryption_info) {
906+ if (!xb_tablespace_keys_write_single (m_stream, m_derived_key, entry.first ,
907+ entry.second .key , entry.second .iv )) {
908+ xb::error () << " Error writing " << XTRABACKUP_KEYS_FILE
909+ << " : failed to save tablespace key." ;
910+ return false ;
911+ }
912+ }
913+
914+ return true ;
915+ }
916+
917+ void TablespaceKeyDumper::finalize () {
918+ if (m_stream) {
919+ ds_close (m_stream);
920+ m_stream = nullptr ;
921+ }
922+ m_finalized = true ;
923+ }
924+
925+ TablespaceKeyDumper::~TablespaceKeyDumper () {
926+ assert (m_finalized && " finalize() must be called before destruction" );
927+ }
928+
929+ bool TablespaceKeyDumper::fail_state (const char *func) {
930+ xb::error () << " Invalid call to " << func
931+ << " : incorrect stage or already called." ;
932+ return false ;
933+ }
0 commit comments