rlm_perl changing User-Name and proxy requests
I have an issue with rlm_perl changing the request User-Name attribute but the proxy request not honoring it. First I'll describe what I'm trying to accomplish and why and then what I'm doing. I'm running a branch of 2.2.1 that has some krb5 realm fixes in it. I have multiple realms that users can authenticate against: our division has replayable password (handled by kerberos) and one time passwords (handled by both YubiKeys and Crypto Card), our lab has replayable passwords (handled by AD) and a separate one time password system (handled by Crypto Card). For services that we want to allow replayable passwords (like IMAP access for instance), we want to allow the user to choose which service to use (division or lab). For services requiring OTP we want the user to choose which OTP token they want to use (some people have multiple because of external requirements). We want users to be able to change these auth preferences on their own and not have this require changing the RADIUS configuration (a.k.a., the users file) to do this. Our account information is kept in LDAP. This is all well and good except that usernames between the division and the lab aren't guaranteed to match - User A might have lastname as their division name, but lastnamefirst as their lab username. For the kerberos and AD request the RADIUS server can handle the request directly using rlm_krb5, but for all the OTP requests the server must proxy to the correct OTP server to handle the request. Here's my plan for accomplishing this. During authorization, rlm_ldap is used to make sure if the user is in LDAP. If not the request is rejected outright (this should help with brute force attempts bogging down all the servers for bogus attempts). Next an rlm_perl module is called to get the user's preferred realm and what username to use in that realm from LDAP. An example would be leggett@ yubi.division.example.com (signifying that I want to use YubiKey from my division). The rlm_perl module updates the request User-Name to be this preference and Auth-Type to be System (see http://pastie.org/5670077). Lastly rlm_realm checks the request to determine if it should be proxied or not. The problem is this: Everything works if the username doesn't change. For instance, if I'm leggett@yubi.division.example.com and leggett@crypto.example.com, things work. The User-Name change being done by rlm_perl is being recognized by rlm_realm and rlm_realm is routing to the proper realm; however, rlm_realm seems to want to clobber User-Name in its own way, so that by the time proxying happens User-Name is set to whatever the initial username was - if I started the process as leggett and wanted my username to eventually be ti.leggett@crypto.example.com, by the time it reaches the proxy phase my User-Name attribute has been reset back to leggett even if I rerun the rlm_perl module after rlm_realm (see http://pastie.org/5670076) I notice that rlm_suffix doesn't overwrite the Stripped-User-Name rlm_perl adds, but appends another entry. This is fine for my purposes since the rlm_perl one is added first subsequent calls use that value. I'm afraid the same is happening with User-Name in that rlm_perl is appending another entry instead of overwriting the ones there. So is there any way around this or am I completely insane with this approach?
On 11 Jan 2013, at 19:58, Ti Leggett <leggett@mcs.anl.gov> wrote:
I have an issue with rlm_perl changing the request User-Name attribute but the proxy request not honoring it. First I'll describe what I'm trying to accomplish and why and then what I'm doing. I'm running a branch of 2.2.1 that has some krb5 realm fixes in it.
I have multiple realms that users can authenticate against: our division has replayable password (handled by kerberos) and one time passwords (handled by both YubiKeys and Crypto Card), our lab has replayable passwords (handled by AD) and a separate one time password system (handled by Crypto Card). For services that we want to allow replayable passwords (like IMAP access for instance), we want to allow the user to choose which service to use (division or lab). For services requiring OTP we want the user to choose which OTP token they want to use (some people have multiple because of external requirements). We want users to be able to change these auth preferences on their own and not have this require changing the RADIUS configuration (a.k.a., the users file) to do this. Our account information is kept in LDAP.
This is all well and good except that usernames between the division and the lab aren't guaranteed to match - User A might have lastname as their division name, but lastnamefirst as their lab username. For the kerberos and AD request the RADIUS server can handle the request directly using rlm_krb5, but for all the OTP requests the server must proxy to the correct OTP server to handle the request.
Here's my plan for accomplishing this.
During authorization, rlm_ldap is used to make sure if the user is in LDAP. If not the request is rejected outright (this should help with brute force attempts bogging down all the servers for bogus attempts).
Yeah it'll just bog down your LDAP server instead. You should use rlm_cache to cache the result of the LDAP lookup (once you have all this working)*. Have you added nostrip for all the realms? The only way I can see it clobbering username is if stripping is enabled. -Arran PS: You know you want to test the threaded version of the updated rlm_krb5 module :) * Only use the rlm_cache module from 2.2.1
On Jan 11, 2013, at 2:32 PM, Arran Cudbard-Bell <a.cudbardb@freeradius.org> wrote:
[snip]
Yeah it'll just bog down your LDAP server instead. You should use rlm_cache to cache the result of the LDAP lookup (once you have all this working)*.
Have you added nostrip for all the realms? The only way I can see it clobbering username is if stripping is enabled.
So that was my first thought too. However, I have limited visibility into the remote lab crypto server and when I sent a request to with a realm included, it flat out dropped the request. Didn't reply at all. So I need the realm to so the proxy portion can hit the right destination, but I need the User-Name stripped so the remote server can understand it.
-Arran
PS: You know you want to test the threaded version of the updated rlm_krb5 module :)
I do! Once I get this configuration working I'll be happy to try it. One of my todos for this whole config revamp is to stress test the environment against a brute force attack (we get them frequently). Then I'll have some before numbers to compare with the after.
* Only use the rlm_cache module from 2.2.1 - List info/subscribe/unsubscribe? See http://www.freeradius.org/list/users.html
On 01/11/2013 08:32 PM, Arran Cudbard-Bell wrote:
Have you added nostrip for all the realms? The only way I can see it clobbering username is if stripping is enabled.
Isn't the problem the special request->username attribute? AFAICT the pairmove code handles this specially ("fixup") but I'm not sure rlm_perl does the same? If that is the case, OP may find that putting the new username in an interim / temp variable then forcing update via unlang works: authorize { ... myperl update request { User-Name := "%{The-Var}" } ... } This is a WAG though...
On 11 Jan 2013, at 20:49, Phil Mayers <p.mayers@imperial.ac.uk> wrote:
On 01/11/2013 08:32 PM, Arran Cudbard-Bell wrote:
Have you added nostrip for all the realms? The only way I can see it clobbering username is if stripping is enabled.
Isn't the problem the special request->username attribute?
It is, request->username appears to be pointing to the original User-Name pair instead of the new perl one.
AFAICT the pairmove code handles this specially ("fixup") but I'm not sure rlm_perl does the same?
Yes, unfortunately. That would have been a nice simple fix. https://github.com/FreeRADIUS/freeradius-server/blob/v2.x.x/src/modules/rlm_... @leggett If you don't mind rebuilding the server, could you change: https://github.com/FreeRADIUS/freeradius-server/blob/v2.x.x/src/main/modcall... And add: RDEBUG("Cached username is \"%s\", list username is \"%s\"", request->username->vp_strvalue, pairfind(request->packet->vps, PW_USER_NAME)->vp_strvalue); Just after modcall_single() Run it in debug mode and you'll see exactly where the username isn't being updated. List username and cached username should always be in sync up until the call to suffix, at which point the cached username should be stripped of the realm.
If that is the case, OP may find that putting the new username in an interim / temp variable then forcing update via unlang works:
authorize { ... myperl update request { User-Name := "%{The-Var}" } ... }
Yeah it should do. That calls radius_pairmove which has the magic update cache logic in it too. -Arran
On Jan 11, 2013, at 3:21 PM, Arran Cudbard-Bell <a.cudbardb@freeradius.org> wrote:
@leggett
If you don't mind rebuilding the server, could you change:
https://github.com/FreeRADIUS/freeradius-server/blob/v2.x.x/src/main/modcall...
And add:
RDEBUG("Cached username is \"%s\", list username is \"%s\"", request->username->vp_strvalue, pairfind(request->packet->vps, PW_USER_NAME)->vp_strvalue);
Just after modcall_single()
Run it in debug mode and you'll see exactly where the username isn't being updated. List username and cached username should always be in sync up until the call to suffix, at which point the cached username should be stripped of the realm.
Ok. I'm flumoxed: +- entering group pre-proxy {...} [pre_proxy_log] expand: /var/log/radius/radacct/%{Client-IP-Address}/pre-proxy-detail-%Y%m%d -> /var/log/radius/radacct/192.168.1.1/pre-proxy-detail-20130111 [pre_proxy_log] /var/log/radius/radacct/%{Client-IP-Address}/pre-proxy-detail-%Y%m%d expands to /var/log/radius/radacct/192.168.1.1/pre-proxy-detail-20130111 [pre_proxy_log] expand: %t -> Fri Jan 11 15:38:05 2013 Cached username is "ti.leggett", list username is "ti.leggett@crypto.example.com" ++[pre_proxy_log] returns ok Sending Access-Request of id 217 to 192.168.1.2 port 1812 NAS-Port-Type = Virtual Service-Type = Authenticate-Only Calling-Station-Id = "host.division.example.com" User-Name = "leggett" User-Password = "password" NAS-Identifier = "sshd" NAS-IP-Address = 192.168.1.1 NAS-Port = 9975 Proxy-State = 0x3831
hi, dont play with User-Name, update/modify Stripped-User-Name instead and use that in the authn/authz stages alan
On Jan 11, 2013, at 2:35 PM, A.L.M.Buxey@lboro.ac.uk wrote:
hi,
dont play with User-Name, update/modify Stripped-User-Name instead and use that in the authn/authz stages
How do I get the remote servers I'm proxying for to understand Stripped-User-Name. As far as I can tell Stripped-User-Name isn't even in the Access-Request to the proxyied server.
alan - List info/subscribe/unsubscribe? See http://www.freeradius.org/list/users.html
Hi,
How do I get the remote servers I'm proxying for to understand Stripped-User-Name. As far as I can tell Stripped-User-Name isn't even in the Access-Request to the proxyied server.
ah, missed the proxy bit. as Phil says, use a temp value and then set User-Name to that just before the proxying occurs (using unlang) - but beware that particular authentication methods dont like User-Name to have changed (thinking some EAP clients) - so this may cause issues in the future or be the cause of issues you are facing. alan
On 11 Jan 2013, at 20:51, Ti Leggett <leggett@mcs.anl.gov> wrote:
On Jan 11, 2013, at 2:35 PM, A.L.M.Buxey@lboro.ac.uk wrote:
hi,
dont play with User-Name, update/modify Stripped-User-Name instead and use that in the authn/authz stages
How do I get the remote servers I'm proxying for to understand Stripped-User-Name. As far as I can tell Stripped-User-Name isn't even in the Access-Request to the proxyied server.
It's not, it's an internal attribute which doesn't get copied into the proxy request. In pre-proxy you can add update proxy-request { User-Name := "%{%{Stripped-User-Name}:-%{User-Name}}" } Which will fix the issue. Where is that User-Name value in the proxy request coming from, is it the one from the original request? Could you include more debug output? -Arran
participants (4)
-
A.L.M.Buxey@lboro.ac.uk -
Arran Cudbard-Bell -
Phil Mayers -
Ti Leggett