Subject: [eap] Re: Survey: handling of retransmissions

From: [email-masked] (Bernard Aboba)
Date: Wed, 1 Jan 2003 11:54:22 -0800 (PST)

It is common for early messages within an EAP method to not
contain a message integrity check, because a key has not yet
been negotiated.

This problem occurs in TLS [RFC2246], for which the solution
is to include all the handshake messages within the MIC included
in the Finished message. If we can assume that the EAP conversation
is available to a method (not clear), then this could work, although it
would not address the DoS issue.

I think what you are saying is that some EAP methods may wish to
process packets themselves (e.g. they want a "UDP" transport)
while others might want a reliable transport. This makes some
sense to me -- but I am still trying to figure out exactly what
transport service RFC 2284 had in mind, and what implementations do.

For example, RFC 2284bis talks about not passing duplicate
Requests to the EAP method in the case of a token card, so I
think that it supports duplicate elimination of a sort. However,
once the Response is sent it could be lost, and so the EAP Peer
EAP can receive the same Request again. In that case,
I think that RFC 2284 implies that the duplicate Request is
passed to the EAP method, which is presumed to have kept state
and therefore can resend the previous Response. If that is true,
then duplicate elimination is sometimes the responsibility of the
EAP layer (when a Response is pending) and sometimes not (when a
Response is not pending).

This is not the service that a reliable, non-duplicating
transport provides -- and protocols like TLS do assume that they
run over such a service.

If someone has a different reading of RFC 2284, please speak up.

On December 20, 2002 Henry Haverinen said this:

Hello,

EAP SIM and EAP AKA are examples of methods that can silently=20
discard EAP packets based on an incorrect ICV.=20

It is also conceivable that an EAP method could delay the
processing of some unprotected packet, say a method-specific
notification. If another packet with a correct ICV is received
during the delay, then the unprotected packet may be silently
discarded. If no other packets are received, the method may
decide to process the unprotected packet. This could also
happen in EAP SIM, where ICV can only be included once=20
keys have been derived, so in the very first packets there
is no ICV.

If we further consider EAP SIM as an example, the fact
that the very first packets are not MAC'd makes it easy
to spoof packets. Of course spoofing will later be detected,
but if only the first received packet is processed, then it is
quite easy to mount a DoS attack. So it makes me wonder if
some method implementations could process several copies of the=20
"same" packet and kind of "fork" separate states for each=20
processed packet. The spoofed states should later be detected
and removed, but if the valid packets were processed separately,=20
the authentication could still succeed.

Based on these examples, I'm inclined to think that the
EAP layer should simply pass all EAP packets of a certain
type to the appropriate method, and let the method
decide how to process the packets. The EAP layer should
not act as a "flip-flop" by keeping track of requests
and corresponding responses or by flushing the packet queue.
This would make the software interface between EAP layer
and methods simple while allowing sophisticated processing
of EAP packets.

I don't know about any implementations that would work like=20
this, so I didn't answer the survey below.

Regards,
Henry

---

From: [email-masked] (James Carlson)
Date: Thu, 2 Jan 2003 07:12:40 -0500

> transport service RFC 2284 had in mind, and what implementations do.

It seems to me that what you're talking about here is really an
internal design issue, and not an on-the-wire protocol issue.

> and therefore can resend the previous Response.

What's the difference?  Suppose the software that supports the
interface between EAP and the token card method is itself smart enough
to eliminate duplicates.  Wouldn't that solve the problem?  This looks
like software and programming interface design, not protocol.

Other than implementation bugs, is there any way that someone viewing
this conversation on the wire can tell if the duplicates were
eliminated within EAP or within the method?  If the answer is "no,"
then there's no protocol issue here.

> If someone has a different reading of RFC 2284, please speak up.

My reading of the original RFC is much simpler: the authenticator
sends a Request message.  It waits for a Response.  If there is none,
then it resends the Request or takes any other action that it deems
appropriate (trying a different method, disconnecting the session).

There is intentionally no discussion of the internal software design:
you can do the methods as a single piece of code with switches, as a
plug-in architecture, or as some O-O monstrosity.  As long as it sends
the right messages on the wire, the design issues involved in making
those differing implementation models work right is *NOT* a protocol
issue and thus not an appropriate IETF issue.

I don't see how internal software interfaces between EAP and its
methods make any difference to the protocol as viewed on the wire.
Or, more to the point: if you're not able to get the behavior on the
wire that the document for the method in use describes, then the
software design is bad, not the document.

-- 
James Carlson, Solaris Networking         <[email-masked]>
Sun Microsystems / 1 Network Drive         71.234W   Vox +1 781 442 2084
MS UBUR02-212 / Burlington MA 01803-2757   42.497N   Fax +1 781 442 1677

---

From: [email-masked] (Bernard Aboba)
Date: Thu, 2 Jan 2003 08:32:32 -0800 (PST)

> then there's no protocol issue here.

The definition of the EAP layer transport service impacts on-the-wire
behavior, as well as security.

As has been pointed out, there are protocols (such as TLS) that assume
a reliable duplicate-free transport. If they are not provided with this
service, then they may not function well -- and this will be reflected in
on-the-wire behavior.

Similarly, there may be EAP methods that prefer to do their own duplicate
elimination, such as those that consider MIC failures to be non-fatal.
If you take an implementation that does duplicate elimination in the EAP
layer, and one that does it in the method layer, and implement such a
method above it, you will not see the same on-the-wire behavior,
particularly in the case where a DoS attack is in progress.

---

From: [email-masked] (James Carlson)
Date: Thu, 2 Jan 2003 13:22:54 -0500

> behavior, as well as security.

