Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 2 additions & 5 deletions net/net-crypto-aes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ int aes_generate_nonce (char res[16]) {

int aes_create_keys(aes_key_t *key, struct aes_session_key *R, int am_client, const char nonce_server[16], const char nonce_client[16], int client_timestamp,
unsigned server_ip, unsigned short server_port, const unsigned char server_ipv6[16], unsigned client_ip, unsigned short client_port,
const unsigned char client_ipv6[16]) {
const unsigned char client_ipv6[16], bool is_ip_v6) {
unsigned char str[16 + 16 + 4 + 4 + 2 + 6 + 4 + 2 + AES_KEY_MAX_LEN + 16 + 16 + 4 + 16 * 2];
int str_len;

Expand All @@ -228,13 +228,10 @@ int aes_create_keys(aes_key_t *key, struct aes_session_key *R, int am_client, co
memcpy(str + 54 + pwd_len, nonce_server, 16);
str_len = 70 + pwd_len;

if (!server_ip) {
assert(!client_ip);
if (is_ip_v6) {
memcpy(str + str_len, client_ipv6, 16);
memcpy(str + str_len + 16, server_ipv6, 16);
str_len += 32;
} else {
assert(client_ip);
}

memcpy(str + str_len, nonce_client, 16);
Expand Down
20 changes: 12 additions & 8 deletions net/net-crypto-aes.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,19 +56,22 @@ int aes_generate_nonce (char res[16]);

int aes_create_keys(aes_key_t *key, struct aes_session_key *R, int am_client, const char nonce_server[16], const char nonce_client[16], int client_timestamp,
unsigned server_ip, unsigned short server_port, const unsigned char server_ipv6[16], unsigned client_ip, unsigned short client_port,
const unsigned char client_ipv6[16]);
const unsigned char client_ipv6[16], bool is_ip_v6);
int aes_create_udp_keys (const aes_key_t* key, aes_udp_session_key_t *R, const process_id_t *local_pid, const process_id_t *remote_pid, int generation);

static inline int aes_create_connection_keys(aes_key_t *key, struct aes_session_key *R, int am_client, char nonce_server[16], char nonce_client[16],
int client_timestamp, struct connection *c) {
static inline int aes_create_connection_keys(unsigned char protocol_version, aes_key_t *key, struct aes_session_key *R, int am_client, char nonce_server[16], char nonce_client[16],
int server_timestamp, int client_timestamp, struct connection *c) {
uint32_t our_ip, remote_ip;
uint16_t our_port, remote_port;
uint8_t remote_ipv6[16] = {'\0'};
uint8_t our_ipv6[16] = {'\0'};
our_ip = remote_ip = our_port = remote_port = 0;

assert(c->local_endpoint.ss_family == c->remote_endpoint.ss_family);
switch (c->local_endpoint.ss_family) {
bool is_ipv6 = false;

if (protocol_version == 0) {
assert(c->local_endpoint.ss_family == c->remote_endpoint.ss_family);
switch (c->local_endpoint.ss_family) {
case AF_INET:
our_ip = inet_sockaddr_address(&c->local_endpoint);
remote_ip = inet_sockaddr_address(&c->remote_endpoint);
Expand All @@ -80,15 +83,16 @@ static inline int aes_create_connection_keys(aes_key_t *key, struct aes_session_
memcpy(our_ipv6, inet6_sockaddr_address(&c->local_endpoint), sizeof(our_ipv6));
our_port = inet6_sockaddr_port(&c->local_endpoint);
remote_port = inet6_sockaddr_port(&c->remote_endpoint);
is_ipv6 = true;
break;
default:
assert(0);
}
}

return am_client
? aes_create_keys(key, R, am_client, nonce_server, nonce_client, client_timestamp, remote_ip, remote_port, remote_ipv6, our_ip, our_port, our_ipv6)

: aes_create_keys(key, R, am_client, nonce_server, nonce_client, client_timestamp, our_ip, our_port, our_ipv6, remote_ip, remote_port, remote_ipv6);
? aes_create_keys(key, R, am_client, nonce_server, nonce_client, client_timestamp, protocol_version == 0 ? remote_ip : server_timestamp, remote_port, remote_ipv6, our_ip, our_port, our_ipv6, is_ipv6)
: aes_create_keys(key, R, am_client, nonce_server, nonce_client, client_timestamp, protocol_version == 0 ? our_ip : server_timestamp, our_port, our_ipv6, remote_ip, remote_port, remote_ipv6, is_ipv6);
}

static inline int get_crypto_key_id(const aes_key_t *key) {
Expand Down
2 changes: 1 addition & 1 deletion net/net-memcache-client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -611,7 +611,7 @@ int mcc_start_crypto (struct connection *c, char *key, int key_len) {

struct aes_session_key aes_keys;

if (aes_create_connection_keys (default_aes_key, &aes_keys, 1, nonce_in, D->nonce, D->nonce_time, c) < 0) {
if (aes_create_connection_keys (0, default_aes_key, &aes_keys, 1, nonce_in, D->nonce, 0, D->nonce_time, c) < 0) {
return -1;
}

Expand Down
2 changes: 1 addition & 1 deletion net/net-memcache-server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1029,7 +1029,7 @@ int mcs_init_crypto (struct connection *c, char *key, int key_len) {

struct aes_session_key aes_keys;

if (aes_create_connection_keys (default_aes_key, &aes_keys, 0, nonce_out, nonce_in, utime, c) < 0) {
if (aes_create_connection_keys (0, default_aes_key, &aes_keys, 0, nonce_out, nonce_in, 0, utime, c) < 0) {
return -1;
}

Expand Down
2 changes: 1 addition & 1 deletion net/net-mysql-client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -567,7 +567,7 @@ int sqlc_init_crypto (struct connection *c, char *key, int key_len) {

struct aes_session_key aes_keys;

if (aes_create_connection_keys (default_aes_key, &aes_keys, 1, nonce_in, nonce_out, utime, c) < 0) {
if (aes_create_connection_keys (0, default_aes_key, &aes_keys, 1, nonce_in, nonce_out, 0, utime, c) < 0) {
return -1;
}

Expand Down
68 changes: 40 additions & 28 deletions net/net-tcp-rpc-client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,9 @@ int tcp_rpcc_default_execute (struct connection *c, int op, raw_message_t *raw)
tvkprintf(net_connections, 3, "rpcc_execute: fd=%d, op=%d, len=%d\n", c->fd, op, raw->total_bytes);
if (op == TL_RPC_PING && raw->total_bytes == 12) {
c->last_response_time = precise_now;
static int Q[12];
int Q[12];
assert (rwm_fetch_data (raw, Q, 12) == 12);
static int P[12];
int P[12];
P[0] = TL_RPC_PONG;
P[1] = Q[1];
P[2] = Q[2];
Expand All @@ -90,18 +90,24 @@ int tcp_rpcc_default_execute (struct connection *c, int op, raw_message_t *raw)

static int tcp_rpcc_process_nonce_packet (struct connection *c, raw_message_t *msg) {
struct tcp_rpc_data *D = TCP_RPC_DATA(c);
static struct tcp_rpc_nonce_packet P;
struct tcp_rpc_nonce_packet P{};
int res;

if (D->packet_num != -2 || D->packet_type != RPC_NONCE) {
return -2;
}
if (D->packet_len != sizeof (struct tcp_rpc_nonce_packet)) {
if (D->packet_len < sizeof (P) || D->packet_len >= 1024) {
return -3;
}
int excess_data_size = D->packet_len - sizeof(P); // fields from newer protocol version

assert (rwm_fetch_data (msg, &P, D->packet_len) == D->packet_len);
tvkprintf(net_connections, 4, "Processing nonce packet, crypto schema: %d, key select: %d\n", P.crypto_schema, P.key_select);
assert (rwm_fetch_data (msg, &P, sizeof(P)) == sizeof(P));
assert (rwm_fetch_data (msg, 0, excess_data_size) == excess_data_size);
tvkprintf(net_connections, 4, "Processing nonce packet, crypto schema: %d, version: %d, excess_data: %d, key select: %d\n", P.crypto_schema, P.protocol_version, excess_data_size, P.key_select);

if (P.protocol_version > 1) { // server must not reply with version > client
return -3;
}

switch (P.crypto_schema) {
case RPC_CRYPTO_NONE:
Expand All @@ -127,7 +133,7 @@ static int tcp_rpcc_process_nonce_packet (struct connection *c, raw_message_t *m
if (abs (P.crypto_ts - D->nonce_time) > 30) {
return -6; //less'om
}
res = TCP_RPCC_FUNC(c)->rpc_start_crypto (c, P.crypto_nonce, P.key_select);
res = TCP_RPCC_FUNC(c)->rpc_start_crypto (c, &P);
if (res < 0) {
return -6;
}
Expand All @@ -142,14 +148,13 @@ static int tcp_rpcc_process_nonce_packet (struct connection *c, raw_message_t *m
static int tcp_rpcc_send_handshake_packet (struct connection *c) {
tvkprintf(net_connections, 4, "tcp_rpcc_send_handshake_packet\n");
struct tcp_rpc_data *D = TCP_RPC_DATA (c);
static struct tcp_rpc_handshake_packet P;
struct tcp_rpc_handshake_packet P{};
if (!PID.ip) {
init_client_PID(c->local_endpoint.ss_family == AF_INET ? inet_sockaddr_address(&c->local_endpoint): 0);
if (!PID.ip) {
PID.ip = get_my_ipv4 ();
}
}
memset (&P, 0, sizeof (P));
P.type = RPC_HANDSHAKE;
P.flags = default_rpc_flags & RPC_CRYPTO_USE_CRC32C;
if (!D->remote_pid.port) {
Expand All @@ -167,11 +172,10 @@ static int tcp_rpcc_send_handshake_packet (struct connection *c) {
}

static int tcp_rpcc_send_handshake_error_packet (struct connection *c, int error_code) {
static struct tcp_rpc_handshake_error_packet P;
struct tcp_rpc_handshake_error_packet P{};
if (!PID.pid) {
init_client_PID(inet_sockaddr_address(&c->local_endpoint));
}
memset (&P, 0, sizeof (P));
P.type = RPC_HANDSHAKE_ERROR;
P.error_code = error_code;
memcpy (&P.sender_pid, &PID, sizeof (PID));
Expand All @@ -185,11 +189,11 @@ static int tcp_rpcc_process_handshake_packet (struct connection *c, raw_message_
tvkprintf(net_connections, 4, "tcp_rpcc_process_handshake_packet\n");

struct tcp_rpc_data *D = TCP_RPC_DATA(c);
static struct tcp_rpc_handshake_packet P;
struct tcp_rpc_handshake_packet P{};
if (D->packet_num != -1 || D->packet_type != RPC_HANDSHAKE) {
return -2;
}
if (D->packet_len != sizeof (struct tcp_rpc_handshake_packet)) {
if (D->packet_len != sizeof (P)) {
tcp_rpcc_send_handshake_error_packet (c, -3);
return -3;
}
Expand Down Expand Up @@ -227,17 +231,23 @@ int tcp_rpcc_parse_execute (struct connection *c) {
int len;

while (true) {
len = c->in.total_bytes;
len = c->in.total_bytes;
if (len <= 0) {
break;
}
if (!D->packet_len) {
if (len < 4) {
if (len < D->packet_v1_padding + 4) {
c->status = conn_reading_answer;
return 4 - len;
return D->packet_v1_padding + 4 - len;
}
if (D->packet_v1_padding) {
assert(D->packet_v1_padding < 4);
assert(rwm_fetch_data(&c->in, 0, D->packet_v1_padding) == D->packet_v1_padding);
D->packet_v1_padding = 0;
}
assert (rwm_fetch_lookup (&c->in, &D->packet_len, 4) == 4);
if (D->packet_len <= 0 || (D->packet_len & 3) || (D->packet_len > TCP_RPCC_FUNC(c)->max_packet_len && TCP_RPCC_FUNC(c)->max_packet_len > 0)) {
// We skip checks for len&3 == 0 for protocol version 0, because there is little value in it.
if (D->packet_len > TCP_RPCC_FUNC(c)->max_packet_len && TCP_RPCC_FUNC(c)->max_packet_len > 0) {
tvkprintf(net_connections, 1, "error while parsing packet: bad packet length %d\n", D->packet_len);
c->status = conn_error;
c->error = -1;
Expand All @@ -259,7 +269,6 @@ int tcp_rpcc_parse_execute (struct connection *c) {
c->status = conn_reading_answer;
return D->packet_len - len;
}


raw_message_t msg;
if (c->in.total_bytes == D->packet_len) {
Expand Down Expand Up @@ -339,6 +348,9 @@ int tcp_rpcc_parse_execute (struct connection *c) {
}

D->in_packet_num++;
if (c->crypto) {
D->packet_v1_padding = (-D->packet_len) & 3;
}
D->packet_len = 0;
if (c->status == conn_running) {
c->status = conn_wait_answer;
Expand Down Expand Up @@ -421,10 +433,10 @@ int tcp_rpcc_init_fake_crypto (struct connection *c) {
return -1;
}

static struct tcp_rpc_nonce_packet buf;
memset (&buf, 0, sizeof (buf));
struct tcp_rpc_nonce_packet buf{};
buf.type = RPC_NONCE;
buf.crypto_schema = RPC_CRYPTO_NONE;
buf.protocol_version = 1; // ask for latest version we support

tcp_rpc_conn_send_data (c, sizeof (buf), &buf);

Expand Down Expand Up @@ -477,13 +489,13 @@ int tcp_rpcc_init_crypto (struct connection *c) {

aes_generate_nonce (TCP_RPC_DATA(c)->nonce);

static struct tcp_rpc_nonce_packet buf;
memset (&buf, 0, sizeof (buf));
struct tcp_rpc_nonce_packet buf{};
memcpy (buf.crypto_nonce, TCP_RPC_DATA(c)->nonce, 16);
buf.crypto_ts = TCP_RPC_DATA(c)->nonce_time;
buf.type = RPC_NONCE;
buf.key_select = get_crypto_key_id (default_aes_key);
buf.crypto_schema = (TCP_RPC_DATA(c)->crypto_flags & RPC_CRYPTO_ALLOW_UNENCRYPTED) ? RPC_CRYPTO_NONE_OR_AES : RPC_CRYPTO_AES;
buf.protocol_version = 1; // ask for latest version we support

tcp_rpc_conn_send_data (c, sizeof (buf), &buf);

Expand All @@ -494,9 +506,9 @@ int tcp_rpcc_init_crypto (struct connection *c) {
return 1;
}

int tcp_rpcc_start_crypto (struct connection *c, char *nonce, int key_select) {
int tcp_rpcc_start_crypto (struct connection *c, struct tcp_rpc_nonce_packet *P) {
struct tcp_rpc_data *D = TCP_RPC_DATA(c);
tvkprintf(net_connections, 4, "rpcc_start_crypto: key_select = %d\n", key_select);
tvkprintf(net_connections, 4, "rpcc_start_crypto: key_select = %d\n", P->key_select);

if (c->crypto) {
return -1;
Expand All @@ -506,13 +518,13 @@ int tcp_rpcc_start_crypto (struct connection *c, char *nonce, int key_select) {
return -1;
}

if (!key_select || key_select != get_crypto_key_id (default_aes_key)) {
if (!P->key_select || P->key_select != get_crypto_key_id (default_aes_key)) {
return -1;
}

struct aes_session_key aes_keys;

if (aes_create_connection_keys (default_aes_key, &aes_keys, 1, nonce, D->nonce, D->nonce_time, c) < 0) {
if (aes_create_connection_keys (P->protocol_version, default_aes_key, &aes_keys, 1, P->crypto_nonce, D->nonce, P->crypto_ts, D->nonce_time, c) < 0) {
return -1;
}

Expand All @@ -529,7 +541,7 @@ void tcp_rpcc_flush_crypto (struct connection *c) {
tvkprintf(net_connections, 4, "rpcc_flush_packet: padding with %d bytes\n", pad_bytes);
if (pad_bytes > 0) {
assert (!(pad_bytes & 3));
static int pad_str[3] = {4, 4, 4};
int pad_str[3] = {4, 4, 4};
assert (pad_bytes <= 12);
assert (rwm_push_data (&c->out, pad_str, pad_bytes) == pad_bytes);
}
Expand All @@ -552,7 +564,7 @@ int tcp_rpcc_flush (struct connection *c) {
tvkprintf(net_connections, 4, "rpcs_flush: padding with %d bytes\n", pad_bytes);
if (pad_bytes > 0) {
assert (!(pad_bytes & 3));
static int pad_str[3] = {4, 4, 4};
int pad_str[3] = {4, 4, 4};
assert (pad_bytes <= 12);
assert (rwm_push_data (&c->out, pad_str, pad_bytes) == pad_bytes);
}
Expand Down
5 changes: 3 additions & 2 deletions net/net-tcp-rpc-client.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <sys/cdefs.h>

#include "net/net-connections.h"
#include "net/net-tcp-rpc-common.h"
#include "net/net-msg.h"

struct tcp_rpc_client_functions {
Expand All @@ -17,7 +18,7 @@ struct tcp_rpc_client_functions {
int (*flush_packet)(struct connection *c); /* execute this to push query to server */
int (*rpc_check_perm)(struct connection *c); /* 1 = allow unencrypted, 2 = allow encrypted */
int (*rpc_init_crypto)(struct connection *c); /* 1 = ok; -1 = no crypto */
int (*rpc_start_crypto)(struct connection *c, char *nonce, int key_select); /* 1 = ok; -1 = no crypto */
int (*rpc_start_crypto)(struct connection *c, struct tcp_rpc_nonce_packet *P); /* 1 = ok; -1 = no crypto */
int (*rpc_wakeup)(struct connection *c);
int (*rpc_alarm)(struct connection *c);
int (*rpc_ready)(struct connection *c);
Expand All @@ -38,7 +39,7 @@ int tcp_rpcc_flush_packet_later (struct connection *c);
int tcp_rpcc_default_check_perm (struct connection *c);
int tcp_rpcc_default_check_perm_crypto (struct connection *c);
int tcp_rpcc_init_crypto (struct connection *c);
int tcp_rpcc_start_crypto (struct connection *c, char *nonce, int key_select);
int tcp_rpcc_start_crypto (struct connection *c, struct tcp_rpc_nonce_packet *P);
int default_tcp_rpc_client_check_ready(struct connection *c);

#define TCP_RPCC_FUNC(c) ((struct tcp_rpc_client_functions *) ((c)->extra))
Expand Down
7 changes: 5 additions & 2 deletions net/net-tcp-rpc-common.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ OPTION_PARSER(OPT_RPC, "no-crc32c", no_argument, "Force use of CRC32 instead of

void tcp_rpc_conn_send (struct connection *c, raw_message_t *raw, int flags) {
tvkprintf(net_connections, 4, "%s: sending message of size %d to conn fd=%d\n", __func__, raw->total_bytes, c->fd);
assert (!(raw->total_bytes & 3));
int Q[2];
Q[0] = raw->total_bytes + 12;
Q[1] = TCP_RPC_DATA(c)->out_packet_num ++;
Expand All @@ -40,11 +39,15 @@ void tcp_rpc_conn_send (struct connection *c, raw_message_t *raw, int flags) {
rwm_push_data_front (&r, Q, 8);
unsigned crc32 = rwm_custom_crc32 (&r, r.total_bytes, TCP_RPC_DATA(c)->custom_crc_partial);
rwm_push_data (&r, &crc32, 4);
if (c->crypto) {
int packet_v1_padding = (-raw->total_bytes) & 3;
char padding[3]{};
rwm_push_data (&r, &padding, packet_v1_padding);
}
rwm_union (&c->out, &r);
}

void tcp_rpc_conn_send_data (struct connection *c, int len, void *Q) {
assert (!(len & 3));
raw_message_t r;
assert (rwm_create (&r, Q, len) == len);
tcp_rpc_conn_send (c, &r, 0);
Expand Down
7 changes: 6 additions & 1 deletion net/net-tcp-rpc-common.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@
struct tcp_rpc_nonce_packet {
int type;
int key_select; /* least significant 32 bits of key to use */
int crypto_schema; /* 0 = NONE, 1 = AES */
unsigned char crypto_schema; /* 0 = NONE, 1 = AES */
unsigned char protocol_version;
unsigned short protocol_flags;
int crypto_ts;
char crypto_nonce[16];
};
Expand All @@ -43,6 +45,7 @@ void tcp_rpc_conn_send_data (struct connection *c, int len, void *Q);
/* in conn->custom_data */
struct tcp_rpc_data {
int packet_len;
int packet_v1_padding;
int packet_num;
int packet_type;
int packet_crc32;
Expand All @@ -67,6 +70,8 @@ struct tcp_rpc_data {

#define TCP_RPC_DATA(c) ((struct tcp_rpc_data *) ((c)->custom_data))

static_assert(sizeof(connection_t::custom_data) >= sizeof(tcp_rpc_data));

#define RPC_CRYPTO_ALLOW_UNENCRYPTED 0x00000001
#define RPC_CRYPTO_ALLOW_ENCRYPTED 0x00000002
#define RPC_CRYPTO_ALLOW_MASK (RPC_CRYPTO_ALLOW_UNENCRYPTED | RPC_CRYPTO_ALLOW_ENCRYPTED)
Expand Down
Loading
Loading