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
|
|