freeradius: auth.py valide challenge chap

This commit is contained in:
Daniel STAN 2015-04-03 23:57:35 +02:00
parent 746e5db7b8
commit 1d3b136bed

View file

@ -10,6 +10,8 @@ import netaddr
import radiusd # Module magique freeradius (radiusd.py is dummy) import radiusd # Module magique freeradius (radiusd.py is dummy)
import ldap import ldap
import os import os
import binascii
import hashlib
import lc_ldap.shortcuts import lc_ldap.shortcuts
from lc_ldap.crans_utils import escape as escape_ldap from lc_ldap.crans_utils import escape as escape_ldap
@ -80,7 +82,7 @@ use_ldap_admin = lc_ldap.shortcuts.with_ldap_conn(retries=2, delay=5,
use_ldap = lc_ldap.shortcuts.with_ldap_conn(retries=2, delay=5, use_ldap = lc_ldap.shortcuts.with_ldap_conn(retries=2, delay=5,
constructor=lc_ldap.shortcuts.lc_ldap_anonymous) constructor=lc_ldap.shortcuts.lc_ldap_anonymous)
def radius_event(f): def radius_event(fun):
"""Décorateur pour les fonctions d'interfaces avec radius. """Décorateur pour les fonctions d'interfaces avec radius.
Une telle fonction prend un uniquement argument, qui est une liste de tuples Une telle fonction prend un uniquement argument, qui est une liste de tuples
(clé, valeur) et renvoie un triplet dont les composantes sont : (clé, valeur) et renvoie un triplet dont les composantes sont :
@ -102,7 +104,7 @@ def radius_event(f):
# Ex: Calling-Station-Id: "une_adresse_mac" # Ex: Calling-Station-Id: "une_adresse_mac"
data[key] = value.replace('"', '') data[key] = value.replace('"', '')
try: try:
return f(data) return fun(data)
except Exception as e: except Exception as e:
logger.error(repr(e) + ' on data ' + repr(auth_data)) logger.error(repr(e) + ' on data ' + repr(auth_data))
raise raise
@ -256,7 +258,7 @@ def register_machine(data, machine, conn):
@radius_event @radius_event
@use_ldap_admin @use_ldap_admin
@use_ldap @use_ldap
def instantiate(p, *conns): def instantiate(_, *conns):
"""Utile pour initialiser les connexions ldap une première fois (otherwise, """Utile pour initialiser les connexions ldap une première fois (otherwise,
do nothing)""" do nothing)"""
logger.info('Instantiation') logger.info('Instantiation')
@ -311,10 +313,39 @@ def authorize_wifi(data):
@radius_event @radius_event
def authorize_fil(data): def authorize_fil(data):
"""For now, do nothing.
TODO: check BL_REJECT.
TODO: check chap auth
""" """
Check le challenge chap, et accepte.
TODO: check BL_REJECT.
"""
chap_ok = False
# Teste l'authentification chap fournie
# password et challenge doivent être données
# en hexa (avec ou sans le 0x devant)
# le User-Name est en réalité la mac ( xx:xx:xx:xx:xx )
password = data.get('CHAP-Password', '')
challenge = data.get('CHAP-Challenge', '')
mac = data.get('User-Name', '')
logger.debug('(fil) authorize(%r)' % ((password, challenge, mac),))
try:
challenge = binascii.a2b_hex(challenge.replace('0x',''))
password = binascii.a2b_hex(password.replace('0x',''))
if hashlib.md5(password[0] + mac + challenge).digest() == password[1:]:
logger.info("(fil) Chap ok")
chap_ok = True
else:
logger.info("(fil) Chap wrong")
except:
logger.info("(fil) Chap challenge check failed")
if not chap_ok:
if DEBUG:
logger.debug('(fil) Continue auth (debug)')
else:
return radiusd.RLM_MODULE_REJECT
return (radiusd.RLM_MODULE_UPDATED, return (radiusd.RLM_MODULE_UPDATED,
(), (),
( (
@ -546,25 +577,8 @@ def decide_vlan(data, is_wifi, conn):
def dummy_fun(p): def dummy_fun(p):
return radiusd.RLM_MODULE_OK return radiusd.RLM_MODULE_OK
def detach(p=None): def detach(_=None):
"""Appelé lors du déchargement du module (enfin, normalement)""" """Appelé lors du déchargement du module (enfin, normalement)"""
print "*** goodbye from auth.py ***" print "*** goodbye from auth.py ***"
return radiusd.RLM_MODULE_OK return radiusd.RLM_MODULE_OK
# à réimplémenter dans le authorize
# chap_ok(os.getenv('CHAP_PASSWORD'), os.getenv('CHAP_CHALLENGE'), mac)
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