Freeradius with multiotp - but otp-pin is in username
Hi guys, i'm trying to setup FreeRADIUS Version 3.0.13 with multiotp BUT I want to enter the information like this: "{Username}:{OTP-PIN}" ==> f.e. "dani:955825" (username in users file) "{Password}" ==> f.e. "blabla" (password in users file) I think this could be a way, to get some devices to work with 2 factor, which are not build for it. I successfully get an ok from multiotp, by regex'ing "{OTP-PIN}" from "{Username}:{OTP-PIN}", but PAP is failing, because I can't get PAP to look for "{Username}" (f.e. "dani"). It always tries to look for "{Username}:{OTP-PIN}" (f.e. "dani:955825") in the authentication-section. It would be nice if you could point me in the right direction. My apologies, if this question was already asked, and I didn't find it. Best regards Gerald remark - begin ------------ I successfully did it with "{Username} " ==> f.e. "dani" (username in users file) "{Password}{OTP-PIN}" ==> f.e. "blabla955825" (password in users file) . But I think the "{Username}" "{Password}{OTP-PIN}" way, fails when it comes to MSCHAP (with ActiveDirectory), because Freeradius compares only password hashes and not plaintext, so it can't recongnise what's the OTP-PIN and what's the password. -------------- remark - end /usr/local/etc/raddb/users #### "dani" Cleartext-Password := "blabla", MS-CHAP-Use-NTLM-Auth := 0 #### /usr/local/etc/dictionary #### ATTRIBUTE User-OTP 3000 string ATTRIBUTE User-Password-TMP 3001 string #### /usr/local/etc/raddb# cat policy.d/pol_usernamemultiotp ##### pol_usernamemultiotp.authorize { if ( &User-Name =~ /^(.*)(\:)([0-9]{6})$/) { update request { User-Password-TMP := "%{User-Password}" User-OTP := "%{3}" User-Password := "%{User-OTP}" User-Name := "%{1}" Stripped-User-Name := "%{1}" } multiotp if (ok) { update request { User-Name := "%{1}" User-Password := "%{User-Password-TMP}" } update control { Auth-Type := PAP } } else { reject } } } ##### radiusd -X output - begin ##### Ready to process requests (0) Received Access-Request Id 192 from 127.0.0.1:56491 to 127.0.0.1:1842 length 81 (0) User-Name = "dani:955825" (0) User-Password = "blabla" (0) NAS-IP-Address = 127.0.0.1 (0) NAS-Port = 100 (0) Message-Authenticator = 0x0cc5e28430dea113b6b4fde2d1537388 (0) # Executing section authorize from file /usr/local/etc/raddb/sites-enabled/custom_otp (0) authorize { (0) policy filter_username { (0) if (&User-Name) { (0) if (&User-Name =~ / /) { (0) if (&User-Name =~ / /) -> FALSE (0) if (&User-Name =~ /@[^@]*@/ ) { (0) if (&User-Name =~ /@[^@]*@/ ) -> FALSE (0) if (&User-Name =~ /\.\./ ) { (0) if (&User-Name =~ /\.\./ ) -> FALSE (0) if ((&User-Name =~ /@/) && (&User-Name !~ /@(.+)\.(.+)$/)) { (0) if ((&User-Name =~ /@/) && (&User-Name !~ /@(.+)\.(.+)$/)) -> FALSE (0) if (&User-Name =~ /\.$/) { (0) if (&User-Name =~ /\.$/) -> FALSE (0) if (&User-Name =~ /@\./) { (0) } # policy filter_username = notfound (0) [preprocess] = ok (0) auth_log: --> /usr/local/var/log/radius/radacct/127.0.0.1/auth-detail-20170521 (0) [auth_log] = ok (0) [chap] = noop (0) [mschap] = noop (0) [digest] = noop (0) suffix: Checking for suffix after "@" (0) suffix: No '@' in User-Name = "dani:955825", looking up realm NULL (0) suffix: No such realm "NULL" (0) [suffix] = noop (0) eap: No EAP-Message, not doing EAP (0) [eap] = noop (0) custom_otp: Searching for user in group "vlan10" rlm_ldap (ldap): Closing connection (0): Hit idle_timeout, was idle for 76 seconds rlm_ldap (ldap): Closing connection (1): Hit idle_timeout, was idle for 76 seconds rlm_ldap (ldap): Closing connection (2): Hit idle_timeout, was idle for 76 seconds rlm_ldap (ldap): You probably need to lower "min" rlm_ldap (ldap): Closing connection (3): Hit idle_timeout, was idle for 76 seconds rlm_ldap (ldap): You probably need to lower "min" rlm_ldap (ldap): Closing connection (4): Hit idle_timeout, was idle for 76 seconds rlm_ldap (ldap): You probably need to lower "min" rlm_ldap (ldap): 0 of 0 connections in use. You may need to increase "spare" rlm_ldap (ldap): Opening additional connection (5), 1 of 32 pending slots used rlm_ldap (ldap): Connecting to ldap://testdc.test.apa.lan:389 rlm_ldap (ldap): Waiting for bind result... rlm_ldap (ldap): Bind successful rlm_ldap (ldap): Reserved connection (5) (0) custom_otp: EXPAND (samaccountname=%{%{Stripped-User-Name}:-%{User-Name}}) (0) custom_otp: --> (samaccountname=dani:955825) (0) custom_otp: Search returned no results rlm_ldap (ldap): Released connection (5) Need 2 more connections to reach min connections (3) rlm_ldap (ldap): Opening additional connection (6), 1 of 31 pending slots used rlm_ldap (ldap): Connecting to ldap://testdc.test.apa.lan:389 rlm_ldap (ldap): Waiting for bind result... rlm_ldap (ldap): Bind successful (0) custom_otp: Searching for user in group "vlan99" rlm_ldap (ldap): Reserved connection (5) (0) custom_otp: EXPAND (samaccountname=%{%{Stripped-User-Name}:-%{User-Name}}) (0) custom_otp: --> (samaccountname=dani:955825) (0) custom_otp: Waiting for search result... (0) custom_otp: Search returned no results rlm_ldap (ldap): Released connection (5) (0) [custom_otp] = noop rlm_ldap (ldap): Reserved connection (6) (0) ldap: EXPAND (samaccountname=%{%{Stripped-User-Name}:-%{User-Name}}) (0) ldap: --> (samaccountname=dani:955825) (0) ldap: Waiting for search result... (0) ldap: Search returned no results rlm_ldap (ldap): Released connection (6) (0) [ldap] = notfound (0) [expiration] = noop (0) [logintime] = noop (0) policy pol_usernamemultiotp.authorize { (0) if ( &User-Name =~ /^(.*)(\:)([0-9]{6})$/) { (0) if ( &User-Name =~ /^(.*)(\:)([0-9]{6})$/) -> TRUE (0) if ( &User-Name =~ /^(.*)(\:)([0-9]{6})$/) { (0) update request { (0) EXPAND %{User-Password} (0) --> blabla (0) User-Password-TMP := blabla (0) EXPAND %{3} (0) --> 955825 (0) User-OTP := 955825 (0) EXPAND %{User-OTP} (0) --> 955825 (0) User-Password := 955825 (0) EXPAND %{1} (0) --> dani (0) User-Name := dani (0) EXPAND %{1} (0) --> dani (0) Stripped-User-Name := dani (0) } # update request = noop (0) multiotp: EXPAND %{User-Name} (0) multiotp: --> dani (0) multiotp: EXPAND %{User-Password} (0) multiotp: --> 955825 (0) multiotp: EXPAND -src=%{Packet-Src-IP-Address} (0) multiotp: --> -src=127.0.0.1 (0) multiotp: EXPAND -chap-challenge=%{CHAP-Challenge} (0) multiotp: --> -chap-challenge= (0) multiotp: EXPAND -chap-password=%{CHAP-Password} (0) multiotp: --> -chap-password= (0) multiotp: EXPAND -ms-chap-challenge=%{MS-CHAP-Challenge} (0) multiotp: --> -ms-chap-challenge= (0) multiotp: EXPAND -ms-chap-response=%{MS-CHAP-Response} (0) multiotp: --> -ms-chap-response= (0) multiotp: EXPAND -ms-chap2-response=%{MS-CHAP2-Response} (0) multiotp: --> -ms-chap2-response= (0) multiotp: Program returned code (0) and output '' (0) multiotp: Program executed successfully (0) [multiotp] = ok (0) if (ok) { (0) if (ok) -> TRUE (0) if (ok) { (0) update request { (0) EXPAND %{1} (0) --> dani (0) User-Name := dani (0) EXPAND %{User-Password-TMP} (0) --> blabla (0) User-Password := blabla (0) } # update request = noop (0) update control { (0) Auth-Type := PAP (0) } # update control = noop (0) } # if (ok) = noop (0) ... skipping else: Preceding "if" was taken (0) } # if ( &User-Name =~ /^(.*)(\:)([0-9]{6})$/) = ok (0) } # policy pol_usernamemultiotp.authorize = ok (0) pap: WARNING: No "known good" password found for the user. Not setting Auth-Type (0) pap: WARNING: Authentication will fail unless a "known good" password is available (0) [pap] = noop (0) } # authorize = ok (0) Found Auth-Type = PAP (0) # Executing group from file /usr/local/etc/raddb/sites-enabled/custom_otp (0) Auth-Type PAP { (0) pap: Login attempt with password (0) pap: No password configured for the user. Cannot do authentication (0) [pap] = fail (0) } # Auth-Type PAP = fail (0) Failed to authenticate the user (0) Using Post-Auth-Type Reject (0) # Executing group from file /usr/local/etc/raddb/sites-enabled/custom_otp (0) Post-Auth-Type REJECT { (0) attr_filter.access_reject: EXPAND %{User-Name} (0) attr_filter.access_reject: --> dani (0) attr_filter.access_reject: Matched entry DEFAULT at line 11 (0) [attr_filter.access_reject] = updated (0) [eap] = noop (0) policy remove_reply_message_if_eap { (0) if (&reply:EAP-Message && &reply:Reply-Message) { (0) if (&reply:EAP-Message && &reply:Reply-Message) -> FALSE (0) else { (0) [noop] = noop (0) } # else = noop (0) } # policy remove_reply_message_if_eap = noop (0) } # Post-Auth-Type REJECT = updated (0) Delaying response for 1.000000 seconds Waking up in 0.1 seconds. Waking up in 0.8 seconds. (0) Sending delayed response (0) Sent Access-Reject Id 192 from 127.0.0.1:1842 to 127.0.0.1:56491 length 20 Waking up in 3.9 seconds. (0) Cleaning up request packet ID 192 with timestamp +76 Ready to process requests ##### radiusd -X output - end
On May 21, 2017, at 6:53 PM, blaster@vorsicht-bissig.de wrote:
i'm trying to setup FreeRADIUS Version 3.0.13 with multiotp BUT I want to enter the information like this: "{Username}:{OTP-PIN}" ==> f.e. "dani:955825" (username in users file) "{Password}" ==> f.e. "blabla" (password in users file)
That's a little unusual, but it should work, mostly. But most people appoint the OTP to the password, not to the User-Name.
I think this could be a way, to get some devices to work with 2 factor, which are not build for it. I successfully get an ok from multiotp, by regex'ing "{OTP-PIN}" from "{Username}:{OTP-PIN}", but PAP is failing, because I can't get PAP to look for "{Username}" (f.e. "dani"). It always tries to look for "{Username}:{OTP-PIN}" (f.e. "dani:955825") in the authentication-section.
Because the default configuration looks up users by the contents of the User-Name attribute. Sine you've modified the User-Name to contain the OTP key, that won't work.
It would be nice if you could point me in the right direction. My apologies, if this question was already asked, and I didn't find it. Best regards Gerald remark - begin ------------ I successfully did it with "{Username} " ==> f.e. "dani" (username in users file) "{Password}{OTP-PIN}" ==> f.e. "blabla955825" (password in users file)
Which is what most people use.
But I think the "{Username}" "{Password}{OTP-PIN}" way, fails when it comes to MSCHAP (with ActiveDirectory), because Freeradius compares only password hashes and not plaintext, so it can't recongnise what's the OTP-PIN and what's the password.
Yes.
-------------- remark - end /usr/local/etc/raddb/users #### "dani" Cleartext-Password := "blabla", MS-CHAP-Use-NTLM-Auth := 0 #### /usr/local/etc/dictionary #### ATTRIBUTE User-OTP 3000 string
You don't need that.
ATTRIBUTE User-Password-TMP 3001 string #### /usr/local/etc/raddb# cat policy.d/pol_usernamemultiotp ##### pol_usernamemultiotp.authorize { if ( &User-Name =~ /^(.*)(\:)([0-9]{6})$/) { update request { User-Password-TMP := "%{User-Password}" User-OTP := "%{3}" User-Password := "%{User-OTP}"
This isn't necessary.
User-Name := "%{1}"
You probably shouldn't re-write the User-Name. Leave it alone.
Stripped-User-Name := "%{1}"
If Stripped-User-Name exists, the server uses it for lookups instead of User-Name. So all you need to do is set Stripped-User-Name correctly.
##### radiusd -X output - begin
Reading it carefully helps... the messages are useful.
##### Ready to process requests (0) Received Access-Request Id 192 from 127.0.0.1:56491 to 127.0.0.1:1842 length 81 (0) User-Name = "dani:955825" (0) User-Password = "blabla" (0) NAS-IP-Address = 127.0.0.1 (0) NAS-Port = 100 (0) Message-Authenticator = 0x0cc5e28430dea113b6b4fde2d1537388
That's the Access-Request...
(0) custom_otp: Searching for user in group "vlan10" rlm_ldap (ldap): Closing connection (0): Hit idle_timeout, was idle for 76 seconds rlm_ldap (ldap): Closing connection (1): Hit idle_timeout, was idle for 76 seconds rlm_ldap (ldap): Closing connection (2): Hit idle_timeout, was idle for 76 seconds rlm_ldap (ldap): You probably need to lower "min" rlm_ldap (ldap): Closing connection (3): Hit idle_timeout, was idle for 76 seconds rlm_ldap (ldap): You probably need to lower "min" rlm_ldap (ldap): Closing connection (4): Hit idle_timeout, was idle for 76 seconds rlm_ldap (ldap): You probably need to lower "min"
Pay attention to those messages. Either increase "idle_timeout", or lower "min".
(0) custom_otp: EXPAND (samaccountname=%{%{Stripped-User-Name}:-%{User-Name}}) (0) custom_otp: --> (samaccountname=dani:955825) (0) custom_otp: Search returned no results
Note that it's looking up the User-Name attribute. i.e. the name *before* any edits.
rlm_ldap (ldap): Released connection (6) (0) [ldap] = notfound (0) [expiration] = noop (0) [logintime] = noop (0) policy pol_usernamemultiotp.authorize {
And AFTER you look up User-Name (the one with the OTP), you run the policy to fix the User-Name. i.e. you have this reversed. The solution is to put the re-write at the TOP of the "authorize" section. That way, the Stripped-User-Name attribute is seen by all modules. And the policy you created is too complicated. Just do this: if ( &User-Name =~ /^(.*):([0-9]{6})$/) { update request { Stripped-User-Name := "%{1}" User-OTP := "%{2}" } } i..e. you don't need a "tmp" password. You don't need to re-write the password. You don't need to match (:) in the regex. Just matching : is good enough. Alan DeKok.
Hello, I put the policy on the top of the authorize section and it works as intendet. Thank you very much, Alan DeKok for your advice! Best regards Gerald On 22.05.2017 14:30, Alan DeKok wrote:
On May 21, 2017, at 6:53 PM, blaster@vorsicht-bissig.de wrote:
i'm trying to setup FreeRADIUS Version 3.0.13 with multiotp BUT I want to enter the information like this: "{Username}:{OTP-PIN}" ==> f.e. "dani:955825" (username in users file) "{Password}" ==> f.e. "blabla" (password in users file) That's a little unusual, but it should work, mostly.
But most people appoint the OTP to the password, not to the User-Name.
I think this could be a way, to get some devices to work with 2 factor, which are not build for it. I successfully get an ok from multiotp, by regex'ing "{OTP-PIN}" from "{Username}:{OTP-PIN}", but PAP is failing, because I can't get PAP to look for "{Username}" (f.e. "dani"). It always tries to look for "{Username}:{OTP-PIN}" (f.e. "dani:955825") in the authentication-section. Because the default configuration looks up users by the contents of the User-Name attribute.
Sine you've modified the User-Name to contain the OTP key, that won't work.
It would be nice if you could point me in the right direction. My apologies, if this question was already asked, and I didn't find it. Best regards Gerald remark - begin ------------ I successfully did it with "{Username} " ==> f.e. "dani" (username in users file) "{Password}{OTP-PIN}" ==> f.e. "blabla955825" (password in users file) Which is what most people use.
But I think the "{Username}" "{Password}{OTP-PIN}" way, fails when it comes to MSCHAP (with ActiveDirectory), because Freeradius compares only password hashes and not plaintext, so it can't recongnise what's the OTP-PIN and what's the password. Yes.
-------------- remark - end /usr/local/etc/raddb/users #### "dani" Cleartext-Password := "blabla", MS-CHAP-Use-NTLM-Auth := 0 #### /usr/local/etc/dictionary #### ATTRIBUTE User-OTP 3000 string You don't need that.
ATTRIBUTE User-Password-TMP 3001 string #### /usr/local/etc/raddb# cat policy.d/pol_usernamemultiotp ##### pol_usernamemultiotp.authorize { if ( &User-Name =~ /^(.*)(\:)([0-9]{6})$/) { update request { User-Password-TMP := "%{User-Password}" User-OTP := "%{3}" User-Password := "%{User-OTP}" This isn't necessary.
User-Name := "%{1}"
You probably shouldn't re-write the User-Name. Leave it alone.
Stripped-User-Name := "%{1}"
If Stripped-User-Name exists, the server uses it for lookups instead of User-Name. So all you need to do is set Stripped-User-Name correctly.
##### radiusd -X output - begin Reading it carefully helps... the messages are useful.
##### Ready to process requests (0) Received Access-Request Id 192 from 127.0.0.1:56491 to 127.0.0.1:1842 length 81 (0) User-Name = "dani:955825" (0) User-Password = "blabla" (0) NAS-IP-Address = 127.0.0.1 (0) NAS-Port = 100 (0) Message-Authenticator = 0x0cc5e28430dea113b6b4fde2d1537388 That's the Access-Request...
(0) custom_otp: Searching for user in group "vlan10" rlm_ldap (ldap): Closing connection (0): Hit idle_timeout, was idle for 76 seconds rlm_ldap (ldap): Closing connection (1): Hit idle_timeout, was idle for 76 seconds rlm_ldap (ldap): Closing connection (2): Hit idle_timeout, was idle for 76 seconds rlm_ldap (ldap): You probably need to lower "min" rlm_ldap (ldap): Closing connection (3): Hit idle_timeout, was idle for 76 seconds rlm_ldap (ldap): You probably need to lower "min" rlm_ldap (ldap): Closing connection (4): Hit idle_timeout, was idle for 76 seconds rlm_ldap (ldap): You probably need to lower "min" Pay attention to those messages. Either increase "idle_timeout", or lower "min".
(0) custom_otp: EXPAND (samaccountname=%{%{Stripped-User-Name}:-%{User-Name}}) (0) custom_otp: --> (samaccountname=dani:955825) (0) custom_otp: Search returned no results Note that it's looking up the User-Name attribute. i.e. the name *before* any edits.
rlm_ldap (ldap): Released connection (6) (0) [ldap] = notfound (0) [expiration] = noop (0) [logintime] = noop (0) policy pol_usernamemultiotp.authorize { And AFTER you look up User-Name (the one with the OTP), you run the policy to fix the User-Name.
i.e. you have this reversed.
The solution is to put the re-write at the TOP of the "authorize" section. That way, the Stripped-User-Name attribute is seen by all modules.
And the policy you created is too complicated. Just do this:
if ( &User-Name =~ /^(.*):([0-9]{6})$/) { update request { Stripped-User-Name := "%{1}" User-OTP := "%{2}" } }
i..e. you don't need a "tmp" password. You don't need to re-write the password. You don't need to match (:) in the regex. Just matching : is good enough.
Alan DeKok.
- List info/subscribe/unsubscribe? See http://www.freeradius.org/list/users.html
participants (2)
-
Alan DeKok -
blaster@vorsicht-bissig.de