/usr/share/pyshared/gluon/contrib/login_methods/x509_auth.py is in python-gluon 1.99.7-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 | #!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Written by Michele Comitini <mcm@glisco.it>
License: GPL v3
Adds support for x509 authentication.
"""
from gluon.globals import current
from gluon.storage import Storage
from gluon.http import HTTP,redirect
#requires M2Crypto
from M2Crypto import X509
class X509Auth(object):
"""
Login using x509 cert from client.
from gluon.contrib.login_methods.x509_auth import X509Account
auth.settings.actions_disabled=['register','change_password',
'request_reset_password','profile']
auth.settings.login_form = X509Account()
"""
def __init__(self):
self.request = current.request
self.ssl_client_raw_cert = self.request.env.ssl_client_raw_cert
# rebuild the certificate passed by the env
# this is double work, but it is the only way
# since we cannot access the web server ssl engine directly
if self.ssl_client_raw_cert:
x509=X509.load_cert_string(self.ssl_client_raw_cert, X509.FORMAT_PEM)
# extract it from the cert
self.serial = self.request.env.ssl_client_serial or ('%x' % x509.get_serial_number()).upper()
subject = x509.get_subject()
# Reordering the subject map to a usable Storage map
# this allows us a cleaner syntax:
# cn = self.subject.cn
self.subject = Storage(filter(None,
map(lambda x:
(x,map(lambda y:
y.get_data().as_text(),
subject.get_entries_by_nid(subject.nid[x]))),
subject.nid.keys())))
def login_form(self, **args):
raise HTTP(403,'Login not allowed. No valid x509 crentials')
def login_url(self, next="/"):
raise HTTP(403,'Login not allowed. No valid x509 crentials')
def logout_url(self, next="/"):
return next
def get_user(self):
'''Returns the user info contained in the certificate.
'''
# We did not get the client cert?
if not self.ssl_client_raw_cert:
return None
# Try to reconstruct some useful info for web2py auth machinery
p = profile = dict()
username = p['username'] = reduce(lambda a,b: '%s | %s' % (a,b), self.subject.CN or self.subject.commonName)
p['first_name'] = reduce(lambda a,b: '%s | %s' % (a,b),self.subject.givenName or username)
p['last_name'] = reduce(lambda a,b: '%s | %s' % (a,b),self.subject.surname)
p['email'] = reduce(lambda a,b: '%s | %s' % (a,b),self.subject.Email or self.subject.emailAddress)
# IMPORTANT WE USE THE CERT SERIAL AS UNIQUE KEY FOR THE USER
p['registration_id'] = self.serial
# If the auth table has a field certificate it will be used to
# save a PEM encoded copy of the user certificate.
p['certificate'] = self.ssl_client_raw_cert
return profile
|