diff --git a/freeradius_utils/auth.py b/freeradius_utils/auth.py
index ab10d457..9bd56015 100644
--- a/freeradius_utils/auth.py
+++ b/freeradius_utils/auth.py
@@ -63,6 +63,7 @@ from preferences.models import OptionalTopologie
options, created = OptionalTopologie.objects.get_or_create()
VLAN_NOK = options.vlan_decision_nok.vlan_id
VLAN_OK = options.vlan_decision_ok.vlan_id
+VLAN_NON_MEMBER = options.vlan_non_member.vlan_id
RADIUS_POLICY = options.radius_general_policy
#: Serveur radius de test (pas la prod)
@@ -338,14 +339,15 @@ def decide_vlan_switch(nas_machine, nas_type, port_number,
- mode strict :
- pas de chambre associée : VLAN_NOK
- pas d'utilisateur dans la chambre : VLAN_NOK
- - cotisation non à jour : VLAN_NOK
+ - cotisation non à jour : VLAN_NON_MEMBER
- sinon passe à common (ci-dessous)
- mode common :
- interface connue (macaddress):
- - utilisateur proprio non cotisant ou banni : VLAN_NOK
+ - utilisateur proprio non cotisant : VLAN_NON_MEMBER
+ - utilisateur proprio banni : VLAN_NOK
- user à jour : VLAN_OK
- interface inconnue :
- - register mac désactivé : VLAN_NOK
+ - register mac désactivé : VLAN_NON_MEMBER
- register mac activé -> redirection vers webauth
"""
# Get port from switch and port number
@@ -414,8 +416,10 @@ def decide_vlan_switch(nas_machine, nas_type, port_number,
if not room_user:
return (sw_name, room, u'Chambre non cotisante -> Web redirect', None, False)
for user in room_user:
- if not user.has_access():
+ if user.is_ban() or user.state != User.STATE_ACTIVE:
return (sw_name, room, u'Chambre resident desactive -> Web redirect', None, False)
+ elif not (user.is_connected() or user.is_whitelisted()):
+ return (sw_name, room, u'Utilisateur non cotisant', VLAN_NON_MEMBER)
# else: user OK, on passe à la verif MAC
# Si on fait de l'auth par mac, on cherche l'interface via sa mac dans la bdd
@@ -431,7 +435,7 @@ def decide_vlan_switch(nas_machine, nas_type, port_number,
# On essaye de register la mac, si l'autocapture a été activée
# Sinon on rejette sur vlan_nok
if not nas_type.autocapture_mac:
- return (sw_name, "", u'Machine inconnue', VLAN_NOK, True)
+ return (sw_name, "", u'Machine inconnue', VLAN_NON_MEMBER)
# On rejette pour basculer sur du webauth
else:
return (sw_name, room, u'Machine Inconnue -> Web redirect', None, False)
@@ -445,8 +449,7 @@ def decide_vlan_switch(nas_machine, nas_type, port_number,
return (sw_name,
room,
u'Machine non active / adherent non cotisant',
- VLAN_NOK,
- True)
+ VLAN_NON_MEMBER)
## Si on choisi de placer les machines sur le vlan correspondant à leur type :
if RADIUS_POLICY == 'MACHINE':
DECISION_VLAN = interface.type.ip_type.vlan.vlan_id
diff --git a/preferences/migrations/0052_auto_20181013_1629.py b/preferences/migrations/0052_auto_20181013_1629.py
new file mode 100644
index 00000000..70498536
--- /dev/null
+++ b/preferences/migrations/0052_auto_20181013_1629.py
@@ -0,0 +1,91 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.10.7 on 2018-10-13 14:29
+from __future__ import unicode_literals
+
+from django.db import migrations, models
+import django.db.models.deletion
+import re2o.mixins
+
+
+def create_radius_policy(apps, schema_editor):
+ OptionalTopologie = apps.get_model('preferences', 'OptionalTopologie')
+ RadiusOption = apps.get_model('preferences', 'RadiusOption')
+ RadiusPolicy = apps.get_model('preferences', 'RadiusPolicy')
+
+ option,_ = OptionalTopologie.objects.get_or_create()
+
+ radius_option = RadiusOption()
+ radius_option.radius_general_policy = option.radius_general_policy
+ radius_option.unknown_machine = RadiusPolicy.objects.create()
+ radius_option.unknown_port = RadiusPolicy.objects.create()
+ radius_option.unknown_room = RadiusPolicy.objects.create()
+ radius_option.non_member = RadiusPolicy.objects.create()
+ radius_option.banned = RadiusPolicy.objects.create()
+ radius_option.vlan_decision_ok = option.vlan_decision_ok
+
+ radius_option.save()
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('machines', '0095_auto_20180919_2225'),
+ ('preferences', '0051_auto_20180919_2225'),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='RadiusOption',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('radius_general_policy', models.CharField(choices=[('MACHINE', "On the IP range's VLAN of the machine"), ('DEFINED', "Preset in 'VLAN for machines accepted by RADIUS'")], default='DEFINED', max_length=32)),
+ ],
+ options={
+ 'verbose_name': 'radius policies',
+ },
+ bases=(re2o.mixins.AclMixin, models.Model),
+ ),
+ migrations.CreateModel(
+ name='RadiusPolicy',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('policy', models.CharField(choices=[('REJECT', 'Reject the machine'), ('SET_VLAN', 'Place the machine on the VLAN')], default='REJECT', max_length=32)),
+ ('vlan', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='machines.Vlan')),
+ ],
+ options={
+ 'verbose_name': 'radius policy',
+ },
+ bases=(re2o.mixins.AclMixin, models.Model),
+ ),
+ migrations.AddField(
+ model_name='radiusoption',
+ name='non_member',
+ field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='non_member_option', to='preferences.RadiusPolicy', verbose_name='Policy non member users.'),
+ ),
+ migrations.AddField(
+ model_name='radiusoption',
+ name='unknown_machine',
+ field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='unknown_machine_option', to='preferences.RadiusPolicy', verbose_name='Policy for unknown machines'),
+ ),
+ migrations.AddField(
+ model_name='radiusoption',
+ name='unknown_port',
+ field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='unknown_port_option', to='preferences.RadiusPolicy', verbose_name='Policy for unknown machines'),
+ ),
+ migrations.AddField(
+ model_name='radiusoption',
+ name='unknown_room',
+ field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='unknown_room_option', to='preferences.RadiusPolicy', verbose_name='Policy for machine connecting from unregistered room (relevant on ports with STRICT radius mode)'),
+ ),
+ migrations.AddField(
+ model_name='radiusoption',
+ name='banned',
+ field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='banned_option', to='preferences.RadiusPolicy', verbose_name='Policy for banned users.'),
+ ),
+ migrations.AddField(
+ model_name='radiusoption',
+ name='vlan_decision_ok',
+ field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='vlan_ok_option', to='machines.Vlan'),
+ ),
+ migrations.RunPython(create_radius_policy),
+ ]
diff --git a/preferences/models.py b/preferences/models.py
index 43ff7580..f3f5527e 100644
--- a/preferences/models.py
+++ b/preferences/models.py
@@ -218,6 +218,7 @@ class OptionalTopologie(AclMixin, PreferencesModel):
blank=True,
null=True
)
+
switchs_web_management = models.BooleanField(
default=False,
help_text="Web management, activé si provision automatique"
@@ -309,7 +310,6 @@ class OptionalTopologie(AclMixin, PreferencesModel):
"""Return true if all settings are ok : switchs on automatic provision,
ip_type"""
return bool(self.provisioned_switchs and self.switchs_ip_type and SwitchManagementCred.objects.filter(default_switch=True).exists() and self.switchs_management_interface_ip and bool(self.switchs_provision != 'sftp' or self.switchs_management_sftp_creds))
-
class Meta:
permissions = (
("view_optionaltopologie", _("Can view the topology options")),
@@ -588,3 +588,86 @@ class MailMessageOption(AclMixin, models.Model):
)
verbose_name = _("email message options")
+
+class RadiusPolicy(AclMixin, models.Model):
+ class Meta:
+ verbose_name = _('radius policy')
+
+ REJECT = 'REJECT'
+ SET_VLAN = 'SET_VLAN'
+ CHOICE_POLICY = (
+ (REJECT, _('Reject the machine')),
+ (SET_VLAN, _('Place the machine on the VLAN'))
+ )
+
+ policy = models.CharField(
+ max_length=32,
+ choices=CHOICE_POLICY,
+ default=REJECT
+ )
+
+ vlan = models.ForeignKey(
+ 'machines.Vlan',
+ on_delete=models.PROTECT,
+ blank=True,
+ null=True
+ )
+
+
+class RadiusOption(AclMixin, models.Model):
+ class Meta:
+ verbose_name = _("radius policies")
+
+ MACHINE = 'MACHINE'
+ DEFINED = 'DEFINED'
+ CHOICE_RADIUS = (
+ (MACHINE, _("On the IP range's VLAN of the machine")),
+ (DEFINED, _("Preset in 'VLAN for machines accepted by RADIUS'")),
+ )
+ radius_general_policy = models.CharField(
+ max_length=32,
+ choices=CHOICE_RADIUS,
+ default='DEFINED'
+ )
+ unknown_machine = models.ForeignKey(
+ RadiusPolicy,
+ on_delete=models.PROTECT,
+ verbose_name=_("Policy for unknown machines"),
+ related_name='unknown_machine_option',
+ )
+ unknown_port = models.ForeignKey(
+ RadiusPolicy,
+ on_delete=models.PROTECT,
+ verbose_name=_("Policy for unknown machines"),
+ related_name='unknown_port_option',
+ )
+ unknown_room = models.ForeignKey(
+ RadiusPolicy,
+ on_delete=models.PROTECT,
+ verbose_name=_(
+ "Policy for machine connecting from "
+ "unregistered room (relevant on ports with STRICT "
+ "radius mode)"
+ ),
+ related_name='unknown_room_option',
+ )
+ non_member = models.ForeignKey(
+ RadiusPolicy,
+ on_delete=models.PROTECT,
+ verbose_name=_("Policy non member users."),
+ related_name='non_member_option',
+ )
+ banned = models.ForeignKey(
+ RadiusPolicy,
+ on_delete=models.PROTECT,
+ verbose_name=_("Policy for banned users."),
+ related_name='banned_option'
+ )
+ vlan_decision_ok = models.OneToOneField(
+ 'machines.Vlan',
+ on_delete=models.PROTECT,
+ related_name='vlan_ok_option',
+ blank=True,
+ null=True
+ )
+
diff --git a/preferences/templates/preferences/aff_radiusoptions.html b/preferences/templates/preferences/aff_radiusoptions.html
new file mode 100644
index 00000000..b434319d
--- /dev/null
+++ b/preferences/templates/preferences/aff_radiusoptions.html
@@ -0,0 +1,96 @@
+{% comment %}
+Re2o est un logiciel d'administration développé initiallement au rezometz. Il
+se veut agnostique au réseau considéré, de manière à être installable en
+quelques clics.
+
+Copyright © 2018 Hugo Levy-Falk
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+{% endcomment %}
+{% load i18n %}
+{% load acl %}
+{% load logs_extra %}
+
+
+
+ {% trans "General policy for VLAN setting" %} |
+ {{ radiusoptions.radius_general_policy }} |
+ {% trans "This setting defines the VLAN policy after acceptance by RADIUS: either on the IP range's VLAN of the machine, or a VLAN preset in 'VLAN for machines accepted by RADIUS'" %} |
+
+
+ {% trans "VLAN for machines accepted by RADIUS" %} |
+ {{ radiusoptions.vlan_decision_ok }} |
+
+
+
+
+
+
+ {% trans "Situation" %} |
+ {% trans "Behavior" %} |
+
+
+
+ {% trans "Unknown machine" %} |
+
+ {% if radiusoptions.unknown_machine.policy == 'REJECT' %}
+ {% trans "Reject" %}
+ {% else %}
+ Vlan {{ radiusoptions.unknown_machine.vlan }}
+ {% endif %}
+ |
+
+
+ {% trans "Unknown port" %} |
+
+ {% if radiusoptions.unknown_port.policy == 'REJECT' %}
+ {% trans "Reject" %}
+ {% else %}
+ Vlan {{ radiusoptions.unknown_port.vlan }}
+ {% endif %}
+ |
+
+
+ {% trans "Unknown room" %} |
+
+ {% if radiusoptions.unknown_room.policy == 'REJECT' %}
+ {% trans "Reject" %}
+ {% else %}
+ Vlan {{ radiusoptions.unknown_room.vlan }}
+ {% endif %}
+ |
+
+
+ {% trans "Non member" %} |
+
+ {% if radiusoptions.non_member.policy == 'REJECT' %}
+ {% trans "Reject" %}
+ {% else %}
+ Vlan {{ radiusoptions.non_member.vlan }}
+ {% endif %}
+ |
+
+
+ {% trans "Banned user" %} |
+
+ {% if radiusoptions.unknown_port.policy == 'REJECT' %}
+ {% trans "Reject" %}
+ {% else %}
+ Vlan {{ radiusoptions.banned.vlan }}
+ {% endif %}
+ |
+
+
+
diff --git a/preferences/templates/preferences/display_preferences.html b/preferences/templates/preferences/display_preferences.html
index 96d3fe16..e031b56c 100644
--- a/preferences/templates/preferences/display_preferences.html
+++ b/preferences/templates/preferences/display_preferences.html
@@ -132,10 +132,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
{% trans "VLAN for machines rejected by RADIUS" %} |
{{ topologieoptions.vlan_decision_nok }} |
-
- Placement sur ce vlan par default en cas de rejet |
- {{ topologieoptions.vlan_decision_nok }} |
-
+
+ {% trans "VLAN for non members machines" %} |
+ {{ topologieoptions.vlan_non_member }} |
+
Clef radius
@@ -162,11 +162,11 @@ with this program; if not, write to the Free Software Foundation, Inc.,
Switchs configurés automatiquement |
{{ topologieoptions.provisioned_switchs|join:", " }} {% if topologieoptions.provisioned_switchs %} OK{% else %}Manquant{% endif %} |
-
+
Plage d'ip de management des switchs |
{{ topologieoptions.switchs_ip_type }} {% if topologieoptions.switchs_ip_type %} OK{% else %}Manquant{% endif %} |
-
+
Serveur des config des switchs |
{{ topologieoptions.switchs_management_interface }} {% if topologieoptions.switchs_management_interface %} - {{ topologieoptions.switchs_management_interface_ip }} OK{% else %}Manquant{% endif %} |
@@ -195,6 +195,22 @@ with this program; if not, write to the Free Software Foundation, Inc.,
+ {% if topologieoptions.provisioned_switchs %}Provision de la config des switchs{% else %}Provision de la config des switchs{% endif%}
+
+
+ Switchs configurés automatiquement |
+ {{ topologieoptions.provisioned_switchs|join:", " }} |
+
+
+
+ {% trans "Radius preferences" %}
+
+
+ {% trans "Edit" %}
+
+ {% include "preferences/aff_radiusoptions.html" %}
+
+
{% trans "General preferences" %}
@@ -225,7 +241,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
{% trans "General message displayed on the website" %} |
{{ generaloptions.general_message }} |
{% trans "Main site url" %} |
- {{ generaloptions.main_site_url }} |
+ {{ generaloptions.main_site_url }} |
{% trans "Summary of the General Terms of Use" %} |
diff --git a/preferences/urls.py b/preferences/urls.py
index 63ca6a39..30163868 100644
--- a/preferences/urls.py
+++ b/preferences/urls.py
@@ -66,6 +66,11 @@ urlpatterns = [
views.edit_options,
name='edit-options'
),
+ url(
+ r'^edit_options/(?PRadiusOption)$',
+ views.edit_options,
+ name='edit-options'
+ ),
url(r'^add_service/$', views.add_service, name='add-service'),
url(
r'^edit_service/(?P[0-9]+)$',
diff --git a/preferences/views.py b/preferences/views.py
index ee81ae89..f62a5a0d 100644
--- a/preferences/views.py
+++ b/preferences/views.py
@@ -62,7 +62,8 @@ from .models import (
HomeOption,
Reminder,
RadiusKey,
- SwitchManagementCred
+ SwitchManagementCred,
+ RadiusOption,
)
from . import models
from . import forms
@@ -86,6 +87,7 @@ def display_options(request):
reminder_list = Reminder.objects.all()
radiuskey_list = RadiusKey.objects.all()
switchmanagementcred_list = SwitchManagementCred.objects.all()
+ radiusoptions, _ = RadiusOption.objects.get_or_create()
return form({
'useroptions': useroptions,
'machineoptions': machineoptions,
@@ -98,7 +100,8 @@ def display_options(request):
'mailcontact_list': mailcontact_list,
'reminder_list': reminder_list,
'radiuskey_list' : radiuskey_list,
- 'switchmanagementcred_list': switchmanagementcred_list,
+ 'switchmanagementcred_list': switchmanagementcred_list,
+ 'radiusoptions' : radiusoptions,
}, 'preferences/display_preferences.html', request)