]> 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>
Fri, 5 Jun 2015 04:31:07 +0000 (06:31 +0200)
committerJuergen Perlinger <perlinger@ntp.org>
Fri, 5 Jun 2015 04:31:07 +0000 (06:31 +0200)
 - trigger a possible autokey update on change of 'sys_tai'

bk: 5571260bZN6HlNYokjRDWhk9uIOMCw

include/ntpd.h
ntpd/ntp_crypto.c
ntpd/ntp_timer.c

index f0bbeb08211f3ec6cc96f90c0b16b2a9284a1f36..b0069f8b86f2421eb718d13a7538d525cdb38728 100644 (file)
@@ -201,6 +201,7 @@ extern      keyid_t session_key     (sockaddr_u *, sockaddr_u *, keyid_t,
 extern int     make_keylist    (struct peer *, struct interface *);
 extern void    key_expire      (struct peer *);
 extern void    crypto_update   (void);
+extern void    crypto_update_taichange(void);
 extern void    crypto_config   (int, char *);
 extern void    crypto_setup    (void);
 extern u_int   crypto_ident    (struct peer *);
index 1084ef4c752fec81137a945d8d83cb4ecf30a53b..802f560e753c593084f0d7d444ca423b48387fbe 100644 (file)
@@ -380,16 +380,13 @@ make_keylist(
                EVP_SignUpdate(&ctx, (u_char *)vp, 12);
                EVP_SignUpdate(&ctx, vp->ptr, sizeof(struct autokey));
                if (EVP_SignFinal(&ctx, vp->sig, &len, sign_pkey)) {
-                       vp->siglen = htonl(sign_siglen);
+                       vp->siglen = htonl(len);
                        peer->flags |= FLAG_ASSOC;
                }
        }
-#ifdef DEBUG
-       if (debug)
-               printf("make_keys: %d %08x %08x ts %u fs %u poll %d\n",
+       DPRINTF(1, ("make_keys: %d %08x %08x ts %u fs %u poll %d\n",
                    peer->keynumber, keyid, cookie, ntohl(vp->tstamp),
-                   ntohl(vp->fstamp), peer->hpoll);
-#endif
+                   ntohl(vp->fstamp), peer->hpoll));
        return (XEVNT_OK);
 }
 
@@ -456,13 +453,9 @@ crypto_recv(
                // HMS: Why pkt[1] instead of ep->associd ?
                associd = (associd_t)ntohl(pkt[1]);
                rval = XEVNT_OK;
-#ifdef DEBUG
-               if (debug)
-                       printf(
-                           "crypto_recv: flags 0x%x ext offset %d len %u code 0x%x associd %d\n",
+               DPRINTF(1, ("crypto_recv: flags 0x%x ext offset %d len %u code 0x%x associd %d\n",
                            peer->crypto, authlen, len, code >> 16,
-                           associd);
-#endif
+                           associd));
 
                /*
                 * Check version number and field length. If bad,
@@ -538,13 +531,9 @@ crypto_recv(
                                rval = XEVNT_LEN;
                                break;
                        }
-#ifdef DEBUG
-                       if (debug)
-                               printf(
-                                   "crypto_recv: ident host 0x%x %d server 0x%x %d\n",
+                       DPRINTF(1, ("crypto_recv: ident host 0x%x %d server 0x%x %d\n",
                                    crypto_flags, peer->associd, fstamp,
-                                   peer->assoc);
-#endif
+                                   peer->assoc));
                        temp32 = crypto_flags & CRYPTO_FLAG_MASK;
 
                        /*
@@ -617,10 +606,7 @@ crypto_recv(
                            peer->assoc, peer->subject,
                            OBJ_nid2ln(temp32));
                        record_crypto_stats(&peer->srcadr, statstr);
-#ifdef DEBUG
-                       if (debug)
-                               printf("crypto_recv: %s\n", statstr);
-#endif
+                       DPRINTF(1, ("crypto_recv: %s\n", statstr));
                        break;
 
                /*
@@ -678,10 +664,7 @@ crypto_recv(
                            OBJ_nid2ln(temp32), temp32,
                            ntohl(ep->fstamp));
                        record_crypto_stats(&peer->srcadr, statstr);
-#ifdef DEBUG
-                       if (debug)
-                               printf("crypto_recv: %s\n", statstr);
-#endif
+                       DPRINTF(1, ("crypto_recv: %s\n", statstr));
                        break;
 
                /*
@@ -718,10 +701,7 @@ crypto_recv(
                        snprintf(statstr, sizeof(statstr), "iff %s fs %u",
                            peer->issuer, ntohl(ep->fstamp));
                        record_crypto_stats(&peer->srcadr, statstr);
-#ifdef DEBUG
-                       if (debug)
-                               printf("crypto_recv: %s\n", statstr);
-#endif
+                       DPRINTF(1, ("crypto_recv: %s\n", statstr));
                        break;
 
                /*
@@ -759,10 +739,7 @@ crypto_recv(
                        snprintf(statstr, sizeof(statstr), "gq %s fs %u",
                            peer->issuer, ntohl(ep->fstamp));
                        record_crypto_stats(&peer->srcadr, statstr);
-#ifdef DEBUG
-                       if (debug)
-                               printf("crypto_recv: %s\n", statstr);
-#endif
+                       DPRINTF(1, ("crypto_recv: %s\n", statstr));
                        break;
 
                /*
@@ -799,10 +776,7 @@ crypto_recv(
                        snprintf(statstr, sizeof(statstr), "mv %s fs %u",
                            peer->issuer, ntohl(ep->fstamp));
                        record_crypto_stats(&peer->srcadr, statstr);
-#ifdef DEBUG
-                       if (debug)
-                               printf("crypto_recv: %s\n", statstr);
-#endif
+                       DPRINTF(1, ("crypto_recv: %s\n", statstr));
                        break;
 
 
@@ -868,10 +842,7 @@ crypto_recv(
                            "cook %x ts %u fs %u", peer->pcookie,
                            ntohl(ep->tstamp), ntohl(ep->fstamp));
                        record_crypto_stats(&peer->srcadr, statstr);
-#ifdef DEBUG
-                       if (debug)
-                               printf("crypto_recv: %s\n", statstr);
-#endif
+                       DPRINTF(1, ("crypto_recv: %s\n", statstr));
                        break;
 
                /*
@@ -930,10 +901,7 @@ crypto_recv(
                            bp->key, ntohl(ep->tstamp),
                            ntohl(ep->fstamp));
                        record_crypto_stats(&peer->srcadr, statstr);
-#ifdef DEBUG
-                       if (debug)
-                               printf("crypto_recv: %s\n", statstr);
-#endif
+                       DPRINTF(1, ("crypto_recv: %s\n", statstr));
                        break;
        
                /*
@@ -970,10 +938,7 @@ crypto_recv(
                            OBJ_nid2ln(temp32), temp32,
                            ntohl(ep->fstamp));
                        record_crypto_stats(&peer->srcadr, statstr);
-#ifdef DEBUG
-                       if (debug)
-                               printf("crypto_recv: %s\n", statstr);
-#endif
+                       DPRINTF(1, ("crypto_recv: %s\n", statstr));
                        break;
 
                /*
@@ -1013,10 +978,7 @@ crypto_recv(
                                 ntohl(ep->pkt[0]), ntohl(ep->pkt[1]),
                                 ntohl(ep->pkt[2]), ntohl(ep->fstamp));
                        record_crypto_stats(&peer->srcadr, statstr);
-#ifdef DEBUG
-                       if (debug)
-                               printf("crypto_recv: %s\n", statstr);
-#endif
+                       DPRINTF(1, ("crypto_recv: %s\n", statstr));
                        break;
 
                /*
@@ -1065,10 +1027,7 @@ crypto_recv(
                            "%04x %d %02x %s", htonl(ep->opcode),
                            associd, rval, eventstr(rval));
                        record_crypto_stats(&peer->srcadr, statstr);
-#ifdef DEBUG
-                       if (debug)
-                               printf("crypto_recv: %s\n", statstr);
-#endif
+                       DPRINTF(1, ("crypto_recv: %s\n", statstr));
                        return (rval);
                }
                authlen += (len + 3) / 4 * 4;
@@ -1413,19 +1372,12 @@ crypto_xmit(
                    "%04x %d %02x %s", opcode, associd, rval,
                    eventstr(rval));
                record_crypto_stats(srcadr_sin, statstr);
-#ifdef DEBUG
-               if (debug)
-                       printf("crypto_xmit: %s\n", statstr);
-#endif
+               DPRINTF(1, ("crypto_xmit: %s\n", statstr));
                if (!(opcode & CRYPTO_RESP))
                        return (0);
        }
-#ifdef DEBUG
-       if (debug)
-               printf(
-                   "crypto_xmit: flags 0x%x offset %d len %d code 0x%x associd %d\n",
-                   crypto_flags, start, len, opcode >> 16, associd);
-#endif
+       DPRINTF(1, ("crypto_xmit: flags 0x%x offset %d len %d code 0x%x associd %d\n",
+                   crypto_flags, start, len, opcode >> 16, associd));
        return (len);
 }
 
@@ -1638,7 +1590,7 @@ crypto_encrypt(
        EVP_SignUpdate(&ctx, (u_char *)&vp->tstamp, 12);
        EVP_SignUpdate(&ctx, vp->ptr, vallen);
        if (EVP_SignFinal(&ctx, vp->sig, &vallen, sign_pkey))
-               vp->siglen = htonl(sign_siglen);
+               vp->siglen = htonl(vallen);
        return (XEVNT_OK);
 }
 
@@ -1870,7 +1822,7 @@ crypto_update(void)
                EVP_SignUpdate(&ctx, (u_char *)&pubkey, 12);
                EVP_SignUpdate(&ctx, pubkey.ptr, ntohl(pubkey.vallen));
                if (EVP_SignFinal(&ctx, pubkey.sig, &len, sign_pkey))
-                       pubkey.siglen = htonl(sign_siglen);
+                       pubkey.siglen = htonl(len);
        }
 
        /*
@@ -1889,7 +1841,7 @@ crypto_update(void)
                EVP_SignUpdate(&ctx, cp->cert.ptr,
                    ntohl(cp->cert.vallen));
                if (EVP_SignFinal(&ctx, cp->cert.sig, &len, sign_pkey))
-                       cp->cert.siglen = htonl(sign_siglen);
+                       cp->cert.siglen = htonl(len);
        }
 
        /*
@@ -1904,7 +1856,7 @@ crypto_update(void)
         */
        leapsec_frame(&leap_data);
        if ( ! memcmp(&leap_data.ebase, &leap_data.ttime, sizeof(vint64))) {
-               time_t   now   = time(NULL);
+               time_t   now    = time(NULL);
                uint32_t nowntp = (uint32_t)now + JAN_1970;
                leapsec_query(&leap_data, nowntp, &now);
        }
@@ -1943,12 +1895,39 @@ crypto_update(void)
        snprintf(statstr, sizeof(statstr), "signature update ts %u",
            ntohl(hostval.tstamp)); 
        record_crypto_stats(NULL, statstr);
-#ifdef DEBUG
-       if (debug)
-               printf("crypto_update: %s\n", statstr);
-#endif
+       DPRINTF(1, ("crypto_update: %s\n", statstr));
 }
 
+/*
+ * crypto_update_taichange - eventually trigger crypto_update
+ *
+ * This is called when a change in 'sys_tai' is detected. This will
+ * happen shortly after a leap second is detected, but unhappily also
+ * early after system start; also, the crypto stuff might be unused and
+ * an unguarded call to crypto_update() causes a crash.
+ *
+ * This function makes sure that there already *is* a valid crypto block
+ * for the use with autokey, and only calls 'crypto_update()' if it can
+ * succeed.
+ *
+ * Returns void (no errors)
+ */
+void
+crypto_update_taichange(void)
+{
+       static const u_int len = 3 * sizeof(u_int32);
+
+       /* check if the signing digest algo is available */
+       if (sign_digest == NULL || sign_pkey == NULL)
+               return;
+
+       /* check size of TAI extension block */
+       if (tai_leap.ptr == NULL || ntohl(tai_leap.vallen) != len)
+               return;
+
+       /* crypto_update should at least not crash here! */
+       crypto_update();
+}
 
 /*
  * value_free - free value structure components.
@@ -2181,7 +2160,7 @@ crypto_alice(
        EVP_SignUpdate(&ctx, (u_char *)&vp->tstamp, 12);
        EVP_SignUpdate(&ctx, vp->ptr, len);
        if (EVP_SignFinal(&ctx, vp->sig, &len, sign_pkey))
-               vp->siglen = htonl(sign_siglen);
+               vp->siglen = htonl(len);
        return (XEVNT_OK);
 }
 
@@ -2289,7 +2268,7 @@ crypto_bob(
        EVP_SignUpdate(&ctx, (u_char *)&vp->tstamp, 12);
        EVP_SignUpdate(&ctx, vp->ptr, vallen);
        if (EVP_SignFinal(&ctx, vp->sig, &vallen, sign_pkey))
-               vp->siglen = htonl(sign_siglen);
+               vp->siglen = htonl(vallen);
        return (XEVNT_OK);
 }
 
@@ -2494,7 +2473,7 @@ crypto_alice2(
        EVP_SignUpdate(&ctx, (u_char *)&vp->tstamp, 12);
        EVP_SignUpdate(&ctx, vp->ptr, len);
        if (EVP_SignFinal(&ctx, vp->sig, &len, sign_pkey))
-               vp->siglen = htonl(sign_siglen);
+               vp->siglen = htonl(len);
        return (XEVNT_OK);
 }
 
@@ -2592,7 +2571,7 @@ crypto_bob2(
        EVP_SignUpdate(&ctx, (u_char *)&vp->tstamp, 12);
        EVP_SignUpdate(&ctx, vp->ptr, len);
        if (EVP_SignFinal(&ctx, vp->sig, &len, sign_pkey))
-               vp->siglen = htonl(sign_siglen);
+               vp->siglen = htonl(len);
        return (XEVNT_OK);
 }
 
@@ -2821,7 +2800,7 @@ crypto_alice3(
        EVP_SignUpdate(&ctx, (u_char *)&vp->tstamp, 12);
        EVP_SignUpdate(&ctx, vp->ptr, len);
        if (EVP_SignFinal(&ctx, vp->sig, &len, sign_pkey))
-               vp->siglen = htonl(sign_siglen);
+               vp->siglen = htonl(len);
        return (XEVNT_OK);
 }
 
@@ -2921,7 +2900,7 @@ crypto_bob3(
        EVP_SignUpdate(&ctx, (u_char *)&vp->tstamp, 12);
        EVP_SignUpdate(&ctx, vp->ptr, len);
        if (EVP_SignFinal(&ctx, vp->sig, &len, sign_pkey))
-               vp->siglen = htonl(sign_siglen);
+               vp->siglen = htonl(len);
        return (XEVNT_OK);
 }
 
@@ -3158,7 +3137,7 @@ cert_sign(
                EVP_SignUpdate(&ctx, (u_char *)vp, 12);
                EVP_SignUpdate(&ctx, vp->ptr, len);
                if (EVP_SignFinal(&ctx, vp->sig, &len, sign_pkey))
-                       vp->siglen = htonl(sign_siglen);
+                       vp->siglen = htonl(len);
        }
 #ifdef DEBUG
        if (debug > 1)
@@ -3441,11 +3420,8 @@ cert_parse(
                                ret->flags |= CERT_TRUST;
                        else if (strcmp(pathbuf, "Private") == 0)
                                ret->flags |= CERT_PRIV;
-#if DEBUG
-                       if (debug)
-                               printf("cert_parse: %s: %s\n",
-                                   OBJ_nid2ln(temp), pathbuf);
-#endif
+                       DPRINTF(1, ("cert_parse: %s: %s\n",
+                                   OBJ_nid2ln(temp), pathbuf));
                        break;
 
                /*
@@ -3456,12 +3432,10 @@ cert_parse(
                        ret->grpkey = BN_bin2bn(&ext->value->data[2],
                            ext->value->length - 2, NULL);
                        /* fall through */
