0001-add-blacklists-by-nameIDs-and-mac-addresses-support.patch
etc/inc/captiveportal_saml.inc | ||
---|---|---|
1 |
<?php |
|
2 | ||
3 |
function display_saml_tabs($file_name) { |
|
4 |
$tab_array = array(); |
|
5 |
$tab_array[] = array(gettext("Service provider"), false, "services_captiveportal_saml_sp.php"); |
|
6 |
# $tab_array[] = array(gettext("Identity provider"), false, "services_captiveportal_saml_idp.php"); |
|
7 |
$tab_array[] = array(gettext("Federations"), false, "services_captiveportal_saml_federation.php"); |
|
8 |
$tab_array[] = array(gettext("Whitelists"), false, "services_captiveportal_saml_whitelist.php"); |
|
9 |
$tab_array[] = array(gettext("Blacklists"), false, "services_captiveportal_saml_blacklist.php"); |
|
10 |
for ($i = 0; $i < sizeof($tab_array); $i++) { |
|
11 |
if ($tab_array[$i][2] == $file_name) { |
|
12 |
$tab_array[$i][1] = true; |
|
13 |
} |
|
14 |
} |
|
15 |
display_top_tabs($tab_array); |
|
16 |
} |
|
17 | ||
18 |
?> |
usr/local/univnautes/sp/rc.sh | ||
---|---|---|
32 | 32 |
) & |
33 | 33 |
} |
34 | 34 | |
35 |
function syncbl() { |
|
36 |
echo "sync blacklist in progress (backgrounded)" | logger -p local4.info -t sp/syncblacklists |
|
37 |
( |
|
38 |
cd /usr/local/univnautes/sp/ |
|
39 |
./update-blacklists.sh | logger -p local4.info -t sp/update-blacklists |
|
40 |
) & |
|
41 |
} |
|
42 | ||
35 | 43 |
function syncdata() { |
36 | 44 |
echo "sync metadatas + geoinfos in progress (backgrounded)" | logger -p local4.info -t sp/syncdata |
37 | 45 |
( |
... | ... | |
56 | 64 |
echo "started (manage.py runfcgi)" | logger -p local4.info -t sp/start |
57 | 65 |
syncdata |
58 | 66 |
syncwl |
67 |
syncbl |
|
59 | 68 |
cronstart |
60 | 69 |
} |
61 | 70 |
usr/local/univnautes/sp/sp/auth.py | ||
---|---|---|
1 | 1 |
# -*- encoding: utf-8 -*- |
2 | 2 | |
3 |
import re |
|
3 | 4 |
import subprocess |
4 | 5 |
import syslog |
5 | 6 |
import xml.etree.ElementTree |
... | ... | |
8 | 9 |
from django.contrib import messages |
9 | 10 | |
10 | 11 |
from authentic2.authsaml2 import signals |
12 |
from sp import pfconfigxml |
|
13 | ||
14 |
COMMENT=re.compile('^\s*($|#)') |
|
11 | 15 | |
12 | 16 |
def user_login_cb(sender, request, attributes={}, **kwargs): |
13 | 17 |
if request and request.user.is_anonymous(): |
... | ... | |
35 | 39 |
# log needs eduPersonTargetedID + transientID + idp |
36 | 40 |
username = eduPersonTargetedID + '|' + eduPersonTargetedID_NameQualifier |
37 | 41 | |
38 |
# TODO : blacklist |
|
39 | ||
40 | 42 |
ip = request.META['REMOTE_ADDR'] |
41 | 43 | |
44 |
# user blacklist |
|
45 |
try: |
|
46 |
nameid_bl = pfconfigxml.get_blacklists('nameid') |
|
47 |
for line in nameid_bl.splitlines(True): |
|
48 |
if COMMENT.match(line): |
|
49 |
continue |
|
50 |
userbl = line.strip() |
|
51 |
# if the line starts with ~, it's a regex |
|
52 |
if userbl[0] == '~' and re.match(userbl[1::], username): |
|
53 |
request.session['pfsenseid'] = 'BLACKLISTED' |
|
54 |
messages.error(request, u"Connexion refusée (règle dans une liste noire).") |
|
55 |
syslog.openlog("logportalauth", syslog.LOG_PID) |
|
56 |
syslog.syslog(syslog.LOG_LOCAL4 | syslog.LOG_INFO , "BLACKLISTED-REGEX: %s,,%s" % (username, ip)) |
|
57 |
return False |
|
58 |
elif userbl.strip() == username: |
|
59 |
request.session['pfsenseid'] = 'BLACKLISTED' |
|
60 |
messages.error(request, u"Connexion refusée (présent dans une liste noire).") |
|
61 |
syslog.openlog("logportalauth", syslog.LOG_PID) |
|
62 |
syslog.syslog(syslog.LOG_LOCAL4 | syslog.LOG_INFO , "BLACKLISTED: %s,,%s" % (username, ip)) |
|
63 |
return False |
|
64 |
except: |
|
65 |
pass |
|
66 | ||
42 | 67 |
# univnautes idp returns univnautesPrivileges attribute (a list) |
43 | 68 |
multiple = 0 |
44 | 69 |
privileges = attributes.get((u'univnautesPrivileges', u'urn:oasis:names:tc:SAML:2.0:attrname-format:basic'), []) |
usr/local/univnautes/sp/sp/management/commands/configxml.py | ||
---|---|---|
18 | 18 | |
19 | 19 |
from django.core.management.base import BaseCommand, CommandError |
20 | 20 |
import os |
21 |
import sys |
|
21 | 22 |
from sp import pfconfigxml |
22 | 23 | |
23 |
def get(key): |
|
24 |
def get(key, args):
|
|
24 | 25 |
if key == 'cpnames': |
25 | 26 |
for n in pfconfigxml.get_saml_cps(): |
26 | 27 |
print n['name'] |
28 |
elif key == 'blacklist': |
|
29 |
if len(args) > 2: |
|
30 |
print pfconfigxml.get_blacklists(args[2]) |
|
31 |
else: |
|
32 |
print >> sys.stderr, 'you need to choose a blacklist (nameid or macadresses)' |
|
27 | 33 | |
28 | 34 |
class Command(BaseCommand): |
29 | 35 |
help = 'get infos from config.xml' |
... | ... | |
35 | 41 |
print "syntax: configxml get|set key" |
36 | 42 |
return |
37 | 43 |
if action == 'get': |
38 |
return get(key) |
|
44 |
return get(key, args)
|
|
39 | 45 |
usr/local/univnautes/sp/sp/pfconfigxml.py | ||
---|---|---|
240 | 240 |
}) |
241 | 241 |
return whitelists |
242 | 242 | |
243 | ||
244 |
def get_blacklists(list_type): |
|
245 |
""" |
|
246 |
<blacklists> |
|
247 |
<macaddresses>base64</macaddresses> |
|
248 |
<nameid>base64</nameid> |
|
249 |
</blacklists> |
|
250 |
""" |
|
251 |
xml_blacklist = root().find('univnautes/blacklists/%s' % list_type) |
|
252 |
if xml_blacklist is not None and xml_blacklist.text: |
|
253 |
return xml_blacklist.text.decode('base64') |
|
254 |
return '' |
|
255 |
usr/local/univnautes/sp/sp/static/univnautes/univnautes.js | ||
---|---|---|
98 | 98 |
}) |
99 | 99 |
}); |
100 | 100 |
marker.entityid = entityid; |
101 |
marker.bindPopup('<p>' + name + '</p><p align="center"><a href="/authsaml2/sso?entity_id=' + entityid + '"><button class="connexion">Connexion</button></a></p>');
|
|
101 |
marker.bindPopup('<p>' + name + '</p><p align="center"><a href="/authsaml2/sso?entity_id=' + entityid + '"><button class="connexion">Connexion</button></a></p>'); |
|
102 | 102 |
new_markers.push(marker); |
103 | 103 |
} |
104 | 104 |
} |
usr/local/univnautes/sp/update-blacklists.sh | ||
---|---|---|
1 |
#!/bin/sh |
|
2 | ||
3 |
log() { |
|
4 |
logger -p local4.info -t macblacklist -- "$*" |
|
5 |
} |
|
6 | ||
7 |
log "update MAC blacklist" |
|
8 |
cd /usr/local/univnautes/sp |
|
9 |
for ctx in $(./manage.py configxml get cpnames); do |
|
10 |
/sbin/ipfw -x $ctx -fq delete 666 |
|
11 |
for MAC in $(./manage.py configxml get blacklist macaddresses | sed 's/#.*$//'); do |
|
12 |
# sanitize |
|
13 |
MAC=`echo $MAC | tr -dc 0-9a-fA-F:` |
|
14 |
if test -n "$MAC"; then |
|
15 |
if /sbin/ipfw -x $ctx -fq add 666 deny MAC $MAC any; then |
|
16 |
log "added: $MAC in $ctx" |
|
17 |
else |
|
18 |
log "ERROR can't add: $MAC (incorrect MAC address ?)" |
|
19 |
fi |
|
20 |
fi |
|
21 |
done |
|
22 |
done |
|
23 | ||
24 |
exit 0 |
usr/local/www/services_captiveportal_saml_blacklist.php | ||
---|---|---|
1 |
<?php |
|
2 |
/* |
|
3 |
services_captiveportal_saml_sp.php |
|
4 |
part of m0n0wall (http://m0n0.ch/wall) |
|
5 | ||
6 |
Copyright (C) 2003-2006 Manuel Kasper <mk@neon1.net>. |
|
7 |
Copyright (C) 2014 Entr'ouvert <info@entrouvert.com>. |
|
8 |
All rights reserved. |
|
9 | ||
10 |
Redistribution and use in source and binary forms, with or without |
|
11 |
modification, are permitted provided that the following conditions are met: |
|
12 | ||
13 |
1. Redistributions of source code must retain the above copyright notice, |
|
14 |
this list of conditions and the following disclaimer. |
|
15 | ||
16 |
2. Redistributions in binary form must reproduce the above copyright |
|
17 |
notice, this list of conditions and the following disclaimer in the |
|
18 |
documentation and/or other materials provided with the distribution. |
|
19 | ||
20 |
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, |
|
21 |
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY |
|
22 |
AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE |
|
23 |
AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, |
|
24 |
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
|
25 |
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
|
26 |
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
|
27 |
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
|
28 |
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
|
29 |
POSSIBILITY OF SUCH DAMAGE. |
|
30 |
*/ |
|
31 |
/* |
|
32 |
pfSense_MODULE: captiveportal |
|
33 |
*/ |
|
34 | ||
35 |
##|+PRIV |
|
36 |
##|*IDENT=page-services-captiveportal-saml-sp |
|
37 |
##|*NAME=Services: Captive portal SAML SP page |
|
38 |
##|*DESCR=Allow access to the 'Services: Captive portal SAML SP' page. |
|
39 |
##|*MATCH=services_captiveportal_saml_sp.php* |
|
40 |
##|-PRIV |
|
41 | ||
42 |
require_once("guiconfig.inc"); |
|
43 |
require_once("functions.inc"); |
|
44 |
require_once("filter.inc"); |
|
45 |
require_once("shaper.inc"); |
|
46 |
require_once("captiveportal.inc"); |
|
47 |
require_once("captiveportal_saml.inc"); |
|
48 | ||
49 |
if (!is_array($config['captiveportal'])) |
|
50 |
$config['captiveportal'] = array(); |
|
51 |
$a_cp =& $config['captiveportal']; |
|
52 | ||
53 |
if (!is_array($config['univnautes'])) |
|
54 |
$config['univnautes'] = array(); |
|
55 |
$a_un =& $config['univnautes']; |
|
56 | ||
57 |
if (!is_array($a_un['blacklists'])) |
|
58 |
$a_un['blacklists'] = array( |
|
59 |
'macaddresses' => array(), |
|
60 |
'nameid' => array() |
|
61 |
); |
|
62 | ||
63 |
$a_blacklist =& $a_un['blacklists']; |
|
64 | ||
65 |
$pconfig['macaddresses'] = base64_decode($a_blacklist['macaddresses']); |
|
66 |
$pconfig['nameid'] = base64_decode($a_blacklist['nameid']); |
|
67 | ||
68 |
$pgtitle = array(gettext("Services"),gettext("Captive portal"), "SAML 2.0 Blacklists"); |
|
69 |
$shortcut_section = "captiveportal"; |
|
70 | ||
71 |
if ($_POST) { |
|
72 | ||
73 |
unset($input_errors); |
|
74 |
$pconfig = $_POST; |
|
75 | ||
76 |
/* input validation */ |
|
77 |
$reqdfields = array(); |
|
78 |
$reqdfieldsn = array(); |
|
79 | ||
80 |
do_input_validation($_POST, $reqdfields, $reqdfieldsn, &$input_errors); |
|
81 | ||
82 |
/* if this is an AJAX caller then handle via JSON */ |
|
83 |
if (isAjax() && is_array($input_errors)) { |
|
84 |
input_errors2Ajax($input_errors); |
|
85 |
exit; |
|
86 |
} |
|
87 | ||
88 |
if (!$input_errors) { |
|
89 |
$a_blacklist['macaddresses'] = base64_encode($pconfig['macaddresses']); |
|
90 |
$a_blacklist['nameid'] = base64_encode($pconfig['nameid']); |
|
91 |
/* write config.xml */ |
|
92 |
write_config(); |
|
93 | ||
94 |
/* reload whitelists */ |
|
95 |
mwexec_bg("/usr/local/univnautes/sp/rc.sh syncbl"); |
|
96 | ||
97 |
/* back to the page */ |
|
98 |
pfSenseHeader("services_captiveportal_saml_blacklist.php"); |
|
99 |
} |
|
100 |
} |
|
101 |
include("head.inc"); |
|
102 |
?> |
|
103 |
<body link="#0000CC" vlink="#0000CC" alink="#0000CC"> |
|
104 |
<?php include("fbegin.inc"); ?> |
|
105 |
<?php if ($input_errors) print_input_errors($input_errors); ?> |
|
106 |
<?php if ($savemsg) print_info_box($savemsg); ?> |
|
107 | ||
108 |
<form action="services_captiveportal_saml_blacklist.php" method="post" enctype="multipart/form-data" name="iform" id="iform"> |
|
109 | ||
110 |
<table width="100%" border="0" cellpadding="0" cellspacing="0"> |
|
111 |
<tr><td class="tabnavtbl"><?php display_saml_tabs(basename(__FILE__)); ?></td></tr> |
|
112 |
<tr> |
|
113 |
<td class="tabcont"> |
|
114 |
<table width="100%" border="0" cellpadding="6" cellspacing="0"> |
|
115 | ||
116 |
<tr> |
|
117 |
<td colspan="2" class="list" height="12"></td> |
|
118 |
</tr> |
|
119 | ||
120 | ||
121 |
<tr> |
|
122 |
<td valign="top" class="vncellreq"><?=gettext("Mac addresses"); ?></td> |
|
123 |
<td class="vtable"> |
|
124 |
<textarea name="macaddresses" cols="65" rows="4" id="macaddresses" class="formpre"><?=htmlspecialchars($pconfig['macaddresses']);?></textarea> |
|
125 |
<br> |
|
126 |
<?=gettext("List of mac address to ban, one per line."); ?> |
|
127 |
</td> |
|
128 |
</tr> |
|
129 | ||
130 |
<tr> |
|
131 |
<td colspan="2" class="list" height="12"></td> |
|
132 |
</tr> |
|
133 |
<tr> |
|
134 |
<td valign="top" class="vncellreq"><?=gettext("SAML NameIDs"); ?></td> |
|
135 |
<td class="vtable"> |
|
136 |
<textarea name="nameid" cols="65" rows="4" id="nameid" class="formpre"><?=htmlspecialchars($pconfig['nameid']);?></textarea> |
|
137 |
<br> |
|
138 |
<?=gettext("List of NameID (SAML identifier) to ban, one per line."); ?> |
|
139 |
</td> |
|
140 |
</tr> |
|
141 | ||
142 |
<tr> |
|
143 |
<td width="22%" valign="top"> </td> |
|
144 |
<td width="78%"> |
|
145 |
<?php echo "<input name='zone' id='zone' type='hidden' value='" . htmlspecialchars($cpzone) . "'/>"; ?> |
|
146 |
<input name="Submit" type="submit" class="formbtn" value="<?=gettext("Save"); ?>" onClick="enable_change(true)"> |
|
147 |
<a href="services_captiveportal_zones.php"><input name="Cancel" type="button" class="formbtn" value="<?=gettext("Cancel"); ?>" onClick="enable_change(true)"></a> |
|
148 |
</td> |
|
149 |
</tr> |
|
150 |
</table> |
|
151 |
</td> |
|
152 |
</tr> |
|
153 |
</table> |
|
154 |
</form> |
|
155 |
<script language="JavaScript"> |
|
156 |
<!-- |
|
157 |
enable_change(false); |
|
158 |
//--> |
|
159 |
</script> |
|
160 |
<?php include("fend.inc"); ?> |
|
161 |
</body> |
|
162 |
</html> |
usr/local/www/services_captiveportal_zones.php | ||
---|---|---|
115 | 115 |
<p> |
116 | 116 |
<a href="services_captiveportal_saml_sp.php">Service provider</a> | |
117 | 117 |
<a href="services_captiveportal_saml_federation.php">Federations</a> | |
118 |
<a href="services_captiveportal_saml_whitelist.php">Whitelist</a> |
|
118 |
<a href="services_captiveportal_saml_whitelist.php">Whitelist</a> | |
|
119 |
<a href="services_captiveportal_saml_blacklist.php">Blacklist</a> |
|
119 | 120 |
</p> |
120 | 121 |
</div> |
121 | 122 | |
122 |
- |