Suggest full passport reset in case of bad secret.

This commit is contained in:
John Preston 2018-04-15 20:22:13 +04:00
parent 03b7a3ca2b
commit 5b615519e8
6 changed files with 83 additions and 22 deletions

View File

@ -397,23 +397,15 @@ void FormController::validateSecureSecret(
_secret = DecryptSecureSecret(salt, encryptedSecret, password); _secret = DecryptSecureSecret(salt, encryptedSecret, password);
if (_secret.empty()) { if (_secret.empty()) {
_secretId = 0; _secretId = 0;
LOG(("API Error: Failed to decrypt secure secret. " LOG(("API Error: Failed to decrypt secure secret."));
"Forgetting all files and data :(")); suggestReset(bytes::make_vector(password));
for (auto &[type, value] : _form.values) { return;
if (!value.data.original.isEmpty()) {
resetValue(value);
}
}
} else if (CountSecureSecretId(_secret) != serverSecretId) { } else if (CountSecureSecretId(_secret) != serverSecretId) {
_secret.clear(); _secret.clear();
_secretId = 0; _secretId = 0;
LOG(("API Error: Wrong secure secret id. " LOG(("API Error: Wrong secure secret id."));
"Forgetting all files and data :(")); suggestReset(bytes::make_vector(password));
for (auto &[type, value] : _form.values) { return;
if (!value.data.original.isEmpty()) {
resetValue(value);
}
}
} else { } else {
_secretId = serverSecretId; _secretId = serverSecretId;
decryptValues(); decryptValues();
@ -425,6 +417,40 @@ void FormController::validateSecureSecret(
_secretReady.fire({}); _secretReady.fire({});
} }
void FormController::suggestReset(bytes::vector password) {
for (auto &[type, value] : _form.values) {
// if (!value.data.original.isEmpty()) {
resetValue(value);
// }
}
_view->suggestReset([=] {
const auto hashForAuth = openssl::Sha256(bytes::concatenate(
_password.salt,
password,
_password.salt));
using Flag = MTPDaccount_passwordInputSettings::Flag;
_saveSecretRequestId = request(MTPaccount_UpdatePasswordSettings(
MTP_bytes(hashForAuth),
MTP_account_passwordInputSettings(
MTP_flags(Flag::f_new_secure_secret),
MTPbytes(), // new_salt
MTPbytes(), // new_password_hash
MTPstring(), // hint
MTPstring(), // email
MTP_bytes(QByteArray()), // new_secure_salt
MTP_bytes(QByteArray()), // new_secure_secret
MTP_long(0)) // new_secure_secret_id
)).done([=](const MTPBool &result) {
_saveSecretRequestId = 0;
generateSecret(password);
}).fail([=](const RPCError &error) {
_saveSecretRequestId = 0;
formFail(error.type());
}).send();
_secretReady.fire({});
});
}
void FormController::decryptValues() { void FormController::decryptValues() {
Expects(!_secret.empty()); Expects(!_secret.empty());
@ -441,10 +467,16 @@ void FormController::decryptValue(Value &value) {
return; return;
} }
if (!value.data.original.isEmpty()) { if (!value.data.original.isEmpty()) {
const auto fields = DeserializeData(DecryptData( const auto decrypted = DecryptData(
bytes::make_span(value.data.original), bytes::make_span(value.data.original),
value.data.hash, value.data.hash,
value.data.secret)); value.data.secret);
if (decrypted.empty()) {
LOG(("API Error: Could not decrypt value fields."));
resetValue(value);
return;
}
const auto fields = DeserializeData(decrypted);
value.data.parsed.fields.clear(); value.data.parsed.fields.clear();
for (const auto [key, text] : fields) { for (const auto [key, text] : fields) {
value.data.parsed.fields[key] = { text }; value.data.parsed.fields[key] = { text };
@ -459,8 +491,7 @@ bool FormController::validateValueSecrets(Value &value) {
_secret, _secret,
value.data.hash); value.data.hash);
if (value.data.secret.empty()) { if (value.data.secret.empty()) {
LOG(("API Error: Could not decrypt data secret. " LOG(("API Error: Could not decrypt data secret."));
"Forgetting files and data :("));
return false; return false;
} }
} }
@ -470,8 +501,7 @@ bool FormController::validateValueSecrets(Value &value) {
_secret, _secret,
file.hash); file.hash);
if (file.secret.empty()) { if (file.secret.empty()) {
LOG(("API Error: Could not decrypt selfie secret. " LOG(("API Error: Could not decrypt file secret."));
"Forgetting files and data :("));
return false; return false;
} }
return true; return true;

View File

@ -250,6 +250,7 @@ public:
bool savingValue(not_null<const Value*> value) const; bool savingValue(not_null<const Value*> value) const;
void cancel(); void cancel();
void cancelSure();
rpl::lifetime &lifetime(); rpl::lifetime &lifetime();
@ -352,8 +353,8 @@ private:
const MTPInputSecureValue &data); const MTPInputSecureValue &data);
FinalData prepareFinalData(); FinalData prepareFinalData();
void suggestReset(bytes::vector password);
void suggestRestart(); void suggestRestart();
void cancelSure();
void cancelAbort(); void cancelAbort();
not_null<Window::Controller*> _controller; not_null<Window::Controller*> _controller;

View File

@ -48,6 +48,7 @@ public:
virtual void showBox(object_ptr<BoxContent> box) = 0; virtual void showBox(object_ptr<BoxContent> box) = 0;
virtual void showToast(const QString &text) = 0; virtual void showToast(const QString &text) = 0;
virtual void suggestReset(base::lambda<void()> callback) = 0;
virtual int closeGetDuration() = 0; virtual int closeGetDuration() = 0;

View File

@ -17,6 +17,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "ui/toast/toast.h" #include "ui/toast/toast.h"
#include "ui/countryinput.h" #include "ui/countryinput.h"
#include "layout.h" #include "layout.h"
#include "styles/style_boxes.h"
namespace Passport { namespace Passport {
@ -639,6 +640,29 @@ void PanelController::deleteValueSure(bool withDetails) {
} }
} }
void PanelController::suggestReset(base::lambda<void()> callback) {
_resetBox = BoxPointer(show(Box<ConfirmBox>(
Lang::Hard::PassportCorrupted(),
Lang::Hard::PassportCorruptedReset(),
[=] { resetPassport(callback); },
[=] { cancelReset(); })).data()); // #TODO passport no need for confirmation?
}
void PanelController::resetPassport(base::lambda<void()> callback) {
const auto box = show(Box<ConfirmBox>(
Lang::Hard::PassportCorruptedResetSure(),
Lang::Hard::PassportCorruptedReset(),
st::attentionBoxButton,
[=] { base::take(_resetBox); callback(); },
[=] { suggestReset(callback); }));
_resetBox = BoxPointer(box.data());
}
void PanelController::cancelReset() {
const auto weak = base::take(_resetBox);
_form->cancelSure();
}
QString PanelController::getDefaultContactValue(Scope::Type type) const { QString PanelController::getDefaultContactValue(Scope::Type type) const {
switch (type) { switch (type) {
case Scope::Type::Phone: case Scope::Type::Phone:

View File

@ -108,6 +108,7 @@ public:
void showBox(object_ptr<BoxContent> box) override; void showBox(object_ptr<BoxContent> box) override;
void showToast(const QString &text) override; void showToast(const QString &text) override;
void suggestReset(base::lambda<void()> callback) override;
int closeGetDuration() override; int closeGetDuration() override;
@ -140,6 +141,9 @@ private:
QString getDefaultContactValue(Scope::Type type) const; QString getDefaultContactValue(Scope::Type type) const;
void deleteValueSure(bool withDetails); void deleteValueSure(bool withDetails);
void resetPassport(base::lambda<void()> callback);
void cancelReset();
not_null<FormController*> _form; not_null<FormController*> _form;
std::vector<Scope> _scopes; std::vector<Scope> _scopes;
rpl::event_stream<> _submitFailed; rpl::event_stream<> _submitFailed;
@ -157,6 +161,8 @@ private:
BoxPointer _scopeDocumentTypeBox; BoxPointer _scopeDocumentTypeBox;
std::map<not_null<const Value*>, BoxPointer> _verificationBoxes; std::map<not_null<const Value*>, BoxPointer> _verificationBoxes;
BoxPointer _resetBox;
rpl::lifetime _lifetime; rpl::lifetime _lifetime;
}; };

View File

@ -789,7 +789,6 @@ LayerStackWidget::~LayerStackWidget() {
// other layers, that call methods of LayerStackWidget and access // other layers, that call methods of LayerStackWidget and access
// its fields, so if it is destroyed already everything crashes. // its fields, so if it is destroyed already everything crashes.
for (auto layer : base::take(_layers)) { for (auto layer : base::take(_layers)) {
layer->setClosing();
layer->hide(); layer->hide();
delete layer; delete layer;
} }