[gnome-shell/wip/smartcard: 16/16] authPrompt: support smartcard authentication



commit d139adc25f42693330796c694467342cb83ad4d3
Author: Ray Strode <rstrode redhat com>
Date:   Thu Jun 27 08:54:19 2013 -0400

    authPrompt: support smartcard authentication
    
    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

 js/gdm/authPrompt.js  |   33 ++++++++++++++++++++++++++++++-
 js/gdm/util.js        |   51 +++++++++++++++++++++++++++++++++++++++++++++++++
 js/ui/screenShield.js |    8 +++++++
 3 files changed, 91 insertions(+), 1 deletions(-)
---
diff --git a/js/gdm/authPrompt.js b/js/gdm/authPrompt.js
index 8e673c3..85a2f4b 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 cc58308..0733d57 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 8271aa0..53eea03 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();


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]