ntp: refactor selection of authentication mode
Replace the flag that enables authentication using a symmetric key with an enum. Specify crypto-NAK as a special mode used for responses instead of relying on zero key ID. Also, rework check_packet_auth() to always save the mode and key ID.
This commit is contained in:
parent
8220e51ae4
commit
61dd4e0ccb
1 changed files with 54 additions and 32 deletions
86
ntp_core.c
86
ntp_core.c
|
@ -60,6 +60,15 @@ typedef enum {
|
||||||
MD_BURST_WAS_ONLINE, /* Burst sampling, return to online afterwards */
|
MD_BURST_WAS_ONLINE, /* Burst sampling, return to online afterwards */
|
||||||
} OperatingMode;
|
} OperatingMode;
|
||||||
|
|
||||||
|
/* ================================================== */
|
||||||
|
/* Enumeration for authentication modes of NTP packets */
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
AUTH_NONE = 0, /* No authentication */
|
||||||
|
AUTH_CRYPTO_NAK, /* Empty MAC indicating authentication error */
|
||||||
|
AUTH_SYMMETRIC, /* MAC using symmetric key (RFC 1305, RFC 5905) */
|
||||||
|
} AuthenticationMode;
|
||||||
|
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
/* Structure used for holding a single peer/server's
|
/* Structure used for holding a single peer/server's
|
||||||
protocol machine */
|
protocol machine */
|
||||||
|
@ -122,12 +131,7 @@ struct NCR_Instance_Record {
|
||||||
double offset_correction; /* Correction applied to measured offset
|
double offset_correction; /* Correction applied to measured offset
|
||||||
(e.g. for asymmetry in network delay) */
|
(e.g. for asymmetry in network delay) */
|
||||||
|
|
||||||
int do_auth; /* Flag indicating whether we
|
AuthenticationMode auth_mode; /* Authentication mode of our requests */
|
||||||
authenticate packets we send to
|
|
||||||
this machine (if it's serving us or
|
|
||||||
the association is symmetric). Note
|
|
||||||
: we don't authenticate if we can't
|
|
||||||
find the key in our database. */
|
|
||||||
uint32_t auth_key_id; /* The ID of the authentication key to
|
uint32_t auth_key_id; /* The ID of the authentication key to
|
||||||
use. */
|
use. */
|
||||||
|
|
||||||
|
@ -495,10 +499,10 @@ NCR_GetInstance(NTP_Remote_Address *remote_addr, NTP_Source_Type type, SourcePar
|
||||||
result->version = NTP_VERSION;
|
result->version = NTP_VERSION;
|
||||||
|
|
||||||
if (params->authkey == INACTIVE_AUTHKEY) {
|
if (params->authkey == INACTIVE_AUTHKEY) {
|
||||||
result->do_auth = 0;
|
result->auth_mode = AUTH_NONE;
|
||||||
result->auth_key_id = 0;
|
result->auth_key_id = 0;
|
||||||
} else {
|
} else {
|
||||||
result->do_auth = 1;
|
result->auth_mode = AUTH_SYMMETRIC;
|
||||||
result->auth_key_id = params->authkey;
|
result->auth_key_id = params->authkey;
|
||||||
if (!KEY_KeyKnown(result->auth_key_id)) {
|
if (!KEY_KeyKnown(result->auth_key_id)) {
|
||||||
LOG(LOGS_WARN, LOGF_NtpCore, "Key %"PRIu32" used by source %s is %s",
|
LOG(LOGS_WARN, LOGF_NtpCore, "Key %"PRIu32" used by source %s is %s",
|
||||||
|
@ -787,7 +791,7 @@ static int
|
||||||
transmit_packet(NTP_Mode my_mode, /* The mode this machine wants to be */
|
transmit_packet(NTP_Mode my_mode, /* The mode this machine wants to be */
|
||||||
int my_poll, /* The log2 of the local poll interval */
|
int my_poll, /* The log2 of the local poll interval */
|
||||||
int version, /* The NTP version to be set in the packet */
|
int version, /* The NTP version to be set in the packet */
|
||||||
int do_auth, /* Boolean indicating whether to authenticate the packet or not */
|
int auth_mode, /* The authentication mode */
|
||||||
uint32_t key_id, /* The authentication key ID */
|
uint32_t key_id, /* The authentication key ID */
|
||||||
NTP_int64 *orig_ts, /* Originate timestamp (from received packet) */
|
NTP_int64 *orig_ts, /* Originate timestamp (from received packet) */
|
||||||
struct timeval *local_rx, /* Local time request packet was received */
|
struct timeval *local_rx, /* Local time request packet was received */
|
||||||
|
@ -911,8 +915,9 @@ transmit_packet(NTP_Mode my_mode, /* The mode this machine wants to be */
|
||||||
|
|
||||||
length = NTP_NORMAL_PACKET_LENGTH;
|
length = NTP_NORMAL_PACKET_LENGTH;
|
||||||
|
|
||||||
/* Authenticate */
|
/* Authenticate the packet if needed */
|
||||||
if (do_auth && key_id) {
|
|
||||||
|
if (auth_mode == AUTH_SYMMETRIC) {
|
||||||
/* Pre-compensate the transmit time by approx. how long it will
|
/* Pre-compensate the transmit time by approx. how long it will
|
||||||
take to generate the authentication data. */
|
take to generate the authentication data. */
|
||||||
local_transmit.tv_usec += KEY_GetAuthDelay(key_id);
|
local_transmit.tv_usec += KEY_GetAuthDelay(key_id);
|
||||||
|
@ -932,8 +937,7 @@ transmit_packet(NTP_Mode my_mode, /* The mode this machine wants to be */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (do_auth) {
|
if (auth_mode == AUTH_CRYPTO_NAK) {
|
||||||
/* Zero key ID means crypto-NAK, append only the ID without any data */
|
|
||||||
message.auth_keyid = 0;
|
message.auth_keyid = 0;
|
||||||
length += sizeof (message.auth_keyid);
|
length += sizeof (message.auth_keyid);
|
||||||
}
|
}
|
||||||
|
@ -1011,7 +1015,7 @@ transmit_timeout(void *arg)
|
||||||
|
|
||||||
/* Send a client packet, don't store the local tx values
|
/* Send a client packet, don't store the local tx values
|
||||||
as the reply will be ignored */
|
as the reply will be ignored */
|
||||||
transmit_packet(MODE_CLIENT, inst->local_poll, inst->version, 0, 0,
|
transmit_packet(MODE_CLIENT, inst->local_poll, inst->version, AUTH_NONE, 0,
|
||||||
&inst->remote_orig, &inst->local_rx, NULL, NULL,
|
&inst->remote_orig, &inst->local_rx, NULL, NULL,
|
||||||
&inst->remote_addr, &local_addr);
|
&inst->remote_addr, &local_addr);
|
||||||
|
|
||||||
|
@ -1027,7 +1031,7 @@ transmit_timeout(void *arg)
|
||||||
|
|
||||||
sent = transmit_packet(inst->mode, inst->local_poll,
|
sent = transmit_packet(inst->mode, inst->local_poll,
|
||||||
inst->version,
|
inst->version,
|
||||||
inst->do_auth, inst->auth_key_id,
|
inst->auth_mode, inst->auth_key_id,
|
||||||
&inst->remote_orig,
|
&inst->remote_orig,
|
||||||
&inst->local_rx, &inst->local_tx, &inst->local_ntp_tx,
|
&inst->local_rx, &inst->local_tx, &inst->local_ntp_tx,
|
||||||
&inst->remote_addr,
|
&inst->remote_addr,
|
||||||
|
@ -1102,7 +1106,8 @@ check_packet_format(NTP_Packet *message, int length)
|
||||||
/* ================================================== */
|
/* ================================================== */
|
||||||
|
|
||||||
static int
|
static int
|
||||||
check_packet_auth(NTP_Packet *pkt, int length, int *has_auth, uint32_t *key_id)
|
check_packet_auth(NTP_Packet *pkt, int length,
|
||||||
|
AuthenticationMode *auth_mode, uint32_t *key_id)
|
||||||
{
|
{
|
||||||
int i, version, remainder, ext_length;
|
int i, version, remainder, ext_length;
|
||||||
unsigned char *data;
|
unsigned char *data;
|
||||||
|
@ -1124,10 +1129,8 @@ check_packet_auth(NTP_Packet *pkt, int length, int *has_auth, uint32_t *key_id)
|
||||||
id = ntohl(*(uint32_t *)(data + i));
|
id = ntohl(*(uint32_t *)(data + i));
|
||||||
if (KEY_CheckAuth(id, (void *)pkt, i, (void *)(data + i + 4),
|
if (KEY_CheckAuth(id, (void *)pkt, i, (void *)(data + i + 4),
|
||||||
remainder - 4)) {
|
remainder - 4)) {
|
||||||
if (key_id)
|
*auth_mode = AUTH_SYMMETRIC;
|
||||||
*key_id = id;
|
*key_id = id;
|
||||||
if (has_auth)
|
|
||||||
*has_auth = 1;
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1150,8 +1153,13 @@ check_packet_auth(NTP_Packet *pkt, int length, int *has_auth, uint32_t *key_id)
|
||||||
/* This is not 100% reliable as a MAC could fail to authenticate and could
|
/* 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
|
pass as an extension field, leaving reminder smaller than the minimum MAC
|
||||||
length. Not a big problem, at worst we won't reply with a crypto-NAK. */
|
length. Not a big problem, at worst we won't reply with a crypto-NAK. */
|
||||||
if (has_auth)
|
if (remainder >= NTP_MIN_MAC_LENGTH) {
|
||||||
*has_auth = remainder >= NTP_MIN_MAC_LENGTH;
|
*auth_mode = AUTH_SYMMETRIC;
|
||||||
|
*key_id = ntohl(*(uint32_t *)(data + i));
|
||||||
|
} else {
|
||||||
|
*auth_mode = AUTH_NONE;
|
||||||
|
*key_id = 0;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1165,6 +1173,7 @@ receive_packet(NTP_Packet *message, struct timeval *now, double now_err, NCR_Ins
|
||||||
uint32_t pkt_refid, pkt_key_id;
|
uint32_t pkt_refid, pkt_key_id;
|
||||||
double pkt_root_delay;
|
double pkt_root_delay;
|
||||||
double pkt_root_dispersion;
|
double pkt_root_dispersion;
|
||||||
|
AuthenticationMode pkt_auth_mode;
|
||||||
|
|
||||||
/* The local time to which the (offset, delay, dispersion) triple will
|
/* The local time to which the (offset, delay, dispersion) triple will
|
||||||
be taken to relate. For client/server operation this is practically
|
be taken to relate. For client/server operation this is practically
|
||||||
|
@ -1254,9 +1263,9 @@ receive_packet(NTP_Packet *message, struct timeval *now, double now_err, NCR_Ins
|
||||||
is bad, or it's authenticated with a different key than expected, it's got
|
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
|
to fail. If we don't expect the packet to be authenticated, just ignore
|
||||||
the test. */
|
the test. */
|
||||||
test5 = !inst->do_auth ||
|
test5 = inst->auth_mode == AUTH_NONE ||
|
||||||
(check_packet_auth(message, length, NULL, &pkt_key_id) &&
|
(check_packet_auth(message, length, &pkt_auth_mode, &pkt_key_id) &&
|
||||||
pkt_key_id == inst->auth_key_id);
|
pkt_auth_mode == inst->auth_mode && pkt_key_id == inst->auth_key_id);
|
||||||
|
|
||||||
/* Test 6 checks for unsynchronised server */
|
/* Test 6 checks for unsynchronised server */
|
||||||
test6 = pkt_leap != LEAP_Unsynchronised &&
|
test6 = pkt_leap != LEAP_Unsynchronised &&
|
||||||
|
@ -1663,7 +1672,8 @@ NCR_ProcessUnknown
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
NTP_Mode pkt_mode, my_mode;
|
NTP_Mode pkt_mode, my_mode;
|
||||||
int has_auth, valid_auth, log_index;
|
int valid_auth, log_index;
|
||||||
|
AuthenticationMode auth_mode;
|
||||||
uint32_t key_id;
|
uint32_t key_id;
|
||||||
|
|
||||||
/* Ignore the packet if it wasn't received by server socket */
|
/* Ignore the packet if it wasn't received by server socket */
|
||||||
|
@ -1709,21 +1719,33 @@ NCR_ProcessUnknown
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if the packet includes MAC that authenticates properly */
|
/* Check if the packet includes MAC that authenticates properly */
|
||||||
valid_auth = check_packet_auth(message, length, &has_auth, &key_id);
|
valid_auth = check_packet_auth(message, length, &auth_mode, &key_id);
|
||||||
|
|
||||||
/* If authentication failed, reply with crypto-NAK */
|
/* If authentication failed, select whether and how we should respond */
|
||||||
if (!valid_auth)
|
if (!valid_auth) {
|
||||||
key_id = 0;
|
switch (auth_mode) {
|
||||||
|
case AUTH_NONE:
|
||||||
|
/* Reply with no MAC */
|
||||||
|
break;
|
||||||
|
case AUTH_SYMMETRIC:
|
||||||
|
/* Reply with crypto-NAK */
|
||||||
|
auth_mode = AUTH_CRYPTO_NAK;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
/* Discard packets in other modes */
|
||||||
|
DEBUG_LOG(LOGF_NtpCore, "NTP packet discarded auth_mode=%d", auth_mode);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Send a reply.
|
/* Send a reply.
|
||||||
- copy the poll value as the client may use it to control its polling
|
- copy the poll value as the client may use it to control its polling
|
||||||
interval
|
interval
|
||||||
- authenticate the packet if the request was authenticated
|
|
||||||
- originate timestamp is the client's transmit time
|
- originate timestamp is the client's transmit time
|
||||||
- don't save our transmit timestamp as we aren't maintaining state about
|
- don't save our transmit timestamp as we aren't maintaining state about
|
||||||
this client */
|
this client */
|
||||||
transmit_packet(my_mode, message->poll, NTP_LVM_TO_VERSION(message->lvm),
|
transmit_packet(my_mode, message->poll, NTP_LVM_TO_VERSION(message->lvm),
|
||||||
has_auth, key_id, &message->transmit_ts, now, NULL, NULL,
|
auth_mode, key_id, &message->transmit_ts, now, NULL, NULL,
|
||||||
remote_addr, local_addr);
|
remote_addr, local_addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue