Return PAM errors from mod_intercept_form_submit
authorRob Crittenden <rcritten@redhat.com>
Tue, 14 Jul 2015 19:35:21 +0000 (15:35 -0400)
committerPatrick Uiterwijk <puiterwijk@redhat.com>
Wed, 15 Jul 2015 14:39:20 +0000 (16:39 +0200)
This fixes several problems:

1. The PAM error was being retrieved from the wrong location
2. The error was not always logged properly
3. The error was not propogated up
4. Even if the error had been propgated up the auth_failed
   routine failed to pass it to the error page template.

A dictionary is used to translate the PAM errors into something
more consulable. This can be used eventually to translate
into other languages.

https://fedorahosted.org/ipsilon/ticket/69

Signed-off-by: Rob Crittenden <rcritten@redhat.com>
Reviewed-by: Patrick Uiterwijk <puiterwijk@redhat.com>
ipsilon/login/authform.py
ipsilon/login/common.py

index eed35fc..b61d4c9 100644 (file)
@@ -9,6 +9,15 @@ from string import Template
 import cherrypy
 import subprocess
 
+# Translate PAM errors into more human-digestible values and eventually
+# other languages.
+PAM_AUTH_ERRORS = {
+    "Authentication token is no longer valid; new one required":
+        "Password is expired",
+    "Authentication failure":
+        "Authentication failure",
+}
+
 
 class Form(LoginFormBase):
 
@@ -19,12 +28,13 @@ class Form(LoginFormBase):
         if not user.is_anonymous:
             return self.lm.auth_successful(self.trans, user.name, 'password')
         else:
-            try:
-                error = cherrypy.request.headers['EXTERNAL_AUTH_ERROR']
-            except KeyError:
-                error = "Unknown error using external authentication"
-                cherrypy.log.error("Error: %s" % error)
-            return self.lm.auth_failed(self.trans)
+            error = cherrypy.request.wsgi_environ.get(
+                'EXTERNAL_AUTH_ERROR',
+                'Unknown error using external authentication'
+            )
+            error = PAM_AUTH_ERRORS.get(error, error)
+            cherrypy.log.error("Error: %s" % error)
+            return self.lm.auth_failed(self.trans, error)
 
 
 class LoginManager(LoginManagerBase):
index db71fb0..31053a0 100644 (file)
@@ -85,7 +85,7 @@ class LoginManagerBase(ConfigHelper, PluginObject):
             trans.wipe()
         raise cherrypy.HTTPRedirect(redirect)
 
-    def auth_failed(self, trans):
+    def auth_failed(self, trans, message=None):
         # try with next module
         next_login = self.next_login()
         if next_login:
@@ -104,7 +104,7 @@ class LoginManagerBase(ConfigHelper, PluginObject):
         # destroy session and return error
         if 'login_return' not in transdata:
             session.logout(None)
-            raise cherrypy.HTTPError(401)
+            raise cherrypy.HTTPError(401, message)
 
         raise cherrypy.HTTPRedirect(transdata['login_return'])