]> git.ipfire.org Git - thirdparty/chrony.git/commitdiff
ntp: restrict authentication of server/peer to specified key
authorMiroslav Lichvar <mlichvar@redhat.com>
Fri, 8 Jan 2016 14:03:09 +0000 (15:03 +0100)
committerMiroslav Lichvar <mlichvar@redhat.com>
Mon, 18 Jan 2016 16:28:47 +0000 (17:28 +0100)
When a server/peer was specified with a key number to enable
authentication with a symmetric key, packets received from the
server/peer were accepted if they were authenticated with any of
the keys contained in the key file and not just the specified key.

This allowed an attacker who knew one key of a client/peer to modify
packets from its servers/peers that were authenticated with other
keys in a man-in-the-middle (MITM) attack. For example, in a network
where each NTP association had a separate key and all hosts had only
keys they needed, a client of a server could not attack other clients
of the server, but it could attack the server and also attack its own
clients (i.e. modify packets from other servers).

To not allow the server/peer to be authenticated with other keys
extend the authentication test to check if the key ID in the received
packet is equal to the configured key number. As a consequence, it's
no longer possible to authenticate two peers to each other with two
different keys, both peers have to be configured to use the same key.

This issue was discovered by Matt Street of Cisco ASIG.

chrony.texi.in
ntp_core.c

index b56fb819cee102ca894add11e6078cfbf06b0a80..25f807b9f942973f2082688b1be75221c72321fb 100644 (file)
@@ -2508,6 +2508,9 @@ The syntax of this directive is identical to that for the @code{server}
 directive (@pxref{server directive}), except that it is used to specify
 an NTP peer rather than an NTP server.
 
+When a key is specified by the @code{key} option to enable authentication, both
+peers must be configured to use the same key and the same key number.
+
 Please note that NTP peers that are not configured with a key to enable
 authentication are vulnerable to a denial-of-service attack.  An attacker
 knowing that NTP hosts A and B are peering with each other can send a packet
index b47766619531a2554cb237fffb30b63bdcba60cc..2843858792cd93c7f8148f13363d03709d86194e 100644 (file)
@@ -1099,7 +1099,7 @@ static int
 receive_packet(NTP_Packet *message, struct timeval *now, double now_err, NCR_Instance inst, NTP_Local_Address *local_addr, int length)
 {
   int pkt_leap;
-  uint32_t pkt_refid;
+  uint32_t pkt_refid, pkt_key_id;
   double pkt_root_delay;
   double pkt_root_dispersion;
 
@@ -1190,11 +1190,13 @@ receive_packet(NTP_Packet *message, struct timeval *now, double now_err, NCR_Ins
      function is called only for known sources. */
 
   /* Test 5 checks for authentication failure.  If we expect authenticated info
-     from this peer/server and the packet doesn't have it or the authentication
-     is bad, it's got to fail.  If the peer or server sends us an authenticated
-     frame, but we're not bothered about whether he authenticates or not, just
-     ignore the test. */
-  test5 = inst->do_auth ? check_packet_auth(message, length, NULL, NULL) : 1;
+     from this peer/server and the packet doesn't have it, the authentication
+     is bad, or it's authenticated with a different key than expected, it's got
+     to fail.  If we don't expect the packet to be authenticated, just ignore
+     the test. */
+  test5 = !inst->do_auth ||
+          (check_packet_auth(message, length, NULL, &pkt_key_id) &&
+           pkt_key_id == inst->auth_key_id);
 
   /* Test 6 checks for unsynchronised server */
   test6 = pkt_leap != LEAP_Unsynchronised &&