Skip to content

Commit baeafcc

Browse files
committed
remove cached password, add verifyPassword(), wipeQString(),
isSecret property for LineEdit
1 parent 213856b commit baeafcc

18 files changed

Lines changed: 230 additions & 56 deletions

components/LineEdit.qml

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ ColumnLayout {
106106
property alias labelHorizontalAlignment: inputLabel.horizontalAlignment
107107
property bool showingHeader: inputLabel.text !== "" || copyButton
108108
property int inputHeight: 39
109+
property bool isSecret: false
109110

110111
signal labelLinkActivated(); // input label, rich text <a> signal
111112
signal editingFinished();
@@ -228,6 +229,31 @@ ColumnLayout {
228229
item.KeyNavigation.tab.forceActiveFocus()
229230
}
230231
}
232+
Keys.onPressed: {
233+
if (isSecret) {
234+
if (event.key === Qt.Key_Left || event.key === Qt.Key_Home) {
235+
event.accepted = true;
236+
}
237+
if (event.key === Qt.Key_Backspace || event.key === Qt.Key_Delete) {
238+
memwipe.wipeQString(item.text);
239+
clear();
240+
event.accepted = true;
241+
}
242+
}
243+
}
244+
MouseArea {
245+
anchors.fill: parent
246+
cursorShape: item.isSecret ? Qt.ArrowCursor : Qt.IBeamCursor
247+
onClicked: {
248+
if (item.isSecret) {
249+
memwipe.wipeQString(item.text);
250+
item.input.clear();
251+
}
252+
else {
253+
item.forceActiveFocus();
254+
}
255+
}
256+
}
231257
Layout.fillWidth: true
232258
Layout.preferredHeight: inputHeight
233259

components/PasswordDialog.qml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,7 @@ Item {
229229
Keys.onEnterPressed: root.onOk()
230230
Keys.onReturnPressed: root.onOk()
231231
Keys.onEscapePressed: root.onCancel()
232+
isSecret: true
232233
}
233234

234235
// padding
@@ -265,6 +266,7 @@ Item {
265266
Keys.onEnterPressed: root.onOk()
266267
Keys.onReturnPressed: root.onOk()
267268
Keys.onEscapePressed: root.onCancel()
269+
isSecret: true
268270
}
269271

270272
// padding

