Subject: [Emu] Appropriate AAA/EAP response to a peer's NAK when there are no overlapping methods

From: Terry Burton <[email-masked]>
Date: Thu, 20 Aug 2020 01:39:08 +0100

Hi,

I'm unable to find the authoritative source that state exactly how the
following conversation continues (TL;DR; the peer NAKs the original
method and the AAA doesn't support any of the peer's proposals):

1. NAS --> Peer : EAP-Request / Identity
2. Peer --> NAS : EAP-Response / Identity ( ID )
3. NAS --> AAA: RADIUS Access-Request / EAP-Message / EAP-Response /
Identity ( ID )
4. AAA --> NAS:  RADIUS Access-Challenge / EAP-Message / EAP-Request /
Method Foo
5. NAS --> Peer: EAP-Request / Method Foo
6. Peer --> NAK: EAP-Response / EAP-Type=NAK (Methods [Bar])
7. NAS --> AAA: RADIUS Access-Request / EAP-Message / EAP-Response /
NAK ( Methods [ Bar ] )
(* Let's assume that the AAA does not support Method Bar so we have
derived that there are no overlapping methods.)
8. AAA: Now what?

I've reviewed RFC 3748 (EAP) and RFC 3579 (RADIUS Support For EAP) and
neither seems to be explicit about what the AAA should do in response
to a NAK in the event of no overlapping methods.

In practise:

* FreeRADIUS sends RADIUS Access-Reject / EAP-Message / EAP-Failure.
* hostapd's RADIUS server sends RADIUS Access-Reject / EAP-Message /
EAP-Failure.
* A commercial RADIUS server implementation sends nothing.

It seems right to indicate an EAP-Failure to the peer in the case of
no overlapping methods (as well as to terminate the NAS's outstanding
RADIUS Access-Request with an Access-Reject), as is the case for a
number of other failure conditions, e.g. authentication failure
*within* an EAP method (Appendix A by way of example), invalid packets
leading to a fatal error within an EAP method (section 2.2).

RFC 3748 section 4.2 on Success and Failure introduces these messages
within the context of finalising an ongoing EAP method:

   The Success packet is sent by the authenticator to the peer after
   completion of an EAP authentication method (Type 4 or greater) to
   indicate that the peer has authenticated successfully to the
   authenticator.  The authenticator MUST transmit an EAP packet with
   the Code field set to 3 (Success).  If the authenticator cannot
   authenticate the peer (unacceptable Responses to one or more
   Requests), then after unsuccessful completion of the EAP method in
   progress, the implementation MUST transmit an EAP packet with the
   Code field set to 4 (Failure).

Perhaps one can argue that a NAK is an unacceptable response to an
ongoing method and therefore the method is unsuccessfully completed so
a Failure should be generated? That's not entirely clear, if that is
the case.

RFC 3748 section 5.3.1 throws in some more doubt, having the following
text that deals explicitly with the peer sending a NAK containing "no
desired alternative" method:

      Type zero (0) is used to indicate that the sender has
      no viable alternatives, and therefore the authenticator SHOULD NOT
      send another Request after receiving a Nak Response containing a
      zero value.

That's specific to one case for which a strict reading would indicate
that the EAP server should remain quiet and consider the EAP
conversation to be complete. It's tempting to think that the same
response (i,e. no response!) should apply more broadly as none of the
AAA implementations I've tested actually differentiate between a NAK
with no desired alternative method vs a NAK with an incompatible list
of alternative methods. (A subtle difference might be relevant: In the
case of NAK / method = [] the peer knows that the EAP conversion can
go no further, whereas in the case that it sends a list of methods
that the AAA happens to not support it does not know this unless it is
subsequently told.)

If I've not missed something then this looks an omission (or lack of
clarity) and the intended AAA response to no overlapping methods (and
indeed "no desired alternative") should be decided and codified.

Thanks,

Terry

---

From: Alan DeKok <[email-masked]>
Date: Wed, 19 Aug 2020 21:42:52 -0400

On Aug 19, 2020, at 8:39 PM, Terry Burton <[email-masked]> wrote:
> ...

  Run around screaming?  It's at least not forbidden by the RFCs.  :(

> to a NAK in the event of no overlapping methods.

  Those specs were written 15+ years ago, when the IETF reviews were a lot less stringent about corner cases.

  RFC 3579 Section 2.1 says:

   Where the initial EAP-Request sent by the NAS is for an
   authentication Type (4 or greater), the peer MAY respond with a Nak
   indicating that it would prefer another authentication method that is
   not implemented locally.  

  I suspect the "not" here is wrong, and the text should say:

   ... it would prefer another authentication method that is implemented locally.  

  The text finishes with:

   ... is possible for the RADIUS server to choose
   an unacceptable method, and for the peer to respond with another Nak.

  And... what then?  There's no suggestion that this NAK exchange should stop after N rounds, and there's no suggestion for how to handle no overlapping methods.

  In short, "here be dragons".

> * FreeRADIUS sends RADIUS Access-Reject / EAP-Message / EAP-Failure.

  We treat "no overlapping methods" as similar to other protocol errors.  For example:

* NAK Type-Data with no contents (forbidden by RFC 3748 Section 5.3.1)

* NAK Type-Data of 0, which indicates "no proposed alternative".  We'll not that RFC 3748 Section 5.3.1 doesn't say what to do here.

* NAK Type-data of 1..3, which is also forbidden by Section 5.3.1

  All of these situations result in RADIUS Access-Reject / EAP-Message / EAP-Failure.

  One reason for choosing this response is that it is a *positive* acknowledgement that the EAP session has failed.  This behaviour seems better than dropping the packet on the floor.  If that happened, the NAS would be unable to distinguish "RADIUS server down" from "EAP protocol failure".

  RFC 3579 Section 2.2. "Invalid Packets" would seem to be applicable here:

   Since EAP method fields (Type, Type-Data) are typically not validated
   by a NAS operating as a pass-through, despite these checks it is
   possible for a NAS to forward an invalid EAP packet to or from the
   RADIUS server.  A RADIUS server receiving EAP-Message attribute(s) it
   does not understand SHOULD make the determination of whether the
   error is fatal or non-fatal based on the EAP Type.  A RADIUS server
   determining that a fatal error has occurred MUST send an
   Access-Reject containing an EAP-Message attribute encapsulating
   EAP-Failure.

  I would suggest that protocol failures are "fatal errors" as per this text, and MUST therefore result in Access-Reject / EAP-Message / EAP-Failure.  At least, where RADIUS is concerned.

> * hostapd's RADIUS server sends RADIUS Access-Reject / EAP-Message /

  I haven't delved into hostap's implementation, but I suspect that they made the same choices we did in FreeRADIUS, for similar reasons.

> * A commercial RADIUS server implementation sends nothing.

  That seems bad.

> leading to a fatal error within an EAP method (section 2.2).

  Yes.  I would argue that inability to agree on what to do is a protocol failure, and should result in an explicit failure signal.

> a Failure should be generated? That's not entirely clear, if that is

  NAK is a reasonable response to the *first* packet coming from a server.   RFC 3748 Section 2.1 forbids NAKs which occur later in the authentication sequence:

   A peer MUST NOT send a Nak (legacy or expanded) in reply to a Request
   after an initial non-Nak Response has been sent.  Since spoofed EAP
   Request packets may be sent by an attacker, an authenticator
   receiving an unexpected Nak SHOULD discard it and log the event.

 I would argue that discarding packets is wrong in the context of AAA.  The NAS needs a positive acknowledgement that the EAP session has been torn down, and that the RADIUS server is still alive.

  So the correct response would be Access-Reject / EAP-Message / EAP-Failure

> conversation to be complete.

  I would argue that it's OK to send EAP-Failure here.  EAP-Failure is Code 4, whereas Request is Code 1.

  The above text reads as forbidding *ongoing* EAP conversations after a failure to negotiate a mutually acceptable method.  But sending Success or Failure would seem to be OK.

  I would then suggest that the text SHOULD say:

     Type zero (0) is used to indicate that the sender has
     no viable alternatives, and therefore the authenticator MUST
     send a Failure packet after receiving a Nak Response containing a
     zero value.

