From 0eee63b723227a10a9cd152b200933937540df8c Mon Sep 17 00:00:00 2001 From: Arseny Smirnov Date: Fri, 6 Apr 2018 22:37:30 +0300 Subject: [PATCH] sendAuthorizationForm (with bugs) GitOrigin-RevId: e68b57a2f6ff2e117913c40779cc9473153828ab --- td/generate/scheme/td_api.tl | 4 +- td/generate/scheme/td_api.tlo | Bin 116972 -> 117040 bytes td/telegram/MessagesManager.h | 4 +- td/telegram/SecureManager.cpp | 130 ++++++++++++++++++++++-- td/telegram/SecureManager.h | 23 +++-- td/telegram/SecureValue.cpp | 186 ++++++++++++++++++++++++++++++---- td/telegram/SecureValue.h | 59 ++++++++--- td/telegram/SecureValue.hpp | 4 +- td/telegram/Td.cpp | 18 +++- td/telegram/Td.h | 2 +- td/telegram/cli.cpp | 19 +++- tdutils/td/utils/Status.h | 4 + tdutils/td/utils/optional.h | 5 +- 13 files changed, 396 insertions(+), 62 deletions(-) diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index ebbded991..a55cc3aef 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -2910,10 +2910,10 @@ checkEmailAddressVerificationCode code:string = Ok; //@description Returns Telegram Passport authorization form for sharing data with a service @bot_id Service's bot identifier @scope Telegram Passport data types requested by the service @public_key Service's public_key @password Password of the current user -getPassportAuthorizationForm bot_id:int32 scope:string public_key:string password:string = PassportAuthorizationForm; +getPassportAuthorizationForm bot_id:int32 scope:string public_key:string payload:string password:string = PassportAuthorizationForm; //@description Sends Telegram Passport authorization form, effectively sharing data with the service @autorization_form_id Authorization form identifier -sendPassportAuthorizationForm autorization_form_id:int32 types:vector = Ok; +sendPassportAuthorizationForm autorization_form_id:int32 types:vector password:string = Ok; //@description Informs the server about the number of pending bot updates if they haven't been processed for a long time; for bots only @pending_update_count The number of pending updates @error_message The last error message diff --git a/td/generate/scheme/td_api.tlo b/td/generate/scheme/td_api.tlo index 26a8ba62e24597a932ceb892f0da4ad9983716fd..8192a44525ddc20968cb5c83e58664dadcaf99e1 100644 GIT binary patch delta 93 zcmV-j0HXiwkq5An2Y|EzSbPX+3b}I{g?s^Pm$)hc5R<6f zIFp>w5Vt6O0U#{|n)Hv}mrSYwC;NeRCt< delta 71 zcmV-N0J#6Kk_YUO2Y|EzSbPYo1da_HXJvGkajF3umwS8x2>}F`g?s^Pw-9{+SSYZ-_#K(c8I%A3 diff --git a/td/telegram/MessagesManager.h b/td/telegram/MessagesManager.h index 619b2ea35..705cae381 100644 --- a/td/telegram/MessagesManager.h +++ b/td/telegram/MessagesManager.h @@ -644,10 +644,10 @@ class MessagePassportDataSent : public MessageContent { class MessagePassportDataReceived : public MessageContent { public: vector values; - SecureCredentials credentials; + EncryptedSecureCredentials credentials; MessagePassportDataReceived() = default; - MessagePassportDataReceived(vector &&values, SecureCredentials &&credentials) + MessagePassportDataReceived(vector &&values, EncryptedSecureCredentials &&credentials) : values(std::move(values)), credentials(std::move(credentials)) { } diff --git a/td/telegram/SecureManager.cpp b/td/telegram/SecureManager.cpp index fbec4770d..8197eca8c 100644 --- a/td/telegram/SecureManager.cpp +++ b/td/telegram/SecureManager.cpp @@ -12,7 +12,7 @@ namespace td { GetSecureValue::GetSecureValue(ActorShared<> parent, std::string password, SecureValueType type, - Promise promise) + Promise promise) : parent_(std::move(parent)), password_(std::move(password)), type_(type), promise_(std::move(promise)) { } @@ -40,7 +40,7 @@ void GetSecureValue::loop() { 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())); + promise_.set_result(r_secure_value.move_as_ok()); stop(); } @@ -73,7 +73,7 @@ void GetSecureValue::on_result(NetQueryPtr query) { } SetSecureValue::SetSecureValue(ActorShared<> parent, string password, SecureValue secure_value, - Promise promise) + Promise promise) : parent_(std::move(parent)) , password_(std::move(password)) , secure_value_(std::move(secure_value)) @@ -230,7 +230,7 @@ void SetSecureValue::on_result(NetQueryPtr query) { 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())); + promise_.set_result(r_secure_value.move_as_ok()); stop(); } @@ -330,7 +330,7 @@ class GetPassportAuthorizationForm : public NetQueryCallback { auto r_secure_value = decrypt_encrypted_secure_value(file_manager, *secret_, std::move(*encrypted_secure_value)); if (r_secure_value.is_ok()) { - secure_value = r_secure_value.move_as_ok(); + secure_value = r_secure_value.move_as_ok().value; } else { LOG(ERROR) << "Failed to decrypt secure value: " << r_secure_value.error(); } @@ -348,6 +348,19 @@ SecureManager::SecureManager(ActorShared<> parent) : parent_(std::move(parent)) } void SecureManager::get_secure_value(std::string password, SecureValueType type, Promise promise) { + auto new_promise = + PromiseCreator::lambda([promise = std::move(promise)](Result r_secure_value) mutable { + if (r_secure_value.is_error()) { + return promise.set_error(r_secure_value.move_as_error()); + } + auto *file_manager = G()->file_manager().get_actor_unsafe(); + promise.set_value(get_passport_data_object(file_manager, r_secure_value.move_as_ok().value)); + }); + do_get_secure_value(std::move(password), type, std::move(new_promise)); +} + +void SecureManager::do_get_secure_value(std::string password, SecureValueType type, + Promise promise) { refcnt_++; create_actor("GetSecureValue", actor_shared(), std::move(password), type, std::move(promise)) .release(); @@ -356,15 +369,23 @@ void SecureManager::get_secure_value(std::string password, SecureValueType type, void SecureManager::set_secure_value(string password, SecureValue secure_value, Promise promise) { refcnt_++; auto type = secure_value.type; + auto new_promise = + PromiseCreator::lambda([promise = std::move(promise)](Result r_secure_value) mutable { + if (r_secure_value.is_error()) { + return promise.set_error(r_secure_value.move_as_error()); + } + auto *file_manager = G()->file_manager().get_actor_unsafe(); + promise.set_value(get_passport_data_object(file_manager, r_secure_value.move_as_ok().value)); + }); set_secure_value_queries_[type] = create_actor("SetSecureValue", actor_shared(), std::move(password), - std::move(secure_value), std::move(promise)); + std::move(secure_value), std::move(new_promise)); } void SecureManager::get_passport_authorization_form(string password, int32 bot_id, string scope, string public_key, - Promise promise) { + string payload, Promise promise) { refcnt_++; auto authorization_form_id = ++authorization_form_id_; - authorization_forms_[authorization_form_id] = AuthorizationForm{bot_id, public_key}; + authorization_forms_[authorization_form_id] = AuthorizationForm{bot_id, scope, public_key, payload}; create_actor("GetPassportAuthorizationForm", actor_shared(), std::move(password), authorization_form_id, bot_id, std::move(scope), std::move(public_key), std::move(promise)) @@ -377,7 +398,91 @@ void SecureManager::send_passport_authorization_form(string password, int32 auth if (it == authorization_forms_.end()) { return promise.set_error(Status::Error(400, "Unknown authorization_form_id")); } + if (types.empty()) { + return promise.set_error(Status::Error(400, "Empty types")); + } + + struct JoinPromise { + std::mutex mutex_; + Promise> promise_; + std::vector credentials_; + int wait_cnt_{0}; + }; + + auto join = std::make_shared(); + std::lock_guard guard(join->mutex_); + for (auto type : types) { + join->wait_cnt_++; + do_get_secure_value(password, type, + PromiseCreator::lambda([join](Result r_secure_value) { + std::lock_guard guard(join->mutex_); + if (!join->promise_) { + return; + } + if (r_secure_value.is_error()) { + return join->promise_.set_error(r_secure_value.move_as_error()); + } + join->credentials_.push_back(r_secure_value.move_as_ok().credentials); + join->wait_cnt_--; + LOG(ERROR) << tag("wait_cnt", join->wait_cnt_); + if (join->wait_cnt_ == 0) { + LOG(ERROR) << "set promise"; + join->promise_.set_value(std::move(join->credentials_)); + } + })); + } + join->promise_ = + PromiseCreator::lambda([promise = std::move(promise), actor_id = actor_id(this), + authorization_form_id](Result> r_credentials) mutable { + LOG(ERROR) << "on promise"; + if (r_credentials.is_error()) { + return promise.set_error(r_credentials.move_as_error()); + } + send_closure(actor_id, &SecureManager::do_send_passport_authorization_form, authorization_form_id, + r_credentials.move_as_ok(), std::move(promise)); + }); } + +void SecureManager::do_send_passport_authorization_form(int32 authorization_form_id, + vector credentials, Promise<> promise) { + LOG(ERROR) << "do_send_passport_authorization_form"; + auto it = authorization_forms_.find(authorization_form_id); + if (it == authorization_forms_.end()) { + return promise.set_error(Status::Error(400, "Unknown authorization_form_id")); + } + if (credentials.empty()) { + return promise.set_error(Status::Error(400, "Empty types")); + } + std::vector> hashes; + for (auto &c : credentials) { + hashes.push_back(telegram_api::make_object( + get_secure_value_type_telegram_object(c.type), BufferSlice(c.hash))); + } + + auto r_encrypted_credentials = encrypted_credentials(credentials, it->second.payload, it->second.public_key); + if (r_encrypted_credentials.is_error()) { + return promise.set_error(r_encrypted_credentials.move_as_error()); + } + + auto td_query = telegram_api::account_acceptAuthorization( + it->second.bot_id, it->second.scope, it->second.public_key, std::move(hashes), + get_secure_credentials_encrypted_object(r_encrypted_credentials.move_as_ok())); + LOG(ERROR) << to_string(td_query); + auto query = G()->net_query_creator().create(create_storer(td_query)); + auto new_promise = + PromiseCreator::lambda([promise = std::move(promise)](Result r_net_query_ptr) mutable { + if (r_net_query_ptr.is_error()) { + return promise.set_error(r_net_query_ptr.move_as_error()); + } + auto r_result = fetch_result(r_net_query_ptr.move_as_ok()); + if (r_result.is_error()) { + return promise.set_error(r_result.move_as_error()); + } + promise.set_value(Unit()); + }); + send_with_promise(std::move(query), std::move(new_promise)); +} + void SecureManager::hangup() { dec_refcnt(); } @@ -391,4 +496,13 @@ void SecureManager::dec_refcnt() { stop(); } } +void SecureManager::on_result(NetQueryPtr query) { + auto token = get_link_token(); + container_.extract(token).set_value(std::move(query)); +} + +void SecureManager::send_with_promise(NetQueryPtr query, Promise promise) { + auto id = container_.create(std::move(promise)); + G()->net_query_dispatcher().dispatch_with_callback(std::move(query), actor_shared(this, id)); +} } // namespace td diff --git a/td/telegram/SecureManager.h b/td/telegram/SecureManager.h index 1061105a3..93a51b1c2 100644 --- a/td/telegram/SecureManager.h +++ b/td/telegram/SecureManager.h @@ -20,13 +20,14 @@ using TdApiSecureValue = td_api::object_ptr; using TdApiAuthorizationForm = td_api::object_ptr; class GetSecureValue : public NetQueryCallback { public: - GetSecureValue(ActorShared<> parent, std::string password, SecureValueType type, Promise promise); + GetSecureValue(ActorShared<> parent, std::string password, SecureValueType type, + Promise promise); private: ActorShared<> parent_; string password_; SecureValueType type_; - Promise promise_; + Promise promise_; optional encrypted_secure_value_; optional secret_; @@ -40,13 +41,14 @@ class GetSecureValue : public NetQueryCallback { class SetSecureValue : public NetQueryCallback { public: - SetSecureValue(ActorShared<> parent, string password, SecureValue secure_value, Promise promise); + SetSecureValue(ActorShared<> parent, string password, SecureValue secure_value, + Promise promise); private: ActorShared<> parent_; string password_; SecureValue secure_value_; - Promise promise_; + Promise promise_; optional secret_; size_t files_left_to_upload_ = 0; @@ -87,14 +89,14 @@ class SetSecureValue : public NetQueryCallback { void merge(FileManager *file_manager, FileId file_id, EncryptedSecureFile &encrypted_file); }; -class SecureManager : public Actor { +class SecureManager : public NetQueryCallback { 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); - void get_passport_authorization_form(string password, int32 bot_id, string scope, string public_key, + void get_passport_authorization_form(string password, int32 bot_id, string scope, string public_key, string payload, Promise promise); void send_passport_authorization_form(string password, int32 authorization_form_id, std::vector types, Promise<> promise); @@ -106,7 +108,9 @@ class SecureManager : public Actor { struct AuthorizationForm { int32 bot_id; + string scope; string public_key; + string payload; }; std::map authorization_forms_; @@ -115,5 +119,12 @@ class SecureManager : public Actor { void hangup() override; void hangup_shared() override; void dec_refcnt(); + void do_get_secure_value(std::string password, SecureValueType type, Promise promise); + void do_send_passport_authorization_form(int32 authorization_form_id, vector credentials, + Promise<> promise); + + void on_result(NetQueryPtr query) override; + Container> container_; + void send_with_promise(NetQueryPtr query, Promise promise); }; } // namespace td diff --git a/td/telegram/SecureValue.cpp b/td/telegram/SecureValue.cpp index d07697247..a51566b37 100644 --- a/td/telegram/SecureValue.cpp +++ b/td/telegram/SecureValue.cpp @@ -13,6 +13,8 @@ #include "td/utils/misc.h" #include "td/utils/overloaded.h" +#include "td/utils/JsonBuilder.h" +#include "td/utils/base64.h" namespace td { @@ -79,6 +81,11 @@ vector get_secure_value_types( return transform(std::move(secure_value_types), get_secure_value_type); } +vector get_secure_value_types_td_api( + vector> &&secure_value_types) { + return transform(std::move(secure_value_types), get_secure_value_type_td_api); +} + td_api::object_ptr get_passport_data_type_object(SecureValueType type) { switch (type) { case SecureValueType::PersonalDetails: @@ -291,6 +298,7 @@ EncryptedSecureValue get_encrypted_secure_value(FileManager *file_manager, if (secure_value->selfie_ != nullptr) { result.selfie = get_secure_file(file_manager, std::move(secure_value->selfie_)); } + result.hash = secure_value->hash_.as_slice().str(); return result; } @@ -347,17 +355,24 @@ vector> get_encrypted_passport }); } -bool operator==(const SecureCredentials &lhs, const SecureCredentials &rhs) { +bool operator==(const EncryptedSecureCredentials &lhs, const EncryptedSecureCredentials &rhs) { return lhs.data == rhs.data && lhs.hash == rhs.hash && lhs.encrypted_secret == rhs.encrypted_secret; } -bool operator!=(const SecureCredentials &lhs, const SecureCredentials &rhs) { +bool operator!=(const EncryptedSecureCredentials &lhs, const EncryptedSecureCredentials &rhs) { return !(lhs == rhs); } -SecureCredentials get_secure_credentials(tl_object_ptr &&credentials) { +telegram_api::object_ptr get_secure_credentials_encrypted_object( + const EncryptedSecureCredentials &credentials) { + return telegram_api::make_object( + BufferSlice(credentials.data), BufferSlice(credentials.hash), BufferSlice(credentials.encrypted_secret)); +} + +EncryptedSecureCredentials get_secure_credentials( + tl_object_ptr &&credentials) { CHECK(credentials != nullptr); - SecureCredentials result; + EncryptedSecureCredentials result; result.data = credentials->data_.as_slice().str(); result.hash = credentials->hash_.as_slice().str(); result.encrypted_secret = credentials->secret_.as_slice().str(); @@ -365,7 +380,7 @@ SecureCredentials get_secure_credentials(tl_object_ptr get_encrypted_credentials_object( - const SecureCredentials &credentials) { + const EncryptedSecureCredentials &credentials) { return td_api::make_object(credentials.data, credentials.hash, credentials.encrypted_secret); } @@ -404,10 +419,11 @@ td_api::object_ptr get_passport_data_object(FileManager *f std::move(files), std::move(selfie)); } -Result decrypt_secure_file(FileManager *file_manager, const secure_storage::Secret &master_secret, - const EncryptedSecureFile &secure_file) { +Result> decrypt_secure_file(FileManager *file_manager, + const secure_storage::Secret &master_secret, + const EncryptedSecureFile &secure_file) { if (!secure_file.file_id.is_valid()) { - return secure_file.file_id; + return std::make_pair(secure_file.file_id, SecureFileCredentials{}); } TRY_RESULT(hash, secure_storage::ValueHash::create(secure_file.file_hash)); TRY_RESULT(encrypted_secret, secure_storage::EncryptedSecret::create(secure_file.encrypted_secret)); @@ -415,33 +431,39 @@ Result decrypt_secure_file(FileManager *file_manager, const secure_stora FileEncryptionKey key{secret}; key.set_value_hash(hash); file_manager->set_encryption_key(secure_file.file_id, std::move(key)); - return secure_file.file_id; + return std::make_pair(secure_file.file_id, SecureFileCredentials{secret.as_slice().str(), hash.as_slice().str()}); } -Result> decrypt_secure_files(FileManager *file_manager, const secure_storage::Secret &secret, - const vector &secure_files) { +Result, vector>> decrypt_secure_files( + FileManager *file_manager, const secure_storage::Secret &secret, const vector &secure_files) { vector res; + vector credentials; res.reserve(secure_files.size()); for (auto &file : secure_files) { TRY_RESULT(decrypted_file, decrypt_secure_file(file_manager, secret, file)); - res.push_back(decrypted_file); + res.push_back(decrypted_file.first); + credentials.push_back(decrypted_file.second); } - return std::move(res); + return std::make_pair(std::move(res), std::move(credentials)); } -Result decrypt_secure_data(const secure_storage::Secret &master_secret, - const EncryptedSecureData &secure_data) { +Result> decrypt_secure_data(const secure_storage::Secret &master_secret, + const EncryptedSecureData &secure_data) { TRY_RESULT(hash, secure_storage::ValueHash::create(secure_data.hash)); TRY_RESULT(encrypted_secret, secure_storage::EncryptedSecret::create(secure_data.encrypted_secret)); TRY_RESULT(secret, encrypted_secret.decrypt(PSLICE() << master_secret.as_slice() << hash.as_slice())); TRY_RESULT(value, secure_storage::decrypt_value(secret, hash, secure_data.data)); - return value.as_slice().str(); + return std::make_pair(value.as_slice().str(), SecureDataCredentials{secret.as_slice().str(), hash.as_slice().str()}); } -Result decrypt_encrypted_secure_value(FileManager *file_manager, const secure_storage::Secret &secret, - const EncryptedSecureValue &encrypted_secure_value) { +Result decrypt_encrypted_secure_value(FileManager *file_manager, + const secure_storage::Secret &secret, + const EncryptedSecureValue &encrypted_secure_value) { SecureValue res; + SecureValueCredentials res_credentials; res.type = encrypted_secure_value.type; + res_credentials.type = res.type; + res_credentials.hash = encrypted_secure_value.hash; switch (encrypted_secure_value.type) { case SecureValueType::EmailAddress: case SecureValueType::PhoneNumber: @@ -449,15 +471,22 @@ Result decrypt_encrypted_secure_value(FileManager *file_manager, co break; default: { TRY_RESULT(data, decrypt_secure_data(secret, encrypted_secure_value.data)); - res.data = std::move(data); + res.data = std::move(data.first); + if (!res.data.empty()) { + res_credentials.data = std::move(data.second); + } TRY_RESULT(files, decrypt_secure_files(file_manager, secret, encrypted_secure_value.files)); - res.files = std::move(files); + res.files = std::move(files.first); + res_credentials.files = std::move(files.second); TRY_RESULT(selfie, decrypt_secure_file(file_manager, secret, encrypted_secure_value.selfie)); - res.selfie = std::move(selfie); + res.selfie = std::move(selfie.first); + if (res.selfie.is_valid()) { + res_credentials.selfie = std::move(selfie.second); + } break; } } - return std::move(res); + return SecureValueWithCredentials{std::move(res), std::move(res_credentials)}; } EncryptedSecureFile encrypt_secure_file(FileManager *file_manager, const secure_storage::Secret &master_secret, @@ -528,4 +557,117 @@ EncryptedSecureValue encrypt_secure_value(FileManager *file_manager, const secur return res; } +template +class AsJsonable : public Jsonable { + public: + AsJsonable(const T &value) : value_(value) { + } + void store(JsonValueScope *scope) const { + *scope + value_; + } + + private: + const T &value_; +}; + +template +auto as_jsonable(const T &value) { + return AsJsonable(value); +} + +JsonScope &operator+(JsonValueScope &scope, const SecureDataCredentials &credentials) { + auto object = scope.enter_object(); + object << ctie("data_hash", base64_encode(credentials.hash)); + object << ctie("secret", base64_encode(credentials.secret)); + return scope; +} + +JsonScope &operator+(JsonValueScope &scope, const SecureFileCredentials &credentials) { + auto object = scope.enter_object(); + object << ctie("file_hash", base64_encode(credentials.hash)); + object << ctie("secret", base64_encode(credentials.secret)); + return scope; +} + +JsonScope &operator+(JsonValueScope &scope, const vector &files) { + auto arr = scope.enter_array(); + for (auto &file : files) { + arr << as_jsonable(file); + } + return scope; +} + +JsonScope &operator+(JsonValueScope &scope, const SecureValueCredentials &credentials) { + auto object = scope.enter_object(); + if (credentials.data) { + object << ctie("data", as_jsonable(credentials.data.value())); + } + if (!credentials.files.empty()) { + object << ctie("files", as_jsonable(credentials.files)); + } + if (credentials.selfie) { + object << ctie("selfie", as_jsonable(credentials.selfie.value())); + } + return scope; +} + +Slice secure_value_type_as_slice(SecureValueType type) { + switch (type) { + case SecureValueType::PersonalDetails: + return "personal_details"; + case SecureValueType::Passport: + return "passport"; + case SecureValueType::DriverLicense: + return "driver_license"; + case SecureValueType::IdentityCard: + return "identity_card"; + case SecureValueType::Address: + return "address"; + case SecureValueType::UtilityBill: + return "utility_bill"; + case SecureValueType::BankStatement: + return "bank_statement"; + case SecureValueType::RentalAgreement: + return "rental_agreement"; + case SecureValueType::PhoneNumber: + return "phone_number"; + case SecureValueType::EmailAddress: + return "email_address"; + default: + case SecureValueType::None: + UNREACHABLE(); + return "none"; + } +} + +JsonScope &operator+(JsonValueScope &scope, const std::vector &credentials) { + auto object = scope.enter_object(); + for (auto &c : credentials) { + object << ctie(secure_value_type_as_slice(c.type), as_jsonable(c)); + } + return scope; +} + +JsonScope &operator+(JsonValueScope &scope, + const std::pair &, const Slice &> &credentials) { + auto object = scope.enter_object(); + object << ctie("secure_data", as_jsonable(credentials.first)); + object << ctie("payload", credentials.second); + return scope; +} + +Result encrypted_credentials(std::vector &credentials, + Slice payload, Slice public_key) { + auto encoded_credentials = json_encode(as_jsonable(ctie(credentials, payload))); + LOG(ERROR) << encoded_credentials; + + auto secret = secure_storage::Secret::create_new(); + auto encrypted_value = secure_storage::encrypt_value(secret, encoded_credentials).move_as_ok(); + EncryptedSecureCredentials res; + res.data = encrypted_value.data.as_slice().str(); + res.hash = encrypted_value.data.as_slice().str(); + TRY_RESULT(encrypted_secret, rsa_encrypt_pkcs1_oaep(public_key, secret.as_slice())); + res.encrypted_secret = encrypted_secret.as_slice().str(); + return res; +} } // namespace td diff --git a/td/telegram/SecureValue.h b/td/telegram/SecureValue.h index 2f6ebf91d..6eb6c3352 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/JsonBuilder.h" #include "td/utils/optional.h" #include "td/utils/Status.h" @@ -39,6 +40,8 @@ SecureValueType get_secure_value_type_td_api(tl_object_ptr get_secure_value_types( vector> &&secure_value_types); +vector get_secure_value_types_td_api( + vector> &&secure_value_types); td_api::object_ptr get_passport_data_type_object(SecureValueType type); td_api::object_ptr get_secure_value_type_telegram_object(SecureValueType type); @@ -116,18 +119,42 @@ telegram_api::object_ptr get_input_secure_value_ vector> get_encrypted_passport_data_object( FileManager *file_manager, const vector &values); -struct SecureCredentials { +struct EncryptedSecureCredentials { string data; string hash; string encrypted_secret; }; -bool operator==(const SecureCredentials &lhs, const SecureCredentials &rhs); -bool operator!=(const SecureCredentials &lhs, const SecureCredentials &rhs); +bool operator==(const EncryptedSecureCredentials &lhs, const EncryptedSecureCredentials &rhs); +bool operator!=(const EncryptedSecureCredentials &lhs, const EncryptedSecureCredentials &rhs); -SecureCredentials get_secure_credentials(tl_object_ptr &&credentials); +EncryptedSecureCredentials get_secure_credentials( + tl_object_ptr &&credentials); -td_api::object_ptr get_encrypted_credentials_object(const SecureCredentials &credentials); +telegram_api::object_ptr get_secure_credentials_encrypted_object( + const EncryptedSecureCredentials &credentials); +td_api::object_ptr get_encrypted_credentials_object( + const EncryptedSecureCredentials &credentials); + +struct SecureDataCredentials { + string hash; + string secret; +}; +struct SecureFileCredentials { + string hash; + string secret; +}; + +struct SecureValueCredentials { + SecureValueType type; + string hash; + optional data; + std::vector files; + optional selfie; +}; + +Result encrypted_credentials(std::vector &credentials, + Slice payload, Slice public_key); class SecureValue { public: @@ -137,18 +164,26 @@ class SecureValue { FileId selfie; }; +struct SecureValueWithCredentials { + SecureValue value; + SecureValueCredentials credentials; +}; + Result get_secure_value(FileManager *file_manager, td_api::object_ptr &&input_passport_data); td_api::object_ptr get_passport_data_object(FileManager *file_manager, const SecureValue &value); -Result decrypt_secure_file(FileManager *file_manager, const secure_storage::Secret &secret, - const EncryptedSecureFile &secure_file); -Result> decrypt_secure_files(FileManager *file_manager, const secure_storage::Secret &secret, - const vector &secure_file); -Result decrypt_secure_data(const secure_storage::Secret &secret, const EncryptedSecureData &secure_data); -Result decrypt_encrypted_secure_value(FileManager *file_manager, const secure_storage::Secret &secret, - const EncryptedSecureValue &encrypted_secure_value); +Result> decrypt_secure_file(FileManager *file_manager, + const secure_storage::Secret &secret, + const EncryptedSecureFile &secure_file); +Result, vector>> decrypt_secure_files( + FileManager *file_manager, const secure_storage::Secret &secret, const vector &secure_file); +Result> decrypt_secure_data(const secure_storage::Secret &secret, + const EncryptedSecureData &secure_data); +Result decrypt_encrypted_secure_value(FileManager *file_manager, + const secure_storage::Secret &secret, + const EncryptedSecureValue &encrypted_secure_value); EncryptedSecureFile encrypt_secure_file(FileManager *file_manager, const secure_storage::Secret &master_secret, FileId file, string &to_hash); diff --git a/td/telegram/SecureValue.hpp b/td/telegram/SecureValue.hpp index fc209043f..d1105d4eb 100644 --- a/td/telegram/SecureValue.hpp +++ b/td/telegram/SecureValue.hpp @@ -43,14 +43,14 @@ void parse(EncryptedSecureData &data, ParserT &parser) { } template -void store(const SecureCredentials &credentials, StorerT &storer) { +void store(const EncryptedSecureCredentials &credentials, StorerT &storer) { store(credentials.data, storer); store(credentials.hash, storer); store(credentials.encrypted_secret, storer); } template -void parse(SecureCredentials &credentials, ParserT &parser) { +void parse(EncryptedSecureCredentials &credentials, ParserT &parser) { parse(credentials.data, parser); parse(credentials.hash, parser); parse(credentials.encrypted_secret, parser); diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index 52699871e..2534d00b1 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -6902,15 +6902,27 @@ void Td::on_request(uint64 id, td_api::getPassportAuthorizationForm &request) { CLEAN_INPUT_STRING(request.password_); CLEAN_INPUT_STRING(request.public_key_); CLEAN_INPUT_STRING(request.scope_); + CLEAN_INPUT_STRING(request.payload_); CREATE_REQUEST_PROMISE(promise); send_closure(secure_manager_, &SecureManager::get_passport_authorization_form, request.password_, request.bot_id_, - request.scope_, request.public_key_, std::move(promise)); + request.scope_, request.public_key_, request.payload_, std::move(promise)); } -void Td::on_request(uint64 id, const td_api::sendPassportAuthorizationForm &request) { +void Td::on_request(uint64 id, td_api::sendPassportAuthorizationForm &request) { CHECK_AUTH(); CHECK_IS_USER(); - LOG(FATAL) << "TODO"; + CLEAN_INPUT_STRING(request.password_); + CREATE_REQUEST_PROMISE(promise); + auto query_promise = PromiseCreator::lambda([promise = std::move(promise)](Result<> result) mutable { + if (result.is_error()) { + promise.set_error(result.move_as_error()); + } else { + promise.set_value(make_tl_object()); + } + }); + send_closure(secure_manager_, &SecureManager::send_passport_authorization_form, request.password_, + request.autorization_form_id_, get_secure_value_types_td_api(std::move(request.types_)), + std::move(query_promise)); } void Td::on_request(uint64 id, const td_api::getSupportUser &request) { diff --git a/td/telegram/Td.h b/td/telegram/Td.h index 393380028..1f7c1fad5 100644 --- a/td/telegram/Td.h +++ b/td/telegram/Td.h @@ -769,7 +769,7 @@ class Td final : public NetQueryCallback { void on_request(uint64 id, td_api::getPassportAuthorizationForm &request); - void on_request(uint64 id, const td_api::sendPassportAuthorizationForm &request); + void on_request(uint64 id, td_api::sendPassportAuthorizationForm &request); void on_request(uint64 id, const td_api::getSupportUser &request); diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index cbd6d0228..2b1f678f8 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -936,7 +936,7 @@ class CliClient final : public Actor { return nullptr; } - static tl_object_ptr as_passport_data_type(string passport_data_type) { + static tl_object_ptr as_passport_data_type(Slice passport_data_type) { if (passport_data_type == "address" || passport_data_type == "a") { return make_tl_object(); } @@ -952,6 +952,10 @@ class CliClient final : public Actor { return make_tl_object(); } + static auto as_passport_data_types(Slice types, char delimiter = ',') { + return transform(full_split(types, delimiter), [](Slice str) { return as_passport_data_type(str); }); + } + static tl_object_ptr as_input_passport_data(string passport_data_type, string file) { vector> files; LOG(ERROR) << "FILE " << file; @@ -1091,9 +1095,18 @@ class CliClient final : public Actor { string bot_id = query.arg("bot_id").str(); string scope = query.arg("scope").str(); string public_key = query.arg("public_key").str(); - send_request( - make_tl_object(to_integer(bot_id), scope, public_key, password)); + string payload = query.arg("payload").str(); + LOG(ERROR) << query.arg("callback_url"); + send_request(make_tl_object(to_integer(bot_id), scope, public_key, + payload, password)); } else if (op == "spaf") { + string password; + string id; + string types; + std::tie(password, args) = split(args); + std::tie(id, types) = split(args); + send_request(make_tl_object(to_integer(id), + as_passport_data_types(types), password)); } else if (op == "srea" || op == "SetRecoveryEmailAddress") { string password; string recovery_email_address; diff --git a/tdutils/td/utils/Status.h b/tdutils/td/utils/Status.h index 8ef2846df..b9248984a 100644 --- a/tdutils/td/utils/Status.h +++ b/tdutils/td/utils/Status.h @@ -401,6 +401,10 @@ class Result { CHECK(status_.is_ok()) << status_; return value_; } + const T &ok_ref() const { + CHECK(status_.is_ok()) << status_; + return value_; + } T move_as_ok() { CHECK(status_.is_ok()) << status_; return std::move(value_); diff --git a/tdutils/td/utils/optional.h b/tdutils/td/utils/optional.h index 450b60f94..8b74f43b3 100644 --- a/tdutils/td/utils/optional.h +++ b/tdutils/td/utils/optional.h @@ -19,12 +19,15 @@ class optional { template optional(T1 &&t) : impl_(std::forward(t)) { } - explicit operator bool() { + explicit operator bool() const { return impl_.is_ok(); } T &value() { return impl_.ok_ref(); } + const T &value() const { + return impl_.ok_ref(); + } T &operator*() { return value(); }