Commit cf26efc6 authored by vvaltman's avatar vvaltman

updated mtproto proxy protocol

parent 20824f5f
......@@ -789,11 +789,38 @@ static int _notify_remote_closed (JOB_REF_ARG(C), long long out_conn_id) {
}
void push_rpc_confirmation (JOB_REF_ARG (C), int confirm) {
struct raw_message *msg = malloc (sizeof (struct raw_message));
rwm_create (msg, "\xdd", 1);
rwm_push_data (msg, &confirm, 4);
mpq_push_w (CONN_INFO(C)->out_queue, msg, 0);
job_signal (JOB_REF_PASS (C), JS_RUN);
if ((lrand48_j() & 1) || !(TCP_RPC_DATA(C)->flags & RPC_F_PAD)) {
struct raw_message *msg = malloc (sizeof (struct raw_message));
rwm_create (msg, "\xdd", 1);
rwm_push_data (msg, &confirm, 4);
mpq_push_w (CONN_INFO(C)->out_queue, msg, 0);
job_signal (JOB_REF_PASS (C), JS_RUN);
} else {
int x = -1;
struct raw_message m;
assert (rwm_create (&m, &x, 4) == 4);
assert (rwm_push_data (&m, &confirm, 4) == 4);
int z = lrand48_j() & 1;
while (z-- > 0) {
int t = lrand48_j();
assert (rwm_push_data (&m, &t, 4) == 4);
}
tcp_rpc_conn_send (JOB_REF_CREATE_PASS (C), &m, 0);
x = 0;
assert (rwm_create (&m, &x, 4) == 4);
z = lrand48_j() & 1;
while (z-- > 0) {
int t = lrand48_j();
assert (rwm_push_data (&m, &t, 4) == 4);
}
tcp_rpc_conn_send (JOB_REF_PASS (C), &m, 0);
}
}
struct client_packet_info {
......@@ -1645,7 +1672,7 @@ conn_target_job_t choose_proxy_target (int target_dc) {
}
static int forward_mtproto_enc_packet (struct tl_in_state *tlio_in, connection_job_t C, long long auth_key_id, int len, int remote_ip_port[5], int rpc_flags) {
if (len < offsetof (struct encrypted_message, message) || (len & 15) != (offsetof (struct encrypted_message, server_salt) & 15)) {
if (len < offsetof (struct encrypted_message, message) /*|| (len & 15) != (offsetof (struct encrypted_message, server_salt) & 15)*/) {
return 0;
}
vkprintf (2, "received mtproto encrypted packet of %d bytes from connection %p (#%d~%d), key=%016llx\n", len, C, CONN_INFO(C)->fd, CONN_INFO(C)->generation, auth_key_id);
......@@ -1670,11 +1697,11 @@ int forward_mtproto_packet (struct tl_in_state *tlio_in, connection_job_t C, int
}
vkprintf (2, "received mtproto packet of %d bytes\n", len);
int inner_len = header[4];
if (inner_len + 20 != len) {
if (inner_len + 20 > len) {
vkprintf (1, "received packet with bad inner length: %d (%d expected)\n", inner_len, len - 20);
return 0;
}
if (len < 40) {
if (inner_len < 20) {
//must have at least function id and nonce
return 0;
}
......
......@@ -185,8 +185,17 @@ int tcp_rpc_write_packet_compact (connection_job_t C, struct raw_message *raw) {
return tcp_rpc_write_packet (C, raw);
}
if (TCP_RPC_DATA(C)->flags & RPC_F_PAD) {
int x = lrand48_j();
int y = lrand48_j() & 3;
assert (rwm_push_data (raw, &x, y) == y);
}
int len = raw->total_bytes;
assert (!(len & 0xfc000003));
assert (!(len & 0xfc000000));
if (!(TCP_RPC_DATA(C)->flags & RPC_F_PAD)) {
assert (!(len & 3));
}
if (TCP_RPC_DATA(C)->flags & RPC_F_MEDIUM) {
rwm_push_data_front (raw, &len, 4);
} else if (len <= 0x7e * 4) {
......
......@@ -105,6 +105,7 @@ int tcp_rpc_default_execute (connection_job_t C, int op, struct raw_message *raw
#define RPCF_USE_CRC32C 2048
/* for flags in struct tcp_rpc_data */
#define RPC_F_PAD 0x8000000
#define RPC_F_DROPPED 0x10000000
#define RPC_F_MEDIUM 0x20000000
#define RPC_F_COMPACT 0x40000000
......
......@@ -149,6 +149,13 @@ int tcp_rpcs_compact_parse_execute (connection_job_t C) {
vkprintf (1, "Medium type\n");
continue;
}
if (packet_len == 0xdddddddd) {
D->flags |= RPC_F_MEDIUM | RPC_F_PAD;
assert (rwm_skip_data (&c->in, 4) == 4);
D->in_packet_num = 0;
vkprintf (1, "Medium type\n");
continue;
}
// http
if ((packet_len == *(int *)"HEAD" || packet_len == *(int *)"POST" || packet_len == *(int *)"GET " || packet_len == *(int *)"OPTI") && TCP_RPCS_FUNC(C)->http_fallback_type) {
......@@ -216,7 +223,7 @@ int tcp_rpcs_compact_parse_execute (connection_job_t C) {
T->read_aeskey.type->ctr128_crypt (&T->read_aeskey, random_header, random_header, 64, T->read_iv, T->read_ebuf, &T->read_num);
unsigned tag = *(unsigned *)(random_header + 56);
if (tag == 0xeeeeeeee || tag == 0xefefefef) {
if (tag == 0xdddddddd || tag == 0xeeeeeeee || tag == 0xefefefef) {
assert (rwm_skip_data (&c->in, 64) == 64);
rwm_union (&c->in_u, &c->in);
rwm_init (&c->in, 0);
......@@ -226,6 +233,9 @@ int tcp_rpcs_compact_parse_execute (connection_job_t C) {
case 0xeeeeeeee:
D->flags |= RPC_F_MEDIUM | RPC_F_EXTMODE2;
break;
case 0xdddddddd:
D->flags |= RPC_F_MEDIUM | RPC_F_EXTMODE2 | RPC_F_PAD;
break;
case 0xefefefef:
D->flags |= RPC_F_COMPACT | RPC_F_EXTMODE2;
break;
......@@ -269,10 +279,10 @@ int tcp_rpcs_compact_parse_execute (connection_job_t C) {
int packet_len_bytes = 4;
if (D->flags & RPC_F_MEDIUM) {
// packet len in `medium` mode
if (D->crypto_flags & RPCF_QUICKACK) {
//if (D->crypto_flags & RPCF_QUICKACK) {
D->flags = (D->flags & ~RPC_F_QUICKACK) | (packet_len & RPC_F_QUICKACK);
packet_len &= ~RPC_F_QUICKACK;
}
//}
} else {
// packet len in `compact` mode
if (packet_len & 0x80) {
......@@ -295,7 +305,7 @@ int tcp_rpcs_compact_parse_execute (connection_job_t C) {
packet_len <<= 2;
}
if (packet_len <= 0 || (packet_len & 0xc0000003)) {
if (packet_len <= 0 || (packet_len & 0xc0000000) || (!(D->flags & RPC_F_PAD) && (packet_len & 3))) {
vkprintf (1, "error while parsing packet: bad packet length %d\n", packet_len);
fail_connection (C, -1);
return 0;
......@@ -317,6 +327,9 @@ int tcp_rpcs_compact_parse_execute (connection_job_t C) {
int packet_type;
rwm_split_head (&msg, &c->in, packet_len);
if (D->flags & RPC_F_PAD) {
rwm_trunc (&msg, packet_len & -4);
}
assert (rwm_fetch_lookup (&msg, &packet_type, 4) == 4);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment