[ntp:security] NOEPEER patch

Harlan Stenn stenn at nwtime.org
Tue Jul 31 08:08:22 UTC 2018


Hi Martin,

First, might I trouble you to tell me how I can repeat this case?

That would be (un)authenticated Windows clients sending these (broken)
requests to an NTP server.

On 7/30/2018 5:52 AM, Martin Burnicki wrote:
> Harlan,
> 
> Harlan Stenn wrote:
>> Martin,
>>
>> Pearly and I have been chatting about this for the past hour.
> 
> We've also run some tests here in the mean time. See below.
> 
>> Here's the thing:
>>
>> We get an AM_NEWPASS situation.  This is one of several cases.
>>
>> 1) it's a broken Windows client.  We want to respond to these.
>>
>> 2) it's not a broken Windows client.  We want to drop these if NOEPEER
>> is set.  We want to spin up an ephemeral association otherwise.
>>
>> The problem is that for the Windows case, we just call fast_xmit() to
>> send the response without spinning up an association.
>>
>> For the non-windows case, we want to either drop the packet without
>> responding (if NOEPEER is set), or spin up an association.
>>
>> We cannot first respond with a fast_xmit() and then decide if we want to
>> spin up an association or not.
>>
>> We have to be able to know if the incoming request is from a broken
>> windows client or not.
>>
>> Do you know how we can do that?
>>
>> Similarly, it would be helpful to know if we can respond to these broken
>> windows clients with a mode 4 (Server) response instead of a mode 2
>> (Passive) response, just to try and let the client know what's going on.
>>
>> I'd hate to be debugging why one side thinks it's doing a (passive)
>> symmetric association when the other (ntpd) side is just responding with
>> symmetric passive packets without actually bringing up an association.
>>
>> Can't this problem also be solved with the ntp.keys file, where the
>> LANtime server would have a 4th argument of an IP address (possibly
>> localhost) so that you would not need to use NOEPEER on local networks?
>>
>> Does the LANtime create ephemeral associations from Windows clients?
> 
> No, actually it doesn't, even if the NOEPEER keyword isn't specified.

That's good, and expected, because of the lengths we've taken to deal
with the broken Windows clients in the past.

> The original problem was that an ephemeral association was mobilized on
> the local node if the remote node used a valid symmetric key, but the
> remote node wasn't explicitly configured. This should be prevented by
> the NOEPEER keyword.

I believe we are in agreement on this point.

In the past, nopeer allowed spinning up ephemeral passive peers IFF the
request was authenticated.

The problem was there was no way to prevent spinning up an ephemeral
passive peer from an authenticated source.

There are (or should be) 2 ways to prevent this.

1) noepeer

2) the 4th argument in the ntp.keys file

You folks previous reported a bug in noepeer where there were cases that
*would* spin up an ephemeral passive peering session.  The bad news here
is the cleanest fix for this prevents broken Windows clients from syncing.

More below.

> I've put some pseudo code together describing the program flow that I
> think is appropriate:
> 
>   // A symmetric Packet has been received.
> 

Isn't that next line supposed to be: Packet has NO signature?

>   if ( !auth_used ) //packet has signature
>   {
>     // Should we eventually accept it
>     // as ephemeral peer anyway?
>     // Probably not.
>     goto send_reply;
>   }
> 
>   // Packet has a signature.

In the next case, the previous code looked like it did a
fast_xmit(MODE_ACTIVE) if an invalid signature was received, and that
makes no sense to me.

>   if ( !auth_ok )  // signature not valid
>   {
>     // We never accept it.
>     send_crypto_nack();
>     goto done;
>   }
> 
>   // Auth is used and OK.

This next case will never happen in the current code - at the point in
question the packet has already made it to the point where we know this
is an incoming request to spin up a *new* passive association:

>   if ( remote_peer_is_configured )
>   {
>     // This is a standard peer association.
>     assoc_type = standard;
> 
>     // No need to check NOEPEER flag.
>     goto create_assoc;
>   }
> 
>   // This is an ephemeral peer.
>   assoc_type = ephemeral;
> 
>   // Check NOEPEER flag if we accept it.
>   if ( noepeer_flag )
>   {
>     // We don't accept ephemeral peers.
>     goto send_reply;
>   }
> 
> create_assoc:
>   // We get here only if we accept a standard
>   // or ephemeral peer association for this
>   // remote node.
>   create_assoc_if_required( assoc_type );
> 
> send_reply:
>   // Send a reply with or without signature,
>   // depending on whether the request had
>   // a signature. We don't get here if a
>   // signature was used, but not valid.
>   send_reply_msg();
> 
> done:  // That's it!
> 
> 
> So as a summary:
> 
> - A reply (symmetric passive in case of a symmetric active request) is
> sent in any case, except that we send a crypto NAK if the request had an
> invalid signature.
> 
> - A peer association is mobilized only if auth is used and OK, and
> -- if the NOEPEER keyword has *not* been specified
> -- or the remote peer has explicitly been specified as peer.
> 
> 
> We have verified here that Windows clients that send unauthenticated
> symmetric active requests are happy if they receive an unauthenticated
> symmetric passive reply from the server.

Thanks!

Are they happy if they receive an unauthenticated mode 4 (SERVER) response?

Dave and I have talked about whether or not it's OK to give a SERVER
response to an unexpected ACTIVE (or PASSIVE) packet.  So far, we've
avoided this case, and I don't know enough about this to make a proper
evaluation.

But to a point I alluded to above...

Dave is a fan of Occam's Razor, perhaps even more than I am.  He wants
to remove un-needed complexity wherever he sees it.  This goes to writing:

 if (a)
	something;

instead of:

 if (a) {
	something;
 }

The current patch for NOEPEER is very clean.

I can see us spending a LOT of time making sure a more complicated code
path will actually work, and will be the source for numerous upcoming
bug reports.  I'd like to avoid this situation.

An argument can easily be made that the Windows clients are *requesting
an ephemeral peering session* as evidenced by their sending a peering
request, and as such, if we're using noepeer we *should* be denying
these packets.

If windows clients are coming in, then if the server in question must
support broken windows clients then I wonder if doing both:

- using 'nopeer' to prevent unauthenticated peering
- use the 4th argument in the  ntp.keys file to prevent
  authenticated peering from unwanted servers

is the better way to go.

For this last case, if *no* (ephemeral?) peering is desired, I believe:

ntp-keys:
 10 md5 foo 0.0.0.0

will work.

Might you be able to test this?

If this works, is it acceptable?

I'm happy to write up more documentation on this.

-- 
Harlan Stenn, Network Time Foundation
http://nwtime.org - be a Member!


More information about the security mailing list