requests which are proxied to a virtual server get ACCEPTED unconditionally! #596

Closed
restena-sw opened this Issue Apr 22, 2014 · 3 comments

Projects

None yet

2 participants

@restena-sw

As discussed earlier on the -devel mailing list, I have a persistent issue that requests get "Auth-Type Accept" even if passwords are wrong.

The issue occurs only if the request initially gets treated via one virtual server, and then proxied to the real one which is supposed to do the checks.

When a request directly gets dispatched to that second virtual server, all checks are done as expected; so it's not a configuration issue in that second virtual server per se.

I would attach a minimalistic "raddb" which produces the issue, but the tracker only accepts images? Available by PM.

Using an arbitrary wrong password (the hash with the real password is "testpass"), authenticate with radtest to 127.0.0.1: gets handled by default, proxied to staff, authenticates unconditionally. Authenticate with [::1], gets handled by staff, user gets rejected as planned.

I can reproduce this with a clean 3.0.2 compilation (using clang, if that really matters at all).

This problem really very significant!

Below are two radtest sessions for the scenario outlined above, plus the -X output on the server side.

Not sure if the following matters: even with the expected flow, I see that "Reject" is an unknown Post-Auth-Type? But that attribute value is read by the dictionary auto-loading magic just fine. Maybe an issue with the dictionary loader?

Here is radtest:

radius-int-test:/usr/local/freeradius/config/raddb # ../../current/bin/radtest swinter foo 127.0.0.1:1812 123 testing123
Sending Access-Request of id 242 from 0.0.0.0 port 54334 to 127.0.0.1 port 1812
User-Name = 'swinter'
User-Password = 'foo'
NAS-IP-Address = 158.64.2.225
NAS-Port = 123
Message-Authenticator = 0x00
rad_recv: Access-Accept packet from host 127.0.0.1 port 1812, id=242, length=20
radius-int-test:/usr/local/freeradius/config/raddb # ../../current/bin/radtest -6 swinter foo [::1]:1812 123 testing123
Sending Access-Request of id 215 from :: port 42306 to ::1 port 1812
User-Name = 'swinter'
User-Password = 'foo'
NAS-IPv6-Address = 2001:a18:1:6::225
NAS-Port = 123
Message-Authenticator = 0x00
rad_recv: Access-Reject packet from host ::1 port 1812, id=215, length=20
radius-int-test:/usr/local/freeradius/config/raddb #

And here is the -X output:

