summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRay Strode <rstrode@redhat.com>2013-06-27 08:54:19 -0400
committerRay Strode <rstrode@redhat.com>2013-07-29 20:21:06 -0400
commitd139adc25f42693330796c694467342cb83ad4d3 (patch)
tree75330ac18569253051fb4429536f630ee00e40c5
parent0d151f8d94947d3380af72145016c14e6a4fa66e (diff)
downloadgnome-shell-wip/smartcard.tar.gz
authPrompt: support smartcard authenticationwip/smartcard
This commit detects when a user inserts a smartcard, and then initiates user verification using the gdm-smartcard PAM service. Likewise, if a user removes their smartcard, password verification (or the user list depending on auth mode and configuration) are initiated https://bugzilla.gnome.org/show_bug.cgi?id=683437
-rw-r--r--js/gdm/authPrompt.js33
-rw-r--r--js/gdm/util.js51
-rw-r--r--js/ui/screenShield.js8
3 files changed, 91 insertions, 1 deletions
diff --git a/js/gdm/authPrompt.js b/js/gdm/authPrompt.js
index 8e673c393..85a2f4b1a 100644
--- a/js/gdm/authPrompt.js
+++ b/js/gdm/authPrompt.js
@@ -60,6 +60,8 @@ const AuthPrompt = new Lang.Class({
this._userVerifier.connect('reset', Lang.bind(this, this._onReset));
this._userVerifier.connect('show-login-hint', Lang.bind(this, this._onShowLoginHint));
this._userVerifier.connect('hide-login-hint', Lang.bind(this, this._onHideLoginHint));
+ this._userVerifier.connect('smartcard-status-changed', Lang.bind(this, this._onSmartcardStatusChanged));
+ this.smartcardDetected = this._userVerifier.smartcardDetected;
this.connect('next', Lang.bind(this, function() {
this.updateSensitivity(false);
@@ -220,6 +222,20 @@ const AuthPrompt = new Lang.Class({
this.emit('prompted');
},
+ _onSmartcardStatusChanged: function() {
+ this.smartcardDetected = this._userVerifier.smartcardDetected;
+
+ // Don't reset on smartcard insertion if we're already verifying
+ // and the smartcard is the main service
+ if (this._userVerifier.serviceIsDefault(GdmUtil.SMARTCARD_SERVICE_NAME) &&
+ this.verificationStatus == AuthPromptStatus.VERIFYING &&
+ this.smartcardDetected)
+ return;
+
+ if (this.verificationStatus != AuthPromptStatus.VERIFICATION_SUCCEEDED)
+ this.reset();
+ },
+
_onShowMessage: function(userVerifier, message, styleClass) {
this.setMessage(message, styleClass);
this.emit('prompted');
@@ -429,7 +445,22 @@ const AuthPrompt = new Lang.Class({
if (oldStatus == AuthPromptStatus.VERIFICATION_FAILED)
this.emit('failed');
- this.emit('reset', BeginRequestType.PROVIDE_USERNAME);
+ let beginRequestType;
+
+ if (this._mode == AuthPromptMode.UNLOCK_ONLY) {
+ // The user is constant at the unlock screen
+ beginRequestType = BeginRequestType.PROVIDE_USERNAME;
+ } else if (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.
+ beginRequestType = BeginRequestType.DONT_PROVIDE_USERNAME;
+ } else {
+ // In all other cases, we should get the username up front.
+ beginRequestType = BeginRequestType.PROVIDE_USERNAME;
+ }
+
+ this.emit('reset', beginRequestType);
},
addCharacter: function(unichar) {
diff --git a/js/gdm/util.js b/js/gdm/util.js
index cc583087a..0733d57e4 100644
--- a/js/gdm/util.js
+++ b/js/gdm/util.js
@@ -13,16 +13,19 @@ const Fprint = imports.gdm.fingerprint;
const Main = imports.ui.main;
const Params = imports.misc.params;
const ShellEntry = imports.ui.shellEntry;
+const SmartcardManager = imports.misc.smartcardManager;
const Tweener = imports.ui.tweener;
const PASSWORD_SERVICE_NAME = 'gdm-password';
const FINGERPRINT_SERVICE_NAME = 'gdm-fingerprint';
+const SMARTCARD_SERVICE_NAME = 'gdm-smartcard';
const FADE_ANIMATION_TIME = 0.16;
const CLONE_FADE_ANIMATION_TIME = 0.25;
const LOGIN_SCREEN_SCHEMA = 'org.gnome.login-screen';
const PASSWORD_AUTHENTICATION_KEY = 'enable-password-authentication';
const FINGERPRINT_AUTHENTICATION_KEY = 'enable-fingerprint-authentication';
+const SMARTCARD_AUTHENTICATION_KEY = 'enable-smartcard-authentication';
const BANNER_MESSAGE_KEY = 'banner-message-enable';
const BANNER_MESSAGE_TEXT_KEY = 'banner-message-text';
const ALLOWED_FAILURES_KEY = 'allowed-failures';
@@ -124,6 +127,23 @@ const ShellUserVerifier = new Lang.Class({
this._updateDefaultService();
this._fprintManager = new Fprint.FprintManager();
+ this._smartcardManager = SmartcardManager.getSmartcardManager();
+
+ // We check for smartcards right away, since an inserted smartcard
+ // at startup should result in immediately initiating authentication.
+ // This is different than fingeprint readers, where we only check them
+ // after a user has been picked.
+ this._checkForSmartcard();
+
+ this._smartcardManager.connect('smartcard-inserted',
+ Lang.bind(this, function() {
+ this._checkForSmartcard();
+ }));
+ this._smartcardManager.connect('smartcard-removed',
+ Lang.bind(this, function() {
+ this._checkForSmartcard();
+ }));
+
this._messageQueue = [];
this._messageQueueTimeoutId = 0;
this.hasPendingMessages = false;
@@ -252,6 +272,28 @@ const ShellUserVerifier = new Lang.Class({
}));
},
+ _checkForSmartcard: function() {
+ let smartcardDetected;
+
+ if (!this._settings.get_boolean(SMARTCARD_AUTHENTICATION_KEY))
+ smartcardDetected = false;
+ else if (this.reauthenticating)
+ smartcardDetected = this._smartcardManager.hasInsertedLoginToken();
+ else
+ smartcardDetected = this._smartcardManager.hasInsertedTokens();
+
+ if (smartcardDetected != this.smartcardDetected) {
+ this.smartcardDetected = smartcardDetected;
+
+ if (this.smartcardDetected)
+ this._preemptingService = SMARTCARD_SERVICE_NAME;
+ else if (this._preemptingService == SMARTCARD_SERVICE_NAME)
+ this._preemptingService = null;
+
+ this.emit('smartcard-status-changed');
+ }
+ },
+
_reportInitError: function(where, error) {
logError(error, where);
this._hold.release();
@@ -309,6 +351,9 @@ const ShellUserVerifier = new Lang.Class({
},
_getForegroundService: function() {
+ if (this._preemptingService)
+ return this._preemptingService;
+
return this._defaultService;
},
@@ -316,9 +361,15 @@ const ShellUserVerifier = new Lang.Class({
return serviceName == this._getForegroundService();
},
+ serviceIsDefault: function(serviceName) {
+ return serviceName == this._defaultService;
+ },
+
_updateDefaultService: function() {
if (this._settings.get_boolean(PASSWORD_AUTHENTICATION_KEY))
this._defaultService = PASSWORD_SERVICE_NAME;
+ else if (this._settings.get_boolean(SMARTCARD_AUTHENTICATION_KEY))
+ this._defaultService = SMARTCARD_SERVICE_NAME;
else if (this._settings.get_boolean(FINGERPRINT_AUTHENTICATION_KEY))
this._defaultService = FINGERPRINT_SERVICE_NAME;
},
diff --git a/js/ui/screenShield.js b/js/ui/screenShield.js
index 8271aa0a1..53eea0324 100644
--- a/js/ui/screenShield.js
+++ b/js/ui/screenShield.js
@@ -23,6 +23,7 @@ const Main = imports.ui.main;
const Overview = imports.ui.overview;
const MessageTray = imports.ui.messageTray;
const ShellDBus = imports.ui.shellDBus;
+const SmartcardManager = imports.misc.smartcardManager;
const Tweener = imports.ui.tweener;
const Util = imports.misc.util;
@@ -516,6 +517,13 @@ const ScreenShield = new Lang.Class({
this._screenSaverDBus = new ShellDBus.ScreenSaverDBus(this);
+ this._smartcardManager = SmartcardManager.getSmartcardManager();
+ this._smartcardManager.connect('smartcard-inserted',
+ Lang.bind(this, function() {
+ if (this._isLocked)
+ this._liftShield(true, 0);
+ }));
+
this._inhibitor = null;
this._aboutToSuspend = false;
this._loginManager = LoginManager.getLoginManager();