diff --git a/td/mtproto/HttpTransport.cpp b/td/mtproto/HttpTransport.cpp index 03c23c89..a84d97ed 100644 --- a/td/mtproto/HttpTransport.cpp +++ b/td/mtproto/HttpTransport.cpp @@ -74,6 +74,10 @@ size_t Transport::max_prepend_size() const { return MAX_PREPEND_SIZE; } +size_t Transport::max_append_size() const { + return 0; +} + } // namespace http } // namespace mtproto } // namespace td diff --git a/td/mtproto/HttpTransport.h b/td/mtproto/HttpTransport.h index c1874a05..6fc6084f 100644 --- a/td/mtproto/HttpTransport.h +++ b/td/mtproto/HttpTransport.h @@ -33,6 +33,7 @@ class Transport : public IStreamTransport { } size_t max_prepend_size() const override; + size_t max_append_size() const override; TransportType get_type() const override { return {TransportType::Http, 0, ""}; } diff --git a/td/mtproto/IStreamTransport.h b/td/mtproto/IStreamTransport.h index 61501955..e69c7724 100644 --- a/td/mtproto/IStreamTransport.h +++ b/td/mtproto/IStreamTransport.h @@ -30,6 +30,7 @@ class IStreamTransport { virtual bool can_write() const = 0; virtual void init(ChainBufferReader *input, ChainBufferWriter *output) = 0; virtual size_t max_prepend_size() const = 0; + virtual size_t max_append_size() const = 0; virtual TransportType get_type() const = 0; }; diff --git a/td/mtproto/RawConnection.cpp b/td/mtproto/RawConnection.cpp index c112d6c7..c58a0e9f 100644 --- a/td/mtproto/RawConnection.cpp +++ b/td/mtproto/RawConnection.cpp @@ -27,7 +27,8 @@ void RawConnection::send_crypto(const Storer &storer, int64 session_id, int64 sa info.salt = salt; info.session_id = session_id; - auto packet = BufferWriter{mtproto::Transport::write(storer, auth_key, &info), transport_->max_prepend_size(), 0}; + auto packet = BufferWriter{mtproto::Transport::write(storer, auth_key, &info), transport_->max_prepend_size(), + transport_->max_append_size()}; mtproto::Transport::write(storer, auth_key, &info, packet.as_slice()); bool use_quick_ack = false; @@ -47,8 +48,8 @@ uint64 RawConnection::send_no_crypto(const Storer &storer) { mtproto::PacketInfo info; info.no_crypto_flag = true; - auto packet = - BufferWriter{mtproto::Transport::write(storer, mtproto::AuthKey(), &info), transport_->max_prepend_size(), 0}; + auto packet = BufferWriter{mtproto::Transport::write(storer, mtproto::AuthKey(), &info), + transport_->max_prepend_size(), transport_->max_append_size()}; mtproto::Transport::write(storer, mtproto::AuthKey(), &info, packet.as_slice()); LOG(INFO) << "Send handshake packet: " << format::as_hex_dump<4>(packet.as_slice()); transport_->write(std::move(packet), false); diff --git a/td/mtproto/TcpTransport.cpp b/td/mtproto/TcpTransport.cpp index d50b2166..d3ab8146 100644 --- a/td/mtproto/TcpTransport.cpp +++ b/td/mtproto/TcpTransport.cpp @@ -58,11 +58,20 @@ void IntermediateTransport::write_prepare_inplace(BufferWriter *message, bool qu CHECK(prepend.size() >= prepend_size); message->confirm_prepend(prepend_size); - as(message->as_slice().begin()) = static_cast(size); + size_t append_size = 0; + if (with_padding()) { + append_size = static_cast(Random::secure_int32()) % 16; + MutableSlice append = message->prepare_append().truncate(append_size); + CHECK(append.size() == append_size); + Random::secure_bytes(append); + message->confirm_append(append.size()); + } + + as(message->as_slice().begin()) = static_cast(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(&magic), 4)); } @@ -153,7 +162,7 @@ void ObfuscatedTransport::init(ChainBufferReader *input, ChainBufferWriter *outp } // TODO: It is actually IntermediateTransport::init_output_stream, so it will work only with // TransportImpl==IntermediateTransport - as(header_slice.begin() + 56) = 0xeeeeeeee; + as(header_slice.begin() + 56) = impl_.with_padding() ? 0xdddddddd : 0xeeeeeeee; if (dc_id_ != 0) { as(header_slice.begin() + 60) = dc_id_; } @@ -161,6 +170,9 @@ void ObfuscatedTransport::init(ChainBufferReader *input, ChainBufferWriter *outp string rheader = header; std::reverse(rheader.begin(), rheader.end()); auto key = as(rheader.data() + 8); + if (secret_.size() == 17) { + secret_ = secret_.substr(1); + } auto fix_key = [&](UInt256 &key) { if (secret_.size() == 16) { Sha256State state; diff --git a/td/mtproto/TcpTransport.h b/td/mtproto/TcpTransport.h index 6737f56a..43c60105 100644 --- a/td/mtproto/TcpTransport.h +++ b/td/mtproto/TcpTransport.h @@ -56,12 +56,20 @@ class AbridgedTransport : public ITransport { class IntermediateTransport : ITransport { public: + explicit IntermediateTransport(bool with_padding) : with_padding_(with_padding) { + } size_t read_from_stream(ChainBufferReader *stream, BufferSlice *message, uint32 *quick_ack) override; void write_prepare_inplace(BufferWriter *message, bool quick_ack) override; void init_output_stream(ChainBufferWriter *stream) override; bool support_quick_ack() const override { return true; } + bool with_padding() const { + return with_padding_; + } + + private: + bool with_padding_; }; using TransportImpl = IntermediateTransport; @@ -94,12 +102,17 @@ class OldTransport : public IStreamTransport { size_t max_prepend_size() const override { return 4; } + + size_t max_append_size() const override { + return 15; + } + TransportType get_type() const override { return TransportType{TransportType::Tcp, 0, ""}; } private: - TransportImpl impl_; + TransportImpl impl_{false}; ChainBufferReader *input_; ChainBufferWriter *output_; }; @@ -138,14 +151,18 @@ class ObfuscatedTransport : public IStreamTransport { return 4; } + size_t max_append_size() const override { + return 15; + } + TransportType get_type() const override { return TransportType{TransportType::ObfuscatedTcp, dc_id_, secret_}; } private: - TransportImpl impl_; int16 dc_id_; std::string secret_; + TransportImpl impl_{secret_.size() >= 17}; AesCtrByteFlow aes_ctr_byte_flow_; ByteFlowSink byte_flow_sink_; ChainBufferReader *input_; diff --git a/td/telegram/net/ConnectionCreator.cpp b/td/telegram/net/ConnectionCreator.cpp index c091420b..4d04ec1e 100644 --- a/td/telegram/net/ConnectionCreator.cpp +++ b/td/telegram/net/ConnectionCreator.cpp @@ -288,7 +288,7 @@ void ConnectionCreator::add_proxy(string server, int32 port, bool enable, } case td_api::proxyTypeMtproto::ID: { auto type = td_api::move_object_as(proxy_type); - if (type->secret_.size() != 32 || hex_decode(type->secret_).is_error()) { + if ((type->secret_.size() != 32 && type->secret_.size() != 34) || hex_decode(type->secret_).is_error()) { return promise.set_error(Status::Error(400, "Wrong server secret")); } new_proxy = Proxy::mtproto(server, port, type->secret_);