diff --git a/configure b/configure index b448b72..d0927a0 100755 --- 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 index 0000000..8a64b62 --- /dev/null +++ b/ntp_auth.c @@ -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 index 0000000..603ac17 --- /dev/null +++ b/ntp_auth.h @@ -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 diff --git a/ntp_core.c b/ntp_core.c index d8bd7b2..fe1bb8a 100644 --- a/ntp_core.c +++ b/ntp_core.c @@ -30,10 +30,10 @@ #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 */ + /* 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); - 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); + 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; - } - - *(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); + /* 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 f7845ec..41b8dcc 100644 --- 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; }