#! /usr/bin/env python # -*- coding: iso-8859-15 -*- import os, md5, 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 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 : 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 isinstance(proprio, Club) and not proprio.adherentPayant(): return (0, "Ne paie pas", "gratuit") # 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") # Cas des personnels logés dans les appartements de l'ENS if proprio.etudes(0) == 'Personnel ENS': return (0, "Personnel ENS", "appts") # 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)