auth.py 19.2 KB
Newer Older
Maël Kervella's avatar
Maël Kervella committed
1
# -*- mode: python; coding: utf-8 -*-
erdnaxe's avatar
erdnaxe committed
2
# SPDX-License-Identifier: GPL-2.0-or-later
lhark's avatar
lhark committed
3
#
4
# Copyirght © 2017  Daniel Stan
lhark's avatar
lhark committed
5 6 7 8
# Copyright © 2017  Gabriel Détraz
# Copyright © 2017  Goulven Kermarec
# Copyright © 2017  Augustin Lemesle

Gabriel Detraz's avatar
Gabriel Detraz committed
9 10 11 12 13 14 15 16 17
"""
Backend python pour freeradius.

Ce fichier contient la définition de plusieurs fonctions d'interface à
freeradius qui peuvent être appelées (suivant les configurations) à certains
moment de l'authentification, en WiFi, filaire, ou par les NAS eux-mêmes.

Inspirés d'autres exemples trouvés ici :
https://github.com/FreeRADIUS/freeradius-server/blob/master/src/modules/rlm_python/
18 19

Inspiré du travail de Daniel Stan au Crans
Gabriel Detraz's avatar
Gabriel Detraz committed
20 21
"""

Maël Kervella's avatar
Maël Kervella committed
22 23
import os
import sys
Maël Kervella's avatar
Maël Kervella committed
24
import logging
Hugo LEVY-FALK's avatar
Hugo LEVY-FALK committed
25
import traceback
Maël Kervella's avatar
Maël Kervella committed
26
import radiusd  # Module magique freeradius (radiusd.py is dummy)
Maël Kervella's avatar
Maël Kervella committed
27

Maël Kervella's avatar
Maël Kervella committed
28
from django.core.wsgi import get_wsgi_application
Maël Kervella's avatar
Maël Kervella committed
29
from django.db.models import Q
Maël Kervella's avatar
Maël Kervella committed
30

31 32 33 34 35 36 37 38 39 40 41
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()

Hugo LEVY-FALK's avatar
Hugo LEVY-FALK committed
42 43 44
from machines.models import Interface, IpList, Nas, Domain
from topologie.models import Port, Switch
from users.models import User
45
from preferences.models import RadiusOption
Hugo LEVY-FALK's avatar
Hugo LEVY-FALK committed
46 47


Gabriel Detraz's avatar
Gabriel Detraz committed
48 49 50 51
#: Serveur radius de test (pas la prod)
TEST_SERVER = bool(os.getenv('DBG_FREERADIUS', False))


Maël Kervella's avatar
Maël Kervella committed
52
# Logging
Gabriel Detraz's avatar
Gabriel Detraz committed
53 54 55 56 57 58 59 60 61 62 63
class RadiusdHandler(logging.Handler):
    """Handler de logs pour freeradius"""

    def emit(self, record):
        """Process un message de log, en convertissant les niveaux"""
        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
Hugo LEVY-FALK's avatar
Hugo LEVY-FALK committed
64
        radiusd.radlog(rad_sig, record.msg.encode('utf-8'))
Gabriel Detraz's avatar
Gabriel Detraz committed
65

Maël Kervella's avatar
Maël Kervella committed
66

Gabriel Detraz's avatar
Gabriel Detraz committed
67 68 69 70 71 72 73 74
# Initialisation d'un logger (pour logguer unifié)
logger = logging.getLogger('auth.py')
logger.setLevel(logging.DEBUG)
formatter = logging.Formatter('%(name)s: [%(levelname)s] %(message)s')
handler = RadiusdHandler()
handler.setFormatter(formatter)
logger.addHandler(handler)

Maël Kervella's avatar
Maël Kervella committed
75

Gabriel Detraz's avatar
Gabriel Detraz committed
76 77
def radius_event(fun):
    """Décorateur pour les fonctions d'interfaces avec radius.
Maël Kervella's avatar
Maël Kervella committed
78 79
    Une telle fonction prend un uniquement argument, qui est une liste de
    tuples (clé, valeur) et renvoie un triplet dont les composantes sont :
Gabriel Detraz's avatar
Gabriel Detraz committed
80 81 82 83 84 85 86 87 88 89
     * le code de retour (voir radiusd.RLM_MODULE_* )
     * un tuple de couples (clé, valeur) pour les valeurs de réponse (accès ok
       et autres trucs du genre)
     * un tuple de couples (clé, valeur) pour les valeurs internes à mettre à
       jour (mot de passe par exemple)

    On se contente avec ce décorateur (pour l'instant) de convertir la liste de
    tuples en entrée en un dictionnaire."""

    def new_f(auth_data):
