diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index b0f344282..ba1008a94 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -1739,14 +1739,14 @@ localizationTargetInfo language_packs:vector = LocalizationTar //@class DeviceToken @description Represents a data needed to subscribe for push notifications through registerDevice method. To use specific push notification service, you must specify the correct application platform and upload valid server authentication data at https://my.telegram.org -//@description A token for Google Cloud Messaging @token Device registration token; may be empty to de-register a device -deviceTokenGoogleCloudMessaging token:string = DeviceToken; +//@description A token for Google Cloud Messaging @token Device registration token; may be empty to de-register a device @encrypt True, if push notifications should be additionally encrypted +deviceTokenGoogleCloudMessaging token:string encrypt:Bool = DeviceToken; //@description A token for Apple Push Notification service @device_token Device token; may be empty to de-register a device @is_app_sandbox True, if App Sandbox is enabled deviceTokenApplePush device_token:string is_app_sandbox:Bool = DeviceToken; -//@description A token for Apple Push Notification service VoIP notifications @device_token Device token; may be empty to de-register a device @is_app_sandbox True, if App Sandbox is enabled -deviceTokenApplePushVoIP device_token:string is_app_sandbox:Bool = DeviceToken; +//@description A token for Apple Push Notification service VoIP notifications @device_token Device token; may be empty to de-register a device @is_app_sandbox True, if App Sandbox is enabled @encrypt True, if push notifications should be additionally encrypted +deviceTokenApplePushVoIP device_token:string is_app_sandbox:Bool encrypt:Bool = DeviceToken; //@description A token for Windows Push Notification Services @access_token The access token that will be used to send notifications; may be empty to de-register a device deviceTokenWindowsPush access_token:string = DeviceToken; diff --git a/td/generate/scheme/td_api.tlo b/td/generate/scheme/td_api.tlo index ee6a6396b..23c0fa866 100644 Binary files a/td/generate/scheme/td_api.tlo and b/td/generate/scheme/td_api.tlo differ diff --git a/td/telegram/DeviceTokenManager.cpp b/td/telegram/DeviceTokenManager.cpp index a9d23c828..a3861322f 100644 --- a/td/telegram/DeviceTokenManager.cpp +++ b/td/telegram/DeviceTokenManager.cpp @@ -19,6 +19,7 @@ #include "td/utils/format.h" #include "td/utils/JsonBuilder.h" #include "td/utils/logging.h" +#include "td/utils/Random.h" #include "td/utils/Status.h" #include "td/utils/tl_helpers.h" @@ -39,11 +40,15 @@ void DeviceTokenManager::TokenInfo::store(StorerT &storer) const { STORE_FLAG(is_unregister); STORE_FLAG(is_register); STORE_FLAG(is_app_sandbox); + STORE_FLAG(encrypt); END_STORE_FLAGS(); store(token, storer); if (has_other_user_ids) { store(other_user_ids, storer); } + if (encrypt) { + store(encryption_key, storer); + } } template @@ -59,6 +64,7 @@ void DeviceTokenManager::TokenInfo::parse(ParserT &parser) { PARSE_FLAG(is_unregister); PARSE_FLAG(is_register); PARSE_FLAG(is_app_sandbox); + PARSE_FLAG(encrypt); END_PARSE_FLAGS_GENERIC(); CHECK(is_sync + is_unregister + is_register == 1); if (is_sync) { @@ -72,6 +78,9 @@ void DeviceTokenManager::TokenInfo::parse(ParserT &parser) { if (has_other_user_ids) { parse(other_user_ids, parser); } + if (encrypt) { + parse(encryption_key, parser); + } } StringBuilder &operator<<(StringBuilder &string_builder, const DeviceTokenManager::TokenInfo &token_info) { @@ -95,6 +104,9 @@ StringBuilder &operator<<(StringBuilder &string_builder, const DeviceTokenManage if (token_info.is_app_sandbox) { string_builder << ", sandboxed"; } + if (token_info.encrypt) { + string_builder << ", encrypted"; + } return string_builder; } @@ -104,6 +116,7 @@ void DeviceTokenManager::register_device(tl_object_ptr devi TokenType token_type; string token; bool is_app_sandbox = false; + bool encrypt = false; switch (device_token_ptr->get_id()) { case td_api::deviceTokenApplePush::ID: { auto device_token = static_cast(device_token_ptr.get()); @@ -116,6 +129,7 @@ void DeviceTokenManager::register_device(tl_object_ptr devi auto device_token = static_cast(device_token_ptr.get()); token = std::move(device_token->token_); token_type = TokenType::GCM; + encrypt = device_token->encrypt_; break; } case td_api::deviceTokenMicrosoftPush::ID: { @@ -153,6 +167,7 @@ void DeviceTokenManager::register_device(tl_object_ptr devi token = std::move(device_token->device_token_); token_type = TokenType::APNS_VOIP; is_app_sandbox = device_token->is_app_sandbox_; + encrypt = device_token->encrypt_; break; } case td_api::deviceTokenWebPush::ID: { @@ -226,11 +241,32 @@ void DeviceTokenManager::register_device(tl_object_ptr devi } info.other_user_ids = std::move(other_user_ids); info.is_app_sandbox = is_app_sandbox; + if (encrypt != info.encrypt) { + if (encrypt) { + constexpr size_t ENCRYPTION_KEY_LENGTH = 256; + info.encryption_key.resize(ENCRYPTION_KEY_LENGTH); + Random::secure_bytes(info.encryption_key); + } else { + info.encryption_key.clear(); + } + info.encrypt = encrypt; + } info.promise.set_value(make_tl_object()); info.promise = std::move(promise); save_info(token_type); } +vector DeviceTokenManager::get_encryption_keys() const { + vector result; + for (int32 token_type = 1; token_type < TokenType::SIZE; token_type++) { + auto &info = tokens_[token_type]; + if (!info.token.empty() && info.encrypt && info.state != TokenInfo::State::Unregister) { + result.push_back(info.encryption_key); + } + } + return result; +} + string DeviceTokenManager::get_database_key(int32 token_type) { return PSTRING() << "device_token" << token_type; } @@ -302,7 +338,7 @@ void DeviceTokenManager::loop() { create_storer(telegram_api::account_unregisterDevice(token_type, info.token, std::move(other_user_ids)))); } else { net_query = G()->net_query_creator().create(create_storer(telegram_api::account_registerDevice( - token_type, info.token, info.is_app_sandbox, BufferSlice(), std::move(other_user_ids)))); + token_type, info.token, info.is_app_sandbox, BufferSlice(info.encryption_key), std::move(other_user_ids)))); } info.net_query_id = net_query->id(); G()->net_query_dispatcher().dispatch_with_callback(std::move(net_query), actor_shared(this, token_type)); @@ -329,7 +365,7 @@ void DeviceTokenManager::on_result(NetQueryPtr net_query) { info.promise.set_value(make_tl_object()); } if (info.state == TokenInfo::State::Unregister) { - info.token = ""; + info.token.clear(); } info.state = TokenInfo::State::Sync; } else { @@ -344,7 +380,7 @@ void DeviceTokenManager::on_result(NetQueryPtr net_query) { info.state = TokenInfo::State::Unregister; } else { info.state = TokenInfo::State::Sync; - info.token = ""; + info.token.clear(); } if (r_flag.is_error()) { LOG(ERROR) << r_flag.error(); diff --git a/td/telegram/DeviceTokenManager.h b/td/telegram/DeviceTokenManager.h index 4d204d31f..441b5a058 100644 --- a/td/telegram/DeviceTokenManager.h +++ b/td/telegram/DeviceTokenManager.h @@ -14,6 +14,7 @@ #include "td/telegram/td_api.h" #include "td/utils/common.h" +#include "td/utils/Slice.h" #include "td/utils/StringBuilder.h" #include @@ -27,6 +28,8 @@ class DeviceTokenManager : public NetQueryCallback { void register_device(tl_object_ptr device_token_ptr, vector other_user_ids, Promise> promise); + vector get_encryption_keys() const; + private: static constexpr size_t MAX_OTHER_USER_IDS = 100; @@ -53,6 +56,8 @@ class DeviceTokenManager : public NetQueryCallback { uint64 net_query_id = 0; vector other_user_ids; bool is_app_sandbox = false; + bool encrypt = false; + string encryption_key; Promise> promise; template diff --git a/td/telegram/NotificationManager.cpp b/td/telegram/NotificationManager.cpp index 54bfff4df..dcb8c2291 100644 --- a/td/telegram/NotificationManager.cpp +++ b/td/telegram/NotificationManager.cpp @@ -9,11 +9,13 @@ #include "td/telegram/AuthManager.h" #include "td/telegram/ConfigShared.h" #include "td/telegram/ContactsManager.h" +#include "td/telegram/DeviceTokenManager.h" #include "td/telegram/Global.h" #include "td/telegram/MessagesManager.h" #include "td/telegram/Td.h" #include "td/telegram/TdDb.h" +#include "td/utils/format.h" #include "td/utils/logging.h" #include "td/utils/misc.h" #include "td/utils/Slice.h" @@ -1869,7 +1871,19 @@ void NotificationManager::on_notification_default_delay_changed() { } void NotificationManager::process_push_notification(const string &payload, Promise &&promise) { - VLOG(notifications) << "Process push notification \"" << payload << '"'; + if (G()->close_flag()) { + return; + } + + auto encryption_keys = td_->device_token_manager_->get_actor_unsafe()->get_encryption_keys(); + for (auto &key : encryption_keys) { + VLOG(notifications) << "Have key \"" << format::escaped(key) << '"'; + } + if (encryption_keys.empty()) { + VLOG(notifications) << "Process push notification \"" << payload << '"'; + } else { + VLOG(notifications) << "Process encrypted push notification \"" << format::escaped(payload) << '"'; + } promise.set_value(Unit()); } diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index 56a31dec0..e29767fb7 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -1367,6 +1367,9 @@ class CliClient final : public Actor { } else if (op == "rdb") { send_request(make_tl_object(make_tl_object(args), as_user_ids(""))); + } else if (op == "rdg") { + send_request(make_tl_object( + make_tl_object(args, true), as_user_ids(""))); } else if (op == "rdt") { string token; string other_user_ids_str;