I think one of the security issues you're referring to is the DoS
issue -- if the authenticatee is somehow proxying out handling of
Request messages (note that this isn't possible with RADIUS or
DIAMETER; not that this matters), then the implementation needs to be
smart enough to limit or eliminate the queue of messages that can
build up before a Response is generated by the proxy.

But how is that really visible to an EAP peer on the wire?  Here's the
behavior conjectured:

	Authenticator		Authenticatee
	Request #1	-->
				(goes out to lunch handling request)
	Request #2	-->	XXX dropped by flush
	Request #3	-->	XXX dropped by flush
			<--	back from lunch: Response #1
	(old id 1; drop)
	(timeout)
	Request #4	-->	...

Here's possible scenario (on a slow, error-prone link) that does *not*
include the behavior described in the draft (pardon the ASCII art;
it's hard to show time delays) and is yet indistinguishable:

	Authenticator		Authenticatee
	Request #1	-
	Request #2	-\
	Request #3	-\\__	Handle Request #1; send Response #1
			 \\__	Request #2 send Response #2
			 /\__	Request #3 send Response #3
	(old id 1; drop) //
	(old id 2; drop) X
	(id 3 lost in transit)
	(timeout)
	Request #4	-->	...

While I agree that, as an implementation issue, it's wise for an
implementation that finds processing EAP messages to be "expensive"
(for whatever local definition of 'expensive' implies) to discard as
much as possible rather than being slogged down by an unfriendly peer,
I disagree that these sorts of details are necessarily appropriate for
a document that describes a protocol, except perhaps as asides.

Part of the issue here is that it's not just what's theoretically
observable by someone who does not bother implementing the protocol as
defined, but what's materially important to the behavior given the
constraints of the protocol, which is why I ask how it matters.  Since
the behavior is defined in terms of Response ID numbers that must
*exactly* match the most recent Request ID number, any other responses
that happen just aren't material.  They MUST be discarded by any
reasonable implementation.  It is as if they never occur.

Note that the same thing happens for retransmit cases where the id
numbers are not changed -- any straggling duplicates are immaterial
because they won't match the latest Request ID number when they
finally arrive.  Anything else is an implementation bug.

> service, then they may not function well -- and this will be reflected in

Since RFC 2284's usage of ID numbers provides a duplicate-free
messaging mechanism, I don't see how that could be understood as
anything other than an implementation error.  If the algorithm chosen
can't handle duplicate messages, then the definition of the method for
EAP needs to address this.

Whether an EAP software module, when treated as a "transport,"
provides duplicate-free messaging or relies on the methods themselves
to detect and deal with duplicates as necessary still looks to me like
an internal software interface implementation issue.  Assuming the
implementation isn't flawed, how can a peer tell whether EAP itself
handled the duplicate or the EAP plug-in method did the job?  (If we
have to assume that the implementation is flawed to get here, then I
think that's enough reason to leave it out of the draft.  IETF
standards-track documents shouldn't be a tutorial on how to write
networking software.)

> particularly in the case where a DoS attack is in progress.

If you take link propagation delays into account, the whole issue
becomes indeterminate.  Since the previous Response may already be in
flight, there is *NO* way for the sender of a new EAP Request (or a
passive observer on the wire) to know whether the previous request has
actually completed.  There are several cases possible here:

	1.  The previous Request isn't done, and (per the draft) the
            new Request is discarded.  The authenticator sees the old
            Response alone.

	2.  The previous Request is already done, and the Response is
            somewhere in flight.  The old Response to the prior
            Request will eventually arrive, *and* the new Request will
            be dispatched and acted upon as well, and generate a
            Response.  If the old Request had the same ID (i.e., the
            new one is a retransmit), then the old Response satisfies
            the Request, and the new Response is discarded (wrong
            ID).  If the old request had a different ID, then the old
            Response is discarded (wrong ID), and the new one is used.

	3.  The previous Request is already done, and the Response is
            in flight.  The new Request itself can be lost due to
            transmission errors, and the new Response can be lost in
            the same way.  The effect is indistinguishable from (1).

Note that (2) is both legal and impermissible according to the current
language of the draft.  The draft can't outlaw physics -- propagation
delays will still happen -- but the draft asserts that queued messages
must be discarded.  Since the real input queue extends from the
receiving EAP implementation on one side back through the underlying
drivers, the wires, and up through the transmit logic on the sender's
side, the receiver can't actually do what's demanded.  It can only
approximate that behavior by flushing some nearby queues.

Where you can't actually tell the difference, and where the
differences are discarded by properly-implemented peers, I suggest
that these differences don't matter and ought not be specified.

---

From: [email-masked] (Bernard Aboba)
Date: Thu, 2 Jan 2003 12:48:31 -0800 (PST)

> Request messages

Actually, I think the DoS attack that people had in mind was one where the
attacker is sending bogus EAP messages, possibly cycling through the
Identifier space, until the right value is found. The bogus packets
have the correct CRC so they are processed by the link layer,
but might not have the right Code or Type. If the method includes a MIC,
it can be assumed that the bogus packets will fail the MIC check.

As an example, the attacker might send:

a. Forged EAP Success packets, hoping to convince the Peer to connect to a
rogue Authenticator, bypassing mutual authentication.
b. Forged EAP Failure packets, hoping to abort the conversation.
c. Forged EAP Requests of a different Type, hoping to abort the
conversation.
d. Forged EAP Requests or Responses which fail the MIC check.

The question is how Peers and Authenticators will react to these attacks.

> 			<--	back from lunch: Response #1

Are requests 2 and 3 retransmissions of 1? If so, then shouldn't the
Authenticatee's Response be processed? If not, then why is the
Authenticator sending a new Request rather than retransmitting?

> 			 /\__	Request #3 send Response #3

Yes, this can happen. The difference is that in the first case, there are
no duplicate Responses, but in the second case, there are (assuming that 2
and 3 are retransmissions of 1).

> a document that describes a protocol, except perhaps as asides.

That seems sensible, but what if you have a situation like this:

Authenticator                                   Authenticatee
Real Request: ID 22  ------->

Attacker:
Bogus Request: ID 22 --------->

Assume that both the bogus and real request have valid CRCs, but that the
bogus request fails a MIC check and the real request passes.

How does the Authenticatee behave? Some possibilities:

a. The Real Request is processed, and elicits a Response. The
Authenticatee then sees a Bogus Request with the same ID, and resends the
Response, even though the Bogus Request is different.

b. The Real Request is processed, and elicits a Response. The
Authenticatee then sees a Bogus Request with the same ID, and processes
the Request, which fails the MIC check. The Authenticatee then either
silently discards (if the method defines that) or aborts (EAP TLS).

> reasonable implementation.  It is as if they never occur.

Agreed.

> finally arrive.  Anything else is an implementation bug.

Agreed -- though I'm not sure that the document indicates this clearly
enough.

> messaging mechanism

Does it? It seems like it just provides for reliable delivery of *at least
one* copy of the message. The question is exactly how duplicates are
processed, and RFC 2284 doesn't seem clear on how that occurs.

> handled the duplicate or the EAP plug-in method did the job?

I don't think it can tell -- but the question is what the expected
behavior is, and whether a method will behave the same way if hosted on
every EAP implementation or not. If the method needs to be able to
handle duplicates, then that would be something that would be specified
in its design.

> but the draft asserts that queued messages
> must be discarded.

I think that we agree that the draft is wrong -- but the question is how
to fix it.

> that these differences don't matter and ought not be specified.

I think you are right about that.

---

From: [email-masked] (James Carlson)
Date: Thu, 2 Jan 2003 17:22:28 -0500

> it can be assumed that the bogus packets will fail the MIC check.

OK.  That's a different case, but I don't think it raises new issues.

In that case, there needs to be some sort of backdoor interface
between the EAP 'method' that computes the information necessary for
the MIC, and the EAP 'mechanism' that does the actual per-message
generation and checking.

> The question is how Peers and Authenticators will react to these attacks.

Assuming it's properly implemented, the system drops the bad
messages.  Whether they're dropped within an "EAP layer," a "method
interface," or even in some front-end processing mechanism sounds like
a local design issue to me.

> Are requests 2 and 3 retransmissions of 1?

Not in that illustration.

> If so, then shouldn't the

There's nothing in RFC 2284 to prohibit the authenticator from
deciding to switch authentication mechanisms for any reason.

However, if you feel more comfortable dealing with pure retransmits,
then here you go:

	Authenticator		Authenticatee
	Request #1	-->
				(goes out to lunch handling request)
	Request #1	-->	XXX dropped by flush
	Request #1	-->	XXX dropped by flush
			<--	back from lunch: Response #1
	Got response #1
	Request #2	-->	Send Response #2
	Got response #2

versus:

	Authenticator		Authenticatee
	Request #1	-->	Send Response #1
	Request #1	-->	Send Response #1
	Request #1	-->	Send Response #1
	Got response #1
	Request #2	-->	...
	Discard old #1
	Discard old #1
	Got response #2

Again, if you add in transmission delays, you can easily make these
two cases indistinguishable on the wire.

> and 3 are retransmissions of 1).

