]> git.ipfire.org Git - thirdparty/ntp.git/commitdiff
Bug 2830 - ntpd doesn't always transfer the correct TAI offset via autokey
authorJuergen Perlinger <perlinger@ntp.org>
Tue, 2 Jun 2015 07:11:10 +0000 (09:11 +0200)
committerJuergen Perlinger <perlinger@ntp.org>
Tue, 2 Jun 2015 07:11:10 +0000 (09:11 +0200)
 fix a few bad ideas and missing links

bk: 556d570eoecOta-7B3n2CIKE7LTJVA

ntpd/ntp_crypto.c
ntpd/ntp_leapsec.c

index 6e0e1eb4b28783b016568e6533cb5656ecdba0b7..1084ef4c752fec81137a945d8d83cb4ecf30a53b 100644 (file)
@@ -988,8 +988,9 @@ crypto_recv(
                         * compare the value timestamps here, as they
                         * can be updated by different servers.
                         */
-                       if ((rval = crypto_verify(ep, NULL, peer)) !=
-                           XEVNT_OK)
+                       rval = crypto_verify(ep, NULL, peer);
+                       if ((rval   != XEVNT_OK          ) ||
+                           (vallen != 3*sizeof(uint32_t))  )
                                break;
 
                        /* Check if we can update the basic TAI offset
@@ -997,27 +998,9 @@ crypto_recv(
                         * and ignores the time stamps in the autokey
                         * message.
                         */
-                       if (vallen == 0) {
-                               /* NOP */
-                       } else if (vallen != 3*sizeof(uint32_t)) {
-#ifdef DEBUG
-                               if (debug)
-                                       printf("crypto_recv: CRYPTO_LEAP: bad value size %u\n", vallen);
-#endif
-                       } else if (sys_leap == LEAP_NOTINSYNC) {
-#ifdef DEBUG
-                               if (debug)
-                                       printf("crypto_recv: CRYPTO_LEAP: not in sync, TAI ignored\n");
-#endif
-                       } else if ( ! leapsec_autokey_tai(ntohl(ep->pkt[0]),
-                                               rbufp->recv_time.l_ui, NULL))
-                       {
-#ifdef DEBUG
-                               if (debug)
-                                       printf("crypto_recv: CRYPTO_LEAP: TAI not updated\n");
-#endif
-                       }
-                       
+                       if (sys_leap != LEAP_NOTINSYNC)
+                               leapsec_autokey_tai(ntohl(ep->pkt[0]),
+                                                   rbufp->recv_time.l_ui, NULL);
                        tai_leap.tstamp = ep->tstamp;
                        tai_leap.fstamp = ep->fstamp;
                        crypto_update();
@@ -1915,27 +1898,38 @@ crypto_update(void)
         */
        tai_leap.tstamp = hostval.tstamp;
        tai_leap.fstamp = hostval.fstamp;
-       if ( ! leapsec_frame(&leap_data))
-               leap_data.tai_offs = 0;
-
-       if (leap_data.tai_offs != 0) { /* might be better with > 10... */
-               len = 3 * sizeof(u_int32);
-               if (tai_leap.ptr == NULL || ntohl(tai_leap.vallen) != len) {
-                       free(tai_leap.ptr);
-                       tai_leap.ptr = emalloc(len);
-                       tai_leap.vallen = htonl(len);
-               }
-               ptr = (u_int32 *)tai_leap.ptr;
+
+       /* Get the leap second era. We might need a full lookup early
+        * after start, when the cache is not yet loaded.
+        */
+       leapsec_frame(&leap_data);
+       if ( ! memcmp(&leap_data.ebase, &leap_data.ttime, sizeof(vint64))) {
+               time_t   now   = time(NULL);
+               uint32_t nowntp = (uint32_t)now + JAN_1970;
+               leapsec_query(&leap_data, nowntp, &now);
+       }
+
+       /* Create the data block. The protocol does not work without. */
+       len = 3 * sizeof(u_int32);
+       if (tai_leap.ptr == NULL || ntohl(tai_leap.vallen) != len) {
+               free(tai_leap.ptr);
+               tai_leap.ptr = emalloc(len);
+               tai_leap.vallen = htonl(len);
+       }
+       ptr = (u_int32 *)tai_leap.ptr;
+       if (leap_data.tai_offs > 10) {
+               /* create a TAI / leap era block. The end time is a
+                * fake -- maybe we can do better.
+                */
                ptr[0] = htonl(leap_data.tai_offs);
                ptr[1] = htonl(leap_data.ebase.d_s.lo);
                if (leap_data.ttime.d_s.hi >= 0)
-                       ptr[2] = htonl(leap_data.ttime.D_s.lo -  7*86400);
+                       ptr[2] = htonl(leap_data.ttime.D_s.lo +  7*86400);
                else
                        ptr[2] = htonl(leap_data.ebase.D_s.lo + 25*86400);
        } else {
-               free(tai_leap.ptr);
-               tai_leap.ptr = NULL;
-               tai_leap.vallen = 0;
+               /* no leap era available */
+               memset(ptr, 0, len);
        }
        if (tai_leap.sig == NULL)
                tai_leap.sig = emalloc(sign_siglen);
@@ -1943,8 +1937,9 @@ crypto_update(void)
        EVP_SignUpdate(&ctx, (u_char *)&tai_leap, 12);
        EVP_SignUpdate(&ctx, tai_leap.ptr, len);
        if (EVP_SignFinal(&ctx, tai_leap.sig, &len, sign_pkey))
-               tai_leap.siglen = htonl(sign_siglen);
+               tai_leap.siglen = htonl(len);
        crypto_flags |= CRYPTO_FLAG_TAI;
+
        snprintf(statstr, sizeof(statstr), "signature update ts %u",
            ntohl(hostval.tstamp)); 
        record_crypto_stats(NULL, statstr);
index 90e053eb6c46a62e3d79a758dc76bf26edc4ab2a..7f6df0a22ac4f77629f0e7ee245d391f46a869f6 100644 (file)
@@ -95,7 +95,7 @@ static int    betweenu32(uint32_t, uint32_t, uint32_t);
 static void   reset_times(leap_table_t*);
 static int    leapsec_add(leap_table_t*, const vint64*, int);
 static int    leapsec_raw(leap_table_t*, const vint64 *, int, int);
-static char * lstostr(const vint64 * ts);
+static const char * lstostr(const vint64 * ts);
 
 /* =====================================================================
  * Get & Set the current leap table
@@ -189,11 +189,16 @@ leapsec_load(
        struct calendar build;
 
        leapsec_clear(pt);
-       if (use_build_limit && ntpcal_get_build_date(&build))
+       if (use_build_limit && ntpcal_get_build_date(&build)) {
+               /* don't prune everything -- permit the last 10yrs
+                * before build.
+                */
+               build.year -= 10;
                limit = ntpcal_date_to_ntp64(&build);
-       else
+       } else {
                memset(&limit, 0, sizeof(limit));
-
+       }
+       
        while (get_line(func, farg, linebuf, sizeof(linebuf))) {
                cp = linebuf;
                if (*cp == '#') {
@@ -390,8 +395,6 @@ leapsec_frame(
 
         memset(qr, 0, sizeof(leap_result_t));
        pt = leapsec_get_table(FALSE);
-       if (ucmpv64(&pt->head.ttime, &pt->head.stime) <= 0)
-                return FALSE;
 
        qr->tai_offs = pt->head.this_tai;
        qr->tai_diff = pt->head.next_tai - pt->head.this_tai;
@@ -399,7 +402,7 @@ leapsec_frame(
        qr->ttime    = pt->head.ttime;
        qr->dynamic  = pt->head.dynls;
 
-        return TRUE;
+       return ucmpv64(&pt->head.ttime, &pt->head.stime) >= 0;
 }
 
 /* ------------------------------------------------------------------ */
@@ -660,8 +663,11 @@ leapsec_autokey_tai(
        (void)tai_offset;
        pt = leapsec_get_table(FALSE);
        
-       /* Bail out if the basic offset is not zero */
-       if (pt->head.base_tai != 0)
+       /* Bail out if the basic offset is not zero and the putative
+        * offset is bigger than 10s. That was in 1972 -- we don't want
+        * to go back that far!
+        */
+       if (pt->head.base_tai != 0 || tai_offset < 10)
                return FALSE;
 
        /* If there's already data in the table, check if an update is
@@ -1147,19 +1153,22 @@ leapsec_validate(
 /*
  * lstostr - prettyprint NTP seconds
  */
-static char * lstostr(
+static const char *
+lstostr(
        const vint64 * ts)
 {
        char *          buf;
        struct calendar tm;
 
+       LIB_GETBUF(buf);
+
        if ( ! (ts->d_s.hi >= 0 && ntpcal_ntp64_to_date(&tm, ts) >= 0))
-               return "9999-12-31T23:59:59Z";
-       
-       LIB_GETBUF(buf);        
-       snprintf(buf, LIB_BUFLENGTH, "%04d-%02d-%02dT%02d:%02d:%02dZ",
-                tm.year, tm.month, tm.monthday,
-                tm.hour, tm.minute, tm.second);
+               snprintf(buf, LIB_BUFLENGTH, "%s", "9999-12-31T23:59:59Z");
+       else
+               snprintf(buf, LIB_BUFLENGTH, "%04d-%02d-%02dT%02d:%02d:%02dZ",
+                       tm.year, tm.month, tm.monthday,
+                       tm.hour, tm.minute, tm.second);
+
        return buf;
 }