[awful patch] "Multiple levels of TLS nesting is invalid."
So saith FreeRADIUS 2.1.1, but I wasn't trying to do multiple levels of TLS nesting. I'm trying to use virtual servers so that a single radiusd can terminate TTLS/PEAP for multiple subrealms, _and_ use the inner-tunnel trick, keeping the configs completely independent for each subrealm. This allows me to hook up different departments with different AAA infrastructures into one radius set-up for our eduroam service. My "default" server has a pair of listen{} blocks, and little else: authorize { suffix } authenticate { } So, rlm_realm finds my virtual servers in proxy.conf, eg: realm dcs.qmul.ac.uk { nostrip virtual_server = dcs } ..and "dcs" has its own EAP config, which references a virtual_server "dcs-inner" for the PEAP/TTLS innards, which has _its_ own EAP config. My problem is that eap.c (line 219), as called by "dcs-inner", notices the request has a grandparent, and assumes it's multiple layers of TLS nesting. Interestingly, the comment omits the magic word "TLS". I think perhaps that the virtual servers appear to count as layers. Anyway, this braindead patch makes it work for me: --- freeradius-server-2.1.1/src/modules/rlm_eap/eap.c.orig 2008-09-25 09:41:26.000000000 +0100 +++ freeradius-server-2.1.1/src/modules/rlm_eap/eap.c 2008-10-14 15:19:53.800553926 +0100 @@ -216,10 +216,13 @@ /* * Multiple levels of nesting are invalid. */ - if (handler->request->parent && handler->request->parent->parent) { - RDEBUG2("Multiple levels of TLS nesting is invalid."); + if (handler->request->parent && handler->request->parent->parent && handler->request->parent->parent->parent ) { + RDEBUG2("Multiple levels of TLS nesting is really invalid."); return EAP_INVALID; } + if (handler->request->parent && handler->request->parent->parent) { + RDEBUG2("Multiple levels of nesting is thought invalid, continuing anyway."); + } /* * Figure out what to do. ..and my "radiusd -X" output now looks like this: Found Auth-Type = dcs-inner-eap +- entering group authenticate {...} [dcs-inner-eap] Request found, released from the list [dcs-inner-eap] Multiple levels of nesting is thought invalid, continuing anyway. [dcs-inner-eap] EAP/mschapv2 [dcs-inner-eap] processing type mschapv2 [mschapv2] +- entering group MS-CHAP {...} [mschap] No Cleartext-Password configured. Cannot create LM-Password. [mschap] Found NT-Password [mschap] Told to do MS-CHAPv2 for username@dcs.qmul.ac.uk with NT-Password [mschap] adding MS-CHAPv2 MPPE keys ++[mschap] returns ok MSCHAP Success ++[dcs-inner-eap] returns handled So.. I hope this is useful. Do drop me a mail on- or off-list on <mb/freeradius@dcs.qmul.ac.uk>, if you want any further information or if I'm not being clear enough. Matt
hi, hmmm, something about that process and flow doesnt sound right at all. alan
Matt Bernstein wrote:
So saith FreeRADIUS 2.1.1, but I wasn't trying to do multiple levels of TLS nesting. I'm trying to use virtual servers so that a single radiusd can terminate TTLS/PEAP for multiple subrealms, _and_ use the inner-tunnel trick, keeping the configs completely independent for each subrealm.
If you have one server certificate for TTLS, you don't need this extra layer of nesting. The TTLS && PEAP modules will look for a *dynamic* definition of the virtual server for the inner-tunnel.
This allows me to hook up different departments with different AAA infrastructures into one radius set-up for our eduroam service.
My "default" server has a pair of listen{} blocks, and little else:
authorize { suffix
update control { Virtual-Server = "%{Realm}" }
..and "dcs" has its own EAP config, which references a virtual_server "dcs-inner" for the PEAP/TTLS innards, which has _its_ own EAP config.
That's... complicated.
My problem is that eap.c (line 219), as called by "dcs-inner", notices the request has a grandparent, and assumes it's multiple layers of TLS nesting. Interestingly, the comment omits the magic word "TLS". I think perhaps that the virtual servers appear to count as layers. Anyway, this braindead patch makes it work for me:
Which pretty much removes the limits on nested queries. I understand why you're doing this, but I'm not sure what the side effects are. Alan DeKok.
On Oct 15 Alan DeKok wrote:
Matt Bernstein wrote:
So saith FreeRADIUS 2.1.1, but I wasn't trying to do multiple levels of TLS nesting. I'm trying to use virtual servers so that a single radiusd can terminate TTLS/PEAP for multiple subrealms, _and_ use the inner-tunnel trick, keeping the configs completely independent for each subrealm.
If you have one server certificate for TTLS, you don't need this extra layer of nesting.
We will have multiple server certificates; our departments are rather independent here.
This allows me to hook up different departments with different AAA infrastructures into one radius set-up for our eduroam service.
My "default" server has a pair of listen{} blocks, and little else:
authorize { suffix
update control { Virtual-Server = "%{Realm}" }
What does this achieve? Does it avoid the first layer of proxying? My set-up is working without it, AFAICT: server default { +- entering group authorize {...} [suffix] Looking up realm "dcs.qmul.ac.uk" for User-Name = "username@dcs.qmul.ac.uk" [suffix] Found realm "dcs.qmul.ac.uk" [suffix] Adding Realm = "dcs.qmul.ac.uk" [suffix] Proxying request from user username to realm dcs.qmul.ac.uk [suffix] Preparing to proxy authentication request to realm "dcs.qmul.ac.uk" ++[suffix] returns updated } # server default
Sending proxied request internally to virtual server. server dcs { +- entering group authorize {...} [dcs-eap] EAP packet type response id 3 length 149
..etc..
..and "dcs" has its own EAP config, which references a virtual_server "dcs-inner" for the PEAP/TTLS innards, which has _its_ own EAP config.
That's... complicated.
A famous aphorism of Butler Lampson goes: All problems in computer science can be solved by another level of indirection... Kevlin Henney's corollary to this is, "...except for the problem of too many layers of indirection." (from <http://en.wikipedia.org/wiki/Abstraction_layer>) Maybe the inner eap config can be the same for the "inner" virtual servers, but the server{} blocks will necessarily be different. I'm trying to normalise it, rather than complicate it.
My problem is that eap.c (line 219), as called by "dcs-inner", notices the request has a grandparent, and assumes it's multiple layers of TLS nesting. Interestingly, the comment omits the magic word "TLS". I think perhaps that the virtual servers appear to count as layers. Anyway, this braindead patch makes it work for me:
Which pretty much removes the limits on nested queries. I understand
I agree; I put the great-grandparent check in there to catch runaway loops. I never said my fix was right.
why you're doing this, but I'm not sure what the side effects are.
Sure. If you're not, I haven't a prayer. ;) My guess is that the eap.c code predates the virtual servers, so when eap.c was written its assumption that the nesting must be TLS could well have been true, but today newer code-paths exist which weird hairy people expect to work.. I have run into another bug: if I instantiate rlm_ldap in my servers "dcs-inner" and "maths-inner", it seems to use the base DN for "maths-inner" (instantiated second) for queries from "dcs-inner". Am I just being too weird and hairy? Or should I use a separate radiusd and raddb for each subrealm, as is the case with my production FreeRADIUS 1.1 set-up? Cheers Matt
Matt Bernstein wrote:
We will have multiple server certificates; our departments are rather independent here.
Ugh. There's not really any good reason for this. If the departmental certs are signed by a university CA, then you can still get away with one server instance.
update control { Virtual-Server = "%{Realm}" }
What does this achieve?
What I said in my previous message: If you have one server certificate for TTLS, you don't need this extra layer of nesting. The TTLS && PEAP modules will look for a *dynamic* definition of the virtual server for the inner-tunnel.
Does it avoid the first layer of proxying?
It does what I said it does.
My set-up is working without it, AFAICT:
Yes, I did read your message. I did see the point where you said your configuration worked. Maybe I was trying to describe how you could acheive your goal *without* source code patches.
Maybe the inner eap config can be the same for the "inner" virtual servers, but the server{} blocks will necessarily be different.
Well, yes. That's the point of virtual servers.
I have run into another bug: if I instantiate rlm_ldap in my servers "dcs-inner" and "maths-inner", it seems to use the base DN for "maths-inner" (instantiated second) for queries from "dcs-inner".
As always, debug mode.
Am I just being too weird and hairy? Or should I use a separate radiusd and raddb for each subrealm, as is the case with my production FreeRADIUS 1.1 set-up?
It's a little complicated. Unnecessarily so, IMHO. Alan DeKok.
At 14:19 +0200 Alan DeKok wrote:
Matt Bernstein wrote:
We will have multiple server certificates; our departments are rather independent here.
Ugh. There's not really any good reason for this. If the departmental certs are signed by a university CA, then you can still get away with one server instance.
I'm not claiming there's no technical solution. On the other hand, our departments don't trust each other more in a political way. We don't really have a university PKI. For eduroam, it's arguable that you want your server cert as local to your user base as possible. Our Maths users have no reason to trust a server certificate issued by my department.
update control { Virtual-Server = "%{Realm}" }
What does this achieve?
What I said in my previous message:
If you have one server certificate for TTLS, you don't need this extra layer of nesting. The TTLS && PEAP modules will look for a *dynamic* definition of the virtual server for the inner-tunnel.
OK, thanks: sorry I didn't understand that before.
Does it avoid the first layer of proxying?
It does what I said it does.
OK, so without a single CA it doesn't help us.
My set-up is working without it, AFAICT:
Yes, I did read your message. I did see the point where you said your configuration worked. Maybe I was trying to describe how you could acheive your goal *without* source code patches.
OK. I think the only way to avoid carrying my filthy patch is to run multiple non-virtual servers.
Maybe the inner eap config can be the same for the "inner" virtual servers, but the server{} blocks will necessarily be different.
Well, yes. That's the point of virtual servers.
I have run into another bug: if I instantiate rlm_ldap in my servers "dcs-inner" and "maths-inner", it seems to use the base DN for "maths-inner" (instantiated second) for queries from "dcs-inner".
As always, debug mode.
Sorry--I'll start a new reply on this point.
Am I just being too weird and hairy? Or should I use a separate radiusd and raddb for each subrealm, as is the case with my production FreeRADIUS 1.1 set-up?
It's a little complicated. Unnecessarily so, IMHO.
I'm trying to allow different departments to use eduroam with whatever AAA backends they want without the bother of having to run a RADIUS server. My institution might be unusual in that there are multiple backends--even within our computing service--but the reasons behind this are not necessarily technical. I hope this makes where I'm coming from a little clearer. Matt
At 14:19 +0200 Alan DeKok wrote:
I have run into another bug: if I instantiate rlm_ldap in my servers "dcs-inner" and "maths-inner", it seems to use the base DN for "maths-inner" (instantiated second) for queries from "dcs-inner".
As always, debug mode.
By this point we've correctly walked from default -> dcs -> dcs-inner. But.. as dcs-inner invokes rlm_ldap, it's using the wrong ldap instance: server dcs-inner { +- entering group authorize {...} [dcs-inner-preprocess] hints: Matched DEFAULT at 1 ++[dcs-inner-preprocess] returns ok ++? if ("%{User-Name}" =~ /^([^@]*)(@([-[:alnum:].]+))?$/) expand: %{User-Name} -> mb ? Evaluating ("%{User-Name}" =~ /^([^@]*)(@([-[:alnum:].]+))?$/) -> TRUE ++? if ("%{User-Name}" =~ /^([^@]*)(@([-[:alnum:].]+))?$/) -> TRUE ++- entering if ("%{User-Name}" =~ /^([^@]*)(@([-[:alnum:].]+))?$/) {...} expand: %{1} -> mb +++[request] returns ok ++- if ("%{User-Name}" =~ /^([^@]*)(@([-[:alnum:].]+))?$/) returns ok [mschap] Found MS-CHAP attributes. Setting 'Auth-Type = mschap' ++[mschap] returns ok [dcs-inner-eap] No EAP-Message, not doing EAP ++[dcs-inner-eap] returns noop rlm_ldap: Entering ldap_groupcmp() [dcs-inner-files] expand: dc=maths,dc=qmul,dc=ac,dc=uk -> dc=maths,dc=qmul,dc=ac,dc=uk [dcs-inner-files] expand: (uid=%{Stripped-User-Name}) -> (uid=mb) rlm_ldap: ldap_get_conn: Checking Id: 0 rlm_ldap: ldap_get_conn: Got Id: 0 rlm_ldap: attempting LDAP reconnection rlm_ldap: (re)connect to ldapserver.maths.qmul.ac.uk:389, authentication 0 rlm_ldap: setting TLS Require Cert to never rlm_ldap: starting TLS rlm_ldap: bind as cn=radiusd,dc=maths,dc=qmul,dc=ac,dc=uk/xxxxxxxx to ldapserver.maths.qmul.ac.uk:389 rlm_ldap: waiting for bind result ... rlm_ldap: Bind was successful rlm_ldap: performing search in dc=maths,dc=qmul,dc=ac,dc=uk, with filter (uid=mb) rlm_ldap: object not found or got ambiguous search result rlm_ldap::ldap_groupcmp: search failed rlm_ldap: ldap_release_conn: Release Id: 0 My radius.conf includes: modules { $INCLUDE ${confdir}/modules/ $INCLUDE ${confdir}/dcs/modules.conf $INCLUDE ${confdir}/maths/modules.conf } instantiate { } $INCLUDE ${confdir}/dcs/server $INCLUDE ${confdir}/maths/server NB x/modules.conf includes x/inner/modules.conf and x/server includes x/inner/server for x in {dcs, maths}. The "server" files, modulo these includes, only contain server{} blocks. If I transpose the $INCLUDE ${confdir}/x/server lines, then it uses the dcs LDAP instance, AFAICT: server dcs-inner { +- entering group authorize {...} [dcs-inner-preprocess] hints: Matched DEFAULT at 1 ++[dcs-inner-preprocess] returns ok ++? if ("%{User-Name}" =~ /^([^@]*)(@([-[:alnum:].]+))?$/) expand: %{User-Name} -> mb ? Evaluating ("%{User-Name}" =~ /^([^@]*)(@([-[:alnum:].]+))?$/) -> TRUE ++? if ("%{User-Name}" =~ /^([^@]*)(@([-[:alnum:].]+))?$/) -> TRUE ++- entering if ("%{User-Name}" =~ /^([^@]*)(@([-[:alnum:].]+))?$/) {...} expand: %{1} -> mb +++[request] returns ok ++- if ("%{User-Name}" =~ /^([^@]*)(@([-[:alnum:].]+))?$/) returns ok [mschap] Found MS-CHAP attributes. Setting 'Auth-Type = mschap' ++[mschap] returns ok [dcs-inner-eap] No EAP-Message, not doing EAP ++[dcs-inner-eap] returns noop rlm_ldap: Entering ldap_groupcmp() [dcs-inner-files] expand: dc=dcs,dc=qmul,dc=ac,dc=uk -> dc=dcs,dc=qmul,dc=ac,dc=uk [dcs-inner-files] expand: %{Stripped-User-Name} -> mb [dcs-inner-files] expand: (uid=%{%{Stripped-User-Name}:-%{User-Name}}) -> (uid=mb) rlm_ldap: ldap_get_conn: Checking Id: 0 rlm_ldap: ldap_get_conn: Got Id: 0 rlm_ldap: attempting LDAP reconnection rlm_ldap: (re)connect to mortar.dcs.qmul.ac.uk:389, authentication 0 rlm_ldap: setting TLS CACert File to /etc/raddb/dcs/certs/DCS_CA_cert.pem rlm_ldap: setting TLS Require Cert to demand rlm_ldap: starting TLS rlm_ldap: bind as cn=radiusd,ou=Infrastructure,dc=dcs,dc=qmul,dc=ac,dc=uk/xxxxxxxxxx to mortar.dcs.qmul.ac.uk:389 rlm_ldap: waiting for bind result ... rlm_ldap: Bind was successful rlm_ldap: performing search in dc=dcs,dc=qmul,dc=ac,dc=uk, with filter (uid=mb) rlm_ldap: ldap_release_conn: Release Id: 0 ${confdir}/dcs/inner/server references ${confdir}/dcs/inner/ldap.common which contains identity = "cn=radiusd,ou=Infrastructure,dc=dcs,dc=qmul,dc=ac,dc=uk" basedn = "dc=dcs,dc=qmul,dc=ac,dc=uk" etc. whereas ${confdir}/maths/inner/server references ${confdir}/maths/inner/ldap.common which contains identity = "cn=radiusd,dc=maths,dc=qmul,dc=ac,dc=uk" basedn = "dc=maths,dc=qmul,dc=ac,dc=uk" and so on. I'm guessing that such parameters aren't scoped locally enough. HTH Matt
Matt Bernstein wrote:
By this point we've correctly walked from default -> dcs -> dcs-inner. But.. as dcs-inner invokes rlm_ldap, it's using the wrong ldap instance: ... rlm_ldap: Entering ldap_groupcmp() [dcs-inner-files] expand: dc=maths,dc=qmul,dc=ac,dc=uk -> dc=maths,dc=qmul,dc=ac,dc=uk [dcs-inner-files] expand: (uid=%{Stripped-User-Name}) -> (uid=mb)
Let me guess. You have "LDAP-Group" as a check item in the "dcs-inner-files" "users" file. You will need to use the LDAP *instance* name to direct the LDAP-Group comparison to the correct version of the LDAP module. e.g. "dcs-inner-ldap-LDAP-Group" Alan DeKok.
participants (3)
-
A.L.M.Buxey@lboro.ac.uk -
Alan DeKok -
Matt Bernstein