Add NewPasswordState struct.
This commit is contained in:
parent
3c400f12b4
commit
b35faee529
@ -371,6 +371,7 @@ set(TDLIB_SOURCE
|
||||
td/telegram/net/Session.cpp
|
||||
td/telegram/net/SessionProxy.cpp
|
||||
td/telegram/net/SessionMultiProxy.cpp
|
||||
td/telegram/NewPasswordState.cpp
|
||||
td/telegram/NotificationManager.cpp
|
||||
td/telegram/NotificationSettings.cpp
|
||||
td/telegram/NotificationType.cpp
|
||||
@ -564,6 +565,7 @@ set(TDLIB_SOURCE
|
||||
td/telegram/net/SessionProxy.h
|
||||
td/telegram/net/SessionMultiProxy.h
|
||||
td/telegram/net/TempAuthKeyWatchdog.h
|
||||
td/telegram/NewPasswordState.h
|
||||
td/telegram/Notification.h
|
||||
td/telegram/NotificationGroupId.h
|
||||
td/telegram/NotificationGroupKey.h
|
||||
|
59
td/telegram/NewPasswordState.cpp
Normal file
59
td/telegram/NewPasswordState.cpp
Normal file
@ -0,0 +1,59 @@
|
||||
//
|
||||
// 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)
|
||||
//
|
||||
#include "td/telegram/NewPasswordState.h"
|
||||
|
||||
namespace td {
|
||||
|
||||
Result<NewPasswordState> get_new_password_state(
|
||||
tl_object_ptr<telegram_api::PasswordKdfAlgo> new_algo,
|
||||
tl_object_ptr<telegram_api::SecurePasswordKdfAlgo> new_secure_algo) {
|
||||
NewPasswordState state;
|
||||
CHECK(new_algo != nullptr);
|
||||
switch (new_algo->get_id()) {
|
||||
case telegram_api::passwordKdfAlgoUnknown::ID:
|
||||
return Status::Error(400, "Please update client to continue");
|
||||
case telegram_api::passwordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow::ID: {
|
||||
auto algo =
|
||||
move_tl_object_as<telegram_api::passwordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow>(new_algo);
|
||||
state.client_salt = algo->salt1_.as_slice().str();
|
||||
state.server_salt = algo->salt2_.as_slice().str();
|
||||
state.srp_g = algo->g_;
|
||||
state.srp_p = algo->p_.as_slice().str();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
CHECK(new_secure_algo != nullptr);
|
||||
switch (new_secure_algo->get_id()) {
|
||||
case telegram_api::securePasswordKdfAlgoUnknown::ID:
|
||||
return Status::Error(400, "Please update client to continue");
|
||||
case telegram_api::securePasswordKdfAlgoSHA512::ID:
|
||||
return Status::Error(500, "Server has sent outdated secret encryption mode");
|
||||
case telegram_api::securePasswordKdfAlgoPBKDF2HMACSHA512iter100000::ID: {
|
||||
auto algo = move_tl_object_as<telegram_api::securePasswordKdfAlgoPBKDF2HMACSHA512iter100000>(new_secure_algo);
|
||||
state.secure_salt = algo->salt_.as_slice().str();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
static constexpr size_t MIN_NEW_SECURE_SALT_SIZE = 8;
|
||||
if (state.secure_salt.size() < MIN_NEW_SECURE_SALT_SIZE) {
|
||||
return Status::Error(500, "New secure salt length too small");
|
||||
}
|
||||
|
||||
static constexpr size_t MIN_NEW_SALT_SIZE = 8;
|
||||
if (state.client_salt.size() < MIN_NEW_SALT_SIZE) {
|
||||
return Status::Error(500, "New salt length too small");
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
} // namespace td
|
28
td/telegram/NewPasswordState.h
Normal file
28
td/telegram/NewPasswordState.h
Normal file
@ -0,0 +1,28 @@
|
||||
//
|
||||
// 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/telegram_api.h"
|
||||
|
||||
#include "td/utils/common.h"
|
||||
#include "td/utils/Status.h"
|
||||
|
||||
namespace td {
|
||||
|
||||
struct NewPasswordState {
|
||||
string client_salt;
|
||||
string server_salt;
|
||||
string srp_p;
|
||||
string secure_salt;
|
||||
int32 srp_g = 0;
|
||||
};
|
||||
|
||||
Result<NewPasswordState> get_new_password_state(
|
||||
tl_object_ptr<telegram_api::PasswordKdfAlgo> new_algo,
|
||||
tl_object_ptr<telegram_api::SecurePasswordKdfAlgo> new_secure_algo);
|
||||
|
||||
} // namespace td
|
@ -496,7 +496,9 @@ void PasswordManager::recover_password(string code, string new_password, string
|
||||
return promise.set_error(r_state.move_as_error());
|
||||
}
|
||||
|
||||
TRY_RESULT_PROMISE(promise, new_settings, get_password_input_settings(update_settings, r_state.ok(), nullptr));
|
||||
TRY_RESULT_PROMISE(
|
||||
promise, new_settings,
|
||||
get_password_input_settings(update_settings, r_state.ok().has_password, r_state.ok().new_state, nullptr));
|
||||
|
||||
send_closure(actor_id, &PasswordManager::do_recover_password, std::move(code), std::move(new_settings),
|
||||
std::move(promise));
|
||||
@ -568,7 +570,8 @@ void PasswordManager::do_update_password_settings(UpdateSettings update_settings
|
||||
}
|
||||
|
||||
Result<PasswordManager::PasswordInputSettings> PasswordManager::get_password_input_settings(
|
||||
const UpdateSettings &update_settings, const PasswordState &state, const PasswordPrivateState *private_state) {
|
||||
const UpdateSettings &update_settings, bool has_password, const NewPasswordState &state,
|
||||
const PasswordPrivateState *private_state) {
|
||||
auto settings = make_tl_object<telegram_api::account_passwordInputSettings>();
|
||||
bool have_secret = private_state != nullptr && private_state->secret;
|
||||
auto update_secure_secret = update_settings.update_secure_secret;
|
||||
@ -577,18 +580,17 @@ Result<PasswordManager::PasswordInputSettings> PasswordManager::get_password_inp
|
||||
settings->flags_ |= telegram_api::account_passwordInputSettings::NEW_ALGO_MASK;
|
||||
settings->flags_ |= telegram_api::account_passwordInputSettings::HINT_MASK;
|
||||
if (!update_settings.new_password.empty()) {
|
||||
auto new_client_salt = create_salt(state.new_client_salt);
|
||||
auto new_client_salt = create_salt(state.client_salt);
|
||||
|
||||
auto new_hash = calc_password_srp_hash(update_settings.new_password, new_client_salt.as_slice(),
|
||||
state.new_server_salt, state.new_srp_g, state.new_srp_p);
|
||||
state.server_salt, state.srp_g, state.srp_p);
|
||||
if (new_hash.is_error()) {
|
||||
return Status::Error(400, "Unable to change password, because it may be unsafe");
|
||||
}
|
||||
settings->new_password_hash_ = new_hash.move_as_ok();
|
||||
settings->new_algo_ =
|
||||
make_tl_object<telegram_api::passwordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow>(
|
||||
std::move(new_client_salt), BufferSlice(state.new_server_salt), state.new_srp_g,
|
||||
BufferSlice(state.new_srp_p));
|
||||
std::move(new_client_salt), BufferSlice(state.server_salt), state.srp_g, BufferSlice(state.srp_p));
|
||||
settings->hint_ = std::move(update_settings.new_hint);
|
||||
if (have_secret) {
|
||||
update_secure_secret = true;
|
||||
@ -599,7 +601,7 @@ Result<PasswordManager::PasswordInputSettings> PasswordManager::get_password_inp
|
||||
}
|
||||
|
||||
// have no password and not setting one
|
||||
if (!update_settings.update_password && !state.has_password) {
|
||||
if (!update_settings.update_password && !has_password) {
|
||||
update_secure_secret = false;
|
||||
}
|
||||
|
||||
@ -610,8 +612,8 @@ Result<PasswordManager::PasswordInputSettings> PasswordManager::get_password_inp
|
||||
|
||||
if (update_secure_secret) {
|
||||
auto secret = have_secret ? std::move(private_state->secret.value()) : secure_storage::Secret::create_new();
|
||||
auto algorithm = make_tl_object<telegram_api::securePasswordKdfAlgoPBKDF2HMACSHA512iter100000>(
|
||||
create_salt(state.new_secure_salt));
|
||||
auto algorithm =
|
||||
make_tl_object<telegram_api::securePasswordKdfAlgoPBKDF2HMACSHA512iter100000>(create_salt(state.secure_salt));
|
||||
auto encrypted_secret = secret.encrypt(
|
||||
update_settings.update_password ? update_settings.new_password : update_settings.current_password,
|
||||
algorithm->salt_.as_slice(), secure_storage::EnryptionAlgorithm::Pbkdf2);
|
||||
@ -629,7 +631,8 @@ Result<PasswordManager::PasswordInputSettings> PasswordManager::get_password_inp
|
||||
|
||||
void PasswordManager::do_update_password_settings_impl(UpdateSettings update_settings, PasswordState state,
|
||||
PasswordPrivateState private_state, Promise<bool> promise) {
|
||||
TRY_RESULT_PROMISE(promise, new_settings, get_password_input_settings(update_settings, state, &private_state));
|
||||
TRY_RESULT_PROMISE(promise, new_settings,
|
||||
get_password_input_settings(update_settings, state.has_password, state.new_state, &private_state));
|
||||
auto current_hash = get_input_check_password(state.has_password ? update_settings.current_password : Slice(), state);
|
||||
auto query = G()->net_query_creator().create(
|
||||
telegram_api::account_updatePasswordSettings(std::move(current_hash), std::move(new_settings)));
|
||||
@ -718,46 +721,11 @@ void PasswordManager::do_get_state(Promise<PasswordState> promise) {
|
||||
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()) {
|
||||
case telegram_api::passwordKdfAlgoUnknown::ID:
|
||||
return promise.set_error(Status::Error(400, "Please update client to continue"));
|
||||
case telegram_api::passwordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow::ID: {
|
||||
auto algo =
|
||||
move_tl_object_as<telegram_api::passwordKdfAlgoSHA256SHA256PBKDF2HMACSHA512iter100000SHA256ModPow>(
|
||||
password->new_algo_);
|
||||
state.new_client_salt = algo->salt1_.as_slice().str();
|
||||
state.new_server_salt = algo->salt2_.as_slice().str();
|
||||
state.new_srp_g = algo->g_;
|
||||
state.new_srp_p = algo->p_.as_slice().str();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
auto &new_state = state.new_state;
|
||||
TRY_RESULT_PROMISE_ASSIGN(
|
||||
promise, new_state,
|
||||
get_new_password_state(std::move(password->new_algo_), std::move(password->new_secure_algo_)));
|
||||
|
||||
CHECK(password->new_secure_algo_ != nullptr);
|
||||
switch (password->new_secure_algo_->get_id()) {
|
||||
case telegram_api::securePasswordKdfAlgoUnknown::ID:
|
||||
return promise.set_error(Status::Error(400, "Please update client to continue"));
|
||||
case telegram_api::securePasswordKdfAlgoSHA512::ID:
|
||||
return promise.set_error(Status::Error(500, "Server has sent outdated secret encryption mode"));
|
||||
case telegram_api::securePasswordKdfAlgoPBKDF2HMACSHA512iter100000::ID: {
|
||||
auto algo = move_tl_object_as<telegram_api::securePasswordKdfAlgoPBKDF2HMACSHA512iter100000>(
|
||||
password->new_secure_algo_);
|
||||
state.new_secure_salt = algo->salt_.as_slice().str();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
if (state.new_secure_salt.size() < MIN_NEW_SECURE_SALT_SIZE) {
|
||||
return promise.set_error(Status::Error(500, "New secure salt length too small"));
|
||||
}
|
||||
if (state.new_client_salt.size() < MIN_NEW_SALT_SIZE) {
|
||||
return promise.set_error(Status::Error(500, "New salt length too small"));
|
||||
}
|
||||
promise.set_value(std::move(state));
|
||||
}));
|
||||
}
|
||||
|
@ -7,6 +7,7 @@
|
||||
#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"
|
||||
@ -90,9 +91,6 @@ class PasswordManager : public NetQueryCallback {
|
||||
static TempPasswordState get_temp_password_state_sync();
|
||||
|
||||
private:
|
||||
static constexpr size_t MIN_NEW_SALT_SIZE = 8;
|
||||
static constexpr size_t MIN_NEW_SECURE_SALT_SIZE = 8;
|
||||
|
||||
ActorShared<> parent_;
|
||||
|
||||
struct PasswordState {
|
||||
@ -109,12 +107,8 @@ class PasswordManager : public NetQueryCallback {
|
||||
string current_srp_p;
|
||||
string current_srp_B;
|
||||
int64 current_srp_id;
|
||||
string new_client_salt;
|
||||
string new_server_salt;
|
||||
int32 new_srp_g;
|
||||
string new_srp_p;
|
||||
|
||||
string new_secure_salt;
|
||||
NewPasswordState new_state;
|
||||
|
||||
State get_password_state_object() const {
|
||||
td_api::object_ptr<td_api::emailAddressAuthenticationCodeInfo> code_info;
|
||||
@ -172,7 +166,7 @@ class PasswordManager : public NetQueryCallback {
|
||||
const PasswordState &state);
|
||||
|
||||
static Result<PasswordInputSettings> get_password_input_settings(const UpdateSettings &update_settings,
|
||||
const PasswordState &state,
|
||||
bool has_password, const NewPasswordState &state,
|
||||
const PasswordPrivateState *private_state);
|
||||
|
||||
void do_recover_password(string code, PasswordInputSettings &&new_settings, Promise<State> &&promise);
|
||||
|
Loading…
Reference in New Issue
Block a user