Skip to content

Commit

Permalink
Add strongly typed ProxySecret class.
Browse files Browse the repository at this point in the history
GitOrigin-RevId: dbde277c6cce57fd6ff51b2e310dab95e60b38c1
  • Loading branch information
levlam committed Jul 9, 2019
1 parent 0c160b0 commit 7958916
Show file tree
Hide file tree
Showing 13 changed files with 194 additions and 89 deletions.
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,7 @@ set(TDLIB_SOURCE
td/mtproto/IStreamTransport.cpp
td/mtproto/Ping.cpp
td/mtproto/PingConnection.cpp
td/mtproto/ProxySecret.cpp
td/mtproto/RawConnection.cpp
td/mtproto/SessionConnection.cpp
td/mtproto/TcpTransport.cpp
Expand Down Expand Up @@ -476,6 +477,7 @@ set(TDLIB_SOURCE
td/mtproto/PacketStorer.h
td/mtproto/Ping.h
td/mtproto/PingConnection.h
td/mtproto/ProxySecret.h
td/mtproto/Query.h
td/mtproto/RawConnection.h
td/mtproto/SessionConnection.h
Expand Down
1 change: 1 addition & 0 deletions td/mtproto/AuthKey.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ class AuthKey {
}

enum : int32 { AUTH_FLAG = 1, WAS_AUTH_FLAG = 2 };

template <class StorerT>
void store(StorerT &storer) const {
storer.store_binary(auth_key_id_);
Expand Down
3 changes: 2 additions & 1 deletion td/mtproto/HttpTransport.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#pragma once

#include "td/mtproto/IStreamTransport.h"
#include "td/mtproto/ProxySecret.h"
#include "td/mtproto/TransportType.h"

#include "td/net/HttpQuery.h"
Expand Down Expand Up @@ -40,7 +41,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, secret_};
return {TransportType::Http, 0, ProxySecret::from_raw(secret_)};
}
bool use_random_padding() const override;

Expand Down
2 changes: 1 addition & 1 deletion td/mtproto/IStreamTransport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ unique_ptr<IStreamTransport> create_transport(TransportType type) {
case TransportType::Tcp:
return td::make_unique<tcp::OldTransport>();
case TransportType::Http:
return td::make_unique<http::Transport>(type.secret);
return td::make_unique<http::Transport>(type.secret.get_raw_secret().str());
}
UNREACHABLE();
}
Expand Down
46 changes: 46 additions & 0 deletions td/mtproto/ProxySecret.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
//
// Copyright Aliaksei Levin ([email protected]), Arseny Smirnov ([email protected]) 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 changes: 65 additions & 0 deletions td/mtproto/ProxySecret.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
//
// Copyright Aliaksei Levin ([email protected]), Arseny Smirnov ([email protected]) 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
15 changes: 6 additions & 9 deletions td/mtproto/TcpTransport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -170,22 +170,19 @@ void ObfuscatedTransport::init(ChainBufferReader *input, ChainBufferWriter *outp
string rheader = header;
std::reverse(rheader.begin(), rheader.end());
UInt256 key = as<UInt256>(rheader.data() + 8);
Slice secret_view = secret_;
if (secret_view.size() == 17) {
secret_view.remove_prefix(1);
}
Slice proxy_secret = secret_.get_proxy_secret();
auto fix_key = [&](UInt256 &key) {
if (secret_view.size() == 16) {
if (!proxy_secret.empty()) {
Sha256State state;
sha256_init(&state);
sha256_update(as_slice(key), &state);
sha256_update(secret_view, &state);
sha256_update(proxy_secret, &state);
sha256_final(&state, as_slice(key));
}
};
fix_key(key);
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_ >> aes_ctr_byte_flow_;
} else {
Expand All @@ -202,7 +199,7 @@ void ObfuscatedTransport::init(ChainBufferReader *input, ChainBufferWriter *outp
}

Result<size_t> ObfuscatedTransport::read_next(BufferSlice *message, uint32 *quick_ack) {
if (emulate_tls_) {
if (secret_.emulate_tls()) {
tls_reader_byte_flow_.wakeup();
} else {
aes_ctr_byte_flow_.wakeup();
Expand All @@ -213,7 +210,7 @@ Result<size_t> ObfuscatedTransport::read_next(BufferSlice *message, uint32 *quic
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 (emulate_tls_) {
if (secret_.emulate_tls()) {
do_write_tls(std::move(message));
} else {
do_write_main(std::move(message));
Expand Down
19 changes: 8 additions & 11 deletions td/mtproto/TcpTransport.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#pragma once

#include "td/mtproto/IStreamTransport.h"
#include "td/mtproto/ProxySecret.h"
#include "td/mtproto/TlsReaderByteFlow.h"
#include "td/mtproto/TransportType.h"

Expand Down Expand Up @@ -112,7 +113,7 @@ class OldTransport : public IStreamTransport {
}

TransportType get_type() const override {
return TransportType{TransportType::Tcp, 0, ""};
return TransportType{TransportType::Tcp, 0, ProxySecret()};
}

bool use_random_padding() const override {
Expand All @@ -127,10 +128,8 @@ class OldTransport : public IStreamTransport {

class ObfuscatedTransport : public IStreamTransport {
public:
ObfuscatedTransport(int16 dc_id, std::string secret)
: dc_id_(dc_id), secret_(std::move(secret)), impl_(secret_.size() >= 17) {
emulate_tls_ = secret_.size() >= 17 && secret_[0] == '\xee';
use_random_padding_ = secret_.size() >= 17;
ObfuscatedTransport(int16 dc_id, const ProxySecret &secret)
: dc_id_(dc_id), secret_(secret), impl_(secret_.use_random_padding()) {
}

Result<size_t> read_next(BufferSlice *message, uint32 *quick_ack) override TD_WARN_UNUSED_RESULT;
Expand All @@ -153,7 +152,7 @@ class ObfuscatedTransport : public IStreamTransport {

size_t max_prepend_size() const override {
size_t res = 4;
if (emulate_tls_) {
if (secret_.emulate_tls()) {
res += 5;
if (is_first_tls_packet_) {
res += 6;
Expand All @@ -174,21 +173,19 @@ class ObfuscatedTransport : public IStreamTransport {
return TransportType{TransportType::ObfuscatedTcp, dc_id_, secret_};
}
bool use_random_padding() const override {
return use_random_padding_;
return secret_.use_random_padding();
}

private:
int16 dc_id_;
std::string secret_;
bool emulate_tls_{false};
bool use_random_padding_{false};
bool is_first_tls_packet_{true};
ProxySecret secret_;
std::string header_;
TransportImpl impl_;
TlsReaderByteFlow tls_reader_byte_flow_;
AesCtrByteFlow aes_ctr_byte_flow_;
ByteFlowSink byte_flow_sink_;
ChainBufferReader *input_;
ChainBufferReader *input_ = nullptr;

static constexpr int32 MAX_TLS_PACKET_LENGTH = 2878;

Expand Down
10 changes: 4 additions & 6 deletions td/mtproto/TransportType.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
//
#pragma once

#include "td/mtproto/ProxySecret.h"

#include "td/utils/common.h"

namespace td {
Expand All @@ -14,14 +16,10 @@ namespace mtproto {
struct TransportType {
enum Type { Tcp, ObfuscatedTcp, Http } type = Tcp;
int16 dc_id{0};
string secret;
ProxySecret secret;

TransportType() = default;
TransportType(Type type, int16 dc_id, string secret) : type(type), dc_id(dc_id), secret(std::move(secret)) {
}

bool emulate_tls() const {
return secret.size() >= 17 && secret[0] == '\xee';
TransportType(Type type, int16 dc_id, ProxySecret secret) : type(type), dc_id(dc_id), secret(std::move(secret)) {
}
};

Expand Down
Loading

0 comments on commit 7958916

Please sign in to comment.