gdm: Limit verification cancellations to be conform to allowed-failures
As per previous commit the user can cancel an ongoing authentication via Escape key and that will always send the user back to the clock view in lockscreen or user-selection view in login prompt. However, we can be a little more permissive and don't switch view to be able to restart the authentication without further action. To avoid this to be abused though, we consider the user verification cancellation via escape key to be a "soft-failure", so once the configured "allowed-failures" gsettings value has been reached, we'd just act as before, ignoring any further request (until we don't get back to the user auth view). In this way we still make brute-force attacks harder to do, while still giving the well-behaving user some ability to fix mistakes. Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/1622>
This commit is contained in:
parent
7e77881717
commit
c8bb45b41c
@ -30,11 +30,13 @@ var AuthPromptStatus = {
|
|||||||
VERIFICATION_FAILED: 2,
|
VERIFICATION_FAILED: 2,
|
||||||
VERIFICATION_SUCCEEDED: 3,
|
VERIFICATION_SUCCEEDED: 3,
|
||||||
VERIFICATION_CANCELLED: 4,
|
VERIFICATION_CANCELLED: 4,
|
||||||
|
VERIFICATION_IN_PROGRESS: 5,
|
||||||
};
|
};
|
||||||
|
|
||||||
var BeginRequestType = {
|
var BeginRequestType = {
|
||||||
PROVIDE_USERNAME: 0,
|
PROVIDE_USERNAME: 0,
|
||||||
DONT_PROVIDE_USERNAME: 1,
|
DONT_PROVIDE_USERNAME: 1,
|
||||||
|
REUSE_USERNAME: 2,
|
||||||
};
|
};
|
||||||
|
|
||||||
var AuthPrompt = GObject.registerClass({
|
var AuthPrompt = GObject.registerClass({
|
||||||
@ -59,6 +61,7 @@ var AuthPrompt = GObject.registerClass({
|
|||||||
this._gdmClient = gdmClient;
|
this._gdmClient = gdmClient;
|
||||||
this._mode = mode;
|
this._mode = mode;
|
||||||
this._defaultButtonWellActor = null;
|
this._defaultButtonWellActor = null;
|
||||||
|
this._cancelledRetries = 0;
|
||||||
|
|
||||||
let reauthenticationOnly;
|
let reauthenticationOnly;
|
||||||
if (this._mode == AuthPromptMode.UNLOCK_ONLY)
|
if (this._mode == AuthPromptMode.UNLOCK_ONLY)
|
||||||
@ -196,6 +199,7 @@ var AuthPrompt = GObject.registerClass({
|
|||||||
}
|
}
|
||||||
|
|
||||||
_activateNext(shouldSpin) {
|
_activateNext(shouldSpin) {
|
||||||
|
this.verificationStatus = AuthPromptStatus.VERIFICATION_IN_PROGRESS;
|
||||||
this.updateSensitivity(false);
|
this.updateSensitivity(false);
|
||||||
|
|
||||||
if (shouldSpin)
|
if (shouldSpin)
|
||||||
@ -501,6 +505,9 @@ var AuthPrompt = GObject.registerClass({
|
|||||||
// We don't need to know the username if the user preempted the login screen
|
// We don't need to know the username if the user preempted the login screen
|
||||||
// with a smartcard or with preauthenticated oVirt credentials
|
// with a smartcard or with preauthenticated oVirt credentials
|
||||||
beginRequestType = BeginRequestType.DONT_PROVIDE_USERNAME;
|
beginRequestType = BeginRequestType.DONT_PROVIDE_USERNAME;
|
||||||
|
} else if (oldStatus === AuthPromptStatus.VERIFICATION_IN_PROGRESS) {
|
||||||
|
// We're going back to retry with current user
|
||||||
|
beginRequestType = BeginRequestType.REUSE_USERNAME;
|
||||||
} else {
|
} else {
|
||||||
// In all other cases, we should get the username up front.
|
// In all other cases, we should get the username up front.
|
||||||
beginRequestType = BeginRequestType.PROVIDE_USERNAME;
|
beginRequestType = BeginRequestType.PROVIDE_USERNAME;
|
||||||
@ -549,7 +556,14 @@ var AuthPrompt = GObject.registerClass({
|
|||||||
if (this.verificationStatus == AuthPromptStatus.VERIFICATION_SUCCEEDED)
|
if (this.verificationStatus == AuthPromptStatus.VERIFICATION_SUCCEEDED)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (this.verificationStatus === AuthPromptStatus.VERIFICATION_IN_PROGRESS) {
|
||||||
|
this._cancelledRetries++;
|
||||||
|
if (this._cancelledRetries > this._userVerifier.allowedFailures)
|
||||||
|
this.verificationStatus = AuthPromptStatus.VERIFICATION_FAILED;
|
||||||
|
} else {
|
||||||
this.verificationStatus = AuthPromptStatus.VERIFICATION_CANCELLED;
|
this.verificationStatus = AuthPromptStatus.VERIFICATION_CANCELLED;
|
||||||
|
}
|
||||||
|
|
||||||
this.reset();
|
this.reset();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -855,6 +855,7 @@ var LoginDialog = GObject.registerClass({
|
|||||||
this._resetGreeterProxy();
|
this._resetGreeterProxy();
|
||||||
this._sessionMenuButton.updateSensitivity(true);
|
this._sessionMenuButton.updateSensitivity(true);
|
||||||
|
|
||||||
|
const previousUser = this._user;
|
||||||
this._user = null;
|
this._user = null;
|
||||||
|
|
||||||
if (this._nextSignalId) {
|
if (this._nextSignalId) {
|
||||||
@ -862,7 +863,11 @@ var LoginDialog = GObject.registerClass({
|
|||||||
this._nextSignalId = 0;
|
this._nextSignalId = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (beginRequest == AuthPrompt.BeginRequestType.PROVIDE_USERNAME) {
|
if (previousUser && beginRequest === AuthPrompt.BeginRequestType.REUSE_USERNAME) {
|
||||||
|
this._user = previousUser;
|
||||||
|
this._authPrompt.setUser(this._user);
|
||||||
|
this._authPrompt.begin({ userName: previousUser.get_user_name() });
|
||||||
|
} else if (beginRequest === AuthPrompt.BeginRequestType.PROVIDE_USERNAME) {
|
||||||
if (!this._disableUserList)
|
if (!this._disableUserList)
|
||||||
this._showUserList();
|
this._showUserList();
|
||||||
else
|
else
|
||||||
|
@ -192,6 +192,10 @@ var ShellUserVerifier = class {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get allowedFailures() {
|
||||||
|
return this._settings.get_int(ALLOWED_FAILURES_KEY);
|
||||||
|
}
|
||||||
|
|
||||||
begin(userName, hold) {
|
begin(userName, hold) {
|
||||||
this._cancellable = new Gio.Cancellable();
|
this._cancellable = new Gio.Cancellable();
|
||||||
this._hold = hold;
|
this._hold = hold;
|
||||||
|
Loading…
Reference in New Issue
Block a user