Using One TIme Passwords with FreeRadius

radius.pkoch at radius.pkoch at
Thu Apr 29 10:22:27 CEST 2021

Dear reader of this mailinglist

I'm new to the RADIUS business and I did my frist FreeRadius 
installation just two weeks ago. I still might misunderstand some of the 
concepts. So keep in mind that whenever I make statments about what 
FreeRadius does or should do - these are all my personal assumptions 
only and might be totally wrong. So far I only tried to get things 
working. I did not look at my "solution" from a security perspective.

I'm describing my solution since this might be useful to other people. 
And I was hoping to get some feedback.

My goal was to allow our users to authenticate with our WiFi 
accesspoints with a 2-factor method. This means for us, that they either 
have to user their identity card (which has a builtin smart card chip) 
or their OTP-token (which generates OATH TOTP values). The solution was 
expected to work with both laptops (Windows and MacOS) and smart 
phones/tablets (iPhones, Android). It was expected to work with 
company-devices (manages by our own MDM) and with BYO-devices from 
eployees or guests.

I never heard of solutions that allows an iPhone to use a smart card for 
authentication. And using smart cards always needs prior installation of 
smart card middleware. But one time passwords can be used whenever a 
password has to be entered. Some of our employees have a second token 
for generation of "guest-passwords". So using passwords generated by our 
OTP-tokens seemed to be the only way to go.

Without two-factor authentication our employees must go to a central 
helpdesk, prove their identity by showing their identity card or 
passport, just to get a piece of paper with a password that allows WiFi 
acces for twelve hours only. If they forward this password to a guest, 
they have to fill out another piece of paper.

With this situation we cannot force the devices to use certain 
algorithms for WiFi-authentication. OTP-authentication might require 
that the supplicant sends the password in clear (PAP or PAP within 
EAP-TTLS). But configuring guest devices to use this authentication 
method is unrealistic. iPhones for example can do this, but only if they 
are under MDM-control.

So we use EAP-PEAP with MSCHAPv2 because that's supported by all devices 
if the accesspoint is configured for WPA2-Enterprise. At least we hope 
that this is true. And we don't care about guests that visit us with 
their Win-XP laptops.

MSCHAPv2 does not send the password in cleartext within the inner 
tunnel. But as you all know there's no need to compare password A with 
password B if you just want to check wether they are equal or not. 
Comparing HashFunction(A) with HashFunction(B) does work as well and the 
hash function used by MSCHAPv2 is well documented in RFC 2759.

So how do you teach FreeRadius to verify an OATH time based one time 
password? rlm_otp and rlm_secureid where of no help. So I read the the 
source code of other FreeRadius modules to find the place where 
FreeRadius does authentication based on the RFC2759 hash function.

I found it in rlm_mschap.c in function do_mschap(). There's a switch 
statement which looks at the value of  method. If method==AUTH_INTERNAL 
FreeRadius calculates the MSCHAPv2 hash on it's own and complains if the 
password is missing. But to my great pleasure (I love this 
FreeRadius-software) I spotted another FreeRadius authentication method 
in that switch-statement, namely AUTH_NTLM_EXEC. With that method 
FreeRadius delegates the decision about wether the MSCHAPv2 hash value 
is correct or not to an external program. The location of this external 
program is configured by the ntlm_auth configuration directive. And the 
idea behind this was obviously to let the ntlm_auth programm from Samba 
do the decision.

But there's no real reason why the ntlm_auth programm must be the Samba 
one. So I put

ntlm_auth = "/etc/radius/check_otp '%{mschap:User-Name}' 
'%{mschap:Challenge}' '%{mschap:NT-Response}' '%{Packet-SRC-IP-Address}'"

into mods-enabled/mschap and wrote my own "ntlm_auth"-style routine. It 
takes the username, challenge and a correct token values, calculates the 
response from these values and compares that with the given response. 
The 4th-parameter has informational purpoes only and will be included in 
syslog-messages when something goes wrong. Actually 
/etc/radius/check_otp does not do anything on its own, but just forwards 
all arguments to our authentication server. One could avoid that 
indirection across check_otp and let FreeRadius talk directly with our 
authentication server. I don't think that's worth the minimal 
performance improvement. And the interface between FreeRadius and the 
"ntlm_auth"-program is very easy to implement.

This solutions is used within our IT-department since monday and will go 
into production next week. So far we had no problems. Everybody is glad 
that he must not visit the helpdesk anymore (which is mostely closed 
anyway due to corona).

There are some pitfalls:

Most important: If a one time password turned out to be correct, it will 
be reused by the supplicant many times. And for obvious reasons you 
don't want to enter a new token value over and over again. Hence the 
check_otp routine must accept token values that were successfully used 
within the past for some amount of time. We use 12 hours for guests and 
I have to fight with the security staff about wether this can be 
increased for employees. Their main argument is, that a valid password 
might be given to other people. So I'm looking for a way to detect 
wether two supplicants are using the same user/password-combination. iOS 
MAC-randomization is my enemy here. Maybe someone has an idea how to do 

Kind regards


More information about the Freeradius-Users mailing list