js/Utils.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ function isNumeric(n) {
3131
function showSeedPage() {
3232
// Shows `Settings->Seed & keys`. Prompts a password dialog.
3333
passwordDialog.onAcceptedCallback = function() {
34-
if(walletPassword === passwordDialog.password){
34+
if(currentWallet.verifyPassword(passwordDialog.password, persistentSettings.kdfRounds)){
3535
if(currentWallet.seedLanguage == "") {
3636
console.log("No seed language set. Using English as default");
3737
currentWallet.setSeedLanguage("English");
@@ -43,6 +43,7 @@ function showSeedPage() {
4343
}
4444
}
4545
passwordDialog.onRejectedCallback = function() {
46+
memwipe.wipeQString(passwordDialog.password);
4647
leftPanel.selectItem(middlePanel.state);
4748
}
4849
passwordDialog.open();

main.qml

Lines changed: 35 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ import moneroComponents.PendingTransaction 1.0
4343
import moneroComponents.NetworkType 1.0
4444
import moneroComponents.Settings 1.0
4545
import moneroComponents.P2PoolManager 1.0
46+
import moneroComponents.Memwipe 1.0
4647

4748
import "components"
4849
import "components" as MoneroComponents
@@ -71,7 +72,6 @@ ApplicationWindow {
7172
property var currentWallet;
7273
property bool disconnected: currentWallet ? currentWallet.disconnected : false
7374
property var transaction;
74-
property var walletPassword
7575
property int restoreHeight:0
7676
property bool daemonSynced: false
7777
property bool walletSynced: false
@@ -140,9 +140,12 @@ ApplicationWindow {
140140
return;
141141
}
142142

143-
passwordDialog.onRejectedCallback = function() { appWindow.showWizard(); }
143+
passwordDialog.onRejectedCallback = function() {
144+
memwipe.wipeQString(passwordDialog.password);
145+
appWindow.showWizard();
146+
}
144147
passwordDialog.onAcceptedCallback = function() {
145-
if(walletPassword === passwordDialog.password)
148+
if (currentWallet.verifyPassword(passwordDialog.password, persistentSettings.kdfRounds))
146149
passwordDialog.close();
147150
else
148151
passwordDialog.showError(qsTr("Wrong password") + translationManager.emptyString);
@@ -225,16 +228,19 @@ ApplicationWindow {
225228

226229
function openWallet(prevState) {
227230
passwordDialog.onAcceptedCallback = function() {
228-
walletPassword = passwordDialog.password;
229231
initialize();
230232
}
231233
passwordDialog.onRejectedCallback = function() {
234+
memwipe.wipeQString(passwordDialog.password);
232235
if (prevState) {
233236
appWindow.viewState = prevState;
234237
}
235238
if (wizard.wizardState == "wizardOpenWallet1") {
236239
wizard.wizardStateView.wizardOpenWallet1View.pageRoot.forceActiveFocus();
237240
}
241+
else if (wizard.wizardState == "wizardCreateWallet5") {
242+
showWizard()
243+
}
238244
};
239245
passwordDialog.open(usefulName(persistentSettings.wallet_path));
240246
}
@@ -271,13 +277,12 @@ ApplicationWindow {
271277
var wallet_path = persistentSettings.wallet_path;
272278
if(isIOS)
273279
wallet_path = appWindow.accountsDir + wallet_path;
274-
// console.log("opening wallet at: ", wallet_path, "with password: ", appWindow.walletPassword);
275280
console.log("opening wallet at: ", wallet_path, ", network type: ", persistentSettings.nettype == NetworkType.MAINNET ? "mainnet" : persistentSettings.nettype == NetworkType.TESTNET ? "testnet" : "stagenet");
276281

277282
this.onWalletOpening();
278283
walletManager.openWalletAsync(
279284
wallet_path,
280-
walletPassword,
285+
passwordDialog.password,
281286
persistentSettings.nettype,
282287
persistentSettings.kdfRounds);
283288
}
@@ -389,7 +394,9 @@ ApplicationWindow {
389394
persistentSettings.getWalletProxyAddress());
390395

391396
// save wallet keys in case wallet settings have been changed in the init
392-
currentWallet.setPassword(walletPassword);
397+
currentWallet.setPassword(passwordDialog.password, passwordDialog.password);
398+
memwipe.wipeQString(passwordDialog.password);
399+
currentWallet.storeAsync(function(){});
393400
}
394401

395402
function isTrustedDaemon() {
@@ -543,7 +550,6 @@ ApplicationWindow {
543550
case "basic_string::_M_replace_aux":
544551
case "std::bad_alloc":
545552
walletManager.clearWalletCache(wallet.path);
546-
walletPassword = passwordDialog.password;
547553
appWindow.initialize();
548554
console.error("Repairing wallet cache with error: ", wallet.errorString);
549555
appWindow.showStatusMessage(qsTr("Repairing incompatible wallet cache. Resyncing wallet."),6);
@@ -1671,13 +1677,13 @@ ApplicationWindow {
16711677
}
16721678
close();
16731679
passwordDialog.onAcceptedCallback = function() {
1674-
if(walletPassword === passwordDialog.password){
1680+
if (currentWallet.verifyPassword(passwordDialog.password, persistentSettings.kdfRounds)) {
16751681
handleAccepted()
16761682
} else {
16771683
passwordDialog.showError(qsTr("Wrong password") + translationManager.emptyString);
16781684
}
16791685
}
1680-
passwordDialog.onRejectedCallback = null;
1686+
passwordDialog.onRejectedCallback = function() { memwipe.wipeQString(passwordDialog.password); }
16811687
if(!persistentSettings.askPasswordBeforeSending) {
16821688
handleAccepted()
16831689
} else {
@@ -1785,8 +1791,7 @@ ApplicationWindow {
17851791
onRejectedCallback();
17861792
}
17871793
onAcceptedNewPassword: {
1788-
if (currentWallet.setPassword(passwordDialog.password)) {
1789-
appWindow.walletPassword = passwordDialog.password;
1794+
if (currentWallet.setPassword(/* old_password */ "", passwordDialog.password)) {
17901795
informationPopup.title = qsTr("Information") + translationManager.emptyString;
17911796
informationPopup.text = qsTr("Password changed successfully") + translationManager.emptyString;
17921797
informationPopup.icon = StandardIcon.Information;
@@ -1797,6 +1802,8 @@ ApplicationWindow {
17971802
}
17981803
informationPopup.onCloseCallback = null;
17991804
informationPopup.open();
1805+
memwipe.wipeQString(passwordDialog.password);
1806+
memwipe.wipeQString(passwordDialog.passwordConfirm);
18001807
}
18011808
onRejectedNewPassword: {}
18021809
Keys.enabled: !passwordDialog.visible && informationPopup.visible
@@ -2352,7 +2359,7 @@ ApplicationWindow {
23522359
}
23532360

23542361
passwordDialog.onAcceptedCallback = function() {
2355-
if(walletPassword === passwordDialog.password){
2362+
if (currentWallet.verifyPassword(passwordDialog.password, persistentSettings.kdfRounds)) {
23562363
passwordDialog.close();
23572364
if (inputDialogVisible) inputDialog.open(inputDialog.inputText)
23582365
if (successfulTxPopupVisible) successfulTxPopup.open(successfulTxPopup.transactionID)
@@ -2362,7 +2369,17 @@ ApplicationWindow {
23622369
}
23632370
}
23642371

2365-
passwordDialog.onRejectedCallback = function() { appWindow.showWizard(); }
2372+
passwordDialog.onRejectedCallback = function() {
2373+
memwipe.wipeQString(passwordDialog.password);
2374+
appWindow.showWizard();
2375+
}
2376+
if (inputDialogVisible) inputDialog.close()
2377+
remoteNodeDialog.close();
2378+
informationPopup.close()
2379+
txConfirmationPopup.close()
2380+
txConfirmationPopup.clearFields()
2381+
txConfirmationPopup.rejected()
2382+
successfulTxPopup.close();
23662383
passwordDialog.open();
23672384
}
23682385

@@ -2497,4 +2514,8 @@ ApplicationWindow {
24972514
id: walletManager
24982515
proxyAddress: persistentSettings.getProxyAddress()
24992516
}
2517+
2518+
Memwipe {
2519+
id: memwipe
2520+
}
25002521
}

monero

Submodule monero updated 1009 files

pages/settings/SettingsInfo.qml

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -195,10 +195,6 @@ Rectangle {
195195
}
196196
if (!isNaN(_restoreHeight)) {
197197
if(_restoreHeight >= 0) {
198-
currentWallet.walletCreationHeight = _restoreHeight
199-
// Restore height is saved in .keys file. Set password to trigger rewrite.
200-
currentWallet.setPassword(appWindow.walletPassword)
201-
202198
// Show confirmation dialog
203199
confirmationDialog.title = qsTr("Rescan wallet cache") + translationManager.emptyString;
204200
confirmationDialog.text = qsTr("Are you sure you want to rebuild the wallet cache?\n"
@@ -210,13 +206,30 @@ Rectangle {
210206
);
211207
confirmationDialog.icon = StandardIcon.Question
212208
confirmationDialog.onAcceptedCallback = function() {
213-
appWindow.closeWallet(function() {
214-
walletManager.clearWalletCache(persistentSettings.wallet_path);
215-
walletManager.openWalletAsync(persistentSettings.wallet_path, appWindow.walletPassword,
216-
persistentSettings.nettype, persistentSettings.kdfRounds);
217-
});
218-
}
209+
passwordDialog.onAcceptedCallback = function() {
210+
if(currentWallet.verifyPassword(passwordDialog.password, persistentSettings.kdfRounds, /* do_wipe */ false)){
211+
currentWallet.walletCreationHeight = _restoreHeight
212+
// Restore height is saved in .keys file. Set password to trigger rewrite.
213+
currentWallet.setPassword(passwordDialog.password, passwordDialog.password);
214+
215+
appWindow.closeWallet(function() {
216+
walletManager.clearWalletCache(persistentSettings.wallet_path);
217+
walletManager.openWalletAsync(persistentSettings.wallet_path, passwordDialog.password,
218+
persistentSettings.nettype, persistentSettings.kdfRounds);
219+
});
220+
221+
passwordDialog.close();
222+
} else {
223+
memwipe.wipeQString(passwordDialog.password);
224+
passwordDialog.showError(qsTr("Wrong password") + translationManager.emptyString);
225+
}
226+
}
227+
passwordDialog.onRejectedCallback = function() {
228+
memwipe.wipeQString(passwordDialog.password);
229+
};
230+
passwordDialog.open(usefulName(persistentSettings.wallet_path));
219231

232+
}
220233
confirmationDialog.onRejectedCallback = null;
221234
confirmationDialog.open()
222235
return;

pages/settings/SettingsLayout.qml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,13 +101,13 @@ Rectangle {
101101
onClicked: {
102102
if (persistentSettings.askPasswordBeforeSending) {
103103
passwordDialog.onAcceptedCallback = function() {
104-
if (appWindow.walletPassword === passwordDialog.password){
104+
if (currentWallet.verifyPassword(passwordDialog.password, persistentSettings.kdfRounds)) {
105105
persistentSettings.askPasswordBeforeSending = false;
106106
} else {
107107
passwordDialog.showError(qsTr("Wrong password"));
108108
}
109109
}
110-
passwordDialog.onRejectedCallback = null;
110+
passwordDialog.onRejectedCallback = function() { memwipe.wipeQString(passwordDialog.password); }
111111
passwordDialog.open()
112112
} else {
113113
persistentSettings.askPasswordBeforeSending = true;

pages/settings/SettingsWallet.qml

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -74,17 +74,22 @@ Rectangle {
7474

7575
onClicked: {
7676
var newPath = currentWallet.path + "_viewonly";
77-
if (currentWallet.createViewOnly(newPath, appWindow.walletPassword)) {
78-
console.log("view only wallet created in " + newPath);
79-
informationPopup.title = qsTr("Success") + translationManager.emptyString;
80-
informationPopup.text = qsTr('The view only wallet has been created with the same password as the current wallet. You can open it by closing this current wallet, clicking the "Open wallet from file" option, and selecting the view wallet in: \n%1\nYou can change the password in the wallet settings.').arg(newPath);
81-
informationPopup.open()
82-
informationPopup.onCloseCallback = null
83-
} else {
84-
informationPopup.title = qsTr("Error") + translationManager.emptyString;
85-
informationPopup.text = currentWallet.errorString;
86-
informationPopup.open()
77+
passwordDialog.onAcceptedCallback = function() {
78+
if (currentWallet.createViewOnly(newPath, passwordDialog.password)) {
79+
console.log("view only wallet created in " + newPath);
80+
informationPopup.title = qsTr("Success") + translationManager.emptyString;
81+
informationPopup.text = qsTr('The view only wallet has been created. You can open it by closing this current wallet, clicking the "Open wallet from file" option, and selecting the view wallet in: \n%1').arg(newPath);
82+
informationPopup.open()
83+
informationPopup.onCloseCallback = null
84+
} else {
85+
informationPopup.title = qsTr("Error") + translationManager.emptyString;
86+
informationPopup.text = currentWallet.errorString;
87+
informationPopup.open()
88+
}
89+
memwipe.wipeQString(passwordDialog.password);
8790
}
91+
passwordDialog.onRejectedCallback = function() { memwipe.wipeQString(passwordDialog.password); }
92+
passwordDialog.open()
8893
}
8994
}
9095

@@ -165,18 +170,13 @@ Rectangle {
165170

166171
onClicked: {
167172
passwordDialog.onAcceptedCallback = function() {
168-
if(appWindow.walletPassword === passwordDialog.password){
173+
if (currentWallet.verifyPassword(passwordDialog.password, persistentSettings.kdfRounds)) {
169174
passwordDialog.openNewPasswordDialog()
170175
} else {
171-
informationPopup.title = qsTr("Error") + translationManager.emptyString;
172-
informationPopup.text = qsTr("Wrong password") + translationManager.emptyString;
173-
informationPopup.open()
174-
informationPopup.onCloseCallback = function() {
175-
passwordDialog.open()
176-
}
176+
passwordDialog.showError(qsTr("Wrong password") + translationManager.emptyString);
177177
}
178178
}
179-
passwordDialog.onRejectedCallback = null;
179+
passwordDialog.onRejectedCallback = function() { memwipe.wipeQString(passwordDialog.password); }
180180
passwordDialog.open()
181181
}
182182
}

src/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ file(GLOB SOURCE_FILES
2121
"libwalletqt/AddressBook.cpp"
2222
"libwalletqt/Subaddress.cpp"
2323
"libwalletqt/SubaddressAccount.cpp"
24+
"libwalletqt/Memwipe.cpp"
2425
"libwalletqt/UnsignedTransaction.cpp"
2526
"libwalletqt/WalletManager.h"
2627
"libwalletqt/Wallet.h"
@@ -33,6 +34,7 @@ file(GLOB SOURCE_FILES
3334
"libwalletqt/AddressBook.h"
3435
"libwalletqt/Subaddress.h"
3536
"libwalletqt/SubaddressAccount.h"
37+
"libwalletqt/Memwipe.h"
3638
"libwalletqt/UnsignedTransaction.h"
3739
"daemon/*.h"
3840
"daemon/*.cpp"

0 commit comments

Comments
 (0)