8
0
Fork 0
mirror of https://gitlab2.federez.net/re2o/re2o synced 2024-11-27 15:12:25 +00:00

Corrige auth.py pour la partie authorize filaire et user

This commit is contained in:
Gabriel Detraz 2016-12-11 01:28:34 +01:00 committed by root
parent 8b0114391a
commit e266a85462
3 changed files with 104 additions and 105 deletions

View file

@ -95,56 +95,37 @@ def authorize(data):
"""Fonction qui aiguille entre nas, wifi et filaire pour authorize """Fonction qui aiguille entre nas, wifi et filaire pour authorize
On se contecte de faire une verification basique de ce que contien la requète On se contecte de faire une verification basique de ce que contien la requète
pour déterminer la fonction à utiliser""" pour déterminer la fonction à utiliser"""
if data.get('NAS-Port-Type', '')==u'Ethernet': if data.get('Service-Type', '')==u'NAS-Prompt-User' or data.get('Service-Type', '')==u'Administrative-User':
return authorize_user(data)
else:
return authorize_fil(data) return authorize_fil(data)
elif u"Wireless" in data.get('NAS-Port-Type', ''):
return authorize_wifi(data)
@radius_event @radius_event
def authorize_wifi(data): def authorize_user(data):
"""Section authorize pour le wifi nas = data.get('NAS-IP-Address', None)
(NB: le filaire est en accept pour tout le monde) nas_id = data.get('NAS-Identifier', None)
Éxécuté avant l'authentification proprement dite. On peut ainsi remplir les user = data.get('User-Name', None)
champs login et mot de passe qui serviront ensuite à l'authentification password = data.get('User-Password', None)
(MschapV2/PEAP ou MschapV2/TTLS)""" out = subprocess.check_output(['/usr/bin/python3', '/var/www/re2o/freeradius_utils/authenticate_user.py', user, password])
if out[:-1] == u"TRUE":
items = get_machines(data) if data.get('Service-Type', '')==u'NAS-Prompt-User':
logger.info(u"Access of user %s on %s (%s)" % (user, nas, nas_id))
if not items: elif data.get('Service-Type', '')==u'Administrative-User':
logger.error('Nothing found') logger.info(u"Enable manager for %s on %s (%s)" % (user, nas, nas_id))
return radiusd.RLM_MODULE_NOTFOUND
if len(items) > 1:
logger.warn('lc_ldap: Too many results (taking first)')
machine = items[0]
proprio = machine.proprio()
if isinstance(proprio, lc_ldap.objets.AssociationCrans):
logger.error('Crans machine trying to authenticate !')
return radiusd.RLM_MODULE_INVALID
for bl in machine.blacklist_actif():
if bl.value['type'] in BL_REJECT:
return radiusd.RLM_MODULE_REJECT
# Kludge : vlan isolement pas possible, donc reject quand-même
if not WIFI_DYN_VLAN and bl.value['type'] in BL_ISOLEMENT:
return radiusd.RLM_MODULE_REJECT
if not machine.get('ipsec', False):
logger.error('WiFi auth but machine has no password')
return radiusd.RLM_MODULE_REJECT
password = machine['ipsec'][0].value.encode('ascii', 'ignore')
# TODO: feed cert here
return (radiusd.RLM_MODULE_UPDATED, return (radiusd.RLM_MODULE_UPDATED,
(), (),
( (
("Cleartext-Password", password), ("Auth-Type", "Accept"),
), ),
) )
else:
return (radiusd.RLM_MODULE_UPDATED,
(),
(
("Auth-Type", "Reject"),
),
)
@radius_event @radius_event
def authorize_fil(data): def authorize_fil(data):
@ -152,34 +133,6 @@ def authorize_fil(data):
Check le challenge chap, et accepte. Check le challenge chap, et accepte.
""" """
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 Exception as err:
logger.info("(fil) Chap challenge check failed with %r" % err)
if not chap_ok:
if TEST_SERVER:
logger.debug('(fil) Continue auth (debug)')
else:
return radiusd.RLM_MODULE_REJECT
return (radiusd.RLM_MODULE_UPDATED, return (radiusd.RLM_MODULE_UPDATED,
(), (),
( (
@ -230,14 +183,16 @@ def post_auth_fil(data):
"""Idem, mais en filaire. """Idem, mais en filaire.
""" """
nas = data.get('NAS-Identifier', None) nas = data.get('NAS-IP-Address', None)
port = data.get('NAS-Port', None) port = data.get('NAS-Port', None)
mac = data.get('Calling-Station-Id', None) mac = data.get('Calling-Station-Id', None)
# Hack, à cause d'une numérotation cisco baroque
port = port[-2:]
out = subprocess.check_output(['/usr/bin/python3', '/var/www/re2o/freeradius_utils/authenticate_filaire.py', nas, port, mac]) out = subprocess.check_output(['/usr/bin/python3', '/var/www/re2o/freeradius_utils/authenticate_filaire.py', nas, port, mac])
reason, vlan_id = make_tuple(out) sw_name, reason, vlan_id = make_tuple(out)
log_message = '(fil) %s -> %s [%s%s]' % \ log_message = '(fil) %s -> %s [%s%s]' % \
(nas + u":" + port, mac, vlan_id, (reason and u': ' + reason).encode('utf-8')) (sw_name + u":" + port, mac, vlan_id, (reason and u': ' + reason).encode('utf-8'))
logger.info(log_message) logger.info(log_message)
# Filaire # Filaire

View file

@ -14,7 +14,7 @@ application = get_wsgi_application()
import argparse import argparse
from machines.models import Interface from machines.models import Interface, IpList
from topologie.models import Room, Port, Switch from topologie.models import Room, Port, Switch
from users.models import User from users.models import User
@ -23,53 +23,60 @@ from re2o.settings import RADIUS_VLAN_DECISION
VLAN_NOK = RADIUS_VLAN_DECISION['VLAN_NOK'] VLAN_NOK = RADIUS_VLAN_DECISION['VLAN_NOK']
VLAN_OK = RADIUS_VLAN_DECISION['VLAN_OK'] VLAN_OK = RADIUS_VLAN_DECISION['VLAN_OK']
def decide_vlan(switch_name, port_number, mac_address): def decide_vlan(switch_ip, port_number, mac_address):
# Get port from switch and port number # Get port from switch and port number
switch = Switch.objects.filter(switch_interface=Interface.objects.filter(dns=switch_name)) switch = Switch.objects.filter(switch_interface=Interface.objects.filter(ipv4=IpList.objects.filter(ipv4=switch_ip)))
if switch: if switch:
sw_name = str(switch[0].switch_interface)
port = Port.objects.filter(switch=switch[0], port=port_number) port = Port.objects.filter(switch=switch[0], port=port_number)
if port: if port:
port = port[0] port = port[0]
if port.radius == 'NO': if port.radius == 'NO':
# Aucune authentification sur ce port # Aucune authentification sur ce port
decision = ("Pas d'authentification sur ce port", VLAN_OK) decision = (sw_name, "Pas d'authentification sur ce port", VLAN_OK)
elif port.radius == 'BLOQ': elif port.radius == 'BLOQ':
# Prise désactivée # Prise désactivée
decision = ('Port desactive', VLAN_NOK) decision = (sw_name, 'Port desactive', VLAN_NOK)
elif port.radius == 'COMMON' or port.radius == 'STRICT': elif port.radius == 'COMMON':
# Authentification par mac # Authentification par mac
interface = Interface.objects.filter(mac_address=mac_address) interface = Interface.objects.filter(mac_address=mac_address)
if not interface: if not interface:
decision = ('Mac not found', VLAN_NOK) decision = (sw_name, 'Mac not found', VLAN_NOK)
elif interface[0].is_active(): elif not interface[0].is_active():
# Verification de la prise decision = (sw_name, 'Machine non active / adherent non cotisant', VLAN_NOK)
if port.radius == 'STRICT': else:
decision = (sw_name, 'Machine OK', VLAN_OK)
elif port.radius == 'STRICT':
if port.room: if port.room:
user = User.objects.filter(room=Room.objects.filter(name=port.room)) user = User.objects.filter(room=Room.objects.filter(name=port.room))
if not user: if not user:
decision = ('Chambre non cotisante', VLAN_NOK) decision = (sw_name, 'Chambre non cotisante', VLAN_NOK)
elif user[0].has_access(): elif not user[0].has_access():
decision = ('Machine OK, Proprio OK', VLAN_OK) decision = (sw_name, 'Resident desactive', VLAN_NOK)
else: else:
decision = ('Chambre inconnue', VLAN_NOK) # Verification de la mac
interface = Interface.objects.filter(mac_address=mac_address)
if not interface:
decision = (sw_name, 'Chambre Ok, but mac not found', VLAN_NOK)
elif not interface[0].is_active():
decision = (sw_name, 'Chambre Ok, but machine non active / adherent non cotisant', VLAN_NOK)
else: else:
# Mode COMMON decision = (sw_name, 'Machine OK, Proprio OK', VLAN_OK)
decision = ('Machine OK', VLAN_OK)
else: else:
decision = ('Machine non active / adherent non cotisant', VLAN_NOK) decision = (sw_name, 'Chambre inconnue', VLAN_NOK)
else: else:
decision = ('VLAN forced', int(port.radius)) decision = (sw_name, 'VLAN forced', int(port.radius))
else: else:
decision = ('port not found!', VLAN_OK) decision = (sw_name, 'port not found!', VLAN_OK)
else: else:
decision = ('switch not found!', VLAN_OK) decision = ('?', 'switch not found!', VLAN_OK)
return decision return decision
if __name__ == '__main__': if __name__ == '__main__':
parser = argparse.ArgumentParser(description='Decide radius vlan attribution') parser = argparse.ArgumentParser(description='Decide radius vlan attribution')
parser.add_argument('switch_name', action="store") parser.add_argument('switch_ip', action="store")
parser.add_argument('port_number', action="store", type=int) parser.add_argument('port_number', action="store", type=int)
parser.add_argument('mac_address', action="store") parser.add_argument('mac_address', action="store")
args = parser.parse_args() args = parser.parse_args()
print(decide_vlan(args.switch_name, args.port_number, args.mac_address)) print(decide_vlan(args.switch_ip, args.port_number, args.mac_address))

View file

@ -0,0 +1,37 @@
import os, sys
proj_path = "/var/www/re2o/"
# This is so Django knows where to find stuff.
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "re2o.settings")
sys.path.append(proj_path)
# This is so my local_settings.py gets loaded.
os.chdir(proj_path)
# This is so models get loaded.
from django.core.wsgi import get_wsgi_application
application = get_wsgi_application()
import argparse
from django.contrib.auth import authenticate
from users.models import User
def authorize_user(user, password):
user = authenticate(username=user, password=password)
if user:
if User.objects.get(pseudo=user):
return "TRUE"
else:
return "FALSE"
else:
return "FALSE"
if __name__ == '__main__':
parser = argparse.ArgumentParser(description='Authorize user')
parser.add_argument('user', action="store")
parser.add_argument('password', action="store")
args = parser.parse_args()
print(authorize_user(args.user, args.password))