summaryrefslogtreecommitdiff
path: root/sql/sql_repl.cc
diff options
context:
space:
mode:
authorSergei Golubchik <serg@mariadb.org>2015-09-02 09:58:08 +0200
committerSergei Golubchik <serg@mariadb.org>2015-09-04 10:33:55 +0200
commitb85a00161e91080cb82b99e812c18eafb6467737 (patch)
tree3b502db8d25f0eb0a93901e3417d097626ecf8ea /sql/sql_repl.cc
parent41d68cabee1d9c2a8e8c7a006b17070392a85ed7 (diff)
downloadmariadb-git-b85a00161e91080cb82b99e812c18eafb6467737.tar.gz
MDEV-8264 encryption for binlog
* Start_encryption_log_event * --encrypt-binlog command line option based on google patches.
Diffstat (limited to 'sql/sql_repl.cc')
-rw-r--r--sql/sql_repl.cc160
1 files changed, 137 insertions, 23 deletions
diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc
index 2a4c26de1c9..5cf55d89d3e 100644
--- a/sql/sql_repl.cc
+++ b/sql/sql_repl.cc
@@ -644,6 +644,9 @@ void set_read_error(binlog_send_info *info, int error)
case LOG_READ_CHECKSUM_FAILURE:
info->errmsg= "event read from binlog did not pass crc check";
break;
+ case LOG_READ_DECRYPT:
+ info->errmsg= "event decryption failure";
+ break;
default:
info->errmsg= "unknown error reading log event on the master";
break;
@@ -918,9 +921,14 @@ get_gtid_list_event(IO_CACHE *cache, Gtid_list_log_event **out_gtid_list)
typ= ev->get_type_code();
if (typ == GTID_LIST_EVENT)
break; /* Done, found it */
+ if (typ == START_ENCRYPTION_EVENT)
+ {
+ if (fdle->start_decryption((Start_encryption_log_event*) ev))
+ errormsg= "Could not set up decryption for binlog.";
+ }
delete ev;
if (typ == ROTATE_EVENT || typ == STOP_EVENT ||
- typ == FORMAT_DESCRIPTION_EVENT)
+ typ == FORMAT_DESCRIPTION_EVENT || typ == START_ENCRYPTION_EVENT)
continue; /* Continue looking */
/* We did not find any Gtid_list_log_event, must be old binlog. */
@@ -1437,7 +1445,7 @@ gtid_state_from_pos(const char *name, uint32 offset,
break;
packet.length(0);
- err= Log_event::read_log_event(&cache, &packet,
+ err= Log_event::read_log_event(&cache, &packet, fdev,
opt_master_verify_checksum ? current_checksum_alg
: BINLOG_CHECKSUM_ALG_OFF);
if (err)
@@ -1474,6 +1482,20 @@ gtid_state_from_pos(const char *name, uint32 offset,
delete fdev;
fdev= tmp;
}
+ else if (typ == START_ENCRYPTION_EVENT)
+ {
+ uint sele_len = packet.length();
+ if (current_checksum_alg == BINLOG_CHECKSUM_ALG_CRC32)
+ {
+ sele_len -= BINLOG_CHECKSUM_LEN;
+ }
+ Start_encryption_log_event sele(packet.ptr(), sele_len, fdev);
+ if (fdev->start_decryption(&sele))
+ {
+ errormsg= "Could not start decryption of binlog.";
+ goto end;
+ }
+ }
else if (typ != FORMAT_DESCRIPTION_EVENT && !found_format_description_event)
{
errormsg= "Did not find format description log event while searching "
@@ -2216,9 +2238,10 @@ static int send_format_descriptor_event(binlog_send_info *info, IO_CACHE *log,
the binlog
*/
info->last_pos= my_b_tell(log);
- error= Log_event::read_log_event(log, packet,
+ error= Log_event::read_log_event(log, packet, info->fdev,
opt_master_verify_checksum
- ? info->current_checksum_alg : BINLOG_CHECKSUM_ALG_OFF);
+ ? info->current_checksum_alg
+ : BINLOG_CHECKSUM_ALG_OFF);
linfo->pos= my_b_tell(log);
if (error)
@@ -2268,10 +2291,13 @@ static int send_format_descriptor_event(binlog_send_info *info, IO_CACHE *log,
return 1;
}
+ uint ev_len= packet->length() - ev_offset;
+ if (info->current_checksum_alg != BINLOG_CHECKSUM_ALG_UNDEF)
+ ev_len-= BINLOG_CHECKSUM_LEN;
+
Format_description_log_event *tmp;
- if (!(tmp= new Format_description_log_event(packet->ptr()+ev_offset,
- packet->length()-ev_offset,
- info->fdev)))
+ if (!(tmp= new Format_description_log_event(packet->ptr() + ev_offset,
+ ev_len, info->fdev)))
{
info->error= ER_MASTER_FATAL_ERROR_READING_BINLOG;
info->errmsg= "Corrupt Format_description event found "
@@ -2338,6 +2364,57 @@ static int send_format_descriptor_event(binlog_send_info *info, IO_CACHE *log,
return 1;
}
+ /*
+ Read the following Start_encryption_log_event but don't send it to slave.
+ Slave doesn't need to know whether master's binlog is encrypted,
+ and if it'll want to encrypt its logs, it should generate its own
+ random nonce, not use the one from the master.
+ */
+ packet->length(0);
+ info->last_pos= linfo->pos;
+ error= Log_event::read_log_event(log, packet, info->fdev,
+ opt_master_verify_checksum
+ ? info->current_checksum_alg
+ : BINLOG_CHECKSUM_ALG_OFF);
+ linfo->pos= my_b_tell(log);
+
+ if (error)
+ {
+ set_read_error(info, error);
+ return 1;
+ }
+
+ event_type= (Log_event_type)((uchar)(*packet)[LOG_EVENT_OFFSET]);
+ if (event_type == START_ENCRYPTION_EVENT)
+ {
+ Start_encryption_log_event *sele= (Start_encryption_log_event *)
+ Log_event::read_log_event(packet->ptr(), packet->length(), &info->errmsg,
+ info->fdev, BINLOG_CHECKSUM_ALG_OFF);
+ if (!sele)
+ {
+ info->error= ER_MASTER_FATAL_ERROR_READING_BINLOG;
+ return 1;
+ }
+
+ if (info->fdev->start_decryption(sele))
+ {
+ info->error= ER_MASTER_FATAL_ERROR_READING_BINLOG;
+ info->errmsg= "Could not decrypt binlog: encryption key error";
+ return 1;
+ }
+ delete sele;
+ }
+ else if (start_pos == BIN_LOG_HEADER_SIZE)
+ {
+ /*
+ not Start_encryption_log_event - seek back. But only if
+ send_one_binlog_file() isn't going to seek anyway
+ */
+ my_b_seek(log, info->last_pos);
+ linfo->pos= info->last_pos;
+ }
+
+
/** all done */
return 0;
}
@@ -2547,7 +2624,7 @@ static int send_events(binlog_send_info *info, IO_CACHE* log, LOG_INFO* linfo,
return 1;
info->last_pos= linfo->pos;
- error= Log_event::read_log_event(log, packet,
+ error= Log_event::read_log_event(log, packet, info->fdev,
opt_master_verify_checksum ? info->current_checksum_alg
: BINLOG_CHECKSUM_ALG_OFF);
linfo->pos= my_b_tell(log);
@@ -2598,8 +2675,9 @@ static int send_events(binlog_send_info *info, IO_CACHE* log, LOG_INFO* linfo,
});
#endif
- if ((info->errmsg= send_event_to_slave(info, event_type, log,
- ev_offset, &info->error_gtid)))
+ if (event_type != START_ENCRYPTION_EVENT &&
+ ((info->errmsg= send_event_to_slave(info, event_type, log,
+ ev_offset, &info->error_gtid))))
return 1;
if (unlikely(info->send_fake_gtid_list) &&
@@ -3876,38 +3954,52 @@ bool mysql_show_binlog_events(THD* thd)
Read the first event in case it's a Format_description_log_event, to
know the format. If there's no such event, we are 3.23 or 4.x. This
code, like before, can't read 3.23 binlogs.
+ Also read the second event, in case it's a Start_encryption_log_event.
This code will fail on a mixed relay log (one which has Format_desc then
Rotate then Format_desc).
*/
- ev= Log_event::read_log_event(&log, (mysql_mutex_t*)0, description_event,
- opt_master_verify_checksum);
- if (ev)
+
+ my_off_t scan_pos = BIN_LOG_HEADER_SIZE;
+ while (scan_pos < pos)
{
+ ev= Log_event::read_log_event(&log, (mysql_mutex_t*)0, description_event,
+ opt_master_verify_checksum);
+ scan_pos = my_b_tell(&log);
+ if (ev == NULL || !ev->is_valid())
+ {
+ mysql_mutex_unlock(log_lock);
+ errmsg = "Wrong offset or I/O error";
+ goto err;
+ }
if (ev->get_type_code() == FORMAT_DESCRIPTION_EVENT)
{
delete description_event;
description_event= (Format_description_log_event*) ev;
}
else
+ {
+ if (ev->get_type_code() == START_ENCRYPTION_EVENT)
+ {
+ if (description_event->start_decryption((Start_encryption_log_event*) ev))
+ {
+ delete ev;
+ mysql_mutex_unlock(log_lock);
+ errmsg = "Could not initialize decryption of binlog.";
+ goto err;
+ }
+ }
delete ev;
+ break;
+ }
}
my_b_seek(&log, pos);
- if (!description_event->is_valid())
- {
- errmsg="Invalid Format_description event; could be out of memory";
- goto err;
- }
-
for (event_count = 0;
(ev = Log_event::read_log_event(&log, (mysql_mutex_t*) 0,
description_event,
opt_master_verify_checksum)); )
{
- if (ev->get_type_code() == FORMAT_DESCRIPTION_EVENT)
- description_event->checksum_alg= ev->checksum_alg;
-
if (event_count >= limit_start &&
ev->net_send(thd, protocol, linfo.log_file_name, pos))
{
@@ -3917,8 +4009,30 @@ bool mysql_show_binlog_events(THD* thd)
goto err;
}
+ if (ev->get_type_code() == FORMAT_DESCRIPTION_EVENT)
+ {
+ Format_description_log_event* new_fdle=
+ (Format_description_log_event*) ev;
+ new_fdle->copy_crypto_data(description_event);
+ delete description_event;
+ description_event= new_fdle;
+ }
+ else
+ {
+ if (ev->get_type_code() == START_ENCRYPTION_EVENT)
+ {
+ if (description_event->start_decryption((Start_encryption_log_event*) ev))
+ {
+ errmsg = "Error starting decryption";
+ delete ev;
+ mysql_mutex_unlock(log_lock);
+ goto err;
+ }
+ }
+ delete ev;
+ }
+
pos = my_b_tell(&log);
- delete ev;
if (++event_count >= limit_end)
break;