Permalink
Browse files

Adding some files I apparently missed in the last two (or three) comm…

…its.
  • Loading branch information...
1 parent ce55f1b commit ea9ae1093ea92eb4b027b41564faa2580827ad3c @liftoff committed Oct 25, 2011
View
@@ -0,0 +1,25 @@
+# Meant to be used with pybabel like so (this file is babel_gateone.cfg):
+# Create a gateone.pot file by extracting _() strings from all the source files (*.py and templates)"
+# $ pybabel extract -o gateone/i18n/gateone.pot -F ./babel_gateone.cfg gateone
+
+# Then you can create a translation for, say, Portuguese (creates a fresh/empty .po file):
+# $ pybabel init -D gateone -i gateone/i18n/gateone.pot -d gateone/i18n/ -l pt_PT
+# Edit the resulting .po file (adding your translations) and lastly, compile it to .mo:
+# $ pybabel compile -D gateone -d gateone/i18n/ -f --statistics
+# Now Gate One will automatically use your translation, awesome!
+
+# If gateone.pot changed, you'll need to update your translation with the new changes:
+# $ pybabel update -d gateone/i18n -l pt_PT -i gateone/i18n/gateone.pot -D gateone
+# That will update the line numbers, comment out any obsolete translations, and add any new untranslated text.
+
+# Extraction from Python source files
+[python: *.py]
+
+# Extraction from Tornado templates
+[tornado: gateone/templates/**.html]
+input_encoding = utf-8
+
+# Extraction from JavaScript files
+[javascript: gateone/static/**.js]
+input_encoding = utf-8
+
View
@@ -0,0 +1,104 @@
+# -*- coding: utf-8 -*-
+#
+# Copyright 2011 Liftoff Software Corporation
+#
+# Thanks to Alan Schmitz for contributing this module!
+
+# Meta
+__version__ = '1.0'
+__license__ = "AGPLv3 or Proprietary (see LICENSE.txt)"
+__version_info__ = (1, 0)
+__doc__ = """
+This authentication module is built on top of python-pam (or PAM). The latest
+version of which can be found here: ftp://ftp.pangalactic.org/pub/tummy/ or if
+that doesn't work try: http://packages.debian.org/lenny/python-pam
+
+It was originally written by Alan Schmitz.
+
+The only non-obvious aspect of this module is that the pam_realm setting is only
+used when the user is asked to authenticate and when the user's information is
+store in the 'users' directory. It isn't actually used in any part of the
+authentication (PAM doesn't take a "realm" setting).
+"""
+
+# Standard library modules
+import httplib, logging, base64
+
+# 3rd party modules
+import PAM
+import tornado.httpserver
+import tornado.ioloop
+import tornado.web
+from tornado.escape import utf8
+from tornado.util import b
+
+
+class PAMAuthMixin(tornado.web.RequestHandler):
+ def initialize(self):
+ """
+ Print out helpful error messages if the requisite settings aren't
+ configured.
+ """
+ self.require_setting("pam_realm", "PAM Single Sign-On")
+ self.require_setting("pam_service", "PAM Single Sign-On")
+
+ def get_authenticated_user(self, callback):
+ """
+ Processes the client's Authorization header and call self.auth_basic()
+ """
+ auth_header = self.request.headers.get('Authorization')
+ if auth_header.startswith('Basic '):
+ self.auth_basic(auth_header, callback)
+
+ def auth_basic(self, auth_header, callback):
+ """
+ Perform Basic authentication using self.settings['pam_realm'].
+ """
+ auth_decoded = base64.decodestring(auth_header[6:])
+ username, password = auth_decoded.split(':', 2)
+
+ def _pam_conv(auth, query_list, user_data=None):
+ resp = []
+ for i in range(len(query_list)):
+ query, qtype = query_list[i]
+ if qtype == PAM.PAM_PROMPT_ECHO_ON:
+ resp.append((username, 0))
+ elif qtype == PAM.PAM_PROMPT_ECHO_OFF:
+ resp.append((password, 0))
+ else:
+ return None
+ return resp
+
+ pam_auth = PAM.pam()
+ pam_auth.start(self.settings['pam_service'])
+ pam_auth.set_item(PAM.PAM_USER, username)
+ pam_auth.set_item(PAM.PAM_TTY, 'console')
+ pam_auth.set_item(PAM.PAM_CONV, _pam_conv)
+ try:
+ pam_auth.authenticate()
+ pam_auth.acct_mgmt()
+ except Exception, e: # Basic auth failed
+ if self.settings['debug']:
+ print(e) # Very useful for debugging Kerberos errors
+ return self.authenticate_redirect()
+ # NOTE: Basic auth just gives us the username without the @REALM part
+ # so we have to add it:
+ user = "%s@%s" % (username, self.settings['pam_realm'])
+ callback(user)
+
+ def authenticate_redirect(self):
+ """
+ Informs the browser that this resource requires authentication (status
+ code 401) which should prompt the browser to reply with credentials.
+
+ The browser will be informed that we support Basic auth.
+ """
+ if self._headers_written:
+ raise Exception('Headers have already been written')
+ self.set_status(401)
+ self.add_header(
+ "WWW-Authenticate",
+ 'Basic realm="%s"' % self.settings['pam_realm']
+ )
+ self.finish()
+ return False
Oops, something went wrong.

0 comments on commit ea9ae10

Please sign in to comment.