
Maintenant radius dit aux switchs quel vlan mettre en non taggé. Ça permet de switcher facilement sur le bon vlan suivant le type de compte et ça évite la désynchronisation de la configuration des switchs. darcs-hash:20080904041337-af139-665172ad09d19f439c6aa8ee6c529752c0e80d95.gz
98 lines
3.3 KiB
Python
Executable file
98 lines
3.3 KiB
Python
Executable file
#! /usr/bin/env python
|
|
# -*- coding: iso-8859-15 -*-
|
|
|
|
import os, md5, sys, binascii
|
|
from commands import getoutput
|
|
from syslog import *
|
|
|
|
sys.path.append('/usr/scripts/gestion')
|
|
from ldap_crans import crans_ldap, AssociationCrans
|
|
from config import ann_scol, dat, vlans
|
|
|
|
def chap_ok(password, challenge, clear_pass) :
|
|
""" Test l'authentification chap fournie
|
|
password et chalenge doivent être données
|
|
en hexa (avec ou sans le 0x devant)
|
|
|
|
retourne True si l'authentification est OK
|
|
retourne False sinon
|
|
"""
|
|
try :
|
|
challenge = binascii.a2b_hex(challenge.replace('0x',''))
|
|
password = binascii.a2b_hex(password.replace('0x',''))
|
|
if md5.new(password[0] + clear_pass + challenge).digest() == password[1:] :
|
|
return True
|
|
except :
|
|
pass
|
|
|
|
return False
|
|
|
|
def do_auth(mac):
|
|
"""Effectue l'authentification. Renvoie (success, msg,
|
|
vlan). success est 0 si l'authentification est réussie, msg est
|
|
pour les logs et vlan est le vlan non taggé à utiliser pour la
|
|
prise."""
|
|
|
|
global ann_scol
|
|
|
|
if not chap_ok(os.getenv('CHAP_PASSWORD'), os.getenv('CHAP_CHALLENGE'), mac):
|
|
return (-1, "Échec test CHAP", "")
|
|
|
|
# Mac dans la base LDAP
|
|
m = crans_ldap(readonly=True).search('mac=%s' % mac)['machine']
|
|
if len(m) == 0:
|
|
return (0, "Mac inconnue", "accueil")
|
|
elif len(m) > 1:
|
|
return (-1, "Pb recherche mac (nb résultat %d!=1)" % len(m), "")
|
|
|
|
# N'appartient pas au Crans et n'a pas de prise attribuée
|
|
# donc sur uplink ou switch non filtré
|
|
# But : éviter le spoof d'une mac d'une machine clef
|
|
proprio = m[0].proprietaire()
|
|
if proprio.__class__ == AssociationCrans and m[0].prise() == u'N/A':
|
|
return (-1, "Machine du crans", "")
|
|
|
|
# blockliste bloq
|
|
if 'bloq' in m[0].blacklist_actif():
|
|
return (-1, "Bloquage total des services pour cette machine", "")
|
|
|
|
# L'adherent ne paie pas, on le met sur le vlan radin
|
|
if not proprio.adherentPayant():
|
|
return (0, "Ne paie pas", "radin")
|
|
|
|
# Paiment ok ?
|
|
paid = max(proprio.paiement() + [0])
|
|
if dat[1] in (8, 9):
|
|
# En septembre les anciennes adhésions sont OK
|
|
ann_scol -= 1
|
|
elif dat[1] == 10 and dat[2] in (1,2,3):
|
|
# On laisse 3 jours ou les gens ont une page sur squid
|
|
ann_scol -= 1
|
|
if ann_scol > paid:
|
|
return (0, "N'a pas payé", "accueil")
|
|
|
|
# C'est bon
|
|
return (0, "Accès adhérent OK", "adherent")
|
|
|
|
if __name__ == '__main__' :
|
|
# Test chap (comme cela on est sur que c'est bien un switch qui demande)
|
|
mac = os.getenv('USER_NAME', '').replace('"', '')
|
|
|
|
# On vérifie si la mac est autorisée
|
|
(r, msg, vlan) = do_auth(mac)
|
|
|
|
# On logue la prise sur laquelle a lieu la tentative
|
|
openlog("radius_auth.py")
|
|
switch = os.getenv("NAS_IDENTIFIER", "").replace('"', '')
|
|
prise = (len(switch) == 6 and (switch[3] + switch[5]) or (switch + "-"))
|
|
prise += "%02d" % int(os.getenv("NAS_PORT", 0))
|
|
syslog("%s -> %s [%s]" % (prise, mac, msg))
|
|
|
|
if vlan:
|
|
# Cela indique au switch comment configurer le vlan par défaut
|
|
# pour cette prise
|
|
print ", ".join(["Tunnel-Type = VLAN",
|
|
"Tunnel-Medium-Type = IEEE-802",
|
|
"Tunnel-Private-Group-Id = \"%d\"" % vlans[vlan]])
|
|
|
|
sys.exit(r)
|