
Ignore-this: 1977068e83e9be1619fb8b946433c61d Sauf pour les membres actifs (tests de maintenance, toussa) Au passage, il faudrait rajouter aussi une limitation au niveau des machines clubs, qui ne devraient pouvoir être connectées que sur la prise dudit club. darcs-hash:20121109012845-28565-25619e6a508450c2f9fbb00c2a0ae81e63ece194.gz
128 lines
4.4 KiB
Python
128 lines
4.4 KiB
Python
#! /usr/bin/env python
|
|
# -*- coding: utf-8 -*-
|
|
|
|
import os, hashlib, sys, binascii
|
|
from syslog import syslog, openlog
|
|
|
|
sys.path.append('/usr/scripts/gestion')
|
|
from ldap_crans import crans_ldap, AssociationCrans, Club
|
|
from config import ann_scol, dat, vlans, periode_transitoire
|
|
import annuaires_pg
|
|
from iptools import AddrInNet
|
|
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 hashlib.md5(password[0] + clear_pass + challenge).digest() == password[1:] :
|
|
return True
|
|
except :
|
|
return False
|
|
|
|
def paiement_ok(adh):
|
|
"""Paiment ok ?"""
|
|
global ann_scol
|
|
paid = max(adh.paiement() + [0])
|
|
if periode_transitoire:
|
|
# Si periode transitoire, on accepte les personnes n'ayant pas
|
|
# réadhéré
|
|
ann_scol -= 1
|
|
return ann_scol <= paid
|
|
|
|
def do_auth(mac, prise):
|
|
"""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
|
|
|
|
# Test chap (comme cela on est sur que c'est bien un switch qui demande)
|
|
if not chap_ok(os.getenv('CHAP_PASSWORD'), os.getenv('CHAP_CHALLENGE'), mac):
|
|
return (-1, "Échec test CHAP", "")
|
|
|
|
# Mac dans la base LDAP
|
|
conn = crans_ldap(readonly=True)
|
|
m = conn.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", "")
|
|
|
|
# les gens qui doivent être isolés
|
|
if ('virus' in m[0].blacklist_actif() or 'ipv6_ra' in m[0].blacklist_actif()
|
|
or 'autodisc_virus' in m[0].blacklist_actif()):
|
|
return (0, "Bad boy", "isolement")
|
|
|
|
# Paiement proprio ?
|
|
if not paiement_ok(proprio):
|
|
return (0, "N'a pas payé", "accueil")
|
|
|
|
# Si l'adhérent n'est pas membre actif, il doit se brancher depuis la prise
|
|
# d'un autre adhérent à jour de cotisation
|
|
if not proprio.droits():
|
|
try:
|
|
chbre = prise[0] + annuaires_pg.reverse(prise[0], prise[1:])[0]
|
|
except IndexError:
|
|
return (0, "Chambre inconnue", "accueil")
|
|
hebergeurs = conn.search('chambre=' + chbre)
|
|
for hebergeur in hebergeurs['adherent'] + hebergeurs['club']:
|
|
if paiement_ok(hebergeur):
|
|
break
|
|
else:
|
|
return (0, "Hébergeur non à jour", "accueil")
|
|
|
|
# Cas des personnels logés dans les appartements de l'ENS
|
|
if (proprio.etudes(0) == 'Personnel ENS' or
|
|
('Nounou' in proprio.droits() and AddrInNet(m[0].ip(),'10.2.9.0/24'))):
|
|
return (0, "Personnel ENS", "appts")
|
|
|
|
# C'est bon
|
|
return (0, "Accès adhérent OK", "adherent")
|
|
|
|
if __name__ == '__main__' :
|
|
mac = os.getenv('USER_NAME', '').replace('"', '')
|
|
switch = os.getenv("NAS_IDENTIFIER", "").replace('"', '').split('.')[0]
|
|
prise = (len(switch) == 6 and (switch[3] + switch[5]) or (switch + "-"))
|
|
prise += "%02d" % int(os.getenv("NAS_PORT", 0))
|
|
|
|
# On vérifie si la mac est autorisée
|
|
(r, msg, vlan) = do_auth(mac, prise)
|
|
|
|
# On logue la prise sur laquelle a lieu la tentative
|
|
openlog("radius_auth.py")
|
|
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]])
|
|
|
|
# On tente de logguer la dernière mac sur une prise donnée
|
|
try:
|
|
f = open('/usr/scripts/var/last_macs/' + prise,'w')
|
|
f.write(mac)
|
|
f.close()
|
|
except:
|
|
pass
|
|
|
|
sys.exit(r)
|