ShellUserVerifier: catch DBus errors and report them to the user
Instead of leaving the login or unlock dialogs in an inconsistent state, catch DBus errors and show an Authentication Error message. The error details are logged in the session logs. https://bugzilla.gnome.org/show_bug.cgi?id=683060
This commit is contained in:
parent
5e12e5f42a
commit
10884ef7f5
@ -649,6 +649,10 @@ const LoginDialog = new Lang.Class({
|
|||||||
this._userVerifier.connect('ask-question', Lang.bind(this, this._askQuestion));
|
this._userVerifier.connect('ask-question', Lang.bind(this, this._askQuestion));
|
||||||
this._userVerifier.connect('show-message', Lang.bind(this, this._showMessage));
|
this._userVerifier.connect('show-message', Lang.bind(this, this._showMessage));
|
||||||
this._userVerifier.connect('reset', Lang.bind(this, this._onReset));
|
this._userVerifier.connect('reset', Lang.bind(this, this._onReset));
|
||||||
|
this._userVerifier.connect('not-supported', Lang.bind(this, function(verifier, error) {
|
||||||
|
Main.notifyError(_("Configuration problem: Could not connect to GDM"), error.message);
|
||||||
|
this._onReset();
|
||||||
|
}));
|
||||||
|
|
||||||
this._userVerifier.connect('show-login-hint', Lang.bind(this, this._showLoginHint));
|
this._userVerifier.connect('show-login-hint', Lang.bind(this, this._showLoginHint));
|
||||||
this._userVerifier.connect('hide-login-hint', Lang.bind(this, this._hideLoginHint));
|
this._userVerifier.connect('hide-login-hint', Lang.bind(this, this._hideLoginHint));
|
||||||
|
@ -141,34 +141,43 @@ const ShellUserVerifier = new Lang.Class({
|
|||||||
}));
|
}));
|
||||||
},
|
},
|
||||||
|
|
||||||
|
_reportInitError: function(where, error) {
|
||||||
|
logError(error, where);
|
||||||
|
this._hold.relase();
|
||||||
|
|
||||||
|
this.emit('show-message', _("Authentication error"), 'login-dialog-message-warning');
|
||||||
|
this._verificationFailed(false);
|
||||||
|
},
|
||||||
|
|
||||||
_reauthenticationChannelOpened: function(client, result) {
|
_reauthenticationChannelOpened: function(client, result) {
|
||||||
try {
|
try {
|
||||||
this._userVerifier = client.open_reauthentication_channel_finish(result);
|
this._userVerifier = client.open_reauthentication_channel_finish(result);
|
||||||
this._connectSignals();
|
} catch(e if e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) {
|
||||||
this._beginVerification();
|
return;
|
||||||
|
} catch(e if e.matches(Gio.DBusError, Gio.DBusError.ACCESS_DENIED) &&
|
||||||
this._hold.release();
|
!this._reauthOnly) {
|
||||||
} catch (e) {
|
// Gdm emits org.freedesktop.DBus.Error.AccessDenied when there is
|
||||||
if (this._reauthOnly) {
|
// no session to reauthenticate. Fall back to performing verification
|
||||||
if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED))
|
// from this login session
|
||||||
return;
|
|
||||||
|
|
||||||
logError(e, 'Failed to open reauthentication channel');
|
|
||||||
this.emit('verification-failed');
|
|
||||||
this._hold.release();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If there's no session running, or it otherwise fails, then fall back
|
|
||||||
// to performing verification from this login session
|
|
||||||
client.get_user_verifier(this._cancellable, Lang.bind(this, this._userVerifierGot));
|
client.get_user_verifier(this._cancellable, Lang.bind(this, this._userVerifierGot));
|
||||||
|
return;
|
||||||
|
} catch(e) {
|
||||||
|
this._reportInitError('Failed to open reauthentication channel', e);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this._connectSignals();
|
||||||
|
this._beginVerification();
|
||||||
|
this._hold.release();
|
||||||
},
|
},
|
||||||
|
|
||||||
_userVerifierGot: function(client, result) {
|
_userVerifierGot: function(client, result) {
|
||||||
try {
|
try {
|
||||||
this._userVerifier = client.get_user_verifier_finish(result);
|
this._userVerifier = client.get_user_verifier_finish(result);
|
||||||
} catch(e if e.matches(Gio.IOErrorEnum, Gio.ErrorEnum.CANCELLED)) {
|
} catch(e if e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) {
|
||||||
|
return;
|
||||||
|
} catch(e) {
|
||||||
|
this._reportInitError('Failed to obtain user verifier', e);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -199,6 +208,9 @@ const ShellUserVerifier = new Lang.Class({
|
|||||||
obj.call_begin_verification_for_user_finish(result);
|
obj.call_begin_verification_for_user_finish(result);
|
||||||
} catch(e if e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) {
|
} catch(e if e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) {
|
||||||
return;
|
return;
|
||||||
|
} catch(e) {
|
||||||
|
this._reportInitError('Failed to start verification for user', e);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this._hold.release();
|
this._hold.release();
|
||||||
@ -215,6 +227,9 @@ const ShellUserVerifier = new Lang.Class({
|
|||||||
obj.call_begin_verification_for_user_finish(result);
|
obj.call_begin_verification_for_user_finish(result);
|
||||||
} catch(e if e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) {
|
} catch(e if e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) {
|
||||||
return;
|
return;
|
||||||
|
} catch(e) {
|
||||||
|
this._reportInitError('Failed to start fingerprint verification for user', e);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this._hold.release();
|
this._hold.release();
|
||||||
@ -228,6 +243,9 @@ const ShellUserVerifier = new Lang.Class({
|
|||||||
obj.call_begin_verification_finish(result);
|
obj.call_begin_verification_finish(result);
|
||||||
} catch(e if e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) {
|
} catch(e if e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) {
|
||||||
return;
|
return;
|
||||||
|
} catch(e) {
|
||||||
|
this._reportInitError('Failed to start verification', e);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this._hold.release();
|
this._hold.release();
|
||||||
@ -306,23 +324,27 @@ const ShellUserVerifier = new Lang.Class({
|
|||||||
this.emit('verification-complete');
|
this.emit('verification-complete');
|
||||||
},
|
},
|
||||||
|
|
||||||
_verificationFailed: function() {
|
_verificationFailed: function(retry) {
|
||||||
// For Not Listed / enterprise logins, immediately reset
|
// For Not Listed / enterprise logins, immediately reset
|
||||||
// the dialog
|
// the dialog
|
||||||
// Otherwise, we allow ALLOWED_FAILURES attempts. After that, we
|
// Otherwise, we allow ALLOWED_FAILURES attempts. After that, we
|
||||||
// go back to the welcome screen.
|
// go back to the welcome screen.
|
||||||
|
|
||||||
if (!this._userName ||
|
let canRetry = retry && this._userName &&
|
||||||
(++this._failCounter) == this._settings.get_int(ALLOWED_FAILURES_KEY)) {
|
this._failCounter < this._settings.get_int(ALLOWED_FAILURES_KEY);
|
||||||
|
|
||||||
|
if (canRetry) {
|
||||||
|
this._failCounter++;
|
||||||
|
|
||||||
|
this.clear();
|
||||||
|
this.begin(this._userName, new Batch.Hold());
|
||||||
|
} else {
|
||||||
// Allow some time to see the message, then reset everything
|
// Allow some time to see the message, then reset everything
|
||||||
Mainloop.timeout_add(3000, Lang.bind(this, function() {
|
Mainloop.timeout_add(3000, Lang.bind(this, function() {
|
||||||
this.cancel();
|
this.cancel();
|
||||||
|
|
||||||
this._onReset();
|
this._onReset();
|
||||||
}));
|
}));
|
||||||
} else {
|
|
||||||
this.clear();
|
|
||||||
this.begin(this._userName, new Batch.Hold());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.emit('verification-failed');
|
this.emit('verification-failed');
|
||||||
@ -333,7 +355,7 @@ const ShellUserVerifier = new Lang.Class({
|
|||||||
// But if, e.g., fingerprint fails, still give
|
// But if, e.g., fingerprint fails, still give
|
||||||
// password authentication a chance to succeed
|
// password authentication a chance to succeed
|
||||||
if (serviceName == PASSWORD_SERVICE_NAME) {
|
if (serviceName == PASSWORD_SERVICE_NAME) {
|
||||||
this._verificationFailed();
|
this._verificationFailed(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.emit('hide-login-hint');
|
this.emit('hide-login-hint');
|
||||||
|
@ -133,6 +133,12 @@ const UnlockDialog = new Lang.Class({
|
|||||||
this._userVerifier.connect('show-login-hint', Lang.bind(this, this._showLoginHint));
|
this._userVerifier.connect('show-login-hint', Lang.bind(this, this._showLoginHint));
|
||||||
this._userVerifier.connect('hide-login-hint', Lang.bind(this, this._hideLoginHint));
|
this._userVerifier.connect('hide-login-hint', Lang.bind(this, this._hideLoginHint));
|
||||||
|
|
||||||
|
this._userVerifier.connect('not-supported', Lang.bind(this, function(verifier, error) {
|
||||||
|
Main.notifyError(_("Could not connect to GDM. Screen locking was automatically disabled."), error.message);
|
||||||
|
this._userVerifier.clear();
|
||||||
|
this.emit('unlocked');
|
||||||
|
}));
|
||||||
|
|
||||||
this._userWidget = new UserWidget(this._user);
|
this._userWidget = new UserWidget(this._user);
|
||||||
this.contentLayout.add_actor(this._userWidget.actor);
|
this.contentLayout.add_actor(this._userWidget.actor);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user