on xenial help sign in
Support locking user out for five seconds after five failed entries
commit551a66199e66763ac5d69002c364a8f7bd4ed31c authorMichael Terry <michael.terry@canonical.com> dateThu 31 Jul 2014, 16:52 (12 years ago) parentaf704d7
5 files changed+40−5
qml/Components/Lockscreen.qml+32−1 qml/Components/PassphraseLockscreen.qml+2−2 qml/Components/PinLockscreen.qml+1−1 qml/Notifications/NotificationMenuItemFactory.qml−1 qml/Shell.qml+5
qml/Components/Lockscreen.qml+32−1
@@ -57,26 +57,37 @@ Showable {
5757
5858 onRequiredChanged: {
5959 if (required && pinPadLoader.item) {
60− pinPadLoader.item.clear(false);
60+ clear(false)
6161 }
6262 }
6363
64+ function forceDelay(delay) {
65+ forcedDelayTimer.interval = delay
66+ forcedDelayTimer.start()
67+ }
68+
6469 function reset() {
6570 // This causes the loader below to destry and recreate the source
6671 pinPadLoader.resetting = true;
6772 pinPadLoader.resetting = false;
73+ pinPadLoader.waiting = false
6874 }
6975
7076 function clear(showAnimation) {
7177 if (pinPadLoader.item) {
7278 pinPadLoader.item.clear(showAnimation);
7379 }
80+ pinPadLoader.waiting = false
7481 }
7582
7683 function showInfoPopup(title, text) {
7784 PopupUtils.open(infoPopupComponent, root, {title: title, text: text})
7885 }
7986
87+ Timer {
88+ id: forcedDelayTimer
89+ }
90+
8091 Rectangle {
8192 // In case background fails to load or is undefined
8293 id: backgroundBackup
@@ -106,6 +117,19 @@ Showable {
106117 bottom: pinPadLoader.top
107118 bottomMargin: units.gu(2)
108119 }
120+ Label {
121+ id: delayTextLabel
122+ objectName: "delayTextLabel"
123+ anchors {
124+ left: parent.left
125+ right: parent.right
126+ }
127+ text: i18n.tr("Too many incorrect attempts, please wait")
128+ horizontalAlignment: Text.AlignHCenter
129+ color: "#f3f3e7"
130+ opacity: 0.6
131+ visible: forcedDelayTimer.running
132+ }
109133 Label {
110134 objectName: "retryCountLabel"
111135 anchors {
@@ -145,6 +169,7 @@ Showable {
145169 verticalCenterOffset: root.alphaNumeric ? -units.gu(10) : -units.gu(4)
146170 }
147171 property bool resetting: false
172+ property bool waiting: false
148173
149174 source: (!resetting && root.required) ? (root.alphaNumeric ? "PassphraseLockscreen.qml" : "PinLockscreen.qml") : ""
150175
@@ -152,6 +177,7 @@ Showable {
152177 target: pinPadLoader.item
153178
154179 onEntered: {
180+ pinPadLoader.waiting = true
155181 root.entered(passphrase);
156182 }
157183
@@ -185,6 +211,11 @@ Showable {
185211 property: "username"
186212 value: root.username
187213 }
214+ Binding {
215+ target: pinPadLoader.item
216+ property: "entryEnabled"
217+ value: !pinPadLoader.waiting && !forcedDelayTimer.running
218+ }
188219 }
189220
190221 Column {
qml/Components/PassphraseLockscreen.qml+2−2
@@ -25,13 +25,13 @@ Item {
2525 property string placeholderText
2626 property string wrongPlaceholderText
2727 property string username: ""
28+ property bool entryEnabled: true
2829
2930 signal entered(string passphrase)
3031 signal cancel()
3132
3233 function clear(playAnimation) {
3334 pinentryField.text = "";
34− pinentryField.enabled = true
3535 if (playAnimation) {
3636 wrongPasswordAnimation.start();
3737 pinentryField.forceActiveFocus();
@@ -76,11 +76,11 @@ Item {
7676 echoMode: TextInput.Password
7777 opacity: 0.9
7878 hasClearButton: false
79+ enabled: entryEnabled
7980 placeholderText: wrongPasswordAnimation.running ? root.wrongPlaceholderText : root.placeholderText
8081
8182 onAccepted: {
8283 if (pinentryField.text) {
83− pinentryField.enabled = false;
8484 root.entered(pinentryField.text);
8585 }
8686 }
qml/Components/PinLockscreen.qml+1−1
@@ -223,7 +223,7 @@ Column {
223223 root.entered(pinentryField.text);
224224 }
225225 }
226− enabled: priv.autoConfirm ? entryEnabled : pinentryField.text.length >= root.minPinLength
226+ enabled: entryEnabled
227227 }
228228 }
229229 }
qml/Notifications/NotificationMenuItemFactory.qml−1
@@ -114,7 +114,6 @@ Loader {
114114
115115 onEntered: {
116116 menuModel.changeState(menuIndex, passphrase);
117− entryEnabled = false;
118117 }
119118
120119 onCancel: {
qml/Shell.qml+5
@@ -55,6 +55,8 @@ Item {
5555 readonly property string focusedApplicationId: ApplicationManager.focusedApplicationId
5656
5757 property int maxFailedLogins: -1 // disabled by default for now, will enable via settings in future
58+ property int failedLoginsDelayAttempts: 5 // number of failed logins
59+ property int failedLoginsDelaySeconds: 5 // seconds of forced waiting
5860
5961 function activateApplication(appId) {
6062 if (ApplicationManager.findApplication(appId)) {
@@ -433,6 +435,9 @@ Item {
433435 SystemImage.factoryReset() // Ouch!
434436 }
435437 }
438+ if (failedLoginsDelayAttempts > 0 && AccountsService.failedLogins % failedLoginsDelayAttempts == 0) {
439+ lockscreen.forceDelay(failedLoginsDelaySeconds * 1000)
440+ }
436441
437442 lockscreen.clear(true);
438443 if (greeter.narrowMode) {