> It's tempting to think that the same

  I agree.  Protocol failures or negotiation failures MUST result in EAP Failure being sent.

> indeed "no desired alternative") should be decided and codified.

  Implementations have largely decided on a mutually acceptable set of behaviour.  This works in practice.

  That point is not to be taken lightly.  A different set of behaviours may cause network instabilities, etc.  And a response of "our implementation is compatible with the RFCs" is not appropriate when that behaviour is causing problems for others.

  I would agree with at the minimum technical errata being reported for RFC 3748 and/or RFC 3579.  I'm not sure that updated documents are required, though.

  Alan DeKok.

---

From: Mohit Sethi M <[email-masked]>
Date: Thu, 20 Aug 2020 09:00:35 +0000

Hi Terry,

I surely must be missing something here:

Packet 6 is an EAP-Response from the peer. Packet 7 contains another EAP-Response inside a RADIUS Access-Request? That doesn't make sense. EAP is lock-step request-response protocol. The conversation you describe is incorrect.

My reading of RFC 3748 is clear that after receiving a NAK from the peer, the server should send another EAP-Request with a different EAP method if its policy allows or then send a failure. The server should also send a failure if the peer NAK Type-Data was 0 (indicating no proposed alternative).

FYI: RFC 4137 says:

   o  Sending a NAK to the authenticator after the authenticator first
      proposes an EAP authentication method to the peer.  When the
      methodState variable has the value PROPOSED, the authenticator is
      obliged to process a NAK that is received in response to its first
      packet of an EAP authentication method.

so the commercial RADIUS server is in violation if it doesn't respond to a NAK from the peer with either another EAP-Request or failure.

--Mohit

On 8/20/20 3:39 AM, Terry Burton wrote:

Hi,

In practise:

Thanks,

Terry

_______________________________________________
Emu mailing list
[email-masked]<mailto:[email-masked]>
https://www.ietf.org/mailman/listinfo/emu

---

From: Terry Burton <[email-masked]>
Date: Thu, 20 Aug 2020 13:02:37 +0100

Hi,

Maybe you were thrown by my typo (to make sure readers were awake). It
should have read "6. Peer --> NAS", i.e.:

6. Peer --> NAS: EAP-Response / EAP-Type=NAK (Methods [Bar])
7. NAS --> AAA: RADIUS Access-Request / EAP-Message / EAP-Response /
NAK ( Methods [ Bar ] )

Packet 7 is just the NAS encapsulating the Peer's NAK within RADIUS
for the AAA, not a separately originating request. The language is the
same as the fourth example in RFC 3579 Appendix A, however that
example skips the identity phase and goes on to successfully negotiate
a method.

> My reading of RFC 3748 is clear that after receiving a NAK from the peer, the server should send another EAP-Request with a different EAP method if its policy allows or then send a failure. The ser…

I'm still not seeing a clear reference for what to send in the event
of no overlapping methods from the text in these RFCs.

> so the commercial RADIUS server is in violation if it doesn't respond to a NAK from the peer with either another EAP-Request or failure.

That's relevant in the sense that it restates that it is appropriate
for a peer to NAK the server's original method selection and that the
server must process the NAK. It doesn't state what happens on the wire
(specifically that an EAP-Failure is sent to the peer, as seems to be
the case in practise) as a result of this processing.

It's also contrary to...

>       send another Request after receiving a Nak Response containing a

... unless the language is loose and we say that an EAP-Failure
request isn't actually a "Request", but that's hard to argue due to
capital "R"equest.

Nevertheless, RFC 4137 Appendix A.2. and A.3. is clear on what to do:

* When the peer sends a NAK with no alternatives we are in RECEIVED.
* In RECEIVED: respMethod == NAK therefore we transition to NAK.
* In NAK: We update the policy to exclude the NAKed method and
transition to SELECT_ACTION.
* In SELECT_ACTION: the result of Policy.getDecision() is presumably
FAILURE for no overlapping methods. Transition to FAILURE.
* In FAILURE: We build a failure response.

