From 809f820cd4a4eebb120ab5dde3f1985d35bcb540 Mon Sep 17 00:00:00 2001 From: yun341 <5933468@qq.com> Date: Sat, 4 Jan 2020 00:31:15 +0800 Subject: [PATCH] gdm: Refactor oVirt to a generic CredentialManager interface Commit 4cda61a1 added support for pre-authenticated logins in oVirt environments. This feature prevents a user from having to type their password twice (once to the oVirt management machine, and then immediately again in the provisioned guest running gnome-shell). That feature is currently oVirt specific, but a similar feature would be useful in non-oVirt based virt farm environments. Toward that end, this commit generalizes the various aspects of the oVirt integration code, so that it can be reused in a subsequent commit for adding single sign on support in vmware deployments, too. Closes: https://gitlab.gnome.org/GNOME/gnome-shell/issues/1983 --- js/gdm/authPrompt.js | 4 ++-- js/gdm/credentialManager.js | 24 +++++++++++++++++++ js/gdm/oVirt.js | 29 +++++++--------------- js/gdm/util.js | 45 ++++++++++++++++++++++------------- js/js-resources.gresource.xml | 1 + 5 files changed, 64 insertions(+), 39 deletions(-) create mode 100644 js/gdm/credentialManager.js diff --git a/js/gdm/authPrompt.js b/js/gdm/authPrompt.js index 29170c555..e535d0f1d 100644 --- a/js/gdm/authPrompt.js +++ b/js/gdm/authPrompt.js @@ -71,7 +71,7 @@ var AuthPrompt = GObject.registerClass({ this._userVerifier.connect('verification-complete', this._onVerificationComplete.bind(this)); this._userVerifier.connect('reset', this._onReset.bind(this)); this._userVerifier.connect('smartcard-status-changed', this._onSmartcardStatusChanged.bind(this)); - this._userVerifier.connect('ovirt-user-authenticated', this._onOVirtUserAuthenticated.bind(this)); + this._userVerifier.connect('credential-manager-authenticated', this._onCredentialManagerAuthenticated.bind(this)); this.smartcardDetected = this._userVerifier.smartcardDetected; this.connect('destroy', this._onDestroy.bind(this)); @@ -242,7 +242,7 @@ var AuthPrompt = GObject.registerClass({ this.emit('prompted'); } - _onOVirtUserAuthenticated() { + _onCredentialManagerAuthenticated() { if (this.verificationStatus != AuthPromptStatus.VERIFICATION_SUCCEEDED) this.reset(); } diff --git a/js/gdm/credentialManager.js b/js/gdm/credentialManager.js new file mode 100644 index 000000000..cf001f4e4 --- /dev/null +++ b/js/gdm/credentialManager.js @@ -0,0 +1,24 @@ +// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- +/* exported CredentialManager */ + +class CredentialManager { + constructor(service) { + this._token = null; + this._service = service; + this._authenticatedSignalId = null; + } + + get token() { + return this._token; + } + + set token(t) { + this._token = t; + if (this._token) + this.emit('user-authenticated', this._token); + } + + get service() { + return this._service; + } +} diff --git a/js/gdm/oVirt.js b/js/gdm/oVirt.js index ff664f249..94a22b823 100644 --- a/js/gdm/oVirt.js +++ b/js/gdm/oVirt.js @@ -3,6 +3,9 @@ const Gio = imports.gi.Gio; const Signals = imports.signals; +const Credential = imports.gdm.credentialManager; + +var SERVICE_NAME = 'gdm-ovirtcred'; const OVirtCredentialsIface = ` @@ -28,30 +31,14 @@ function OVirtCredentials() { return self; } -var OVirtCredentialsManager = class { +var OVirtCredentialsManager = class OVirtCredentialsManager extends Credential.CredentialManager { constructor() { - this._token = null; - + super(SERVICE_NAME); this._credentials = new OVirtCredentials(); this._credentials.connectSignal('UserAuthenticated', - this._onUserAuthenticated.bind(this)); - } - - _onUserAuthenticated(proxy, sender, [token]) { - this._token = token; - this.emit('user-authenticated', token); - } - - hasToken() { - return this._token != null; - } - - getToken() { - return this._token; - } - - resetToken() { - this._token = null; + (proxy, sender, [token]) => { + this.token = token; + }); } }; Signals.addSignalMethods(OVirtCredentialsManager.prototype); diff --git a/js/gdm/util.js b/js/gdm/util.js index cc3fe3934..fc7df2706 100644 --- a/js/gdm/util.js +++ b/js/gdm/util.js @@ -24,7 +24,6 @@ Gio._promisify(Gdm.UserVerifierProxy.prototype, var PASSWORD_SERVICE_NAME = 'gdm-password'; var FINGERPRINT_SERVICE_NAME = 'gdm-fingerprint'; var SMARTCARD_SERVICE_NAME = 'gdm-smartcard'; -var OVIRT_SERVICE_NAME = 'gdm-ovirtcred'; var FADE_ANIMATION_TIME = 160; var CLONE_FADE_ANIMATION_TIME = 250; @@ -160,13 +159,19 @@ var ShellUserVerifier = class { this._failCounter = 0; - this._oVirtCredentialsManager = OVirt.getOVirtCredentialsManager(); + this._credentialManagers = {}; + this._credentialManagers[OVirt.SERVICE_NAME] = OVirt.getOVirtCredentialsManager(); - if (this._oVirtCredentialsManager.hasToken()) - this._oVirtUserAuthenticated(this._oVirtCredentialsManager.getToken()); + for (let service in this._credentialManagers) { + if (this._credentialManagers[service].token) { + this._onCredentialManagerAuthenticated(this._credentialManagers[service], + this._credentialManagers[service].token); + } - this._oVirtUserAuthenticatedId = this._oVirtCredentialsManager.connect('user-authenticated', - this._oVirtUserAuthenticated.bind(this)); + this._credentialManagers[service]._authenticatedSignalId = + this._credentialManagers[service].connect('user-authenticated', + this._onCredentialManagerAuthenticated.bind(this)); + } } begin(userName, hold) { @@ -222,8 +227,11 @@ var ShellUserVerifier = class { this._smartcardManager.disconnect(this._smartcardRemovedId); this._smartcardManager = null; - this._oVirtCredentialsManager.disconnect(this._oVirtUserAuthenticatedId); - this._oVirtCredentialsManager = null; + for (let service in this._credentialManagers) { + let credentialManager = this._credentialManagers[service]; + credentialManager.disconnect(credentialManager._authenticatedSignalId); + credentialManager = null; + } } answerQuery(serviceName, answer) { @@ -311,9 +319,9 @@ var ShellUserVerifier = class { }); } - _oVirtUserAuthenticated(_token) { - this._preemptingService = OVIRT_SERVICE_NAME; - this.emit('ovirt-user-authenticated'); + _onCredentialManagerAuthenticated(credentialManager, _token) { + this._preemptingService = credentialManager.service; + this.emit('credential-manager-authenticated'); } _checkForSmartcard() { @@ -490,9 +498,12 @@ var ShellUserVerifier = class { if (!this.serviceIsForeground(serviceName)) return; - if (serviceName == OVIRT_SERVICE_NAME) { - // The only question asked by this service is "Token?" - this.answerQuery(serviceName, this._oVirtCredentialsManager.getToken()); + let token = null; + if (this._credentialManagers[serviceName]) + token = this._credentialManagers[serviceName].token; + + if (token) { + this.answerQuery(serviceName, token); return; } @@ -560,8 +571,10 @@ var ShellUserVerifier = class { // If the login failed with the preauthenticated oVirt credentials // then discard the credentials and revert to default authentication // mechanism. - if (this.serviceIsForeground(OVIRT_SERVICE_NAME)) { - this._oVirtCredentialsManager.resetToken(); + let foregroundService = Object.keys(this._credentialManagers).find(service => + this.serviceIsForeground(service)); + if (foregroundService) { + this._credentialManagers[foregroundService].token = null; this._preemptingService = null; this._verificationFailed(false); return; diff --git a/js/js-resources.gresource.xml b/js/js-resources.gresource.xml index c0a77eddc..cf9bd8ddf 100644 --- a/js/js-resources.gresource.xml +++ b/js/js-resources.gresource.xml @@ -6,6 +6,7 @@ gdm/fingerprint.js gdm/loginDialog.js gdm/oVirt.js + gdm/credentialManager.js gdm/realmd.js gdm/util.js