diff --git a/js/Makefile.am b/js/Makefile.am index 7df786f2a..d614f4fc0 100644 --- a/js/Makefile.am +++ b/js/Makefile.am @@ -21,6 +21,7 @@ nobase_dist_js_DATA = \ gdm/batch.js \ gdm/fingerprint.js \ gdm/loginDialog.js \ + gdm/oVirt.js \ gdm/realmd.js \ gdm/util.js \ extensionPrefs/main.js \ diff --git a/js/gdm/authPrompt.js b/js/gdm/authPrompt.js index fe2cf2d38..1880e36c4 100644 --- a/js/gdm/authPrompt.js +++ b/js/gdm/authPrompt.js @@ -59,6 +59,7 @@ const AuthPrompt = new Lang.Class({ this._userVerifier.connect('verification-complete', Lang.bind(this, this._onVerificationComplete)); this._userVerifier.connect('reset', Lang.bind(this, this._onReset)); this._userVerifier.connect('smartcard-status-changed', Lang.bind(this, this._onSmartcardStatusChanged)); + this._userVerifier.connect('ovirt-user-authenticated', Lang.bind(this, this._onOVirtUserAuthenticated)); this.smartcardDetected = this._userVerifier.smartcardDetected; this.connect('next', Lang.bind(this, function() { @@ -219,6 +220,11 @@ const AuthPrompt = new Lang.Class({ this.emit('prompted'); }, + _onOVirtUserAuthenticated: function() { + if (this.verificationStatus != AuthPromptStatus.VERIFICATION_SUCCEEDED) + this.reset(); + }, + _onSmartcardStatusChanged: function() { this.smartcardDetected = this._userVerifier.smartcardDetected; @@ -444,10 +450,11 @@ const AuthPrompt = new Lang.Class({ // The user is constant at the unlock screen, so it will immediately // respond to the request with the username beginRequestType = BeginRequestType.PROVIDE_USERNAME; - } else if (this.smartcardDetected && - this._userVerifier.serviceIsForeground(GdmUtil.SMARTCARD_SERVICE_NAME)) { + } else if (this._userVerifier.serviceIsForeground(GdmUtil.OVIRT_SERVICE_NAME) || + (this.smartcardDetected && + this._userVerifier.serviceIsForeground(GdmUtil.SMARTCARD_SERVICE_NAME))) { // We don't need to know the username if the user preempted the login screen - // with a smartcard. + // with a smartcard or with preauthenticated oVirt credentials beginRequestType = BeginRequestType.DONT_PROVIDE_USERNAME; } else { // In all other cases, we should get the username up front. diff --git a/js/gdm/oVirt.js b/js/gdm/oVirt.js new file mode 100644 index 000000000..1a31f4329 --- /dev/null +++ b/js/gdm/oVirt.js @@ -0,0 +1,62 @@ +// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*- + +const Gio = imports.gi.Gio; +const Lang = imports.lang; +const Signals = imports.signals; + +const OVirtCredentialsIface = + + + +; + +const OVirtCredentialsInfo = Gio.DBusInterfaceInfo.new_for_xml(OVirtCredentialsIface); + +let _oVirtCredentialsManager = null; + +function OVirtCredentials() { + var self = new Gio.DBusProxy({ g_connection: Gio.DBus.system, + g_interface_name: OVirtCredentialsInfo.name, + g_interface_info: OVirtCredentialsInfo, + g_name: 'org.ovirt.vdsm.Credentials', + g_object_path: '/org/ovirt/vdsm/Credentials', + g_flags: (Gio.DBusProxyFlags.DO_NOT_LOAD_PROPERTIES) }); + self.init(null); + return self; +} + +const OVirtCredentialsManager = new Lang.Class({ + Name: 'OVirtCredentialsManager', + _init: function() { + this._token = null; + + this._credentials = new OVirtCredentials(); + this._credentials.connectSignal('UserAuthenticated', + Lang.bind(this, this._onUserAuthenticated)); + }, + + _onUserAuthenticated: function(proxy, sender, [token]) { + this._token = token; + this.emit('user-authenticated', token); + }, + + hasToken: function() { + return this._token != null; + }, + + getToken: function() { + return this._token; + }, + + resetToken: function() { + this._token = null; + } +}); +Signals.addSignalMethods(OVirtCredentialsManager.prototype); + +function getOVirtCredentialsManager() { + if (!_oVirtCredentialsManager) + _oVirtCredentialsManager = new OVirtCredentialsManager(); + + return _oVirtCredentialsManager; +} diff --git a/js/gdm/util.js b/js/gdm/util.js index f42190220..66852fd27 100644 --- a/js/gdm/util.js +++ b/js/gdm/util.js @@ -10,6 +10,7 @@ const St = imports.gi.St; const Batch = imports.gdm.batch; const Fprint = imports.gdm.fingerprint; +const OVirt = imports.gdm.oVirt; const Main = imports.ui.main; const Params = imports.misc.params; const ShellEntry = imports.ui.shellEntry; @@ -19,6 +20,7 @@ const Tweener = imports.ui.tweener; const PASSWORD_SERVICE_NAME = 'gdm-password'; const FINGERPRINT_SERVICE_NAME = 'gdm-fingerprint'; const SMARTCARD_SERVICE_NAME = 'gdm-smartcard'; +const OVIRT_SERVICE_NAME = 'gdm-ovirtcred'; const FADE_ANIMATION_TIME = 0.16; const CLONE_FADE_ANIMATION_TIME = 0.25; @@ -151,6 +153,14 @@ const ShellUserVerifier = new Lang.Class({ this.reauthenticating = false; this._failCounter = 0; + + this._oVirtCredentialsManager = OVirt.getOVirtCredentialsManager(); + + if (this._oVirtCredentialsManager.hasToken()) + this._oVirtUserAuthenticated(this._oVirtCredentialsManager.getToken()); + + this._oVirtCredentialsManager.connect('user-authenticated', + Lang.bind(this, this._oVirtUserAuthenticated)); }, begin: function(userName, hold) { @@ -277,6 +287,11 @@ const ShellUserVerifier = new Lang.Class({ })); }, + _oVirtUserAuthenticated: function(token) { + this._preemptingService = OVIRT_SERVICE_NAME; + this.emit('ovirt-user-authenticated'); + }, + _checkForSmartcard: function() { let smartcardDetected; @@ -455,6 +470,12 @@ const ShellUserVerifier = new Lang.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()); + return; + } + this.emit('ask-question', serviceName, secretQuestion, '\u25cf'); }, @@ -515,6 +536,16 @@ const ShellUserVerifier = new Lang.Class({ }, _onConversationStopped: function(client, serviceName) { + // 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(); + this._preemptingService = null; + this._verificationFailed(false); + return; + } + // if the password service fails, then cancel everything. // But if, e.g., fingerprint fails, still give // password authentication a chance to succeed diff --git a/js/ui/screenShield.js b/js/ui/screenShield.js index 32fd737b6..731122a79 100644 --- a/js/ui/screenShield.js +++ b/js/ui/screenShield.js @@ -19,6 +19,7 @@ const Background = imports.ui.background; const GnomeSession = imports.misc.gnomeSession; const Hash = imports.misc.hash; const Layout = imports.ui.layout; +const OVirt = imports.gdm.oVirt; const LoginManager = imports.misc.loginManager; const Lightbox = imports.ui.lightbox; const Main = imports.ui.main; @@ -545,6 +546,13 @@ const ScreenShield = new Lang.Class({ this._liftShield(true, 0); })); + this._oVirtCredentialsManager = OVirt.getOVirtCredentialsManager(); + this._oVirtCredentialsManager.connect('user-authenticated', + Lang.bind(this, function() { + if (this._isLocked) + this._liftShield(true, 0); + })); + this._inhibitor = null; this._aboutToSuspend = false; this._loginManager = LoginManager.getLoginManager();