From 5b615519e8466031fca942adbfbbafb1ab705689 Mon Sep 17 00:00:00 2001 From: John Preston Date: Sun, 15 Apr 2018 20:22:13 +0400 Subject: [PATCH] Suggest full passport reset in case of bad secret. --- .../passport/passport_form_controller.cpp | 70 +++++++++++++------ .../passport/passport_form_controller.h | 3 +- .../passport/passport_form_view_controller.h | 1 + .../passport/passport_panel_controller.cpp | 24 +++++++ .../passport/passport_panel_controller.h | 6 ++ Telegram/SourceFiles/window/layer_widget.cpp | 1 - 6 files changed, 83 insertions(+), 22 deletions(-) diff --git a/Telegram/SourceFiles/passport/passport_form_controller.cpp b/Telegram/SourceFiles/passport/passport_form_controller.cpp index b2ba564cf..3fb2e78c4 100644 --- a/Telegram/SourceFiles/passport/passport_form_controller.cpp +++ b/Telegram/SourceFiles/passport/passport_form_controller.cpp @@ -397,23 +397,15 @@ void FormController::validateSecureSecret( _secret = DecryptSecureSecret(salt, encryptedSecret, password); if (_secret.empty()) { _secretId = 0; - LOG(("API Error: Failed to decrypt secure secret. " - "Forgetting all files and data :(")); - for (auto &[type, value] : _form.values) { - if (!value.data.original.isEmpty()) { - resetValue(value); - } - } + LOG(("API Error: Failed to decrypt secure secret.")); + suggestReset(bytes::make_vector(password)); + return; } else if (CountSecureSecretId(_secret) != serverSecretId) { _secret.clear(); _secretId = 0; - LOG(("API Error: Wrong secure secret id. " - "Forgetting all files and data :(")); - for (auto &[type, value] : _form.values) { - if (!value.data.original.isEmpty()) { - resetValue(value); - } - } + LOG(("API Error: Wrong secure secret id.")); + suggestReset(bytes::make_vector(password)); + return; } else { _secretId = serverSecretId; decryptValues(); @@ -425,6 +417,40 @@ void FormController::validateSecureSecret( _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() { Expects(!_secret.empty()); @@ -441,10 +467,16 @@ void FormController::decryptValue(Value &value) { return; } if (!value.data.original.isEmpty()) { - const auto fields = DeserializeData(DecryptData( + const auto decrypted = DecryptData( bytes::make_span(value.data.original), 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(); for (const auto [key, text] : fields) { value.data.parsed.fields[key] = { text }; @@ -459,8 +491,7 @@ bool FormController::validateValueSecrets(Value &value) { _secret, value.data.hash); if (value.data.secret.empty()) { - LOG(("API Error: Could not decrypt data secret. " - "Forgetting files and data :(")); + LOG(("API Error: Could not decrypt data secret.")); return false; } } @@ -470,8 +501,7 @@ bool FormController::validateValueSecrets(Value &value) { _secret, file.hash); if (file.secret.empty()) { - LOG(("API Error: Could not decrypt selfie secret. " - "Forgetting files and data :(")); + LOG(("API Error: Could not decrypt file secret.")); return false; } return true; diff --git a/Telegram/SourceFiles/passport/passport_form_controller.h b/Telegram/SourceFiles/passport/passport_form_controller.h index 903e3bd39..45f9d6e81 100644 --- a/Telegram/SourceFiles/passport/passport_form_controller.h +++ b/Telegram/SourceFiles/passport/passport_form_controller.h @@ -250,6 +250,7 @@ public: bool savingValue(not_null value) const; void cancel(); + void cancelSure(); rpl::lifetime &lifetime(); @@ -352,8 +353,8 @@ private: const MTPInputSecureValue &data); FinalData prepareFinalData(); + void suggestReset(bytes::vector password); void suggestRestart(); - void cancelSure(); void cancelAbort(); not_null _controller; diff --git a/Telegram/SourceFiles/passport/passport_form_view_controller.h b/Telegram/SourceFiles/passport/passport_form_view_controller.h index c9e916fe3..6ef43feab 100644 --- a/Telegram/SourceFiles/passport/passport_form_view_controller.h +++ b/Telegram/SourceFiles/passport/passport_form_view_controller.h @@ -48,6 +48,7 @@ public: virtual void showBox(object_ptr box) = 0; virtual void showToast(const QString &text) = 0; + virtual void suggestReset(base::lambda callback) = 0; virtual int closeGetDuration() = 0; diff --git a/Telegram/SourceFiles/passport/passport_panel_controller.cpp b/Telegram/SourceFiles/passport/passport_panel_controller.cpp index dc0ecedc3..38ebb4e52 100644 --- a/Telegram/SourceFiles/passport/passport_panel_controller.cpp +++ b/Telegram/SourceFiles/passport/passport_panel_controller.cpp @@ -17,6 +17,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "ui/toast/toast.h" #include "ui/countryinput.h" #include "layout.h" +#include "styles/style_boxes.h" namespace Passport { @@ -639,6 +640,29 @@ void PanelController::deleteValueSure(bool withDetails) { } } +void PanelController::suggestReset(base::lambda callback) { + _resetBox = BoxPointer(show(Box( + Lang::Hard::PassportCorrupted(), + Lang::Hard::PassportCorruptedReset(), + [=] { resetPassport(callback); }, + [=] { cancelReset(); })).data()); // #TODO passport no need for confirmation? +} + +void PanelController::resetPassport(base::lambda callback) { + const auto box = show(Box( + 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 { switch (type) { case Scope::Type::Phone: diff --git a/Telegram/SourceFiles/passport/passport_panel_controller.h b/Telegram/SourceFiles/passport/passport_panel_controller.h index 5789d5771..1adb33197 100644 --- a/Telegram/SourceFiles/passport/passport_panel_controller.h +++ b/Telegram/SourceFiles/passport/passport_panel_controller.h @@ -108,6 +108,7 @@ public: void showBox(object_ptr box) override; void showToast(const QString &text) override; + void suggestReset(base::lambda callback) override; int closeGetDuration() override; @@ -140,6 +141,9 @@ private: QString getDefaultContactValue(Scope::Type type) const; void deleteValueSure(bool withDetails); + void resetPassport(base::lambda callback); + void cancelReset(); + not_null _form; std::vector _scopes; rpl::event_stream<> _submitFailed; @@ -157,6 +161,8 @@ private: BoxPointer _scopeDocumentTypeBox; std::map, BoxPointer> _verificationBoxes; + BoxPointer _resetBox; + rpl::lifetime _lifetime; }; diff --git a/Telegram/SourceFiles/window/layer_widget.cpp b/Telegram/SourceFiles/window/layer_widget.cpp index 574eb1ad2..3a8ce5008 100644 --- a/Telegram/SourceFiles/window/layer_widget.cpp +++ b/Telegram/SourceFiles/window/layer_widget.cpp @@ -789,7 +789,6 @@ LayerStackWidget::~LayerStackWidget() { // other layers, that call methods of LayerStackWidget and access // its fields, so if it is destroyed already everything crashes. for (auto layer : base::take(_layers)) { - layer->setClosing(); layer->hide(); delete layer; }