From 2f5ca11592f337e3b1540e6c8fb6c8eaedc815ee Mon Sep 17 00:00:00 2001 From: Arseny Smirnov Date: Fri, 6 Apr 2018 16:24:29 +0300 Subject: [PATCH] getAuthorizationForm GitOrigin-RevId: 3b432a32cb4af7a35dc7d000e8cfceed97400c1d --- td/generate/scheme/td_api.tl | 8 +-- td/generate/scheme/td_api.tlo | Bin 116800 -> 116972 bytes td/telegram/SecureManager.cpp | 118 +++++++++++++++++++++++++++++++++- td/telegram/SecureManager.h | 14 ++++ td/telegram/SecureStorage.cpp | 3 +- td/telegram/SecureValue.cpp | 3 + td/telegram/Td.cpp | 5 +- td/telegram/cli.cpp | 28 ++++++++ 8 files changed, 172 insertions(+), 7 deletions(-) diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index 55c936f02..ebbded991 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -838,7 +838,7 @@ inputPassportData type:PassportDataType data:string files:vector self //@description Contains information about requested Telegram Passport authorization form @id Authorization form unique identifier @data Available data -passportAuthorizationForm id:int32 data:vector = PassportAuthorizationForm; +passportAuthorizationForm id:int32 data:vector selfie_required:Bool privacy_policy_url:string = PassportAuthorizationForm; //@description Contains an encrypted Telegram Passport data credentials @data The encrypted credentials @hash The decrypted data hash @secret Encrypted by service public key secret for data decryption @@ -2909,11 +2909,11 @@ resendEmailAddressVerificationCode = EmailAddressAuthenticationCodeInfo; 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 -getPassportAuthorizationForm bot_id:int32 scope:string public_key:string = PassportAuthorizationForm; +//@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; //@description Sends Telegram Passport authorization form, effectively sharing data with the service @autorization_form_id Authorization form identifier -sendPassportAuthorizationForm autorization_form_id:int32 = Ok; +sendPassportAuthorizationForm autorization_form_id:int32 types:vector = 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 ed1aea7e3d4514faa771805a5f9c0509b0639501..26a8ba62e24597a932ceb892f0da4ad9983716fd 100644 GIT binary patch delta 195 zcmX>wf&I-y_6=7ASW_=+U6P#6Q^P2|`HR4X{cK=WKPNM}am}&aom5j!d71CKJ7w#~h=Ef+n-D4Hw4_N@`;ZKSH delta 158 zcmaDek^R5~_6=7ASQpyazm%LFxQbDF^A~{&``N(!g6WAhj8dE+_RV8LK1`D@#;Z(z zxkFjPrsfg@BLf5!IkV|-*tQ)6soK2Y;*M1usZE6iGU=%$VB@$LVA`3dx7IMGPkx}v r!2%N6E>p{>qs!8@`|8!{KC2it7#XLRu3|Kvp5V$TvHi;`#vif(Q?xxZ diff --git a/td/telegram/SecureManager.cpp b/td/telegram/SecureManager.cpp index 05e56459e..a30c95ca4 100644 --- a/td/telegram/SecureManager.cpp +++ b/td/telegram/SecureManager.cpp @@ -84,7 +84,7 @@ SetSecureValue::UploadCallback::UploadCallback(ActorId actor_id) } void SetSecureValue::UploadCallback::on_upload_ok(FileId file_id, tl_object_ptr input_file) { - UNREACHABLE(); + send_closure(actor_id_, &SetSecureValue::on_upload_ok, file_id, nullptr); } void SetSecureValue::UploadCallback::on_upload_encrypted_ok( FileId file_id, tl_object_ptr input_file) { @@ -246,6 +246,104 @@ void SetSecureValue::merge(FileManager *file_manager, FileId file_id, SecureFile LOG_IF(ERROR, status.is_error()) << status.error(); } +class GetPassportAuthorizationForm : public NetQueryCallback { + public: + GetPassportAuthorizationForm(ActorShared<> parent, string password, int32 authorization_form_id, int32 bot_id, + string scope, string public_key, Promise promise) + : parent_(std::move(parent)) + , password_(std::move(password)) + , authorization_form_id_(authorization_form_id) + , bot_id_(bot_id) + , scope_(std::move(scope)) + , public_key_(std::move(public_key)) + , promise_(std::move(promise)) { + } + + private: + ActorShared<> parent_; + string password_; + int32 authorization_form_id_; + int32 bot_id_; + string scope_; + string public_key_; + Promise promise_; + optional secret_; + telegram_api::object_ptr authorization_form_; + + 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 on_error(Status status) { + promise_.set_error(std::move(status)); + stop(); + } + + void start_up() override { + auto account_get_authorization_form = + telegram_api::account_getAuthorizationForm(bot_id_, std::move(scope_), std::move(public_key_)); + auto query = G()->net_query_creator().create(create_storer(account_get_authorization_form)); + 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, &GetPassportAuthorizationForm::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()); + } + authorization_form_ = r_result.move_as_ok(); + loop(); + } + + void loop() override { + if (!secret_ || !authorization_form_) { + return; + } + auto *file_manager = G()->file_manager().get_actor_unsafe(); + std::vector values; + auto types = get_secure_value_types(std::move(authorization_form_->required_types_)); + for (auto type : types) { + optional encrypted_secure_value; + for (auto &value : authorization_form_->values_) { + auto value_type = get_secure_value_type(std::move(value->type_)); + if (value_type != type) { + continue; + } + encrypted_secure_value = get_encrypted_secure_value(file_manager, std::move(value)); + break; + } + + SecureValue secure_value; + secure_value.type = type; + if (encrypted_secure_value) { + 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(); + } else { + LOG(ERROR) << "Failed to decrypt secure value: " << r_secure_value.error(); + } + } + values.push_back(get_passport_data_object(file_manager, std::move(secure_value))); + } + promise_.set_value(make_tl_object(authorization_form_id_, std::move(values), + authorization_form_->selfie_required_, + authorization_form_->privacy_policy_url_)); + stop(); + } +}; + SecureManager::SecureManager(ActorShared<> parent) : parent_(std::move(parent)) { } @@ -262,6 +360,24 @@ void SecureManager::set_secure_value(string password, SecureValue secure_value, std::move(secure_value), std::move(promise)); } +void SecureManager::get_passport_authorization_form(string password, int32 bot_id, string scope, string public_key, + Promise promise) { + refcnt_++; + auto authorization_form_id = ++authorization_form_id_; + authorization_forms_[authorization_form_id] = AuthorizationForm{bot_id, public_key}; + create_actor("GetPassportAuthorizationForm", actor_shared(), std::move(password), + authorization_form_id, bot_id, std::move(scope), std::move(public_key), + std::move(promise)) + .release(); +} + +void SecureManager::send_passport_authorization_form(string password, int32 authorization_form_id, + std::vector types, Promise<> promise) { + auto it = authorization_forms_.find(authorization_form_id); + if (it == authorization_forms_.end()) { + return promise.set_error(Status::Error(400, "Unknown authorization_form_id")); + } +} void SecureManager::hangup() { dec_refcnt(); } diff --git a/td/telegram/SecureManager.h b/td/telegram/SecureManager.h index 5b5578b62..e870e90c2 100644 --- a/td/telegram/SecureManager.h +++ b/td/telegram/SecureManager.h @@ -17,6 +17,7 @@ namespace td { 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); @@ -93,11 +94,24 @@ class SecureManager : public Actor { 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, + Promise promise); + void send_passport_authorization_form(string password, int32 authorization_form_id, + std::vector types, Promise<> promise); + private: ActorShared<> parent_; int32 refcnt_{1}; std::map> set_secure_value_queries_; + struct AuthorizationForm { + int32 bot_id; + string public_key; + }; + + std::map authorization_forms_; + int32 authorization_form_id_{0}; + void hangup() override; void hangup_shared() override; void dec_refcnt(); diff --git a/td/telegram/SecureStorage.cpp b/td/telegram/SecureStorage.cpp index c14c8675b..4073440a2 100644 --- a/td/telegram/SecureStorage.cpp +++ b/td/telegram/SecureStorage.cpp @@ -17,7 +17,8 @@ namespace secure_storage { Result ValueHash::create(Slice data) { UInt256 hash; if (data.size() != ::td::as_slice(hash).size()) { - return Status::Error("Wrong hash size"); + LOG(FATAL); + return Status::Error(PSLICE() << "Wrong hash size " << data.size()); } ::td::as_slice(hash).copy_from(data); return ValueHash{hash}; diff --git a/td/telegram/SecureValue.cpp b/td/telegram/SecureValue.cpp index 15df93016..233ce5f05 100644 --- a/td/telegram/SecureValue.cpp +++ b/td/telegram/SecureValue.cpp @@ -405,6 +405,9 @@ td_api::object_ptr get_passport_data_object(FileManager *f Result decrypt_secure_file(FileManager *file_manager, const secure_storage::Secret &master_secret, const SecureFile &secure_file) { + if (!secure_file.file_id.is_valid()) { + return secure_file.file_id; + } TRY_RESULT(hash, secure_storage::ValueHash::create(secure_file.file_hash)); TRY_RESULT(encrypted_secret, secure_storage::EncryptedSecret::create(secure_file.encrypted_secret)); TRY_RESULT(secret, encrypted_secret.decrypt(PSLICE() << master_secret.as_slice() << hash.as_slice())); diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index 3563f1510..52699871e 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -6899,9 +6899,12 @@ void Td::on_request(uint64 id, td_api::checkEmailAddressVerificationCode &reques void Td::on_request(uint64 id, td_api::getPassportAuthorizationForm &request) { CHECK_AUTH(); CHECK_IS_USER(); + CLEAN_INPUT_STRING(request.password_); CLEAN_INPUT_STRING(request.public_key_); CLEAN_INPUT_STRING(request.scope_); - LOG(FATAL) << "TODO"; + 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)); } void Td::on_request(uint64 id, const td_api::sendPassportAuthorizationForm &request) { diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index 4aa0c849f..cbd6d0228 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -15,6 +15,8 @@ #include "memprof/memprof.h" +#include "td/net/HttpReader.h" + #include "td/utils/buffer.h" #include "td/utils/BufferedFd.h" #include "td/utils/FileLog.h" @@ -944,8 +946,12 @@ class CliClient final : public Actor { if (passport_data_type == "phone" || passport_data_type == "p") { return make_tl_object(); } + if (passport_data_type == "pd") { + return make_tl_object(); + } return make_tl_object(); } + static tl_object_ptr as_input_passport_data(string passport_data_type, string file) { vector> files; LOG(ERROR) << "FILE " << file; @@ -960,6 +966,8 @@ class CliClient final : public Actor { data = "{todo}"; } else if (passport_data_type == "phone" || passport_data_type == "p") { data = "{todo}"; + } else if (passport_data_type == "pd") { + data = "{todo}"; } else { data = "I am cucumber"; } @@ -1066,6 +1074,26 @@ class CliClient final : public Actor { recovery_email_address = ""; } send_request(make_tl_object(password, new_password, new_hint, true, recovery_email_address)); + } else if (op == "secureid") { + string password; + std::tie(password, args) = split(args); + ChainBufferWriter writer; + writer.append(PSLICE() << "GET " << args << " HTTP/1.1\r\n\r\n\r\n"); + ChainBufferReader reader = writer.extract_reader(); + HttpReader http_reader; + http_reader.init(&reader); + HttpQuery query; + auto status = http_reader.read_next(&query); + if (status.is_error()) { + LOG(ERROR) << status.error(); + return; + } + 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)); + } else if (op == "spaf") { } else if (op == "srea" || op == "SetRecoveryEmailAddress") { string password; string recovery_email_address;