From: Juergen Perlinger Date: Mon, 3 Mar 2014 09:06:43 +0000 (+0100) Subject: * [Bug 2570] refuse to load leapsec file with bad/missing SHA1 hash X-Git-Tag: NTP_4_2_7P429~2^2~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c5041a669dd0463d30c8f4cf2967dc9142816e57;p=thirdparty%2Fntp.git * [Bug 2570] refuse to load leapsec file with bad/missing SHA1 hash -- change reading the hash line code: NIST omits leading zeros. bk: 53144623bTRFhCJTd-Oy-ZauxaxFlA --- diff --git a/ChangeLog b/ChangeLog index ff526fa52..9a6c0178a 100644 --- 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. diff --git a/ntpd/ntp_leapsec.c b/ntpd/ntp_leapsec.c index 2e52d0a83..695d3a773 100644 --- a/ntpd/ntp_leapsec.c +++ b/ntpd/ntp_leapsec.c @@ -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 diff --git a/tests/ntpd/leapsec.cpp b/tests/ntpd/leapsec.cpp index f8e1a13e3..ba18a3052 100644 --- a/tests/ntpd/leapsec.cpp +++ b/tests/ntpd/leapsec.cpp @@ -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 // =====================================================================