]> git.ipfire.org Git - thirdparty/chrony.git/commitdiff
ntp: move auth parsing to ntp_auth
authorMiroslav Lichvar <mlichvar@redhat.com>
Thu, 15 Aug 2019 09:20:36 +0000 (11:20 +0200)
committerMiroslav Lichvar <mlichvar@redhat.com>
Thu, 5 Mar 2020 15:02:15 +0000 (16:02 +0100)
Move the remaining authentication-specific code to the new file.

ntp_auth.c
ntp_auth.h
ntp_core.c

index 8a64b624ead82b66cc4293ece29779e229b1e6d2..d6a4959a65dce42624c40c74e2cd54abac8f48f6 100644 (file)
@@ -32,6 +32,7 @@
 #include "logging.h"
 #include "memory.h"
 #include "ntp_auth.h"
+#include "ntp_ext.h"
 #include "ntp_signd.h"
 #include "srcparams.h"
 #include "util.h"
@@ -109,6 +110,19 @@ adjust_timestamp(NTP_AuthMode mode, uint32_t key_id, struct timespec *ts)
 
 /* ================================================== */
 
+static int
+is_zero_data(unsigned char *data, int length)
+{
+  int i;
+
+  for (i = 0; i < length; i++)
+    if (data[i])
+      return 0;
+  return 1;
+}
+
+/* ================================================== */
+
 static NAU_Instance
 create_instance(NTP_AuthMode mode)
 {
@@ -220,6 +234,107 @@ NAU_GenerateRequestAuth(NAU_Instance instance, NTP_Packet *request, NTP_PacketIn
 
 /* ================================================== */
 
+int
+NAU_ParsePacket(NTP_Packet *packet, NTP_PacketInfo *info)
+{
+  int parsed, remainder, ef_length, ef_type;
+  unsigned char *data;
+
+  data = (void *)packet;
+  parsed = NTP_HEADER_LENGTH;
+  remainder = info->length - parsed;
+
+  info->ext_fields = 0;
+
+  /* Check if this is a plain NTP packet with no extension fields or MAC */
+  if (remainder <= 0)
+    return 1;
+
+  /* In NTPv3 and older packets don't have extension fields.  Anything after
+     the header is assumed to be a MAC. */
+  if (info->version <= 3) {
+    info->auth.mode = AUTH_SYMMETRIC;
+    info->auth.mac.start = parsed;
+    info->auth.mac.length = remainder;
+    info->auth.mac.key_id = ntohl(*(uint32_t *)(data + parsed));
+
+    /* Check if it is an MS-SNTP authenticator field or extended authenticator
+       field with zeroes as digest */
+    if (info->version == 3 && info->auth.mac.key_id) {
+      if (remainder == 20 && is_zero_data(data + parsed + 4, remainder - 4))
+        info->auth.mode = AUTH_MSSNTP;
+      else if (remainder == 72 && is_zero_data(data + parsed + 8, remainder - 8))
+        info->auth.mode = AUTH_MSSNTP_EXT;
+    }
+
+    return 1;
+  }
+
+  /* Check for a crypto NAK */
+  if (remainder == 4 && ntohl(*(uint32_t *)(data + parsed)) == 0) {
+    info->auth.mode = AUTH_SYMMETRIC;
+    info->auth.mac.start = parsed;
+    info->auth.mac.length = remainder;
+    info->auth.mac.key_id = 0;
+    return 1;
+  }
+
+  /* Parse the rest of the NTPv4 packet */
+
+  while (remainder > 0) {
+    /* Check if the remaining data is a valid MAC.  There is a limit on MAC
+       length in NTPv4 packets to allow deterministic parsing of extension
+       fields (RFC 7822), but we need to support longer MACs to not break
+       compatibility with older chrony clients.  This needs to be done before
+       trying to parse the data as an extension field. */
+
+    if (remainder >= NTP_MIN_MAC_LENGTH && remainder <= NTP_MAX_MAC_LENGTH) {
+      info->auth.mac.key_id = ntohl(*(uint32_t *)(data + parsed));
+      if (remainder <= NTP_MAX_V4_MAC_LENGTH ||
+          KEY_CheckAuth(info->auth.mac.key_id, data, parsed, (void *)(data + parsed + 4),
+                        remainder - 4, NTP_MAX_MAC_LENGTH - 4))
+        break;
+    }
+
+    /* Check if this is a valid NTPv4 extension field and skip it */
+    if (!NEF_ParseField(packet, info->length, parsed, &ef_length, &ef_type, NULL, NULL)) {
+      /* Invalid MAC or format error */
+      DEBUG_LOG("Invalid format or MAC");
+      return 0;
+    }
+
+    assert(ef_length > 0);
+
+    switch (ef_type) {
+      default:
+        DEBUG_LOG("Unknown extension field type=%x", (unsigned int)ef_type);
+    }
+
+    info->ext_fields++;
+    parsed += ef_length;
+    remainder = info->length - parsed;
+  }
+
+  if (remainder == 0) {
+    /* No MAC */
+    return 1;
+  } else if (remainder >= NTP_MIN_MAC_LENGTH) {
+    /* This is not 100% reliable as a MAC could fail to authenticate and could
+       pass as an extension field, leaving reminder smaller than the minimum MAC
+       length */
+    info->auth.mode = AUTH_SYMMETRIC;
+    info->auth.mac.start = parsed;
+    info->auth.mac.length = remainder;
+    info->auth.mac.key_id = ntohl(*(uint32_t *)(data + parsed));
+    return 1;
+  }
+
+  DEBUG_LOG("Invalid format");
+  return 0;
+}
+
+/* ================================================== */
+
 int
 NAU_CheckRequestAuth(NTP_Packet *request, NTP_PacketInfo *info)
 {
index 603ac17f77b762e9f1550a64d6c0250595f60b85..7537238fda1e44be1683c7f70ae047cdc6541668 100644 (file)
@@ -56,6 +56,9 @@ extern void NAU_AdjustRequestTimestamp(NAU_Instance instance, struct timespec *t
 extern int NAU_GenerateRequestAuth(NAU_Instance instance, NTP_Packet *request,
                                    NTP_PacketInfo *info);
 
+/* Parse a request or response to detect the authentication mode */
+extern int NAU_ParsePacket(NTP_Packet *packet, NTP_PacketInfo *info);
+
 /* Verify that a request is authentic */
 extern int NAU_CheckRequestAuth(NTP_Packet *request, NTP_PacketInfo *info);
 
index fe1bb8af388679b80b70855c79487432d08edf25..9ce133a50f704bb12e5d89d432a6ab36c76e8844 100644 (file)
@@ -32,7 +32,6 @@
 #include "array.h"
 #include "ntp_auth.h"
 #include "ntp_core.h"
-#include "ntp_ext.h"
 #include "ntp_io.h"
 #include "memory.h"
 #include "sched.h"
@@ -44,7 +43,6 @@
 #include "util.h"
 #include "conf.h"
 #include "logging.h"
-#include "keys.h"
 #include "addrfilt.h"
 #include "clientlog.h"
 
@@ -1268,25 +1266,9 @@ transmit_timeout(void *arg)
 
 /* ================================================== */
 
-static int
-is_zero_data(unsigned char *data, int length)
-{
-  int i;
-
-  for (i = 0; i < length; i++)
-    if (data[i])
-      return 0;
-  return 1;
-}
-
-/* ================================================== */
-
 static int
 parse_packet(NTP_Packet *packet, int length, NTP_PacketInfo *info)
 {
-  int parsed, remainder, ef_length, ef_type;
-  unsigned char *data;
-
   if (length < NTP_HEADER_LENGTH || length % 4U != 0) {
     DEBUG_LOG("NTP packet has invalid length %d", length);
     return 0;
@@ -1303,95 +1285,11 @@ parse_packet(NTP_Packet *packet, int length, NTP_PacketInfo *info)
     return 0;
   }
 
-  data = (void *)packet;
-  parsed = NTP_HEADER_LENGTH;
-  remainder = length - parsed;
-
-  /* Check if this is a plain NTP packet with no extension fields or MAC */
-  if (remainder == 0)
-    return 1;
-
-  /* In NTPv3 and older packets don't have extension fields.  Anything after
-     the header is assumed to be a MAC. */
-  if (info->version <= 3) {
-    info->auth.mode = AUTH_SYMMETRIC;
-    info->auth.mac.start = parsed;
-    info->auth.mac.length = remainder;
-    info->auth.mac.key_id = ntohl(*(uint32_t *)(data + parsed));
-
-    /* Check if it is an MS-SNTP authenticator field or extended authenticator
-       field with zeroes as digest */
-    if (info->version == 3 && info->auth.mac.key_id) {
-      if (remainder == 20 && is_zero_data(data + parsed + 4, remainder - 4))
-        info->auth.mode = AUTH_MSSNTP;
-      else if (remainder == 72 && is_zero_data(data + parsed + 8, remainder - 8))
-        info->auth.mode = AUTH_MSSNTP_EXT;
-    }
-
-    return 1;
-  }
-
-  /* Check for a crypto NAK */
-  if (remainder == 4 && ntohl(*(uint32_t *)(data + parsed)) == 0) {
-    info->auth.mode = AUTH_SYMMETRIC;
-    info->auth.mac.start = parsed;
-    info->auth.mac.length = remainder;
-    info->auth.mac.key_id = 0;
-    return 1;
-  }
-
-  /* Parse the rest of the NTPv4 packet */
-
-  while (remainder > 0) {
-    /* Check if the remaining data is a valid MAC.  There is a limit on MAC
-       length in NTPv4 packets to allow deterministic parsing of extension
-       fields (RFC 7822), but we need to support longer MACs to not break
-       compatibility with older chrony clients.  This needs to be done before
-       trying to parse the data as an extension field. */
-
-    if (remainder >= NTP_MIN_MAC_LENGTH && remainder <= NTP_MAX_MAC_LENGTH) {
-      info->auth.mac.key_id = ntohl(*(uint32_t *)(data + parsed));
-      if (remainder <= NTP_MAX_V4_MAC_LENGTH ||
-          KEY_CheckAuth(info->auth.mac.key_id, data, parsed, (void *)(data + parsed + 4),
-                        remainder - 4, NTP_MAX_MAC_LENGTH - 4))
-        break;
-    }
-
-    /* Check if this is a valid NTPv4 extension field and skip it */
-    if (!NEF_ParseField(packet, length, parsed, &ef_length, &ef_type, NULL, NULL)) {
-      /* Invalid MAC or format error */
-      DEBUG_LOG("Invalid format or MAC");
-      return 0;
-    }
-
-    assert(ef_length > 0);
-
-    switch (ef_type) {
-      default:
-        DEBUG_LOG("Unknown extension field type=%x", (unsigned int)ef_type);
-    }
-
-    info->ext_fields++;
-    parsed += ef_length;
-    remainder = length - parsed;
-  }
-
-  if (remainder == 0) {
-    /* No MAC */
-    return 1;
-  } else if (remainder >= NTP_MIN_MAC_LENGTH) {
-    /* This is not 100% reliable as a MAC could fail to authenticate and could
-       pass as an extension field, leaving reminder smaller than the minimum MAC
-       length */
-    info->auth.mode = AUTH_SYMMETRIC;
-    info->auth.mac.start = parsed;
-    info->auth.mac.length = remainder;
-    info->auth.mac.key_id = ntohl(*(uint32_t *)(data + parsed));
-    return 1;
-  }
+  /* Parse authentication extension fields or MAC */
+  if (!NAU_ParsePacket(packet, info))
+    return 0;
 
-  DEBUG_LOG("Invalid format");
-  return 0;
+  return 1;
 }
 
 /* ================================================== */