I think duplicate responses are indistinguishable from any other sort
of unwanted responses.  They don't match the current ID.  They're
junk.

> bogus request fails a MIC check and the real request passes.

It depends, I think, on how the MIC is defined to operate.  Since EAP
doesn't have a MIC on its own, I don't see how that's really an EAP
issue.

If the goal is to specify how all possible future MICs should work
with EAP, then I'd be inclined go with the 'silent discard' behavior
(despite what EAP TLS may say) since anything else will open fairly
obvious DoS vulnerabilities.

> silently discards (if the method defines that) or aborts (EAP TLS).

c. The Real Request is processed and elicits a Response.  The Bogus
   Request fails the MIC and is silently ignored.  No change in any
   authenticatee state is made.  No additional Response is generated.
   It didn't happen.

> processed, and RFC 2284 doesn't seem clear on how that occurs.

Perhaps that's the bit that needs to be made clear.  For canonical EAP
processing, once you receive a message with a given ID number, you're
done with that ID.  Move on.  Allocate a new ID for new messages.  Any
duplicates still in flight that may arrive must be dumped on the
floor.  (But see below.)

> every EAP implementation or not.

That's still an internal software design issue, and I'd really rather
see such issues handled in forums that are equipped to handle them in
an architecture-dependent way.  For UNIX systems, that would probably
be The Open Group.  For MS systems, I have no clue, and I'd prefer to
keep it that way.  ;-}

> If the method needs to be able to

If the definition of the method itself specifies special handling of
duplicates as part of the protocol, I think that's really pretty awful
and I'd argue against such a draft if I saw it, but I see no specific
reason to document it one way or the other in the base EAP
specification.  The requirement would still essentially be an internal
software design issue ("how do I access dups when I need to?"), not
something that's visible on the wire.  (Unless there's a wire I don't
know about between 'EAP itself' and 'the method' ...)

---

From: [email-masked] (John Vollbrecht)
Date: Thu, 02 Jan 2003 17:31:57 -0500

> > behavior, as well as security.

I agree with James Carlson's point here.  I think the on the wire protocol 
is not affected by how the flushing is done. This implies that the exact 
method for dealing with it should not be specified in the protocol.

On the other hand, there does seem to be a potential for DOS attacks, 
especially in 802.11 application, so the method of flushing can be 
important if equipment is to interwork well.  This implies to me that this 
could be a subject for an 802.11 recommended practices document.

