]> git.ipfire.org Git - thirdparty/ntp.git/commitdiff
* [Bug 2570] refuse to load leapsec file with bad/missing SHA1 hash
authorJuergen Perlinger <perlinger@ntp.org>
Mon, 3 Mar 2014 09:06:43 +0000 (10:06 +0100)
committerJuergen Perlinger <perlinger@ntp.org>
Mon, 3 Mar 2014 09:06:43 +0000 (10:06 +0100)
-- change reading the hash line code: NIST omits leading zeros.

bk: 53144623bTRFhCJTd-Oy-ZauxaxFlA

ChangeLog
ntpd/ntp_leapsec.c
tests/ntpd/leapsec.cpp

index ff526fa520c198e74644e8dc604d3ce0469804f1..9a6c0178a0721e01fcd8a2871a82a6ec31169d9a 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,5 @@
+* [Bug 2570] refuse to load leapsec file with bad/missing SHA1 hash
+  -- change reading the hash line code: NIST omits leading zeros.
 * CID 1165098: Remove logically dead code from refclock_true.c.
 * In ntp_dir_sep.m4, we care about $host_os, not $target_os.
 * [Bug 2540] bootstrap script needs to 'touch' files in finer-grained groups.
index 2e52d0a836d2448fe441d1e3ec882c8c05ee90d1..695d3a7735ae9cb865ba8decd33c7667b6c2c748 100644 (file)
@@ -1045,36 +1045,38 @@ typedef struct {
 } sha1_digest;
 
 /* [internal] parse a digest line to get the hash signature
- * I would have preferred the CTYPE 'isblank()' function, but alas,
- * it's not in MSVC bevore Studio2013; it also seems to be added
- * with the C99 standard (not being sure about that) and not all
- * target compilers implement this. Using a direct character
- * compare is the way out; the NIST leapsec file is 7bit ASCII
- * and the locale should not matter much here.
+ * The NIST code creating the hash writes them out as 5 hex integers
+ * without leading zeros. This makes reading them back as hex-encoded
+ * BLOB impossible, because there might be less than 40 hex digits.
+ *
+ * The solution is to read the values back as integers, and then do the
+ * byte twiddle necessary to get it into an array of 20 chars. The
+ * drawback is that it permits any acceptable number syntax provided by
+ * 'scanf()' and 'strtoul()', including optional signs and '0x'
+ * prefixes.
  */
 static int/*BOOL*/
 do_leap_hash(
        sha1_digest * mac,
        char const  * cp )
 {
-       int idx, dv;
+       int wi, di, num, len;
+       unsigned long tmp[5];
 
        memset(mac, 0, sizeof(*mac));
-       for (idx = 0;  *cp && idx < 2*sizeof(*mac);  ++cp) {
-               if (isdigit(*cp))
-                       dv = *cp - '0';
-               else if (isxdigit(*cp))
-                       dv = (toupper(*cp) - 'A' + 10);
-               else if ('\t' == *cp || ' ' == *cp) /*isblank(*cp))*/
-                       continue;
-               else
-                       break;
+       num = sscanf(cp, " %lx %lx %lx %lx %lx%n",
+                    &tmp[0], &tmp[1], &tmp[2], &tmp[3], &tmp[4],
+                    &len);
+       if (num != 5 || cp[len] > ' ')
+               return FALSE;
 
-               mac->hv[idx/2] = (unsigned char)(
-                       (mac->hv[idx/2] * 16) + dv);
-               ++idx;
-       }
-       return (idx == 2*sizeof(*mac));
+       /* now do the byte twiddle */
+       for (wi=0; wi < 5; ++wi)
+               for (di=3; di >= 0; --di) {
+                       mac->hv[wi*4 + di] = (unsigned char)tmp[wi];
+                       tmp[wi] >>= 8;
+               }
+       return TRUE;
 }
 
 /* [internal] add the digits of a data line to the hash, stopping at the
index f8e1a13e343ce6c91fc654926f8f3d614ac5c584..ba18a305293d7fa98e0a6d8fba48a7c0d625a6c6 100644 (file)
@@ -162,6 +162,66 @@ static const char leap_mhash [] =
     "#h f2349a02 788b9534 a8f2e141 f2029Q6d 4064a7ee\n"
     "#\n";
 
+// short table with only 4 hash groups
+static const char leap_shash [] =
+    "#\n"
+    "#@        3610569600\n"
+    "#$        3610566000\n"
+    "#\n"
+    "2272060800 10     # 1 Jan 1972\n"
+    "2287785600        11      # 1 Jul 1972\n"
+    "2303683200        12      # 1 Jan 1973\n"
+    "2335219200        13      # 1 Jan 1974\n"
+    "2366755200        14      # 1 Jan 1975\n"
+    "2398291200        15      # 1 Jan 1976\n"
+    "2429913600        16      # 1 Jan 1977\n"
+    "2461449600        17      # 1 Jan 1978\n"
+    "2492985600        18      # 1 Jan 1979\n"
+    "2524521600        19      # 1 Jan 1980\n"
+    "#\n"
+    "#h f2349a02 788b9534 a8f2e141 f2029Q6d\n"
+    "#\n";
+
+// table with good hash and truncated/missing leading zeros
+static const char leap_gthash [] = {
+    "#\n"
+    "#$         3535228800\n"
+    "#\n"
+    "# Updated through IERS Bulletin C46\n"
+    "# File expires on:  28 June 2014\n"
+    "#\n"
+    "#@        3612902400\n"
+    "#\n"
+    "2272060800        10      # 1 Jan 1972\n"
+    "2287785600        11      # 1 Jul 1972\n"
+    "2303683200        12      # 1 Jan 1973\n"
+    "2335219200        13      # 1 Jan 1974\n"
+    "2366755200        14      # 1 Jan 1975\n"
+    "2398291200        15      # 1 Jan 1976\n"
+    "2429913600        16      # 1 Jan 1977\n"
+    "2461449600        17      # 1 Jan 1978\n"
+    "2492985600        18      # 1 Jan 1979\n"
+    "2524521600        19      # 1 Jan 1980\n"
+    "2571782400        20      # 1 Jul 1981\n"
+    "2603318400        21      # 1 Jul 1982\n"
+    "2634854400        22      # 1 Jul 1983\n"
+    "2698012800        23      # 1 Jul 1985\n"
+    "2776982400        24      # 1 Jan 1988\n"
+    "2840140800        25      # 1 Jan 1990\n"
+    "2871676800        26      # 1 Jan 1991\n"
+    "2918937600        27      # 1 Jul 1992\n"
+    "2950473600        28      # 1 Jul 1993\n"
+    "2982009600        29      # 1 Jul 1994\n"
+    "3029443200        30      # 1 Jan 1996\n"
+    "3076704000        31      # 1 Jul 1997\n"
+    "3124137600        32      # 1 Jan 1999\n"
+    "3345062400        33      # 1 Jan 2006\n"
+    "3439756800        34      # 1 Jan 2009\n"
+    "3550089600        35      # 1 Jul 2012\n"
+    "#\n"
+    "#h        1151a8f e85a5069 9000fcdb 3d5e5365 1d505b37"
+};
+
 static uint32_t lsec2009 = 3439756800u; // 1 Jan 2009, 00:00:00 utc
 static uint32_t lsec2012 = 3550089600u; // 1 Jul 2012, 00:00:00 utc
 
@@ -285,6 +345,20 @@ TEST_F(leapsecTest, ValidateMalformed) {
        EXPECT_EQ(LSVALID_BADFORMAT, rc);
 }
 
+// ----------------------------------------------------------------------
+TEST_F(leapsecTest, ValidateMalformedShort) {
+       const char *cp = leap_shash;
+       int         rc = leapsec_validate(stringreader, &cp);
+       EXPECT_EQ(LSVALID_BADFORMAT, rc);
+}
+
+// ----------------------------------------------------------------------
+TEST_F(leapsecTest, ValidateNoLeadZero) {
+       const char *cp = leap_gthash;
+       int         rc = leapsec_validate(stringreader, &cp);
+       EXPECT_EQ(LSVALID_GOODHASH, rc);
+}
+
 // =====================================================================
 // BASIC FUNCTIONS
 // =====================================================================