Merge branch 'secure-lock' into 'main'

Draft: Support secure locking

See merge request GNOME/gnome-shell!3258
This commit is contained in:
Adrian Vovk 2024-06-27 18:29:24 +00:00
commit d0ffa5860e
5 changed files with 64 additions and 23 deletions

View file

@ -52,6 +52,7 @@ export const AuthPrompt = GObject.registerClass({
'next': {},
'prompted': {},
'reset': {param_types: [GObject.TYPE_UINT]},
'verified': {},
},
}, class AuthPrompt extends St.BoxLayout {
_init(gdmClient, mode) {
@ -404,6 +405,7 @@ export const AuthPrompt = GObject.registerClass({
this.verificationStatus = AuthPromptStatus.VERIFICATION_SUCCEEDED;
this.cancelButton.reactive = false;
this.cancelButton.can_focus = false;
this.emit('verified');
}
_onReset() {

View file

@ -125,7 +125,7 @@ class LoginManagerSystemd extends Signals.EventEmitter {
'org.freedesktop.login1',
objectPath);
log(`Considering ${session}, class=${sessionProxy.Class}`);
if (sessionProxy.Class === 'greeter') {
if (sessionProxy.Class === 'greeter' || sessionProxy.Class === "lock-screen") {
log(`Yes, will monitor session ${session}`);
sessionId = session;
break;

View file

@ -178,7 +178,7 @@ export class ScreenShield extends Signals.EventEmitter {
_activateDialog() {
if (this._isLocked) {
this._ensureUnlockDialog(true /* allowCancel */);
this._ensureUnlockDialog();
this._dialog.activate();
} else {
this.deactivate(true /* animate */);
@ -357,7 +357,8 @@ export class ScreenShield extends Signals.EventEmitter {
this.actor.show();
this._isGreeter = Main.sessionMode.isGreeter;
this._isLocked = true;
this._ensureUnlockDialog(true);
this._lockScreenState = MessageTray.State.SHOWN;
this._ensureUnlockDialog();
}
_hideLockScreenComplete() {
@ -416,7 +417,7 @@ export class ScreenShield extends Signals.EventEmitter {
this._showPointer();
}
_ensureUnlockDialog(allowCancel) {
_ensureUnlockDialog() {
if (!this._dialog) {
let constructor = Main.sessionMode.unlockDialog;
if (!constructor) {
@ -440,7 +441,6 @@ export class ScreenShield extends Signals.EventEmitter {
'wake-up-screen', this._wakeUpScreen.bind(this));
}
this._dialog.allowCancel = allowCancel;
this._dialog.grab_key_focus();
return true;
}
@ -605,7 +605,7 @@ export class ScreenShield extends Signals.EventEmitter {
if (this._activationTime === 0)
this._activationTime = GLib.get_monotonic_time();
if (!this._ensureUnlockDialog(true))
if (!this._ensureUnlockDialog())
return;
this.actor.show();
@ -620,6 +620,7 @@ export class ScreenShield extends Signals.EventEmitter {
animateLockScreen: animate,
fadeToBlack: true,
});
// On wayland, a crash brings down the entire session, so we don't
// need to defend against being restarted unlocked
if (!Meta.is_wayland_compositor())

View file

@ -78,6 +78,19 @@ const _modes = {
panelStyle: 'unlock-screen',
},
'lock-screen': {
isGreeter: true,
isPrimary: true,
unlockDialog: UnlockDialog,
components: ['polkitAgent'],
panel: {
left: [],
center: [],
right: ['dwellClick', 'a11y', 'keyboard', 'quickSettings'],
},
panelStyle: 'unlock-screen',
},
'user': {
hasOverview: true,
showCalendarEvents: true,

View file

@ -535,21 +535,38 @@ export const UnlockDialog = GObject.registerClass({
this.add_action(tapAction);
// Background
this._backgroundGroup = new Clutter.Actor();
this.add_child(this._backgroundGroup);
if (!Main.sessionMode.isGreeter) {
// We don't currently support storing a background picture for
// user accounts, so for now the secure lock screen will just have
// a blank background.
this._bgManagers = [];
this._backgroundGroup = new Clutter.Actor();
this.add_child(this._backgroundGroup);
const themeContext = St.ThemeContext.get_for_stage(global.stage);
themeContext.connectObject('notify::scale-factor',
() => this._updateBackgroundEffects(), this);
this._bgManagers = [];
this._updateBackgrounds();
Main.layoutManager.connectObject('monitors-changed',
this._updateBackgrounds.bind(this), this);
const themeContext = St.ThemeContext.get_for_stage(global.stage);
themeContext.connectObject('notify::scale-factor',
() => this._updateBackgroundEffects(), this);
this._updateBackgrounds();
Main.layoutManager.connectObject('monitors-changed',
this._updateBackgrounds.bind(this), this);
}
this._userManager = AccountsService.UserManager.get_default();
this._userName = GLib.get_user_name();
if (!Main.sessionMode.isGreeter) {
this._userName = GLib.get_user_name();
} else {
this._userName = GLib.getenv('GDM_LOCK_SCREEN_USER');
if (!this._userName) {
// In the secure lock screen, this is a hard error. Fail-whale
const error = new GLib.Error(
Gio.IOErrorEnum, Gio.IOErrorEnum.FAILED,
'Could not get user for GDM lock screen');
global.context.terminate_with_error(error);
}
}
this._user = this._userManager.get_user(this._userName);
// Authentication & Clock stack
@ -565,8 +582,6 @@ export const UnlockDialog = GObject.registerClass({
this._stack.add_child(this._clock);
this._showClock();
this.allowCancel = false;
Main.ctrlAltTabManager.addGroup(this, _('Unlock Window'), 'dialog-password-symbolic');
// Notifications
@ -706,6 +721,7 @@ export const UnlockDialog = GObject.registerClass({
this._authPrompt.connect('failed', this._fail.bind(this));
this._authPrompt.connect('cancelled', this._fail.bind(this));
this._authPrompt.connect('reset', this._onReset.bind(this));
this._authPrompt.connect('verified', this._onVerified.bind(this));
this._promptBox.add_child(this._authPrompt);
}
@ -802,8 +818,16 @@ export const UnlockDialog = GObject.registerClass({
this._authPrompt.begin({userName});
}
_onVerified() {
// Make sure we don't get stuck at the successfully authenticated
// prompt, when we're running as the secure lock screen in GDM and
// the user immediately re-triggers a secure-lock
if (Main.sessionMode.isGreeter)
this._showClock();
}
_escape() {
if (this._authPrompt && this.allowCancel)
if (this._authPrompt && !Main.sessionMode.isGreeter)
this._authPrompt.cancel();
}
@ -862,10 +886,11 @@ export const UnlockDialog = GObject.registerClass({
}
_updateUserSwitchVisibility() {
this._otherUserButton.visible = this._userManager.can_switch() &&
this._userManager.has_multiple_users &&
this._screenSaverSettings.get_boolean('user-switch-enabled') &&
!this._lockdownSettings.get_boolean('disable-user-switching');
let needed = this._userManager.can_switch() &&
this._userManager.has_multiple_users;
let enabled = this._screenSaverSettings.get_boolean('user-switch-enabled') &&
!this._lockdownSettings.get_boolean('disable-user-switching');
this._otherUserButton.visible = needed && (enabled || Main.sessionMode.isGreeter);
}
cancel() {