Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Maud Kerebel
scripts
Commits
77e0b1da
Commit
77e0b1da
authored
Jul 22, 2014
by
Daniel STAN
Browse files
freeradius/auth.py: préparation à l'auth filaire
parent
5446bb81
Changes
4
Hide whitespace changes
Inline
Side-by-side
freeradius/auth.py
View file @
77e0b1da
#!/bin/bash /usr/scripts/python.sh
# ⁻*- coding: utf-8 -*-
#
# Draft de fichier d'authentification
#
# Ce fichier contient la définition de plusieurs fonctions d'interface à freeradius
# qui peuvent être appelées (suivant les configurations) à certains moment de
# l'éxécution.
#
import
logging
import
traceback
import
netaddr
import
radiusd
# Module magique freeradius (radiusd.py is dummy)
import
lc_ldap.shortcuts
from
lc_ldap.crans_utils
import
escape
as
escape_ldap
import
lc_ldap.crans_utils
from
gestion.config.config
import
vlans
import
lc_ldap.objets
import
radiusd
import
netaddr
import
traceback
from
gestion.config.config
import
vlans
from
gestion.gen_confs.trigger
import
trigger_generate_cochon
as
trigger_generate
import
annuaires_pg
...
...
@@ -27,13 +28,34 @@ test_v6 = [
USERNAME_SUFFIX
=
'.wifi.crans.org'
## -*- Logging -*-
# Initialisation d'un logger pour faire des stats etc
# pour l'instant, on centralise tout sur thot en mode debug
logger
=
logging
.
getLogger
(
'auth.py'
)
logger
.
setLevel
(
logging
.
DEBUG
)
formatter
=
logging
.
Formatter
(
'%(name)s: [%(levelname)s] %(message)s'
)
handler
=
logging
.
handlers
.
SysLogHandler
(
address
=
'/dev/log'
)
try
:
handler
.
addFormatter
(
formatter
)
except
AttributeError
:
handler
.
formatter
=
formatter
logger
.
addHandler
(
handler
)
## -*- Types de blacklists -*-
#: reject tout de suite
bl_reject
=
[
u
'bloq'
]
#: place sur le vlan isolement
bl_isolement
=
[
u
'virus'
,
u
'autodisc_virus'
,
u
'autodisc_p2p'
,
u
'ipv6_ra'
]
# TODO carte_etudiant: dépend si sursis ou non (regarder lc_ldap)
# TODO LOGSSSSS
#: place sur accueil
bl_accueil
=
[
u
'carte_etudiant'
,
u
'chambre_invalide'
,
u
'paiement'
]
# Decorateur utilisé plus tard (same connection)
## -*- Decorateurs -*-
# À appliquer sur les fonctions qui ont besoin d'une conn ldap
use_ldap_admin
=
lc_ldap
.
shortcuts
.
with_ldap_conn
(
retries
=
2
,
delay
=
5
,
constructor
=
lc_ldap
.
shortcuts
.
lc_ldap_admin
)
use_ldap
=
lc_ldap
.
shortcuts
.
with_ldap_conn
(
retries
=
2
,
delay
=
5
,
...
...
@@ -145,13 +167,6 @@ def get_prise_chbre(data):
chbre
=
None
return
prise
,
chbre
def
get_ap
(
data
):
"""Extrait la prise (wifi)"""
## WiFi: NAS-Identifier => vide
## Nas-Port => numéro sur l'interface
## Nas-IP-Address => adresse IP de la borne
pass
@
use_ldap_admin
def
register_mac
(
data
,
machine
,
conn
):
"""Enregistre la mac actuelle sur une machine donnée."""
...
...
@@ -186,8 +201,7 @@ def instantiate(p, *conns):
pass
@
radius_event
@
use_ldap
def
wifi_authorize
(
data
,
conn
):
def
authorize_wifi
(
data
):
"""Section authorize pour le wifi
(NB: le filaire est en accept pour tout le monde)
Éxécuté avant l'authentification proprement dite. On peut ainsi remplir les
...
...
@@ -233,38 +247,93 @@ def wifi_authorize(data, conn):
)
@
radius_event
@
use_ldap
def
post_auth
(
data
,
conn
):
def
authorize_fil
(
data
):
"""For now, do nothing.
TODO: check bl_reject.
TODO: check chap auth
"""
return
radiusd
.
RLM_MODULE_OK
@
radius_event
def
post_auth_wifi
(
data
):
"""Appelé une fois que l'authentification est ok.
On peut rajouter quelques éléments dans la réponse radius ici.
Comme par exemple le vlan sur lequel placer le client"""
is_wifi
=
False
vlan_name
=
None
reason
=
''
identity
=
""
#TODO
prise
=
""
chbre
=
None
items
=
get_machines
(
data
)
decision
=
'adherent'
,
''
port
,
vlan_name
,
reason
=
decide_vlan
(
data
,
True
)
mac
=
data
.
get
(
'Calling-Station-Id'
,
None
)
log_message
=
'(wifi) %s -> %s [%s%s]'
%
\
(
port
,
mac
,
vlan_name
,
(
reason
and
u
': '
+
reason
).
encode
(
u
'utf-8'
))
logger
.
info
(
log_message
)
radiusd
.
radlog
(
radiusd
.
L_AUTH
,
log_message
)
# Si NAS ayant des mapping particuliers, à signaler ici
vlan_id
=
vlans
[
vlan_name
]
# WiFi : Pour l'instant, on ne met pas d'infos de vlans dans la réponse
# les bornes wifi ont du mal avec cela
return
radiusd
.
RLM_MODULE_OK
@
radius_event
def
post_auth_fil
(
data
):
"""Idem, mais en filaire.
Pas testé."""
port
,
vlan_name
,
reason
=
decide_vlan
(
data
,
True
)
mac
=
data
.
get
(
'Calling-Station-Id'
,
None
)
log_message
=
'(fil) %s -> %s [%s%s]'
%
\
(
port
,
mac
,
vlan_name
,
(
reason
and
u
': '
+
reason
).
encode
(
u
'utf-8'
))
logger
.
info
(
log_message
)
radiusd
.
radlog
(
radiusd
.
L_AUTH
,
log_message
)
# Si NAS ayant des mapping particuliers, à signaler ici
vlan_id
=
vlans
[
vlan_name
]
# Filaire
return
(
radiusd
.
RLM_MODULE_UPDATED
,
(
(
"Tunnel-Type"
,
"VLAN"
),
(
"Tunnel-Medium-Type"
,
"IEEE-802"
),
(
"Tunnel-Private-Group-Id"
,
'%d'
%
vlan
),
),
()
)
@
use_ldap
def
decide_vlan
(
data
,
is_wifi
,
conn
):
"""Décide du vlan non-taggué à assigner, et donne une raison
à ce choix.
Retourne un (port, vlan_name, reason)
où port = est une prise réseau / chambre (si filaire)
"wifi" si wifi
"""
if
is_wifi
:
decision
=
'wifi'
,
''
port
=
data
.
get
(
'Called-Station-Id'
,
'?'
)
else
:
decision
=
'adherent'
,
''
prise
,
chbre
=
get_prise_chbre
(
data
)
port
=
"%s/%s"
%
(
prise
,
chbre
)
items
=
get_machines
(
data
)
if
not
items
:
decision
=
'accueil'
,
'Machine inconnue'
return
radiusd
.
RLM_MODULE_NOTFOUND
# TODO faire un truc plus propre
return
(
port
,
'accueil'
,
'Machine inconnue'
)
machine
=
items
[
0
]
proprio
=
machine
.
proprio
()
if
isinstance
(
machine
,
lc_ldap
.
objets
.
machineWifi
):
decision
=
'wifi'
,
''
is_wifi
=
True
if
not
machine
[
'ipHostNumber'
]
or
unicode
(
machine
[
'macAddress'
][
0
])
in
test_v6
:
if
not
machine
[
'ipHostNumber'
]:
decision
=
'v6only'
,
'No IPv4'
elif
unicode
(
machine
[
'macAddress'
][
0
])
in
test_v6
:
decision
=
'v6only'
,
'Test machine v6'
elif
machine
[
'ipHostNumber'
][
0
].
value
in
netaddr
.
IPNetwork
(
'10.2.9.0/24'
):
# Cas des personnels logés dans les appartements de l'ENS
decision
=
'appts'
,
'Personnel ENS'
# Application des blacklists
for
bl
in
machine
.
blacklist_actif
():
if
bl
.
value
[
'type'
]
in
bl_isolement
:
decision
=
'isolement'
,
unicode
(
bl
)
...
...
@@ -275,43 +344,28 @@ def post_auth(data, conn):
if
not
is_wifi
:
# Si l'adhérent n'est pas membre actif, il doit se brancher depuis la
# prise d'un autre adhérent à jour de cotisation
prise
,
chbre
=
get_prise_chbre
(
data
)
if
proprio
[
'droits'
]:
decision
=
decision
[
0
],
decision
[
1
]
+
' (force MA)'
elif
chbre
is
None
:
force_ma
=
False
if
chbre
is
None
and
not
proprio
[
'droits'
]:
decision
=
"accueil"
,
"Chambre inconnue"
el
s
e
:
el
if
chbre
is
not
Non
e
:
chbre
=
escape_ldap
(
chbre
)
hebergeurs
=
conn
.
search
(
u
'(&(chambre=%s)(cid=*)(aid=*))'
%
chbre
)
for
hebergeur
in
hebergeurs
:
if
not
hebergeur
.
blacklist_actif
():
break
else
:
decision
=
"accueil"
,
"Hébergeur blacklisté"
# Unpack and log
if
chbre
is
not
None
:
prise
+=
'/'
+
chbre
vlan_name
,
reason
=
decision
vlan
=
vlans
[
vlan_name
]
radiusd
.
radlog
(
radiusd
.
L_INFO
,
'auth.py: %s -> %s [%s%s]'
%
(
prise
,
identity
,
vlan_name
,
(
reason
and
u
': '
+
reason
).
encode
(
u
'utf-8'
))
)
# WiFi : Pour l'instant, on ne met pas d'infos de vlans dans la réponse
# les bornes wifi ont du mal avec cela
if
is_wifi
:
return
radiusd
.
RLM_MODULE_OK
# Si tous les hebergeurs sont blacklistés, autorisé
# uniquement si MA
if
not
proprio
[
'droits'
]:
decision
=
"accueil"
,
"Hébergeur blacklisté"
else
:
force_ma
=
True
else
:
force_ma
=
True
if
force_ma
:
decision
=
decision
[
0
],
decision
[
1
]
+
' (force MA)'
return
(
radiusd
.
RLM_MODULE_UPDATED
,
(
(
"Tunnel-Type"
,
"VLAN"
),
(
"Tunnel-Medium-Type"
,
"IEEE-802"
),
(
"Tunnel-Private-Group-Id"
,
'%d'
%
vlan
),
),
()
)
return
(
port
,)
+
decision
@
radius_event
def
dummy_fun
(
p
):
...
...
freeradius/rlm_python_fil.conf
0 → 100644
View file @
77e0b1da
# Configuration for the Python module.
#
#
python
crans_fil
{
mod_instantiate
=
freeradius
.
auth
func_instantiate
=
instantiate
# Spécifique au WiFi : rempli le mdp
mod_authorize
=
freeradius
.
auth
func_authorize
=
authorize_fil
# Renseigne le vlan
# remplacer par dummy_fun pour ignorer le tagging de vlan
mod_post_auth
=
freeradius
.
auth
func_post_auth
=
post_auth_fil
# Que faire avant de quitter
mod_detach
=
freeradius
.
auth
func_detach
=
detach
# Le reste est dumb et inutile
mod_accounting
=
freeradius
.
auth
func_accounting
=
dummy_fun
mod_pre_proxy
=
freeradius
.
auth
func_pre_proxy
=
dummy_fun
mod_post_proxy
=
freeradius
.
auth
func_post_proxy
=
dummy_fun
mod_recv_coa
=
freeradius
.
auth
func_recv_coa
=
dummy_fun
mod_send_coa
=
freeradius
.
auth
func_send_coa
=
dummy_fun
}
freeradius/rlm_python_wifi.conf
View file @
77e0b1da
...
...
@@ -8,12 +8,12 @@ python crans_wifi {
# Spécifique au WiFi : rempli le mdp
mod_authorize
=
freeradius
.
auth
func_authorize
=
wifi_
authorize
func_authorize
=
authorize
_wifi
# Renseigne le vlan
# remplacer par dummy_fun pour ignorer le tagging de vlan
mod_post_auth
=
freeradius
.
auth
func_post_auth
=
post_auth
func_post_auth
=
post_auth
_wifi
# Que faire avant de quitter
mod_detach
=
freeradius
.
auth
...
...
freeradius/test.py
View file @
77e0b1da
...
...
@@ -17,14 +17,14 @@ delattr(sys, 'argv')
auth
.
instantiate
(())
p
=
(
(
'Calling-Station-Id'
,
'b
a:27:eb:3c:54:d5
'
),
(
'User-Name'
,
'
test18
'
),
(
'Calling-Station-Id'
,
'b
0:79:94:cf:d1:9a
'
),
(
'User-Name'
,
'
moo-torola
'
),
)
print
repr
(
auth
.
wifi_
authorize
(
p
))
print
repr
(
auth
.
authorize
_wifi
(
p
))
print
"wait for 3s, tu peux aller crasher le serveur pg ou ldap"
sys
.
stdout
.
flush
()
time
.
sleep
(
3
)
print
repr
(
auth
.
post_auth
(
p
))
print
repr
(
auth
.
post_auth
_wifi
(
p
))
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment