freeradius: auth.py valide challenge chap
This commit is contained in:
parent
746e5db7b8
commit
1d3b136bed
1 changed files with 38 additions and 24 deletions
|
@ -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
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue