diff --git a/cmdmon.c b/cmdmon.c index ba6e985..5e3fc55 100644 --- a/cmdmon.c +++ b/cmdmon.c @@ -743,6 +743,8 @@ handle_add_source(CMD_Request *rx_message, CMD_Reply *tx_message) (ntohl(rx_message->data.ntp_source.flags) & REQ_ADDSRC_NOSELECT ? SRC_SELECT_NOSELECT : 0) | (ntohl(rx_message->data.ntp_source.flags) & REQ_ADDSRC_TRUST ? SRC_SELECT_TRUST : 0) | (ntohl(rx_message->data.ntp_source.flags) & REQ_ADDSRC_REQUIRE ? SRC_SELECT_REQUIRE : 0); + params.nts = 0; + params.nts_port = 0; status = NSR_AddSourceByName(name, port, pool, type, ¶ms); switch (status) { diff --git a/cmdparse.c b/cmdparse.c index 37037d1..0124586 100644 --- a/cmdparse.c +++ b/cmdparse.c @@ -62,6 +62,8 @@ CPS_ParseNTPSourceAdd(char *line, CPS_NTP_Source *src) src->params.filter_length = 0; src->params.interleaved = 0; src->params.sel_options = 0; + src->params.nts = 0; + src->params.nts_port = SRC_DEFAULT_NTSPORT; src->params.authkey = INACTIVE_AUTHKEY; src->params.max_delay = SRC_DEFAULT_MAXDELAY; src->params.max_delay_ratio = SRC_DEFAULT_MAXDELAYRATIO; @@ -140,6 +142,11 @@ CPS_ParseNTPSourceAdd(char *line, CPS_NTP_Source *src) } else if (!strcasecmp(cmd, "minstratum")) { if (sscanf(line, "%d%n", &src->params.min_stratum, &n) != 1) return 0; + } else if (!strcasecmp(cmd, "nts")) { + src->params.nts = 1; + } else if (!strcasecmp(cmd, "ntsport")) { + if (sscanf(line, "%d%n", &src->params.nts_port, &n) != 1) + return 0; } else if (!strcasecmp(cmd, "offset")) { if (sscanf(line, "%lf%n", &src->params.offset, &n) != 1) return 0; diff --git a/ntp.h b/ntp.h index 3edc18d..90f24c2 100644 --- a/ntp.h +++ b/ntp.h @@ -119,6 +119,7 @@ typedef enum { NTP_AUTH_SYMMETRIC, /* MAC using symmetric key (RFC 1305, RFC 5905) */ NTP_AUTH_MSSNTP, /* MS-SNTP authenticator field */ NTP_AUTH_MSSNTP_EXT, /* MS-SNTP extended authenticator field */ + NTP_AUTH_NTS, /* Network Time Security (RFC ????) */ } NTP_AuthMode; /* Structure describing an NTP packet */ diff --git a/ntp_auth.c b/ntp_auth.c index 4f99154..9c1056d 100644 --- a/ntp_auth.c +++ b/ntp_auth.c @@ -34,6 +34,9 @@ #include "ntp_auth.h" #include "ntp_ext.h" #include "ntp_signd.h" +#include "nts_ntp.h" +#include "nts_ntp_client.h" +#include "nts_ntp_server.h" #include "srcparams.h" #include "util.h" @@ -42,6 +45,7 @@ struct NAU_Instance_Record { NTP_AuthMode mode; /* Authentication mode of NTP packets */ uint32_t key_id; /* Identifier of a symmetric key */ + NNC_Instance nts; /* Client NTS state */ }; /* ================================================== */ @@ -131,6 +135,7 @@ create_instance(NTP_AuthMode mode) instance = MallocNew(struct NAU_Instance_Record); instance->mode = mode; instance->key_id = INACTIVE_AUTHKEY; + instance->nts = NULL; assert(sizeof (instance->key_id) == 4); @@ -164,9 +169,23 @@ NAU_CreateSymmetricInstance(uint32_t key_id) /* ================================================== */ +NAU_Instance +NAU_CreateNtsInstance(IPSockAddr *nts_address, const char *name, const IPSockAddr *ntp_address) +{ + NAU_Instance instance = create_instance(NTP_AUTH_NTS); + + instance->nts = NNC_CreateInstance(nts_address, name, ntp_address); + + return instance; +} + +/* ================================================== */ + void NAU_DestroyInstance(NAU_Instance instance) { + if (instance->nts) + NNC_DestroyInstance(instance->nts); Free(instance); } @@ -198,6 +217,10 @@ int NAU_PrepareRequestAuth(NAU_Instance instance) { switch (instance->mode) { + case NTP_AUTH_NTS: + if (!NNC_PrepareForAuth(instance->nts)) + return 0; + break; default: break; } @@ -225,6 +248,10 @@ NAU_GenerateRequestAuth(NAU_Instance instance, NTP_Packet *request, NTP_PacketIn if (!generate_symmetric_auth(instance->key_id, request, info)) return 0; break; + case NTP_AUTH_NTS: + if (!NNC_GenerateRequestAuth(instance->nts, request, info)) + return 0; + break; default: assert(0); } @@ -307,6 +334,12 @@ NAU_ParsePacket(NTP_Packet *packet, NTP_PacketInfo *info) assert(ef_length > 0); switch (ef_type) { + case NTP_EF_NTS_UNIQUE_IDENTIFIER: + case NTP_EF_NTS_COOKIE: + case NTP_EF_NTS_COOKIE_PLACEHOLDER: + case NTP_EF_NTS_AUTH_AND_EEF: + info->auth.mode = NTP_AUTH_NTS; + break; default: DEBUG_LOG("Unknown extension field type=%x", (unsigned int)ef_type); } @@ -351,6 +384,10 @@ NAU_CheckRequestAuth(NTP_Packet *request, NTP_PacketInfo *info, uint32_t *kod) case NTP_AUTH_MSSNTP: /* MS-SNTP requests are not authenticated */ break; + case NTP_AUTH_NTS: + if (!NNS_CheckRequestAuth(request, info, kod)) + return 0; + break; default: return 0; } @@ -388,6 +425,10 @@ NAU_GenerateResponseAuth(NTP_Packet *request, NTP_PacketInfo *request_info, return 0; /* Don't send the original packet */ return 0; + case NTP_AUTH_NTS: + if (!NNS_GenerateResponseAuth(request, request_info, response, response_info, kod)) + return 0; + break; default: DEBUG_LOG("Could not authenticate response auth_mode=%d", (int)request_info->auth.mode); return 0; @@ -416,6 +457,10 @@ NAU_CheckResponseAuth(NAU_Instance instance, NTP_Packet *response, NTP_PacketInf if (!check_symmetric_auth(response, info)) return 0; break; + case NTP_AUTH_NTS: + if (!NNC_CheckResponseAuth(instance->nts, response, info)) + return 0; + break; default: return 0; } @@ -432,6 +477,9 @@ NAU_ChangeAddress(NAU_Instance instance, IPAddr *address) case NTP_AUTH_NONE: case NTP_AUTH_SYMMETRIC: break; + case NTP_AUTH_NTS: + NNC_ChangeAddress(instance->nts, address); + break; default: assert(0); } diff --git a/ntp_auth.h b/ntp_auth.h index 8211c63..b1f06eb 100644 --- a/ntp_auth.h +++ b/ntp_auth.h @@ -35,6 +35,8 @@ 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); +extern NAU_Instance NAU_CreateNtsInstance(IPSockAddr *nts_address, const char *name, + const IPSockAddr *ntp_address); /* Destroy an instance */ extern void NAU_DestroyInstance(NAU_Instance instance); diff --git a/ntp_core.c b/ntp_core.c index 0c6349f..68b86e1 100644 --- a/ntp_core.c +++ b/ntp_core.c @@ -559,7 +559,17 @@ NCR_CreateInstance(NTP_Remote_Address *remote_addr, NTP_Source_Type type, result->auto_offline = params->auto_offline; result->poll_target = params->poll_target; - if (params->authkey != INACTIVE_AUTHKEY) { + if (params->nts) { + IPSockAddr nts_address; + + if (result->mode == MODE_ACTIVE) + LOG(LOGS_WARN, "NTS not supported with peers"); + + nts_address.ip_addr = remote_addr->ip_addr; + nts_address.port = params->nts_port; + + result->auth = NAU_CreateNtsInstance(&nts_address, name, &result->remote_addr); + } else if (params->authkey != INACTIVE_AUTHKEY) { result->auth = NAU_CreateSymmetricInstance(params->authkey); } else { result->auth = NAU_CreateNoneInstance(); diff --git a/srcparams.h b/srcparams.h index deabd23..59d8a23 100644 --- a/srcparams.h +++ b/srcparams.h @@ -52,6 +52,8 @@ typedef struct { int filter_length; int interleaved; int sel_options; + int nts; + int nts_port; uint32_t authkey; double max_delay; double max_delay_ratio; @@ -74,6 +76,7 @@ typedef struct { #define SRC_DEFAULT_MINSAMPLES (-1) #define SRC_DEFAULT_MAXSAMPLES (-1) #define SRC_DEFAULT_ASYMMETRY 1.0 +#define SRC_DEFAULT_NTSPORT 11443 #define INACTIVE_AUTHKEY 0 /* Flags for source selection */