radius-int-test:/usr/local/freeradius # ./current/sbin/radiusd -X
radiusd: FreeRADIUS Version 3.0.2, for host x86_64-unknown-linux-gnu, built on Apr 22 2014 at 09:59:48
Copyright (C) 1999-2014 The FreeRADIUS server project and contributors
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE
You may redistribute copies of FreeRADIUS under the terms of the
GNU General Public License
For more information about these matters, see the file named COPYRIGHT
Starting - reading configuration files ...
including dictionary file /usr/local/freeradius/3.0.2-clang/share/freeradius/dictionary
including configuration file /usr/local/freeradius/config/raddb/radiusd.conf
including configuration file /usr/local/freeradius/config/raddb/proxy.conf
including configuration file /usr/local/freeradius/config/raddb/clients.conf
including files in directory /usr/local/freeradius/config/raddb/mods-enabled/
including configuration file /usr/local/freeradius/config/raddb/mods-enabled/suffix
including configuration file /usr/local/freeradius/config/raddb/mods-enabled/staff-auth
including configuration file /usr/local/freeradius/config/raddb/mods-enabled/mschap
including configuration file /usr/local/freeradius/config/raddb/mods-enabled/ok
including configuration file /usr/local/freeradius/config/raddb/mods-enabled/pap
including configuration file /usr/local/freeradius/config/raddb/mods-enabled/expr
including configuration file /usr/local/freeradius/config/raddb/mods-enabled/handled
including configuration file /usr/local/freeradius/config/raddb/mods-enabled/chap
including files in directory /usr/local/freeradius/config/raddb/sites-enabled/
including configuration file /usr/local/freeradius/config/raddb/sites-enabled/staff
including configuration file /usr/local/freeradius/config/raddb/sites-enabled/default
main {
security {
user = "radiusd"
group = "radiusd"
allow_core_dumps = yes
}
}
Core dumps are enabled.
main {
name = "radiusd"
prefix = "/usr/local/freeradius/current"
localstatedir = "/var"
sbindir = "/usr/local/freeradius/current/sbin"
logdir = "/var/log/radius"
run_dir = "/var/run/radiusd"
libdir = "/usr/local/freeradius/current/lib64"
radacctdir = "/var/log/radius/radacct"
panic_action = "gdb -silent -x /usr/local/freeradius/config/raddb/panic.gdb %e %p 2>&1 | tee /var/log/radius/gdb-radiusd-%p.log"
hostname_lookups = no
max_request_time = 30
cleanup_delay = 5
max_requests = 1024
pidfile = "/var/run/radiusd/radiusd.pid"
checkrad = "/usr/local/freeradius/current/sbin/checkrad"
debug_level = 0
proxy_requests = yes
log {
stripped_names = no
auth = no
auth_badpass = no
auth_goodpass = no
msg_denied = "You are already logged in - access denied"
}
security {
max_attributes = 200
reject_delay = 0
status_server = yes
}
}
radiusd: #### Loading Realms and Home Servers ####
proxy server {
retry_delay = 5
retry_count = 3
default_fallback = no
dead_time = 120
wake_all_if_all_dead = no
}
realm TO-STAFF {
nostrip
virtual_server = staff
}
realm NULL {
virtual_server = staff
}
radiusd: #### Loading Clients ####
client localhost4 {
ipaddr = 127.0.0.1
require_message_authenticator = no
secret = <<< secret >>>
shortname = "localhost"
limit {
max_connections = 16
lifetime = 0
idle_timeout = 30
}
}
client localhost6 {
ipv6addr = ::1 IPv6 address [::1]
require_message_authenticator = no
secret = <<< secret >>>
shortname = "localhost"
virtual_server = "staff"
limit {
max_connections = 16
lifetime = 0
idle_timeout = 30
}
}
radiusd: #### Instantiating modules ####
instantiate {

Loaded module rlm_expr

Instantiating module "expr" from file /usr/local/freeradius/config/raddb/mods-enabled/expr

expr {
safe_characters = "@abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.-_: /"
}
}
modules {

Loaded module rlm_realm

Instantiating module "suffix" from file /usr/local/freeradius/config/raddb/mods-enabled/suffix

realm suffix {
format = "suffix"
delimiter = "@"
ignore_default = no
ignore_null = no
}

Loaded module rlm_files

Instantiating module "staff-auth" from file /usr/local/freeradius/config/raddb/mods-enabled/staff-auth

files staff-auth {
usersfile = "/usr/local/freeradius/config/raddb/staff/auth"
acctusersfile = "/usr/local/freeradius/config/raddb/staff/auth"
preproxy_usersfile = "/usr/local/freeradius/config/raddb/staff/auth"
compat = "no"
}
reading pairlist file /usr/local/freeradius/config/raddb/staff/auth
reading pairlist file /usr/local/freeradius/config/raddb/staff/auth
reading pairlist file /usr/local/freeradius/config/raddb/staff/auth

Loaded module rlm_mschap

Instantiating module "mschap" from file /usr/local/freeradius/config/raddb/mods-enabled/mschap

mschap {
use_mppe = yes
require_encryption = yes
require_strong = yes
with_ntdomain_hack = yes
passchange {
}
allow_retry = yes
}

Loaded module rlm_always

Instantiating module "ok" from file /usr/local/freeradius/config/raddb/mods-enabled/ok

always ok {
rcode = "ok"
simulcount = 0
mpp = no
}

Loaded module rlm_pap

Instantiating module "pap" from file /usr/local/freeradius/config/raddb/mods-enabled/pap

pap {
auto_header = no
normalise = yes
}

Instantiating module "handled" from file /usr/local/freeradius/config/raddb/mods-enabled/handled

always handled {
rcode = "handled"
simulcount = 0
mpp = no
}

Loaded module rlm_chap

Instantiating module "chap" from file /usr/local/freeradius/config/raddb/mods-enabled/chap

} # modules
radiusd: #### Loading Virtual Servers ####
server { # from file /usr/local/freeradius/config/raddb/sites-enabled/default

Loading authorize {...}

} # server
server staff { # from file /usr/local/freeradius/config/raddb/sites-enabled/staff

Loading authenticate {...}

Loading authorize {...}

} # server staff
radiusd: #### Opening IP addresses and Ports ####
listen {
type = "auth"
ipv6addr = :: IPv6 address [::]
port = 1812
}
listen {
type = "acct"
ipv6addr = :: IPv6 address [::]
port = 1813
}
listen {
type = "auth"
ipaddr = *
port = 1812
}
listen {
type = "acct"
ipaddr = *
port = 1813
}
Listening on auth address :: port 1812
Listening on acct address :: port 1813
Listening on auth address * port 1812
Listening on acct address * port 1813
Opening new proxy socket 'proxy address * port 0'
Listening on proxy address * port 47952
Ready to process requests.
rad_recv: Access-Request packet from host 127.0.0.1 port 54334, id=242, length=77
User-Name = 'swinter'
User-Password = 'foo'
NAS-IP-Address = 158.64.2.225
NAS-Port = 123
Message-Authenticator = 0xc2e68ebc81b627b05f5c0c842cc8fc65
(0) # Executing section authorize from file /usr/local/freeradius/config/raddb/sites-enabled/default
(0) authorize {
(0) suffix : No '@' in User-Name = "swinter", looking up realm NULL
(0) suffix : Found realm "NULL"
(0) suffix : Adding Stripped-User-Name = "swinter"
(0) suffix : Adding Realm = "NULL"
(0) suffix : Proxying request from user swinter to realm NULL
(0) suffix : Preparing to proxy authentication request to realm "NULL"
(0) [suffix] = updated
(0) } # authorize = updated
Proxying to virtual server staff
(0) # Executing section authorize from file /usr/local/freeradius/config/raddb/sites-enabled/staff
(0) authorize {
(0) staff-auth : users: Matched entry swinter at line 1
(0) [staff-auth] = ok
(0) [mschap] = noop
(0) [pap] = noop
(0) } # authorize = ok
(0) Auth-Type = Accept, accepting the user
Sending Access-Accept of id 242 from 127.0.0.1 port 1812 to 127.0.0.1 port 54334
(0) Finished request 0.
Waking up in 0.3 seconds.
Waking up in 4.6 seconds.
(0) Cleaning up request packet ID 242 with timestamp +18
Ready to process requests.
rad_recv: Access-Request packet from host ::1 port 42306, id=215, length=89
User-Name = 'swinter'
User-Password = 'foo'
NAS-IPv6-Address = 2001:a18:1:6::225
NAS-Port = 123
Message-Authenticator = 0x90bd72be3812e4aef72841bc7d51f4cf
(1) # Executing section authorize from file /usr/local/freeradius/config/raddb/sites-enabled/staff
(1) authorize {
(1) staff-auth : users: Matched entry swinter at line 1
(1) [staff-auth] = ok
(1) [mschap] = noop
(1) pap : Normalizing NT-Password from hex encoding, 32 bytes -> 16 bytes
(1) [pap] = updated
(1) } # authorize = updated
(1) Found Auth-Type = PAP
(1) # Executing group from file /usr/local/freeradius/config/raddb/sites-enabled/staff
(1) Auth-Type PAP {
(1) pap : Login attempt with password
(1) pap : Comparing with "known-good" NT-Password
(1) pap : EXPAND foo
(1) pap : --> foo
(1) pap : NT-Hash of foo = ac8e657f83df82beea5d43bdaf7800cc
(1) pap : EXPAND %{mschap:NT-Hash %{User-Password}}
(1) pap : --> ac8e657f83df82beea5d43bdaf7800cc
(1) ERROR: pap : NT digest does not match "known good" digest
(1) pap : Passwords don't match
(1) [pap] = reject
(1) } # Auth-Type PAP = reject
(1) Failed to authenticate the user.
(1) Using Post-Auth-Type Reject
(1) WARNING: Unknown value specified for Post-Auth-Type. Cannot perform requested action.
Sending Access-Reject of id 215 from ::1 port 1812 to ::1 port 42306
(1) Finished request 1.
Waking up in 0.3 seconds.
Waking up in 4.6 seconds.
(1) Cleaning up request packet ID 215 with timestamp +30
Ready to process requests.

