using external script in virtual server config

the2nd at the2nd at
Sun Feb 1 14:32:31 CET 2015

replying to myself as i figured it out how to handle mschapv2 requests 
using rlm_python.

as supposed there are python modules to do this:

using the functions from these modules it was relatively easy to write a 
python module that can handle mschapv2 requests. currently i'm not sure 
if my module works with all variants but it works at least with all wlan 
devices i've tested so far and also when using eapol_test.

everyone who is interested in this may have a look at my module which is 
available here:

also the readme and the sample freeradius configs may have some 
interesting infos:

if you only store the nt hash of the user passwords in your backend, 
instead of clear-text passwords, you have to modify two functions of 
python-mschap. but thats easy.

i hope this will help someone else who wants to do the same.

if there is anything wrong with my code i'm happy about every feedback.

btw. it would be really nice to have an interface (e.g. python/perl 
bindings) to the freeradius mschap module to use it for mschap requests 
instead of doing it in the corresponding language.


On 2015-01-27 20:37, the2nd at wrote:
> On 2015-01-27 19:21, Alan DeKok wrote:
>> On Jan 27, 2015, at 1:05 PM, the2nd at wrote:
>>> sorry i dont want to be rude but it's just not true what you say. 
>>> authData is send from rlm_python to the authenticate() function of 
>>> the module it loads. i just used the example module that 
>>> comes with freeradius as a "template". and it does exactly what you 
>>> call "my invention". it uses authData to get a tuple with 
>>> authentication data (e.g. username and password):
>>   Ok… but I still don’t need to see that.  It’s just not relevant to
>> *anything*.  The debug output is relevant.
> i think it is relevant because if it contains a challange/response
> that is in the format of what mschap hands over to the original
> ntlm_auth from samba my script is able to verify the request.
>>> so its not my code that sets this tuple and its nothing i have 
>>> invented. and all i want to know is if it is possible to get 
>>> "%{mschap:Challenge}"  and "%{mschap:NT-Response}" in this tuple to 
>>> verify an mschap request just like it can be done with the ntlm_auth 
>>> statement from within the mschap module.
>>   I’ve told you how to do that.  And it works.. *if* the packet
>> contains MS-CHAP.  If the packet doesn’t contain MS-CHAP, it won’t
>> work.
>>> and i think thats a valid use case when someone wants to integrate an 
>>> otp solution with freeradius using rlm_python.
>>   Sure.  Then *you* read the RFCs to figure out how MS-CHAP works.
>> That’s what I did.  And then I wrote rlm_mschap.  With comments.
>>   Why should I cut & paste all of that to the list, when it’s already
>> available to you?  Why haven’t you read the RFC and source yourself?
>>> the first one is using my python script as a replacement of ntlm_auth 
>>> from within the mschap module and succeeds. the second one uses 
>>> rlm_python and my module. you can see in the debug ouput whats in 
>>> authData (one of the lines that starts with because i used 
>>> the provided log function to log it.
>>  ...
>>> [eap] EAP/peap
>>   OK… that’s not MS-CHAP, but it might still work.
>>> [mschapv2] +group MS-CHAP {
>>> [otpme_ntlm] Creating challenge hash with username: testuser1
>>> [otpme_ntlm] Client is using MS-CHAPv2 for testuser1, we need 
>>> NT-Password
>>> [otpme_ntlm] 	expand: %{Stripped-User-Name} ->
>>> [otpme_ntlm] 	... expanding second conditional
>>> [otpme_ntlm] 	expand: %{User-Name} -> testuser1
>>> [otpme_ntlm] 	expand: %{%{User-Name}:-None} -> testuser1
>>> [otpme_ntlm] 	expand: %{%{Stripped-User-Name}:-%{%{User-Name}:-None}} 
>>> -> testuser1
>>> [otpme_ntlm] Creating challenge hash with username: testuser1
>>> [otpme_ntlm] 	expand: %{otpme_ntlm:Challenge} -> a9696cdff7c89500
>>> [otpme_ntlm] 	expand: %{%{otpme_ntlm:Challenge}:-00} -> 
>>> a9696cdff7c89500
>>> [otpme_ntlm] 	expand: %{otpme_ntlm:NT-Response} -> 
>>> b30b7de20b87d7158c571ff2bbffa75e2751147babd02c71
>>> [otpme_ntlm] 	expand: %{%{otpme_ntlm:NT-Response}:-00} -> 
>>> b30b7de20b87d7158c571ff2bbffa75e2751147babd02c71
>>> [otpme_ntlm] 	expand: %{NAS-Identifier} ->
>>> [otpme_ntlm] 	expand: %{Client-IP-Address} ->
>>> Exec output: NT_KEY: DAC3BE8FCFB20063D121449A6B2A28B4
>>> Exec plaintext: NT_KEY: DAC3BE8FCFB20063D121449A6B2A28B4
>>   Which the normal ntlm_auth program.
>>   You do realize that ntlm_auth implements all of the MS-CHAP
>> algorithms, right?  And that if you replace ntlm_auth with a python
>> module, you’ve got to re-implement MS-CHAP?
> i already have this working with my script. it is possible to verify
> the challenge/response that it gets from the mschap module. i tried
> this with eapol_test and also with different smartphones and notebooks
> using a linksys access point and wpa2 enterprice that send the request
> to freeradius. the problem is that i was not able to get same
> challenge/response from rlm_python.
>>   And then the second debug output:
>>> [mschapv2] # Executing group from file /etc/raddb/sites-enabled/otpme
>>> [mschapv2] +group MS-CHAP {
>>> [mschapv2] ++update request {
>>> [mschapv2] Creating challenge hash with username: testuser1
>>> [mschapv2] 	expand: %{mschap:Challenge} -> 7b0455c972d1cf5a
>>> [mschapv2] 	expand: %{mschap:NT-Response} -> 
>>> 29e51adbb58ea4ca9bf39d832700639c0f2eebefb98900be
>>> [mschapv2] ++} # update request = noop
>>> (('EAP-Message', 
>>> '0x020600441a0206003f31ce62417d83cc845be89af47e43de8e85000000000000000029e51adbb58ea4ca9bf39d832700639c0f2eebefb98900be00746573747573657231'), 
>>> ('FreeRADIUS-Proxied-To', ''), ('User-Name', '"testuser1"'), 
>>> ('State', '0xef3dc50aef3bdf904f03abafc54a8a4c'), ('NAS-IP-Address', 
>>> ''), ('Calling-Station-Id', '"02-00-00-00-00-01"'), 
>>> ('Framed-MTU', '1400'), ('NAS-Port-Type', 'Wireless-802.11'), 
>>> ('Connect-Info', '"CONNECT 11Mbps 802.11b"'), ('EAP-Type', 
>>> 'MS-CHAP-V2'), ('MS-CHAP-Challenge', 
>>> '0x9718a01768fd75c1209b1c257a4fd2be'), ('MS-CHAP2-Response', 
>>> '0x0665ce62417d83cc845be89af47e43de8e85000000000000000029e51adbb58ea4ca9bf39d832700639c0f2eebefb98900be'), 
>>> ('MS-CHAP-User-Name', '"testuser1"'), ('Tmp-Octets-0', 
>>> '0x37623034353563393732643163663561'), ('Tmp-Octets-1', 
>>> '0x323965353161646262353865613463613962663339643833323730303633396330663265656265666239383930306265'))
>>> ++[otpme_mod] = fail
>>> +} # group MS-CHAP = fail
>>   Which means your python module is returning “fail”.
> it fails because in the current state it needs what is shown in the
> lines above
>>> [mschapv2] 	expand: %{mschap:Challenge} -> 7b0455c972d1cf5a
>>> [mschapv2] 	expand: %{mschap:NT-Response} -> 
>>> 29e51adbb58ea4ca9bf39d832700639c0f2eebefb98900be
> but it gets what is in the line that starts with:
>>   Well… don’t do that.  You probably also want to do:
>> 	update request {
>> 		Tmp-Octets-0 := “0x%{mschap:Challenge}”
>> 		Tmp-Octets-1 := “0x{mschap:NT-Response}”
>> 	}
>>   Right now, the Tmp-Octets attributes contain *ASCII* text.  This
>> should be obvious from looking at them.
> i just want to make sure if i got it right. should the "update
> request" statement make %{mschap:Challenge} and {mschap:NT-Response}
> available inside the tuple that my module gets from rlm_python? and
> should they be in the same format as what is passed to ntlm_auth from
> the mschap module? because thats what i thought i should get with this
> statement and maybe there is a misunderstanding.
> i changed my config now to use the update statement from above. but
> your example has a % before the challenge and none before the
> response. is this how it should be?
>>   Once you fix that, the only issue is re-implementing MS-CHAP in
>> python.  Good luck with that.  There are literally hundreds of pages
>> of documentation and sample code which should help you.
> i havent looked into the details of mschap yet. but if the challenge
> response format i get from rlm_python is different than what mschap
> hands over to ntlm_auth i guess there are python modules available to
> handle them (is this mschapv2?). i will check this if thats the
> case....
> thanks for you help!
>>   Alan DeKok.
>> -
>> List info/subscribe/unsubscribe? See 
> -
> List info/subscribe/unsubscribe? See 

More information about the Freeradius-Users mailing list