From 8135f4b427b7bdef4566da59504fcec260e818fa Mon Sep 17 00:00:00 2001 From: John Preston Date: Mon, 8 Jul 2019 18:02:45 +0200 Subject: [PATCH] Support base64 encoding of the secret. --- Telegram/Resources/langs/lang.strings | 2 + Telegram/SourceFiles/boxes/connection_box.cpp | 61 +++++- Telegram/SourceFiles/core/utils.cpp | 191 +++++++++++++----- Telegram/SourceFiles/core/utils.h | 25 ++- .../SourceFiles/mtproto/connection_tcp.cpp | 25 ++- Telegram/SourceFiles/mtproto/dc_options.cpp | 2 +- .../mtproto/mtp_abstract_socket.cpp | 8 +- .../SourceFiles/mtproto/mtp_abstract_socket.h | 2 +- .../SourceFiles/mtproto/mtp_tcp_socket.cpp | 4 +- Telegram/SourceFiles/mtproto/mtp_tcp_socket.h | 2 +- .../SourceFiles/mtproto/mtp_tls_socket.cpp | 51 +++-- Telegram/SourceFiles/mtproto/mtp_tls_socket.h | 7 +- Telegram/SourceFiles/storage/localstorage.cpp | 6 +- 13 files changed, 269 insertions(+), 117 deletions(-) diff --git a/Telegram/Resources/langs/lang.strings b/Telegram/Resources/langs/lang.strings index c346b4e68..c226c127a 100644 --- a/Telegram/Resources/langs/lang.strings +++ b/Telegram/Resources/langs/lang.strings @@ -145,6 +145,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL "lng_sure_ban_admin" = "This user is an admin. Are you sure you want to go ahead and restrict them?"; "lng_sure_enable_socks" = "Are you sure you want to enable this proxy?\n\nServer: {server}\nPort: {port}\n\nYou can change your proxy server later in the Settings (Connection Type)."; "lng_sure_enable" = "Enable"; +"lng_proxy_invalid" = "The proxy link is invalid."; +"lng_proxy_unsupported" = "Your Telegram Desktop version doesn't support this proxy type or the proxy link is invalid. Please update Telegram Desktop to the latest version."; "lng_edit_deleted" = "This message was deleted"; "lng_edit_too_long" = "Your message text is too long"; diff --git a/Telegram/SourceFiles/boxes/connection_box.cpp b/Telegram/SourceFiles/boxes/connection_box.cpp index fc6f1474e..3113fa9cd 100644 --- a/Telegram/SourceFiles/boxes/connection_box.cpp +++ b/Telegram/SourceFiles/boxes/connection_box.cpp @@ -31,6 +31,57 @@ namespace { constexpr auto kSaveSettingsDelayedTimeout = crl::time(1000); +class Base64UrlInput : public Ui::MaskedInputField { +public: + Base64UrlInput( + QWidget *parent, + const style::InputField &st, + rpl::producer placeholder, + const QString &val); + +protected: + void correctValue( + const QString &was, + int wasCursor, + QString &now, + int &nowCursor) override; + +}; + +Base64UrlInput::Base64UrlInput( + QWidget *parent, + const style::InputField &st, + rpl::producer placeholder, + const QString &val) +: MaskedInputField(parent, st, std::move(placeholder), val) { + if (!QRegularExpression("^[a-zA-Z0-9_\\-]+$").match(val).hasMatch()) { + setText(QString()); + } +} + +void Base64UrlInput::correctValue( + const QString &was, + int wasCursor, + QString &now, + int &nowCursor) { + QString newText; + newText.reserve(now.size()); + auto newPos = nowCursor; + for (auto i = 0, l = now.size(); i < l; ++i) { + const auto ch = now[i]; + if ((ch >= '0' && ch <= '9') + || (ch >= 'a' && ch <= 'z') + || (ch >= 'A' && ch <= 'Z') + || (ch == '-') + || (ch == '_')) { + newText.append(ch); + } else if (i < nowCursor) { + --newPos; + } + } + setCorrectedText(now, nowCursor, newText, newPos); +} + class ProxyRow : public Ui::RippleButton { public: using View = ProxiesBoxController::ItemView; @@ -150,7 +201,7 @@ private: QPointer _port; QPointer _user; QPointer _password; - QPointer _secret; + QPointer _secret; QPointer> _credentials; QPointer> _mtprotoCredentials; @@ -852,12 +903,11 @@ void ProxyBox::setupMtprotoCredentials(const ProxyData &data) { addLabel(mtproto, tr::lng_proxy_credentials(tr::now)); auto secretWrap = object_ptr(mtproto); - _secret = Ui::CreateChild( + _secret = Ui::CreateChild( secretWrap.data(), st::connectionUserInputField, tr::lng_connection_proxy_secret_ph(), (data.type == Type::Mtproto) ? data.password : QString()); - _secret->setMaxLength(ProxyData::MaxMtprotoPasswordLength()); _secret->move(0, 0); _secret->heightValue( ) | rpl::start_with_next([=, wrap = secretWrap.data()](int height) { @@ -975,6 +1025,11 @@ void ProxiesBoxController::ShowApplyConfirmation( strong->closeBox(); } }), LayerOption::KeepOther); + } else { + Ui::show(Box( + (proxy.status() == ProxyData::Status::Unsupported + ? tr::lng_proxy_unsupported(tr::now) + : tr::lng_proxy_invalid(tr::now)))); } } diff --git a/Telegram/SourceFiles/core/utils.cpp b/Telegram/SourceFiles/core/utils.cpp index f4f3c5e85..02a75e8f4 100644 --- a/Telegram/SourceFiles/core/utils.cpp +++ b/Telegram/SourceFiles/core/utils.cpp @@ -62,30 +62,127 @@ namespace { std::atomic GlobalAtomicRequestId = 0; - QReadWriteLock unixtimeLock; - volatile int32 unixtimeDelta = 0; - volatile bool unixtimeWasSet = false; - volatile uint64 _msgIdStart, _msgIdLocal = 0, _msgIdMsStart; +QReadWriteLock unixtimeLock; +volatile int32 unixtimeDelta = 0; +volatile bool unixtimeWasSet = false; +volatile uint64 _msgIdStart, _msgIdLocal = 0, _msgIdMsStart; - void _initMsgIdConstants() { +void _initMsgIdConstants() { #ifdef Q_OS_WIN - LARGE_INTEGER li; - QueryPerformanceCounter(&li); - _msgIdMsStart = li.QuadPart; + LARGE_INTEGER li; + QueryPerformanceCounter(&li); + _msgIdMsStart = li.QuadPart; #elif defined Q_OS_MAC - _msgIdMsStart = mach_absolute_time(); + _msgIdMsStart = mach_absolute_time(); #else - timespec ts; - clock_gettime(CLOCK_REALTIME, &ts); - _msgIdMsStart = 1000000000 * uint64(ts.tv_sec) + uint64(ts.tv_nsec); + timespec ts; + clock_gettime(CLOCK_REALTIME, &ts); + _msgIdMsStart = 1000000000 * uint64(ts.tv_sec) + uint64(ts.tv_nsec); #endif - uint32 msgIdRand; - memset_rand(&msgIdRand, sizeof(uint32)); - _msgIdStart = (((uint64)((uint32)unixtime()) << 32) | (uint64)msgIdRand); - } + uint32 msgIdRand; + memset_rand(&msgIdRand, sizeof(uint32)); + _msgIdStart = (((uint64)((uint32)unixtime()) << 32) | (uint64)msgIdRand); } +[[nodiscard]] bool IsHexMtprotoPassword(const QString &password) { + const auto bad = [](QChar ch) { + const auto code = ch.unicode(); + return (code < 'a' || code > 'f') + && (code < 'A' || code > 'F') + && (code < '0' || code > '9'); + }; + return (password.size() % 2 == 0) + && (std::find_if(password.begin(), password.end(), bad) + == password.end()); +} + +[[nodiscard]] ProxyData::Status HexMtprotoPasswordStatus( + const QString &password) { + const auto size = password.size() / 2; + const auto valid = (size == 16) + || (size == 17 && (password[0] == 'd') && (password[1] == 'd')) + || (size >= 21 && (password[0] == 'e') && (password[1] == 'e')); + if (valid) { + return ProxyData::Status::Valid; + } else if (size < 16) { + return ProxyData::Status::Invalid; + } + return ProxyData::Status::Unsupported; +} + +[[nodiscard]] bytes::vector SecretFromHexMtprotoPassword( + const QString &password) { + Expects(password.size() % 2 == 0); + + const auto size = password.size() / 2; + const auto fromHex = [](QChar ch) -> int { + const auto code = int(ch.unicode()); + if (code >= '0' && code <= '9') { + return (code - '0'); + } else if (code >= 'A' && code <= 'F') { + return 10 + (code - 'A'); + } else if (ch >= 'a' && ch <= 'f') { + return 10 + (code - 'a'); + } + Unexpected("Code in ProxyData fromHex."); + }; + auto result = bytes::vector(size); + for (auto i = 0; i != size; ++i) { + const auto high = fromHex(password[2 * i]); + const auto low = fromHex(password[2 * i + 1]); + if (high < 0 || low < 0) { + return {}; + } + result[i] = static_cast(high * 16 + low); + } + return result; +} + +[[nodiscard]] bool IsBase64UrlMtprotoPassword(const QString &password) { + const auto bad = [](QChar ch) { + const auto code = ch.unicode(); + return (code < 'a' || code > 'z') + && (code < 'A' || code > 'Z') + && (code < '0' || code > '9') + && (code != '_') + && (code != '-'); + }; + return (password.size() % 4 != 1) + && (std::find_if(password.begin(), password.end(), bad) + == password.end()); +} + +[[nodiscard]] ProxyData::Status Base64UrlMtprotoPasswordStatus( + const QString &password) { + const auto size = (password.size() * 3) / 4; + const auto valid = (size == 16) + || (size == 17 + && (password[0] == '3') + && ((password[1] >= 'Q') && (password[1] <= 'Z') + || (password[1] >= 'a') && (password[1] <= 'f'))) + || (size >= 21 + && (password[0] == '7') + && (password[1] >= 'g') + && (password[1] <= 'v')); + if (size < 16) { + return ProxyData::Status::Invalid; + } else if (valid) { + return ProxyData::Status::Valid; + } + return ProxyData::Status::Unsupported; +} + +[[nodiscard]] bytes::vector SecretFromBase64UrlMtprotoPassword( + const QString &password) { + const auto result = QByteArray::fromBase64( + password.toLatin1(), + QByteArray::Base64UrlEncoding); + return bytes::make_vector(bytes::make_span(result)); +} + +} // namespace + TimeId LocalUnixtime() { return (TimeId)time(nullptr); } @@ -233,16 +330,16 @@ namespace { } bool ProxyData::valid() const { - if (type == Type::None || host.isEmpty() || !port) { - return false; - } else if (type == Type::Mtproto && !ValidMtprotoPassword(password)) { - return false; - } - return true; + return status() == Status::Valid; } -int ProxyData::MaxMtprotoPasswordLength() { - return 34; +ProxyData::Status ProxyData::status() const { + if (type == Type::None || host.isEmpty() || !port) { + return Status::Invalid; + } else if (type == Type::Mtproto) { + return MtprotoPasswordStatus(password); + } + return Status::Valid; } bool ProxyData::supportsCalls() const { @@ -259,30 +356,13 @@ bool ProxyData::tryCustomResolve() const { bytes::vector ProxyData::secretFromMtprotoPassword() const { Expects(type == Type::Mtproto); - Expects(password.size() % 2 == 0); - const auto length = password.size() / 2; - const auto fromHex = [](QChar ch) -> int { - const auto code = int(ch.unicode()); - if (code >= '0' && code <= '9') { - return (code - '0'); - } else if (code >= 'A' && code <= 'F') { - return 10 + (code - 'A'); - } else if (ch >= 'a' && ch <= 'f') { - return 10 + (code - 'a'); - } - return -1; - }; - auto result = bytes::vector(length); - for (auto i = 0; i != length; ++i) { - const auto high = fromHex(password[2 * i]); - const auto low = fromHex(password[2 * i + 1]); - if (high < 0 || low < 0) { - return {}; - } - result[i] = static_cast(high * 16 + low); + if (IsHexMtprotoPassword(password)) { + return SecretFromHexMtprotoPassword(password); + } else if (IsBase64UrlMtprotoPassword(password)) { + return SecretFromBase64UrlMtprotoPassword(password); } - return result; + return {}; } ProxyData::operator bool() const { @@ -304,16 +384,17 @@ bool ProxyData::operator!=(const ProxyData &other) const { return !(*this == other); } -bool ProxyData::ValidMtprotoPassword(const QString &secret) { - using Expression = QRegularExpression; - if (secret.size() == 32) { - static const auto check = Expression("^[a-fA-F0-9]{32}$"); - return check.match(secret).hasMatch(); - } else if (secret.size() == 34) { - static const auto check = Expression("^(dd|ee)[a-fA-F0-9]{32}$"); - return check.match(secret).hasMatch(); +bool ProxyData::ValidMtprotoPassword(const QString &password) { + return MtprotoPasswordStatus(password) == Status::Valid; +} + +ProxyData::Status ProxyData::MtprotoPasswordStatus(const QString &password) { + if (IsHexMtprotoPassword(password)) { + return HexMtprotoPasswordStatus(password); + } else if (IsBase64UrlMtprotoPassword(password)) { + return Base64UrlMtprotoPasswordStatus(password); } - return false; + return Status::Invalid; } ProxyData ToDirectIpProxy(const ProxyData &proxy, int ipIndex) { diff --git a/Telegram/SourceFiles/core/utils.h b/Telegram/SourceFiles/core/utils.h index e74ab39ce..eb72300d1 100644 --- a/Telegram/SourceFiles/core/utils.h +++ b/Telegram/SourceFiles/core/utils.h @@ -270,6 +270,11 @@ struct ProxyData { Http, Mtproto, }; + enum class Status { + Valid, + Unsupported, + Invalid, + }; Type type = Type::None; QString host; @@ -279,16 +284,18 @@ struct ProxyData { std::vector resolvedIPs; crl::time resolvedExpireAt = 0; - bool valid() const; - bool supportsCalls() const; - bool tryCustomResolve() const; - bytes::vector secretFromMtprotoPassword() const; - explicit operator bool() const; - bool operator==(const ProxyData &other) const; - bool operator!=(const ProxyData &other) const; + [[nodiscard]] bool valid() const; + [[nodiscard]] Status status() const; + [[nodiscard]] bool supportsCalls() const; + [[nodiscard]] bool tryCustomResolve() const; + [[nodiscard]] bytes::vector secretFromMtprotoPassword() const; + [[nodiscard]] explicit operator bool() const; + [[nodiscard]] bool operator==(const ProxyData &other) const; + [[nodiscard]] bool operator!=(const ProxyData &other) const; - static bool ValidMtprotoPassword(const QString &secret); - static int MaxMtprotoPasswordLength(); + [[nodiscard]] static bool ValidMtprotoPassword(const QString &password); + [[nodiscard]] static Status MtprotoPasswordStatus( + const QString &password); }; diff --git a/Telegram/SourceFiles/mtproto/connection_tcp.cpp b/Telegram/SourceFiles/mtproto/connection_tcp.cpp index bd54c1c24..7d22ea1d3 100644 --- a/Telegram/SourceFiles/mtproto/connection_tcp.cpp +++ b/Telegram/SourceFiles/mtproto/connection_tcp.cpp @@ -30,7 +30,7 @@ constexpr auto kConnectionStartPrefixSize = 64; class TcpConnection::Protocol { public: - static std::unique_ptr Create(bytes::vector &&secret); + static std::unique_ptr Create(bytes::const_span secret); virtual uint32 id() const = 0; virtual bool supportsArbitraryLength() const = 0; @@ -223,15 +223,14 @@ bytes::const_span TcpConnection::Protocol::VersionD::readPacket( return bytes.subspan(sizeLength, size - sizeLength); } -auto TcpConnection::Protocol::Create(bytes::vector &&secret) +auto TcpConnection::Protocol::Create(bytes::const_span secret) -> std::unique_ptr { - if (secret.size() == 17 - && (static_cast(secret[0]) == 0xDD - || static_cast(secret[0]) == 0xEE)) { + if ((secret.size() >= 21 && secret[0] == bytes::type(0xEE)) + || (secret.size() == 17 && secret[0] == bytes::type(0xDD))) { return std::make_unique( - bytes::make_vector(bytes::make_span(secret).subspan(1))); + bytes::make_vector(secret.subspan(1, 16))); } else if (secret.size() == 16) { - return std::make_unique(std::move(secret)); + return std::make_unique(bytes::make_vector(secret)); } else if (secret.empty()) { return std::make_unique(); } @@ -522,10 +521,13 @@ void TcpConnection::connectToServer( Expects(_protocol == nullptr); Expects(_protocolDcId == 0); + const auto secret = (_proxy.type == ProxyData::Type::Mtproto) + ? _proxy.secretFromMtprotoPassword() + : protocolSecret; if (_proxy.type == ProxyData::Type::Mtproto) { _address = _proxy.host; _port = _proxy.port; - _protocol = Protocol::Create(_proxy.secretFromMtprotoPassword()); + _protocol = Protocol::Create(secret); DEBUG_LOG(("TCP Info: " "dc:%1 - Connecting to proxy '%2'" @@ -534,14 +536,17 @@ void TcpConnection::connectToServer( } else { _address = address; _port = port; - _protocol = Protocol::Create(base::duplicate(protocolSecret)); + _protocol = Protocol::Create(secret); DEBUG_LOG(("TCP Info: " "dc:%1 - Connecting to '%2'" ).arg(protocolDcId ).arg(_address + ':' + QString::number(_port))); } - _socket = AbstractSocket::Create(thread(), protocolSecret, _proxy); + _socket = AbstractSocket::Create( + thread(), + secret, + ToNetworkProxy(_proxy)); _protocolDcId = protocolDcId; _socket->connected( diff --git a/Telegram/SourceFiles/mtproto/dc_options.cpp b/Telegram/SourceFiles/mtproto/dc_options.cpp index ae6f34b58..f4959f414 100644 --- a/Telegram/SourceFiles/mtproto/dc_options.cpp +++ b/Telegram/SourceFiles/mtproto/dc_options.cpp @@ -257,7 +257,7 @@ bool DcOptions::ApplyOneOption( return false; } } - i->second.push_back(Endpoint(dcId, flags, ip, port, secret)); + i->second.emplace_back(dcId, flags, ip, port, secret); } else { data.emplace(dcId, std::vector( 1, diff --git a/Telegram/SourceFiles/mtproto/mtp_abstract_socket.cpp b/Telegram/SourceFiles/mtproto/mtp_abstract_socket.cpp index e83f8c289..1de6e6654 100644 --- a/Telegram/SourceFiles/mtproto/mtp_abstract_socket.cpp +++ b/Telegram/SourceFiles/mtproto/mtp_abstract_socket.cpp @@ -16,12 +16,8 @@ namespace internal { std::unique_ptr AbstractSocket::Create( not_null thread, const bytes::vector &secret, - const ProxyData &proxy) { - const auto proxySecret = (proxy.type == ProxyData::Type::Mtproto) - ? proxy.secretFromMtprotoPassword() - : bytes::vector(); - const auto &usingSecret = proxySecret.empty() ? secret : proxySecret; - if (!usingSecret.empty() && usingSecret[0] == bytes::type(0xEE)) { + const QNetworkProxy &proxy) { + if (secret.size() >= 21 && secret[0] == bytes::type(0xEE)) { return std::make_unique(thread, secret, proxy); } else { return std::make_unique(thread, proxy); diff --git a/Telegram/SourceFiles/mtproto/mtp_abstract_socket.h b/Telegram/SourceFiles/mtproto/mtp_abstract_socket.h index 26fade37d..f86fe3939 100644 --- a/Telegram/SourceFiles/mtproto/mtp_abstract_socket.h +++ b/Telegram/SourceFiles/mtproto/mtp_abstract_socket.h @@ -17,7 +17,7 @@ public: static std::unique_ptr Create( not_null thread, const bytes::vector &secret, - const ProxyData &proxy); + const QNetworkProxy &proxy); explicit AbstractSocket(not_null thread) { moveToThread(thread); diff --git a/Telegram/SourceFiles/mtproto/mtp_tcp_socket.cpp b/Telegram/SourceFiles/mtproto/mtp_tcp_socket.cpp index 49429848d..f5a5f28fe 100644 --- a/Telegram/SourceFiles/mtproto/mtp_tcp_socket.cpp +++ b/Telegram/SourceFiles/mtproto/mtp_tcp_socket.cpp @@ -10,10 +10,10 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL namespace MTP { namespace internal { -TcpSocket::TcpSocket(not_null thread, const ProxyData &proxy) +TcpSocket::TcpSocket(not_null thread, const QNetworkProxy &proxy) : AbstractSocket(thread) { _socket.moveToThread(thread); - _socket.setProxy(ToNetworkProxy(proxy)); + _socket.setProxy(proxy); const auto wrap = [&](auto handler) { return [=](auto &&...args) { InvokeQueued(this, [=] { handler(args...); }); diff --git a/Telegram/SourceFiles/mtproto/mtp_tcp_socket.h b/Telegram/SourceFiles/mtproto/mtp_tcp_socket.h index 3c845e09a..61ad897d6 100644 --- a/Telegram/SourceFiles/mtproto/mtp_tcp_socket.h +++ b/Telegram/SourceFiles/mtproto/mtp_tcp_socket.h @@ -14,7 +14,7 @@ namespace internal { class TcpSocket final : public AbstractSocket { public: - TcpSocket(not_null thread, const ProxyData &proxy); + TcpSocket(not_null thread, const QNetworkProxy &proxy); void connectToHost(const QString &address, int port) override; bool isConnected() override; diff --git a/Telegram/SourceFiles/mtproto/mtp_tls_socket.cpp b/Telegram/SourceFiles/mtproto/mtp_tls_socket.cpp index c363cedd0..b0da6885a 100644 --- a/Telegram/SourceFiles/mtproto/mtp_tls_socket.cpp +++ b/Telegram/SourceFiles/mtproto/mtp_tls_socket.cpp @@ -131,8 +131,8 @@ class ClientHelloGenerator { public: ClientHelloGenerator( const MTPTlsClientHello &rules, - const QByteArray &domain, - const bytes::vector &key); + bytes::const_span domain, + bytes::const_span key); [[nodiscard]] ClientHello result(); private: @@ -149,8 +149,8 @@ private: void writeDigest(); void writeTimestamp(); - const QByteArray &_domain; - const bytes::vector &_key; + bytes::const_span _domain; + bytes::const_span _key; bytes::vector _greases; std::vector _scopeStack; QByteArray _result; @@ -162,8 +162,8 @@ private: ClientHelloGenerator::ClientHelloGenerator( const MTPTlsClientHello &rules, - const QByteArray &domain, - const bytes::vector &key) + bytes::const_span domain, + bytes::const_span key) : _domain(domain) , _key(key) , _greases(PrepareGreases()) { @@ -256,7 +256,7 @@ void ClientHelloGenerator::writeBlock(const MTPDtlsBlockDomain &data) { if (storage.empty()) { return; } - bytes::copy(storage, bytes::make_span(_domain)); + bytes::copy(storage, _domain); } void ClientHelloGenerator::writeBlock(const MTPDtlsBlockScope &data) { @@ -309,22 +309,11 @@ void ClientHelloGenerator::writeTimestamp() { [[nodiscard]] ClientHello PrepareClientHello( const MTPTlsClientHello &rules, - const QByteArray &domain, - const bytes::vector &key) { + bytes::const_span domain, + bytes::const_span key) { return ClientHelloGenerator(rules, domain, key).result(); } -[[nodiscard]] bytes::vector ExtractKey( - const bytes::vector &secret, - const ProxyData &proxy) { - const auto proxySecret = proxy.secretFromMtprotoPassword(); - const auto &useSecret = proxySecret.empty() ? secret : proxySecret; - if (useSecret.size() != 17 || useSecret[0] != bytes::type(0xEE)) { - return {}; - } - return bytes::make_vector(bytes::make_span(useSecret).subspan(1)); -} - [[nodiscard]] bool CheckPart(bytes::const_span data, QLatin1String check) { if (data.size() < check.size()) { return false; @@ -345,11 +334,13 @@ void ClientHelloGenerator::writeTimestamp() { TlsSocket::TlsSocket( not_null thread, const bytes::vector &secret, - const ProxyData &proxy) + const QNetworkProxy &proxy) : AbstractSocket(thread) -, _key(ExtractKey(secret, proxy)) { +, _secret(secret) { + Expects(_secret.size() >= 21 && _secret[0] == bytes::type(0xEE)); + _socket.moveToThread(thread); - _socket.setProxy(ToNetworkProxy(proxy)); + _socket.setProxy(proxy); const auto wrap = [&](auto handler) { return [=](auto &&...args) { InvokeQueued(this, [=] { handler(args...); }); @@ -377,6 +368,14 @@ TlsSocket::TlsSocket( wrap([=](Error e) { handleError(e); })); } +bytes::const_span TlsSocket::domainFromSecret() const { + return bytes::make_span(_secret).subspan(17); +} + +bytes::const_span TlsSocket::keyFromSecret() const { + return bytes::make_span(_secret).subspan(1, 16); +} + void TlsSocket::plainConnected() { if (_state != State::Connecting) { return; @@ -385,8 +384,8 @@ void TlsSocket::plainConnected() { static const auto kClientHelloRules = PrepareClientHelloRules(); const auto hello = PrepareClientHello( kClientHelloRules, - "www.google.com", - _key); + domainFromSecret(), + keyFromSecret()); if (hello.data.isEmpty()) { LOG(("TLS Error: Could not generate Client Hello!")); _state = State::Error; @@ -492,7 +491,7 @@ void TlsSocket::checkHelloDigest() { kHelloDigestLength); const auto digestCopy = bytes::make_vector(digest); bytes::set_with_const(digest, bytes::type(0)); - const auto check = openssl::HmacSha256(_key, fulldata); + const auto check = openssl::HmacSha256(keyFromSecret(), fulldata); if (bytes::compare(digestCopy, check) != 0) { LOG(("TLS Error: Bad Server Hello digest.")); handleError(); diff --git a/Telegram/SourceFiles/mtproto/mtp_tls_socket.h b/Telegram/SourceFiles/mtproto/mtp_tls_socket.h index ffa82d419..cc6da1976 100644 --- a/Telegram/SourceFiles/mtproto/mtp_tls_socket.h +++ b/Telegram/SourceFiles/mtproto/mtp_tls_socket.h @@ -17,7 +17,7 @@ public: TlsSocket( not_null thread, const bytes::vector &secret, - const ProxyData &proxy); + const QNetworkProxy &proxy); void connectToHost(const QString &address, int port) override; bool isConnected() override; @@ -36,6 +36,9 @@ private: Error, }; + [[nodiscard]] bytes::const_span domainFromSecret() const; + [[nodiscard]] bytes::const_span keyFromSecret() const; + void plainConnected(); void plainDisconnected(); void plainReadyRead(); @@ -49,8 +52,8 @@ private: [[nodiscard]] bool checkNextPacket(); void shiftIncomingBy(int amount); + const bytes::vector _secret; QTcpSocket _socket; - bytes::vector _key; State _state = State::NotConnected; QByteArray _incoming; int _incomingGoodDataOffset = 0; diff --git a/Telegram/SourceFiles/storage/localstorage.cpp b/Telegram/SourceFiles/storage/localstorage.cpp index 99903a4ea..69d7fda34 100644 --- a/Telegram/SourceFiles/storage/localstorage.cpp +++ b/Telegram/SourceFiles/storage/localstorage.cpp @@ -1332,9 +1332,13 @@ bool _readSetting(quint32 blockId, QDataStream &stream, int version, ReadSetting const auto unchecked = static_cast(settings); switch (unchecked) { + case ProxyData::Settings::Enabled: + Global::SetProxySettings(Global::SelectedProxy() + ? ProxyData::Settings::Enabled + : ProxyData::Settings::System); + break; case ProxyData::Settings::Disabled: case ProxyData::Settings::System: - case ProxyData::Settings::Enabled: Global::SetProxySettings(unchecked); break; default: