Révocations

Comment gérer les impondérables ?

Dans notre solution globale, nous gérons le réseau filaire par une authentification de type « login/password » où l'adresse MAC joue le rôle des deux composants. Nous disposons d'une base de données MySQL (ou Postgresql) qui recense toutes les adresses MAC connues. Nous avons pu tester son bon fonctionnement en utilisant un « login/password » introduit dans la base de données.

En ce qui concerne le réseau Wi-Fi, nous avons confié à EAP l'authentification, via le protocole TLS. Nous avons vu que, dans ce cas, tout se passe par l'intermédiaire des certificats, et qu'il n'y a aucune information dans la base de données.

Comment faire alors si pour une raison ou une autre, nous devions être amenés à bloquer un utilisateur disposant d'un certificat en cours de validité ? Il peut y avoir plusieurs raisons qui pourraient amener à cette résolution, comme :

  • un vol déclaré de la machine sur laquelle le certificat a été installé,
  • un utilisateur autorisé pour une certaine durée, mais qui pour une raison ou une autre, n'a plus rien à faire sur notre réseau, temporairement ou définitivement (non respect de la charte des utilisateurs, démission, etc.).

Dans notre configuration actuelle, ce type de situation ne peut être géré, il nous faut trouver une solution, si possible pas trop complexe à maintenir.

Deux voies sont à explorer :

  • l'utilisation de certificats de révocation,
  • trouver un moyen pour qu'en plus de l'authentification par certificats, le nom d'utilisateur doive être présent dans la base de données pour autoriser l'attachement.

Certificat de révocation

TinyCA sait générer simplement des certificats de révocation, et FreeRADIUS peut être configuré assez simplement pour en tenir compte. Cette solution offre cependant deux gros défauts pour la maintenance :

  • à chaque nouvelle suspension de compte, il faut révoquer le certificat correspondant au compte suspendu, recréer un nouveau certificat de révocations , l'exporter, l'installer sur le serveur puis redémarrer le serveur,
  • en cas de suspension provisoire, un certificat révoqué doit être recréé puis réinstallé sur la machine cliente à la fin de la suspension du compte.

Cette solution n'est clairement pas facile à gérer.

Usage de la base de données

Etat des lieux

Actuellement, eap est un mode d'authentification par défaut, si bien que tout certificat présenté, s'il est authentique et non révoqué, sera accepté sans autre contrainte. Si nous trouvons un moyen pour que eap ne soit utilisé que si l'utilisateur est référencé dans la base, les choses deviendraient beaucoup plus simples, il suffirait d'ajouter ou de supprimer une ligne dans la base pour suspendre, temporairement ou non, un compte d'utilisateur, même si le certificat est encore en cours de validité.

Nous verrons que lorsque le client est configuré pour utiliser eap-tls, il présente son cetificat, dans tous les cas de figure. Dans ce certificat, il y a le nom de l'utilisateur. Exemple :

Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number: 20 (0x14)
        Signature Algorithm: sha1WithRSAEncryption
        Issuer: C=FR, ST=France, L=Marseille, O=Maison, OU=Reseau_maison, CN=root_maison_CA/emailAddress=chris@maison.mrs
        Validity
            Not Before: Jan  6 12:17:58 2009 GMT
            Not After : Nov 13 12:17:58 2016 GMT
        Subject: C=FR, ST=France, L=Marseille, O=Maison, OU=Reseau_maison, CN=user1/emailAddress=user1@maison.mrs
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
            RSA Public Key: (4096 bit)
...
Si nous trouvons un moyen d'expliquer à notre FreeRADIUS que seuls les utilisateurs référencés dans un groupe particulier pourront utiliser EAP, ceci devrait résoudre notre problème.

Pour rappel, nous avons actuellement dans /etc/freeradius/sites-avalable/default les directives suivantes :

authorize {
	preprocess
	eap {
		ok = return
	}
	sql
}
authenticate {
	Auth-Type CHAP {
		chap
	}
	eap
}

Authentification EAP sélective

Nous allons simplifier /etc/freeradius/sites-avalable/default comme suit :

authorize {
	preprocess
	sql
}
...

De cette manière, eap ne sera plus autorisé par défaut et, sans informations supplémentaires, plus aucun certificat ne sera accepté puisque eap-tls ne sera plus reconnu comme un moyen d'authentification valide.

Voici ce qu'il va se passer lorsque user1 va présenter son certificat :

rad_recv: Access-Request packet from host 192.168.1.254 port 1285, id=0, length=199
	Message-Authenticator = 0xcb9362792c3a93b83a28b6153462c2db
	Service-Type = Framed-User
	User-Name = "user1\000"
	Framed-MTU = 1488
	Called-Station-Id = "00-0F-3D-AB-66-E8:maisonwifi"
	Calling-Station-Id = "00-1F-3C-4B-07-9C"
	NAS-Identifier = "D-Link Access Poi"
	NAS-Port-Type = Wireless-802.11
	Connect-Info = "CONNECT 54Mbps 802.11g"
	EAP-Message = 0x0200000e016c61702d70726f6673
	NAS-IP-Address = 192.168.1.254
	NAS-Port = 1
	NAS-Port-Id = "STA port # 1"
+- entering group authorize
++[preprocess] returns ok
	expand: %{User-Name} -> user1
rlm_sql (sql): sql_set_user escaped user --> 'user1'
rlm_sql (sql): Reserving sql socket id: 3
	expand: SELECT id, username, attribute, value, op FROM radcheck WHERE username = '%{SQL-User-Name}' ORDER BY id -> SELECT id, username, attribute, value, op FROM radcheck WHERE username = 'user1' ORDER BY id
	expand: SELECT groupname FROM radusergroup WHERE username = '%{SQL-User-Name}' ORDER BY priority -> SELECT groupname FROM radusergroup WHERE username = 'user1' ORDER BY priority
rlm_sql (sql): Released sql socket id: 3
rlm_sql (sql): User user1 not found
++[sql] returns notfound
auth: No authenticate method (Auth-Type) configuration found for the request: Rejecting the user
auth: Failed to validate the user.
Login incorrect: [user1\000/] (from client dwl2100ap port 1 cli 00-1F-3C-4B-07-9C)
Delaying reject of request 10 for 1 seconds
Going to the next request
Waking up in 0.9 seconds.
Sending delayed reject for request 10
Sending Access-Reject of id 0 to 192.168.1.254 port 1285
Waking up in 3.9 seconds.

Il n'y a pas de mot de passe, il n'y a pas d'autre méthode d'authentification, le client est rejeté.

La notion de groupes existe dans radius. Si nous créons un groupe d'utilisateurs qui ont EAP comme méthode d'authentification, et que nous plaçons dans ce groupe les noms des clients qui ont un certificat en cours de validité, ça devrait fonctionner.

Le groupe wifiGroup

Dans la table radgroupcheck, nous créons un groupe que nous appellerons « wifiGroup » auquel nous accordons le type d'authentification EAP :

mysql> INSERT INTO radgroupcheck(GroupName,Attribute,op,Value) VALUES ('wifiGroup','Auth-Type',':=','EAP');
Query OK, 1 row affected (0.00 sec)

Il nous reste maintenant à associer dans la table usergroup l'utilisateur « user1 » au groupe « wifiGroup » :

mysql> INSERT INTO usergroup(UserName,GroupName) VALUES ('user1','wifiGroup');
Query OK, 1 row affected (0.00 sec)

Et à vérifier que notre méthode fonctionne :

ad_recv: Access-Request packet from host 192.168.1.254 port 1287, id=5, length=1703
	Message-Authenticator = 0x5a717acfbd03837c04baa4ff01be6399
	Service-Type = Framed-User
	User-Name = "user1\000"
	Framed-MTU = 1488
	State = 0x411d49f94518440d3eeebef8b48bd82c
	Called-Station-Id = "00-0F-3D-AB-66-E8:maisonwifi"
	Calling-Station-Id = "00-1F-3C-4B-07-9C"
	NAS-Identifier = "D-Link Access Poi"
	NAS-Port-Type = Wireless-802.11
	Connect-Info = "CONNECT 54Mbps 802.11g"
	EAP-Message = 0x020505d20dc000000a901603010a600b00075000074d00074a308207463082052ea003020102020114300d06092a864886f70d0101050500308199310b3009060355040613024652310f300d060355040813064672616e636531123010060355040713094d61727365696c6c65310c300a060355040a1303454d453110300e060355040b130752657365617578311430120603550403140b526f6f745f454d455f4341312f302d06092a864886f70d0109011620736572766963652e696e666f40656d652d656e736569676e656d656e742e6672301e170d3039303130363132313735385a170d3136313131333132313735385a308185310b30090603
	EAP-Message = 0x55040613024652310f300d060355040813064672616e636531123010060355040713094d61727365696c6c65310c300a060355040a1303454d453110300e060355040b13075265736561757831123010060355040313096c61702d70726f6673311d301b06092a864886f70d010901160e63616c65636140656d652e6f726730820222300d06092a864886f70d01010105000382020f003082020a02820201009e200fbbd6d82d2e6187673e7d4ca8fbd7696a564c550e782a40030cf67af8509402a4085765c329804c850bc7f629c0bff57690f7aa879422bb7ebf47cd3efa7e7bd3d6f8ad3c4718e1ba584f73d50fb146fde97aa3d52501b746b63c
	EAP-Message = 0x597d42670715fb9f0dc758c3efca14ea6efdc1ace976f9dc5346205c04e0b42de56aa643dec29cd0e8aa37223b78748490e089790962226f930d756851fb3fe720be5c65d06fa57c6c1f01a2cf45dd5613ff543d68fe5a10fd94c377e42cb665d7dd8413ce97bae64a00316a8947d33251e0c87b5a514c63854301548305c3ca82b1066f3d59e1be77a96031c08c1dc0606ab45fc4122d6bd7ba5e109c5b36b8529fe7c8e0faae713ebcc143baba93374d78de699814170794caa720559840589f7b71d3390667b20c7a39bf312e68ca48b2a9ea45cab51fdd3451b2753c7d9be63109f8d33bf51993ff0778f4fded95f834d81fe7f499d8e8e025867a
	EAP-Message = 0x8b9b1ecb74502381f8ce29f3b94ef2808da6438ec64cca64a2644ea659e747b6287bd674b5fcaa4efbcedb4d4b8146c2d831ab675844e2856512f5e5b385c4a7403cc7871114a0c5d645663dfb17f38e3f842c20c688fba23303d1b7b3982d811c9e14af8dfc13129e5d5a3646712f35cacdd850bfe300b0d954cfc041024c2e5adf0f3c2589479df978c1685f8eaf7c6525e70fb9058d2aae777ceb8d9880734d040a51b6d90203010001a38201a9308201a530090603551d1304023000301106096086480186f84201010404030204b0302b06096086480186f842010d041e161c54696e7943412047656e6572617465642043657274696669636174
	EAP-Message = 0x65301d0603551d0e0416041447069b70658e7d9f0f4ffe350b37543da59b7f1f3081ce0603551d230481c63081c380143cabad8ef6977ba1e75c1ec13a2221e66e91f252a1819fa4819c308199310b3009060355040613024652310f300d060355040813064672616e636531123010060355040713094d61727365696c6c65310c300a060355040a1303454d453110300e060355040b130752657365617578311430120603550403140b526f6f745f454d455f4341312f302d06092a864886f70d0109011620736572766963652e696e666f40656d652d656e736569676e656d656e742e667282090083382b812e0c60d7302b0603551d120424302281
	EAP-Message = 0x20736572766963652e696e666f40656d652d656e736569676e656d656e742e667230190603551d1104123010810e63616c65636140656d652e6f7267300b0603551d0f0404030205a030130603551d25040c300a06082b06010505070302300d06092a864886f70d010105050003820201006ba84b0aa33cf563f4581aa849ce83c46cd8dfdcb87c3c57487b26d46dad9683e29e03edcbe5633e2b2b263b9a9f30c18678317a8e6f2db9d6e3961b74af15f45f93b1f8ffbf76f0d598b433c7a025e15777e19053d22fd62934dc5ae268c6d7f839a59f0e6922ff861fce27683d89
	NAS-IP-Address = 192.168.1.254
	NAS-Port = 1
	NAS-Port-Id = "STA port # 1"
+- entering group authorize
++[preprocess] returns ok
	expand: %{User-Name} -> user1
rlm_sql (sql): sql_set_user escaped user --> 'user1'
rlm_sql (sql): Reserving sql socket id: 1
	expand: SELECT id, username, attribute, value, op FROM radcheck WHERE username = '%{SQL-User-Name}' ORDER BY id -> SELECT id, username, attribute, value, op FROM radcheck WHERE username = 'user1' ORDER BY id
	expand: SELECT groupname FROM radusergroup WHERE username = '%{SQL-User-Name}' ORDER BY priority -> SELECT groupname FROM radusergroup WHERE username = 'user1' ORDER BY priority
	expand: SELECT id, groupname, attribute, Value, op FROM radgroupcheck WHERE groupname = '%{Sql-Group}' ORDER BY id -> SELECT id, groupname, attribute, Value, op FROM radgroupcheck WHERE groupname = 'wifiUsers' ORDER BY id
rlm_sql (sql): User found in group wifiUsers
	expand: SELECT id, groupname, attribute, value, op FROM radgroupreply WHERE groupname = '%{Sql-Group}' ORDER BY id -> SELECT id, groupname, attribute, value, op FROM radgroupreply WHERE groupname = 'wifiUsers' ORDER BY id
rlm_sql (sql): Released sql socket id: 1
++[sql] returns ok
 rad_check_password: Found Auth-Type EAP
auth: type "EAP"
+- entering group authenticate
 rlm_eap: Request found, released from the list
 rlm_eap: EAP/tls
 rlm_eap: processing type tls
 rlm_eap_tls: Authenticate
 rlm_eap_tls: processing TLS
....
Passons sur la suite, notre utilisateur user1 va maintenant disposer de l'authentification de type EAP et le reste va se passer convenablement pour lui.

Cette méthode finalement fort simple nous permet en agissant sur le contenu de la table usergroup d'autoriser ou non un utilisateur présentant un certificat valide sur la bonne foi du nom (CN) présenté par le client, CN qui se trouve dans le certificat. Il nous est désormais possible d'interdire l'accès à un utilisateur disposant d'un certificat en cours de validité, sans avoir besoin de passer par un certificat de révocations.

Conclusion

Nous sommes loin d'avoir vu tout ce qu'il est possible de faire avec RADIUS, mais nous avons réalisé ce que nous voulions faire.

Dans le cas du réseau filaire, il est également possible d'attribuer un ID de VLAN différent suivant l'utilisateur authentifié, de même qu'il est possible de remplacer EAP-TLS par PEAP, si l'on dispose par exemple d'un annuaire ActiveDirectory et que l'on souhaite que les clients Wi-Fi soient authentifiés avec leur « login/password » du réseau Microsoft, plutôt que par un certificat. La machine qui héberge FreeRadius doit alors être intégrée au domaine Microsoft et pouvoir interroger l'annuaire ActiveDirectory. A mon sens, EAP-TLS reste largement préférable, ne serait-ce qu'à cause des fuites (toujours possibles) de login/passwords.