From de9f167bffc4805883631ccdaf89d21b2e338c96 Mon Sep 17 00:00:00 2001 From: levlam Date: Sun, 10 Feb 2019 23:16:52 +0300 Subject: [PATCH] Add checkRecoveryEmailAddressCode method. GitOrigin-RevId: 9601d8227586f988dae26ffb230c6f12f0196193 --- td/generate/scheme/td_api.tl | 15 ++++++---- td/generate/scheme/td_api.tlo | Bin 143972 -> 144068 bytes td/telegram/PasswordManager.cpp | 48 ++++++++++++++++++++++++++------ td/telegram/PasswordManager.h | 14 ++++++++-- td/telegram/Td.cpp | 8 ++++++ td/telegram/Td.h | 2 ++ td/telegram/cli.cpp | 6 ++-- 7 files changed, 75 insertions(+), 18 deletions(-) diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index 081b63a79..78e0fa54c 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -109,8 +109,10 @@ authorizationStateClosing = AuthorizationState; authorizationStateClosed = AuthorizationState; -//@description Represents the current state of 2-step verification @has_password True, if a 2-step verification password is set @password_hint Hint for the password; can be empty @has_recovery_email_address True, if a recovery email is set @has_passport_data True, if some Telegram Passport elements were saved @unconfirmed_recovery_email_address_pattern Pattern of the email address to which the confirmation email was sent -passwordState has_password:Bool password_hint:string has_recovery_email_address:Bool has_passport_data:Bool unconfirmed_recovery_email_address_pattern:string = PasswordState; +//@description Represents the current state of 2-step verification @has_password True, if a 2-step verification password is set @password_hint Hint for the password; can be empty +//@has_recovery_email_address True, if a recovery email is set @has_passport_data True, if some Telegram Passport elements were saved +//@recovery_email_address_code_info Information about the recovery email address to which the confirmation email was sent; may be null +passwordState has_password:Bool password_hint:string has_recovery_email_address:Bool has_passport_data:Bool recovery_email_address_code_info:emailAddressAuthenticationCodeInfo = PasswordState; //@description Contains information about the current recovery email address @recovery_email_address Recovery email address recoveryEmailAddress recovery_email_address:string = RecoveryEmailAddress; @@ -2585,17 +2587,20 @@ setDatabaseEncryptionKey new_encryption_key:bytes = Ok; //@description Returns the current state of 2-step verification getPasswordState = PasswordState; -//@description Changes the password for the user. If a new recovery email address is specified, then the error EMAIL_UNCONFIRMED is returned and the password change will not be applied until the new recovery email address has been confirmed. The application should periodically call getPasswordState to check whether the new email address has been confirmed +//@description Changes the password for the user. If a new recovery email address is specified, then the change will not be applied until the new recovery email address is confirmed //@old_password Previous password of the user @new_password New password of the user; may be empty to remove the password @new_hint New password hint; may be empty @set_recovery_email_address Pass true if the recovery email address should be changed @new_recovery_email_address New recovery email address; may be empty setPassword old_password:string new_password:string new_hint:string set_recovery_email_address:Bool new_recovery_email_address:string = PasswordState; -//@description Returns a recovery email address that was previously set up. This method can be used to verify a password provided by the user @password The password for the current user +//@description Returns a 2-step verification recovery email address that was previously set up. This method can be used to verify a password provided by the user @password The password for the current user getRecoveryEmailAddress password:string = RecoveryEmailAddress; -//@description Changes the recovery email address of the user. If a new recovery email address is specified, then the error EMAIL_UNCONFIRMED is returned and the email address will not be changed until the new email has been confirmed. The application should periodically call getPasswordState to check whether the email address has been confirmed. +//@description Changes the 2-step verification recovery email address of the user. If a new recovery email address is specified, then the change will not be applied until the new recovery email address is confirmed //-If new_recovery_email_address is the same as the email address that is currently set up, this call succeeds immediately and aborts all other requests waiting for an email confirmation @password Password of the current user @new_recovery_email_address New recovery email address setRecoveryEmailAddress password:string new_recovery_email_address:string = PasswordState; +//@description Checks the 2-step verification recovery email address code @code Verification code +checkRecoveryEmailAddressCode code:string = Ok; + //@description Requests to send a password recovery code to an email address that was previously set up requestPasswordRecovery = EmailAddressAuthenticationCodeInfo; diff --git a/td/generate/scheme/td_api.tlo b/td/generate/scheme/td_api.tlo index a4145075a9be48c6bf588e5d399f4c464eada4c7..ac689d677e62d9cc145f4fae8a6ec4aedaebb6ac 100644 GIT binary patch delta 242 zcmaFzgyYCljtvQ%6Q_u5F5$ev#}ccry?b+j#D-rIAQo>yVsUYKeo;zrNn%MV0|Q8G zx`Z&}9!7=f4}}@Ub&~T_QsXo8(()M~fWx-!pz@>HE{srqku#ePNDQQLyMhQ~M+2kN z_LWl@mkV)a9697Co1BrFoIUxXl*n|wWsF|i1C}$2n1XG-c}&O$WCn@>HFp?Sh=QFs q{lrH`3ovVY$|uGHIuJn(d8RiImV^S+2MCKtktqYButJgPjQ{`!*HIh* delta 208 zcmX@|l;g=0jtvQ%lV7NaY%bxv!N=ly@zM6p0TLU2$%0tC1&PJQ<@rS^!6k_$sSFGt zv75()d|0O+^kmeZ?jy|D!J}20mzeZz7_5mO165ez_3fGE77$n-`407lAMMF0Q* diff --git a/td/telegram/PasswordManager.cpp b/td/telegram/PasswordManager.cpp index 9b65e6bd6..51b260e48 100644 --- a/td/telegram/PasswordManager.cpp +++ b/td/telegram/PasswordManager.cpp @@ -181,7 +181,8 @@ void PasswordManager::get_secure_secret(string password, Promise promise) { +void PasswordManager::do_get_secure_secret(bool allow_recursive, string password, + Promise promise) { if (secret_) { return promise.set_value(secret_.value().clone()); } @@ -189,7 +190,7 @@ void PasswordManager::do_get_secure_secret(bool recursive, string password, Prom return promise.set_error(Status::Error(400, "PASSWORD_HASH_INVALID")); } get_full_state( - password, PromiseCreator::lambda([password, recursive, promise = std::move(promise), + password, PromiseCreator::lambda([password, allow_recursive, promise = std::move(promise), actor_id = actor_id(this)](Result r_state) mutable { if (r_state.is_error()) { return promise.set_error(r_state.move_as_error()); @@ -202,7 +203,7 @@ void PasswordManager::do_get_secure_secret(bool recursive, string password, Prom send_closure(actor_id, &PasswordManager::cache_secret, state.private_state.secret.value().clone()); return promise.set_value(std::move(state.private_state.secret.value())); } - if (!recursive) { + if (!allow_recursive) { return promise.set_error(Status::Error(400, "Failed to get Telegram Passport secret")); } @@ -379,6 +380,19 @@ void PasswordManager::get_recovery_email_address(string password, })); } +void PasswordManager::check_recovery_email_address_code(string code, Promise promise) { + auto query = + G()->net_query_creator().create(create_storer(telegram_api::account_confirmPasswordEmail(std::move(code)))); + send_with_promise(std::move(query), + PromiseCreator::lambda([promise = std::move(promise)](Result r_query) mutable { + auto r_result = fetch_result(std::move(r_query)); + if (r_result.is_error()) { + return promise.set_error(r_result.move_as_error()); + } + return promise.set_value(Unit()); + })); +} + void PasswordManager::send_email_address_verification_code( string email, Promise> promise) { last_verified_email_address_ = email; @@ -457,8 +471,7 @@ void PasswordManager::update_password_settings(UpdateSettings update_settings, P return promise.set_error(r_update_settings.move_as_error()); } if (!r_update_settings.ok()) { - promise.set_error(Status::Error(5, "account_updatePasswordSettings returned false")); - return; + return promise.set_error(Status::Error(5, "account_updatePasswordSettings returned false")); } send_closure(actor_id, &PasswordManager::get_state, std::move(promise)); }); @@ -557,11 +570,17 @@ void PasswordManager::do_update_password_settings_impl(UpdateSettings update_set auto query = G()->net_query_creator().create( create_storer(telegram_api::account_updatePasswordSettings(std::move(current_hash), std::move(new_settings)))); - send_with_promise(std::move(query), - PromiseCreator::lambda([promise = std::move(promise)](Result r_query) mutable { + send_with_promise(std::move(query), PromiseCreator::lambda([actor_id = actor_id(this), promise = std::move(promise)]( + Result r_query) mutable { auto r_result = fetch_result(std::move(r_query)); if (r_result.is_error()) { - if (r_result.error().code() == 400 && r_result.error().message() == "EMAIL_UNCONFIRMED") { + Slice prefix("EMAIL_UNCONFIRMED"); + Slice message = r_result.error().message(); + if (r_result.error().code() == 400 && begins_with(message, prefix)) { + if (message.size() >= prefix.size() + 2 && message[prefix.size()] == '_') { + send_closure(actor_id, &PasswordManager::on_get_code_length, + to_integer(message.substr(prefix.size() + 1))); + } return promise.set_value(true); } return promise.set_error(r_result.move_as_error()); @@ -570,6 +589,16 @@ void PasswordManager::do_update_password_settings_impl(UpdateSettings update_set })); } +void PasswordManager::on_get_code_length(int32 code_length) { + if (code_length <= 0 || code_length > 100) { + LOG(ERROR) << "Receive invalid code length " << code_length; + return; + } + + LOG(INFO) << "Set code length to " << code_length; + last_code_length_ = code_length; +} + void PasswordManager::get_state(Promise promise) { do_get_state(PromiseCreator::lambda([promise = std::move(promise)](Result r_state) mutable { if (r_state.is_error()) { @@ -582,7 +611,7 @@ void PasswordManager::get_state(Promise promise) { void PasswordManager::do_get_state(Promise promise) { auto query = G()->net_query_creator().create(create_storer(telegram_api::account_getPassword())); send_with_promise( - std::move(query), PromiseCreator::lambda([actor_id = actor_id(this), + std::move(query), PromiseCreator::lambda([actor_id = actor_id(this), code_length = last_code_length_, promise = std::move(promise)](Result r_query) mutable { auto r_result = fetch_result(std::move(r_query)); if (r_result.is_error()) { @@ -623,6 +652,7 @@ void PasswordManager::do_get_state(Promise promise) { send_closure(actor_id, &PasswordManager::drop_cached_secret); } state.unconfirmed_recovery_email_address_pattern = std::move(password->email_unconfirmed_pattern_); + state.code_length = code_length; CHECK(password->new_algo_ != nullptr); switch (password->new_algo_->get_id()) { diff --git a/td/telegram/PasswordManager.h b/td/telegram/PasswordManager.h index 0f3cf4d83..3facd25f5 100644 --- a/td/telegram/PasswordManager.h +++ b/td/telegram/PasswordManager.h @@ -66,6 +66,7 @@ class PasswordManager : public NetQueryCallback { string recovery_email_address, Promise promise); void set_recovery_email_address(string password, string new_recovery_email_address, Promise promise); void get_recovery_email_address(string password, Promise> promise); + void check_recovery_email_address_code(string code, Promise promise); void send_email_address_verification_code( string email, Promise> promise); @@ -96,6 +97,7 @@ class PasswordManager : public NetQueryCallback { bool has_recovery_email_address = false; bool has_secure_values = false; string unconfirmed_recovery_email_address_pattern; + int32 code_length = 0; string current_client_salt; string current_server_salt; @@ -111,8 +113,13 @@ class PasswordManager : public NetQueryCallback { string new_secure_salt; State as_td_api() const { + td_api::object_ptr code_info; + if (!unconfirmed_recovery_email_address_pattern.empty()) { + code_info = td_api::make_object( + unconfirmed_recovery_email_address_pattern, code_length); + } return td_api::make_object(has_password, password_hint, has_recovery_email_address, - has_secure_values, unconfirmed_recovery_email_address_pattern); + has_secure_values, std::move(code_info)); } }; @@ -147,6 +154,8 @@ class PasswordManager : public NetQueryCallback { string last_verified_email_address_; + int32 last_code_length_ = 0; + static Result decrypt_secure_secret( Slice password, tl_object_ptr algo_ptr, Slice secret, int64 secret_id); @@ -162,9 +171,10 @@ class PasswordManager : public NetQueryCallback { void do_update_password_settings(UpdateSettings update_settings, PasswordFullState full_state, Promise promise); void do_update_password_settings_impl(UpdateSettings update_settings, PasswordState state, PasswordPrivateState private_state, Promise promise); + void on_get_code_length(int32 code_length); void do_get_state(Promise promise); void get_full_state(string password, Promise promise); - void do_get_secure_secret(bool recursive, string passwod, Promise promise); + void do_get_secure_secret(bool allow_recursive, string password, Promise promise); void do_get_full_state(string password, PasswordState state, Promise promise); void cache_secret(secure_storage::Secret secret); void drop_cached_secret(); diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index e7b1075d4..fb05f3337 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -4650,6 +4650,14 @@ void Td::on_request(uint64 id, td_api::getRecoveryEmailAddress &request) { std::move(promise)); } +void Td::on_request(uint64 id, td_api::checkRecoveryEmailAddressCode &request) { + CHECK_IS_USER(); + CLEAN_INPUT_STRING(request.code_); + CREATE_OK_REQUEST_PROMISE(); + send_closure(password_manager_, &PasswordManager::check_recovery_email_address_code, request.code_, + std::move(promise)); +} + void Td::on_request(uint64 id, td_api::requestPasswordRecovery &request) { CHECK_IS_USER(); CREATE_REQUEST_PROMISE(); diff --git a/td/telegram/Td.h b/td/telegram/Td.h index b536ee700..10259a45f 100644 --- a/td/telegram/Td.h +++ b/td/telegram/Td.h @@ -377,6 +377,8 @@ class Td final : public NetQueryCallback { void on_request(uint64 id, td_api::setRecoveryEmailAddress &request); + void on_request(uint64 id, td_api::checkRecoveryEmailAddressCode &request); + void on_request(uint64 id, td_api::requestPasswordRecovery &request); void on_request(uint64 id, td_api::recoverPassword &request); diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index 159701444..bd30128f9 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -1360,6 +1360,10 @@ class CliClient final : public Actor { string recovery_email_address; std::tie(password, recovery_email_address) = split(args); send_request(make_tl_object(password, recovery_email_address)); + } else if (op == "grea" || op == "GetRecoveryEmailAddress") { + send_request(make_tl_object(args)); + } else if (op == "creac") { + send_request(make_tl_object(args)); } else if (op == "spncc") { send_request(make_tl_object(args, false, false)); } else if (op == "cpncc") { @@ -1370,8 +1374,6 @@ class CliClient final : public Actor { send_request(make_tl_object()); } else if (op == "rp" || op == "RecoverPassword") { send_request(make_tl_object(args)); - } else if (op == "grea" || op == "GetRecoveryEmailAddress") { - send_request(make_tl_object(args)); } else if (op == "gtp" || op == "GetTemporaryPassword") { send_request(make_tl_object()); } else if (op == "ctp" || op == "CreateTemporaryPassword") {