rlm_python learnings - PAP and MSCHAPv2

Lang, Russell Russell.Lang at team.telstra.com
Fri Jan 17 04:27:12 CET 2020

FreeRADIUS is working, using rlm_python to do authentication for WPA2-Personal and WPA2-Enterprise Wi-Fi clients. 
This is a summary of the issues I found and suggested improvements.  
Using FreeRADIUS 3.0.15 package on Ubuntu 18.04.

We previously had FreeRADIUS configured to exec a python process for each PAP or MSCHAPv2  authentication, 
which then called a REST API to check the user.
This was slow (120ms) due to the time taken to start a process and load python.

To speed this up, I first tried to use rlm_rest.  
This didn't work because we don't have the cleartext password, only the NT hash.

Next I tried rlm_python, which I did get working.

For PAP, during FreeRADIUS default authorize processing, it says no cleartext password,
so it does not set Auth-Type=PAP, and so it does not call the PAP authenticate code.
My workaround is python authorize code to set config:Auth-Type=python if User-Name and User-Password are set,
but not EAP-Message.  The default site config has "python" in the authorize section, 
and "Auth-Type python { python }" in the authenticate section.  
This is fragile, so if you have any better suggestions...

For PEAP-MSCHAPv2, the default site config is unchanged.  
The inner-tunnel authenticate config has "Auth-Type mschap { python }".
In the python authenticate code, I take the params and pass them to a REST API as JSON, 
then take the response from the REST API and return this as the reply.
This means I am passing MS-CHAP-User-Name, MS-CHAP-Challenge and MS-CHAP2-Response
into the API, and getting MS-CHAP2-Success as the reply.
MS-CHAP-Challenge is in the expected format.

Issue 1: MS-CHAP2-Response is NOT in the format defined in the RFC.  The first byte is unknown.  
Second byte is the flag, moved from the end of the response, which is still wrong because it isn't 0.
Subsequent bytes are as expected (16 bytes peer challenge, 8 bytes padding, 24 bytes NT response).
I reformat the response to the RFC format before handing to the REST API.
MS-CHAP-Response is also wrong in the same way, although the flag byte is the expected 1
(to indicate NT response is present).

Issue 2: I generate the correct MS-CHAP2-Success packet "S=40hex" and include it in the python
module reply. FreeRADIUS removes the first byte of this (source code confirms this)
and sends the remainder, making it incorrect.
My kludge is to add a padding byte at the start of the MS-CHAP2-Success python reply,
for FreeRADIUS to remove.

Have a fall-through authenticate method if Auth-Type is not set.    This would avoid my fragile python authorize code, and allow PAP authentication without a cleartext password.

Allow PAP authorize and rlm_rest to work if the NT hash of the password is available.

More information about the Freeradius-Users mailing list