]> git.ipfire.org Git - thirdparty/chrony.git/commitdiff
ntp: avoid truncation of NTPv4 MACs by default
authorMiroslav Lichvar <mlichvar@redhat.com>
Tue, 29 Nov 2016 12:26:46 +0000 (13:26 +0100)
committerMiroslav Lichvar <mlichvar@redhat.com>
Fri, 2 Dec 2016 13:53:03 +0000 (14:53 +0100)
If the MAC in NTPv4 requests would be truncated, use version 3 by
default to avoid the truncation. This is necessary for compatibility
with older chronyd servers, which do not respond to messages with
truncated MACs.

cmdparse.c
doc/chrony.conf.adoc
keys.c
keys.h
ntp_core.c

index d22ba21ac98d581116ee372afc94560a54ef5a92..700da327950614172ded0c3614b7fd806f89db24 100644 (file)
@@ -54,7 +54,7 @@ CPS_ParseNTPSourceAdd(char *line, CPS_NTP_Source *src)
   src->params.iburst = 0;
   src->params.min_stratum = SRC_DEFAULT_MINSTRATUM;
   src->params.poll_target = SRC_DEFAULT_POLLTARGET;
-  src->params.version = NTP_VERSION;
+  src->params.version = 0;
   src->params.max_sources = SRC_DEFAULT_MAXSOURCES;
   src->params.min_samples = SRC_DEFAULT_MINSAMPLES;
   src->params.max_samples = SRC_DEFAULT_MAXSAMPLES;
index d19e9ee4e0ca19cc373a607a60f5993d54551be8..d2650449a1eeeb049dfd811ddd5ebb588504ad79 100644 (file)
@@ -215,9 +215,13 @@ avoid selecting that source. This is useful with low stratum sources that are
 known to be unreliable or inaccurate and which should be used only when other
 sources are unreachable.
 *version* _version_:::
-This option sets the NTP version number used in packets sent to the server.
-This can be useful when the server runs an old NTP implementation that does not
-respond to newer versions. The default version number is 4.
+This option sets the NTP version of packets sent to the server. This can be
+useful when the server runs an old NTP implementation that does not respond to
+requests using a newer version. The default version depends on whether a key is
+specified by the *key* option and which authentication hash function the key
+is using. If the output size of the hash function is longer than 160 bits, the
+default version is 3 for compatibility with older *chronyd* servers. Otherwise,
+the default version is 4.
 
 [[pool]]*pool* _name_ [_option_]...::
 The syntax of this directive is similar to that for the <<server,*server*>>
diff --git a/keys.c b/keys.c
index dfe18a3813d676d9c74c80eb5634c38fba6706ef..09b27bc16565cb396e08f994941378b062b2a6ef 100644 (file)
--- a/keys.c
+++ b/keys.c
@@ -322,6 +322,22 @@ KEY_GetAuthDelay(uint32_t key_id)
 
 /* ================================================== */
 
+int
+KEY_GetAuthLength(uint32_t key_id)
+{
+  unsigned char buf[MAX_HASH_LENGTH];
+  Key *key;
+
+  key = get_key_by_id(key_id);
+
+  if (!key)
+    return 0;
+
+  return HSH_Hash(key->hash_id, buf, 0, buf, 0, buf, sizeof (buf));
+}
+
+/* ================================================== */
+
 int
 KEY_CheckKeyLength(uint32_t key_id)
 {
diff --git a/keys.h b/keys.h
index 9e5d2368846b5b456e98eb7549030517fd128261..82f3a261d66ed38a7dd653400367df474e505d67 100644 (file)
--- a/keys.h
+++ b/keys.h
@@ -37,6 +37,7 @@ extern void KEY_Reload(void);
 extern int KEY_GetKey(uint32_t key_id, char **key, int *len);
 extern int KEY_KeyKnown(uint32_t key_id);
 extern int KEY_GetAuthDelay(uint32_t key_id);
+extern int KEY_GetAuthLength(uint32_t key_id);
 extern int KEY_CheckKeyLength(uint32_t key_id);
 
 extern int KEY_GenerateAuth(uint32_t key_id, const unsigned char *data,
index 01c103f6687c241fd35f68702d0636005bb09034..37512bca8a5231c95aa4cfea3ee8744cd7eef20e 100644 (file)
@@ -520,11 +520,7 @@ 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 = params->version;
-  if (result->version < NTP_MIN_COMPAT_VERSION)
-    result->version = NTP_MIN_COMPAT_VERSION;
-  else if (result->version > NTP_VERSION)
-    result->version = NTP_VERSION;
+  result->version = NTP_VERSION;
 
   if (params->authkey == INACTIVE_AUTHKEY) {
     result->auth_mode = AUTH_NONE;
@@ -541,8 +537,16 @@ NCR_GetInstance(NTP_Remote_Address *remote_addr, NTP_Source_Type type, SourcePar
           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;
   }
 
+  if (params->version)
+    result->version = CLAMP(NTP_MIN_COMPAT_VERSION, params->version, NTP_VERSION);
+
   /* Create a source instance for this NTP source */
   result->source = SRC_CreateNewInstance(UTI_IPToRefid(&remote_addr->ip_addr),
                                          SRC_NTP, params->sel_options,