From 0e84b5e02dcd84862ecd18484bdfaf2b70eeb06c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pierre-Elliott=20B=C3=A9cue?= Date: Fri, 3 May 2013 01:48:00 +0200 Subject: [PATCH] =?UTF-8?q?[mac=5Fprises]=20On=20envoie=20plus=20qu'un=20e?= =?UTF-8?q?mail=20par=20jour,=20qui=20contient=20un=20r=C3=A9sum=C3=A9=20q?= =?UTF-8?q?ualitatif,=20et=20des=20d=C3=A9tails=20en=20pi=C3=A8ce=20jointe?= =?UTF-8?q?.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- gestion/config/mac_prise.py | 37 +-- surveillance/mac_prises/mac_prise.py | 15 +- surveillance/mac_prises/mac_prise_analyzer.py | 250 +++++++++++++----- surveillance/mac_prises/mac_prise_cleaner.sh | 3 - surveillance/mac_prises/mac_prise_daily.sh | 6 + surveillance/mac_prises/mac_prise_reperage.py | 119 --------- 6 files changed, 199 insertions(+), 231 deletions(-) delete mode 100755 surveillance/mac_prises/mac_prise_cleaner.sh create mode 100755 surveillance/mac_prises/mac_prise_daily.sh delete mode 100755 surveillance/mac_prises/mac_prise_reperage.py diff --git a/gestion/config/mac_prise.py b/gestion/config/mac_prise.py index 8bdcf477..789c1fb6 100644 --- a/gestion/config/mac_prise.py +++ b/gestion/config/mac_prise.py @@ -8,45 +8,32 @@ hargneux = True #: Si pour une chambre donnée, il y a plus de 300 entrées filaires #: n'appartenant pas à l'adhérent propriétaire de la mac, on prévient. -max_inconnues_par_jour = 300 +max_inconnues_par_jour = 480 #: Titre utilisé dans le corps du message titre_mac_inconnue = u"Repérage de macs potentiellement non désirées dans les chambres suivantes." #: Pour la recherche dans postgres -delay = { 'instant': '2 min', - 'heuristique': '30 min', +delay = { 'instantanne': '2 min', + 'moyen': '30 min', 'journalier': '1 day', } #: Contient trois dictionnaire. Le paramètre mac signifie "combien de chambres doivent voir la même mac pour que ça soit suspect" #: Le paramètre chambre signifie "combien de macs doivent traverser une même chambre pour que ça soit suspect" -suspect = { 'instant':{'mac': 2, 'chambre': 2}, - 'heuristique':{'mac': 2, 'chambre': 2}, - 'journalier':{'mac': 2, 'chambre': 2}, +suspect = { 'instantanne':2, + 'moyen':2, + 'journalier':2, } -#: Contient trois dictionnaire. Le paramètre mac signifie "combien de chambres doivent voir la même mac pour que ça soit très suspect" -#: Le paramètre chambre signifie "combien de macs doivent traverser une même chambre pour que ça soit très suspect" -tres_suspect = { 'instant':{'mac': 3, 'chambre': 3}, - 'heuristique':{'mac': 3, 'chambre': 3}, - 'journalier':{'mac': 3, 'chambre': 3}, - } - #: Le point central des analyses. -rapport_suspect = { 'instant':{'mac': 0.51, 'chambre': 0.51}, - 'heuristique':{'mac': 0.4, 'chambre': 0.55}, - 'journalier':{'mac': 0.2, 'chambre': 0.58}, +rapport_suspect = { 'instantanne':0.51, + 'moyen':0.4, + 'journalier':0.2, } #: Titre des paragraphes suspects -titre_suspect = { 'instant':{'mac': u"Macs se baladant un peu trop entre les chambres (instantanné)", 'chambre': u"Chambres avec un peu trop de macs (instantanné)"}, - 'heuristique':{'mac': u"Macs se baladant un peu trop entre les chambres (délai moyen)", 'chambre': u"Chambres avec un peu trop de macs (délai moyen)"}, - 'journalier':{'mac': u"Macs s'étant peut-être un peu trop baladées aujourd'hui", 'chambre': u"Chambres avec un peu trop de macs sur un jour"}, +titre_suspect = { 'instantanne':u"Macs se baladant un peu trop entre les chambres (instantanneanné)", + 'moyen':u"Macs se baladant un peu trop entre les chambres (délai moyen)", + 'journalier':u"Macs s'étant peut-être un peu trop baladées aujourd'hui", } - -#: Titre des paragraphes très suspects -titre_tres_suspect = { 'instant':{'mac': u"/!\ Spoof potentiel des macs suivantes dans les chambres ci-après (instantanné)", 'chambre': u"/!\ Les chambres ci-après contiennent étrangement trop de macs inconnues ! (instantanné)"}, - 'heuristique':{'mac': u"/!\ Spoof potentiel des macs suivantes dans les chambres ci-après (délai moyen)", 'chambre': u"/!\ Les chambres ci-après contiennent étrangement trop de macs inconnues ! (délai moyen)"}, - 'journalier':{'mac': u"/!\ Spoof probable des macs suivantes dans les chambres ci-après aujourd'hui !!", 'chambre': u"/!\ Les chambres suivantes contiennent trop de macs inconnues (sur un jour)"}, - } diff --git a/surveillance/mac_prises/mac_prise.py b/surveillance/mac_prises/mac_prise.py index 2e241826..0af55c29 100755 --- a/surveillance/mac_prises/mac_prise.py +++ b/surveillance/mac_prises/mac_prise.py @@ -2,14 +2,14 @@ # -*- coding: utf8 -*- # # -# PEB - 01/04/2012 +# PEB - 01/04/2012 -> now() # -import os, sys, re +import os, sys +import sys +import re from commands import getstatusoutput -import time - # nécessite apparemment que l'objet conn soit bien créé lors de l'exec # de annuaires_pg, il faut être root (ou dans je ne sais quel groupe) @@ -103,14 +103,7 @@ def __exec(cmd): if __name__ == '__main__': switchs = sys.argv[1:] - date = time.strftime('%F %T') for switch in switchs: macs = liste_chambres_macs(switch) print macs - -# fichier = -# for chambre in macs.keys(): -# for mac in macs[chambre]: -# -# curseur.execute(requete, (date, chambre, mac)) diff --git a/surveillance/mac_prises/mac_prise_analyzer.py b/surveillance/mac_prises/mac_prise_analyzer.py index 99f8a15f..ca681a7c 100755 --- a/surveillance/mac_prises/mac_prise_analyzer.py +++ b/surveillance/mac_prises/mac_prise_analyzer.py @@ -12,9 +12,14 @@ from config import mac_prise from affich_tools import tableau sys.path.append('/usr/scripts/lc_ldap') import lc_ldap +import collections ldap = lc_ldap.lc_ldap_local() +conn = psycopg2.connect(user='crans', database='mac_prises') +conn.set_session(autocommit = True) +cur = conn.cursor(cursor_factory = psycopg2.extras.DictCursor) + membres_actifs = ldap.search('(|(droits=Cableur)(droits=Nounou)(droits=Apprenti)(droits=Bureau))') chambres_ma = [] for membre_actif in membres_actifs: @@ -31,20 +36,12 @@ for club in clubs: except: pass -conn = psycopg2.connect(user='crans', database='mac_prises') -conn.set_session(autocommit = True) -cur = conn.cursor(cursor_factory = psycopg2.extras.DictCursor) - requete = "SELECT * FROM signales WHERE date >= timestamp 'now' - interval '1 day';" cur.execute(requete) signales = cur.fetchall() -longueur = { 'mac': (24, 3), - 'chambre': (10, 7), - } -titres = { 'mac':(u'mac', u'chambres'), - 'chambre': (u'chambre', u'macs'), - } +longueur = (24, 7) +titres = (u'mac', u'chambres') alignements = ('c', 'c') def lin(x, y, z): @@ -53,87 +50,168 @@ def lin(x, y, z): """ return (float(x)/float(y)-1.0)/(float(z)-1.0) -def genere_comptage(duree, groupe, associes): +def genere_comptage(duree): """ Grosse fonction de hack pour ne pas écrire six fois le même formatage de sortie bidon. Prend en argument : * duree, qui peut valoir 'instant', 'heuristique', ou 'journalier', permet d'importer les variables de config qui vont bien - * groupe, qui précise selon quoi on groupe (mac ou chambre) - * associes, qui contient l'autre champ """ + global date + global Logs pb_comptage_suspect = {} output = "" - requete = "SELECT array_to_string(array_agg(DISTINCT date), ', ') AS dates , %(groupe)s, array_to_string(array_agg(DISTINCT %(associes)s), ', ') AS %(associes)ss, COUNT(DISTINCT %(associes)s) AS nb_%(associes)ss_distinctes, COUNT(%(associes)s) AS nb_%(associes)ss, COUNT(DISTINCT date) as nb_dates_distinctes, COUNT(DISTINCT %(groupe)s) as nb_%(groupe)ss_distinctes FROM correspondance WHERE date >= timestamp 'now' - interval '%(delay)s' GROUP BY %(groupe)s;" % { 'groupe': groupe, 'associes': associes, 'delay': mac_prise.delay[duree] } + requete = "SELECT array_to_string(array_agg(DISTINCT date), ', ') AS dates , mac, array_to_string(array_agg(DISTINCT chambre), ', ') AS chambres, COUNT(DISTINCT chambre) AS nb_chambres_distinctes, COUNT(chambre) AS nb_chambres, COUNT(DISTINCT date) as nb_dates_distinctes, COUNT(DISTINCT mac) as nb_macs_distinctes FROM correspondance WHERE date >= timestamp 'now' - interval '%(delay)s' GROUP BY mac;" % {'delay': mac_prise.delay[duree]} cur.execute(requete) fetched = cur.fetchall() for entry in fetched: - - if groupe == "mac": - machines = ldap.search('(macAddress=%s)' % entry[groupe]) - if len(machines) > 0: - if isinstance(machines[0], lc_ldap.machineWifi): - continue - else: + machines = ldap.search('(macAddress=%s)' % entry['mac']) + if len(machines) > 0: + if isinstance(machines[0], lc_ldap.machineWifi): continue + else: + continue - if entry['nb_'+associes+'s_distinctes'] >= mac_prise.suspect[duree][groupe]: - Logs.append(u"Recherche par %s, entrée suspecte : %s -> %s : %s distinctes sur %s dates distinctes\n" % (groupe, entry[groupe], entry[associes+'s'], entry['nb_'+associes+'s'], entry['nb_dates_distinctes'])) - liste_associes = entry[associes+'s'].split(', ') + if entry['nb_chambres_distinctes'] >= mac_prise.suspect[duree]: + Logs.append(u"Recherche par %s, entrée suspecte : %s -> %s : %s distinctes sur %s dates distinctes\n" % ('mac', entry['mac'], entry['chambres'], entry['nb_chambres'], entry['nb_dates_distinctes'])) + liste_chambres = entry['chambres'].split(', ') # On calcule la "probabilité" qu'un truc ne soit pas clair concernant la chambre/mac - rapport = lin(entry['nb_'+associes+'s'], entry['nb_dates_distinctes'], float(entry['nb_'+associes+'s_distinctes'])) - if rapport >= mac_prise.rapport_suspect[duree][groupe]: - Logs.append(u"Entrée ajoutée au tableau %s pour la recherche par %s, car rapport supérieur au seuil.\n\n" % (duree, groupe)) - pb_comptage_suspect[entry[groupe]] = (liste_associes, rapport, mac_prise.rapport_suspect[duree][groupe]) + rapport = lin(entry['nb_chambres'], entry['nb_dates_distinctes'], float(entry['nb_chambres_distinctes'])) + if rapport >= mac_prise.rapport_suspect[duree]: + Logs.append(u"Entrée ajoutée au tableau %s, car rapport supérieur au seuil.\n\n" % (duree)) + pb_comptage_suspect[entry['mac']] = (liste_chambres, rapport, mac_prise.rapport_suspect[duree]) else: - Logs.append(u"Entrée rejetée du tableau %s pour la recherche par %s, car rapport inférieur au seuil : (%s).\n\n" % (duree, groupe, rapport)) + Logs.append(u"Entrée rejetée du tableau %s, car rapport inférieur au seuil : (%s).\n\n" % (duree, rapport)) else: pass if len(pb_comptage_suspect) > 0: - output += mac_prise.titre_suspect[duree][groupe] + "\n" - - # On prend la longueur de la plus longue valeur, on s'assure que cette longueur fait celle de la légende, plus un entier de marge - longueur_max = max([len(", ".join(a[0])) for a in pb_comptage_suspect.values()] + [longueur[associes][1]]) + 4 - largeurs = (longueur[groupe][0], longueur_max, 11, 9) - titre = (titres[groupe][0], titres[groupe][1], "rapport", "seuil") - alignement = (alignements[0], alignements[1], 'c', 'c') + for clef, valeur in pb_comptage_suspect.items(): + requete = "INSERT INTO spotted (mac, type, chambre, date, rapport, seuil) VALUES(%s, %s, %s, %s, %s, %s);" + cur.execute(requete, (clef, duree, ", ".join(valeur[0]), date, valeur[1], valeur[2])) + return None + +def summary(): + """ + Fonction résumant les entrées "spotted" des dernières 24h + """ + + output = u"" + Logs = u"" + + requete = "SELECT * FROM spotted WHERE date >= timestamp 'now' - interval '1 day' ORDER BY date ASC;" + cur.execute(requete) + fetched = cur.fetchall() + liste_triee = collections.defaultdict(dict) + + for entry in fetched: + chbres = entry['chambre'].split(', ') + chbres.sort() + chbres = tuple(chbres) + if liste_triee[entry['mac']].has_key(entry['type']): + if liste_triee[entry['mac']][entry['type']].has_key(chbres): + liste_triee[entry['mac']][entry['type']][chbres].append((entry['date'], entry['rapport'], entry['seuil'])) + else: + liste_triee[entry['mac']][entry['type']][chbres] = [] + else: + liste_triee[entry['mac']][entry['type']] = {} + + for mac, ltype in liste_triee.items(): + data = [] + output += u"Il y a eu une activité suspecte concernant la mac %s :\n\n" % mac + Logs += u"Activité pour %s :\n" % mac + for dtype, dataset in ltype.items(): + number = 0 + chambres = set() + for chbres, dataframe in dataset.items(): + chambres.update(chbres) + number += len(dataframe) + data += [[dtype, ", ".join(list(chbres)), donnee[0], donnee[1], donnee[2]] for donnee in dataframe] + output += u'Sur le relevé %s, la mac est apparue %s fois. Elle est apparue dans les chambres suivantes : %s.\n' % (dtype, number, ", ".join(list(chambres))) + output += u'Consulter les logs (en PJ) pour plus d\'informations.\n\n' + maxlen = max([len(a[1]) for a in data]) + 4 + titres = (u'relevé', u'chambres', u'date', u'rapport', u'seuil') + alignements = ('c', 'c', 'c', 'c', 'c') + largeurs = (12, maxlen, 20, 10, 10) + Logs += tableau(data, titres, largeurs, alignements) + Logs += u"\n\n" + + return output, Logs + +def reperage_mac_inconnue(): + """ + Fonction de repérage d'une mac qui ne devrait pas être + dans telle chambre, sur une plage de 24h, suivant un + paramètre de config pour le nombre d'occurrences. + """ + + output = u"" + probleme = {} + requete = "SELECT chambre, mac, COUNT(mac) as nb_min FROM correspondance WHERE date >= timestamp 'now' - interval '24 hours' GROUP BY chambre, mac ORDER BY chambre ASC;" + cur.execute(requete) + fetched = cur.fetchall() + liste_parsee = collections.defaultdict(dict) + + for entry in fetched: + liste_parsee[entry['chambre']][entry['mac']] = int(entry['nb_min']) + + for chambre in liste_parsee.keys(): + if chambre in chambres_ma + chambres_clubs: + continue + + for mac in liste_parsee[chambre].keys(): + try: + proprio_associe = ldap.search('macAddress=%s' % mac)[0].proprio() + if str(proprio_associe['chbre'][0]).lower() == chambre.lower(): + garbage = liste_parsee[chambre].pop(mac) + except: + pass + number = sum(liste_parsee[chambre].values()) + + if number >= mac_prise.max_inconnues_par_jour: + probleme[chambre] = (liste_parsee[chambre].keys(), number) + + if len(probleme) > 0: + output += mac_prise.titre_mac_inconnue+"\n" + + longueur_max = max([len(", ".join(a[0])) for a in probleme.values()] + [len("macs")]) + 2 + largeurs = (len('chambre') + 2, longueur_max, len('compteur') + 2, len('seuil') + 2) data = [] - clefs = pb_comptage_suspect.keys() + clefs = probleme.keys() clefs.sort() for clef in clefs: - data.append([clef, ", ".join(pb_comptage_suspect[clef][0]), pb_comptage_suspect[clef][1], pb_comptage_suspect[clef][2]]) - - output += tableau(data, titre, largeurs, alignement) + data.append([clef, ", ".join(probleme[clef][0]), probleme[clef][1], mac_prise.max_inconnues_par_jour]) + + output += tableau(data, ('chambre', 'macs', 'compteur', 'seuil'), largeurs, ('c', 'c', 'c', 'c')) output += u"\n\n\n" return output if __name__ == '__main__': - output = u"Détection de spoof potentiel\n\n\n" - coupure = len(output) + date = time.strftime('%F %T') + if len(sys.argv) >= 2: + output = u'' + Logs = u'' + if '--summary' in sys.argv or 'summary' in sys.argv: + # On envoie le résumé + output += u' *Résumé des apparitions de mac dans plusieurs chambres*\n\n' + texte, Logs = summary() + output += texte + output += u"\n\n" + if '--reperage' in sys.argv or 'reperage' in sys.argv: + # On envoie le repérage + output += u' *Repérage de spoof potentiel par comptage*\n\n' + output += reperage_mac_inconnue() - Logs = [u"Logs du script mac_prise_analyzer\n\n\n"] - - output += genere_comptage('instant', 'mac', 'chambre') - output += genere_comptage('heuristique', 'mac', 'chambre') - output += genere_comptage('journalier', 'mac', 'chambre') - - if time.localtime().tm_min % 30 == 0 and mac_prise.hargneux: - hargneux = True - else: - hargneux = False - - if len(output) == coupure and not hargneux: - sys.exit(0) - - message = """From: %(from)s + Logs = Logs.encode('UTF-8') + output = output.encode('UTF-8') + message = """From: %(from)s To: %(to)s -Subject: %(subject)s +Subject: Résumé quotidien : mac_prises. Content-Type: multipart/mixed; boundary="_424234545aaff-ffca234efff-556adceff5646_" --_424234545aaff-ffca234efff-556adceff5646_ @@ -141,9 +219,6 @@ Content-Type: text/plain; charset="UTF-8" %(contenu)s --- -Script d'analyse mac_prise (en test) - --_424234545aaff-ffca234efff-556adceff5646_ Content-Type: text/plain; charset="UTF-8" Content-Disposition: attachment; filename="logs_analyse" @@ -151,17 +226,46 @@ Content-Disposition: attachment; filename="logs_analyse" %(logs)s --_424234545aaff-ffca234efff-556adceff5646_-- - """ - - corps = message % { 'from': 'Spoofing watcher ', - 'to': 'test@lists.crans.org', - 'subject': 'Analyse du spoofing', - 'contenu': output, - 'logs': "".join(Logs), - } + + corps = message % { 'from': 'Spoofing watcher ', + 'to': 'test@lists.crans.org', + 'subject': 'Résumé journalier ', + 'contenu': output, + 'logs': Logs, + } - mail = smtplib.SMTP('localhost') - mailfrom = 'spoof-watcher@crans.org' - mailto = 'test@lists.crans.org' - mail.sendmail(mailfrom, mailto, corps.encode('utf-8')) + mail = smtplib.SMTP('localhost') + mailfrom = 'spoof-watcher@crans.org' + mailto = 'test@lists.crans.org' + mail.sendmail(mailfrom, mailto, corps) + else: + Logs = [u"Logs du script mac_prise_analyzer\n\n\n"] + genere_comptage('instantanne') + genere_comptage('moyen') + genere_comptage('journalier') + + if time.localtime().tm_min % 30 == 0 and mac_prise.hargneux: + hargneux = True + else: + hargneux = False + + if hargneux: + message = """From: %(from)s + To: %(to)s + Subject: %(subject)s + Content-Type: text/plain; charset="UTF-8" + + %(logs)s + """ + + corps = message % { 'from': 'Spoofing watcher ', + 'to': 'test@lists.crans.org', + 'subject': 'Logs de mac_prises_analyzer', + 'logs': "".join(Logs), + } + + mail = smtplib.SMTP('localhost') + mailfrom = 'spoof-watcher@crans.org' + mailto = 'test@lists.crans.org' + mail.sendmail(mailfrom, mailto, corps.encode('utf-8')) diff --git a/surveillance/mac_prises/mac_prise_cleaner.sh b/surveillance/mac_prises/mac_prise_cleaner.sh deleted file mode 100755 index 4ee58175..00000000 --- a/surveillance/mac_prises/mac_prise_cleaner.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/sh - -psql -U crans mac_prises -c "DELETE FROM correspondance WHERE date <= timestamp 'now' - interval '2 days';" 1>/dev/null diff --git a/surveillance/mac_prises/mac_prise_daily.sh b/surveillance/mac_prises/mac_prise_daily.sh new file mode 100755 index 00000000..3d5c2888 --- /dev/null +++ b/surveillance/mac_prises/mac_prise_daily.sh @@ -0,0 +1,6 @@ +#!/bin/sh + +SUMMARY='/usr/scripts/surveillance/mac_prises/mac_prises_analyzer.py --summary --reperage' + +psql -U crans mac_prises -c "DELETE FROM correspondance WHERE date <= timestamp 'now' - interval '2 days';" 1>/dev/null +psql -U crans mac_prises -c "DELETE FROM spotted WHERE date <= timestamp 'now' - interval '2 days';" 1>/dev/null diff --git a/surveillance/mac_prises/mac_prise_reperage.py b/surveillance/mac_prises/mac_prise_reperage.py deleted file mode 100755 index 7b6cbd95..00000000 --- a/surveillance/mac_prises/mac_prise_reperage.py +++ /dev/null @@ -1,119 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf8 -*- - -import psycopg2 -import psycopg2.extras -import sys -import smtplib - -sys.path.append('/usr/scripts/gestion') -from config import mac_prise -from affich_tools import tableau -sys.path.append('/usr/scripts/lc_ldap') -import lc_ldap -import collections - -ldap = lc_ldap.lc_ldap_local() - -membres_actifs = ldap.search('(|(droits=Cableur)(droits=Nounou)(droits=Apprenti)(droits=Bureau))') -chambres_ma = [] -for membre_actif in membres_actifs: - try: - chambres_ma.append(str(membre_actif['chbre'][0]).lower()) - except: - pass - -clubs = ldap.search('cid=*') -chambres_clubs = [] -for club in clubs: - try: - chambres_clubs.append(str(club['chbre'][0]).lower()) - except: - pass - -conn = psycopg2.connect(user='crans', database='mac_prises') -cur = conn.cursor(cursor_factory = psycopg2.extras.DictCursor) - -def reperage_mac_inconnue(): - """ - Fonction de repérage d'une mac qui ne devrait pas être - dans telle chambre, sur une plage de 24h, suivant un - paramètre de config pour le nombre d'occurrences. - - Sans doute le truc le plus important, sera en tête du mail - """ - - output = u"" - probleme = {} - requete = "SELECT chambre, mac, COUNT(mac) as nb_min FROM correspondance WHERE date >= timestamp 'now' - interval '24 hours' GROUP BY chambre, mac ORDER BY chambre ASC;" - cur.execute(requete) - fetched = cur.fetchall() - liste_parsee = collections.defaultdict(dict) - - for entry in fetched: - liste_parsee[entry['chambre']][entry['mac']] = int(entry['nb_min']) - - for chambre in liste_parsee.keys(): - if chambre in chambres_ma + chambres_clubs: - continue - - for mac in liste_parsee[chambre].keys(): - try: - proprio_associe = ldap.search('macAddress=%s' % mac)[0].proprio() - if str(proprio_associe['chbre'][0]).lower() == chambre.lower(): - garbage = liste_parsee[chambre].pop(mac) - except: - pass - number = sum(liste_parsee[chambre].values()) - - if number >= mac_prise.max_inconnues_par_jour: - probleme[chambre] = (liste_parsee[chambre].keys(), number) - - if len(probleme) > 0: - output += mac_prise.titre_mac_inconnue+"\n" - - longueur_max = max([len(", ".join(a[0])) for a in probleme.values()] + [len("macs")]) + 2 - largeurs = (len('chambre') + 2, longueur_max, len('compteur') + 2, len('seuil') + 2) - - data = [] - clefs = probleme.keys() - clefs.sort() - for clef in clefs: - data.append([clef, ", ".join(probleme[clef][0]), probleme[clef][1], mac_prise.max_inconnues_par_jour]) - - output += tableau(data, ('chambre', 'macs', 'compteur', 'seuil'), largeurs, ('c', 'c', 'c', 'c')) - output += u"\n\n\n" - - return output - -if __name__ == '__main__': - output = u'Repérage de spoof potentiel par comptage' - coupure = len(output) - - output += reperage_mac_inconnue() - - if len(output) == coupure and not mac_prise.hargneux: - sys.exit(0) - - message = """From: %(from)s -To: %(to)s -Subject: %(subject)s -Content-Type: text/plain; charset="UTF-8" - -%(contenu)s - --- -Script d'analyse mac_prise (en test) - -""" - - corps = message % { 'from': 'Spoofing watcher ', - 'to': 'test@lists.crans.org', - 'subject': 'Analyse horaire du spoofing', - 'contenu': output, - } - - mail = smtplib.SMTP('localhost') - mailfrom = 'spoof-watcher@crans.org' - mailto = 'test@lists.crans.org' - mail.sendmail(mailfrom, mailto, corps.encode('utf-8'))