Skip to content

Commit

Permalink
Allow auth using rdb channel
Browse files Browse the repository at this point in the history
  • Loading branch information
amitnagl committed May 19, 2024
1 parent 9916f80 commit 96c93f3
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 37 deletions.
96 changes: 65 additions & 31 deletions src/replication.c
Original file line number Diff line number Diff line change
Expand Up @@ -2660,16 +2660,31 @@ void fullSyncWithMaster(connection* conn) {
goto error;
}
/* Send replica capabilities */
if (server.repl_rdb_conn_state == REPL_RDB_CONN_SEND_CAPA) {
serverLog(LL_DEBUG, "Received first reply from primary using rdb connection. Sending capa");

if (server.repl_rdb_conn_state == REPL_RDB_CONN_SEND_HANDSHAKE) {
serverLog(LL_DEBUG, "Received first reply from primary using rdb connection.");
/* AUTH with the master if required. */
if (server.masterauth) {
char *args[3] = {"AUTH",NULL,NULL};
size_t lens[3] = {4,0,0};
int argc = 1;
if (server.masteruser) {
args[argc] = server.masteruser;
lens[argc] = strlen(server.masteruser);
argc++;
}
args[argc] = server.masterauth;
lens[argc] = sdslen(server.masterauth);
argc++;
err = sendCommandArgv(conn, argc, args, lens);
if (err) goto write_error;
}
/* Send replica lisening port to master for clarification */
sds portstr = getReplicaPortString();
err = sendCommand(conn, "REPLCONF", "capa", "eof",
"rdb-only", "1", "rdb-conn", "1", "listening-port", portstr, NULL);
sdsfree(portstr);
if (err) goto write_error;
server.repl_rdb_conn_state = REPL_RDB_CONN_RECEIVE_REPLCONF_REPLY;
server.repl_rdb_conn_state = REPL_RDB_CONN_RECEIVE_AUTH_REPLY;

if (connSetReadHandler(conn, fullSyncWithMaster) == C_ERR) {
char conninfo[CONN_INFO_LEN];
Expand All @@ -2680,6 +2695,23 @@ void fullSyncWithMaster(connection* conn) {
}
return;
}
if (server.repl_rdb_conn_state == REPL_RDB_CONN_RECEIVE_AUTH_REPLY && !server.masterauth) {
server.repl_rdb_conn_state = REPL_RDB_CONN_RECEIVE_REPLCONF_REPLY;
}
/* Receive AUTH reply. */
if (server.repl_rdb_conn_state == REPL_RDB_CONN_RECEIVE_AUTH_REPLY) {
err = receiveSynchronousResponse(conn);
if (err == NULL) goto no_response_error;
if (err[0] == '-') {
serverLog(LL_WARNING,"Unable to AUTH to MASTER: %s",err);
sdsfree(err);
goto error;
}
sdsfree(err);
err = NULL;
server.repl_rdb_conn_state = REPL_RDB_CONN_RECEIVE_REPLCONF_REPLY;
return;
}
/* Receive replconf response */
if (server.repl_rdb_conn_state == REPL_RDB_CONN_RECEIVE_REPLCONF_REPLY) {
err = receiveSynchronousResponse(conn);
Expand Down Expand Up @@ -3297,37 +3329,39 @@ void setupMainConnForPsync(connection *conn) {
* RDB Channel Sync
* ┌──────────────────────────────────────────────────────────────┐
* │ RDB connection states Main connection state │
* ┌───────────────────┐ ┌────────────┐ │ ──────────────────────────┐ ┌───────────────────┐ │
* │RECEIVE_PING_REPLY │ ┌───►SEND_PSYNC │ -FULLSYNCNEEDED───┤RDB_CONN_SEND_CAPA │ ┌──►SEND_HANDSHAKE │ │
* └────────┬──────────┘ │ └─┬──────────┘ │ │ ──┬───────────────────────┘ │ └──┬────────────────┘ │
* ┌───────────────────┐ ┌────────────┐ │ ┌────────────────────────────┐ ┌───────────────────┐ │
* │RECEIVE_PING_REPLY │ ┌───►SEND_PSYNC │ -FULLSYNCNEEDED─┤REPL_RDB_CONN_SEND_HANDSHAKE│ ┌──►SEND_HANDSHAKE │ │
* └────────┬──────────┘ │ └─┬──────────┘ │ │ └────┬───────────────────────┘ │ └──┬────────────────┘ │
* │+PONG │ │PSYNC (use cached-master) │ │ │REPLCONF set-rdb-conn-id
* ┌────────▼──────────┐ │ ┌─▼─────────────────┐ │ │ ┌───────▼───────────────────────┐ │ ┌──▼────────────────┐ │
* │SEND_HANDSHAKE │ │ ┌─┤RECEIVE_PSYNC_REPLY├─┘ │ │RDB_CONN_RECEIVE_REPLCONF_REPLY│ │ │RECEIVE_CAPA_REPLY │ │
* │SEND_HANDSHAKE │ │ ┌─┤RECEIVE_PSYNC_REPLY├─┘ │ │RDB_CONN_RECEIVE_AUTH_REPLY │ │ │RECEIVE_CAPA_REPLY │ │
* └────────┬──────────┘ │ │ └─┬─────────────────┘ │ └───────┬───────────────────────┘ │ └──┬────────────────┘ │
* │ │ │ │+FULLRESYNC │ │ │ │+OK │
* ┌────────▼──────────┐ │ │ ┌─▼─────────────────┐ │ ┌───────▼─────────────── │ ┌──▼────────────────┐ │
* │RECEIVE_AUTH_REPLY │ │ │ │TRANSFER │ │ │RDB_CONN_RECEIVE_ENDOFF│ │ │SEND_PSYNC │ │
* └────────┬──────────┘ │ │ └───────────────────┘ │ └───────┬─────────────── │ └──┬────────────────┘ │
* │+OK │ │ │ │$ENDOFF │ │PSYNC use snapshot │
* ┌────────▼──────────┐ │ │ │ ─────────────────────────┘ │end-offset provided│
* │RECEIVE_PORT_REPLY │ │ │ │ │by the master │
* └────────┬──────────┘ │ │ │ ────────────────────── ┌──▼────────────────┐ │
* │+OK │ │+CONTINUE │ │RDB_CONN_RDB_LOAD │RECEIVE_PSYNC_REPLY│ │
* ┌────────▼──────────┐ │ │ │ ────────────────────── └──┬────────────────┘ │
* │RECEIVE_IP_REPLY │ │ │ │ │Done loading snapshot │+CONTINUE │
* │ │ │ │+FULLRESYNC │ │+OK │ │+OK │
* ┌────────▼──────────┐ │ │ ┌─▼─────────────────┐ │ ┌───────▼───────────────────────┐ │ ┌──▼────────────────┐ │
* │RECEIVE_AUTH_REPLY │ │ │ │TRANSFER │ │ │RDB_CONN_RECEIVE_REPLCONF_REPLY│ │ │SEND_PSYNC │ │
* └────────┬──────────┘ │ │ └───────────────────┘ │ └───────┬───────────────────────┘ │ └──┬────────────────┘ │
* │+OK │ │ │ │+OK │ │PSYNC use snapshot │
* ┌────────▼──────────┐ │ │ │ ──────────────────────┐ │ │end-offset provided│
* │RECEIVE_PORT_REPLY │ │ │ │ │RDB_CONN_RECEIVE_ENDOFF│ │by the master │
* └────────┬──────────┘ │ │ │ ────────────────────── ┌──▼────────────────┐ │
* │+OK │ │+CONTINUE │ │$ENDOFF │RECEIVE_PSYNC_REPLY│ │
* ┌────────▼──────────┐ │ │ │ ─────────────────────────┘ └──┬────────────────┘ │
* │RECEIVE_IP_REPLY │ │ │ │ │ │+CONTINUE │
* └────────┬──────────┘ │ │ │ ┌───────▼───────────────┐ ┌──▼────────────────┐ │
* │+OK │ │ │ │RDB_CONN_RDB_LOADED │ │TRANSFER │ │
* │+OK │ │ │ │RDB_CONN_RDB_LOAD │ │TRANSFER │ │
* ┌────────▼──────────┐ │ │ │ └───────┬───────────────┘ └────┬──────────────┘ │
* │RECEIVE_IP_REPLY │ │ │ │ │ │ │
* └────────┬──────────┘ │ │ │ │Slave loads local replication │ │
* │+OK │ │ │ │buffer into memory │ │
* ┌────────▼────────────────┐ │ │ ┌─────────┼──────────┴─────────────────────────────────┘ │
* │RECEIVE_NO_FULLSYNC_REPLY│ │ │ │ │ │
* └─┬────┬──────────────────┘ │ └────┐ │ └──────────────────────────────────────────────────────────────┘
* │+OK │Unrecognized REPLCONF │ │
* ┌─▼────▼────────────┐ │ ┌──▼───────────▼────┐
* │RECEIVE_CAPA_REPLY ├───────┘ │CONNECTED │
* └───────────────────┘ └───────────────────┘
* │RECEIVE_IP_REPLY │ │ │ │ │Done loading snapshot │ │
* └────────┬──────────┘ │ │ │ ┌───────▼───────────────┐ │ │
* │+OK │ │ │ │RDB_CONN_RDB_LOADED │ │ │
* ┌────────▼────────────────┐ │ │ │ └───────┬───────────────┘ │ │
* │RECEIVE_NO_FULLSYNC_REPLY│ │ │ │ │ │ │
* └─┬────┬──────────────────┘ │ └────┐ │ │Slave loads local replication │ │
* │+OK │Unrecognized REPLCONF │ │ │buffer into memory │ │
* ┌─▼────▼────────────┐ │ │ ┌────────┼──────────┴─────────────────────────────────┘ │
* │RECEIVE_CAPA_REPLY ├───────┘ │ │ │ │
* └───────────────────┘ ┌──▼────────────▼───┐ │ │
* │CONNECTED │ └──────────────────────────────────────────────────────────────┘
* └───────────────────┘
*/
/* This handler fires when the non blocking connect was able to
* establish a connection with the master. */
Expand Down Expand Up @@ -3646,7 +3680,7 @@ void syncWithMaster(connection *conn) {
strerror(errno), connGetInfo(conn, conninfo, sizeof(conninfo)));
goto error;
}
server.repl_rdb_conn_state = REPL_RDB_CONN_SEND_CAPA;
server.repl_rdb_conn_state = REPL_RDB_CONN_SEND_HANDSHAKE;
return;
}
/* Setup the non blocking download of the bulk file. */
Expand Down
9 changes: 5 additions & 4 deletions src/server.h
Original file line number Diff line number Diff line change
Expand Up @@ -467,10 +467,11 @@ typedef enum {
* slaves to remember what to do next. */
typedef enum {
REPL_RDB_CONN_STATE_NONE = 0, /* No active replication */
REPL_RDB_CONN_SEND_CAPA, /* Send replica cob-channel capabilities */
REPL_RDB_CONN_RECEIVE_REPLCONF_REPLY, /* Wait for REPLCONF reply */
REPL_RDB_CONN_RECEIVE_ENDOFF, /* Wait for $ENDOFF reply */
REPL_RDB_CONN_RDB_LOAD, /* Loading rdb using rdb channel */
REPL_RDB_CONN_SEND_HANDSHAKE, /* Send handshake sequence to master */
REPL_RDB_CONN_RECEIVE_AUTH_REPLY, /* Wait for AUTH reply */
REPL_RDB_CONN_RECEIVE_REPLCONF_REPLY, /* Wait for REPLCONF reply */
REPL_RDB_CONN_RECEIVE_ENDOFF, /* Wait for $ENDOFF reply */
REPL_RDB_CONN_RDB_LOAD, /* Loading rdb using rdb channel */
REPL_RDB_CONN_RDB_LOADED,
} repl_rdb_conn_state;

Expand Down
7 changes: 5 additions & 2 deletions tests/unit/auth.tcl
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ start_server {tags {"auth external:skip"} overrides {requirepass foobar}} {
}
}

foreach rdbchann {yes no} {
start_server {tags {"auth_binary_password external:skip"}} {
test {AUTH fails when binary password is wrong} {
r config set requirepass "abc\x00def"
Expand All @@ -65,12 +66,13 @@ start_server {tags {"auth_binary_password external:skip"}} {
set master_port [srv -1 port]
set slave [srv 0 client]

test {MASTERAUTH test with binary password} {
test "MASTERAUTH test with binary password rdbchannel = $rdbchann" {
$master config set requirepass "abc\x00def"

$master config set repl-rdb-channel $rdbchann
# Configure the replica with masterauth
set loglines [count_log_lines 0]
$slave config set masterauth "abc"
$slave config set repl-rdb-channel $rdbchann
$slave slaveof $master_host $master_port

# Verify replica is not able to sync with master
Expand All @@ -87,3 +89,4 @@ start_server {tags {"auth_binary_password external:skip"}} {
}
}
}
}

0 comments on commit 96c93f3

Please sign in to comment.