2018-04-13 20:11:55 +00:00
# -*- mode: python; coding: utf-8 -*-
2021-05-13 17:29:49 +00:00
# Re2o est un logiciel d'administration développé initiallement au Rézo Metz. Il
2017-01-15 23:01:18 +00:00
# se veut agnostique au réseau considéré, de manière à être installable en
# quelques clics.
#
2017-12-03 18:44:24 +00:00
# Copyirght © 2017 Daniel Stan
2017-01-15 23:01:18 +00:00
# Copyright © 2017 Gabriel Détraz
2019-09-29 14:02:28 +00:00
# Copyright © 2017 Lara Kermarec
2017-01-15 23:01:18 +00:00
# Copyright © 2017 Augustin Lemesle
#
# 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.
2016-12-08 14:13:41 +00:00
"""
2020-05-16 01:57:29 +00:00
Python backend for freeradius .
2016-12-08 14:13:41 +00:00
2020-05-16 10:56:09 +00:00
This file contains definition of some functions called by freeradius backend
2020-05-16 01:57:29 +00:00
during auth for wifi , wired device and nas .
2016-12-08 14:13:41 +00:00
2020-05-16 01:57:29 +00:00
Other examples can be found here :
2016-12-08 14:13:41 +00:00
https : / / github . com / FreeRADIUS / freeradius - server / blob / master / src / modules / rlm_python /
2017-10-11 20:22:31 +00:00
2020-05-16 01:57:29 +00:00
Inspired by Daniel Stan in Crans
2016-12-08 14:13:41 +00:00
"""
2021-05-13 17:43:39 +00:00
import logging
2018-04-13 20:11:55 +00:00
import os
import sys
2019-01-23 20:30:17 +00:00
import traceback
2021-05-13 17:33:56 +00:00
2021-05-13 17:43:39 +00:00
import radiusd # Magic module freeradius (radiusd.py is dummy)
2018-04-14 15:30:14 +00:00
from django . core . wsgi import get_wsgi_application
2018-04-13 20:11:55 +00:00
from django . db . models import Q
2018-04-14 15:30:14 +00:00
2017-09-10 20:50:20 +00:00
proj_path = " /var/www/re2o/ "
# This is so Django knows where to find stuff.
os . environ . setdefault ( " DJANGO_SETTINGS_MODULE " , " re2o.settings " )
sys . path . append ( proj_path )
# This is so my local_settings.py gets loaded.
os . chdir ( proj_path )
# This is so models get loaded.
application = get_wsgi_application ( )
2021-05-13 17:43:39 +00:00
from machines . models import Domain , Interface , IpList , Nas
from preferences . models import RadiusOption
2018-04-26 07:19:10 +00:00
from topologie . models import Port , Switch
from users . models import User
2021-05-13 17:33:56 +00:00
2018-04-26 07:19:10 +00:00
2021-05-13 17:33:56 +00:00
# Logging
2016-12-08 14:13:41 +00:00
class RadiusdHandler ( logging . Handler ) :
2021-05-13 17:30:52 +00:00
""" Logs handler for freeradius """
2016-12-08 14:13:41 +00:00
def emit ( self , record ) :
2021-05-13 17:30:52 +00:00
""" Log message processing, level are converted """
2016-12-08 14:13:41 +00:00
if record . levelno > = logging . WARN :
rad_sig = radiusd . L_ERR
elif record . levelno > = logging . INFO :
rad_sig = radiusd . L_INFO
else :
rad_sig = radiusd . L_DBG
2021-05-13 17:29:49 +00:00
radiusd . radlog ( rad_sig , str ( record . msg ) )
2016-12-08 14:13:41 +00:00
2018-04-13 20:11:55 +00:00
2021-05-13 17:43:39 +00:00
# Init for logging
2019-11-04 16:55:03 +00:00
logger = logging . getLogger ( " auth.py " )
2016-12-08 14:13:41 +00:00
logger . setLevel ( logging . DEBUG )
2019-11-04 16:55:03 +00:00
formatter = logging . Formatter ( " %(name)s : [ %(levelname)s ] %(message)s " )
2016-12-08 14:13:41 +00:00
handler = RadiusdHandler ( )
handler . setFormatter ( formatter )
logger . addHandler ( handler )
2018-04-13 20:11:55 +00:00
2016-12-08 14:13:41 +00:00
def radius_event ( fun ) :
2021-05-13 17:30:52 +00:00
""" Decorator for freeradius fonction with radius.
This function take a unique argument which is a list of tuples ( key , value )
and return a tuple of 3 values which are :
* return code ( see radiusd . RLM_MODULE_ * )
* a tuple of 2 elements for response value ( access ok , etc )
* a tuple of 2 elements for internal value to update ( password for example )
Here , we convert the list of tuples into a dictionnary .
"""
2016-12-08 14:13:41 +00:00
def new_f ( auth_data ) :
2021-05-17 19:59:33 +00:00
""" The function transforming the tuples as dict """
2018-04-14 15:30:14 +00:00
if isinstance ( auth_data , dict ) :
2016-12-08 14:13:41 +00:00
data = auth_data
else :
data = dict ( )
for ( key , value ) in auth_data or [ ] :
# Beware: les valeurs scalaires sont entre guillemets
# Ex: Calling-Station-Id: "une_adresse_mac"
2019-11-04 16:55:03 +00:00
data [ key ] = value . replace ( ' " ' , " " )
2016-12-08 14:13:41 +00:00
try :
return fun ( data )
except Exception as err :
2019-09-10 17:11:14 +00:00
exc_type , exc_instance , exc_traceback = sys . exc_info ( )
2019-11-04 16:55:03 +00:00
formatted_traceback = " " . join ( traceback . format_tb ( exc_traceback ) )
logger . error ( " Failed %r on data %r " % ( err , auth_data ) )
2021-05-13 17:33:56 +00:00
logger . error ( " Function %r , Traceback : %r " % ( fun , formatted_traceback ) )
2018-11-05 13:26:46 +00:00
return radiusd . RLM_MODULE_FAIL
2016-12-08 14:13:41 +00:00
return new_f
2017-12-03 18:44:24 +00:00
2016-12-08 14:13:41 +00:00
@radius_event
def instantiate ( * _ ) :
2021-05-13 17:33:56 +00:00
""" Usefull for instantiate ldap connexions otherwise,
do nothing """
2019-11-04 16:55:03 +00:00
logger . info ( " Instantiation " )
2016-12-08 14:13:41 +00:00
2018-04-13 20:11:55 +00:00
2016-12-08 14:13:41 +00:00
@radius_event
def authorize ( data ) :
2020-05-16 01:57:29 +00:00
""" Here, we test if the Nas is known.
- If the nas is unknown , we assume that it is a 802.1 X request ,
- If the nas is known , we apply the 802.1 X if enabled ,
- It the nas is known AND nas auth is enabled with mac address , returns
accept here """
2021-05-13 17:43:39 +00:00
# For proxified request, split
2021-05-13 17:33:56 +00:00
nas = data . get ( " NAS-IP-Address " , data . get ( " NAS-Identifier " , None ) )
nas_instance = find_nas_from_request ( nas )
2021-05-13 17:43:39 +00:00
# For none proxified requests
2021-05-13 17:33:56 +00:00
nas_type = None
if nas_instance :
nas_type = Nas . objects . filter ( nas_type = nas_instance . machine_type ) . first ( )
if not nas_type or nas_type . port_access_mode == " 802.1X " :
user = data . get ( " User-Name " , " " )
user = user . split ( " @ " , 1 ) [ 0 ]
mac = data . get ( " Calling-Station-Id " , " " )
result , log , password = check_user_machine_and_register ( nas_type , user , mac )
logger . info ( str ( log ) )
logger . info ( str ( user ) )
2017-11-11 18:06:50 +00:00
2017-09-12 17:40:04 +00:00
if not result :
return radiusd . RLM_MODULE_REJECT
else :
2018-04-13 20:11:55 +00:00
return (
radiusd . RLM_MODULE_UPDATED ,
( ) ,
2019-11-04 16:55:03 +00:00
( ( str ( " NT-Password " ) , str ( password ) ) , ) ,
2017-09-12 17:40:04 +00:00
)
2016-12-08 14:13:41 +00:00
2017-09-12 17:40:04 +00:00
else :
2019-11-04 16:55:03 +00:00
return ( radiusd . RLM_MODULE_UPDATED , ( ) , ( ( " Auth-Type " , " Accept " ) , ) )
2016-12-08 14:13:41 +00:00
2018-04-13 20:11:55 +00:00
2016-12-08 14:13:41 +00:00
@radius_event
def post_auth ( data ) :
2021-05-17 19:59:33 +00:00
""" Function called after the user is authenticated """
2018-04-14 15:30:14 +00:00
2019-11-04 16:55:03 +00:00
nas = data . get ( " NAS-IP-Address " , data . get ( " NAS-Identifier " , None ) )
2021-05-13 17:33:56 +00:00
nas_instance = find_nas_from_request ( nas )
2021-05-13 17:43:39 +00:00
# All non proxified requests
2021-05-13 17:33:56 +00:00
if not nas_instance :
2021-05-13 17:28:56 +00:00
logger . info ( " Proxified request, nas unknown " )
2017-09-14 15:24:12 +00:00
return radiusd . RLM_MODULE_OK
2021-05-13 17:33:56 +00:00
nas_type = Nas . objects . filter ( nas_type = nas_instance . machine_type ) . first ( )
if not nas_type :
logger . info ( " This kind of nas is not registered in the database! " )
return radiusd . RLM_MODULE_OK
2017-12-03 18:44:24 +00:00
2021-05-13 17:33:56 +00:00
mac = data . get ( " Calling-Station-Id " , None )
2021-05-13 17:28:56 +00:00
2021-05-13 17:33:56 +00:00
# Switchs and access point can have several interfaces
nas_machine = nas_instance . machine
# If it is a switchs
if hasattr ( nas_machine , " switch " ) :
port = data . get ( " NAS-Port-Id " , data . get ( " NAS-Port " , None ) )
# If the switch is part of a stack, calling ip is different from calling switch.
instance_stack = nas_machine . switch . stack
if instance_stack :
# If it is a stack, we select the correct switch in the stack
2021-05-14 11:05:32 +00:00
#
# For Juniper, the result looks something like this: NAS-Port-Id = "ge-0/0/6.0""
# For other brands (e.g. HP or Mikrotik), the result usually looks like: NAS-Port-Id = "6.0"
# This "magic split" handles both cases
# Cisco can rot in Hell for all I care, so their format is not supported (it looks like NAS-Port-ID = atm 31/31/7:255.65535 guangzhou001/0/31/63/31/127)
2021-05-13 17:33:56 +00:00
id_stack_member = port . split ( " - " ) [ 1 ] . split ( " / " ) [ 0 ]
nas_machine = (
Switch . objects . filter ( stack = instance_stack )
. filter ( stack_member_id = id_stack_member )
. prefetch_related ( " interface_set__domain__extension " )
. first ( )
)
2021-05-14 11:05:32 +00:00
# Find the port number from freeradius
#
# For Juniper, the result looks something like this: NAS-Port-Id = "ge-0/0/6.0""
# For other brands (e.g. HP or Mikrotik), the result usually looks like: NAS-Port-Id = "6.0"
# This "magic split" handles both cases
# Cisco can rot in Hell for all I care, so their format is not supported (it looks like NAS-Port-ID = atm 31/31/7:255.65535 guangzhou001/0/31/63/31/127)
2021-05-13 17:33:56 +00:00
port = port . split ( " . " ) [ 0 ] . split ( " / " ) [ - 1 ] [ - 2 : ]
out = decide_vlan_switch ( nas_machine , nas_type , port , mac )
sw_name , room , reason , vlan_id , decision , attributes = out
2018-08-30 00:11:14 +00:00
if decision :
2020-05-16 01:57:29 +00:00
log_message = " (wired) %s -> %s [ %s %s ] " % (
2021-05-13 17:33:56 +00:00
sw_name + " : " + port + " / " + str ( room ) ,
2018-08-30 00:11:14 +00:00
mac ,
vlan_id ,
2020-05-16 01:57:29 +00:00
( reason and " : " + reason ) ,
2018-08-30 00:11:14 +00:00
)
logger . info ( log_message )
2017-09-12 17:40:04 +00:00
2021-05-13 17:33:56 +00:00
# Wired connexion
2018-08-30 00:11:14 +00:00
return (
radiusd . RLM_MODULE_UPDATED ,
(
( " Tunnel-Type " , " VLAN " ) ,
( " Tunnel-Medium-Type " , " IEEE-802 " ) ,
2019-11-04 16:55:03 +00:00
( " Tunnel-Private-Group-Id " , " %d " % int ( vlan_id ) ) ,
)
+ tuple ( attributes ) ,
( ) ,
2018-08-30 00:11:14 +00:00
)
else :
2021-05-13 17:33:56 +00:00
log_message = " (fil) %s -> %s [Reject %s ] " % (
sw_name + " : " + port + " / " + str ( room ) ,
2018-08-30 00:11:14 +00:00
mac ,
2020-05-16 01:57:29 +00:00
( reason and " : " + reason ) ,
2018-08-30 00:11:14 +00:00
)
logger . info ( log_message )
2017-09-12 17:40:04 +00:00
2019-11-04 16:55:03 +00:00
return ( radiusd . RLM_MODULE_REJECT , tuple ( attributes ) , ( ) )
2016-12-08 14:13:41 +00:00
2017-09-12 17:40:04 +00:00
else :
return radiusd . RLM_MODULE_OK
2016-12-08 14:13:41 +00:00
2018-04-13 20:11:55 +00:00
2021-05-13 17:33:56 +00:00
# TODO : remove this function
@radius_event
def dummy_fun ( _ ) :
""" Do nothing, successfully. """
return radiusd . RLM_MODULE_OK
def detach ( _ = None ) :
""" Detatch the auth """
print ( " *** goodbye from auth.py *** " )
return radiusd . RLM_MODULE_OK
def find_nas_from_request ( nas_id ) :
""" Get the nas object from its ID """
nas = (
Interface . objects . filter (
Q ( domain = Domain . objects . filter ( name = nas_id ) )
| Q ( ipv4 = IpList . objects . filter ( ipv4 = nas_id ) )
)
. select_related ( " machine_type " )
. select_related ( " machine__switch__stack " )
)
return nas . first ( )
def check_user_machine_and_register ( nas_type , username , mac_address ) :
2020-05-16 01:57:29 +00:00
""" Check if username and mac are registered. Register it if unknown.
Return the user ntlm password if everything is ok .
2021-05-13 17:33:56 +00:00
Used for 802.1 X auth """
interface = Interface . objects . filter ( mac_address = mac_address ) . first ( )
user = User . objects . filter ( pseudo__iexact = username ) . first ( )
2017-09-12 17:40:04 +00:00
if not user :
2020-05-16 01:57:29 +00:00
return ( False , " User unknown " , " " )
2021-05-13 17:33:56 +00:00
if not user . has_access ( ) :
2020-05-16 01:57:29 +00:00
return ( False , " Invalid connexion (non-contributing user) " , " " )
2021-05-13 17:33:56 +00:00
if interface :
if interface . machine . user != user :
2019-11-04 16:55:03 +00:00
return (
False ,
2020-05-16 01:57:29 +00:00
" Mac address registered on another user account " ,
2019-11-04 16:55:03 +00:00
" " ,
)
2021-05-13 17:33:56 +00:00
elif not interface . is_active :
2020-05-16 01:57:29 +00:00
return ( False , " Interface/Machine disabled " , " " )
2021-05-13 17:33:56 +00:00
elif not interface . ipv4 :
interface . assign_ipv4 ( )
return ( True , " Ok, new ipv4 assignement... " , user . pwd_ntlm )
2017-09-12 17:40:04 +00:00
else :
2021-05-13 17:33:56 +00:00
return ( True , " Access ok " , user . pwd_ntlm )
2017-09-14 14:42:50 +00:00
elif nas_type :
2021-05-13 17:33:56 +00:00
if nas_type . autocapture_mac :
result , reason = user . autoregister_machine ( mac_address , nas_type )
if result :
return ( True , " Access Ok, Registering mac... " , user . pwd_ntlm )
else :
return ( False , " Error during mac register %s " % reason , " " )
2017-10-04 11:50:12 +00:00
else :
2020-05-16 01:57:29 +00:00
return ( False , " Unknown interface/machine " , " " )
2017-09-12 17:40:04 +00:00
else :
2020-05-16 01:57:29 +00:00
return ( False , " Unknown interface/machine " , " " )
2017-09-12 17:40:04 +00:00
2021-05-13 17:33:56 +00:00
def decide_vlan_switch ( nas_machine , nas_type , port_number , mac_address ) :
2020-05-16 01:57:29 +00:00
""" Function for selecting vlan for a switch with wired mac auth radius.
2021-05-13 17:33:56 +00:00
Several modes are available :
2020-05-16 01:57:29 +00:00
- all modes :
2021-05-13 17:33:56 +00:00
- unknown NAS : VLAN_OK ,
- unknown port : Decision set in Re2o RadiusOption
- No radius on this port : VLAN_OK
- force : returns vlan provided by the database
2018-12-04 19:00:18 +00:00
- mode strict :
2020-05-16 01:57:29 +00:00
- no room : Decision set in Re2o RadiusOption ,
- no user in this room : Reject ,
- user of this room is banned or disable : Reject ,
2021-05-13 17:43:39 +00:00
- user of this room non - contributor and not whitelisted :
2020-05-16 01:57:29 +00:00
Decision set in Re2o RadiusOption
2018-12-04 19:00:18 +00:00
- mode common :
2020-05-16 01:57:29 +00:00
- mac - address already registered :
- related user non contributor / interface disabled :
2021-05-13 17:33:56 +00:00
Decision set in Re2o RadiusOption
2020-05-16 01:57:29 +00:00
- related user is banned :
2021-05-13 17:33:56 +00:00
Decision set in Re2o RadiusOption
2020-05-16 01:57:29 +00:00
- user contributing : VLAN_OK ( can assign ipv4 if needed )
- unknown interface :
- register mac disabled : Decision set in Re2o RadiusOption
2021-05-13 17:33:56 +00:00
- register mac enabled : redirect to webauth
2018-12-04 19:00:18 +00:00
Returns :
2020-05-16 01:57:29 +00:00
tuple with :
2021-05-13 17:33:56 +00:00
- Switch name ( str )
- Room ( str )
2020-05-16 01:57:29 +00:00
- Reason of the decision ( str )
2018-12-04 19:00:18 +00:00
- vlan_id ( int )
- decision ( bool )
2021-05-13 17:33:56 +00:00
- Other Attributs ( attribut : str , operator : str , value : str )
2017-11-19 20:09:57 +00:00
"""
2019-09-10 17:11:14 +00:00
attributes_kwargs = {
2021-05-13 17:33:56 +00:00
" client_mac " : str ( mac_address ) ,
" switch_port " : str ( port_number ) ,
2019-09-10 17:11:14 +00:00
}
2021-05-13 17:33:56 +00:00
# Get port from switch and port number
2017-10-04 02:31:28 +00:00
extra_log = " "
2021-05-13 17:43:39 +00:00
# If NAS is unknown, go to default vlan
2018-03-26 23:26:17 +00:00
if not nas_machine :
2019-09-09 15:59:43 +00:00
return (
2019-11-04 16:55:03 +00:00
" ? " ,
2020-05-16 01:57:29 +00:00
" Unknown room " ,
" Unknown NAS " ,
2019-11-04 16:55:03 +00:00
RadiusOption . get_cached_value ( " vlan_decision_ok " ) . vlan_id ,
2019-09-09 15:59:43 +00:00
True ,
2019-11-04 16:55:03 +00:00
RadiusOption . get_attributes ( " ok_attributes " , attributes_kwargs ) ,
2019-09-09 15:59:43 +00:00
)
2017-09-10 20:50:20 +00:00
2019-11-04 16:55:03 +00:00
sw_name = str ( getattr ( nas_machine , " short_name " , str ( nas_machine ) ) )
2017-09-10 20:50:20 +00:00
2019-09-10 17:11:14 +00:00
switch = Switch . objects . filter ( machine_ptr = nas_machine ) . first ( )
2019-11-04 16:55:03 +00:00
attributes_kwargs [ " switch_ip " ] = str ( switch . ipv4 )
port = Port . objects . filter ( switch = switch , port = port_number ) . first ( )
2018-07-11 17:37:22 +00:00
2021-05-13 17:33:56 +00:00
# If the port is unknwon, go to default vlan
# We don't have enought information to make a better decision
if not port :
2018-12-04 19:00:18 +00:00
return (
2021-05-13 17:33:56 +00:00
sw_name ,
2020-05-16 01:57:29 +00:00
" Unknown port " ,
2021-05-13 17:33:56 +00:00
" PUnknown port " ,
getattr (
RadiusOption . get_cached_value ( " unknown_port_vlan " ) , " vlan_id " , None
) ,
RadiusOption . get_cached_value ( " unknown_port " ) != RadiusOption . REJECT ,
RadiusOption . get_attributes ( " unknown_port_attributes " , attributes_kwargs ) ,
2018-12-04 19:00:18 +00:00
)
2021-05-13 17:43:39 +00:00
2020-05-16 01:57:29 +00:00
# Retrieve port profile
2018-07-11 17:37:22 +00:00
port_profile = port . get_port_profile
2018-06-30 16:36:14 +00:00
2020-05-16 01:57:29 +00:00
# If a vlan is precised in port config, we use it
2021-05-13 17:33:56 +00:00
if port_profile . vlan_untagged :
DECISION_VLAN = int ( port_profile . vlan_untagged . vlan_id )
extra_log = " Force sur vlan " + str ( DECISION_VLAN )
2019-09-09 15:59:43 +00:00
attributes = ( )
2017-10-04 02:31:28 +00:00
else :
2021-05-13 17:33:56 +00:00
DECISION_VLAN = RadiusOption . get_cached_value ( " vlan_decision_ok " ) . vlan_id
attributes = RadiusOption . get_attributes ( " ok_attributes " , attributes_kwargs )
2017-09-10 20:50:20 +00:00
2020-05-16 01:57:29 +00:00
# If the port is disabled in re2o, REJECT
2021-05-13 17:33:56 +00:00
if not port . state :
return ( sw_name , port . room , " Port disabled " , None , False , ( ) )
2018-06-30 17:04:15 +00:00
2020-05-16 01:57:29 +00:00
# If radius is disabled, decision is OK
2021-05-13 17:33:56 +00:00
if port_profile . radius_type == " NO " :
2019-11-04 16:55:03 +00:00
return (
2021-05-13 17:33:56 +00:00
sw_name ,
" " ,
2020-05-16 01:57:29 +00:00
" No Radius auth enabled on this port " + extra_log ,
2019-11-04 16:55:03 +00:00
DECISION_VLAN ,
True ,
attributes ,
)
2017-09-10 20:50:20 +00:00
2020-05-16 01:57:29 +00:00
# If 802.1X is enabled, people has been previously accepted.
# Go to the decision vlan
2021-05-13 17:33:56 +00:00
if ( nas_type . port_access_mode , port_profile . radius_type ) == ( " 802.1X " , " 802.1X " ) :
room = port . room or " Room unknown "
2018-12-04 19:00:18 +00:00
return (
2021-05-13 17:33:56 +00:00
sw_name ,
room ,
2020-05-16 01:57:29 +00:00
" Accept authentication 802.1X " ,
2018-12-04 19:00:18 +00:00
DECISION_VLAN ,
2019-09-09 15:59:43 +00:00
True ,
2019-11-04 16:55:03 +00:00
attributes ,
2018-12-04 19:00:18 +00:00
)
2018-06-30 22:17:24 +00:00
2020-05-16 01:57:29 +00:00
# Otherwise, we are in mac radius.
# If strict mode is enabled, we check every user related with this port. If
2021-05-13 17:33:56 +00:00
# one user or more is not enabled, we reject to prevent from sharing or
2020-05-16 01:57:29 +00:00
# spoofing mac.
2021-05-13 17:33:56 +00:00
if port_profile . radius_mode == " STRICT " :
room = port . room
if not room :
2018-12-04 19:00:18 +00:00
return (
2021-05-13 17:33:56 +00:00
sw_name ,
" Unknown " ,
2020-05-16 01:57:29 +00:00
" Unkwown room " ,
2021-05-13 17:33:56 +00:00
getattr (
RadiusOption . get_cached_value ( " unknown_room_vlan " ) , " vlan_id " , None
) ,
RadiusOption . get_cached_value ( " unknown_room " ) != RadiusOption . REJECT ,
RadiusOption . get_attributes (
" unknown_room_attributes " , attributes_kwargs
) ,
2018-12-04 19:00:18 +00:00
)
2017-09-10 20:50:20 +00:00
2021-05-13 17:33:56 +00:00
room_user = User . objects . filter (
Q ( club__room = port . room ) | Q ( adherent__room = port . room )
)
if not room_user :
2018-12-04 19:00:18 +00:00
return (
2021-05-13 17:33:56 +00:00
sw_name ,
room ,
2020-05-16 01:57:29 +00:00
" Non-contributing room " ,
2021-05-13 17:33:56 +00:00
getattr (
RadiusOption . get_cached_value ( " non_member_vlan " ) , " vlan_id " , None
) ,
RadiusOption . get_cached_value ( " non_member " ) != RadiusOption . REJECT ,
RadiusOption . get_attributes ( " non_member_attributes " , attributes_kwargs ) ,
2018-12-04 19:00:18 +00:00
)
2021-05-13 17:33:56 +00:00
for user in room_user :
if user . is_ban ( ) or user . state != User . STATE_ACTIVE :
return (
sw_name ,
room ,
" User is banned or disabled " ,
getattr (
RadiusOption . get_cached_value ( " banned_vlan " ) , " vlan_id " , None
) ,
RadiusOption . get_cached_value ( " banned " ) != RadiusOption . REJECT ,
RadiusOption . get_attributes ( " banned_attributes " , attributes_kwargs ) ,
)
elif user . email_state == User . EMAIL_STATE_UNVERIFIED :
return (
sw_name ,
room ,
" User is suspended (mail has not been confirmed) " ,
getattr (
RadiusOption . get_cached_value ( " non_member_vlan " ) ,
" vlan_id " ,
None ,
) ,
RadiusOption . get_cached_value ( " non_member " ) != RadiusOption . REJECT ,
RadiusOption . get_attributes (
" non_member_attributes " , attributes_kwargs
) ,
)
elif not ( user . is_connected ( ) or user . is_whitelisted ( ) ) :
return (
sw_name ,
room ,
" Non-contributing member " ,
getattr (
RadiusOption . get_cached_value ( " non_member_vlan " ) ,
" vlan_id " ,
None ,
) ,
RadiusOption . get_cached_value ( " non_member " ) != RadiusOption . REJECT ,
RadiusOption . get_attributes (
" non_member_attributes " , attributes_kwargs
) ,
)
2020-05-16 01:57:29 +00:00
# else: user OK, so we check MAC now
2017-09-10 20:50:20 +00:00
2021-05-13 17:33:56 +00:00
# If we are authenticating with mac, we look for the interfaces and its mac address
if port_profile . radius_mode == " COMMON " or port_profile . radius_mode == " STRICT " :
# Mac auth
interface = (
Interface . objects . filter ( mac_address = mac_address )
. select_related ( " machine__user " )
. select_related ( " ipv4 " )
. first ( )
)
# If mac is unknown,
if not interface :
room = port . room
# We try to register mac, if autocapture is enabled
# Final decision depend on RADIUSOption set in re2o
if nas_type . autocapture_mac :
return (
sw_name ,
room ,
" Unknown mac/interface " ,
getattr (
RadiusOption . get_cached_value ( " unknown_machine_vlan " ) ,
" vlan_id " ,
None ,
) ,
RadiusOption . get_cached_value ( " unknown_machine " )
!= RadiusOption . REJECT ,
RadiusOption . get_attributes (
" unknown_machine_attributes " , attributes_kwargs
) ,
)
# Otherwise, if autocapture mac is not enabled,
else :
return (
sw_name ,
" " ,
" Unknown mac/interface " ,
getattr (
RadiusOption . get_cached_value ( " unknown_machine_vlan " ) ,
" vlan_id " ,
None ,
) ,
RadiusOption . get_cached_value ( " unknown_machine " )
!= RadiusOption . REJECT ,
RadiusOption . get_attributes (
" unknown_machine_attributes " , attributes_kwargs
) ,
)
2021-05-13 17:30:52 +00:00
2021-05-13 17:33:56 +00:00
# Mac/Interface is found, check if related user is contributing and ok
# If needed, set ipv4 to it
else :
room = port . room
if interface . machine . user . is_ban ( ) :
2018-12-04 19:00:18 +00:00
return (
2021-05-13 17:33:56 +00:00
sw_name ,
room ,
" Banned user " ,
getattr (
RadiusOption . get_cached_value ( " banned_vlan " ) , " vlan_id " , None
) ,
RadiusOption . get_cached_value ( " banned " ) != RadiusOption . REJECT ,
RadiusOption . get_attributes ( " banned_attributes " , attributes_kwargs ) ,
)
if not interface . is_active :
return (
sw_name ,
room ,
" Disabled interface / non-contributing member " ,
getattr (
RadiusOption . get_cached_value ( " non_member_vlan " ) ,
" vlan_id " ,
None ,
) ,
RadiusOption . get_cached_value ( " non_member " ) != RadiusOption . REJECT ,
RadiusOption . get_attributes (
" non_member_attributes " , attributes_kwargs
) ,
)
# If settings is set to related interface vlan policy based on interface type:
if RadiusOption . get_cached_value ( " radius_general_policy " ) == " MACHINE " :
DECISION_VLAN = interface . machine_type . ip_type . vlan . vlan_id
if not interface . ipv4 :
interface . assign_ipv4 ( )
return (
sw_name ,
room ,
2021-05-13 17:30:52 +00:00
" Ok, assigning new ipv4 " + extra_log ,
DECISION_VLAN ,
True ,
attributes ,
2018-12-04 19:00:18 +00:00
)
2021-05-13 17:33:56 +00:00
else :
2018-12-04 19:00:18 +00:00
return (
2021-05-13 17:33:56 +00:00
sw_name ,
room ,
" Interface OK " + extra_log ,
2018-12-04 19:00:18 +00:00
DECISION_VLAN ,
2019-09-09 15:59:43 +00:00
True ,
2019-11-04 16:55:03 +00:00
attributes ,
2018-12-04 19:00:18 +00:00
)