I am curious to know if the retransmission method as originally described 
has been found to be problem for TLS - does anyone have any insight into 
that?

John

---

From: [email-masked] (Bernard Aboba)
Date: Thu, 2 Jan 2003 15:08:35 -0800 (PST)

> of unwanted responses.  They don't match the current ID.  They're

Is this always true? Once a Peer has sent a Response, until it receives a
new Request, the current ID is the same. So a retransmission will match
the current ID, no?

Similarly, when an Authenticator receives a Response, but has not yet sent
a Request, the current ID is the same. So if a duplicate Response arrives,
it will match the current ID, no?

> obvious DoS vulnerabilities.

I agree. The question is whether the correctly MIC'd frame would even be
delivered to the EAP method or not.

>    authenticatee state is made.  No additional Response is generated.

RFC 2284 Section 2.2.1 says:

"Additionally, the peer must be prepared to
silently discard received retransmissions while waiting for
user input."

I am assuming here that the Real Request was processed and elicited a
Response *before* the bogus Request was received. If the bogus Request
came in before the Response was sent, it will be silently discarded
without even a MIC check, right?

What if the bogus packet arrived first? The MIC check fails, so no
Response is sent. Is this "waiting for user input" so that the real packet
is discarded too? Or is it as though the Request never arrived, so that
the real packet is processed, and elicits a Response?

> duplicates still in flight that may arrive must be dumped on the

But Responses can be lost, which means that a Peer needs to respond to
retransmitted Requests, even if it has already seen a Request with that
ID. And as you noted, Requests (and Responses) can fail validation, in
which case it is like they never happened (silent discard).

---

From: [email-masked] (James Carlson)
Date: Fri, 3 Jan 2003 09:21:16 -0500

> new Request, the current ID is the same. So a retransmission will match

On the authenticatee, yes.  That's how received *Requests* are
handled.  I was talking about duplicate *Responses* above.

Once an implementation has sent a Request and until it finally
receives a Response for that Request, the current ID is the same.
Once the first (of any number) of Response messages has been received,
the transaction is done.  The current ID is no longer valid.  Any
additional Response copies that arrive are garbage to be discarded --
just as would be any Response messages that bear any invalid ID
number.

This is just standard programming practice, and isn't called out
specifically in the RFC.  However, there is this text:

2.2.1.  Request and Response

   Description

      The Request packet is sent by the authenticator to the peer.  Each
      Request has a type field which serves to indicate what is being
      requested.  The authenticator MUST transmit an EAP packet with the
      Code field set to 1 (Request).  Additional Request packets MUST be
      sent until a valid Response packet is received, or an optional
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
      retry counter expires.  Retransmitted Requests MUST be sent with
[...]

Thus, by implication, once the valid Response packet is received,
you're done.  You don't need to send Request messages anymore --
you've got the answer you wanted -- and you don't need to do anything
special with any duplicate Response messages that come in.

Here's a useful thought experiment.  The case that you seem to be
concerned about looks like this in action:

	Authenticator		Authenticatee
	Request #1 >--
	              \
	(timeout)      \
	Request #1 >--  ----->	Send Response #1
	              \    --<
	               \  /
	                -/--->  Send Response #1 (dup)
	Got rep #1 <-----  --<
                          /
	                 /
	Got dup!   <-----

The "Send Response #1 (dup)" part isn't a problem -- the authenticatee
can detect this easily (Request ID matches ID for last received
Request) and can send the last Response.  The "Got dup!" part on the
authenticator side is the only remaining question, and it's the one I
was addressing in my last message.