I note that both receiving a NAK (RECEIVED -> NAK -> SELECT_ACTION ->
FAILURE transition) and receiving an unacceptable method response
(RECEIVED -> INTEGRITY_CHECK -> METHOD_RESPONSE -> SELECT_ACTION
transition) ultimately arrive at the same FAILURE state that builds a
EAP-Failure packet. It appears that the agreed upon behaviour is
codified here.

Its behaviour also does not differentiate between a peer NAK of "type
0" and one containing a list of alternative methods.

Terry

---

From: Mohit Sethi M <[email-masked]>
Date: Thu, 20 Aug 2020 12:34:17 +0000

Hi Terry,

On 8/20/20 3:02 PM, Terry Burton wrote:

On Thu, 20 Aug 2020 at 10:00, Mohit Sethi M
<mohit.m.sethi=[email-masked]><mailto:mohit.m.sethi=[email-masked]> wrote:

Hi,

Indeed. I misread the packet sequence to imply that the server was sending an EAP-Response (which is why I had a disclaimer at the beginning :)).

FYI: RFC 4137 says:

It's also contrary to...

.... unless the language is loose and we say that an EAP-Failure
request isn't actually a "Request", but that's hard to argue due to
capital "R"equest.

Why is EAP-Failure a request? It's an EAP packet with a different Code? So the SHOULD NOT doesn't forbid the server from sending an EAP-Failure. RFC 3748 even calls Failure as a response: "An authenticator MAY wish to issue multiple Requests before sending a Failure response in order to allow for human typing mistakes."

This seems to be the correct behavior (at least for me).

--Mohit

Terry

Hi,

In practise:

Thanks,

Terry

---

From: Oleg Pekar <[email-masked]>
Date: Thu, 20 Aug 2020 16:07:27 +0300

Hi Terry

EAP-Failure.
>* A commercial RADIUS server implementation sends nothing.

Cisco Identity Services Engine RADIUS also returns  RADIUS
Access-Reject / EAP-Message / EAP-Failure in this case.

Not sure that if AAA server will send a list of his allowed protocols
in reply to NAK - the EAP client would be able to use it. Usually
credentials are configured per protocol and not always
interchangeable. So if the client wants EAP-GTC as an inner method in
PEAP and claims this in an inner EAP NAK message and the server will
reply that it has EAP-MSCHAPv2 and EAP-TLS inner methods - client can
be unable to leverage this info.

-Oleg

On Thu, Aug 20, 2020 at 3:39 AM Terry Burton <[email-masked]> wrote:
> [email-masked]

---

From: Terry Burton <[email-masked]>
Date: Thu, 20 Aug 2020 14:26:36 +0100

On Thu, 20 Aug 2020 at 13:34, Mohit Sethi M
<mohit.m.sethi=[email-masked]> wrote:
<...snip...>
> Why is EAP-Failure a request? It's an EAP packet with a different Code? So the SHOULD NOT doesn't forbid the server from sending an EAP-Failure. RFC 3748 even calls Failure as a response: "An authe…

That's a small "r"esponse and I'd dare to say that even that usage
isn't particularly helpful! :-)

I think it's well established that any message from the authenticator
to the peer (Code = 1) is an "R"equest and that any message from the
peer to the authenticator (Code = 2) is an EAP "R"esponse. NAK is just
a "Type" of Request / Response (depending on direction). So when the
above text mentions "R"equest it actually refers to EAP packets with
Code = 1, i.e. it says (seemingly erroneously as Alan points out) that
no further messages of any type should be sent from the authenticator
to the peer within the conversation.

---

From: Mohit Sethi M <[email-masked]>
Date: Thu, 20 Aug 2020 13:54:02 +0000

Hi Terry,

It would be a misinterpretation to say that everything from the 
authenticator is an EAP-Request hence EAP-Failure is also a Request. 
It's an EAP packet with a different Code. Thus, it is wrong to say that 
text "the authenticator SHOULD NOT send another Request" also implies 
that the authenticator SHOULD NOT send an EAP-Failure.