Maël Kervella's avatar
Maël Kervella committed
90 91
        """ The function transforming the tuples as dict """
        if isinstance(auth_data, dict):
Gabriel Detraz's avatar
Gabriel Detraz committed
92 93 94 95 96 97 98 99
            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"
                data[key] = value.replace('"', '')
        try:
Maël Kervella's avatar
Maël Kervella committed
100 101
            # TODO s'assurer ici que les tuples renvoyés sont bien des
            # (str,str) : rlm_python ne digère PAS les unicodes
Gabriel Detraz's avatar
Gabriel Detraz committed
102 103 104
            return fun(data)
        except Exception as err:
            logger.error('Failed %r on data %r' % (err, auth_data))
Hugo LEVY-FALK's avatar
Hugo LEVY-FALK committed
105
            logger.debug('Function %r, Traceback: %s' % (fun, repr(traceback.format_stack())))
106
            return radiusd.RLM_MODULE_FAIL
Gabriel Detraz's avatar
Gabriel Detraz committed
107 108 109

    return new_f

110

Gabriel Detraz's avatar
Gabriel Detraz committed
111 112 113 114 115 116
@radius_event
def instantiate(*_):
    """Utile pour initialiser les connexions ldap une première fois (otherwise,
    do nothing)"""
    logger.info('Instantiation')
    if TEST_SERVER:
117
        logger.info(u'DBG_FREERADIUS is enabled')
Gabriel Detraz's avatar
Gabriel Detraz committed
118

Maël Kervella's avatar
Maël Kervella committed
119

Gabriel Detraz's avatar
Gabriel Detraz committed
120 121
@radius_event
def authorize(data):
122
    """On test si on connait le calling nas:
Maël Kervella's avatar
Maël Kervella committed
123 124
    - si le nas est inconnue, on suppose que c'est une requète 802.1X, on la
      traite
125
    - si le nas est connu, on applique 802.1X si le mode est activé
Maël Kervella's avatar
Maël Kervella committed
126 127
    - si le nas est connu et si il s'agit d'un nas auth par mac, on repond
      accept en authorize
128
    """
129
    # Pour les requetes proxifiees, on split
130 131 132
    nas = data.get('NAS-IP-Address', data.get('NAS-Identifier', None))
    nas_instance = find_nas_from_request(nas)
    # Toutes les reuquètes non proxifiées
Gabriel Detraz's avatar
Gabriel Detraz committed
133
    nas_type = None
134
    if nas_instance:
135
        nas_type = Nas.objects.filter(nas_type=nas_instance.machine_type).first()
136
    if not nas_type or nas_type.port_access_mode == '802.1X':
137
        user = data.get('User-Name', '').decode('utf-8', errors='replace')
138
        user = user.split('@', 1)[0]
139
        mac = data.get('Calling-Station-Id', '')
Maël Kervella's avatar
Maël Kervella committed
140 141 142 143 144
        result, log, password = check_user_machine_and_register(
            nas_type,
            user,
            mac
        )
145
        logger.info(log.encode('utf-8'))
146 147
        logger.info(user.encode('utf-8'))

148 149 150
        if not result:
            return radiusd.RLM_MODULE_REJECT
        else:
Maël Kervella's avatar
Maël Kervella committed
151 152 153 154 155 156
            return (
                radiusd.RLM_MODULE_UPDATED,
                (),
                (
                    (str("NT-Password"), str(password)),
                ),
157
            )
Gabriel Detraz's avatar
Gabriel Detraz committed
158

159
    else:
Maël Kervella's avatar
Maël Kervella committed
160 161 162 163 164 165
        return (
            radiusd.RLM_MODULE_UPDATED,
            (),
            (
                ("Auth-Type", "Accept"),
            ),
166
        )
Gabriel Detraz's avatar
Gabriel Detraz committed
167

Maël Kervella's avatar
Maël Kervella committed
168

Gabriel Detraz's avatar
Gabriel Detraz committed
169 170
@radius_event
def post_auth(data):
Maël Kervella's avatar
Maël Kervella committed
171 172 173
    """ Function called after the user is authenticated
    """

174
    nas = data.get('NAS-IP-Address', data.get('NAS-Identifier', None))
root's avatar
root committed
175
    nas_instance = find_nas_from_request(nas)
176
    # Toutes les reuquètes non proxifiées
177
    if not nas_instance:
Gabriel Detraz's avatar
Gabriel Detraz committed
178
        logger.info(u"Requete proxifiee, nas inconnu".encode('utf-8'))
179
        return radiusd.RLM_MODULE_OK
180
    nas_type = Nas.objects.filter(nas_type=nas_instance.machine_type).first()
181
    if not nas_type:
Maël Kervella's avatar
Maël Kervella committed
182
        logger.info(
Gabriel Detraz's avatar
Gabriel Detraz committed
183
            u"Type de nas non enregistre dans la bdd!".encode('utf-8')
Maël Kervella's avatar
Maël Kervella committed
184
        )
185
        return radiusd.RLM_MODULE_OK
186

Gabriel Detraz's avatar
Gabriel Detraz committed
187
    mac = data.get('Calling-Station-Id', None)
188

Maël Kervella's avatar
Maël Kervella committed
189 190
    # Switch et bornes héritent de machine et peuvent avoir plusieurs
    # interfaces filles
191
    nas_machine = nas_instance.machine
192
    # Si il s'agit d'un switch
193
    if hasattr(nas_machine, 'switch'):
194
        port = data.get('NAS-Port-Id', data.get('NAS-Port', None))
Maël Kervella's avatar
Maël Kervella committed
195 196
        # Pour les infrastructures possédant des switchs Juniper :
        # On vérifie si le switch fait partie d'un stack Juniper
197
        instance_stack = nas_machine.switch.stack
198 199 200
        if instance_stack:
            # Si c'est le cas, on resélectionne le bon switch dans la stack
            id_stack_member = port.split("-")[1].split('/')[0]
Maël Kervella's avatar
Maël Kervella committed
201 202 203 204 205
            nas_machine = (Switch.objects
                           .filter(stack=instance_stack)
                           .filter(stack_member_id=id_stack_member)
                           .prefetch_related(
                               'interface_set__domain__extension'
Maël Kervella's avatar
Maël Kervella committed
206
                           )
Maël Kervella's avatar
Maël Kervella committed
207 208 209
                           .first())
        # On récupère le numéro du port sur l'output de freeradius.
        # La ligne suivante fonctionne pour cisco, HP et Juniper
210
        port = port.split(".")[0].split('/')[-1][-2:]
211
        out = decide_vlan_switch(nas_machine, nas_type, port, mac)
212 213 214 215 216 217 218 219 220 221
        sw_name, room, reason, vlan_id, decision = out

        if decision:
            log_message = '(fil) %s -> %s [%s%s]' % (
                sw_name + u":" + port + u"/" + str(room),
                mac,
                vlan_id,
                (reason and u': ' + reason).encode('utf-8')
            )
            logger.info(log_message)
222

223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239
            # Filaire
            return (
                radiusd.RLM_MODULE_UPDATED,
                (
                    ("Tunnel-Type", "VLAN"),
                    ("Tunnel-Medium-Type", "IEEE-802"),
                    ("Tunnel-Private-Group-Id", '%d' % int(vlan_id)),
                ),
                ()
            )
        else:
            log_message = '(fil) %s -> %s [Reject:%s]' % (
                sw_name + u":" + port + u"/" + str(room),
                mac,
                (reason and u': ' + reason).encode('utf-8')
            )
            logger.info(log_message)
240

241
            return radiusd.RLM_MODULE_REJECT
Gabriel Detraz's avatar
Gabriel Detraz committed
242

243 244
    else:
        return radiusd.RLM_MODULE_OK
Gabriel Detraz's avatar
Gabriel Detraz committed
245

Maël Kervella's avatar
Maël Kervella committed
246

Maël Kervella's avatar
Maël Kervella committed
247
# TODO : remove this function
Gabriel Detraz's avatar
Gabriel Detraz committed
248 249 250 251 252
@radius_event
def dummy_fun(_):
    """Do nothing, successfully. (C'est pour avoir un truc à mettre)"""
    return radiusd.RLM_MODULE_OK

