8
0
Fork 0
mirror of https://gitlab2.federez.net/re2o/re2o synced 2024-11-22 11:23:10 +00:00

Radius opers according to policies.

This commit is contained in:
Hugo LEVY-FALK 2018-12-04 20:00:18 +01:00 committed by chirac
parent 6df47b08ec
commit 2702d7c116

View file

@ -57,14 +57,12 @@ application = get_wsgi_application()
from machines.models import Interface, IpList, Nas, Domain from machines.models import Interface, IpList, Nas, Domain
from topologie.models import Port, Switch from topologie.models import Port, Switch
from users.models import User from users.models import User
from preferences.models import OptionalTopologie from preferences.models import RadiusOption
options, created = OptionalTopologie.objects.get_or_create() OPTIONS, created = RadiusOption.objects.get_or_create()
VLAN_NOK = options.vlan_decision_nok.vlan_id VLAN_OK = OPTIONS.vlan_decision_ok.vlan_id
VLAN_OK = options.vlan_decision_ok.vlan_id RADIUS_POLICY = OPTIONS.radius_general_policy
VLAN_NON_MEMBER = options.vlan_non_member.vlan_id
RADIUS_POLICY = options.radius_general_policy
#: Serveur radius de test (pas la prod) #: Serveur radius de test (pas la prod)
TEST_SERVER = bool(os.getenv('DBG_FREERADIUS', False)) TEST_SERVER = bool(os.getenv('DBG_FREERADIUS', False))
@ -288,6 +286,7 @@ def find_nas_from_request(nas_id):
.select_related('machine__switch__stack')) .select_related('machine__switch__stack'))
return nas.first() return nas.first()
def check_user_machine_and_register(nas_type, username, mac_address): def check_user_machine_and_register(nas_type, username, mac_address):
"""Verifie le username et la mac renseignee. L'enregistre si elle est """Verifie le username et la mac renseignee. L'enregistre si elle est
inconnue. inconnue.
@ -328,27 +327,44 @@ def check_user_machine_and_register(nas_type, username, mac_address):
def decide_vlan_switch(nas_machine, nas_type, port_number, def decide_vlan_switch(nas_machine, nas_type, port_number,
mac_address): mac_address):
"""Fonction de placement vlan pour un switch en radius filaire auth par """Fonction de placement vlan pour un switch en radius filaire auth par
mac. mac.
Plusieurs modes : Plusieurs modes :
- nas inconnu, port inconnu : on place sur le vlan par defaut VLAN_OK - tous les modes:
- pas de radius sur le port : VLAN_OK - nas inconnu: VLAN_OK
- bloq : VLAN_NOK - port inconnu: Politique définie dans RadiusOption
- force : placement sur le vlan indiqué dans la bdd - pas de radius sur le port: VLAN_OK
- mode strict : - force: placement sur le vlan indiqué dans la bdd
- pas de chambre associée : VLAN_NOK - mode strict:
- pas d'utilisateur dans la chambre : VLAN_NOK - pas de chambre associée: Politique définie
- cotisation non à jour : VLAN_NON_MEMBER dans RadiusOption
- sinon passe à common (ci-dessous) - pas d'utilisateur dans la chambre : Rejet
- mode common : (redirection web si disponible)
- interface connue (macaddress): - utilisateur de la chambre banni ou désactivé : Rejet
- utilisateur proprio non cotisant : VLAN_NON_MEMBER (redirection web si disponible)
- utilisateur proprio banni : VLAN_NOK - utilisateur de la chambre non cotisant et non whiteslist:
- user à jour : VLAN_OK Politique définie dans RadiusOption
- interface inconnue :
- register mac désactivé : VLAN_NON_MEMBER - sinon passe à common (ci-dessous)
- register mac activé -> redirection vers webauth - mode common :
- interface connue (macaddress):
- utilisateur proprio non cotisant / machine désactivée:
Politique définie dans RadiusOption
- utilisateur proprio banni :
Politique définie dans RadiusOption
- user à jour : VLAN_OK (réassignation de l'ipv4 au besoin)
- interface inconnue :
- register mac désactivé : Politique définie
dans RadiusOption
- register mac activé: redirection vers webauth
Returns:
tuple avec :
- Nom du switch (str)
- chambre (str)
- raison de la décision (str)
- vlan_id (int)
- decision (bool)
""" """
# Get port from switch and port number # Get port from switch and port number
extra_log = "" extra_log = ""
@ -369,7 +385,13 @@ def decide_vlan_switch(nas_machine, nas_type, port_number,
# Aucune information particulière ne permet de déterminer quelle # Aucune information particulière ne permet de déterminer quelle
# politique à appliquer sur ce port # politique à appliquer sur ce port
if not port: if not port:
return (sw_name, "Chambre inconnue", u'Port inconnu', VLAN_OK, True) return (
sw_name,
"Chambre inconnue",
u'Port inconnu',
OPTIONS.unknown_port_vlan.vlan_id,
OPTIONS.unknown_port != OPTIONS.REJECT
)
# On récupère le profil du port # On récupère le profil du port
port_profile = port.get_port_profile port_profile = port.get_port_profile
@ -382,9 +404,9 @@ def decide_vlan_switch(nas_machine, nas_type, port_number,
else: else:
DECISION_VLAN = VLAN_OK DECISION_VLAN = VLAN_OK
# Si le port est désactivé, on rejette sur le vlan de déconnexion # Si le port est désactivé, on rejette la connexion
if not port.state: if not port.state:
return (sw_name, port.room, u'Port desactivé', VLAN_NOK, True) return (sw_name, port.room, u'Port desactivé', None, False)
# Si radius est désactivé, on laisse passer # Si radius est désactivé, on laisse passer
if port_profile.radius_type == 'NO': if port_profile.radius_type == 'NO':
@ -394,35 +416,68 @@ def decide_vlan_switch(nas_machine, nas_type, port_number,
DECISION_VLAN, DECISION_VLAN,
True) True)
# Si le 802.1X est activé sur ce port, cela veut dire que la personne a été accept précédemment # Si le 802.1X est activé sur ce port, cela veut dire que la personne a
# été accept précédemment
# Par conséquent, on laisse passer sur le bon vlan # Par conséquent, on laisse passer sur le bon vlan
if nas_type.port_access_mode == '802.1X' and port_profile.radius_type == '802.1X': if (nas_type.port_access_mode, port_profile.radius_type) == ('802.1X', '802.1X'):
room = port.room or "Chambre/local inconnu" room = port.room or "Chambre/local inconnu"
return (sw_name, room, u'Acceptation authentification 802.1X', DECISION_VLAN, True) return (
sw_name,
room,
u'Acceptation authentification 802.1X',
DECISION_VLAN,
True
)
# Sinon, cela veut dire qu'on fait de l'auth radius par mac # Sinon, cela veut dire qu'on fait de l'auth radius par mac
# Si le port est en mode strict, on vérifie que tous les users # Si le port est en mode strict, on vérifie que tous les users
# rattachés à ce port sont bien à jour de cotisation. Sinon on rejette (anti squattage) # rattachés à ce port sont bien à jour de cotisation. Sinon on rejette
# Il n'est pas possible de se connecter sur une prise strict sans adhérent à jour de cotis # (anti squattage)
# dedans # Il n'est pas possible de se connecter sur une prise strict sans adhérent
# à jour de cotis dedans
if port_profile.radius_mode == 'STRICT': if port_profile.radius_mode == 'STRICT':
room = port.room room = port.room
if not room: if not room:
return (sw_name, "Inconnue", u'Chambre inconnue', VLAN_NOK, True) return (
sw_name,
"Inconnue",
u'Chambre inconnue',
OPTIONS.unknown_room_vlan.vlan_id,
OPTIONS.unknown_room != OPTIONS.REJECT
)
room_user = User.objects.filter( room_user = User.objects.filter(
Q(club__room=port.room) | Q(adherent__room=port.room) Q(club__room=port.room) | Q(adherent__room=port.room)
) )
if not room_user: if not room_user:
return (sw_name, room, u'Chambre non cotisante -> Web redirect', None, False) return (
sw_name,
room,
u'Chambre non cotisante -> Web redirect',
None,
False
)
for user in room_user: for user in room_user:
if user.is_ban() or user.state != User.STATE_ACTIVE: if user.is_ban() or user.state != User.STATE_ACTIVE:
return (sw_name, room, u'Chambre resident desactive -> Web redirect', None, False) return (
sw_name,
room,
u'Utilisateur banni ou désactivé -> Web redirect',
None,
False
)
elif not (user.is_connected() or user.is_whitelisted()): elif not (user.is_connected() or user.is_whitelisted()):
return (sw_name, room, u'Utilisateur non cotisant', VLAN_NON_MEMBER) return (
sw_name,
room,
u'Utilisateur non cotisant',
OPTIONS.non_member_vlan.vlan_id,
OPTIONS.non_member != OPTIONS.REJECT
)
# else: user OK, on passe à la verif MAC # 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 # Si on fait de l'auth par mac, on cherche l'interface
# via sa mac dans la bdd
if port_profile.radius_mode == 'COMMON' or port_profile.radius_mode == 'STRICT': if port_profile.radius_mode == 'COMMON' or port_profile.radius_mode == 'STRICT':
# Authentification par mac # Authentification par mac
interface = (Interface.objects interface = (Interface.objects
@ -432,37 +487,67 @@ def decide_vlan_switch(nas_machine, nas_type, port_number,
.first()) .first())
if not interface: if not interface:
room = port.room room = port.room
# On essaye de register la mac, si l'autocapture a été activée # On essaye de register la mac, si l'autocapture a été activée,
# Sinon on rejette sur vlan_nok # on rejette pour faire une redirection web si possible.
if not nas_type.autocapture_mac: if nas_type.autocapture_mac:
return (sw_name, "", u'Machine inconnue', VLAN_NON_MEMBER) return (
# On rejette pour basculer sur du webauth sw_name,
room,
u'Machine Inconnue -> Web redirect',
None,
False
)
# Sinon on bascule sur la politique définie dans les options
# radius.
else: else:
return (sw_name, room, u'Machine Inconnue -> Web redirect', None, False) return (
sw_name,
"",
u'Machine inconnue',
OPTIONS.unknown_machine_vlan.vlan_id,
OPTIONS.unknown_machine != OPTIONS.REJECT
)
# L'interface a été trouvée, on vérifie qu'elle est active, sinon on reject # L'interface a été trouvée, on vérifie qu'elle est active,
# sinon on reject
# Si elle n'a pas d'ipv4, on lui en met une # Si elle n'a pas d'ipv4, on lui en met une
# Enfin on laisse passer sur le vlan pertinent # Enfin on laisse passer sur le vlan pertinent
else: else:
room = port.room room = port.room
if interface.machine.user.is_banned():
return (
sw_name,
room,
u'Adherent banni',
OPTIONS.banned_vlan.vlan_id,
OPTIONS.banned != OPTIONS.REJECT
)
if not interface.is_active: if not interface.is_active:
return (sw_name, return (
room, sw_name,
u'Machine non active / adherent non cotisant', room,
VLAN_NON_MEMBER) u'Machine non active / adherent non cotisant',
## Si on choisi de placer les machines sur le vlan correspondant à leur type : OPTIONS.non_member_vlan.vlan_id,
OPTIONS.non_member != OPTIONS.REJECT
)
# Si on choisi de placer les machines sur le vlan
# correspondant à leur type :
if RADIUS_POLICY == 'MACHINE': if RADIUS_POLICY == 'MACHINE':
DECISION_VLAN = interface.type.ip_type.vlan.vlan_id DECISION_VLAN = interface.type.ip_type.vlan.vlan_id
if not interface.ipv4: if not interface.ipv4:
interface.assign_ipv4() interface.assign_ipv4()
return (sw_name, return (
room, sw_name,
u"Ok, Reassignation de l'ipv4" + extra_log, room,
DECISION_VLAN, u"Ok, Reassignation de l'ipv4" + extra_log,
True) DECISION_VLAN,
True
)
else: else:
return (sw_name, return (
room, sw_name,
u'Machine OK' + extra_log, room,
DECISION_VLAN, u'Machine OK' + extra_log,
True) DECISION_VLAN,
True
)