Also, Section 5 of RFC 3748 says that NAK is response only. So I don't 
understand what you mean by 'NAK is just a "Type" of Request / Response 
(depending on direction)'. NAKs are only sent by the peer to the 
authenticator/server. Sending a NAK in the other direction would be a 
violation of RFC 3748 and is not supported or implemented.

--Mohit

---

From: Terry Burton <[email-masked]>
Date: Thu, 20 Aug 2020 15:41:55 +0100

> that the authenticator SHOULD NOT send an EAP-Failure.

You're right. Thanks.

> violation of RFC 3748 and is not supported or implemented.

I was probably thrown because RFC 3579 section 2.6.2 on Role Reversal has this:

   Since EAP is a peer-to-peer protocol, an independent and simultaneous
   authentication may take place in the reverse direction.  Both peers
   may act as authenticators and authenticatees at the same time.

   However, role reversal is not supported by this specification.  A
   RADIUS server MUST respond to an Access-Request encapsulating an
   EAP-Request with an Access-Reject.  In order to avoid retransmissions
   by the peer, the Access-Reject SHOULD include an EAP-Response/Nak
   packet indicating no preferred method, encapsulated within
   EAP-Message attribute(s).

Notionally that's an "EAP-Response/NAK" sent in the "wrong" direction:
AAA --> NAS --> Peer

However I believe that this is considering the case where the peer
contains an EAP server that is trying to initiate an authentication of
the NAS (not allowed), and therefore the AAA tells the peer to go
away.

---

From: Mohit Sethi M <[email-masked]>
Date: Fri, 21 Aug 2020 07:27:08 +0000

Hi Terry,

> the NAS (not allowed), and therefore the AAA tells the peer to go

Sorry for nitpicking here. But it is important to distinguish the two 
components that comprise a AAA server: RADIUS server and EAP server. RFC 
3579 briefly alludes to this difference and uses different terms for a 
RADIUS server and an EAP server. Sure, they will likely run on the same 
machine and are tightly integrated, yet they are independent components. 
The text you point to in RFC 3579 doesn't imply that the NAK is sent 
from the EAP server. It only says that to avoid retransmissions, a 
RADIUS server should generate an Access-Reject containing a 
EAP-Response/Nak on its own (without involving the EAP server). So 
technically, this NAK is still not sent by the EAP server in the 
so-called 'wrong direction'. In common realistic implementations, RADIUS 
servers only proxy data to/from the EAP server and do not generally 
inject EAP packets on their own. Which is why I suspect that this is not 
implemented in the radius server of hostap: 
https://w1.fi/cgit/hostap/tree/src/radius/radius_server.c#n1437

--Mohit

---

From: Alan DeKok <[email-masked]>
Date: Fri, 21 Aug 2020 08:50:07 -0400

> machine and are tightly integrated, yet they are independent components. 

  Some minor nit picking here...

  In practice, EAP servers are tightly coupled with RADIUS servers.  At least for ones which implement non-trivial EAP methods.

  But I agree that they need to be treated as independent components.

  FWIW, I've looked for EAP server implementations.  As best I can tell for Open Source, it's just hostap and FreeRADIUS.  Everything else is either dead, or implements only a tiny subset of EAP, such as EAP-MD5.

> servers only proxy data to/from the EAP server

  I'm wary of the word "proxy".  Proxying implies some kind of transport, as with RADIUS proxying.

  The public implementations of RADIUS+EAP  have the two components in the same process, using shared libraries.  The interaction between the two is just API calls.

> and do not generally 

  The RADIUS side of hostap doesn't inject the EAP Failure.  The underlying EAP implementation injects it.

  The eap_sm_Policy_getDecision() function returns failure if there are no compatible EAP methods.  The calling function then returns EAP Failure.

https://w1.fi/cgit/hostap/tree/src/eap_server/eap_server.c#n1722

  The EAP server implementation in FreeRADIUS also returns an EAP Failure packet  if there are no compatible EAP methods.

  The underlying principle here is that silently dropping packets is considered bad.  Therefore, no matter what happens inside of the EAP state machine, the outcome is one of 3 things:

* more EAP negotiation
* Success
* Failure

  The only time the RADIUS side injects an EAP Failure is if the session is rejected for administrative reasons.  And, the EAP state machine is bypassed.   e.g. deny this particular user on this particular device, even if their EAP credentials are OK.

   In that case, the EAP stack is bypassed.  The Access-Reject handler checks for an EAP-Message in the Access-Request.  If found, the RADIUS layer synthesizes an EAP Failure inside of an EAP-Message.

  Since hostap doesn't really have policies in it's RADIUS server implementation, it doesn't implement this check.

   Alan DeKok.

---

From: Mohit Sethi M <[email-masked]>
Date: Sun, 23 Aug 2020 13:48:48 +0000

Hi Alan,

>    But I agree that they need to be treated as independent components.
Not sure what you are nit picking. Because you essentially agree that 
they are independent components yet tightly integrated in most 
implementations.
>    FWIW, I've looked for EAP server implementations.  As best I can tell for Open Source, it's just hostap and FreeRADIUS.  Everything else is either dead, or implements only a tiny subset of EAP,…
I bow to you and Jouni for all the hard work in maintaining these 
excellent pieces of software.
>    Since hostap doesn't really have policies in it's RADIUS server implementation, it doesn't implement this check.

Sorry, but you are missing context here. The discussion was no longer 
about sending an EAP failure when no suitable EAP methods are available. 
Terry and I were discussing the direction of NAK messages in an EAP 
conversation. I highlighted that a NAK is only sent by the peer to the 
server (and not in the reverse direction). To this, Terry pointed to the 

>      EAP-Message attribute(s).
It may seem from this text that a NAK is sent in the reverse direction 
(i.e. from server to peer). But I was pointing to Terry that this NAK is 
sent by the RADIUS server (and not the EAP server). So the fact that NAK 
messages are sent by the EAP peer only still holds true. This protection 
against retransmissions is not implemented in hostap ( as you can see in 
https://w1.fi/cgit/hostap/tree/src/radius/radius_server.c#n1437) or 
FreeRADIUS. I suspect because deployments don't encounter this kind of 
role reversal in practice.

--Mohit

---

From: Alan DeKok <[email-masked]>
Date: Sun, 23 Aug 2020 12:12:29 -0400

> following text in RFC 3579 Section 2.6.2 titled "Role Reversal":

  Ok.

>>     EAP-Message attribute(s).

  FreeRADIUS allows EAP-Request, largely for LEAP.  Tho TBH that should probably be deleted.

> role reversal in practice.

  Yes, I haven't seen EAP -Request sent to RADIUS servers, other than for LEAP.

  I'm not sure what you mean by "protection against retransmissions" though.

  Alan DeKok.

---

From: Mohit Sethi M <[email-masked]>
Date: Sun, 23 Aug 2020 16:52:51 +0000

Hi again,

>    I'm not sure what you mean by "protection against retransmissions" though.

Well. I am referring to the text from the RFC 3579: "In order to avoid 
retransmissions by the peer, the Access-Reject SHOULD include an 
EAP-Response/Nak packet indicating no preferred method, encapsulated 
within EAP-Message attribute(s)." It is clear that hostap does not (yet) 
implement this SHOULD. I suspect that FreeRADIUS doesn't either. Maybe 
that's because it needs to allow role reversal (i.e. peer sending an 
EAP-Request) for LEAP?

--Mohit

---

From: Alan DeKok <[email-masked]>
Date: Sun, 23 Aug 2020 16:50:32 -0400

On Aug 23, 2020, at 12:52 PM, Mohit Sethi M <[email-masked]> wrote:
> within EAP-Message attribute(s)."

  Ah, OK.

> It is clear that hostap does not (yet) 

  Yes.

  TBH, it's 2020.  I'll just go delete support for LEAP.  There's just no reason to allow it to be used.

  I'll also add the NAK in the access-Reject as per RFC 3579.

  Alan DeKok.