Add NewPasswordState struct.

This commit is contained in:
levlam 2021-06-28 21:03:17 +03:00
parent 3c400f12b4
commit b35faee529
5 changed files with 109 additions and 58 deletions

View File

@ -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

View 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

View 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

View File

@ -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));
}));
}

View File

@ -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);