Suppose, instead, that the EAP implementation does what comes
naturally when that first reply comes in -- it generates a new
request.  In that case, the sequence looks like this:

	Authenticator		Authenticatee
	Request #1 >--
	              \
	(timeout)      \
	Request #1 >--  ----->	Send Response #1
	              \    --<
	               \  /
	                -/--->  Send Response #1 (dup)
	Got rep #1 <-----  --<
        Request #2 >--    /
	              \  /
	(not #2)   <---\-
	(drop)          ----->  Send Response #2

In this case, the duplicate is dropped because the ID number is
clearly wrong.  Note that both peers keep track of *only* the most
recent ID value in use.  The fact that #1 was once somehow valid in
the past is of absolutely no consequence once the authenticator sends
Request #2.  #1 is now junk, just as would be #5 or #240.

Since this is the 'normal' case -- the EAP authenticator progress is
basically clocked by the valid Response messages it receives -- it
makes a great deal of design sense to make sure that there are no
"special" cases.  That is to say, if the authenticator (for any
reason) has nothing more to say after a Response comes in, then it
should make sure that any additional Response copies of that same ID
are discarded as they would be ordinarily.  Doing otherwise creates a
strange corner case that need not exist and adds no benefit.

How you choose to do this in implementation is your business.  One way
to do it would be to increment the ID number variable when you receive
a valid Response to an outstanding Request, rather than when an
"initial" Request is generated.  Another way would be to set a
"waiting for Response" flag when sending Request, and clearing that
flag when a valid Response is seen.  If a Response is received when
the flag isn't set, then that Response is discarded without looking
further.

Not surprisingly (given EAP's pedigree), this is the same logic as
employed by RFC 1661 PPP.  The Configure-Request (section 5.1)
description has this somewhat clearer description of how to set an
identifier:

   Identifier

      The Identifier field MUST be changed whenever the contents of the
      Options field changes, and whenever a valid reply has been
      received for a previous request.  For retransmissions, the
      Identifier MAY remain unchanged.

> it will match the current ID, no?

No.  There is no current ID at that point.

> delivered to the EAP method or not.

If it doesn't have an Identifier value equal to that assigned to the
most recent *outstanding* Request, then it should be dropped silently.

> silently discard received retransmissions while waiting for

Right.  Note that this is on the authenticatee side -- it's talking
about dropping duplicate Requests that are received before you're able
generate a valid Response for the first of those Requests that you
saw.  In other words, when the first Request comes in with a
particular novel ID number, you pop up a little dialog box asking the
user for his password (or whatever).  If you get a duplicate Request
for that ID number before the human finishes typing, there's no way
you could possibly respond -- you don't know what he's going to type.
You have to continue to wait.  This section says that you "wait" by
dropping those duplicate Request messages.

> without even a MIC check, right?

That sounds like an implementation optimization.  Since the MIC is
likely to be computationally expensive, checking simple things (like
sequence numbers) first would be an obvious bit of goodness.  I don't
think it affects correctness, though.

> is discarded too?

No.  No Request has been received.  It's the same *as if* the bogus
Request message had a bad CRC, or was malformed in any of a half dozen
other ways.  Bad messages are discarded.

> Or is it as though the Request never arrived, so that

Right.

> ID.

That's correct on the *authenticatee* side.  The implementation issue
for the authenticatee is that you need to keep a copy of the last
Response you sent in case the peer times out and asks again.  On the
authenticator side, which is the side that's doing the ID checking and
generation I'm referring to above, that's not true.  All the
authenticator ever does is send the same Request over and over until
it sees a Response that it wants.  The Request can be lost, or the
Response can be lost -- neither matters.  All that matters is that a
matching Response eventually arrives.

I think the confusion here might over the distinction in roles between
the authenticator and authenticatee.  The roles are different but
complementary.

The authenticator is completely uninterested in duplicates.
Duplicates have nothing to do with the way the authenticator works.
It merely sends (and resends) the same Request until it gets a
matching Response.  When the matching Response comes in, it moves on
to a new Request.

The authenticatee is interested only in detecting retransmitted
Requests.  If the Request ID number received is equal to the last one
received, then one of two things happens:

	- The prior Response is resent.

	- There's no prior Response (the processing of the Request
          isn't complete), so nothing is done.

If it's not equal, then this is a new Request to handle.  In effect,
it cancels any prior Request seen.  Whether an implementation actually
terminates an outstanding Request (abruptly closing the dialog box,
for instance) is a local implementation issue.

> And as you noted, Requests (and Responses) can fail validation, in

Right.  The handling of such cases doesn't seem to me to be
significantly different from handling packets with truncated data, bad
CRCs, mangled framing bits, or other fatal errors.  They're counted,
logged, archived, but not acted upon.

The logic (borrowed from PPP, and leaving out a ton of error handling)
looks something like this.  Note that it can be implemented as a state
machine as well, but you have to be careful to handle the Identifier
values properly.

int current_request_id;		/* initialize to pseudorandom%256 value */
int last_handled_request = -1;
eap_packet_t *copy_of_last_request = NULL;
eap_packet_t *copy_of_last_response = NULL;

/* authenticatee side */
void handle_request(eap_packet_t *req_pkt)
{
	int pktid = eap_get_id(req_pkt);	/* extract id number */

	/* handle a retransmit */
	if (pktid == last_handled_request) {
		if (copy_of_last_response != NULL)
			send_response(eap_copy_packet(copy_of_last_response));
		free_eap_packet(req_pkt);
		return;
	}
	if (copy_of_last_response != NULL) {
		free_eap_packet(copy_of_last_response);
		copy_of_last_response = NULL;
	} else {
		/* xxx if you have a way of canceling requests, do it here */
	}
	last_handled_request = pktid;
	process_request(req_pkt, formulated_response_callback);
}

/* called when the request processing is done; pop-up box 'ok' clicked */
void formulated_response_callback(eap_packet_t *resp_pkt)
{
	copy_of_last_response = eap_copy_packet(resp_pkt);
	eap_send_packet(resp_pkt);
}

/* authenticator side */
void handle_response(eap_packet_t *resp_pkt)
{
	int pktid = eap_get_id(resp_pkt);

	if (pktid != current_request_id) {
		free_eap_packet(resp_pkt);
		return;
	}
	current_request_id++;
	/*
	 * This can generate a new Request.  If it does, then a timer
	 * is set, and a copy is placed in copy_of_last_request.  If
	 * it doesn't (i.e., Success or Failure), then nothing else is
	 * done.
	 */
	process_response(resp_pkt);
}

/* authenticator only */
void handle_request_timeout(void)
{
	/* this timeout can't happen if we haven't sent a Request */
	assert(copy_of_last_request != NULL);
	eap_send_packet(eap_copy_packet(copy_of_last_request));
}

---

From: [email-masked] (Bernard Aboba)
Date: Fri, 3 Jan 2003 06:41:57 -0800 (PST)

> method for dealing with it should not be specified in the protocol.

RFC 2284 contains the following language in Section 2.2.1:

"Additionally, the peer must be prepared to silently discard received
retransmissions while waiting for user input."

and

"If a peer receives a duplicate Request
before it has sent a Response to the initial Request (i.e. it's
waiting for user input), it MUST silently discard the duplicate
Request."

How are these paragraphs to be interpretted? Does the MUST regarding
silently discard apply only to methods that take user input? Or does it
apply to EAP in general? Are you recommending that these paragraphs be
removed?

---

From: [email-masked] (James Carlson)
Date: Fri, 3 Jan 2003 11:02:59 -0500

> retransmissions while waiting for user input."

Right.  That's specifying how received duplicate Request messages are
handled in the case where a Response has not yet been generated.

> waiting for user input), it MUST silently discard the duplicate

That says the same thing.

> apply to EAP in general? Are you recommending that these paragraphs be

The problem is with asynchronous methods -- ones that invoke some
non-EAP activity (e.g., a dialog box or database query) that will
complete at a later time.  If you do this, then there's a 'limbo'
state on the authenticatee: already received a Request, but no
Response yet generated.  In this one case, duplicate Request messages
are silently discarded because no Response can possibly be generated.

Once the Response has been generated (which is immediate for a
synchronous handler), duplicate Requests are processed as usual: a
duplicate Response is sent.

As an implementation issue, *if* you return to your dispatcher after
handling a received Request but before you generate a Response, *then*
you must discard duplicate received Requests until you do generate a
Response.

Even so, it should be noted that this is "just" an optimization.
Everything works fine if the EAP authenticatee queues all input
messages (i.e., blocks while calling that dialog box handler) and then
handles them synchronously after generating the Response.  You'll
generate lots of duplicate Response messages, but the authenticator
doesn't care: he uses only the first one he gets and drops the others.

Another way to state that is that there's no way that an outside
observer can tell if the authenticatee (a) replied to the Request, but
the reply has been delayed for a long time in some transmit queue or
(b) blocks internally and does all the processing synchronously.  The
two cases look the same from the outside.

---

From: [email-masked] (Bernard Aboba)
Date: Fri, 3 Jan 2003 07:22:32 -0800 (PST)

> just as would be any Response messages that bear any invalid ID

Yes, I agree -- and I hope that the language is clear enough.

> you're done.

Yes, although I think that the word "valid" might require elaboration.
For example, failure of a MIC check would render an EAP packet invalid.

> special with any duplicate Response messages that come in.

Yes.

> was addressing in my last message.

Actually, this isn't the part that bothers me. My concern relates to RFC
2284, Section 2.2.1:

"If a peer recieves a
duplicate Request for which it has already sent a Response, it
MUST resend it's Response.  If a peer receives a duplicate Request
before it has sent a Response to the initial Request (i.e. it's
waiting for user input), it MUST silently discard the duplicate
Request."

This is neither a reliable transport service, nor a datagram service, but
a wierd mixture of the two. According to your model, the Identifier hasn't
changed until the peer receives a new Request, so why does it silently
discard?

Agreed.

>       Identifier MAY remain unchanged.

Are you recommending that this language be used instead? I do think it is
clearer.

> No.  There is no current ID at that point.

OK.

> most recent *outstanding* Request, then it should be dropped silently.

OK.

> dropping those duplicate Request messages.

Does this apply only to EAP methods taking user input, or to all EAP
methods?

> think it affects correctness, though.

I'm trying to figure out what behavior RFC 2284 is trying to mandate. Can
an implementation decide not to silently discard in this case (e.g. it's
not waiting for user input)?

> other ways.  Bad messages are discarded.

I agree. I'm just puzzled by the language in Section 2.2.1.

> Response you sent in case the peer times out and asks again.

Where does RFC 2284 say that a copy Response is sent? If only the ID
portion of the Request is checked, then we don't necessarily know that it
is the same Request, even if the ID is the same. So a different Response
could conceivably be generated. I realize that this is a corner case, but
we want to understand the behavior under DoS attack.

> matching Response eventually arrives.

Yes.

> matching valid Response.  When the matching Response comes in, it moves
> on

>           isn't complete), so nothing is done.

This is the part that's not clear in RFC 2284. Does "nothing is done"
always mean silent discard? Does an invalid Request imply that there's no
prior Response?

> it cancels any prior Request seen.

Even if it has not yet sent a Response? Wouldn't this increase the
vulnerability to DoS attacks?

> logged, archived, but not acted upon.

Makes sense. I think more language is needed to clarify this, though.

---

From: [email-masked] (Bernard Aboba)
Date: Fri, 3 Jan 2003 07:30:11 -0800 (PST)

> Even so, it should be noted that this is "just" an optimization.

If so, then I would suggest that the MUST be lowered to a MAY, with a
caution about the DoS implications.

> doesn't care: he uses only the first one he gets and drops the others.

I'd argue that the peer will have more work to do in event of a DoS
attack, but if there is no silent discard, then it will
eventually get to the valid Request that passes the MIC check, amongst the
sea of invalid Requests.  What I don't like is the idea of silently discarding a
valid Request packet as a result of receiving (and not yet responding to) an
invalid Request. As you've pointed out, this doesn't happen on the
authenticator side, because the term "valid Response" is used.

---

From: [email-masked] (James Carlson)
Date: Fri, 3 Jan 2003 12:19:20 -0500

Bernard Aboba writes:
> a wierd mixture of the two.

I disagree.  It's reliable, in-order, and unduplicated.  It uses
retransmissions to recover from errors, and it eliminates duplicates
by use of a unique identifier.  The fact that it's a simplex protocol
means that it's pretty crude as a transport, but it's just fine for
low-volume authentication data.

> According to your model, the Identifier hasn't

Because there's no plausible Response that it could possibly send.

You've received Request ID number 1.  You're working on a Response for
that Request, but you don't have that Response ready yet.  You get
another Request ID number 1 in.  What do you do?  You can't "resend"
the Response you don't have.  So, you do *nothing*.

That's the point.  This language is there to alleviate the "but what
if I can't resend?" concern.

> Are you recommending that this language be used instead? I do think it is

I do think that the language could be made clearer, but copying that
language directly from PPP might not be the right answer because EAP
has tighter constraints on the authenticator -- it requires the
creator of IDs to reuse ID numbers on retransmission.  (s/MAY/MUST/)

It's a fair reference, though, because the same ideas are used.

> Does this apply only to EAP methods taking user input, or to all EAP

Any asynchronous method where EAP remains free to process future
messages while a Response is being formulated.  "User input" is one of
those.  A connection to some external database or client-side
authentication service *might* be another, if the implementation is
really sophisticated.

> not waiting for user input)?

Certainly; it can queue all received messages following the Request
and handle them after the one currently being dispatched is complete.
Such behavior isn't distinguishable from a transmission delay.  It
might be suboptimal, but it can't be called "wrong" from the EAP
protocol point of view.

> I agree. I'm just puzzled by the language in Section 2.2.1.

If you treat it as a bad message, you never get to the point of
thinking about retransmitting a reply per 2.2.1.  You wouldn't process
a frame with a CRC error and then try to generate a reply based on
that; similarly, if something fails MIC, there's no reason to try to
generate any reply there.

> is the same Request, even if the ID is the same.

A really conservative authenticatee implementation would indeed check
that the Response is *competely* identical in all respects.  I agree
with that.  If it gets the same ID but the rest is different, then the
peer is an idiot -- he's sent a 'retransmission' that isn't really a
retransmission.  Personally, I'd either discard the packet (and log
it), or drop the connection cold.  There's no use in talking to
implementations that are this seriously flawed, and any implementation
that could get this wrong likely has other (possibly even more
serious) problems.

In 2.2.1:

      [...]  Any new (non-retransmission)
      Requests MUST modify the Identifier field.  [...]

There's no option to change the contents of the Request but use the
same Identifier.

> So a different Response
> could conceivably be generated.

No.

> I realize that this is a corner case, but

      [...]  If a peer recieves a
      duplicate Request for which it has already sent a Response, it
      MUST resend it's Response.  [...]

Just resend the Response.

> always mean silent discard?

The two are equivalent for the protocol.

> Does an invalid Request imply that there's no
> prior Response?

I assume we're still talking about MICs here.  An invalid packet means
there's no point in processing it in any way.  I would say that an
"invalid Request" isn't even a Request.  It's nothing but noise.

> Even if it has not yet sent a Response?

Per 2284, yes.  There's no requirement in there that an authenticator
stick with the same Request forever.

> Wouldn't this increase the

Not exactly.  You can do anything you like inside both peers.  If,
based on the environment you deploy into, you think it's likely that
you'll be DoS'd by a bad authenticator, then the right thing to do
might be to count the number of received unique EAP Request messages
and forcibly shut the link down if the number is "too high."

I think that's a quality-of-implementation issue.

> caution about the DoS implications.

I think the fear is that someone might be tempted to send a completely
bogus Response instead.  It should say something like:

	If the receiving implementation has the capability of
	continuing to process newly-received EAP messages while a
	Request message is still being processed (and a corresponding
	Response has not yet been generated), then that implementation
	MUST silently discard any duplicate Request messages that it
	receives in the interval before the corresponding Response is
	generated.

... or some such.

> sea of invalid Requests.

It's not clear to me whether there's any significantly greater amount
of work to do, or if this is even near the weak point in the
protocol.  The additional work that it would have to do would be to
check one byte (the Identifier) in a sea of messages that a "bad" peer
could generate from whole cloth anyway.

I don't think any of this is necessarily important from a DoS point of
view.  DoS concerns in security protocols usually revolve around the
operations that invoke a "hard to do" function, such as computing
MD5.  Duplicate Requests don't do that.  Having an authenticator that
sends a flood of MD5-Challenge Request messages, each with a unique
Identifier value, is much more credible threat, and EAP has no
inherent protection against it.

>  What I don't like is the idea of silently discarding a

If you have some way to tell what a "valid" Request looks like -- such
as a MIC or CRC or nonce -- then you can do what you suggest.
Otherwise, you can't, and you need to return to first principles: if
the peer is acting broken, then stop talking to it.

---

From: [email-masked] (Bernard Aboba)
Date: Fri, 3 Jan 2003 08:44:42 -0800 (PST)

> It's a fair reference, though, because the same ideas are used.

How about:

"The Identifier field MUST be changed whenever the contents of the
Type-Data field changes, and whenever a valid Response has been received
for a previous Request."

Right.

> thinking about retransmitting a reply per 2.2.1.

Yes, but the invalid message does result in silent discard of potentially
valid messages.

> that the Response is *completely* identical in all respects.  I agree
> with that.

I don't think this distinction is material if the initial Request is a
valid one. If it is invalid, it needs to be silently discarded, and state
left as though it never arrived.

> If it gets the same ID but the rest is different, then the

This seems reasonable on  physically secure media like PPP. However, on
802.11, an attacker only need be in range to have access to the media. So
aborting the conversation on receiving invalid packets makes it easy for
an attacker to abort the session.

Yes.

> "invalid Request" isn't even a Request.  It's nothing but noise.

OK. How about this?