@alandekok
Member

I'll look at this on wednesday. Arran says he can reproduce it (sort of). He sees an infinite proxy loop

@restena-sw

Well, not what I see, but at least good to hear that something's confirmed wrong. If you check my earlier mails on -devel: I found via gdb "step" that the control items from before-proxy are still in the request structure when in the second virtual server. I guess if I had the "suffix" module enabled in the second server, I'd end up at the same perpetual proxying.

Makes me wonder: should the control list not be cleared when handing over a request to a new virtual server?

@alandekok
Member

OK... the issue appears to be that the request isn't proxied to the virtual server, it's sent directly to the virtual server without any changes.

The solution is to make a "fake" request, copy the request attributes to it, ensure that the config items are empty, and then run it through the virtual server. I'll take a look at this today

@alandekok alandekok added a commit that referenced this issue Apr 23, 2014
@alandekok alandekok Fix handling of proxying to virtual servers. Fixes #596
The downside is that there isn't really any parent/child
relationship between the real request and the fake one.
So if the fake one blocks for 60s, the real one will be told
to stop, and the fake one with happily continue.

We'll need a separate commit to fix that issue.
5008864
@alandekok alandekok added a commit that closed this issue Apr 23, 2014
@alandekok alandekok Fix handling of proxying to virtual servers. Fixes #596
The downside is that there isn't really any parent/child
relationship between the real request and the fake one.
So if the fake one blocks for 60s, the real one will be told
to stop, and the fake one with happily continue.

We'll need a separate commit to fix that issue.
b109849
@alandekok alandekok closed this in b109849 Apr 23, 2014
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment