]> git.ipfire.org Git - thirdparty/chrony.git/commitdiff
ntp: refactor authentication
authorMiroslav Lichvar <mlichvar@redhat.com>
Wed, 14 Aug 2019 16:23:45 +0000 (18:23 +0200)
committerMiroslav Lichvar <mlichvar@redhat.com>
Thu, 5 Mar 2020 15:02:15 +0000 (16:02 +0100)
Move most of the authentication-specific code to a new file and
introduce authenticator instances in order to support other
authentication mechanisms (e.g. NTS).

configure
ntp_auth.c [new file with mode: 0644]
ntp_auth.h [new file with mode: 0644]
ntp_core.c
stubs.c

index b448b72f9f8b98aabfd18fd3fe55e23dcf781599..d0927a06fed5e8dc232b85fcb817044bc218a8ef 100755 (executable)
--- a/configure
+++ b/configure
@@ -483,7 +483,7 @@ fi
 
 if [ $feat_ntp = "1" ]; then
   add_def FEAT_NTP
-  EXTRA_OBJECTS="$EXTRA_OBJECTS ntp_core.o ntp_ext.o ntp_io.o ntp_sources.o"
+  EXTRA_OBJECTS="$EXTRA_OBJECTS ntp_auth.o ntp_core.o ntp_ext.o ntp_io.o ntp_sources.o"
   if [ $feat_ntp_signd = "1" ]; then
     add_def FEAT_SIGND
     EXTRA_OBJECTS="$EXTRA_OBJECTS ntp_signd.o"
diff --git a/ntp_auth.c b/ntp_auth.c
new file mode 100644 (file)
index 0000000..8a64b62
--- /dev/null
@@ -0,0 +1,310 @@
+/*
+  chronyd/chronyc - Programs for keeping computer clocks accurate.
+
+ **********************************************************************
+ * Copyright (C) Miroslav Lichvar  2019
+ * 
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ * 
+ **********************************************************************
+
+  =======================================================================
+
+  NTP authentication
+  */
+
+#include "config.h"
+
+#include "sysincl.h"
+
+#include "keys.h"
+#include "logging.h"
+#include "memory.h"
+#include "ntp_auth.h"
+#include "ntp_signd.h"
+#include "srcparams.h"
+#include "util.h"
+
+/* Structure to hold authentication configuration and state */
+
+struct NAU_Instance_Record {
+  NTP_AuthMode mode;            /* Authentication mode of NTP packets */
+  uint32_t key_id;              /* Identifier of a symmetric key */
+};
+
+/* ================================================== */
+
+static int
+generate_symmetric_auth(uint32_t key_id, NTP_Packet *packet, NTP_PacketInfo *info)
+{
+  int auth_len, max_auth_len;
+
+  /* Truncate long MACs in NTPv4 packets to allow deterministic parsing
+     of extension fields (RFC 7822) */
+  max_auth_len = (info->version == 4 ? NTP_MAX_V4_MAC_LENGTH : NTP_MAX_MAC_LENGTH) - 4;
+  max_auth_len = MIN(max_auth_len, sizeof (NTP_Packet) - info->length - 4);
+
+  auth_len = KEY_GenerateAuth(key_id, (unsigned char *)packet, info->length,
+                              (unsigned char *)packet + info->length + 4, max_auth_len);
+  if (!auth_len) {
+    DEBUG_LOG("Could not generate auth data with key %"PRIu32, key_id);
+    return 0;
+  }
+
+  *(uint32_t *)((unsigned char *)packet + info->length) = htonl(key_id);
+  info->length += 4 + auth_len;
+
+  return 1;
+}
+
+/* ================================================== */
+
+static int
+check_symmetric_auth(NTP_Packet *packet, NTP_PacketInfo *info)
+{
+  int trunc_len;
+
+  if (info->auth.mac.length < NTP_MIN_MAC_LENGTH)
+    return 0;
+
+  trunc_len = info->version == 4 && info->auth.mac.length <= NTP_MAX_V4_MAC_LENGTH ?
+              NTP_MAX_V4_MAC_LENGTH : NTP_MAX_MAC_LENGTH;
+
+  if (!KEY_CheckAuth(info->auth.mac.key_id, (void *)packet, info->auth.mac.start,
+                     (unsigned char *)packet + info->auth.mac.start + 4,
+                     info->auth.mac.length - 4, trunc_len - 4))
+    return 0;
+
+  return 1;
+}
+
+/* ================================================== */
+
+static void
+adjust_timestamp(NTP_AuthMode mode, uint32_t key_id, struct timespec *ts)
+{
+  switch (mode) {
+    case AUTH_SYMMETRIC:
+      ts->tv_nsec += KEY_GetAuthDelay(key_id);
+      UTI_NormaliseTimespec(ts);
+      break;
+    case AUTH_MSSNTP:
+      ts->tv_nsec += NSD_GetAuthDelay(key_id);
+      UTI_NormaliseTimespec(ts);
+    default:
+      break;
+  }
+}
+
+/* ================================================== */
+
+static NAU_Instance
+create_instance(NTP_AuthMode mode)
+{
+  NAU_Instance instance;
+
+  instance = MallocNew(struct NAU_Instance_Record);
+  instance->mode = mode;
+  instance->key_id = INACTIVE_AUTHKEY;
+
+  assert(sizeof (instance->key_id) == 4);
+
+  return instance;
+}
+
+/* ================================================== */
+
+NAU_Instance
+NAU_CreateNoneInstance(void)
+{
+  return create_instance(AUTH_NONE);
+}
+
+/* ================================================== */
+
+NAU_Instance
+NAU_CreateSymmetricInstance(uint32_t key_id)
+{
+  NAU_Instance instance = create_instance(AUTH_SYMMETRIC);
+
+  instance->key_id = key_id;
+
+  if (!KEY_KeyKnown(key_id))
+    LOG(LOGS_WARN, "Key %"PRIu32" is %s", key_id, "missing");
+  else if (!KEY_CheckKeyLength(key_id))
+    LOG(LOGS_WARN, "Key %"PRIu32" is %s", key_id, "too short");
+
+  return instance;
+}
+
+/* ================================================== */
+
+void
+NAU_DestroyInstance(NAU_Instance instance)
+{
+  Free(instance);
+}
+
+/* ================================================== */
+
+int
+NAU_IsAuthEnabled(NAU_Instance instance)
+{
+  return instance->mode != AUTH_NONE;
+}
+
+/* ================================================== */
+
+int
+NAU_GetSuggestedNtpVersion(NAU_Instance instance)
+{
+  /* If the MAC in NTPv4 packets would be truncated, prefer NTPv3 for
+     compatibility with older chronyd servers */
+  if (instance->mode == AUTH_SYMMETRIC &&
+      KEY_GetAuthLength(instance->key_id) + sizeof (instance->key_id) > NTP_MAX_V4_MAC_LENGTH)
+    return 3;
+
+  return NTP_VERSION;
+}
+
+/* ================================================== */
+
+int
+NAU_PrepareRequestAuth(NAU_Instance instance)
+{
+  switch (instance->mode) {
+    default:
+      break;
+  }
+
+  return 1;
+}
+
+/* ================================================== */
+
+void
+NAU_AdjustRequestTimestamp(NAU_Instance instance, struct timespec *ts)
+{
+  adjust_timestamp(instance->mode, instance->key_id, ts);
+}
+
+/* ================================================== */
+
+int
+NAU_GenerateRequestAuth(NAU_Instance instance, NTP_Packet *request, NTP_PacketInfo *info)
+{
+  switch (instance->mode) {
+    case AUTH_NONE:
+      break;
+    case AUTH_SYMMETRIC:
+      if (!generate_symmetric_auth(instance->key_id, request, info))
+        return 0;
+      break;
+    default:
+      assert(0);
+  }
+
+  return 1;
+}
+
+/* ================================================== */
+
+int
+NAU_CheckRequestAuth(NTP_Packet *request, NTP_PacketInfo *info)
+{
+  switch (info->auth.mode) {
+    case AUTH_NONE:
+      break;
+    case AUTH_SYMMETRIC:
+      if (!check_symmetric_auth(request, info))
+        return 0;
+      break;
+    case AUTH_MSSNTP:
+      /* MS-SNTP requests are not authenticated */
+      break;
+    default:
+      return 0;
+  }
+
+  return 1;
+}
+
+/* ================================================== */
+
+void
+NAU_AdjustResponseTimestamp(NTP_Packet *request, NTP_PacketInfo *info, struct timespec *ts)
+{
+  adjust_timestamp(info->auth.mode, info->auth.mac.key_id, ts);
+}
+
+/* ================================================== */
+
+int
+NAU_GenerateResponseAuth(NTP_Packet *request, NTP_PacketInfo *request_info,
+                         NTP_Packet *response, NTP_PacketInfo *response_info,
+                         NTP_Remote_Address *remote_addr, NTP_Local_Address *local_addr)
+{
+  switch (request_info->auth.mode) {
+    case AUTH_NONE:
+      break;
+    case AUTH_SYMMETRIC:
+      if (!generate_symmetric_auth(request_info->auth.mac.key_id, response, response_info))
+        return 0;
+      break;
+    case AUTH_MSSNTP:
+      /* Sign the packet asynchronously by ntp_signd */
+      if (!NSD_SignAndSendPacket(request_info->auth.mac.key_id, response, response_info,
+                                 remote_addr, local_addr))
+        return 0;
+      /* Don't send the original packet */
+      return 0;
+    default:
+      DEBUG_LOG("Could not authenticate response auth_mode=%d", (int)request_info->auth.mode);
+      return 0;
+  }
+
+  return 1;
+}
+
+/* ================================================== */
+
+int
+NAU_CheckResponseAuth(NAU_Instance instance, NTP_Packet *response, NTP_PacketInfo *info)
+{
+  /* If we don't expect the packet to be authenticated, ignore any
+     authentication data in the packet */
+  if (instance->mode == AUTH_NONE)
+    return 1;
+
+  /* The authentication must match the expected mode */
+  if (info->auth.mode != instance->mode)
+    return 0;
+
+  switch (info->auth.mode) {
+    case AUTH_NONE:
+      break;
+    case AUTH_SYMMETRIC:
+      /* Check if it is authenticated with the specified key */
+      if (info->auth.mac.key_id != instance->key_id)
+        return 0;
+      /* and that the MAC is valid */
+      if (!check_symmetric_auth(response, info))
+        return 0;
+      break;
+    default:
+      return 0;
+  }
+
+  return 1;
+}
diff --git a/ntp_auth.h b/ntp_auth.h
new file mode 100644 (file)
index 0000000..603ac17
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+  chronyd/chronyc - Programs for keeping computer clocks accurate.
+
+ **********************************************************************
+ * Copyright (C) Miroslav Lichvar  2019
+ * 
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ * 
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ * 
+ **********************************************************************
+
+  =======================================================================
+
+  Header file for NTP authentication
+  */
+
+#ifndef GOT_NTP_AUTH_H
+#define GOT_NTP_AUTH_H
+
+#include "addressing.h"
+#include "ntp.h"
+
+typedef struct NAU_Instance_Record *NAU_Instance;
+
+/* Create an authenticator instance in a specific mode */
+extern NAU_Instance NAU_CreateNoneInstance(void);
+extern NAU_Instance NAU_CreateSymmetricInstance(uint32_t key_id);
+
+/* Destroy an instance */
+extern void NAU_DestroyInstance(NAU_Instance instance);
+
+/* Check if an instance is not in the None mode */
+extern int NAU_IsAuthEnabled(NAU_Instance instance);
+
+/* Get NTP version recommended for better compatibility */
+extern int NAU_GetSuggestedNtpVersion(NAU_Instance instance);
+
+/* Perform operations necessary for NAU_GenerateRequestAuth() */
+extern int NAU_PrepareRequestAuth(NAU_Instance instance);
+
+/* Adjust a transmit timestamp for an estimated minimum time it takes to call
+   NAU_GenerateRequestAuth() */
+extern void NAU_AdjustRequestTimestamp(NAU_Instance instance, struct timespec *ts);
+
+/* Extend a request with data required by the authentication mode */
+extern int NAU_GenerateRequestAuth(NAU_Instance instance, NTP_Packet *request,
+                                   NTP_PacketInfo *info);
+
+/* Verify that a request is authentic */
+extern int NAU_CheckRequestAuth(NTP_Packet *request, NTP_PacketInfo *info);
+
+/* Adjust a transmit timestamp for an estimated minimum time it takes to call
+   NAU_GenerateResponseAuth() */
+extern void NAU_AdjustResponseTimestamp(NTP_Packet *request, NTP_PacketInfo *info,
+                                        struct timespec *ts);
+
+/* Extend a response with data required by the authentication mode.  This
+   function can be called only if the previous call of NAU_CheckRequestAuth()
+   was on the same request. */
+extern int NAU_GenerateResponseAuth(NTP_Packet *request, NTP_PacketInfo *request_info,
+                                    NTP_Packet *response, NTP_PacketInfo *response_info,
+                                    NTP_Remote_Address *remote_addr,
+                                    NTP_Local_Address *local_addr);
+
+/* Verify that a response is authentic */
+extern int NAU_CheckResponseAuth(NAU_Instance instance, NTP_Packet *response,
+                                 NTP_PacketInfo *info);
+
+#endif
index d8bd7b285be073fb552162a921eef548a2545001..fe1bb8af388679b80b70855c79487432d08edf25 100644 (file)
 #include "sysincl.h"
 
 #include "array.h"
+#include "ntp_auth.h"
 #include "ntp_core.h"
 #include "ntp_ext.h"
 #include "ntp_io.h"
-#include "ntp_signd.h"
 #include "memory.h"
 #include "sched.h"
 #include "reference.h"
@@ -128,9 +128,7 @@ struct NCR_Instance_Record {
   double offset_correction;     /* Correction applied to measured offset
                                    (e.g. for asymmetry in network delay) */
 
-  NTP_AuthMode auth_mode;       /* Authentication mode of our requests */
-  uint32_t auth_key_id;          /* The ID of the authentication key to
-                                   use. */
+  NAU_Instance auth;            /* Authentication */
 
   /* Count of transmitted packets since last valid response */
   unsigned int tx_count;
@@ -200,6 +198,7 @@ struct NCR_Instance_Record {
 typedef struct {
   NTP_Remote_Address addr;
   NTP_Local_Address local_addr;
+  NAU_Instance auth;
   int interval;
 } BroadcastDestination;
 
@@ -407,8 +406,10 @@ NCR_Finalise(void)
   if (server_sock_fd6 != INVALID_SOCK_FD)
     NIO_CloseServerSocket(server_sock_fd6);
 
-  for (i = 0; i < ARR_GetSize(broadcasts); i++)
+  for (i = 0; i < ARR_GetSize(broadcasts); i++) {
     NIO_CloseServerSocket(((BroadcastDestination *)ARR_GetElement(broadcasts, i))->local_addr.sock_fd);
+    NAU_DestroyInstance(((BroadcastDestination *)ARR_GetElement(broadcasts, i))->auth);
+  }
 
   ARR_DestroyInstance(broadcasts);
   ADF_DestroyTable(access_auth_table);
@@ -562,30 +563,14 @@ NCR_GetInstance(NTP_Remote_Address *remote_addr, NTP_Source_Type type, SourcePar
   result->auto_offline = params->auto_offline;
   result->poll_target = params->poll_target;
 
-  result->version = NTP_VERSION;
-
-  if (params->authkey == INACTIVE_AUTHKEY) {
-    result->auth_mode = AUTH_NONE;
-    result->auth_key_id = 0;
+  if (params->authkey != INACTIVE_AUTHKEY) {
+    result->auth = NAU_CreateSymmetricInstance(params->authkey);
   } else {
-    result->auth_mode = AUTH_SYMMETRIC;
-    result->auth_key_id = params->authkey;
-    if (!KEY_KeyKnown(result->auth_key_id)) {
-      LOG(LOGS_WARN, "Key %"PRIu32" used by source %s is %s",
-          result->auth_key_id, UTI_IPToString(&result->remote_addr.ip_addr),
-          "missing");
-    } else if (!KEY_CheckKeyLength(result->auth_key_id)) {
-      LOG(LOGS_WARN, "Key %"PRIu32" used by source %s is %s",
-          result->auth_key_id, UTI_IPToString(&result->remote_addr.ip_addr),
-          "too short");
-    }
-
-    /* If the MAC in NTPv4 packets would be truncated, use version 3 by
-       default for compatibility with older chronyd servers */
-    if (KEY_GetAuthLength(result->auth_key_id) + 4 > NTP_MAX_V4_MAC_LENGTH)
-      result->version = 3;
+    result->auth = NAU_CreateNoneInstance();
   }
 
+  result->version = NAU_GetSuggestedNtpVersion(result->auth);
+
   if (params->version)
     result->version = CLAMP(NTP_MIN_COMPAT_VERSION, params->version, NTP_VERSION);
 
@@ -639,6 +624,8 @@ NCR_DestroyInstance(NCR_Instance instance)
   if (instance->filter)
     SPF_DestroyInstance(instance->filter);
 
+  NAU_DestroyInstance(instance->auth);
+
   /* This will destroy the source instance inside the
      structure, which will cause reselection if this was the
      synchronising source etc. */
@@ -919,8 +906,7 @@ transmit_packet(NTP_Mode my_mode, /* The mode this machine wants to be */
                 int interleaved, /* Flag enabling interleaved mode */
                 int my_poll, /* The log2 of the local poll interval */
                 int version, /* The NTP version to be set in the packet */
-                int auth_mode, /* The authentication mode */
-                uint32_t key_id, /* The authentication key ID */
+                NAU_Instance auth, /* The authentication to be used for the packet */
                 NTP_int64 *remote_ntp_rx, /* The receive timestamp from received packet */
                 NTP_int64 *remote_ntp_tx, /* The transmit timestamp from received packet */
                 NTP_Local_Timestamp *local_rx, /* The RX time of the received packet */
@@ -938,9 +924,9 @@ transmit_packet(NTP_Mode my_mode, /* The mode this machine wants to be */
 {
   NTP_PacketInfo info;
   NTP_Packet message;
-  int auth_len, max_auth_len, ret, precision;
   struct timespec local_receive, local_transmit;
   double smooth_offset, local_transmit_err;
+  int ret, precision;
   NTP_int64 ts_fuzz;
 
   /* Parameters read from reference module */
@@ -950,6 +936,8 @@ transmit_packet(NTP_Mode my_mode, /* The mode this machine wants to be */
   struct timespec our_ref_time;
   double our_root_delay, our_root_dispersion;
 
+  assert(auth || (request && request_info));
+
   /* Don't reply with version higher than ours */
   if (version > NTP_VERSION) {
     version = NTP_VERSION;
@@ -1065,39 +1053,27 @@ transmit_packet(NTP_Mode my_mode, /* The mode this machine wants to be */
     if (smooth_time)
       UTI_AddDoubleToTimespec(&local_transmit, smooth_offset, &local_transmit);
 
-    /* Authenticate the packet */
-
-    if (auth_mode == AUTH_SYMMETRIC || auth_mode == AUTH_MSSNTP) {
-      /* Pre-compensate the transmit time by approximately how long it will
-         take to generate the authentication data */
-      local_transmit.tv_nsec += auth_mode == AUTH_SYMMETRIC ?
-                                KEY_GetAuthDelay(key_id) : NSD_GetAuthDelay(key_id);
-      UTI_NormaliseTimespec(&local_transmit);
-      UTI_TimespecToNtp64(interleaved ? &local_tx->ts : &local_transmit,
-                          &message.transmit_ts, &ts_fuzz);
-
-      if (auth_mode == AUTH_SYMMETRIC) {
-        /* Truncate long MACs in NTPv4 packets to allow deterministic parsing
-           of extension fields (RFC 7822) */
-        max_auth_len = (version == 4 ?
-                        NTP_MAX_V4_MAC_LENGTH : (sizeof (message) - info.length)) - 4;
-
-        auth_len = KEY_GenerateAuth(key_id, (unsigned char *)&message, info.length,
-                                    (unsigned char *)&message + info.length + 4, max_auth_len);
-        if (!auth_len) {
-          DEBUG_LOG("Could not generate auth data with key %"PRIu32, key_id);
-          return 0;
-        }
+    /* Pre-compensate the transmit time by approximately how long it will take
+       to generate the authentication data */
+    if (auth)
+      NAU_AdjustRequestTimestamp(auth, &local_transmit);
+    else
+      NAU_AdjustResponseTimestamp(request, request_info, &local_transmit);
 
-        *(uint32_t *)((unsigned char *)&message + info.length) = htonl(key_id);
-        info.length += 4 + auth_len;
-      } else if (auth_mode == AUTH_MSSNTP) {
-        /* MS-SNTP packets are signed (asynchronously) by ntp_signd */
-        return NSD_SignAndSendPacket(key_id, &message, &info, where_to, from);
+    UTI_TimespecToNtp64(interleaved ? &local_tx->ts : &local_transmit,
+                        &message.transmit_ts, &ts_fuzz);
+
+    /* Generate the authentication data */
+    if (auth) {
+      if (!NAU_GenerateRequestAuth(auth, &message, &info)) {
+        DEBUG_LOG("Could not generate request auth");
+        return 0;
       }
     } else {
-      UTI_TimespecToNtp64(interleaved ? &local_tx->ts : &local_transmit,
-                          &message.transmit_ts, &ts_fuzz);
+      if (!NAU_GenerateResponseAuth(request, request_info, &message, &info, where_to, from)) {
+        DEBUG_LOG("Could not generate response auth");
+        return 0;
+      }
     }
 
     /* Do not send a packet with a non-zero transmit timestamp which is
@@ -1174,6 +1150,16 @@ transmit_timeout(void *arg)
 
   DEBUG_LOG("Transmit timeout for %s", UTI_IPSockAddrToString(&inst->remote_addr));
 
+  /* Prepare authentication */
+  if (!NAU_PrepareRequestAuth(inst->auth)) {
+    if (inst->burst_total_samples_to_go > 0)
+      inst->burst_total_samples_to_go--;
+    adjust_poll(inst, 0.25);
+    SRC_UpdateReachability(inst->source, 0);
+    restart_timeout(inst, get_transmit_delay(inst, 1, 0.0));
+    return;
+  }
+
   /* Open new client socket */
   if (inst->mode == MODE_CLIENT) {
     close_client_socket(inst);
@@ -1225,7 +1211,7 @@ transmit_timeout(void *arg)
 
   /* Send the request (which may also be a response in the symmetric mode) */
   sent = transmit_packet(inst->mode, interleaved, inst->local_poll, inst->version,
-                         inst->auth_mode, inst->auth_key_id,
+                         inst->auth,
                          initial ? NULL : &inst->remote_ntp_rx,
                          initial ? &inst->init_remote_ntp_tx : &inst->remote_ntp_tx,
                          initial ? &inst->init_local_rx : &inst->local_rx,
@@ -1410,45 +1396,6 @@ parse_packet(NTP_Packet *packet, int length, NTP_PacketInfo *info)
 
 /* ================================================== */
 
-static int
-check_symmetric_auth(NTP_Packet *packet, NTP_PacketInfo *info)
-{
-  int trunc_len;
-
-  if (info->auth.mac.length < NTP_MIN_MAC_LENGTH)
-    return 0;
-
-  trunc_len = info->version == 4 && info->auth.mac.length <= NTP_MAX_V4_MAC_LENGTH ?
-              NTP_MAX_V4_MAC_LENGTH : NTP_MAX_MAC_LENGTH;
-
-  if (!KEY_CheckAuth(info->auth.mac.key_id, (void *)packet, info->auth.mac.start,
-                     (unsigned char *)packet + info->auth.mac.start + 4,
-                     info->auth.mac.length - 4, trunc_len - 4))
-    return 0;
-
-  return 1;
-}
-
-/* ================================================== */
-
-static int
-check_packet_auth(NTP_Packet *packet, NTP_PacketInfo *info,
-                  NTP_AuthMode *auth_mode, uint32_t *key_id)
-{
-  *auth_mode = info->auth.mode;
-
-  if (info->auth.mode != AUTH_SYMMETRIC)
-    return 0;
-
-  if (!check_symmetric_auth(packet, info))
-    return 0;
-
-  *key_id = info->auth.mac.key_id;
-  return 1;
-}
-
-/* ================================================== */
-
 static int
 check_delay_ratio(NCR_Instance inst, SST_Stats stats,
                 struct timespec *sample_time, double delay)
@@ -1610,10 +1557,9 @@ process_response(NCR_Instance inst, NTP_Local_Address *local_addr,
   SST_Stats stats;
 
   int pkt_leap, pkt_version;
-  uint32_t pkt_refid, pkt_key_id;
+  uint32_t pkt_refid;
   double pkt_root_delay;
   double pkt_root_dispersion;
-  NTP_AuthMode pkt_auth_mode;
 
   /* The skew and estimated frequency offset relative to the remote source */
   double skew, source_freq_lo, source_freq_hi;
@@ -1668,14 +1614,8 @@ process_response(NCR_Instance inst, NTP_Local_Address *local_addr,
   /* Test 4 would check for denied access.  It would always pass as this
      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, 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->auth_mode == AUTH_NONE ||
-          (check_packet_auth(message, info, &pkt_auth_mode, &pkt_key_id) &&
-           pkt_auth_mode == inst->auth_mode && pkt_key_id == inst->auth_key_id);
+  /* Test 5 checks for authentication failure */
+  test5 = NAU_CheckResponseAuth(inst->auth, message, info);
 
   /* Test 6 checks for unsynchronised server */
   test6 = pkt_leap != LEAP_Unsynchronised &&
@@ -1994,7 +1934,7 @@ process_response(NCR_Instance inst, NTP_Local_Address *local_addr,
                                test5) << 1 | test6) << 1 | test7) << 1 |
                             testA) << 1 | testB) << 1 | testC) << 1 | testD;
     inst->report.interleaved = interleaved_packet;
-    inst->report.authenticated = inst->auth_mode != AUTH_NONE;
+    inst->report.authenticated = NAU_IsAuthEnabled(inst->auth);
     inst->report.tx_tss_char = tss_chars[local_transmit.source];
     inst->report.rx_tss_char = tss_chars[local_receive.source];
 
@@ -2179,9 +2119,7 @@ NCR_ProcessRxUnknown(NTP_Remote_Address *remote_addr, NTP_Local_Address *local_a
   NTP_Mode my_mode;
   NTP_int64 *local_ntp_rx, *local_ntp_tx;
   NTP_Local_Timestamp local_tx, *tx_ts;
-  int valid_auth, log_index, interleaved, poll, version;
-  NTP_AuthMode auth_mode;
-  uint32_t key_id;
+  int log_index, interleaved, poll, version;
 
   /* Ignore the packet if it wasn't received by server socket */
   if (!NIO_IsServerSocket(local_addr->sock_fd)) {
@@ -2230,23 +2168,10 @@ NCR_ProcessRxUnknown(NTP_Remote_Address *remote_addr, NTP_Local_Address *local_a
       return;
   }
 
-  /* Check if the packet includes MAC that authenticates properly */
-  valid_auth = check_packet_auth(message, &info, &auth_mode, &key_id);
-
-  /* If authentication failed, select whether and how we should respond */
-  if (!valid_auth) {
-    switch (auth_mode) {
-      case AUTH_NONE:
-        /* Reply with no MAC */
-        break;
-      case AUTH_MSSNTP:
-        /* Ignore the failure (MS-SNTP servers don't check client MAC) */
-        break;
-      default:
-        /* Discard packets in other modes */
-        DEBUG_LOG("NTP packet discarded auth_mode=%u", auth_mode);
-        return;
-    }
+  /* Check authentication */
+  if (!NAU_CheckRequestAuth(message, &info)) {
+    DEBUG_LOG("NTP packet discarded auth mode=%d", (int)info.auth.mode);
+    return;
   }
 
   /* If it is an NTPv4 packet with a long MAC and no extension fields,
@@ -2288,8 +2213,8 @@ NCR_ProcessRxUnknown(NTP_Remote_Address *remote_addr, NTP_Local_Address *local_a
   poll = MAX(poll, message->poll);
 
   /* Send a reply */
-  transmit_packet(my_mode, interleaved, poll, version,
-                  auth_mode, key_id, &message->receive_ts, &message->transmit_ts,
+  transmit_packet(my_mode, interleaved, poll, version, NULL,
+                  &message->receive_ts, &message->transmit_ts,
                   rx_ts, tx_ts, local_ntp_rx, NULL, remote_addr, local_addr,
                   message, &info);
 
@@ -2727,8 +2652,9 @@ broadcast_timeout(void *arg)
   UTI_ZeroNtp64(&orig_ts);
   zero_local_timestamp(&recv_ts);
 
-  transmit_packet(MODE_BROADCAST, 0, poll, NTP_VERSION, 0, 0, &orig_ts, &orig_ts, &recv_ts,
-                  NULL, NULL, NULL, &destination->addr, &destination->local_addr, NULL, NULL);
+  transmit_packet(MODE_BROADCAST, 0, poll, NTP_VERSION, destination->auth,
+                  &orig_ts, &orig_ts, &recv_ts, NULL, NULL, NULL,
+                  &destination->addr, &destination->local_addr, NULL, NULL);
 
   /* Requeue timeout.  We don't care if interval drifts gradually. */
   SCH_AddTimeoutInClass(destination->interval, get_separation(poll), SAMPLING_RANDOMNESS,
@@ -2749,6 +2675,7 @@ NCR_AddBroadcastDestination(IPAddr *addr, unsigned short port, int interval)
   destination->local_addr.ip_addr.family = IPADDR_UNSPEC;
   destination->local_addr.if_index = INVALID_IF_INDEX;
   destination->local_addr.sock_fd = NIO_OpenServerSocket(&destination->addr);
+  destination->auth = NAU_CreateNoneInstance();
   destination->interval = CLAMP(1, interval, 1 << MAX_POLL);
 
   SCH_AddTimeoutInClass(destination->interval, MAX_SAMPLING_SEPARATION, SAMPLING_RANDOMNESS,
diff --git a/stubs.c b/stubs.c
index f7845ec5a2f5d2cad84f0cd628e8db3716f71964..41b8dcc97b7000d690a6142e9698a0910447ddca 100644 (file)
--- a/stubs.c
+++ b/stubs.c
@@ -412,7 +412,8 @@ NSD_GetAuthDelay(uint32_t key_id)
 }
 
 int
-NSD_SignAndSendPacket(uint32_t key_id, NTP_Packet *packet, NTP_Remote_Address *remote_addr, NTP_Local_Address *local_addr, int length)
+NSD_SignAndSendPacket(uint32_t key_id, NTP_Packet *packet, NTP_PacketInfo *info,
+                      NTP_Remote_Address *remote_addr, NTP_Local_Address *local_addr)
 {
   return 0;
 }