Maël Kervella's avatar
Maël Kervella committed
253

Gabriel Detraz's avatar
Gabriel Detraz committed
254 255
def detach(_=None):
    """Appelé lors du déchargement du module (enfin, normalement)"""
Maël Kervella's avatar
Maël Kervella committed
256
    print("*** goodbye from auth.py ***")
Gabriel Detraz's avatar
Gabriel Detraz committed
257 258
    return radiusd.RLM_MODULE_OK

Maël Kervella's avatar
Maël Kervella committed
259

260
def find_nas_from_request(nas_id):
Maël Kervella's avatar
Maël Kervella committed
261
    """ Get the nas object from its ID """
Maël Kervella's avatar
Maël Kervella committed
262 263 264 265 266
    nas = (Interface.objects
           .filter(
               Q(domain=Domain.objects.filter(name=nas_id)) |
               Q(ipv4=IpList.objects.filter(ipv4=nas_id))
           )
267
           .select_related('machine_type')
Maël Kervella's avatar
Maël Kervella committed
268
           .select_related('machine__switch__stack'))
root's avatar
root committed
269
    return nas.first()
270

271

272
def check_user_machine_and_register(nas_type, username, mac_address):
Maël Kervella's avatar
Maël Kervella committed
273 274
    """Verifie le username et la mac renseignee. L'enregistre si elle est
    inconnue.
275 276 277
    Renvoie le mot de passe ntlm de l'user si tout est ok
    Utilise pour les authentifications en 802.1X"""
    interface = Interface.objects.filter(mac_address=mac_address).first()
erdnaxe's avatar
erdnaxe committed
278
    user = User.objects.filter(username__iexact=username).first()
279
    if not user:
280 281
        return (False, u"User inconnu", '')
    if not user.has_access():
Gabriel Detraz's avatar
Gabriel Detraz committed
282
        return (False, u"Adherent non cotisant", '')
283 284
    if interface:
        if interface.machine.user != user:
Maël Kervella's avatar
Maël Kervella committed
285
            return (False,
Gabriel Detraz's avatar
Gabriel Detraz committed
286
                    u"Machine enregistree sur le compte d'un autre "
Maël Kervella's avatar
Maël Kervella committed
287 288
                    "user...",
                    '')
289
        elif not interface.is_active:
Gabriel Detraz's avatar
Gabriel Detraz committed
290
            return (False, u"Machine desactivee", '')
291 292 293
        elif not interface.ipv4:
            interface.assign_ipv4()
            return (True, u"Ok, Reassignation de l'ipv4", user.pwd_ntlm)
294
        else:
295
            return (True, u"Access ok", user.pwd_ntlm)
296
    elif nas_type:
297
        if nas_type.autocapture_mac:
298 299
            result, reason = user.autoregister_machine(mac_address, nas_type)
            if result:
Maël Kervella's avatar
Maël Kervella committed
300 301 302
                return (True,
                        u'Access Ok, Capture de la mac...',
                        user.pwd_ntlm)
303
            else:
304
                return (False, u'Erreur dans le register mac %s' % reason, '')
305 306
        else:
            return (False, u'Machine inconnue', '')
307
    else:
308
        return (False, u"Machine inconnue", '')
309 310


311
def decide_vlan_switch(nas_machine, nas_type, port_number,
312
                       mac_address):
Maël Kervella's avatar
Maël Kervella committed
313 314
    """Fonction de placement vlan pour un switch en radius filaire auth par
    mac.
315
    Plusieurs modes :
316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349
        - tous les modes:
            - nas inconnu: VLAN_OK
            - port inconnu: Politique définie dans RadiusOption
        - pas de radius sur le port: VLAN_OK
        - force: placement sur le vlan indiqué dans la bdd
        - mode strict:
            - pas de chambre associée: Politique définie
              dans RadiusOption
            - pas d'utilisateur dans la chambre : Rejet
              (redirection web si disponible)
            - utilisateur de la chambre banni ou désactivé : Rejet
              (redirection web si disponible)
            - utilisateur de la chambre non cotisant et non whiteslist:
              Politique définie dans RadiusOption

            - sinon passe à common (ci-dessous)
        - 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)
350
    """
351
    # Get port from switch and port number
352
    extra_log = ""