"If a peer receives a duplicate Request
before it has sent a Response to a valid initial Request (i.e.
it's waiting for user input), it MUST silently discard the duplicate
Request."

That way, silent discard isn't mandated if the initial Request is
determined to be invalid.

---

From: [email-masked] (James Carlson)
Date: Fri, 3 Jan 2003 13:21:45 -0500

> Type-Data field changes, and whenever a valid Response has been received

That's good, and roughly equivalent to what was in RFC 2284.

> Yes, but the invalid message does result in silent discard of potentially

How so?

If you receive and process an invalid message, then shame on you.
Sure, you'll end up discarding later valid messages.  You might also
cause all sorts of other problems.

If you receive an invalid message and discard it, then I don't see how
that discarded message can hurt you.  Can you elaborate on that?

> left as though it never arrived.

Right.  Except that I would argue that Requests are not peculiar in
this regard: all invalid packets of whatever nature need to be
silently discarded.  (Where "silently discared" also implies that the
state is unaltered.)

If we don't process packets with CRC errors, we ought not be
processing packets that have other errors.

> an attacker to abort the session.

There's a subtle difference here: if the packet is something that only
the peer could have generated, but the contents represent foolishness,
such as a Request that passes MIC (or comes from a physically secure
wire) and has a duplicate Identifier, but has altered contents, then
the peer must be an idiot.  Dropping him like a bad habit is a prudent
response to protect the rest of the network.  Only a human can
defenestrate the offending equipment.

If the packet could come from any source, including an attacker or
just plain old noise, then you do need to discard without paying
attention to the contents.

Which one is true depends strongly on the deployment considerations --
as you're describing with 802.11.  It's not just 802.11, though.
Suppose that someone (in the future) replaced WEP with something that
was cryptographically secure enough to rule out tampering.  In that
case, you'd want to be stricter about the sorts of things you're
willing to tolerate out of a good peer.

For another case, consider just CRCs.  We would ordinarily say that
packets with CRC errors are discarded silently, and no processing at
all is performed, and that we don't treat these as problems with the
peer, right?

Consider a link where the CRC error rate is so high that only one in
10 packets makes it through.  Such a link is probably completely
unusable.  EAP will eventually establish an authentication through
patience.  Is that a good thing?  Certainly not if your point of view
is centered on the health of the network -- a bad link forms a black
hole in the network that will harm everyone else's performance
(assuming it looks like an attractive route for some traffic -- if
it's not, then why'd you even try to bring up the link?).

This case would be similar in implementation.  If the link is awful,
either because of peer bugs or link errors or frequent attacks, you
*might* be better off in some cases without that link.

> determined to be invalid.

I don't think that quite captures the idea.  If MIC must be addressed
at all, then I'd recommend a separate paragraph somewhere to handle
it:

	If some sort of message integrity checking is employed, then
	implementations are REQUIRED to discard any message that fails
	this check silently.  The types of checking that might be
	employed depend on the underlying communications medium and
	the threat model for the deployment.  In all cases, the
	foregoing descriptions of EAP message handling assume that
	validation is effectively performed as though it occurs before
	examining any of the EAP message fields (such as 'Code').

I still don't think that this is necessary.  Discarding errors is just
plain good engineering sense.  There's no way to predict what the
message "might" have said if it didn't have an error, so there's no
sensible way to act on an invalid message of any sort.  I don't think
that normal implementation practice needs to be described here.

Further, someone skilled in the art should be able to tell that all
that is necessary is that all checking is done "as if" performed
logically before any state is changed.  An implementation that parses
individual bits as they stream off of the wire could (at least in
theory) perform all of the EAP dispatching on each bit as it arrives
using a copy of the current state.  When the final bit of the message
is clocked in, the resulting CRC (and other check bits) are verified,
and if they're right, then the new EAP state is committed.  Otherwise,
it reverts to the old state.

I don't think such optimizations (even where possible) need to be in
the base document.  A document that talks about implementing a
particular MIC with EAP *might* need to discuss how best to optimize
the order of operations to validate an incoming message ("first check
the Identifier and discard if incorrect, else run MIC and discard if
failed, else dispatch based on Code"), but I don't think that's
relevant here.

---

From: [email-masked] (Yoshihiro Ohba)
Date: Fri, 3 Jan 2003 18:15:16 -0500

> authenticator side, because the term "valid Response" is used.

There would be two issues if there is no silent discard on 
detecting duplicate Request.

First, each EAP method specification is required to have explicit
description on the behavior when detecting duplicate Request, which
might complicate the method design.

Second, eliminating silent discard could introduce another type of DoS
attack.  A peer might have to spend its CPU resource for cryptographic
calculation of many broken requests until it finally receives
cryptographically valid request.  The attack will be more "effective",
especially if the cypher suites applied to the method is a type of
doing encryption after adding sequence number and ICV fields (like TLS
does) as replay protection cannot be performed before decrypting the
packet.

Yoshihiro Ohba

> 
> 
> _______________________________________________
> eap mailing list
> [email-masked]
> http://mail.frascone.com/mailman/listinfo/eap
>

---

From: [email-masked] (James Carlson)
Date: Sun, 5 Jan 2003 11:21:24 -0500

> might complicate the method design.

No.  RFC 2284 EAP already describes what to do when you detect a
duplicate Request at the authenticatee.  EAP methods that choose to
override this behavior by definition can do that, but they're
certainly not required to do this.

I'd additionally argue that any EAP method that goes so far as to
redefine EAP's clear handling of duplicates to be flawed.  I don't see
what value such a method could add.

If there are such methods, a much better way to guarantee
recalculation (which is obviously what's wanted) is to change the
Identifier and the contents of the Request for each Request sent.
That's compatible with RFC 2284 and doesn't require magic behavior on
the part of the authenticatee.

> cryptographically valid request.

That's incorrect per RFC 2284.  If you receive a duplicate Request,
you do *NO* additional calculation in any case.  You instead resend
the last Response, if you have one, or nothing if you don't:

      Requests MUST modify the Identifier field.  If a peer recieves a
      Request.

Note that it just says "resend it's [sic] Response."  It doesn't say
"recalculate the result based on the Request and then transmit that
Response."

>  The attack will be more "effective",

Replay protection consists of making sure that the same saved Response
value can never be a valid Response in a future session, nor a valid
Response to a rechallenge in the same session.  It's immaterial for
repeats involved in retransmissions.

---

From: [email-masked] (Yoshihiro Ohba)
Date: Sun, 5 Jan 2003 21:35:41 -0500

I agree with James' commment.

Please see my additional comment in line.

>       waiting for user input), it MUST silently discard the duplicate

I agree.  I think the above text in RFC2284 is now missing in the
recent strawman rewrite of section 4.1 recently posted on the mailing
list and should be included in RFC2284bis, thinking much about
compatibility with RFC2284 than trying to modify the EAP protocol
behavior just to deal with the TLS problem.

Yoshihiro Ohba