From cf26efc6367ef3a30cde96ba76d6eaf11871a10a Mon Sep 17 00:00:00 2001 From: vvaltman Date: Mon, 9 Jul 2018 14:04:50 +0300 Subject: [PATCH] updated mtproto proxy protocol --- mtproto/mtproto-proxy.c | 43 +++++++++++++++++++++++++++++------- net/net-tcp-rpc-common.c | 11 ++++++++- net/net-tcp-rpc-common.h | 1 + net/net-tcp-rpc-ext-server.c | 21 ++++++++++++++---- 4 files changed, 63 insertions(+), 13 deletions(-) diff --git a/mtproto/mtproto-proxy.c b/mtproto/mtproto-proxy.c index 711b1f5..9eef02b 100644 --- a/mtproto/mtproto-proxy.c +++ b/mtproto/mtproto-proxy.c @@ -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; } diff --git a/net/net-tcp-rpc-common.c b/net/net-tcp-rpc-common.c index ab175f6..4e9958f 100644 --- a/net/net-tcp-rpc-common.c +++ b/net/net-tcp-rpc-common.c @@ -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) { diff --git a/net/net-tcp-rpc-common.h b/net/net-tcp-rpc-common.h index e1f3618..ad43ece 100644 --- a/net/net-tcp-rpc-common.h +++ b/net/net-tcp-rpc-common.h @@ -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 diff --git a/net/net-tcp-rpc-ext-server.c b/net/net-tcp-rpc-ext-server.c index 4d7ed55..efc29cf 100644 --- a/net/net-tcp-rpc-ext-server.c +++ b/net/net-tcp-rpc-ext-server.c @@ -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);