Skip to content

Commit b168a45

Browse files
authored
vk rpc protocol version 1 supported, with optional encryption (#1463)
1 parent 671c384 commit b168a45

13 files changed

Lines changed: 122 additions & 87 deletions

net/net-crypto-aes.cpp

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,7 @@ int aes_generate_nonce (char res[16]) {
205205

206206
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,
207207
unsigned server_ip, unsigned short server_port, const unsigned char server_ipv6[16], unsigned client_ip, unsigned short client_port,
208-
const unsigned char client_ipv6[16]) {
208+
const unsigned char client_ipv6[16], bool is_ip_v6) {
209209
unsigned char str[16 + 16 + 4 + 4 + 2 + 6 + 4 + 2 + AES_KEY_MAX_LEN + 16 + 16 + 4 + 16 * 2];
210210
int str_len;
211211

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

231-
if (!server_ip) {
232-
assert(!client_ip);
231+
if (is_ip_v6) {
233232
memcpy(str + str_len, client_ipv6, 16);
234233
memcpy(str + str_len + 16, server_ipv6, 16);
235234
str_len += 32;
236-
} else {
237-
assert(client_ip);
238235
}
239236

240237
memcpy(str + str_len, nonce_client, 16);

net/net-crypto-aes.h

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -56,19 +56,22 @@ int aes_generate_nonce (char res[16]);
5656

5757
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,
5858
unsigned server_ip, unsigned short server_port, const unsigned char server_ipv6[16], unsigned client_ip, unsigned short client_port,
59-
const unsigned char client_ipv6[16]);
59+
const unsigned char client_ipv6[16], bool is_ip_v6);
6060
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);
6161

62-
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],
63-
int client_timestamp, struct connection *c) {
62+
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],
63+
int server_timestamp, int client_timestamp, struct connection *c) {
6464
uint32_t our_ip, remote_ip;
6565
uint16_t our_port, remote_port;
6666
uint8_t remote_ipv6[16] = {'\0'};
6767
uint8_t our_ipv6[16] = {'\0'};
6868
our_ip = remote_ip = our_port = remote_port = 0;
6969

70-
assert(c->local_endpoint.ss_family == c->remote_endpoint.ss_family);
71-
switch (c->local_endpoint.ss_family) {
70+
bool is_ipv6 = false;
71+
72+
if (protocol_version == 0) {
73+
assert(c->local_endpoint.ss_family == c->remote_endpoint.ss_family);
74+
switch (c->local_endpoint.ss_family) {
7275
case AF_INET:
7376
our_ip = inet_sockaddr_address(&c->local_endpoint);
7477
remote_ip = inet_sockaddr_address(&c->remote_endpoint);
@@ -80,15 +83,16 @@ static inline int aes_create_connection_keys(aes_key_t *key, struct aes_session_
8083
memcpy(our_ipv6, inet6_sockaddr_address(&c->local_endpoint), sizeof(our_ipv6));
8184
our_port = inet6_sockaddr_port(&c->local_endpoint);
8285
remote_port = inet6_sockaddr_port(&c->remote_endpoint);
86+
is_ipv6 = true;
8387
break;
8488
default:
8589
assert(0);
90+
}
8691
}
8792

8893
return am_client
89-
? 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)
90-
91-
: 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);
94+
? 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)
95+
: 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);
9296
}
9397

9498
static inline int get_crypto_key_id(const aes_key_t *key) {

net/net-memcache-client.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -611,7 +611,7 @@ int mcc_start_crypto (struct connection *c, char *key, int key_len) {
611611

612612
struct aes_session_key aes_keys;
613613

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

net/net-memcache-server.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1029,7 +1029,7 @@ int mcs_init_crypto (struct connection *c, char *key, int key_len) {
10291029

10301030
struct aes_session_key aes_keys;
10311031

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

net/net-mysql-client.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -567,7 +567,7 @@ int sqlc_init_crypto (struct connection *c, char *key, int key_len) {
567567

568568
struct aes_session_key aes_keys;
569569

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

net/net-tcp-rpc-client.cpp

Lines changed: 40 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -73,9 +73,9 @@ int tcp_rpcc_default_execute (struct connection *c, int op, raw_message_t *raw)
7373
tvkprintf(net_connections, 3, "rpcc_execute: fd=%d, op=%d, len=%d\n", c->fd, op, raw->total_bytes);
7474
if (op == TL_RPC_PING && raw->total_bytes == 12) {
7575
c->last_response_time = precise_now;
76-
static int Q[12];
76+
int Q[12];
7777
assert (rwm_fetch_data (raw, Q, 12) == 12);
78-
static int P[12];
78+
int P[12];
7979
P[0] = TL_RPC_PONG;
8080
P[1] = Q[1];
8181
P[2] = Q[2];
@@ -90,18 +90,24 @@ int tcp_rpcc_default_execute (struct connection *c, int op, raw_message_t *raw)
9090

9191
static int tcp_rpcc_process_nonce_packet (struct connection *c, raw_message_t *msg) {
9292
struct tcp_rpc_data *D = TCP_RPC_DATA(c);
93-
static struct tcp_rpc_nonce_packet P;
93+
struct tcp_rpc_nonce_packet P{};
9494
int res;
9595

9696
if (D->packet_num != -2 || D->packet_type != RPC_NONCE) {
9797
return -2;
9898
}
99-
if (D->packet_len != sizeof (struct tcp_rpc_nonce_packet)) {
99+
if (D->packet_len < sizeof (P) || D->packet_len >= 1024) {
100100
return -3;
101101
}
102+
int excess_data_size = D->packet_len - sizeof(P); // fields from newer protocol version
102103

103-
assert (rwm_fetch_data (msg, &P, D->packet_len) == D->packet_len);
104-
tvkprintf(net_connections, 4, "Processing nonce packet, crypto schema: %d, key select: %d\n", P.crypto_schema, P.key_select);
104+
assert (rwm_fetch_data (msg, &P, sizeof(P)) == sizeof(P));
105+
assert (rwm_fetch_data (msg, 0, excess_data_size) == excess_data_size);
106+
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);
107+
108+
if (P.protocol_version > 1) { // server must not reply with version > client
109+
return -3;
110+
}
105111

106112
switch (P.crypto_schema) {
107113
case RPC_CRYPTO_NONE:
@@ -127,7 +133,7 @@ static int tcp_rpcc_process_nonce_packet (struct connection *c, raw_message_t *m
127133
if (abs (P.crypto_ts - D->nonce_time) > 30) {
128134
return -6; //less'om
129135
}
130-
res = TCP_RPCC_FUNC(c)->rpc_start_crypto (c, P.crypto_nonce, P.key_select);
136+
res = TCP_RPCC_FUNC(c)->rpc_start_crypto (c, &P);
131137
if (res < 0) {
132138
return -6;
133139
}
@@ -142,14 +148,13 @@ static int tcp_rpcc_process_nonce_packet (struct connection *c, raw_message_t *m
142148
static int tcp_rpcc_send_handshake_packet (struct connection *c) {
143149
tvkprintf(net_connections, 4, "tcp_rpcc_send_handshake_packet\n");
144150
struct tcp_rpc_data *D = TCP_RPC_DATA (c);
145-
static struct tcp_rpc_handshake_packet P;
151+
struct tcp_rpc_handshake_packet P{};
146152
if (!PID.ip) {
147153
init_client_PID(c->local_endpoint.ss_family == AF_INET ? inet_sockaddr_address(&c->local_endpoint): 0);
148154
if (!PID.ip) {
149155
PID.ip = get_my_ipv4 ();
150156
}
151157
}
152-
memset (&P, 0, sizeof (P));
153158
P.type = RPC_HANDSHAKE;
154159
P.flags = default_rpc_flags & RPC_CRYPTO_USE_CRC32C;
155160
if (!D->remote_pid.port) {
@@ -167,11 +172,10 @@ static int tcp_rpcc_send_handshake_packet (struct connection *c) {
167172
}
168173

169174
static int tcp_rpcc_send_handshake_error_packet (struct connection *c, int error_code) {
170-
static struct tcp_rpc_handshake_error_packet P;
175+
struct tcp_rpc_handshake_error_packet P{};
171176
if (!PID.pid) {
172177
init_client_PID(inet_sockaddr_address(&c->local_endpoint));
173178
}
174-
memset (&P, 0, sizeof (P));
175179
P.type = RPC_HANDSHAKE_ERROR;
176180
P.error_code = error_code;
177181
memcpy (&P.sender_pid, &PID, sizeof (PID));
@@ -185,11 +189,11 @@ static int tcp_rpcc_process_handshake_packet (struct connection *c, raw_message_
185189
tvkprintf(net_connections, 4, "tcp_rpcc_process_handshake_packet\n");
186190

187191
struct tcp_rpc_data *D = TCP_RPC_DATA(c);
188-
static struct tcp_rpc_handshake_packet P;
192+
struct tcp_rpc_handshake_packet P{};
189193
if (D->packet_num != -1 || D->packet_type != RPC_HANDSHAKE) {
190194
return -2;
191195
}
192-
if (D->packet_len != sizeof (struct tcp_rpc_handshake_packet)) {
196+
if (D->packet_len != sizeof (P)) {
193197
tcp_rpcc_send_handshake_error_packet (c, -3);
194198
return -3;
195199
}
@@ -227,17 +231,23 @@ int tcp_rpcc_parse_execute (struct connection *c) {
227231
int len;
228232

229233
while (true) {
230-
len = c->in.total_bytes;
234+
len = c->in.total_bytes;
231235
if (len <= 0) {
232236
break;
233237
}
234238
if (!D->packet_len) {
235-
if (len < 4) {
239+
if (len < D->packet_v1_padding + 4) {
236240
c->status = conn_reading_answer;
237-
return 4 - len;
241+
return D->packet_v1_padding + 4 - len;
242+
}
243+
if (D->packet_v1_padding) {
244+
assert(D->packet_v1_padding < 4);
245+
assert(rwm_fetch_data(&c->in, 0, D->packet_v1_padding) == D->packet_v1_padding);
246+
D->packet_v1_padding = 0;
238247
}
239248
assert (rwm_fetch_lookup (&c->in, &D->packet_len, 4) == 4);
240-
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)) {
249+
// We skip checks for len&3 == 0 for protocol version 0, because there is little value in it.
250+
if (D->packet_len > TCP_RPCC_FUNC(c)->max_packet_len && TCP_RPCC_FUNC(c)->max_packet_len > 0) {
241251
tvkprintf(net_connections, 1, "error while parsing packet: bad packet length %d\n", D->packet_len);
242252
c->status = conn_error;
243253
c->error = -1;
@@ -259,7 +269,6 @@ int tcp_rpcc_parse_execute (struct connection *c) {
259269
c->status = conn_reading_answer;
260270
return D->packet_len - len;
261271
}
262-
263272

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

341350
D->in_packet_num++;
351+
if (c->crypto) {
352+
D->packet_v1_padding = (-D->packet_len) & 3;
353+
}
342354
D->packet_len = 0;
343355
if (c->status == conn_running) {
344356
c->status = conn_wait_answer;
@@ -421,10 +433,10 @@ int tcp_rpcc_init_fake_crypto (struct connection *c) {
421433
return -1;
422434
}
423435

424-
static struct tcp_rpc_nonce_packet buf;
425-
memset (&buf, 0, sizeof (buf));
436+
struct tcp_rpc_nonce_packet buf{};
426437
buf.type = RPC_NONCE;
427438
buf.crypto_schema = RPC_CRYPTO_NONE;
439+
buf.protocol_version = 1; // ask for latest version we support
428440

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

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

478490
aes_generate_nonce (TCP_RPC_DATA(c)->nonce);
479491

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

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

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

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

501513
if (c->crypto) {
502514
return -1;
@@ -506,13 +518,13 @@ int tcp_rpcc_start_crypto (struct connection *c, char *nonce, int key_select) {
506518
return -1;
507519
}
508520

509-
if (!key_select || key_select != get_crypto_key_id (default_aes_key)) {
521+
if (!P->key_select || P->key_select != get_crypto_key_id (default_aes_key)) {
510522
return -1;
511523
}
512524

513525
struct aes_session_key aes_keys;
514526

515-
if (aes_create_connection_keys (default_aes_key, &aes_keys, 1, nonce, D->nonce, D->nonce_time, c) < 0) {
527+
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) {
516528
return -1;
517529
}
518530

@@ -529,7 +541,7 @@ void tcp_rpcc_flush_crypto (struct connection *c) {
529541
tvkprintf(net_connections, 4, "rpcc_flush_packet: padding with %d bytes\n", pad_bytes);
530542
if (pad_bytes > 0) {
531543
assert (!(pad_bytes & 3));
532-
static int pad_str[3] = {4, 4, 4};
544+
int pad_str[3] = {4, 4, 4};
533545
assert (pad_bytes <= 12);
534546
assert (rwm_push_data (&c->out, pad_str, pad_bytes) == pad_bytes);
535547
}
@@ -552,7 +564,7 @@ int tcp_rpcc_flush (struct connection *c) {
552564
tvkprintf(net_connections, 4, "rpcs_flush: padding with %d bytes\n", pad_bytes);
553565
if (pad_bytes > 0) {
554566
assert (!(pad_bytes & 3));
555-
static int pad_str[3] = {4, 4, 4};
567+
int pad_str[3] = {4, 4, 4};
556568
assert (pad_bytes <= 12);
557569
assert (rwm_push_data (&c->out, pad_str, pad_bytes) == pad_bytes);
558570
}

net/net-tcp-rpc-client.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <sys/cdefs.h>
99

1010
#include "net/net-connections.h"
11+
#include "net/net-tcp-rpc-common.h"
1112
#include "net/net-msg.h"
1213

1314
struct tcp_rpc_client_functions {
@@ -17,7 +18,7 @@ struct tcp_rpc_client_functions {
1718
int (*flush_packet)(struct connection *c); /* execute this to push query to server */
1819
int (*rpc_check_perm)(struct connection *c); /* 1 = allow unencrypted, 2 = allow encrypted */
1920
int (*rpc_init_crypto)(struct connection *c); /* 1 = ok; -1 = no crypto */
20-
int (*rpc_start_crypto)(struct connection *c, char *nonce, int key_select); /* 1 = ok; -1 = no crypto */
21+
int (*rpc_start_crypto)(struct connection *c, struct tcp_rpc_nonce_packet *P); /* 1 = ok; -1 = no crypto */
2122
int (*rpc_wakeup)(struct connection *c);
2223
int (*rpc_alarm)(struct connection *c);
2324
int (*rpc_ready)(struct connection *c);
@@ -38,7 +39,7 @@ int tcp_rpcc_flush_packet_later (struct connection *c);
3839
int tcp_rpcc_default_check_perm (struct connection *c);
3940
int tcp_rpcc_default_check_perm_crypto (struct connection *c);
4041
int tcp_rpcc_init_crypto (struct connection *c);
41-
int tcp_rpcc_start_crypto (struct connection *c, char *nonce, int key_select);
42+
int tcp_rpcc_start_crypto (struct connection *c, struct tcp_rpc_nonce_packet *P);
4243
int default_tcp_rpc_client_check_ready(struct connection *c);
4344

4445
#define TCP_RPCC_FUNC(c) ((struct tcp_rpc_client_functions *) ((c)->extra))

net/net-tcp-rpc-common.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ OPTION_PARSER(OPT_RPC, "no-crc32c", no_argument, "Force use of CRC32 instead of
2727

2828
void tcp_rpc_conn_send (struct connection *c, raw_message_t *raw, int flags) {
2929
tvkprintf(net_connections, 4, "%s: sending message of size %d to conn fd=%d\n", __func__, raw->total_bytes, c->fd);
30-
assert (!(raw->total_bytes & 3));
3130
int Q[2];
3231
Q[0] = raw->total_bytes + 12;
3332
Q[1] = TCP_RPC_DATA(c)->out_packet_num ++;
@@ -40,11 +39,15 @@ void tcp_rpc_conn_send (struct connection *c, raw_message_t *raw, int flags) {
4039
rwm_push_data_front (&r, Q, 8);
4140
unsigned crc32 = rwm_custom_crc32 (&r, r.total_bytes, TCP_RPC_DATA(c)->custom_crc_partial);
4241
rwm_push_data (&r, &crc32, 4);
42+
if (c->crypto) {
43+
int packet_v1_padding = (-raw->total_bytes) & 3;
44+
char padding[3]{};
45+
rwm_push_data (&r, &padding, packet_v1_padding);
46+
}
4347
rwm_union (&c->out, &r);
4448
}
4549

4650
void tcp_rpc_conn_send_data (struct connection *c, int len, void *Q) {
47-
assert (!(len & 3));
4851
raw_message_t r;
4952
assert (rwm_create (&r, Q, len) == len);
5053
tcp_rpc_conn_send (c, &r, 0);

net/net-tcp-rpc-common.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@
1717
struct tcp_rpc_nonce_packet {
1818
int type;
1919
int key_select; /* least significant 32 bits of key to use */
20-
int crypto_schema; /* 0 = NONE, 1 = AES */
20+
unsigned char crypto_schema; /* 0 = NONE, 1 = AES */
21+
unsigned char protocol_version;
22+
unsigned short protocol_flags;
2123
int crypto_ts;
2224
char crypto_nonce[16];
2325
};
@@ -43,6 +45,7 @@ void tcp_rpc_conn_send_data (struct connection *c, int len, void *Q);
4345
/* in conn->custom_data */
4446
struct tcp_rpc_data {
4547
int packet_len;
48+
int packet_v1_padding;
4649
int packet_num;
4750
int packet_type;
4851
int packet_crc32;
@@ -67,6 +70,8 @@ struct tcp_rpc_data {
6770

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

73+
static_assert(sizeof(connection_t::custom_data) >= sizeof(tcp_rpc_data));
74+
7075
#define RPC_CRYPTO_ALLOW_UNENCRYPTED 0x00000001
7176
#define RPC_CRYPTO_ALLOW_ENCRYPTED 0x00000002
7277
#define RPC_CRYPTO_ALLOW_MASK (RPC_CRYPTO_ALLOW_UNENCRYPTED | RPC_CRYPTO_ALLOW_ENCRYPTED)

0 commit comments

Comments
 (0)