@@ -216,38 +216,37 @@ Showable {
218 onTriggered: {
218 onTriggered: {
219− var now = new Date();
219+ var diff = delayTarget - new Date();
221+ delayMinutes = Math.ceil(diff / 60000);
222+ start(); // go again
228+ function checkForForcedDelay() {
229+ if (greeterSettings.lockedOutTime === 0) {
221− // We're going to compare stored time to system time here.
233+ var now = new Date();
222− // - We do this every tick (rather than just once at the start)
234+ delayTarget = new Date(greeterSettings.lockedOutTime + failedLoginsDelayMinutes * 60000);
223− // because clock time can change while we're running. For example,
224− // ntpdate runs as an ifupdown script.
225− // - And we trust this check because if a malicious actor is able
226− // to manipulate time to avoid our lockout, there's not much we
227− // can do to stop them.
229 // If tooEarly is true, something went very wrong. Bug or NTP
236 // If tooEarly is true, something went very wrong. Bug or NTP
230 // misconfiguration maybe?
237 // misconfiguration maybe?
231 var tooEarly = now.getTime() < greeterSettings.lockedOutTime;
238 var tooEarly = now.getTime() < greeterSettings.lockedOutTime;
232 var tooLate = now >= delayTarget;
239 var tooLate = now >= delayTarget;
241+ // Compare stored time to system time. If a malicious actor is
242+ // able to manipulate time to avoid our lockout, they already have
243+ // enough access to cause damage. So we choose to trust this check.
234 if (tooEarly || tooLate) {
244 if (tooEarly || tooLate) {
236 delayMinutes = 0;
246 delayMinutes = 0;
238− var diff = delayTarget - now;
248+ triggered();
239− delayMinutes = Math.ceil(diff / 60000);
240− start(); // go again
244− function checkForForcedDelay() {
245− if (greeterSettings.lockedOutTime === 0) {
249− delayTarget = new Date(greeterSettings.lockedOutTime + failedLoginsDelayMinutes * 60000);
253 Component.onCompleted: checkForForcedDelay()
252 Component.onCompleted: checkForForcedDelay()