Révision 64a0aa33
Ajouté par Thomas Noël il y a plus de 9 ans
usr/local/univnautes/sp/sp/__init__.py | ||
---|---|---|
1 |
import auth |
|
2 |
|
usr/local/univnautes/sp/sp/auth.py | ||
---|---|---|
1 |
# -*- encoding: utf-8 -*- |
|
2 |
|
|
3 |
import subprocess |
|
4 |
import settings |
|
5 |
from django.contrib import messages |
|
6 |
|
|
7 |
from authentic2.authsaml2 import signals |
|
8 |
|
|
9 |
import xml.etree.ElementTree |
|
10 |
import syslog |
|
11 |
|
|
12 |
def user_login_cb(sender, request, attributes={}, **kwargs): |
|
13 |
if request and request.user.is_anonymous(): |
|
14 |
return |
|
15 |
|
|
16 |
request.session['prefered_idp'] = attributes['__issuer'] |
|
17 |
if 'displayName' in attributes: |
|
18 |
request.session['display_name'] = attributes['displayName'][0] |
|
19 |
|
|
20 |
nameid = 'nameID:%s' % attributes['__nameid'] |
|
21 |
# use eduPersonTargetedID (OID 1.3.6.1.4.1.5923.1.1.1.10), fallback to __nameid/__issuer |
|
22 |
try: |
|
23 |
if 'eduPersonTargetedID' in attributes: |
|
24 |
attrkey = 'eduPersonTargetedID' |
|
25 |
else: |
|
26 |
attrkey = ('urn:oid:1.3.6.1.4.1.5923.1.1.1.10', 'urn:oasis:names:tc:SAML:2.0:attrname-format:uri') |
|
27 |
eduPersonTargetedID_xml = xml.etree.ElementTree.fromstring(attributes[attrkey][0]) |
|
28 |
eduPersonTargetedID = 'eduPersonTargetedID:%s' % eduPersonTargetedID_xml.text |
|
29 |
eduPersonTargetedID_NameQualifier = eduPersonTargetedID_xml.attrib['NameQualifier'] |
|
30 |
except: |
|
31 |
eduPersonTargetedID = nameid |
|
32 |
eduPersonTargetedID_NameQualifier = attributes['__issuer'] |
|
33 |
|
|
34 |
# log needs eduPersonTargetedID + transientID + idp |
|
35 |
username = eduPersonTargetedID + '|' + eduPersonTargetedID_NameQualifier |
|
36 |
|
|
37 |
# TODO : blacklist |
|
38 |
|
|
39 |
ip = request.META['REMOTE_ADDR'] |
|
40 |
|
|
41 |
# univnautes idp returns univnautesPrivileges attribute (a list) |
|
42 |
multiple = 0 |
|
43 |
privileges = attributes.get((u'univnautesPrivileges', u'urn:oasis:names:tc:SAML:2.0:attrname-format:basic'), []) |
|
44 |
if 'univnautes-idp-multiple' in privileges: |
|
45 |
multiple = 1 |
|
46 |
|
|
47 |
cmd = [ c % { |
|
48 |
'ip': ip, |
|
49 |
'username': username, |
|
50 |
'nameid': nameid, |
|
51 |
'multiple': multiple, |
|
52 |
} for c in settings.UNIVNAUTES_CP_ALLOW_CMD ] |
|
53 |
|
|
54 |
if settings.DEBUG: |
|
55 |
syslog.openlog("sp/auth", syslog.LOG_PID) |
|
56 |
syslog.syslog(syslog.LOG_LOCAL4 | syslog.LOG_INFO , "cmd: %r" % ' '.join(cmd)) |
|
57 |
|
|
58 |
# open the firewall for this client |
|
59 |
try: |
|
60 |
p = subprocess.Popen(cmd, close_fds=True, |
|
61 |
stdin=subprocess.PIPE, |
|
62 |
stdout=subprocess.PIPE, |
|
63 |
stderr=subprocess.PIPE) |
|
64 |
except OSError, e: |
|
65 |
request.session['pfsenseid'] = 'ERROR' |
|
66 |
messages.error(request, u"Erreur : OSError %s" % e) |
|
67 |
syslog.openlog("sp/auth", syslog.LOG_PID) |
|
68 |
syslog.syslog(syslog.LOG_LOCAL4 | syslog.LOG_INFO , "ERROR: OSError %s" % e) |
|
69 |
return False |
|
70 |
stdout, stderr = p.communicate() |
|
71 |
if p.returncode != 0: |
|
72 |
request.session['pfsenseid'] = 'ERROR' |
|
73 |
messages.error(request, u"Erreur : returncode=%d" % p.returncode) |
|
74 |
syslog.openlog("sp/auth", syslog.LOG_PID) |
|
75 |
syslog.syslog(syslog.LOG_LOCAL4 | syslog.LOG_INFO , "ERROR: returncode=%d" % p.returncode) |
|
76 |
return False |
|
77 |
# cp_allow returns the pfsense CP sessionid on stdout : store it in django session |
|
78 |
request.session['pfsenseid'] = stdout |
|
79 |
return True |
|
80 |
|
|
81 |
signals.auth_login.connect(user_login_cb, dispatch_uid='authentic2.idp') |
|
82 |
|
usr/local/univnautes/sp/sp/context_processors.py | ||
---|---|---|
23 | 23 |
context_extras = {} |
24 | 24 |
context_extras.update(settings.SP_UI) |
25 | 25 |
context_extras['idps'] = LibertyProvider.objects.all() |
26 |
context_extras['pfsenseid'] = request.session.get('pfsenseid') |
|
27 |
context_extras['display_name'] = request.session.get('display_name') |
|
26 | 28 |
return context_extras |
27 | 29 |
|
usr/local/univnautes/sp/sp/settings.py | ||
---|---|---|
83 | 83 |
) |
84 | 84 |
|
85 | 85 |
# Make this unique, and don't share it with anybody. |
86 |
SECRET_KEY_FILENAME='/usr/local/univnautes/sp/secret.key'
|
|
86 |
SECRET_KEY_FILENAME = os.path.join(PROJECT_PATH, 'secret.key')
|
|
87 | 87 |
try: |
88 | 88 |
with open(SECRET_KEY_FILENAME, 'rb') as sk: |
89 | 89 |
SECRET_KEY = sk.read() |
... | ... | |
93 | 93 |
with open(SECRET_KEY_FILENAME, 'wb') as sk: |
94 | 94 |
sk.write(SECRET_KEY) |
95 | 95 |
|
96 |
# List of callables that know how to import templates from various sources.
|
|
96 |
# List of callables to import templates from various sources. |
|
97 | 97 |
TEMPLATE_LOADERS = ( |
98 | 98 |
'django.template.loaders.filesystem.Loader', |
99 | 99 |
'django.template.loaders.app_directories.Loader', |
... | ... | |
113 | 113 |
# Python dotted path to the WSGI application used by Django's runserver. |
114 | 114 |
WSGI_APPLICATION = 'sp.wsgi.application' |
115 | 115 |
|
116 |
TEMPLATE_DIRS = ( |
|
117 |
os.path.join(PROJECT_PATH, 'sp', 'templates'), |
|
118 |
) |
|
116 |
#TEMPLATE_DIRS = (
|
|
117 |
# os.path.join(PROJECT_PATH, 'sp', 'templates'),
|
|
118 |
#)
|
|
119 | 119 |
|
120 | 120 |
INSTALLED_APPS = ( |
121 | 121 |
'django.contrib.auth', |
... | ... | |
135 | 135 |
INSTALLED_APPS += ('django.contrib.admin',) |
136 | 136 |
|
137 | 137 |
SESSION_SERIALIZER = 'django.contrib.sessions.serializers.PickleSerializer' |
138 |
# can't be 'django.contrib.sessions.serializers.JSONSerializer' with authentic2
|
|
138 |
# it can't be 'django.contrib.sessions.serializers.JSONSerializer' with authentic2 (attributes)
|
|
139 | 139 |
|
140 | 140 |
SESSION_COOKIE_NAME = 'univnautes-sp-sessionid' |
141 | 141 |
SESSION_ENGINE = 'django.contrib.sessions.backends.file' |
... | ... | |
182 | 182 |
'authentic2.authsaml2.backends.AuthSAML2PersistentBackend', |
183 | 183 |
'authentic2.authsaml2.backends.AuthSAML2TransientBackend') |
184 | 184 |
|
185 |
# pfSense captive portal commands : |
|
186 |
UNIVNAUTES_CP_ALLOW_CMD = [ |
|
187 |
os.path.join(PROJECT_PATH, 'sp', 'cp_allow'), |
|
188 |
'ip=%(ip)s', |
|
189 |
'username=%(username)s', |
|
190 |
'nameid=%(nameid)s', |
|
191 |
'multiple=%(multiple)s'] |
|
185 | 192 |
|
186 |
# get some values from config.xml |
|
193 |
# now get some values from config.xml
|
|
187 | 194 |
# => server must be restarted if config.xml is changed |
188 | 195 |
|
189 | 196 |
if 'CONFIG_XML' in os.environ: |
... | ... | |
206 | 213 |
'sp.context_processors.sp', |
207 | 214 |
) |
208 | 215 |
|
209 |
# FIXME: get this from SP_UI config |
|
216 |
# FIXME: get this from SP_UI config (i.e. config.xml)
|
|
210 | 217 |
PROXYMAP_URL = 'http://lactuca.entrouvert.org/proxymap/mapbox/%(z)d/%(x)d/%(y)d.png32' |
211 | 218 |
|
usr/local/univnautes/sp/sp/templates/homepage.html | ||
---|---|---|
2 | 2 |
{% load static %} |
3 | 3 |
|
4 | 4 |
{% block content %} |
5 |
|
|
6 |
{% if pfsenseid == 'ERROR' %} |
|
7 |
|
|
8 |
<h2> |
|
9 |
{% if display_name %}{{ display_name }}, il{% else %}Il{% endif %} y a eu une |
|
10 |
erreur lors de l'ouverture de l'accès. |
|
11 |
</h2> |
|
12 |
|
|
13 |
<p> |
|
14 |
Vous pouvez essayer de <button><a href="/accounts/logout/">vous reconnecter</a></button>. |
|
15 |
</p> |
|
16 |
|
|
17 |
{% elif pfsenseid == 'BLACKLIST' %} |
|
18 |
|
|
19 |
<h2>L'accès a été refusé.</h2> |
|
20 |
|
|
21 |
{% else %} |
|
22 |
|
|
5 | 23 |
<h2> |
6 |
Vous avez maintenant accès à Internet. |
|
24 |
{% if display_name %}{{ display_name }}, vous{% else %}Vous{% endif %} |
|
25 |
avez maintenant accès au réseau. |
|
7 | 26 |
</h2> |
8 | 27 |
|
9 | 28 |
<p> |
10 |
Après avoir utilisé cette connexion, n'oubliez pas de fermer votre navigateur,
|
|
11 |
afin que la session de connexion à votre établissement soit bien fermée.
|
|
29 |
Après avoir utilisé cet accès, n'oubliez pas de fermer votre navigateur, afin
|
|
30 |
que la session de connexion à votre établissement soit bien fermée. |
|
12 | 31 |
</p> |
13 | 32 |
|
14 | 33 |
<p> |
15 |
En cas de problème d'accès, essayez de <button><a href="/accounts/logout/">vous reconnecter</a></button>. |
|
34 |
En cas de problème d'accès, essayez de <button><a href="/accounts/logout/">vous |
|
35 |
reconnecter</a></button>. |
|
16 | 36 |
</p> |
17 |
{% endblock %} |
|
18 | 37 |
|
19 |
{% block page-end %} |
|
38 |
{% endif %} |
|
39 |
|
|
20 | 40 |
{% endblock %} |
21 | 41 |
|
42 |
{% block page-end %}{% endblock %} |
|
43 |
|
Formats disponibles : Unified diff
handle user_login_callback (attributes, call cp_allow..)