353
    # Si le NAS est inconnu, on place sur le vlan defaut
354
    if not nas_machine:
355
        return ('?', u'Chambre inconnue', u'Nas inconnu', RadiusOption.get_cached_value('vlan_decision_ok').vlan_id, True)
356

357
    sw_name = str(getattr(nas_machine, 'short_name', str(nas_machine)))
358

Maël Kervella's avatar
Maël Kervella committed
359 360 361 362 363 364
    port = (Port.objects
            .filter(
                switch=Switch.objects.filter(machine_ptr=nas_machine),
                port=port_number
            )
            .first())
Hugo LEVY-FALK's avatar
Hugo LEVY-FALK committed
365

Maël Kervella's avatar
Maël Kervella committed
366
    # Si le port est inconnu, on place sur le vlan defaut
chirac's avatar
chirac committed
367 368
    # Aucune information particulière ne permet de déterminer quelle
    # politique à appliquer sur ce port
369
    if not port:
370 371 372 373
        return (
            sw_name,
            "Chambre inconnue",
            u'Port inconnu',
374 375
            getattr(RadiusOption.get_cached_value('unknown_port_vlan'), 'vlan_id', None),
            RadiusOption.get_cached_value('unknown_port')!= RadiusOption.REJECT
376
        )
377

378
    # On récupère le profil du port
Hugo LEVY-FALK's avatar
Hugo LEVY-FALK committed
379
    port_profile = port.get_port_profile
380

Hugo LEVY-FALK's avatar
Hugo LEVY-FALK committed
381
    # Si un vlan a été précisé dans la config du port,
chirac's avatar
chirac committed
382
    # on l'utilise pour VLAN_OK
Hugo LEVY-FALK's avatar
Hugo LEVY-FALK committed
383 384
    if port_profile.vlan_untagged:
        DECISION_VLAN = int(port_profile.vlan_untagged.vlan_id)
385 386
        extra_log = u"Force sur vlan " + str(DECISION_VLAN)
    else:
Hugo LEVY-FALK's avatar
Hugo LEVY-FALK committed
387
        DECISION_VLAN = RadiusOption.get_cached_value('vlan_decision_ok').vlan_id
388

389
    # Si le port est désactivé, on rejette la connexion
390
    if not port.state:
Gabriel Detraz's avatar
Gabriel Detraz committed
391
        return (sw_name, port.room, u'Port desactive', None, False)
392

chirac's avatar
chirac committed
393
    # Si radius est désactivé, on laisse passer
Hugo LEVY-FALK's avatar
Hugo LEVY-FALK committed
394
    if port_profile.radius_type == 'NO':
Maël Kervella's avatar
Maël Kervella committed
395 396 397
        return (sw_name,
                "",
                u"Pas d'authentification sur ce port" + extra_log,
398 399
                DECISION_VLAN,
                True)
400

401 402
    # Si le 802.1X est activé sur ce port, cela veut dire que la personne a
    # été accept précédemment
chirac's avatar
chirac committed
403
    # Par conséquent, on laisse passer sur le bon vlan
404
    if (nas_type.port_access_mode, port_profile.radius_type) == ('802.1X', '802.1X'):
chirac's avatar
chirac committed
405
        room = port.room or "Chambre/local inconnu"
406 407 408 409 410 411 412
        return (
            sw_name,
            room,
            u'Acceptation authentification 802.1X',
            DECISION_VLAN,
            True
        )
chirac's avatar
chirac committed
413 414 415

    # 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
416 417 418 419
    # rattachés à ce port sont bien à jour de cotisation. Sinon on rejette
    # (anti squattage)
    # Il n'est pas possible de se connecter sur une prise strict sans adhérent
    # à jour de cotis dedans
Hugo LEVY-FALK's avatar
Hugo LEVY-FALK committed
420
    if port_profile.radius_mode == 'STRICT':
421 422
        room = port.room
        if not room:
423 424 425 426
            return (
                sw_name,
                "Inconnue",
                u'Chambre inconnue',
427 428
                getattr(RadiusOption.get_cached_value('unknown_room_vlan'), 'vlan_id', None),
                RadiusOption.get_cached_value('unknown_room')!= RadiusOption.REJECT
429
            )
430

