From 09600304b9df4f073b758cd0ac75bd18ca5209d8 Mon Sep 17 00:00:00 2001 From: Arseny Smirnov Date: Thu, 5 Apr 2018 14:18:47 +0300 Subject: [PATCH] SecureManager GitOrigin-RevId: 6728500e0f00dd7b739e862e715a43a4c7eae8e2 --- CMakeLists.txt | 2 + td/telegram/SecureManager.cpp | 244 ++++++++++++++++++++++++++++++++++ td/telegram/SecureManager.h | 99 ++++++++++++++ td/telegram/Td.cpp | 241 ++------------------------------- td/telegram/Td.h | 2 + 5 files changed, 355 insertions(+), 233 deletions(-) create mode 100644 td/telegram/SecureManager.cpp create mode 100644 td/telegram/SecureManager.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 41aef850e..3ffafaef8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -400,6 +400,7 @@ set(TDLIB_SOURCE td/telegram/SecretChatActor.cpp td/telegram/SecretChatDb.cpp td/telegram/SecretChatsManager.cpp + td/telegram/SecureManager.cpp td/telegram/SecureStorage.cpp td/telegram/SecureValue.cpp td/telegram/SequenceDispatcher.cpp @@ -521,6 +522,7 @@ set(TDLIB_SOURCE td/telegram/SecretChatDb.h td/telegram/SecretChatsManager.h td/telegram/SecretInputMedia.h + td/telegram/SecureManager.h td/telegram/SecureStorage.h td/telegram/SecureValue.h td/telegram/SequenceDispatcher.h diff --git a/td/telegram/SecureManager.cpp b/td/telegram/SecureManager.cpp new file mode 100644 index 000000000..e9e5d1155 --- /dev/null +++ b/td/telegram/SecureManager.cpp @@ -0,0 +1,244 @@ +// +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2018 +// +// 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/telegram/SecureManager.h" + +#include "td/telegram/Global.h" +#include "td/telegram/PasswordManager.h" +#include "td/telegram/net/NetQueryDispatcher.h" + +namespace td { +GetSecureValue::GetSecureValue(ActorShared<> parent, std::string password, SecureValueType type, + Promise promise) + : parent_(std::move(parent)), password_(std::move(password)), type_(type), promise_(std::move(promise)) { +} + +void GetSecureValue::on_error(Status status) { + promise_.set_error(std::move(status)); + stop(); +} + +void GetSecureValue::on_secret(Result r_secret, bool dummy) { + LOG_IF(ERROR, r_secret.is_error()) << r_secret.error(); + LOG_IF(ERROR, r_secret.is_ok()) << r_secret.ok().get_hash(); + if (r_secret.is_error()) { + return on_error(r_secret.move_as_error()); + } + secret_ = r_secret.move_as_ok(); + loop(); +} + +void GetSecureValue::loop() { + if (!encrypted_secure_value_ || !secret_) { + return; + } + auto *file_manager = G()->file_manager().get_actor_unsafe(); + auto r_secure_value = decrypt_encrypted_secure_value(file_manager, *secret_, *encrypted_secure_value_); + if (r_secure_value.is_error()) { + return on_error(r_secure_value.move_as_error()); + } + promise_.set_result(get_passport_data_object(file_manager, r_secure_value.move_as_ok())); + stop(); +} +void GetSecureValue::start_up() { + std::vector> vec; + vec.push_back(get_secure_value_type_telegram_object(type_)); + + auto query = G()->net_query_creator().create(create_storer(telegram_api::account_getSecureValue(std::move(vec)))); + + G()->net_query_dispatcher().dispatch_with_callback(std::move(query), actor_shared(this)); + + send_closure(G()->password_manager(), &PasswordManager::get_secure_secret, password_, optional(), + PromiseCreator::lambda([actor_id = actor_id(this)](Result r_secret) { + send_closure(actor_id, &GetSecureValue::on_secret, std::move(r_secret), true); + })); +} + +void GetSecureValue::on_result(NetQueryPtr query) { + auto r_result = fetch_result(std::move(query)); + if (r_result.is_error()) { + return on_error(r_result.move_as_error()); + } + auto result = r_result.move_as_ok(); + if (result.size() != 1) { + return on_error(Status::Error(PSLICE() << "Expected vector of size 1 got " << result.size())); + } + LOG(ERROR) << to_string(result[0]); + encrypted_secure_value_ = get_encrypted_secure_value(G()->file_manager().get_actor_unsafe(), std::move(result[0])); + loop(); +} + +SetSecureValue::SetSecureValue(ActorShared<> parent, string password, SecureValue secure_value, + Promise promise) + : parent_(std::move(parent)) + , password_(std::move(password)) + , secure_value_(std::move(secure_value)) + , promise_(std::move(promise)) { +} + +SetSecureValue::UploadCallback::UploadCallback(ActorId actor_id) : actor_id_(actor_id) { +} + +void SetSecureValue::UploadCallback::on_upload_ok(FileId file_id, tl_object_ptr input_file) { + UNREACHABLE(); +} +void SetSecureValue::UploadCallback::on_upload_encrypted_ok( + FileId file_id, tl_object_ptr input_file) { + UNREACHABLE(); +} +void SetSecureValue::UploadCallback::on_upload_secure_ok(FileId file_id, + tl_object_ptr input_file) { + send_closure(actor_id_, &SetSecureValue::on_upload_ok, file_id, std::move(input_file)); +} +void SetSecureValue::UploadCallback::on_upload_error(FileId file_id, Status error) { + send_closure(actor_id_, &SetSecureValue::on_upload_error, file_id, std::move(error)); +} + +void SetSecureValue::on_upload_ok(FileId file_id, tl_object_ptr input_file) { + for (auto &info : to_upload_) { + if (info.file_id != file_id) { + continue; + } + CHECK(!info.input_file); + info.input_file = std::move(input_file); + CHECK(files_left_to_upload_ != 0); + files_left_to_upload_--; + return loop(); + } + UNREACHABLE(); +} +void SetSecureValue::on_upload_error(FileId file_id, Status error) { + return on_error(std::move(error)); +} + +void SetSecureValue::on_error(Status status) { + promise_.set_error(std::move(status)); + stop(); +} + +void SetSecureValue::on_secret(Result r_secret, bool x) { + LOG_IF(ERROR, r_secret.is_error()) << r_secret.error(); + LOG_IF(ERROR, r_secret.is_ok()) << r_secret.ok().get_hash(); + if (r_secret.is_error()) { + return on_error(r_secret.move_as_error()); + } + secret_ = r_secret.move_as_ok(); + loop(); +} + +void SetSecureValue::start_up() { + send_closure(G()->password_manager(), &PasswordManager::get_secure_secret, password_, optional(), + PromiseCreator::lambda([actor_id = actor_id(this)](Result r_secret) { + send_closure(actor_id, &SetSecureValue::on_secret, std::move(r_secret), true); + })); + auto *file_manager = G()->file_manager().get_actor_unsafe(); + + // Remove duplicated files + for (auto it = secure_value_.files.begin(); it != secure_value_.files.end();) { + bool is_duplicate = false; + for (auto pit = secure_value_.files.begin(); pit != it; pit++) { + if (file_manager->get_file_view(*it).file_id() == file_manager->get_file_view(*pit).file_id()) { + is_duplicate = true; + break; + } + } + if (is_duplicate) { + it = secure_value_.files.erase(it); + } else { + it++; + } + } + + to_upload_.resize(secure_value_.files.size()); + upload_callback_ = std::make_shared(actor_id(this)); + for (size_t i = 0; i < to_upload_.size(); i++) { + to_upload_[i].file_id = file_manager->dup_file_id(secure_value_.files[i]); + file_manager->upload(to_upload_[i].file_id, upload_callback_, 1, 0); + files_left_to_upload_++; + } +} + +void SetSecureValue::loop() { + if (state_ == State::WaitSecret) { + if (!secret_) { + return; + } + if (files_left_to_upload_ != 0) { + return; + } + auto *file_manager = G()->file_manager().get_actor_unsafe(); + auto input_secure_value = get_input_secure_value_object( + file_manager, encrypt_secure_value(file_manager, *secret_, secure_value_), to_upload_); + auto save_secure_value = + telegram_api::account_saveSecureValue(std::move(input_secure_value), secret_.value().get_hash()); + LOG(ERROR) << to_string(save_secure_value); + auto query = G()->net_query_creator().create(create_storer(save_secure_value)); + + G()->net_query_dispatcher().dispatch_with_callback(std::move(query), actor_shared(this)); + state_ = State::WaitSetValue; + } +} +void SetSecureValue::on_result(NetQueryPtr query) { + auto r_result = fetch_result(std::move(query)); + if (r_result.is_error()) { + return on_error(r_result.move_as_error()); + } + auto result = r_result.move_as_ok(); + LOG(ERROR) << to_string(result); + auto *file_manager = G()->file_manager().get_actor_unsafe(); + auto encrypted_secure_value = get_encrypted_secure_value(file_manager, std::move(result)); + if (secure_value_.files.size() != encrypted_secure_value.files.size()) { + return on_error(Status::Error("Different files count")); + } + for (size_t i = 0; i < secure_value_.files.size(); i++) { + auto file_view = file_manager->get_file_view(secure_value_.files[i]); + CHECK(!file_view.empty()); + CHECK(file_view.encryption_key().has_value_hash()); + if (file_view.encryption_key().value_hash().as_slice() != encrypted_secure_value.files[i].file_hash) { + LOG(ERROR) << "hash mismatch"; + continue; + } + auto status = file_manager->merge(encrypted_secure_value.files[i].file_id, secure_value_.files[i]); + LOG_IF(ERROR, status.is_error()) << status.error(); + } + auto r_secure_value = decrypt_encrypted_secure_value(file_manager, *secret_, encrypted_secure_value); + if (r_secure_value.is_error()) { + return on_error(r_secure_value.move_as_error()); + } + promise_.set_result(get_passport_data_object(file_manager, r_secure_value.move_as_ok())); + stop(); +} + +SecureManager::SecureManager(ActorShared<> parent) : parent_(std::move(parent)) { +} + +void SecureManager::get_secure_value(std::string password, SecureValueType type, Promise promise) { + refcnt_++; + create_actor("GetSecureValue", actor_shared(), std::move(password), type, std::move(promise)) + .release(); +} + +void SecureManager::set_secure_value(string password, SecureValue secure_value, Promise promise) { + refcnt_++; + auto type = secure_value.type; + set_secure_value_queries_[type] = create_actor("SetSecureValue", actor_shared(), std::move(password), + std::move(secure_value), std::move(promise)); +} + +void SecureManager::hangup() { + dec_refcnt(); +} + +void SecureManager::hangup_shared() { + dec_refcnt(); +} +void SecureManager::dec_refcnt() { + refcnt_--; + if (refcnt_ == 0) { + stop(); + } +} +} // namespace td diff --git a/td/telegram/SecureManager.h b/td/telegram/SecureManager.h new file mode 100644 index 000000000..112c337a6 --- /dev/null +++ b/td/telegram/SecureManager.h @@ -0,0 +1,99 @@ +// +// Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2018 +// +// 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/actor/actor.h" + +#include "td/telegram/net/NetQuery.h" +#include "td/telegram/SecureValue.h" +#include "td/telegram/files/FileManager.h" + +#include "td/telegram/td_api.h" + +#include "td/utils/optional.h" + +namespace td { +using TdApiSecureValue = td_api::object_ptr; +class GetSecureValue : public NetQueryCallback { + public: + GetSecureValue(ActorShared<> parent, std::string password, SecureValueType type, Promise promise); + + private: + ActorShared<> parent_; + string password_; + SecureValueType type_; + Promise promise_; + optional encrypted_secure_value_; + optional secret_; + + void on_error(Status status); + void on_secret(Result r_secret, bool dummy); + void loop() override; + void start_up() override; + + void on_result(NetQueryPtr query) override; +}; + +class SetSecureValue : public NetQueryCallback { + public: + SetSecureValue(ActorShared<> parent, string password, SecureValue secure_value, Promise promise); + + private: + ActorShared<> parent_; + string password_; + SecureValue secure_value_; + Promise promise_; + optional secret_; + + size_t files_left_to_upload_ = 0; + vector to_upload_; + class UploadCallback; + std::shared_ptr upload_callback_; + + enum class State { WaitSecret, WaitSetValue } state_ = State::WaitSecret; + + class UploadCallback : public FileManager::UploadCallback { + public: + explicit UploadCallback(ActorId actor_id); + + private: + ActorId actor_id_; + void on_upload_ok(FileId file_id, tl_object_ptr input_file) override; + void on_upload_encrypted_ok(FileId file_id, tl_object_ptr input_file) override; + void on_upload_secure_ok(FileId file_id, tl_object_ptr input_file) override; + void on_upload_error(FileId file_id, Status error) override; + }; + + void on_upload_ok(FileId file_id, tl_object_ptr input_file); + void on_upload_error(FileId file_id, Status error); + + void on_error(Status status); + + void on_secret(Result r_secret, bool x); + + void start_up() override; + + void loop() override; + void on_result(NetQueryPtr query) override; +}; + +class SecureManager : public Actor { + public: + SecureManager(ActorShared<> parent); + + void get_secure_value(std::string password, SecureValueType type, Promise promise); + void set_secure_value(string password, SecureValue secure_value, Promise promise); + + private: + ActorShared<> parent_; + int32 refcnt_{1}; + std::map> set_secure_value_queries_; + + void hangup() override; + void hangup_shared() override; + void dec_refcnt(); +}; +} // namespace td diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index 8a910b5bb..d86987bb2 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -45,6 +45,7 @@ #include "td/telegram/PasswordManager.h" #include "td/telegram/Photo.h" #include "td/telegram/PrivacyManager.h" +#include "td/telegram/SecureManager.h" #include "td/telegram/SecureValue.h" #include "td/telegram/SecretChatId.h" #include "td/telegram/SecretChatsManager.h" @@ -3800,233 +3801,6 @@ class GetTermsOfServiceRequest : public RequestActor { } }; -using TdApiSecureValue = td_api::object_ptr; -class GetSecureValue : public NetQueryCallback { - public: - GetSecureValue(std::string password, SecureValueType type, Promise promise) - : password_(std::move(password)), type_(type), promise_(std::move(promise)) { - } - - private: - string password_; - SecureValueType type_; - Promise promise_; - optional encrypted_secure_value_; - optional secret_; - - void on_error(Status status) { - promise_.set_error(std::move(status)); - stop(); - } - - void on_secret(Result r_secret, bool dummy) { - LOG_IF(ERROR, r_secret.is_error()) << r_secret.error(); - LOG_IF(ERROR, r_secret.is_ok()) << r_secret.ok().get_hash(); - if (r_secret.is_error()) { - return on_error(r_secret.move_as_error()); - } - secret_ = r_secret.move_as_ok(); - loop(); - } - - void loop() override { - if (!encrypted_secure_value_ || !secret_) { - return; - } - auto *file_manager = G()->td().get_actor_unsafe()->file_manager_.get(); - auto r_secure_value = decrypt_encrypted_secure_value(file_manager, *secret_, *encrypted_secure_value_); - if (r_secure_value.is_error()) { - return on_error(r_secure_value.move_as_error()); - } - promise_.set_result(get_passport_data_object(file_manager, r_secure_value.move_as_ok())); - stop(); - } - void start_up() override { - std::vector> vec; - vec.push_back(get_secure_value_type_telegram_object(type_)); - - auto query = G()->net_query_creator().create(create_storer(telegram_api::account_getSecureValue(std::move(vec)))); - - G()->net_query_dispatcher().dispatch_with_callback(std::move(query), actor_shared(this)); - - send_closure(G()->password_manager(), &PasswordManager::get_secure_secret, password_, optional(), - PromiseCreator::lambda([actor_id = actor_id(this)](Result r_secret) { - send_closure(actor_id, &GetSecureValue::on_secret, std::move(r_secret), true); - })); - } - - void on_result(NetQueryPtr query) override { - auto r_result = fetch_result(std::move(query)); - if (r_result.is_error()) { - return on_error(r_result.move_as_error()); - } - auto result = r_result.move_as_ok(); - if (result.size() != 1) { - return on_error(Status::Error(PSLICE() << "Expected vector of size 1 got " << result.size())); - } - LOG(ERROR) << to_string(result[0]); - encrypted_secure_value_ = - get_encrypted_secure_value(G()->td().get_actor_unsafe()->file_manager_.get(), std::move(result[0])); - loop(); - } -}; - -class SetSecureValue : public NetQueryCallback { - public: - SetSecureValue(string password, SecureValue secure_value, Promise promise) - : password_(std::move(password)), secure_value_(std::move(secure_value)), promise_(std::move(promise)) { - } - - private: - string password_; - SecureValue secure_value_; - Promise promise_; - optional secret_; - - size_t files_left_to_upload_ = 0; - vector to_upload_; - class UploadCallback; - std::shared_ptr upload_callback_; - - enum class State { WaitSecret, WaitSetValue } state_ = State::WaitSecret; - - class UploadCallback : public FileManager::UploadCallback { - public: - explicit UploadCallback(ActorId actor_id) : actor_id_(actor_id) { - } - - private: - ActorId actor_id_; - void on_upload_ok(FileId file_id, tl_object_ptr input_file) override { - UNREACHABLE(); - } - void on_upload_encrypted_ok(FileId file_id, tl_object_ptr input_file) override { - UNREACHABLE(); - } - void on_upload_secure_ok(FileId file_id, tl_object_ptr input_file) override { - send_closure(actor_id_, &SetSecureValue::on_upload_ok, file_id, std::move(input_file)); - } - void on_upload_error(FileId file_id, Status error) override { - send_closure(actor_id_, &SetSecureValue::on_upload_error, file_id, std::move(error)); - } - }; - - void on_upload_ok(FileId file_id, tl_object_ptr input_file) { - for (auto &info : to_upload_) { - if (info.file_id != file_id) { - continue; - } - CHECK(!info.input_file); - info.input_file = std::move(input_file); - CHECK(files_left_to_upload_ != 0); - files_left_to_upload_--; - return loop(); - } - UNREACHABLE(); - } - void on_upload_error(FileId file_id, Status error) { - return on_error(std::move(error)); - } - - void on_error(Status status) { - promise_.set_error(std::move(status)); - stop(); - } - - void on_secret(Result r_secret, bool x) { - LOG_IF(ERROR, r_secret.is_error()) << r_secret.error(); - LOG_IF(ERROR, r_secret.is_ok()) << r_secret.ok().get_hash(); - if (r_secret.is_error()) { - return on_error(r_secret.move_as_error()); - } - secret_ = r_secret.move_as_ok(); - loop(); - } - - void start_up() override { - send_closure(G()->password_manager(), &PasswordManager::get_secure_secret, password_, optional(), - PromiseCreator::lambda([actor_id = actor_id(this)](Result r_secret) { - send_closure(actor_id, &SetSecureValue::on_secret, std::move(r_secret), true); - })); - auto *file_manager = G()->file_manager().get_actor_unsafe(); - - // Remove duplicated files - for (auto it = secure_value_.files.begin(); it != secure_value_.files.end();) { - bool is_duplicate = false; - for (auto pit = secure_value_.files.begin(); pit != it; pit++) { - if (file_manager->get_file_view(*it).file_id() == file_manager->get_file_view(*pit).file_id()) { - is_duplicate = true; - break; - } - } - if (is_duplicate) { - it = secure_value_.files.erase(it); - } else { - it++; - } - } - - to_upload_.resize(secure_value_.files.size()); - upload_callback_ = std::make_shared(actor_id(this)); - for (size_t i = 0; i < to_upload_.size(); i++) { - to_upload_[i].file_id = file_manager->dup_file_id(secure_value_.files[i]); - file_manager->upload(to_upload_[i].file_id, upload_callback_, 1, 0); - files_left_to_upload_++; - } - } - - void loop() override { - if (state_ == State::WaitSecret) { - if (!secret_) { - return; - } - if (files_left_to_upload_ != 0) { - return; - } - auto *file_manager = G()->td().get_actor_unsafe()->file_manager_.get(); - auto input_secure_value = get_input_secure_value_object( - file_manager, encrypt_secure_value(file_manager, *secret_, secure_value_), to_upload_); - auto save_secure_value = - telegram_api::account_saveSecureValue(std::move(input_secure_value), secret_.value().get_hash()); - LOG(ERROR) << to_string(save_secure_value); - auto query = G()->net_query_creator().create(create_storer(save_secure_value)); - - G()->net_query_dispatcher().dispatch_with_callback(std::move(query), actor_shared(this)); - state_ = State::WaitSetValue; - } - } - void on_result(NetQueryPtr query) override { - auto r_result = fetch_result(std::move(query)); - if (r_result.is_error()) { - return on_error(r_result.move_as_error()); - } - auto result = r_result.move_as_ok(); - LOG(ERROR) << to_string(result); - auto *file_manager = G()->td().get_actor_unsafe()->file_manager_.get(); - auto encrypted_secure_value = get_encrypted_secure_value(file_manager, std::move(result)); - if (secure_value_.files.size() != encrypted_secure_value.files.size()) { - return on_error(Status::Error("Different files count")); - } - for (size_t i = 0; i < secure_value_.files.size(); i++) { - auto file_view = file_manager->get_file_view(secure_value_.files[i]); - CHECK(!file_view.empty()); - CHECK(file_view.encryption_key().has_value_hash()); - if (file_view.encryption_key().value_hash().as_slice() != encrypted_secure_value.files[i].file_hash) { - LOG(ERROR) << "hash mismatch"; - continue; - } - auto status = file_manager->merge(encrypted_secure_value.files[i].file_id, secure_value_.files[i]); - LOG_IF(ERROR, status.is_error()) << status.error(); - } - auto r_secure_value = decrypt_encrypted_secure_value(file_manager, *secret_, encrypted_secure_value); - if (r_secure_value.is_error()) { - return on_error(r_secure_value.move_as_error()); - } - promise_.set_result(get_passport_data_object(file_manager, r_secure_value.move_as_ok())); - stop(); - } -}; - /** Td **/ Td::Td(std::unique_ptr callback) : callback_(std::move(callback)) { } @@ -4535,6 +4309,8 @@ void Td::clear() { LOG(DEBUG) << "PasswordManager was cleared " << timer; privacy_manager_.reset(); LOG(DEBUG) << "PrivacyManager was cleared " << timer; + secure_manager_.reset(); + LOG(DEBUG) << "SecureManager was cleared " << timer; secret_chats_manager_.reset(); LOG(DEBUG) << "SecretChatsManager was cleared " << timer; storage_manager_.reset(); @@ -4782,6 +4558,7 @@ Status Td::init(DbKey key) { password_manager_ = create_actor("PasswordManager", create_reference()); G()->set_password_manager(password_manager_.get()); privacy_manager_ = create_actor("PrivacyManager", create_reference()); + secure_manager_ = create_actor("SecureManager", create_reference()); secret_chats_manager_ = create_actor("SecretChatsManager", create_reference()); G()->set_secret_chats_manager(secret_chats_manager_.get()); storage_manager_ = create_actor("StorageManager", create_reference(), @@ -7056,9 +6833,8 @@ void Td::on_request(uint64 id, td_api::getPassportData &request) { if (request.type_ == nullptr) { return promise.set_error(Status::Error(400, "Type must not be empty")); } - create_actor("GetSecureValue", std::move(request.password_), - get_secure_value_type_td_api(std::move(request.type_)), std::move(promise)) - .release(); + send_closure(secure_manager_, &SecureManager::get_secure_value, std::move(request.password_), + get_secure_value_type_td_api(std::move(request.type_)), std::move(promise)); } void Td::on_request(uint64 id, td_api::setPassportData &request) { @@ -7070,9 +6846,8 @@ void Td::on_request(uint64 id, td_api::setPassportData &request) { if (r_secure_value.is_error()) { return promise.set_error(r_secure_value.move_as_error()); } - create_actor("SetSecureValue", std::move(request.password_), r_secure_value.move_as_ok(), - std::move(promise)) - .release(); + send_closure(secure_manager_, &SecureManager::set_secure_value, std::move(request.password_), + r_secure_value.move_as_ok(), std::move(promise)); } void Td::on_request(uint64 id, const td_api::deletePassportData &request) { diff --git a/td/telegram/Td.h b/td/telegram/Td.h index ce03f0e60..393380028 100644 --- a/td/telegram/Td.h +++ b/td/telegram/Td.h @@ -47,6 +47,7 @@ class MessagesManager; class NetStatsManager; class PasswordManager; class PrivacyManager; +class SecureManager; class SecretChatsManager; class StickersManager; class StorageManager; @@ -149,6 +150,7 @@ class Td final : public NetQueryCallback { ActorOwn net_stats_manager_; ActorOwn password_manager_; ActorOwn privacy_manager_; + ActorOwn secure_manager_; ActorOwn secret_chats_manager_; ActorOwn state_manager_; ActorOwn storage_manager_;