Add strongly typed ProxySecret class.

GitOrigin-RevId: dbde277c6cce57fd6ff51b2e310dab95e60b38c1
This commit is contained in:
levlam 2019-07-09 05:01:12 +03:00
parent 0c160b008b
commit 7958916080
13 changed files with 194 additions and 89 deletions

View File

@ -345,6 +345,7 @@ set(TDLIB_SOURCE
td/mtproto/IStreamTransport.cpp td/mtproto/IStreamTransport.cpp
td/mtproto/Ping.cpp td/mtproto/Ping.cpp
td/mtproto/PingConnection.cpp td/mtproto/PingConnection.cpp
td/mtproto/ProxySecret.cpp
td/mtproto/RawConnection.cpp td/mtproto/RawConnection.cpp
td/mtproto/SessionConnection.cpp td/mtproto/SessionConnection.cpp
td/mtproto/TcpTransport.cpp td/mtproto/TcpTransport.cpp
@ -476,6 +477,7 @@ set(TDLIB_SOURCE
td/mtproto/PacketStorer.h td/mtproto/PacketStorer.h
td/mtproto/Ping.h td/mtproto/Ping.h
td/mtproto/PingConnection.h td/mtproto/PingConnection.h
td/mtproto/ProxySecret.h
td/mtproto/Query.h td/mtproto/Query.h
td/mtproto/RawConnection.h td/mtproto/RawConnection.h
td/mtproto/SessionConnection.h td/mtproto/SessionConnection.h

View File

@ -56,6 +56,7 @@ class AuthKey {
} }
enum : int32 { AUTH_FLAG = 1, WAS_AUTH_FLAG = 2 }; enum : int32 { AUTH_FLAG = 1, WAS_AUTH_FLAG = 2 };
template <class StorerT> template <class StorerT>
void store(StorerT &storer) const { void store(StorerT &storer) const {
storer.store_binary(auth_key_id_); storer.store_binary(auth_key_id_);

View File

@ -7,6 +7,7 @@
#pragma once #pragma once
#include "td/mtproto/IStreamTransport.h" #include "td/mtproto/IStreamTransport.h"
#include "td/mtproto/ProxySecret.h"
#include "td/mtproto/TransportType.h" #include "td/mtproto/TransportType.h"
#include "td/net/HttpQuery.h" #include "td/net/HttpQuery.h"
@ -40,7 +41,7 @@ class Transport : public IStreamTransport {
size_t max_prepend_size() const override; size_t max_prepend_size() const override;
size_t max_append_size() const override; size_t max_append_size() const override;
TransportType get_type() const override { TransportType get_type() const override {
return {TransportType::Http, 0, secret_}; return {TransportType::Http, 0, ProxySecret::from_raw(secret_)};
} }
bool use_random_padding() const override; bool use_random_padding() const override;

View File

@ -19,7 +19,7 @@ unique_ptr<IStreamTransport> create_transport(TransportType type) {
case TransportType::Tcp: case TransportType::Tcp:
return td::make_unique<tcp::OldTransport>(); return td::make_unique<tcp::OldTransport>();
case TransportType::Http: case TransportType::Http:
return td::make_unique<http::Transport>(type.secret); return td::make_unique<http::Transport>(type.secret.get_raw_secret().str());
} }
UNREACHABLE(); UNREACHABLE();
} }

View File

@ -0,0 +1,46 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2019
//
// 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/ProxySecret.h"
#include "td/utils/base64.h"
#include "td/utils/misc.h"
namespace td {
namespace mtproto {
Result<ProxySecret> ProxySecret::from_link(Slice encoded_secret) {
auto r_decoded = hex_decode(encoded_secret);
if (r_decoded.is_error()) {
r_decoded = base64url_decode(encoded_secret);
}
if (r_decoded.is_error()) {
return Status::Error(400, "Wrong proxy secret");
}
return from_binary(r_decoded.ok());
}
Result<ProxySecret> ProxySecret::from_binary(Slice raw_unchecked_secret) {
if (raw_unchecked_secret.size() == 16 ||
(raw_unchecked_secret.size() == 17 && static_cast<unsigned char>(raw_unchecked_secret[0]) == 0xdd) ||
(raw_unchecked_secret.size() >= 17 && static_cast<unsigned char>(raw_unchecked_secret[0]) == 0xee)) {
return from_raw(raw_unchecked_secret);
}
if (raw_unchecked_secret.size() < 16) {
return Status::Error(400, "Wrong proxy secret");
}
return Status::Error(400, "Unsupported proxy secret");
}
string ProxySecret::get_encoded_secret() const {
if (emulate_tls()) {
return base64url_encode(secret_);
}
return buffer_to_hex(secret_);
}
} // namespace mtproto
} // namespace td

65
td/mtproto/ProxySecret.h Normal file
View File

@ -0,0 +1,65 @@
//
// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2019
//
// 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)
//
#pragma once
#include "td/utils/common.h"
#include "td/utils/Slice.h"
#include "td/utils/Status.h"
namespace td {
namespace mtproto {
class ProxySecret {
public:
static Result<ProxySecret> from_link(Slice encoded_secret);
static Result<ProxySecret> from_binary(Slice raw_unchecked_secret);
static ProxySecret from_raw(Slice raw_secret) {
ProxySecret result;
result.secret_ = raw_secret.str();
return result;
}
Slice get_raw_secret() const {
return secret_;
}
Slice get_proxy_secret() const {
auto proxy_secret = Slice(secret_).truncate(17);
if (proxy_secret.size() == 17) {
proxy_secret.remove_prefix(1);
}
return proxy_secret;
}
string get_encoded_secret() const;
bool use_random_padding() const {
return secret_.size() >= 17;
}
bool emulate_tls() const {
return secret_.size() >= 17 && static_cast<unsigned char>(secret_[0]) == 0xee;
}
string get_domain() const {
CHECK(emulate_tls());
return secret_.substr(17);
}
private:
friend bool operator==(const ProxySecret &lhs, const ProxySecret &rhs) {
return lhs.secret_ == rhs.secret_;
}
string secret_;
};
inline bool operator!=(const ProxySecret &lhs, const ProxySecret &rhs) {
return !(lhs == rhs);
}
} // namespace mtproto
} // namespace td

View File

@ -170,22 +170,19 @@ void ObfuscatedTransport::init(ChainBufferReader *input, ChainBufferWriter *outp
string rheader = header; string rheader = header;
std::reverse(rheader.begin(), rheader.end()); std::reverse(rheader.begin(), rheader.end());
UInt256 key = as<UInt256>(rheader.data() + 8); UInt256 key = as<UInt256>(rheader.data() + 8);
Slice secret_view = secret_; Slice proxy_secret = secret_.get_proxy_secret();
if (secret_view.size() == 17) {
secret_view.remove_prefix(1);
}
auto fix_key = [&](UInt256 &key) { auto fix_key = [&](UInt256 &key) {
if (secret_view.size() == 16) { if (!proxy_secret.empty()) {
Sha256State state; Sha256State state;
sha256_init(&state); sha256_init(&state);
sha256_update(as_slice(key), &state); sha256_update(as_slice(key), &state);
sha256_update(secret_view, &state); sha256_update(proxy_secret, &state);
sha256_final(&state, as_slice(key)); sha256_final(&state, as_slice(key));
} }
}; };
fix_key(key); fix_key(key);
aes_ctr_byte_flow_.init(key, as<UInt128>(rheader.data() + 8 + 32)); aes_ctr_byte_flow_.init(key, as<UInt128>(rheader.data() + 8 + 32));
if (emulate_tls_) { if (secret_.emulate_tls()) {
tls_reader_byte_flow_.set_input(input_); tls_reader_byte_flow_.set_input(input_);
tls_reader_byte_flow_ >> aes_ctr_byte_flow_; tls_reader_byte_flow_ >> aes_ctr_byte_flow_;
} else { } else {
@ -202,7 +199,7 @@ void ObfuscatedTransport::init(ChainBufferReader *input, ChainBufferWriter *outp
} }
Result<size_t> ObfuscatedTransport::read_next(BufferSlice *message, uint32 *quick_ack) { Result<size_t> ObfuscatedTransport::read_next(BufferSlice *message, uint32 *quick_ack) {
if (emulate_tls_) { if (secret_.emulate_tls()) {
tls_reader_byte_flow_.wakeup(); tls_reader_byte_flow_.wakeup();
} else { } else {
aes_ctr_byte_flow_.wakeup(); aes_ctr_byte_flow_.wakeup();
@ -213,7 +210,7 @@ Result<size_t> ObfuscatedTransport::read_next(BufferSlice *message, uint32 *quic
void ObfuscatedTransport::write(BufferWriter &&message, bool quick_ack) { void ObfuscatedTransport::write(BufferWriter &&message, bool quick_ack) {
impl_.write_prepare_inplace(&message, quick_ack); impl_.write_prepare_inplace(&message, quick_ack);
output_state_.encrypt(message.as_slice(), message.as_slice()); output_state_.encrypt(message.as_slice(), message.as_slice());
if (emulate_tls_) { if (secret_.emulate_tls()) {
do_write_tls(std::move(message)); do_write_tls(std::move(message));
} else { } else {
do_write_main(std::move(message)); do_write_main(std::move(message));

View File

@ -7,6 +7,7 @@
#pragma once #pragma once
#include "td/mtproto/IStreamTransport.h" #include "td/mtproto/IStreamTransport.h"
#include "td/mtproto/ProxySecret.h"
#include "td/mtproto/TlsReaderByteFlow.h" #include "td/mtproto/TlsReaderByteFlow.h"
#include "td/mtproto/TransportType.h" #include "td/mtproto/TransportType.h"
@ -112,7 +113,7 @@ class OldTransport : public IStreamTransport {
} }
TransportType get_type() const override { TransportType get_type() const override {
return TransportType{TransportType::Tcp, 0, ""}; return TransportType{TransportType::Tcp, 0, ProxySecret()};
} }
bool use_random_padding() const override { bool use_random_padding() const override {
@ -127,10 +128,8 @@ class OldTransport : public IStreamTransport {
class ObfuscatedTransport : public IStreamTransport { class ObfuscatedTransport : public IStreamTransport {
public: public:
ObfuscatedTransport(int16 dc_id, std::string secret) ObfuscatedTransport(int16 dc_id, const ProxySecret &secret)
: dc_id_(dc_id), secret_(std::move(secret)), impl_(secret_.size() >= 17) { : dc_id_(dc_id), secret_(secret), impl_(secret_.use_random_padding()) {
emulate_tls_ = secret_.size() >= 17 && secret_[0] == '\xee';
use_random_padding_ = secret_.size() >= 17;
} }
Result<size_t> read_next(BufferSlice *message, uint32 *quick_ack) override TD_WARN_UNUSED_RESULT; Result<size_t> read_next(BufferSlice *message, uint32 *quick_ack) override TD_WARN_UNUSED_RESULT;
@ -153,7 +152,7 @@ class ObfuscatedTransport : public IStreamTransport {
size_t max_prepend_size() const override { size_t max_prepend_size() const override {
size_t res = 4; size_t res = 4;
if (emulate_tls_) { if (secret_.emulate_tls()) {
res += 5; res += 5;
if (is_first_tls_packet_) { if (is_first_tls_packet_) {
res += 6; res += 6;
@ -174,21 +173,19 @@ class ObfuscatedTransport : public IStreamTransport {
return TransportType{TransportType::ObfuscatedTcp, dc_id_, secret_}; return TransportType{TransportType::ObfuscatedTcp, dc_id_, secret_};
} }
bool use_random_padding() const override { bool use_random_padding() const override {
return use_random_padding_; return secret_.use_random_padding();
} }
private: private:
int16 dc_id_; int16 dc_id_;
std::string secret_;
bool emulate_tls_{false};
bool use_random_padding_{false};
bool is_first_tls_packet_{true}; bool is_first_tls_packet_{true};
ProxySecret secret_;
std::string header_; std::string header_;
TransportImpl impl_; TransportImpl impl_;
TlsReaderByteFlow tls_reader_byte_flow_; TlsReaderByteFlow tls_reader_byte_flow_;
AesCtrByteFlow aes_ctr_byte_flow_; AesCtrByteFlow aes_ctr_byte_flow_;
ByteFlowSink byte_flow_sink_; ByteFlowSink byte_flow_sink_;
ChainBufferReader *input_; ChainBufferReader *input_ = nullptr;
static constexpr int32 MAX_TLS_PACKET_LENGTH = 2878; static constexpr int32 MAX_TLS_PACKET_LENGTH = 2878;

View File

@ -6,6 +6,8 @@
// //
#pragma once #pragma once
#include "td/mtproto/ProxySecret.h"
#include "td/utils/common.h" #include "td/utils/common.h"
namespace td { namespace td {
@ -14,14 +16,10 @@ namespace mtproto {
struct TransportType { struct TransportType {
enum Type { Tcp, ObfuscatedTcp, Http } type = Tcp; enum Type { Tcp, ObfuscatedTcp, Http } type = Tcp;
int16 dc_id{0}; int16 dc_id{0};
string secret; ProxySecret secret;
TransportType() = default; TransportType() = default;
TransportType(Type type, int16 dc_id, string secret) : type(type), dc_id(dc_id), secret(std::move(secret)) { TransportType(Type type, int16 dc_id, ProxySecret secret) : type(type), dc_id(dc_id), secret(std::move(secret)) {
}
bool emulate_tls() const {
return secret.size() >= 17 && secret[0] == '\xee';
} }
}; };

View File

@ -137,7 +137,7 @@ void Proxy::store(StorerT &storer) const {
} else if (type_ == Proxy::Type::Mtproto) { } else if (type_ == Proxy::Type::Mtproto) {
store(server_, storer); store(server_, storer);
store(port_, storer); store(port_, storer);
store(secret_, storer); store(secret_.get_encoded_secret(), storer);
} else { } else {
CHECK(type_ == Proxy::Type::None); CHECK(type_ == Proxy::Type::None);
} }
@ -155,7 +155,7 @@ void Proxy::parse(ParserT &parser) {
} else if (type_ == Proxy::Type::Mtproto) { } else if (type_ == Proxy::Type::Mtproto) {
parse(server_, parser); parse(server_, parser);
parse(port_, parser); parse(port_, parser);
parse(secret_, parser); secret_ = mtproto::ProxySecret::from_link(parser.template fetch_string<Slice>()).move_as_ok();
} else { } else {
LOG_CHECK(type_ == Proxy::Type::None) << static_cast<int32>(type_); LOG_CHECK(type_ == Proxy::Type::None) << static_cast<int32>(type_);
} }
@ -170,7 +170,8 @@ StringBuilder &operator<<(StringBuilder &string_builder, const Proxy &proxy) {
case Proxy::Type::HttpCaching: case Proxy::Type::HttpCaching:
return string_builder << "ProxyHttpCaching " << proxy.server() << ":" << proxy.port(); return string_builder << "ProxyHttpCaching " << proxy.server() << ":" << proxy.port();
case Proxy::Type::Mtproto: case Proxy::Type::Mtproto:
return string_builder << "ProxyMtproto " << proxy.server() << ":" << proxy.port() << "/" << proxy.secret(); return string_builder << "ProxyMtproto " << proxy.server() << ":" << proxy.port() << "/"
<< proxy.secret().get_encoded_secret();
case Proxy::Type::None: case Proxy::Type::None:
return string_builder << "ProxyEmpty"; return string_builder << "ProxyEmpty";
default: default:
@ -239,16 +240,6 @@ void ConnectionCreator::add_proxy(int32 old_proxy_id, string server, int32 port,
return promise.set_error(Status::Error(400, "Wrong port number")); return promise.set_error(Status::Error(400, "Wrong port number"));
} }
auto is_secret_supported = [](Slice secret) {
if (secret.size() == 32) {
return true;
}
if (secret.size() == 34) {
return begins_with(secret, "dd") || begins_with(secret, "ee");
}
return false;
};
Proxy new_proxy; Proxy new_proxy;
switch (proxy_type->get_id()) { switch (proxy_type->get_id()) {
case td_api::proxyTypeSocks5::ID: { case td_api::proxyTypeSocks5::ID: {
@ -267,13 +258,11 @@ void ConnectionCreator::add_proxy(int32 old_proxy_id, string server, int32 port,
} }
case td_api::proxyTypeMtproto::ID: { case td_api::proxyTypeMtproto::ID: {
auto type = td_api::move_object_as<td_api::proxyTypeMtproto>(proxy_type); auto type = td_api::move_object_as<td_api::proxyTypeMtproto>(proxy_type);
if (hex_decode(type->secret_).is_error()) { auto r_secret = mtproto::ProxySecret::from_link(type->secret_);
return promise.set_error(Status::Error(400, "Wrong secret")); if (r_secret.is_error()) {
return promise.set_error(r_secret.move_as_error());
} }
if (!is_secret_supported(type->secret_)) { new_proxy = Proxy::mtproto(server, port, r_secret.move_as_ok());
return promise.set_error(Status::Error(400, "Unsupported secret"));
}
new_proxy = Proxy::mtproto(server, port, type->secret_);
break; break;
} }
default: default:
@ -397,7 +386,7 @@ void ConnectionCreator::get_proxy_link(int32 proxy_id, Promise<string> promise)
} }
} else { } else {
url += "&secret="; url += "&secret=";
url += url_encode(proxy.secret()); url += proxy.secret().get_encoded_secret();
} }
promise.set_value(std::move(url)); promise.set_value(std::move(url));
} }
@ -502,7 +491,7 @@ void ConnectionCreator::ping_proxy_resolved(int32 proxy_id, IPAddress ip_address
} }
auto socket_fd = r_socket_fd.move_as_ok(); auto socket_fd = r_socket_fd.move_as_ok();
bool emulate_tls = extra.transport_type.emulate_tls(); auto secret = extra.transport_type.secret;
auto socket_fd_promise = auto socket_fd_promise =
PromiseCreator::lambda([promise = std::move(promise), actor_id = actor_id(this), PromiseCreator::lambda([promise = std::move(promise), actor_id = actor_id(this),
@ -514,7 +503,7 @@ void ConnectionCreator::ping_proxy_resolved(int32 proxy_id, IPAddress ip_address
std::move(transport_type), std::move(promise)); std::move(transport_type), std::move(promise));
}); });
CHECK(proxy.use_proxy()); CHECK(proxy.use_proxy());
if (proxy.use_socks5_proxy() || proxy.use_http_tcp_proxy() || emulate_tls) { if (proxy.use_socks5_proxy() || proxy.use_http_tcp_proxy() || secret.emulate_tls()) {
class Callback : public TransparentProxy::Callback { class Callback : public TransparentProxy::Callback {
public: public:
explicit Callback(Promise<SocketFd> promise) : promise_(std::move(promise)) { explicit Callback(Promise<SocketFd> promise) : promise_(std::move(promise)) {
@ -540,11 +529,11 @@ void ConnectionCreator::ping_proxy_resolved(int32 proxy_id, IPAddress ip_address
children_[token] = {false, create_actor<HttpProxy>("PingHttpProxy", std::move(socket_fd), extra.mtproto_ip, children_[token] = {false, create_actor<HttpProxy>("PingHttpProxy", std::move(socket_fd), extra.mtproto_ip,
proxy.proxy().user().str(), proxy.proxy().password().str(), proxy.proxy().user().str(), proxy.proxy().password().str(),
std::move(callback), create_reference(token))}; std::move(callback), create_reference(token))};
} else if (emulate_tls) { } else if (secret.emulate_tls()) {
children_[token] = { children_[token] = {
false, create_actor<TlsInit>("PingTlsInit", std::move(socket_fd), extra.mtproto_ip, "www.google.com", false, create_actor<TlsInit>("PingTlsInit", std::move(socket_fd), extra.mtproto_ip, secret.get_domain(),
hex_decode(proxy.proxy().secret().substr(2)).move_as_ok(), std::move(callback), secret.get_proxy_secret().str(), std::move(callback), create_reference(token),
create_reference(token), G()->get_dns_time_difference())}; G()->get_dns_time_difference())};
} else { } else {
UNREACHABLE(); UNREACHABLE();
} }
@ -694,7 +683,7 @@ td_api::object_ptr<td_api::proxy> ConnectionCreator::get_proxy_object(int32 prox
type = make_tl_object<td_api::proxyTypeHttp>(proxy.user().str(), proxy.password().str(), true); type = make_tl_object<td_api::proxyTypeHttp>(proxy.user().str(), proxy.password().str(), true);
break; break;
case Proxy::Type::Mtproto: case Proxy::Type::Mtproto:
type = make_tl_object<td_api::proxyTypeMtproto>(proxy.secret().str()); type = make_tl_object<td_api::proxyTypeMtproto>(proxy.secret().get_encoded_secret());
break; break;
default: default:
UNREACHABLE(); UNREACHABLE();
@ -790,8 +779,11 @@ void ConnectionCreator::request_raw_connection_by_ip(IPAddress ip_address,
if (r_socket_fd.is_error()) { if (r_socket_fd.is_error()) {
return promise.set_error(r_socket_fd.move_as_error()); return promise.set_error(r_socket_fd.move_as_error());
} }
// TODO TransportType is wrong
auto raw_connection = make_unique<mtproto::RawConnection>( auto raw_connection = make_unique<mtproto::RawConnection>(
r_socket_fd.move_as_ok(), mtproto::TransportType{mtproto::TransportType::ObfuscatedTcp, 0, ""}, nullptr); r_socket_fd.move_as_ok(),
mtproto::TransportType{mtproto::TransportType::ObfuscatedTcp, 0, mtproto::ProxySecret()}, nullptr);
raw_connection->extra_ = network_generation_; raw_connection->extra_ = network_generation_;
promise.set_value(std::move(raw_connection)); promise.set_value(std::move(raw_connection));
} }
@ -805,8 +797,7 @@ Result<mtproto::TransportType> ConnectionCreator::get_transport_type(const Proxy
int16 raw_dc_id = narrow_cast<int16>(info.option->is_media_only() ? -int_dc_id : int_dc_id); int16 raw_dc_id = narrow_cast<int16>(info.option->is_media_only() ? -int_dc_id : int_dc_id);
if (proxy.use_mtproto_proxy()) { if (proxy.use_mtproto_proxy()) {
TRY_RESULT(secret, hex_decode(proxy.proxy().secret())); return mtproto::TransportType{mtproto::TransportType::ObfuscatedTcp, raw_dc_id, proxy.proxy().secret()};
return mtproto::TransportType{mtproto::TransportType::ObfuscatedTcp, raw_dc_id, std::move(secret)};
} }
if (proxy.use_http_caching_proxy()) { if (proxy.use_http_caching_proxy()) {
CHECK(info.option != nullptr); CHECK(info.option != nullptr);
@ -815,14 +806,15 @@ Result<mtproto::TransportType> ConnectionCreator::get_transport_type(const Proxy
proxy_authorization = proxy_authorization =
"|basic " + td::base64_encode(PSLICE() << proxy.proxy().user() << ':' << proxy.proxy().password()); "|basic " + td::base64_encode(PSLICE() << proxy.proxy().user() << ':' << proxy.proxy().password());
} }
return mtproto::TransportType{mtproto::TransportType::Http, 0, return mtproto::TransportType{
PSTRING() << info.option->get_ip_address().get_ip_str() << proxy_authorization}; mtproto::TransportType::Http, 0,
mtproto::ProxySecret::from_raw(PSTRING() << info.option->get_ip_address().get_ip_str() << proxy_authorization)};
} }
if (info.use_http) { if (info.use_http) {
return mtproto::TransportType{mtproto::TransportType::Http, 0, ""}; return mtproto::TransportType{mtproto::TransportType::Http, 0, mtproto::ProxySecret()};
} else { } else {
return mtproto::TransportType{mtproto::TransportType::ObfuscatedTcp, raw_dc_id, info.option->get_secret().str()}; return mtproto::TransportType{mtproto::TransportType::ObfuscatedTcp, raw_dc_id, info.option->get_secret()};
} }
} }
@ -971,7 +963,7 @@ void ConnectionCreator::client_loop(ClientInfo &client) {
client.checking_connections++; client.checking_connections++;
} }
bool emulate_tls = extra.transport_type.emulate_tls(); mtproto::ProxySecret secret = extra.transport_type.secret;
auto promise = PromiseCreator::lambda( auto promise = PromiseCreator::lambda(
[actor_id = actor_id(this), check_mode, transport_type = extra.transport_type, hash = client.hash, [actor_id = actor_id(this), check_mode, transport_type = extra.transport_type, hash = client.hash,
@ -985,7 +977,7 @@ void ConnectionCreator::client_loop(ClientInfo &client) {
td::make_unique<detail::StatsCallback>(client.is_media ? media_net_stats_callback_ : common_net_stats_callback_, td::make_unique<detail::StatsCallback>(client.is_media ? media_net_stats_callback_ : common_net_stats_callback_,
actor_id(this), client.hash, extra.stat); actor_id(this), client.hash, extra.stat);
if (proxy.use_socks5_proxy() || proxy.use_http_tcp_proxy() || emulate_tls) { if (proxy.use_socks5_proxy() || proxy.use_http_tcp_proxy() || secret.emulate_tls()) {
VLOG(connections) << "In client_loop: create new transparent proxy connection " << extra.debug_str; VLOG(connections) << "In client_loop: create new transparent proxy connection " << extra.debug_str;
class Callback : public TransparentProxy::Callback { class Callback : public TransparentProxy::Callback {
public: public:
@ -1029,11 +1021,11 @@ void ConnectionCreator::client_loop(ClientInfo &client) {
children_[token] = {true, create_actor<HttpProxy>("HttpProxy", std::move(socket_fd), extra.mtproto_ip, children_[token] = {true, create_actor<HttpProxy>("HttpProxy", std::move(socket_fd), extra.mtproto_ip,
proxy.proxy().user().str(), proxy.proxy().password().str(), proxy.proxy().user().str(), proxy.proxy().password().str(),
std::move(callback), create_reference(token))}; std::move(callback), create_reference(token))};
} else if (emulate_tls) { } else if (secret.emulate_tls()) {
children_[token] = { children_[token] = {
true, create_actor<TlsInit>("TlsInit", std::move(socket_fd), extra.mtproto_ip, "www.google.com", true, create_actor<TlsInit>("TlsInit", std::move(socket_fd), extra.mtproto_ip, secret.get_domain(),
hex_decode(proxy.proxy().secret().substr(2)).move_as_ok(), std::move(callback), secret.get_proxy_secret().str(), std::move(callback), create_reference(token),
create_reference(token), G()->get_dns_time_difference())}; G()->get_dns_time_difference())};
} else { } else {
UNREACHABLE(); UNREACHABLE();
} }

View File

@ -16,6 +16,7 @@
#include "td/telegram/StateManager.h" #include "td/telegram/StateManager.h"
#include "td/mtproto/AuthData.h" #include "td/mtproto/AuthData.h"
#include "td/mtproto/ProxySecret.h"
#include "td/mtproto/TransportType.h" #include "td/mtproto/TransportType.h"
#include "td/actor/actor.h" #include "td/actor/actor.h"
@ -86,7 +87,7 @@ class Proxy {
return proxy; return proxy;
} }
static Proxy mtproto(string server, int32 port, string secret) { static Proxy mtproto(string server, int32 port, mtproto::ProxySecret secret) {
Proxy proxy; Proxy proxy;
proxy.type_ = Type::Mtproto; proxy.type_ = Type::Mtproto;
proxy.server_ = std::move(server); proxy.server_ = std::move(server);
@ -111,7 +112,7 @@ class Proxy {
return password_; return password_;
} }
CSlice secret() const { const mtproto::ProxySecret &secret() const {
return secret_; return secret_;
} }
@ -132,7 +133,7 @@ class Proxy {
int32 port_ = 0; int32 port_ = 0;
string user_; string user_;
string password_; string password_;
string secret_; mtproto::ProxySecret secret_;
}; };
inline bool operator==(const Proxy &lhs, const Proxy &rhs) { inline bool operator==(const Proxy &lhs, const Proxy &rhs) {

View File

@ -6,9 +6,10 @@
// //
#pragma once #pragma once
#include "td/telegram/telegram_api.h" #include "td/mtproto/ProxySecret.h"
#include "td/telegram/net/DcId.h" #include "td/telegram/net/DcId.h"
#include "td/telegram/telegram_api.h"
#include "td/utils/common.h" #include "td/utils/common.h"
#include "td/utils/format.h" #include "td/utils/format.h"
@ -27,7 +28,7 @@ class DcOption {
int32 flags_ = 0; int32 flags_ = 0;
DcId dc_id_; DcId dc_id_;
IPAddress ip_address_; IPAddress ip_address_;
string secret_; mtproto::ProxySecret secret_;
struct PrintFlags { struct PrintFlags {
int32 flags; int32 flags;
@ -69,10 +70,11 @@ class DcOption {
} }
if (!option.secret_.empty()) { if (!option.secret_.empty()) {
flags_ |= Flags::HasSecret; flags_ |= Flags::HasSecret;
if (option.secret_.size() != 16u && option.secret_.size() != 17u) { auto r_secret = mtproto::ProxySecret::from_binary(option.secret_.as_slice());
if (r_secret.is_error()) {
return; return;
} }
secret_ = option.secret_.as_slice().str(); secret_ = r_secret.move_as_ok();
} }
init_ip_address(ip, port); init_ip_address(ip, port);
} }
@ -86,11 +88,12 @@ class DcOption {
} }
case telegram_api::ipPortSecret::ID: { case telegram_api::ipPortSecret::ID: {
auto &ip_port = static_cast<const telegram_api::ipPortSecret &>(ip_port_ref); auto &ip_port = static_cast<const telegram_api::ipPortSecret &>(ip_port_ref);
if (ip_port.secret_.size() != 16u && ip_port.secret_.size() != 17u) { auto r_secret = mtproto::ProxySecret::from_binary(ip_port.secret_.as_slice());
if (r_secret.is_error()) {
return; return;
} }
flags_ |= Flags::HasSecret; flags_ |= Flags::HasSecret;
secret_ = ip_port.secret_.as_slice().str(); secret_ = r_secret.move_as_ok();
init_ip_address(IPAddress::ipv4_to_str(static_cast<uint32>(ip_port.ipv4_)), ip_port.port_); init_ip_address(IPAddress::ipv4_to_str(static_cast<uint32>(ip_port.ipv4_)), ip_port.port_);
break; break;
} }
@ -129,7 +132,7 @@ class DcOption {
return ip_address_.is_valid() && dc_id_.is_exact(); return ip_address_.is_valid() && dc_id_.is_exact();
} }
Slice get_secret() const { const mtproto::ProxySecret &get_secret() const {
return secret_; return secret_;
} }
@ -141,7 +144,7 @@ class DcOption {
storer.store_string(ip_address_.get_ip_str()); storer.store_string(ip_address_.get_ip_str());
storer.store_int(ip_address_.get_port()); storer.store_int(ip_address_.get_port());
if ((flags_ & Flags::HasSecret) != 0) { if ((flags_ & Flags::HasSecret) != 0) {
storer.store_string(secret_); td::store(secret_.get_raw_secret(), storer);
} }
} }
@ -163,7 +166,7 @@ class DcOption {
auto port = parser.fetch_int(); auto port = parser.fetch_int();
init_ip_address(ip, port); init_ip_address(ip, port);
if ((flags_ & Flags::HasSecret) != 0) { if ((flags_ & Flags::HasSecret) != 0) {
secret_ = parser.template fetch_string<std::string>(); secret_ = mtproto::ProxySecret::from_raw(parser.template fetch_string<Slice>());
} }
} }
@ -213,7 +216,7 @@ inline StringBuilder &operator<<(StringBuilder &sb, const DcOption::PrintFlags &
inline StringBuilder &operator<<(StringBuilder &sb, const DcOption &dc_option) { inline StringBuilder &operator<<(StringBuilder &sb, const DcOption &dc_option) {
return sb << tag("DcOption", format::concat(dc_option.dc_id_, tag("ip", dc_option.ip_address_.get_ip_str()), return sb << tag("DcOption", format::concat(dc_option.dc_id_, tag("ip", dc_option.ip_address_.get_ip_str()),
tag("port", dc_option.ip_address_.get_port()), tag("port", dc_option.ip_address_.get_port()),
tag("secret_len", dc_option.secret_.size()), tag("secret_len", dc_option.get_secret().get_raw_secret().size()),
tag("flags", DcOption::PrintFlags{dc_option.flags_}))); tag("flags", DcOption::PrintFlags{dc_option.flags_})));
} }

View File

@ -16,6 +16,7 @@
#include "td/mtproto/HandshakeActor.h" #include "td/mtproto/HandshakeActor.h"
#include "td/mtproto/Ping.h" #include "td/mtproto/Ping.h"
#include "td/mtproto/PingConnection.h" #include "td/mtproto/PingConnection.h"
#include "td/mtproto/ProxySecret.h"
#include "td/mtproto/RawConnection.h" #include "td/mtproto/RawConnection.h"
#include "td/mtproto/TlsInit.h" #include "td/mtproto/TlsInit.h"
#include "td/mtproto/TransportType.h" #include "td/mtproto/TransportType.h"
@ -177,8 +178,9 @@ class TestPingActor : public Actor {
void start_up() override { void start_up() override {
ping_connection_ = mtproto::PingConnection::create_req_pq( ping_connection_ = mtproto::PingConnection::create_req_pq(
make_unique<mtproto::RawConnection>(SocketFd::open(ip_address_).move_as_ok(), make_unique<mtproto::RawConnection>(
mtproto::TransportType{mtproto::TransportType::Tcp, 0, ""}, nullptr), SocketFd::open(ip_address_).move_as_ok(),
mtproto::TransportType{mtproto::TransportType::Tcp, 0, mtproto::ProxySecret()}, nullptr),
3); 3);
Scheduler::subscribe(ping_connection_->get_poll_info().extract_pollable_fd(this)); Scheduler::subscribe(ping_connection_->get_poll_info().extract_pollable_fd(this));
@ -287,9 +289,9 @@ class HandshakeTestActor : public Actor {
} }
void loop() override { void loop() override {
if (!wait_for_raw_connection_ && !raw_connection_) { if (!wait_for_raw_connection_ && !raw_connection_) {
raw_connection_ = raw_connection_ = make_unique<mtproto::RawConnection>(
make_unique<mtproto::RawConnection>(SocketFd::open(get_default_ip_address()).move_as_ok(), SocketFd::open(get_default_ip_address()).move_as_ok(),
mtproto::TransportType{mtproto::TransportType::Tcp, 0, ""}, nullptr); mtproto::TransportType{mtproto::TransportType::Tcp, 0, mtproto::ProxySecret()}, nullptr);
} }
if (!wait_for_handshake_ && !handshake_) { if (!wait_for_handshake_ && !handshake_) {
handshake_ = make_unique<mtproto::AuthKeyHandshake>(dc_id_, 0); handshake_ = make_unique<mtproto::AuthKeyHandshake>(dc_id_, 0);
@ -483,9 +485,9 @@ class FastPingTestActor : public Actor {
void start_up() override { void start_up() override {
// Run handshake to create key and salt // Run handshake to create key and salt
auto raw_connection = auto raw_connection = make_unique<mtproto::RawConnection>(
make_unique<mtproto::RawConnection>(SocketFd::open(get_default_ip_address()).move_as_ok(), SocketFd::open(get_default_ip_address()).move_as_ok(),
mtproto::TransportType{mtproto::TransportType::Tcp, 0, ""}, nullptr); mtproto::TransportType{mtproto::TransportType::Tcp, 0, mtproto::ProxySecret()}, nullptr);
auto handshake = make_unique<mtproto::AuthKeyHandshake>(get_default_dc_id(), 60 * 100 /*temp*/); auto handshake = make_unique<mtproto::AuthKeyHandshake>(get_default_dc_id(), 60 * 100 /*temp*/);
create_actor<mtproto::HandshakeActor>( create_actor<mtproto::HandshakeActor>(
"HandshakeActor", std::move(handshake), std::move(raw_connection), make_unique<HandshakeContext>(), 10.0, "HandshakeActor", std::move(handshake), std::move(raw_connection), make_unique<HandshakeContext>(), 10.0,