diff options
Diffstat (limited to 'protocols/Telegram/tdlib/td/td/mtproto/TcpTransport.cpp')
-rw-r--r-- | protocols/Telegram/tdlib/td/td/mtproto/TcpTransport.cpp | 138 |
1 files changed, 123 insertions, 15 deletions
diff --git a/protocols/Telegram/tdlib/td/td/mtproto/TcpTransport.cpp b/protocols/Telegram/tdlib/td/td/mtproto/TcpTransport.cpp index e7613acab0..d46baddf39 100644 --- a/protocols/Telegram/tdlib/td/td/mtproto/TcpTransport.cpp +++ b/protocols/Telegram/tdlib/td/td/mtproto/TcpTransport.cpp @@ -1,12 +1,13 @@ // -// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2018 +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2022 // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // #include "td/mtproto/TcpTransport.h" -#include "td/utils/logging.h" +#include "td/utils/as.h" +#include "td/utils/common.h" #include "td/utils/Random.h" #include "td/utils/Slice.h" @@ -15,6 +16,7 @@ namespace td { namespace mtproto { namespace tcp { + size_t IntermediateTransport::read_from_stream(ChainBufferReader *stream, BufferSlice *message, uint32 *quick_ack) { CHECK(message); size_t stream_size = stream->size(); @@ -58,11 +60,20 @@ void IntermediateTransport::write_prepare_inplace(BufferWriter *message, bool qu CHECK(prepend.size() >= prepend_size); message->confirm_prepend(prepend_size); - as<uint32>(message->as_slice().begin()) = static_cast<uint32>(size); + size_t append_size = 0; + if (with_padding()) { + append_size = Random::secure_uint32() % 16; + MutableSlice append = message->prepare_append().substr(0, append_size); + CHECK(append.size() == append_size); + Random::secure_bytes(append); + message->confirm_append(append.size()); + } + + as<uint32>(message->as_slice().begin()) = static_cast<uint32>(size + append_size); } void IntermediateTransport::init_output_stream(ChainBufferWriter *stream) { - const uint32 magic = 0xeeeeeeee; + const uint32 magic = with_padding() ? 0xdddddddd : 0xeeeeeeee; stream->append(Slice(reinterpret_cast<const char *>(&magic), 4)); } @@ -121,8 +132,7 @@ void AbridgedTransport::write_prepare_inplace(BufferWriter *message, bool quick_ } void AbridgedTransport::init_output_stream(ChainBufferWriter *stream) { - const uint8 magic = 0xef; - stream->append(Slice(&magic, 1)); + stream->append("\xef"); } void ObfuscatedTransport::init(ChainBufferReader *input, ChainBufferWriter *output) { @@ -137,15 +147,18 @@ void ObfuscatedTransport::init(ChainBufferReader *input, ChainBufferWriter *outp try_cnt++; CHECK(try_cnt < 10); Random::secure_bytes(header_slice.ubegin(), header.size()); + if (secret_.emulate_tls()) { + break; + } if (as<uint8>(header.data()) == 0xef) { continue; } - auto first_int = as<uint32>(header.data()); + uint32 first_int = as<uint32>(header.data()); if (first_int == 0x44414548 || first_int == 0x54534f50 || first_int == 0x20544547 || first_int == 0x4954504f || - first_int == 0xeeeeeeee) { + first_int == 0xdddddddd || first_int == 0xeeeeeeee || first_int == 0x02010316) { continue; } - auto second_int = as<uint32>(header.data() + sizeof(uint32)); + uint32 second_int = as<uint32>(header.data() + sizeof(uint32)); if (second_int == 0) { continue; } @@ -153,19 +166,114 @@ void ObfuscatedTransport::init(ChainBufferReader *input, ChainBufferWriter *outp } // TODO: It is actually IntermediateTransport::init_output_stream, so it will work only with // TransportImpl==IntermediateTransport - as<uint32>(header_slice.begin() + 56) = 0xeeeeeeee; + as<uint32>(header_slice.begin() + 56) = impl_.with_padding() ? 0xdddddddd : 0xeeeeeeee; + if (dc_id_ != 0) { + as<int16>(header_slice.begin() + 60) = dc_id_; + } string rheader = header; std::reverse(rheader.begin(), rheader.end()); - aes_ctr_byte_flow_.init(as<UInt256>(rheader.data() + 8), as<UInt128>(rheader.data() + 8 + 32)); - aes_ctr_byte_flow_.set_input(input_); + UInt256 key = as<UInt256>(rheader.data() + 8); + Slice proxy_secret = secret_.get_proxy_secret(); + auto fix_key = [&](UInt256 &key) { + if (!proxy_secret.empty()) { + Sha256State state; + state.init(); + state.feed(as_slice(key)); + state.feed(proxy_secret); + state.extract(as_slice(key)); + } + }; + fix_key(key); + aes_ctr_byte_flow_.init(key, as<UInt128>(rheader.data() + 8 + 32)); + if (secret_.emulate_tls()) { + tls_reader_byte_flow_.set_input(input_); + tls_reader_byte_flow_ >> aes_ctr_byte_flow_; + } else { + aes_ctr_byte_flow_.set_input(input_); + } aes_ctr_byte_flow_ >> byte_flow_sink_; output_key_ = as<UInt256>(header.data() + 8); - output_state_.init(output_key_, as<UInt128>(header.data() + 8 + 32)); - output_->append(header_slice.substr(0, 56)); + fix_key(output_key_); + output_state_.init(as_slice(output_key_), Slice(header.data() + 8 + 32, 16)); + header_ = header; output_state_.encrypt(header_slice, header_slice); - output_->append(header_slice.substr(56, 8)); + MutableSlice(header_).substr(56).copy_from(header_slice.substr(56)); +} + +Result<size_t> ObfuscatedTransport::read_next(BufferSlice *message, uint32 *quick_ack) { + if (secret_.emulate_tls()) { + tls_reader_byte_flow_.wakeup(); + } else { + aes_ctr_byte_flow_.wakeup(); + } + return impl_.read_from_stream(byte_flow_sink_.get_output(), message, quick_ack); +} + +void ObfuscatedTransport::write(BufferWriter &&message, bool quick_ack) { + impl_.write_prepare_inplace(&message, quick_ack); + output_state_.encrypt(message.as_slice(), message.as_slice()); + if (secret_.emulate_tls()) { + do_write_tls(std::move(message)); + } else { + do_write_main(std::move(message)); + } +} + +void ObfuscatedTransport::do_write_main(BufferWriter &&message) { + BufferBuilder builder(std::move(message)); + if (!header_.empty()) { + builder.prepend(header_); + header_ = {}; + } + do_write(builder.extract()); +} + +void ObfuscatedTransport::do_write_tls(BufferWriter &&message) { + CHECK(header_.size() <= MAX_TLS_PACKET_LENGTH); + if (message.size() + header_.size() > MAX_TLS_PACKET_LENGTH) { + auto buffer_slice = message.as_buffer_slice(); + auto slice = buffer_slice.as_slice(); + while (!slice.empty()) { + auto buf = buffer_slice.from_slice(slice.substr(0, MAX_TLS_PACKET_LENGTH - header_.size())); + slice.remove_prefix(buf.size()); + BufferBuilder builder; + builder.append(std::move(buf)); + do_write_tls(std::move(builder)); + } + return; + } + + BufferBuilder builder(std::move(message)); + do_write_tls(std::move(builder)); +} + +void ObfuscatedTransport::do_write_tls(BufferBuilder &&builder) { + if (!header_.empty()) { + builder.prepend(header_); + header_ = {}; + } + + size_t size = builder.size(); + CHECK(size <= MAX_TLS_PACKET_LENGTH); + + char buf[] = "\x17\x03\x03\x00\x00"; + buf[3] = static_cast<char>((size >> 8) & 0xff); + buf[4] = static_cast<char>(size & 0xff); + builder.prepend(Slice(buf, 5)); + + if (is_first_tls_packet_) { + is_first_tls_packet_ = false; + Slice first_prefix("\x14\x03\x03\x00\x01\x01"); + builder.prepend(first_prefix); + } + + do_write(builder.extract()); +} + +void ObfuscatedTransport::do_write(BufferSlice &&message) { + output_->append(std::move(message)); } } // namespace tcp |