Maël Kervella's avatar
Maël Kervella committed
431 432 433
        room_user = User.objects.filter(
            Q(club__room=port.room) | Q(adherent__room=port.room)
        )
434
        if not room_user:
435 436 437 438 439 440 441
            return (
                sw_name,
                room,
                u'Chambre non cotisante -> Web redirect',
                None,
                False
            )
442
        for user in room_user:
Hugo LEVY-FALK's avatar
Hugo LEVY-FALK committed
443
            if user.is_ban() or user.state != User.STATE_ACTIVE:
444 445 446
                return (
                    sw_name,
                    room,
Gabriel Detraz's avatar
Gabriel Detraz committed
447
                    u'Utilisateur banni ou desactive -> Web redirect',
448 449 450
                    None,
                    False
                )
Hugo LEVY-FALK's avatar
Hugo LEVY-FALK committed
451
            elif not (user.is_connected() or user.is_whitelisted()):
452 453 454 455
                return (
                    sw_name,
                    room,
                    u'Utilisateur non cotisant',
456 457
                    getattr(RadiusOption.get_cached_value('non_member_vlan'), 'vlan_id', None),
                    RadiusOption.get_cached_value('non_member')!= RadiusOption.REJECT
458
                )
459 460
        # else: user OK, on passe à la verif MAC

461 462
    # Si on fait de l'auth par mac, on cherche l'interface
    # via sa mac dans la bdd
Hugo LEVY-FALK's avatar
Hugo LEVY-FALK committed
463
    if port_profile.radius_mode == 'COMMON' or port_profile.radius_mode == 'STRICT':
464
        # Authentification par mac
Maël Kervella's avatar
Maël Kervella committed
465 466 467 468 469
        interface = (Interface.objects
                     .filter(mac_address=mac_address)
                     .select_related('machine__user')
                     .select_related('ipv4')
                     .first())
470
        if not interface:
471
            room = port.room
472 473 474 475 476 477 478 479 480 481 482 483
            # On essaye de register la mac, si l'autocapture a été activée,
            # on rejette pour faire une redirection web si possible.
            if nas_type.autocapture_mac:
                return (
                    sw_name,
                    room,
                    u'Machine Inconnue -> Web redirect',
                    None,
                    False
                )
            # Sinon on bascule sur la politique définie dans les options
            # radius.
484
            else:
485 486 487 488
                return (
                    sw_name,
                    "",
                    u'Machine inconnue',
489 490
                    getattr(RadiusOption.get_cached_value('unknown_machine_vlan'), 'vlan_id', None),
                    RadiusOption.get_cached_value('unknown_machine')!= RadiusOption.REJECT
491 492 493 494
                )

        # L'interface a été trouvée, on vérifie qu'elle est active,
        # sinon on reject
chirac's avatar
chirac committed
495 496
        # Si elle n'a pas d'ipv4, on lui en met une
        # Enfin on laisse passer sur le vlan pertinent
497
        else:
498
            room = port.room
499
            if interface.machine.user.is_ban():
500 501 502 503
                return (
                    sw_name,
                    room,
                    u'Adherent banni',
504 505
                    getattr(RadiusOption.get_cached_value('banned_vlan'), 'vlan_id', None),
                    RadiusOption.get_cached_value('banned')!= RadiusOption.REJECT
506
                )
507
            if not interface.is_active:
508 509 510 511
                return (
                    sw_name,
                    room,
                    u'Machine non active / adherent non cotisant',
512 513
                    getattr(RadiusOption.get_cached_value('non_member_vlan'), 'vlan_id', None),
                    RadiusOption.get_cached_value('non_member')!= RadiusOption.REJECT
514 515 516
                )
            # Si on choisi de placer les machines sur le vlan
            # correspondant à leur type :
517
            if RadiusOption.get_cached_value('radius_general_policy') == 'MACHINE':
518
                DECISION_VLAN = interface.machine_type.ip_type.vlan.vlan_id
519
            if not interface.ipv4:
520
                interface.assign_ipv4()
521 522 523 524 525 526 527
                return (
                    sw_name,
                    room,
                    u"Ok, Reassignation de l'ipv4" + extra_log,
                    DECISION_VLAN,
                    True
                )
528
            else:
529 530 531 532 533 534 535
                return (
                    sw_name,
                    room,
                    u'Machine OK' + extra_log,
                    DECISION_VLAN,
                    True
                )