-#if DEBUG
                default:
-                       if (debug)
-                               printf("cert_parse: %s\n",
-                                   OBJ_nid2ln(temp));
-#endif
+                       DPRINTF(1, ("cert_parse: %s\n",
+                                   OBJ_nid2ln(temp)));
+                       break;
                }
        }
        if (strcmp(ret->subject, ret->issuer) == 0) {
@@ -3646,9 +3620,9 @@ crypto_key(
        snprintf(statstr, sizeof(statstr), "%s mod %d", &linkname[2],
            EVP_PKEY_size(pkey) * 8);
        record_crypto_stats(addr, statstr);
+       
+       DPRINTF(1, ("crypto_key: %s\n", statstr));
 #ifdef DEBUG
-       if (debug)
-               printf("crypto_key: %s\n", statstr);
        if (debug > 1) {
                if (pkey->type == EVP_PKEY_DSA)
                        DSA_print_fp(stdout, pkey->pkey.dsa, 0);
@@ -3763,10 +3737,7 @@ crypto_cert(
        snprintf(statstr, sizeof(statstr), "%s 0x%x len %lu",
            &linkname[2], ret->flags, len);
        record_crypto_stats(NULL, statstr);
-#ifdef DEBUG
-       if (debug)
-               printf("crypto_cert: %s\n", statstr);
-#endif
+       DPRINTF(1, ("crypto_cert: %s\n", statstr));
        return (ret);
 }
 
@@ -3836,12 +3807,8 @@ crypto_setup(void)
                get_systime(&seed);
                RAND_seed(&seed, sizeof(l_fp));
                RAND_write_file(randfile);
-#ifdef DEBUG
-               if (debug)
-                       printf(
-                           "crypto_setup: OpenSSL version %lx random seed file %s bytes read %d\n",
-                           SSLeay(), randfile, bytes);
-#endif
+               DPRINTF(1, ("crypto_setup: OpenSSL version %lx random seed file %s bytes read %d\n",
+                           SSLeay(), randfile, bytes));
        }
 
        /*
@@ -3970,10 +3937,7 @@ crypto_setup(void)
        snprintf(statstr, sizeof(statstr), "setup 0x%x host %s %s",
            crypto_flags, hostname, OBJ_nid2ln(cinfo->nid));
        record_crypto_stats(NULL, statstr);
-#ifdef DEBUG
-       if (debug)
-               printf("crypto_setup: %s\n", statstr);
-#endif
+       DPRINTF(1, ("crypto_setup: %s\n", statstr));
 }
 
 
@@ -3988,10 +3952,8 @@ crypto_config(
 {
        int     nid;
 
-#ifdef DEBUG
-       if (debug > 1)
-               printf("crypto_config: item %d %s\n", item, cp);
-#endif
+       DPRINTF(1, ("crypto_config: item %d %s\n", item, cp));
+
        switch (item) {
 
        /*
index e7e949e149f5fe4eab2aa54468ad0a11c2303f59..4757ffe5b68fc26af80b3da6f81eb962794543d2 100644 (file)
@@ -516,6 +516,7 @@ check_leapsec(
 
        leap_result_t lsdata;
        u_int32       lsprox;
+       int/*BOOL*/   update_autokey;
        
 #ifndef SYS_WINNT  /* WinNT port has its own leap second handling */
 # ifdef KERNEL_PLL
@@ -523,11 +524,12 @@ check_leapsec(
 # else
        leapsec_electric(0);
 # endif
-#endif 
+#endif
        if (reset)      {
                lsprox = LSPROX_NOWARN;
                leapsec_reset_frame();
                memset(&lsdata, 0, sizeof(lsdata));
+               update_autokey = FALSE;
        } else if (leapsec_query(&lsdata, now, tpiv)) {
                /* Full hit. Eventually step the clock, but always
                 * announce the leap event has happened.
@@ -556,7 +558,9 @@ check_leapsec(
                lsprox  = LSPROX_NOWARN;
                leapsec = LSPROX_NOWARN;
                sys_tai = lsdata.tai_offs;
+               update_autokey = TRUE;
        } else {
+               update_autokey = (sys_tai != lsdata.tai_offs);
                lsprox  = lsdata.proximity;
                sys_tai = lsdata.tai_offs;
        }
@@ -592,4 +596,6 @@ check_leapsec(
                 leapdif = lsdata.tai_diff;
         else
                 leapdif = 0;
+       if (update_autokey)
+               crypto_update_taichange();
 }