diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index a05d53195..bc6f4a017 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -9358,6 +9358,13 @@ removeAllFilesFromDownloads only_active:Bool only_completed:Bool delete_from_cac searchFileDownloads query:string only_active:Bool only_completed:Bool offset:string limit:int32 = FoundFileDownloads; +//@description Application verification has been completed. Can be called before authorization +//@verification_id Unique identifier for the verification process as received from updateApplicationVerificationRequired +//@token Play Integrity API token for the Android application, or secret from push notification for the iOS application; +//-pass an empty string to abort verification and receive error VERIFICATION_FAILED for the request +setApplicationVerificationToken verification_id:int53 token:string = Ok; + + //@description Returns information about a file with messages exported from another application @message_file_head Beginning of the message file; up to 100 first lines getMessageFileType message_file_head:string = MessageFileType; diff --git a/td/generate/scheme/telegram_api.tl b/td/generate/scheme/telegram_api.tl index d91b226ce..a62280503 100644 --- a/td/generate/scheme/telegram_api.tl +++ b/td/generate/scheme/telegram_api.tl @@ -28,6 +28,8 @@ test.useConfigSimple = help.ConfigSimple; test.parseInputAppEvent = InputAppEvent; invokeWithBusinessConnectionPrefix#dd289f8e connection_id:string = Error; +invokeWithGooglePlayIntegrityPrefix#1df92984 nonce:string token:string = Error; +invokeWithApnsSecretPrefix#0dae54f8 nonce:string secret:string = Error; ---types--- diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index 81d578972..9be0a03ca 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -2768,6 +2768,7 @@ bool Td::is_preauthentication_request(int32 id) { case td_api::getNetworkStatistics::ID: case td_api::addNetworkStatistics::ID: case td_api::resetNetworkStatistics::ID: + case td_api::setApplicationVerificationToken::ID: case td_api::getCountries::ID: case td_api::getCountryCode::ID: case td_api::getPhoneNumberInfo::ID: @@ -7499,6 +7500,14 @@ void Td::on_request(uint64 id, td_api::searchFileDownloads &request) { request.only_completed_, std::move(request.offset_), request.limit_, std::move(promise)); } +void Td::on_request(uint64 id, td_api::setApplicationVerificationToken &request) { + CHECK_IS_USER(); + CLEAN_INPUT_STRING(request.token_); + CREATE_OK_REQUEST_PROMISE(); + G()->net_query_dispatcher().set_verification_token(request.verification_id_, std::move(request.token_), + std::move(promise)); +} + void Td::on_request(uint64 id, td_api::getMessageFileType &request) { CHECK_IS_USER(); CLEAN_INPUT_STRING(request.message_file_head_); diff --git a/td/telegram/Td.h b/td/telegram/Td.h index c950fcaf3..f32909dd2 100644 --- a/td/telegram/Td.h +++ b/td/telegram/Td.h @@ -1325,6 +1325,8 @@ class Td final : public Actor { void on_request(uint64 id, td_api::searchFileDownloads &request); + void on_request(uint64 id, td_api::setApplicationVerificationToken &request); + void on_request(uint64 id, td_api::getMessageFileType &request); void on_request(uint64 id, const td_api::getMessageImportConfirmationText &request); diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index cedcd7a04..be05c7984 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -4923,6 +4923,11 @@ class CliClient final : public Actor { chat_id, message_thread_id_, get_input_message_reply_to(), default_message_send_options(), std::move(input_message_contents))); } + } else if (op == "savt") { + int64 verification_id; + string token; + get_args(args, verification_id, token); + send_request(td_api::make_object(verification_id, token)); } else if (op == "gmft") { auto r_message_file_head = read_file_str(args, 2 << 10); if (r_message_file_head.is_error()) { diff --git a/td/telegram/net/NetQueryDispatcher.cpp b/td/telegram/net/NetQueryDispatcher.cpp index 1b79f902d..cb88748c7 100644 --- a/td/telegram/net/NetQueryDispatcher.cpp +++ b/td/telegram/net/NetQueryDispatcher.cpp @@ -410,4 +410,12 @@ void NetQueryDispatcher::check_authorization_is_ok() { send_closure(dc_auth_manager_, &DcAuthManager::check_authorization_is_ok); } +void NetQueryDispatcher::set_verification_token(int64 verification_id, string &&token, Promise &&promise) { + if (verifier_.empty()) { + return promise.set_error(Status::Error(400, "Application verification not allowed")); + } + send_closure_later(verifier_, &NetQueryVerifier::set_verification_token, verification_id, std::move(token), + std::move(promise)); +} + } // namespace td diff --git a/td/telegram/net/NetQueryDispatcher.h b/td/telegram/net/NetQueryDispatcher.h index 881d53568..6023530c8 100644 --- a/td/telegram/net/NetQueryDispatcher.h +++ b/td/telegram/net/NetQueryDispatcher.h @@ -57,6 +57,8 @@ class NetQueryDispatcher { void set_main_dc_id(int32 new_main_dc_id); void check_authorization_is_ok(); + void set_verification_token(int64 verification_id, string &&token, Promise &&promise); + private: std::atomic stop_flag_{false}; bool need_destroy_auth_key_{false}; diff --git a/td/telegram/net/NetQueryVerifier.cpp b/td/telegram/net/NetQueryVerifier.cpp index 59c0fa9eb..bff7f4548 100644 --- a/td/telegram/net/NetQueryVerifier.cpp +++ b/td/telegram/net/NetQueryVerifier.cpp @@ -11,6 +11,9 @@ #include "td/telegram/Td.h" #include "td/utils/common.h" +#include "td/utils/Slice.h" +#include "td/utils/Storer.h" +#include "td/utils/utf8.h" namespace td { @@ -18,6 +21,12 @@ void NetQueryVerifier::verify(NetQueryPtr query, string nonce) { CHECK(query->is_ready()); CHECK(query->is_error()); + if (!check_utf8(nonce)) { + query->set_error(Status::Error(400, "Invalid verification nonce")); + G()->net_query_dispatcher().dispatch(std::move(query)); + return; + } + auto query_id = next_query_id_++; queries_.emplace(query_id, std::make_pair(std::move(query), nonce)); @@ -25,6 +34,34 @@ void NetQueryVerifier::verify(NetQueryPtr query, string nonce) { td_api::make_object(query_id, nonce)); } +void NetQueryVerifier::set_verification_token(int64 query_id, string &&token, Promise &&promise) { + auto it = queries_.find(query_id); + if (it == queries_.end()) { + return promise.set_error(Status::Error(400, "Verification not found")); + } + auto query = std::move(it->second.first); + auto nonce = std::move(it->second.second); + queries_.erase(it); + promise.set_value(Unit()); + + if (token.empty()) { + query->set_error(Status::Error(400, "VERIFICATION_FAILED")); + } else { +#if TD_ANDROID + telegram_api::invokeWithGooglePlayIntegrityPrefix prefix(nonce, token); +#else + telegram_api::invokeWithApnsSecretPrefix prefix(nonce, token); +#endif + auto storer = DefaultStorer(prefix); + string prefix_str(storer.size(), '\0'); + auto real_size = storer.store(MutableSlice(prefix_str).ubegin()); + CHECK(real_size == prefix_str.size()); + query->add_verification_prefix(prefix_str); + } + query->resend(); + G()->net_query_dispatcher().dispatch(std::move(query)); +} + void NetQueryVerifier::tear_down() { for (auto &it : queries_) { it.second.first->set_error(Global::request_aborted_error()); diff --git a/td/telegram/net/NetQueryVerifier.h b/td/telegram/net/NetQueryVerifier.h index f6f4be601..db3b70bd1 100644 --- a/td/telegram/net/NetQueryVerifier.h +++ b/td/telegram/net/NetQueryVerifier.h @@ -21,8 +21,11 @@ class NetQueryVerifier final : public Actor { public: explicit NetQueryVerifier(ActorShared<> parent) : parent_(std::move(parent)) { } + void verify(NetQueryPtr query, string nonce); + void set_verification_token(int64 query_id, string &&token, Promise &&promise); + private: void tear_down() final;