// // Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2021 // // 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/telegram/net/NetQuery.h" #include "td/telegram/NewPasswordState.h" #include "td/telegram/SecureStorage.h" #include "td/telegram/td_api.h" #include "td/telegram/telegram_api.h" #include "td/actor/actor.h" #include "td/actor/PromiseFuture.h" #include "td/utils/buffer.h" #include "td/utils/common.h" #include "td/utils/Container.h" #include "td/utils/optional.h" #include "td/utils/Slice.h" #include "td/utils/Status.h" #include "td/utils/tl_helpers.h" namespace td { struct TempPasswordState { bool has_temp_password = false; string temp_password; int32 valid_until = 0; // unix_time tl_object_ptr get_temporary_password_state_object() const; template void store(StorerT &storer) const { using ::td::store; CHECK(has_temp_password); store(temp_password, storer); store(valid_until, storer); } template void parse(ParserT &parser) { using ::td::parse; has_temp_password = true; parse(temp_password, parser); parse(valid_until, parser); } }; class PasswordManager : public NetQueryCallback { public: using State = tl_object_ptr; using TempState = tl_object_ptr; using PasswordInputSettings = tl_object_ptr; explicit PasswordManager(ActorShared<> parent) : parent_(std::move(parent)) { } static tl_object_ptr get_input_check_password(Slice password, Slice client_salt, Slice server_salt, int32 g, Slice p, Slice B, int64 id); static Result get_password_input_settings(string new_password, string new_hint, const NewPasswordState &state); void get_state(Promise promise); void set_password(string current_password, string new_password, string new_hint, bool set_recovery_email_address, 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 resend_recovery_email_address_code(Promise promise); void send_email_address_verification_code( string email, Promise> promise); void resend_email_address_verification_code( Promise> promise); void check_email_address_verification_code(string code, Promise promise); void request_password_recovery(Promise> promise); void recover_password(string code, string new_password, string new_hint, Promise promise); void get_secure_secret(string password, Promise promise); void get_input_check_password_srp(string password, Promise> &&promise); void get_temp_password_state(Promise promise) /*const*/; void create_temp_password(string password, int32 timeout, Promise promise); void drop_temp_password(); void drop_cached_secret(); static TempPasswordState get_temp_password_state_sync(); private: ActorShared<> parent_; struct PasswordState { bool has_password = false; string password_hint; 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; int32 current_srp_g; string current_srp_p; string current_srp_B; int64 current_srp_id; NewPasswordState new_state; State get_password_state_object() 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, std::move(code_info)); } }; struct PasswordPrivateState { string email; optional secret; }; struct PasswordFullState { PasswordState state; PasswordPrivateState private_state; }; struct UpdateSettings { string current_password; bool update_password = false; string new_password; string new_hint; bool update_secure_secret = false; bool update_recovery_email_address = false; string recovery_email_address; }; optional secret_; double secret_expire_time_ = 0; TempPasswordState temp_password_state_; Promise create_temp_password_promise_; 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); static BufferSlice calc_password_hash(Slice password, Slice client_salt, Slice server_salt); static Result calc_password_srp_hash(Slice password, Slice client_salt, Slice server_salt, int32 g, Slice p); static tl_object_ptr get_input_check_password(Slice password, const PasswordState &state); static Result get_password_input_settings(const UpdateSettings &update_settings, bool has_password, const NewPasswordState &state, const PasswordPrivateState *private_state); void do_recover_password(string code, PasswordInputSettings &&new_settings, Promise &&promise); void update_password_settings(UpdateSettings update_settings, Promise promise); 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 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 do_create_temp_password(string password, int32 timeout, PasswordState &&password_state, Promise promise); void on_finish_create_temp_password(Result result, bool dummy); void on_result(NetQueryPtr query) override; void start_up() override; void timeout_expired() override; void hangup() override; Container> container_; void send_with_promise(NetQueryPtr query, Promise promise); }; } // namespace td