diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index c5ca7bd6f..8a84672d4 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -834,7 +834,7 @@ passportDataTypeEmailAddress = PassportDataType; passportData type:PassportDataType data:string files:vector selfie:file = PassportData; //@description Contains information about a Telegram Passport data to save @type Telegram Passport data type @data TODO data should be typed @files List of attached files with a document @selfie Selfie with the document -inputPassportData type:PassportDataType data:string files:vector selfie:file = InputPassportData; +inputPassportData type:PassportDataType data:string files:vector selfie:InputFile = InputPassportData; //@class PassportAuthorizationForm Contains information about requested Telegram Passport authorization form @data Available data diff --git a/td/generate/scheme/td_api.tlo b/td/generate/scheme/td_api.tlo index d415a2983..112371c33 100644 Binary files a/td/generate/scheme/td_api.tlo and b/td/generate/scheme/td_api.tlo differ diff --git a/td/telegram/SecureManager.cpp b/td/telegram/SecureManager.cpp index e9e5d1155..05e56459e 100644 --- a/td/telegram/SecureManager.cpp +++ b/td/telegram/SecureManager.cpp @@ -43,6 +43,7 @@ void GetSecureValue::loop() { 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_)); @@ -98,17 +99,24 @@ void SetSecureValue::UploadCallback::on_upload_error(FileId file_id, Status erro } void SetSecureValue::on_upload_ok(FileId file_id, tl_object_ptr input_file) { + SecureInputFile *info_ptr = nullptr; 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(); + info_ptr = &info; + break; } - UNREACHABLE(); + if (selfie_ && selfie_.value().file_id == file_id) { + info_ptr = &selfie_.value(); + } + CHECK(info_ptr); + auto &info = *info_ptr; + CHECK(!info.input_file); + info.input_file = std::move(input_file); + CHECK(files_left_to_upload_ != 0); + files_left_to_upload_--; + return loop(); } void SetSecureValue::on_upload_error(FileId file_id, Status error) { return on_error(std::move(error)); @@ -145,6 +153,10 @@ void SetSecureValue::start_up() { break; } } + if (secure_value_.selfie.is_valid() && + file_manager->get_file_view(*it).file_id() == file_manager->get_file_view(secure_value_.selfie).file_id()) { + is_duplicate = true; + } if (is_duplicate) { it = secure_value_.files.erase(it); } else { @@ -155,10 +167,17 @@ void SetSecureValue::start_up() { 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_++; + start_upload(file_manager, secure_value_.files[i], to_upload_[i]); } + if (selfie_) { + start_upload(file_manager, secure_value_.selfie, selfie_.value()); + } +} + +void SetSecureValue::start_upload(FileManager *file_manager, FileId file_id, SecureInputFile &info) { + info.file_id = file_manager->dup_file_id(file_id); + file_manager->upload(info.file_id, upload_callback_, 1, 0); + files_left_to_upload_++; } void SetSecureValue::loop() { @@ -171,7 +190,7 @@ void SetSecureValue::loop() { } 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_); + file_manager, encrypt_secure_value(file_manager, *secret_, secure_value_), to_upload_, selfie_); auto save_secure_value = telegram_api::account_saveSecureValue(std::move(input_secure_value), secret_.value().get_hash()); LOG(ERROR) << to_string(save_secure_value); @@ -181,6 +200,14 @@ void SetSecureValue::loop() { state_ = State::WaitSetValue; } } + +void SetSecureValue::tear_down() { + auto *file_manager = G()->file_manager().get_actor_unsafe(); + for (auto &file_info : to_upload_) { + file_manager->upload(file_info.file_id, nullptr, 0, 0); + } +} + void SetSecureValue::on_result(NetQueryPtr query) { auto r_result = fetch_result(std::move(query)); if (r_result.is_error()) { @@ -194,15 +221,10 @@ void SetSecureValue::on_result(NetQueryPtr query) { 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(); + merge(file_manager, secure_value_.files[i], encrypted_secure_value.files[i]); + } + if (secure_value_.selfie.is_valid()) { + merge(file_manager, secure_value_.selfie, encrypted_secure_value.selfie); } auto r_secure_value = decrypt_encrypted_secure_value(file_manager, *secret_, encrypted_secure_value); if (r_secure_value.is_error()) { @@ -212,6 +234,18 @@ void SetSecureValue::on_result(NetQueryPtr query) { stop(); } +void SetSecureValue::merge(FileManager *file_manager, FileId file_id, SecureFile &encrypted_file) { + auto file_view = file_manager->get_file_view(file_id); + CHECK(!file_view.empty()); + CHECK(file_view.encryption_key().has_value_hash()); + if (file_view.encryption_key().value_hash().as_slice() != encrypted_file.file_hash) { + LOG(ERROR) << "hash mismatch"; + return; + } + auto status = file_manager->merge(encrypted_file.file_id, file_id); + LOG_IF(ERROR, status.is_error()) << status.error(); +} + SecureManager::SecureManager(ActorShared<> parent) : parent_(std::move(parent)) { } diff --git a/td/telegram/SecureManager.h b/td/telegram/SecureManager.h index 112c337a6..5b5578b62 100644 --- a/td/telegram/SecureManager.h +++ b/td/telegram/SecureManager.h @@ -50,6 +50,8 @@ class SetSecureValue : public NetQueryCallback { size_t files_left_to_upload_ = 0; vector to_upload_; + optional selfie_; + class UploadCallback; std::shared_ptr upload_callback_; @@ -75,9 +77,13 @@ class SetSecureValue : public NetQueryCallback { void on_secret(Result r_secret, bool x); void start_up() override; + void tear_down() override; void loop() override; void on_result(NetQueryPtr query) override; + + void start_upload(FileManager *file_manager, FileId file_id, SecureInputFile &info); + void merge(FileManager *file_manager, FileId file_id, SecureFile &encrypted_file); }; class SecureManager : public Actor { diff --git a/td/telegram/SecureValue.cpp b/td/telegram/SecureValue.cpp index ce6dcb73e..dcc65a614 100644 --- a/td/telegram/SecureValue.cpp +++ b/td/telegram/SecureValue.cpp @@ -310,7 +310,8 @@ td_api::object_ptr get_encrypted_passport_data_ob } telegram_api::object_ptr get_input_secure_value_object( - FileManager *file_manager, const EncryptedSecureValue &value, std::vector &input_files) { + FileManager *file_manager, const EncryptedSecureValue &value, std::vector &input_files, + optional &selfie) { bool is_plain = value.type == SecureValueType::PhoneNumber || value.type == SecureValueType::EmailAddress; bool has_selfie = value.selfie.file_id.is_valid(); int32 flags = 0; @@ -330,11 +331,12 @@ telegram_api::object_ptr get_input_secure_value_ } if (has_selfie) { flags |= telegram_api::inputSecureValue::SELFIE_MASK; + CHECK(selfie); } return telegram_api::make_object( flags, get_secure_value_type_telegram_object(value.type), is_plain ? nullptr : get_secure_data_object(value.data), get_input_secure_files_object(file_manager, value.files, input_files), std::move(plain_data), - has_selfie ? /*TODO*/ nullptr : nullptr); + has_selfie ? get_input_secure_file_object(file_manager, value.selfie, *selfie) : nullptr); } vector> get_encrypted_passport_data_object( @@ -381,15 +383,24 @@ Result get_secure_value(FileManager *file_manager, false, true)); res.files.push_back(file_id); } - // res.selfie = TODO + if (input_passport_data->selfie_) { + TRY_RESULT(file_id, file_manager->get_input_file_id(FileType::Secure, std::move(input_passport_data->selfie_), + DialogId{}, false, false, false, true)); + res.selfie = file_id; + } return res; } td_api::object_ptr get_passport_data_object(FileManager *file_manager, const SecureValue &value) { std::vector> files; files = transform(value.files, [&](FileId id) { return file_manager->get_file_object(id, true); }); - //TODO selfie + + td_api::object_ptr selfie; + if (value.selfie.is_valid()) { + selfie = file_manager->get_file_object(value.selfie, true); + } + return td_api::make_object(get_passport_data_type_object(value.type), value.data, - std::move(files), nullptr); + std::move(files), std::move(selfie)); } Result decrypt_secure_file(FileManager *file_manager, const secure_storage::Secret &master_secret, @@ -436,9 +447,8 @@ Result decrypt_encrypted_secure_value(FileManager *file_manager, co res.data = std::move(data); TRY_RESULT(files, decrypt_secure_files(file_manager, secret, encrypted_secure_value.files)); res.files = std::move(files); - // TODO - //TRY_RESULT(selfie, decrypt_secure_file(file_manager, secret, encrypted_secure_value.selfie)); - //res.selfie = std::move(selfie); + TRY_RESULT(selfie, decrypt_secure_file(file_manager, secret, encrypted_secure_value.selfie)); + res.selfie = std::move(selfie); break; } } @@ -506,8 +516,7 @@ EncryptedSecureValue encrypt_secure_value(FileManager *file_manager, const secur string to_hash; res.data = encrypt_secure_data(master_secret, secure_value.data, to_hash); res.files = encrypt_secure_files(file_manager, master_secret, secure_value.files, to_hash); - // TODO - //res.selfie = encrypt_secure_file(file_manager, master_secret, secure_value.selfie, to_hash); + res.selfie = encrypt_secure_file(file_manager, master_secret, secure_value.selfie, to_hash); res.hash = ss::calc_value_hash(to_hash).as_slice().str(); break; } diff --git a/td/telegram/SecureValue.h b/td/telegram/SecureValue.h index ee410cb45..6ba721645 100644 --- a/td/telegram/SecureValue.h +++ b/td/telegram/SecureValue.h @@ -13,6 +13,7 @@ #include "td/telegram/SecureStorage.h" #include "td/utils/common.h" +#include "td/utils/optional.h" #include "td/utils/Status.h" namespace td { @@ -108,7 +109,8 @@ vector get_encrypted_secure_values( td_api::object_ptr get_encrypted_passport_data_object(FileManager *file_manager, const EncryptedSecureValue &value); telegram_api::object_ptr get_input_secure_value_object( - FileManager *file_manager, const EncryptedSecureValue &value, vector &input_files); + FileManager *file_manager, const EncryptedSecureValue &value, vector &input_files, + optional &selfie); vector> get_encrypted_passport_data_object( FileManager *file_manager, const vector &values);