Binlog files have 15 bytes of header XORed with IV
Events saved and read have 15 bytes of header XORed with IV. Partial events are still not handled. Next implementation will encrypt the whole event instead of 15 bytes XOR
This commit is contained in:
@ -941,10 +941,11 @@ newSession(ROUTER *instance, SESSION *session)
|
||||
slave->mariadb10_compat = false;
|
||||
slave->heartbeat = 0;
|
||||
slave->lastEventReceived = 0;
|
||||
slave->encryption_ctx = NULL;
|
||||
|
||||
/**
|
||||
* Add this session to the list of active sessions.
|
||||
*/
|
||||
* Add this session to the list of active sessions.
|
||||
*/
|
||||
spinlock_acquire(&inst->lock);
|
||||
slave->next = inst->slaves;
|
||||
inst->slaves = slave;
|
||||
@ -1021,6 +1022,10 @@ static void freeSession(ROUTER* router_instance,
|
||||
{
|
||||
MXS_FREE(slave->passwd);
|
||||
}
|
||||
if (slave->encryption_ctx)
|
||||
{
|
||||
MXS_FREE(slave->encryption_ctx);
|
||||
}
|
||||
MXS_FREE(slave);
|
||||
}
|
||||
|
||||
|
@ -77,6 +77,7 @@ extern uint32_t extract_field(uint8_t *src, int bits);
|
||||
static void blr_format_event_size(double *event_size, char *label);
|
||||
extern int MaxScaleUptime();
|
||||
extern void encode_value(unsigned char *data, unsigned int value, int len);
|
||||
extern void blr_extract_header(register uint8_t *ptr, register REP_HEADER *hdr);
|
||||
|
||||
typedef struct binlog_event_desc
|
||||
{
|
||||
@ -108,19 +109,6 @@ typedef enum
|
||||
BLRM_START_ENCRYPTION /*< Start Encryption event */
|
||||
} generated_event_t;
|
||||
|
||||
/**
|
||||
* The offset in FDE event content that points to the number of events
|
||||
* the master server supports.
|
||||
*/
|
||||
|
||||
/* Defines and offsets for binlog encryption */
|
||||
#define BLRM_FDE_EVENT_TYPES_OFFSET (2 + 50 + 4 + 1)
|
||||
#define BLRM_CRYPTO_SCHEME_LENGTH 1
|
||||
#define BLRM_KEY_VERSION_LENGTH 4
|
||||
#define BLRM_IV_LENGTH AES_BLOCK_SIZE
|
||||
#define BLRM_IV_OFFS_LENGTH 4
|
||||
#define BLRM_NONCE_LENGTH (BLRM_IV_LENGTH - BLRM_IV_OFFS_LENGTH)
|
||||
|
||||
/**
|
||||
* MariaDB 10.1.7 Start Encryption event content
|
||||
*
|
||||
@ -142,22 +130,6 @@ typedef struct start_encryption_event
|
||||
* form the encrryption IV for the event */
|
||||
} START_ENCRYPTION_EVENT;
|
||||
|
||||
/**
|
||||
* Binlog encryption context of current binlog file
|
||||
*
|
||||
* nonce for current binlog
|
||||
* key version
|
||||
* crypto_scheme
|
||||
*/
|
||||
typedef struct binlog_encryption_ctx
|
||||
{
|
||||
uint8_t binlog_crypto_scheme; /**< Encryption scheme */
|
||||
uint32_t binlog_key_version; /**< Encryption key version */
|
||||
uint8_t nonce[BLRM_NONCE_LENGTH]; /**< nonce (random bytes) of current binlog.
|
||||
* These bytes + the binlog event current pos
|
||||
* form the encrryption IV for the event */
|
||||
} BINLOG_ENCRYPTION_CTX;
|
||||
|
||||
/**
|
||||
* Initialise the binlog file for this instance. MaxScale will look
|
||||
* for all the binlogs that it has on local disk, determine the next
|
||||
@ -441,6 +413,7 @@ blr_write_binlog_record(ROUTER_INSTANCE *router, REP_HEADER *hdr, uint32_t size,
|
||||
int n;
|
||||
bool write_begin_encryption = false;
|
||||
uint64_t file_offset = router->current_pos;
|
||||
uint32_t event_size[4];
|
||||
|
||||
/* Track whether FORMAT_DESCRIPTION_EVENT has been received */
|
||||
if (hdr->event_type == FORMAT_DESCRIPTION_EVENT)
|
||||
@ -462,7 +435,7 @@ blr_write_binlog_record(ROUTER_INSTANCE *router, REP_HEADER *hdr, uint32_t size,
|
||||
}
|
||||
}
|
||||
|
||||
if (router->encryption_ctx != NULL)
|
||||
if (router->encryption.enabled && router->encryption_ctx != NULL && !write_begin_encryption)
|
||||
{
|
||||
BINLOG_ENCRYPTION_CTX *tmp_encryption_ctx = (BINLOG_ENCRYPTION_CTX *)(router->encryption_ctx);
|
||||
uint8_t iv[BLRM_IV_LENGTH];
|
||||
@ -484,21 +457,31 @@ blr_write_binlog_record(ROUTER_INSTANCE *router, REP_HEADER *hdr, uint32_t size,
|
||||
nonce_hex,
|
||||
tmp_encryption_ctx->binlog_crypto_scheme,
|
||||
tmp_encryption_ctx->binlog_key_version);
|
||||
|
||||
/**
|
||||
* Encrypt binlog event:
|
||||
*
|
||||
* Save event size (buf + 9, 4 bytes)
|
||||
* move first 4 bytes of buf to buf + 9 ...
|
||||
* encrypt buf starting from buf + 4 (so it will be event_size - 4)
|
||||
* move encrypted_data + 9, (4 bytes), to encrypted_data[0]
|
||||
* write saved_event_size 4 bytes into encrypted_data + 9
|
||||
* write encrypted_data
|
||||
*/
|
||||
|
||||
memcpy(&event_size, buf + BINLOG_EVENT_LEN_OFFSET , 4);
|
||||
memmove(buf + BINLOG_EVENT_LEN_OFFSET, buf, 4);
|
||||
uint8_t *buf_ptr = buf + 4;
|
||||
/* 16 bytes after buf + 4 are owerwritten by XORed with IV */
|
||||
/* Only 15 bytes are involved */
|
||||
for (int i=0; i < (AES_BLOCK_SIZE - 1); i++)
|
||||
{
|
||||
buf_ptr[i]= buf_ptr[i] ^ iv[i];
|
||||
}
|
||||
memmove(buf, buf + BINLOG_EVENT_LEN_OFFSET, 4);
|
||||
memcpy(buf + BINLOG_EVENT_LEN_OFFSET, &event_size, 4);
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO:
|
||||
*
|
||||
* save event size (buf + 9, 4 bytes)
|
||||
* move first 4 bytes of buf to buf + 9 ...
|
||||
* encrypt buf starting from buf + 4 (so it will be event_size - 4)
|
||||
* move encrypted_data + 9, (4 bytesi), to encrypted_data[0]
|
||||
* write saved_event_size 4 bytes into encrypted_data + 9
|
||||
* write encrypted_data
|
||||
*
|
||||
* First task is the data move only in current 'buf', no encryption at all.
|
||||
*/
|
||||
|
||||
|
||||
/* Write current received event from master */
|
||||
if ((n = pwrite(router->binlog_fd, buf, size,
|
||||
router->last_written)) != size)
|
||||
@ -622,6 +605,8 @@ blr_open_binlog(ROUTER_INSTANCE *router, char *binlog)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
file->encryption_ctx = NULL;
|
||||
|
||||
file->next = router->files;
|
||||
router->files = file;
|
||||
spinlock_release(&router->fileslock);
|
||||
@ -648,6 +633,7 @@ blr_read_binlog(ROUTER_INSTANCE *router, BLFILE *file, unsigned long pos, REP_HE
|
||||
int n;
|
||||
unsigned long filelen = 0;
|
||||
struct stat statb;
|
||||
SLAVE_ENCRYPTION_CTX *file_enc_ctx = NULL;
|
||||
|
||||
memset(hdbuf, '\0', BINLOG_EVENT_HDR_LEN);
|
||||
|
||||
@ -732,6 +718,10 @@ blr_read_binlog(ROUTER_INSTANCE *router, BLFILE *file, unsigned long pos, REP_HE
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Get encryption_ctx */
|
||||
file_enc_ctx = file->encryption_ctx;
|
||||
|
||||
spinlock_release(&file->lock);
|
||||
spinlock_release(&router->binlog_lock);
|
||||
|
||||
@ -772,6 +762,35 @@ blr_read_binlog(ROUTER_INSTANCE *router, BLFILE *file, unsigned long pos, REP_HE
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Check whether we need to decrypt the current event */
|
||||
if (file_enc_ctx && pos >= file_enc_ctx->first_enc_event_pos)
|
||||
{
|
||||
uint8_t *event_ptr = hdbuf;
|
||||
uint8_t iv[AES_BLOCK_SIZE];
|
||||
uint8_t event_size[4];
|
||||
|
||||
/* Encryption IV is 12 bytes nonce + 4 bytes event position */
|
||||
memcpy(&iv, file_enc_ctx->nonce, BLRM_NONCE_LENGTH);
|
||||
gw_mysql_set_byte4(iv + BLRM_NONCE_LENGTH, (unsigned long)pos);
|
||||
|
||||
/* Save event size */
|
||||
memcpy(&event_size, event_ptr + BINLOG_EVENT_LEN_OFFSET , 4);
|
||||
|
||||
MXS_INFO("Decoding encrypted event @ pos %lu, size %lu",
|
||||
(unsigned long)pos, (unsigned long)extract_field(event_size, 32));
|
||||
|
||||
memmove(event_ptr + BINLOG_EVENT_LEN_OFFSET, event_ptr, 4);
|
||||
uint8_t *buf_ptr = event_ptr + 4;
|
||||
/* 16 bytes after buf + 4 are owerwritten by XORed with IV */
|
||||
// 15 for now
|
||||
for (int i=0; i < (AES_BLOCK_SIZE - 1); i++)
|
||||
{
|
||||
buf_ptr[i]= buf_ptr[i] ^ iv[i];
|
||||
}
|
||||
memmove(event_ptr, event_ptr + BINLOG_EVENT_LEN_OFFSET, 4);
|
||||
memcpy(event_ptr + BINLOG_EVENT_LEN_OFFSET, &event_size, 4);
|
||||
}
|
||||
|
||||
hdr->timestamp = EXTRACT32(hdbuf);
|
||||
hdr->event_type = hdbuf[4];
|
||||
hdr->serverid = EXTRACT32(&hdbuf[5]);
|
||||
@ -971,6 +990,7 @@ blr_close_binlog(ROUTER_INSTANCE *router, BLFILE *file)
|
||||
{
|
||||
close(file->fd);
|
||||
file->fd = -1;
|
||||
file->encryption_ctx = NULL;
|
||||
MXS_FREE(file);
|
||||
}
|
||||
}
|
||||
@ -1686,7 +1706,7 @@ blr_read_events_all_events(ROUTER_INSTANCE *router, int fix, int debug)
|
||||
/* Detect possible Start Encryption Event */
|
||||
if (hdr.event_type == MARIADB10_START_ENCRYPTION_EVENT)
|
||||
{
|
||||
char nonce_hex[12 * 2 + 1] = "";
|
||||
char nonce_hex[AES_BLOCK_SIZE * 2 + 1] = "";
|
||||
START_ENCRYPTION_EVENT ste_event = {};
|
||||
BINLOG_ENCRYPTION_CTX *new_encryption_ctx = MXS_CALLOC(1, sizeof(BINLOG_ENCRYPTION_CTX));
|
||||
if (new_encryption_ctx == NULL)
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2016 MariaDB Corporation Ab
|
||||
* Copyright (c) 201nMariaDB Corporation Ab
|
||||
*
|
||||
* Use of this software is governed by the Business Source License included
|
||||
* in the LICENSE.TXT file and at www.mariadb.com/bsl.
|
||||
@ -97,6 +97,7 @@ extern int blr_file_new_binlog(ROUTER_INSTANCE *router, char *file);
|
||||
extern int blr_file_write_master_config(ROUTER_INSTANCE *router, char *error);
|
||||
extern char *blr_extract_column(GWBUF *buf, int col);
|
||||
extern uint32_t extract_field(uint8_t *src, int bits);
|
||||
void blr_extract_header(register uint8_t *ptr, register REP_HEADER *hdr);
|
||||
int blr_file_get_next_binlogname(ROUTER_INSTANCE *router);
|
||||
static void encode_value(unsigned char *data, unsigned int value, int len);
|
||||
static int blr_slave_query(ROUTER_INSTANCE *router, ROUTER_SLAVE *slave, GWBUF *queue);
|
||||
@ -109,7 +110,7 @@ int blr_slave_catchup(ROUTER_INSTANCE *router, ROUTER_SLAVE *slave, bool large);
|
||||
uint8_t *blr_build_header(GWBUF *pkt, REP_HEADER *hdr);
|
||||
int blr_slave_callback(DCB *dcb, DCB_REASON reason, void *data);
|
||||
static int blr_slave_fake_rotate(ROUTER_INSTANCE *router, ROUTER_SLAVE *slave, BLFILE** filep);
|
||||
static void blr_slave_send_fde(ROUTER_INSTANCE *router, ROUTER_SLAVE *slave);
|
||||
static uint32_t blr_slave_send_fde(ROUTER_INSTANCE *router, ROUTER_SLAVE *slave, GWBUF *fde);
|
||||
static int blr_slave_send_maxscale_version(ROUTER_INSTANCE *router, ROUTER_SLAVE *slave);
|
||||
static int blr_slave_send_server_id(ROUTER_INSTANCE *router, ROUTER_SLAVE *slave);
|
||||
static int blr_slave_send_maxscale_variables(ROUTER_INSTANCE *router, ROUTER_SLAVE *slave);
|
||||
@ -164,6 +165,8 @@ static int blr_slave_send_columndef_with_status_schema(ROUTER_INSTANCE *router,
|
||||
static void blr_send_slave_heartbeat(void *inst);
|
||||
static int blr_slave_send_heartbeat(ROUTER_INSTANCE *router, ROUTER_SLAVE *slave);
|
||||
static int blr_set_master_ssl(ROUTER_INSTANCE *router, CHANGE_MASTER_OPTIONS config, char *error_message);
|
||||
static int blr_slave_read_ste(ROUTER_INSTANCE *router, ROUTER_SLAVE *slave, uint32_t fde_end_pos);
|
||||
static GWBUF *blr_slave_read_fde(ROUTER_INSTANCE *router, ROUTER_SLAVE *slave);
|
||||
|
||||
void poll_fake_write_event(DCB *dcb);
|
||||
|
||||
@ -1965,6 +1968,7 @@ blr_slave_binlog_dump(ROUTER_INSTANCE *router, ROUTER_SLAVE *slave, GWBUF *queue
|
||||
int len, rval, binlognamelen;
|
||||
REP_HEADER hdr;
|
||||
uint32_t chksum;
|
||||
uint32_t fde_end_pos;
|
||||
|
||||
ptr = GWBUF_DATA(queue);
|
||||
len = extract_field(ptr, 24);
|
||||
@ -2093,15 +2097,40 @@ blr_slave_binlog_dump(ROUTER_INSTANCE *router, ROUTER_SLAVE *slave, GWBUF *queue
|
||||
slave->lastReply = time(0);
|
||||
}
|
||||
|
||||
GWBUF *fde = blr_slave_read_fde(router, slave);
|
||||
if (fde == NULL)
|
||||
{
|
||||
// ERROR
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* FDE ends at pos 4 + FDE size */
|
||||
fde_end_pos = 4 + GWBUF_LENGTH(fde);
|
||||
|
||||
/* Send the FORMAT_DESCRIPTION_EVENT */
|
||||
if (slave->binlog_pos != 4)
|
||||
{
|
||||
blr_slave_send_fde(router, slave);
|
||||
blr_slave_send_fde(router, slave, fde);
|
||||
}
|
||||
|
||||
/* set lastEventReceived */
|
||||
slave->lastEventReceived = FORMAT_DESCRIPTION_EVENT;
|
||||
|
||||
/**
|
||||
* Check for START_ENCRYPTION_EVENT (after FDE) if
|
||||
* client request pos is greater than 4
|
||||
*
|
||||
* TODO: If router has binlog encryption take it
|
||||
* otherwise error
|
||||
* If no encryption and event found return error
|
||||
*
|
||||
* If event is found the contest is set into slave struct
|
||||
*/
|
||||
if (slave->binlog_pos != 4)
|
||||
{
|
||||
blr_slave_read_ste(router, slave, fde_end_pos);
|
||||
}
|
||||
|
||||
slave->dcb->low_water = router->low_water;
|
||||
slave->dcb->high_water = router->high_water;
|
||||
|
||||
@ -2298,22 +2327,82 @@ blr_slave_catchup(ROUTER_INSTANCE *router, ROUTER_SLAVE *slave, bool large)
|
||||
#endif
|
||||
int events_before = slave->stats.n_events;
|
||||
|
||||
/* Set file encryption context from slave pointer */
|
||||
spinlock_acquire(&slave->catch_lock);
|
||||
if (slave->encryption_ctx)
|
||||
{
|
||||
file->encryption_ctx = slave->encryption_ctx;
|
||||
}
|
||||
else
|
||||
{
|
||||
file->encryption_ctx = NULL;
|
||||
}
|
||||
spinlock_release(&slave->catch_lock);
|
||||
|
||||
while (burst-- && burst_size > 0 &&
|
||||
(record = blr_read_binlog(router, file, slave->binlog_pos, &hdr, read_errmsg)) != NULL)
|
||||
{
|
||||
char binlog_name[BINLOG_FNAMELEN + 1];
|
||||
uint32_t binlog_pos;
|
||||
uint32_t event_size;
|
||||
|
||||
strcpy(binlog_name, slave->binlogfile);
|
||||
binlog_pos = slave->binlog_pos;
|
||||
|
||||
/* Don't sent special events generated by MaxScale */
|
||||
if (hdr.event_type == MARIADB10_START_ENCRYPTION_EVENT || hdr.event_type == IGNORABLE_EVENT || (hdr.flags & LOG_EVENT_IGNORABLE_F))
|
||||
if (hdr.event_type == MARIADB10_START_ENCRYPTION_EVENT ||
|
||||
hdr.event_type == IGNORABLE_EVENT ||
|
||||
(hdr.flags & LOG_EVENT_IGNORABLE_F))
|
||||
{
|
||||
/* In case of file rotation or pos = 4 the events are sent from position 4.
|
||||
* new FDE at pos 4 is read.
|
||||
* We need to check whether the first event after FDE
|
||||
* is the MARIADB10_START_ENCRYPTION_EVENT of the new file.
|
||||
*
|
||||
* Read it if slave->encryption_ctx is NULL and set the slave->encryption_ctx accordingly
|
||||
*/
|
||||
spinlock_acquire(&slave->catch_lock);
|
||||
|
||||
if (hdr.event_type == MARIADB10_START_ENCRYPTION_EVENT && !slave->encryption_ctx)
|
||||
{
|
||||
/* read it, set slave & file context */
|
||||
uint8_t *record_ptr = GWBUF_DATA(record);
|
||||
SLAVE_ENCRYPTION_CTX *new_encryption_ctx = MXS_CALLOC(1, sizeof(SLAVE_ENCRYPTION_CTX));
|
||||
record_ptr += BINLOG_EVENT_HDR_LEN;
|
||||
new_encryption_ctx->binlog_crypto_scheme = record_ptr[0];
|
||||
memcpy(&new_encryption_ctx->binlog_key_version, record_ptr + 1, BLRM_KEY_VERSION_LENGTH);
|
||||
memcpy(new_encryption_ctx->nonce, record_ptr + 1 + BLRM_KEY_VERSION_LENGTH, BLRM_NONCE_LENGTH);
|
||||
|
||||
/* Save current first_enc_event_pos */
|
||||
if (slave->encryption_ctx)
|
||||
{
|
||||
SLAVE_ENCRYPTION_CTX *slave_enc_ctx = (SLAVE_ENCRYPTION_CTX *)slave->encryption_ctx;
|
||||
new_encryption_ctx->first_enc_event_pos = slave_enc_ctx->first_enc_event_pos;
|
||||
}
|
||||
|
||||
/* set the encryption ctx into slave */
|
||||
slave->encryption_ctx = new_encryption_ctx;
|
||||
|
||||
MXS_INFO("Start Encryption event found while reading. Binlog %s is encrypted. First event at %lu",
|
||||
slave->binlogfile,
|
||||
(unsigned long) hdr.next_pos);
|
||||
}
|
||||
|
||||
MXS_INFO("Found ignorable event [%s] of size %lu while reading binlog %s at %lu",
|
||||
blr_get_event_description(router, hdr.event_type),
|
||||
(unsigned long)hdr.event_size,
|
||||
slave->binlogfile,
|
||||
(unsigned long) slave->binlog_pos);
|
||||
|
||||
/* set next pos */
|
||||
slave->binlog_pos = hdr.next_pos;
|
||||
|
||||
spinlock_release(&slave->catch_lock);
|
||||
|
||||
gwbuf_free(record);
|
||||
record = NULL;
|
||||
continue;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (hdr.event_type == ROTATE_EVENT)
|
||||
@ -2325,6 +2414,11 @@ blr_slave_catchup(ROUTER_INSTANCE *router, ROUTER_SLAVE *slave, bool large)
|
||||
MXS_ERROR("blr_close_binlog took %lu maxscale beats", hkheartbeat - beat1);
|
||||
}
|
||||
blr_slave_rotate(router, slave, GWBUF_DATA(record));
|
||||
|
||||
/* reset the encryption context */
|
||||
MXS_FREE(slave->encryption_ctx);
|
||||
slave->encryption_ctx = NULL;
|
||||
|
||||
beat1 = hkheartbeat;
|
||||
#ifdef BLFILE_IN_SLAVE
|
||||
if ((slave->file = blr_open_binlog(router, slave->binlogfile)) == NULL)
|
||||
@ -2558,6 +2652,10 @@ blr_slave_catchup(ROUTER_INSTANCE *router, ROUTER_SLAVE *slave, bool large)
|
||||
slave->binlogfile, (unsigned long)slave->binlog_pos,
|
||||
router->binlog_name, router->binlog_position);
|
||||
|
||||
/* Reset encryption context */
|
||||
MXS_FREE(slave->encryption_ctx);
|
||||
slave->encryption_ctx = NULL;
|
||||
|
||||
#ifdef BLFILE_IN_SLAVE
|
||||
if (blr_slave_fake_rotate(router, slave, &slave->file))
|
||||
#else
|
||||
@ -2763,13 +2861,14 @@ blr_slave_fake_rotate(ROUTER_INSTANCE *router, ROUTER_SLAVE *slave, BLFILE** fil
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a "fake" format description event to the newly connected slave
|
||||
* Read the format description event FDE from current slave logfile
|
||||
*
|
||||
* @param router The router instance
|
||||
* @param slave The slave to send the event to
|
||||
* @return The read FDE event on success or NULL on error
|
||||
*/
|
||||
static void
|
||||
blr_slave_send_fde(ROUTER_INSTANCE *router, ROUTER_SLAVE *slave)
|
||||
static GWBUF *
|
||||
blr_slave_read_fde(ROUTER_INSTANCE *router, ROUTER_SLAVE *slave)
|
||||
{
|
||||
BLFILE *file;
|
||||
REP_HEADER hdr;
|
||||
@ -2784,7 +2883,7 @@ blr_slave_send_fde(ROUTER_INSTANCE *router, ROUTER_SLAVE *slave)
|
||||
|
||||
if ((file = blr_open_binlog(router, slave->binlogfile)) == NULL)
|
||||
{
|
||||
return;
|
||||
return NULL;
|
||||
}
|
||||
if ((record = blr_read_binlog(router, file, 4, &hdr, err_msg)) == NULL)
|
||||
{
|
||||
@ -2799,20 +2898,56 @@ blr_slave_send_fde(ROUTER_INSTANCE *router, ROUTER_SLAVE *slave)
|
||||
}
|
||||
|
||||
blr_close_binlog(router, file);
|
||||
return;
|
||||
return NULL;
|
||||
}
|
||||
blr_close_binlog(router, file);
|
||||
|
||||
return record;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a "fake" format description event to the newly connected slave
|
||||
*
|
||||
* @param router The router instance
|
||||
* @param slave The slave to send the event to
|
||||
* @return The FDE event size on success or 0 on error
|
||||
*/
|
||||
static uint32_t
|
||||
blr_slave_send_fde(ROUTER_INSTANCE *router, ROUTER_SLAVE *slave, GWBUF *fde)
|
||||
{
|
||||
BLFILE *file;
|
||||
REP_HEADER hdr;
|
||||
GWBUF *head;
|
||||
uint8_t *ptr;
|
||||
uint32_t chksum;
|
||||
char err_msg[BINLOG_ERROR_MSG_LEN + 1];
|
||||
uint32_t event_size;
|
||||
uint8_t *event_ptr;
|
||||
|
||||
if (fde == NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
err_msg[BINLOG_ERROR_MSG_LEN] = '\0';
|
||||
event_ptr = GWBUF_DATA(fde);
|
||||
head = gwbuf_alloc(5);
|
||||
ptr = GWBUF_DATA(head);
|
||||
encode_value(ptr, hdr.event_size + 1, 24); // Payload length
|
||||
|
||||
event_size = GWBUF_LENGTH(fde);
|
||||
|
||||
/* Set payload to event_size + 1 (the ok/err byte) */
|
||||
encode_value(ptr, event_size + 1, 32);
|
||||
ptr += 3;
|
||||
*ptr++ = slave->seqno++;
|
||||
*ptr++ = 0; // OK
|
||||
head = gwbuf_append(head, record);
|
||||
ptr = GWBUF_DATA(record);
|
||||
encode_value(ptr, time(0), 32); // Overwrite timestamp
|
||||
ptr += 13;
|
||||
encode_value(ptr, 0, 32); // Set next position to 0
|
||||
*ptr++ = 0; // OK/ERR byte
|
||||
head = gwbuf_append(head, fde);
|
||||
event_ptr = GWBUF_DATA(fde);
|
||||
encode_value(event_ptr, time(0), 32); // Overwrite timestamp
|
||||
event_ptr += 13; // 4 time + 1 type + 4 server_id + 4 event_size
|
||||
/* event_ptr points to position of the next event */
|
||||
encode_value(event_ptr, 0, 32); // Set next position to 0
|
||||
|
||||
/*
|
||||
* Since we have changed the timestamp we must recalculate the CRC
|
||||
*
|
||||
@ -2820,16 +2955,15 @@ blr_slave_send_fde(ROUTER_INSTANCE *router, ROUTER_SLAVE *slave)
|
||||
* calculate a new checksum
|
||||
* and write it into the header
|
||||
*/
|
||||
ptr = GWBUF_DATA(record) + hdr.event_size - 4;
|
||||
ptr = GWBUF_DATA(fde) + event_size - BINLOG_EVENT_CRC_SIZE;
|
||||
chksum = crc32(0L, NULL, 0);
|
||||
chksum = crc32(chksum, GWBUF_DATA(record), hdr.event_size - 4);
|
||||
chksum = crc32(chksum, GWBUF_DATA(fde), event_size - BINLOG_EVENT_CRC_SIZE);
|
||||
encode_value(ptr, chksum, 32);
|
||||
|
||||
slave->dcb->func.write(slave->dcb, head);
|
||||
return slave->dcb->func.write(slave->dcb, head);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Send the field count packet in a response packet sequence.
|
||||
*
|
||||
@ -5577,3 +5711,69 @@ bool blr_notify_waiting_slave(ROUTER_SLAVE *slave)
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read START_ENCRYPTION_EVENT, after FDE
|
||||
*/
|
||||
static int
|
||||
blr_slave_read_ste(ROUTER_INSTANCE *router, ROUTER_SLAVE *slave, uint32_t fde_end_pos)
|
||||
{
|
||||
BLFILE *file;
|
||||
REP_HEADER hdr;
|
||||
GWBUF *record, *head;
|
||||
uint8_t *ptr;
|
||||
uint32_t chksum;
|
||||
char err_msg[BINLOG_ERROR_MSG_LEN + 1];
|
||||
|
||||
err_msg[BINLOG_ERROR_MSG_LEN] = '\0';
|
||||
|
||||
memset(&hdr, 0, BINLOG_EVENT_HDR_LEN);
|
||||
|
||||
if ((file = blr_open_binlog(router, slave->binlogfile)) == NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if ((record = blr_read_binlog(router, file, fde_end_pos, &hdr, err_msg)) == NULL)
|
||||
{
|
||||
if (hdr.ok != SLAVE_POS_READ_OK)
|
||||
{
|
||||
MXS_ERROR("Slave %s:%i, server-id %d, binlog '%s', blr_read_binlog failure: %s",
|
||||
slave->dcb->remote,
|
||||
ntohs((slave->dcb->ipv4).sin_port),
|
||||
slave->serverid,
|
||||
slave->binlogfile,
|
||||
err_msg);
|
||||
}
|
||||
|
||||
blr_close_binlog(router, file);
|
||||
return 0;
|
||||
}
|
||||
|
||||
blr_close_binlog(router, file);
|
||||
|
||||
/* check for START_ENCRYPTION_EVENT */
|
||||
if (hdr.event_type == MARIADB10_START_ENCRYPTION_EVENT)
|
||||
{
|
||||
uint8_t *record_ptr = GWBUF_DATA(record);
|
||||
SLAVE_ENCRYPTION_CTX *new_encryption_ctx = MXS_CALLOC(1, sizeof(SLAVE_ENCRYPTION_CTX));
|
||||
record_ptr += BINLOG_EVENT_HDR_LEN;
|
||||
new_encryption_ctx->binlog_crypto_scheme = record_ptr[0]; // 1 Byte
|
||||
memcpy(&new_encryption_ctx->binlog_key_version, record_ptr + 1, BLRM_KEY_VERSION_LENGTH);
|
||||
memcpy(new_encryption_ctx->nonce, record_ptr + 1 + BLRM_KEY_VERSION_LENGTH, BLRM_NONCE_LENGTH);
|
||||
/* Set the pos of first encrypted event */
|
||||
new_encryption_ctx->first_enc_event_pos = fde_end_pos + hdr.event_size;
|
||||
|
||||
spinlock_acquire(&slave->catch_lock);
|
||||
/* set the encryption ctx into slave */
|
||||
MXS_FREE(slave->encryption_ctx);
|
||||
slave->encryption_ctx = new_encryption_ctx;
|
||||
spinlock_release(&slave->catch_lock);
|
||||
|
||||
MXS_INFO("Start Encryption event found. Binlog %s is encrypted. First event at %lu",
|
||||
slave->binlogfile,
|
||||
(unsigned long)fde_end_pos + hdr.event_size);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
Reference in New Issue
Block a user