]> git.ipfire.org Git - thirdparty/ntp.git/commitdiff
Fixes from Dave Mills
authorHarlan Stenn <stenn@ntp.org>
Fri, 21 Oct 2005 00:22:12 +0000 (20:22 -0400)
committerHarlan Stenn <stenn@ntp.org>
Fri, 21 Oct 2005 00:22:12 +0000 (20:22 -0400)
bk: 435834b4Dg162cQNqdcd1T7EBI3xYg

include/ntp.h
include/ntp_crypto.h
include/ntpd.h
libntp/statestr.c
ntpd/ntp_crypto.c
ntpd/ntp_loopfilter.c
ntpd/ntp_proto.c

index 0543674b1a49c093bcc99e5f9160fb250a9348bd..b26a5a7ec192a9f87ca6ce849ea6c5be49fe6254 100644 (file)
@@ -293,8 +293,10 @@ struct peer {
        associd_t assoc;        /* peer association ID */
        u_int32 crypto;         /* peer status word */
        EVP_PKEY *pkey;         /* public key */
-       tstamp_t first;         /* not valid before */
-       tstamp_t last;          /* not valid after */
+       tstamp_t first;         /* server signature invalid before */
+       tstamp_t last;          /* server signature invalid after */
+       tstamp_t cfirst;        /* client signature invalid before */
+       tstamp_t clast;         /* client signature invalid after */
        const EVP_MD *digest;   /* message digest algorithm */
        char    *subject;       /* certificate subject name */
        char    *issuer;        /* certificate issuer name */
index ce545b5b904366abb397f27093801a7fa4742d23..840618e6c2a82c0b6d96c7a1ff60d883dfa96c32 100644 (file)
@@ -27,6 +27,7 @@
 #define CRYPTO_FLAG_AUTO  0x1000 /* autokey verified */
 #define CRYPTO_FLAG_SIGN  0x2000 /* certificate signed */
 #define CRYPTO_FLAG_LEAP  0x4000 /* leapseconds table verified */
+#define        CRYPTO_FLAG_INVLD 0x8000 /* invalid certificate trail */
 
 /*
  * Flags used for certificate management
 #define XEVNT_SGL      XEVNT_CMD(7) /* bad signature length */
 #define XEVNT_SIG      XEVNT_CMD(8) /* signature not verified */
 #define XEVNT_VFY      XEVNT_CMD(9) /* certificate not verified */
-#define XEVNT_PER      XEVNT_CMD(10) /* certificate expired */
+#define XEVNT_PER      XEVNT_CMD(10) /* host certificate expired */
 #define XEVNT_CKY      XEVNT_CMD(11) /* bad or missing cookie */
 #define XEVNT_DAT      XEVNT_CMD(12) /* bad or missing leapseconds table */
 #define XEVNT_CRT      XEVNT_CMD(13) /* bad or missing certificate */
 #define XEVNT_ID       XEVNT_CMD(14) /* bad or missing group key */
 #define        XEVNT_ERR       XEVNT_CMD(15) /* protocol error */
+#define        XEVNT_SRV       XEVNT_CMD(16) /* server certificate expired */
 
 /*
  * Configuration codes
index 980a6845268fbbaa033f84da3fa677339faee0cf..63681636d75d42dd151f683b6b00bc5ff111864c 100644 (file)
@@ -139,7 +139,7 @@ extern      struct  peer *findmanycastpeer  P((struct recvbuf *));
 extern int     crypto_recv     P((struct peer *, struct recvbuf *));
 extern int     crypto_xmit     P((struct pkt *, struct sockaddr_storage *, int, struct exten *, keyid_t));
 extern keyid_t session_key     P((struct sockaddr_storage *, struct sockaddr_storage *, keyid_t, keyid_t, u_long));
-extern void    make_keylist    P((struct peer *, struct interface *));
+extern int     make_keylist    P((struct peer *, struct interface *));
 extern void    key_expire      P((struct peer *));
 extern void    crypto_update   P((void));
 extern void    crypto_config   P((int, char *));
index 90df2ddfe9a60f2cae7373970a6c657978a0f1ae..85552b3ab0d6775d702c15193d184682b32edf13 100644 (file)
@@ -134,12 +134,13 @@ struct codestring crypto_codes[] = {
        { XEVNT_SGL & ~CRPT_EVENT,      "bad_signature_length" },
        { XEVNT_SIG & ~CRPT_EVENT,      "signature_not_verified" },
        { XEVNT_VFY & ~CRPT_EVENT,      "certificate_not_verified" },
-       { XEVNT_PER & ~CRPT_EVENT,      "certificate_expired" },
+       { XEVNT_PER & ~CRPT_EVENT,      "host certificate_expired" },
        { XEVNT_CKY & ~CRPT_EVENT,      "bad_or_missing_cookie" },
        { XEVNT_DAT & ~CRPT_EVENT,      "bad_or_missing_leapsecond_table" },
        { XEVNT_CRT & ~CRPT_EVENT,      "bad_or_missing_certificate" }, 
        { XEVNT_ID & ~CRPT_EVENT,       "bad_or_missing_group_key" },
        { XEVNT_ERR & ~CRPT_EVENT,      "protocol_error" },
+       { XEVNT_SRV & ~CRPT_EVENT,      "server certificate expired" },
        { -1,                           "crypto" }
 };
 #endif /* OPENSSL */
index e6976948d58bb6ee1ea31e87ca93cee24d1a66ea..99ca05e4f479c87771197f8ab14e39169a7c4d31 100644 (file)
@@ -239,13 +239,17 @@ session_key(
 /*
  * make_keylist - generate key list
  *
+ * Returns
+ * XEVNT_OK    success
+ * XEVNT_PER   host certificate expired
+ *
  * This routine constructs a pseudo-random sequence by repeatedly
  * hashing the session key starting from a given source address,
  * destination address, private value and the next key ID of the
  * preceeding session key. The last entry on the list is saved along
  * with its sequence number and public signature.
  */
-void
+int
 make_keylist(
        struct peer *peer,      /* peer structure pointer */
        struct interface *dstadr /* interface */
@@ -323,7 +327,10 @@ make_keylist(
        vp->fstamp = hostval.tstamp;
        vp->vallen = htonl(sizeof(struct autokey));
        vp->siglen = 0;
-       if (vp->tstamp != 0) {
+       if (tstamp != 0) {
+               if (tstamp < cinfo->first || tstamp > cinfo->last)
+                       return (XEVNT_PER);
+
                if (vp->sig == NULL)
                        vp->sig = emalloc(sign_siglen);
                EVP_SignInit(&ctx, sign_digest);
@@ -342,6 +349,7 @@ make_keylist(
                    ntohl(ap->seq), ntohl(ap->key), cookie,
                    ntohl(vp->tstamp), ntohl(vp->fstamp), peer->hpoll);
 #endif
+       return (XEVNT_OK);
 }
 
 
@@ -601,7 +609,7 @@ crypto_recv(
                        strcpy(peer->issuer, cinfo->issuer);
 
                        /*
-                        * We plug in the public key and group key in
+                        * We plug in the public key and lifetime from
                         * the first certificate received. However, note
                         * that this certificate might not be signed by
                         * the server, so we can't check the
@@ -615,7 +623,23 @@ crypto_recv(
                                X509_free(cert);
                                peer->first = cinfo->first;
                                peer->last = cinfo->last;
+                       } else if (max(peer->first, cinfo->first) <
+                           min(peer->last, cinfo->last)) {
+                               peer->flags |= CRYPTO_FLAG_INVLD;
+                               sprintf(statstr,
+                                   "broken server certificate trail %s->%s",
+                                   cinfo->issuer, cinfo->subject);
+                               record_crypto_stats(&peer->srcadr,
+                                   statstr);
+                               report_event(XEVNT_SRV, peer);
+#ifdef DEBUG
+                               if (debug)
+                                       printf("crypto_recv: %s\n",
+                                           statstr);
+#endif
                        }
+                       peer->cfirst = cinfo->first;
+                       peer->clast = cinfo->last;
                        peer->flash &= ~TEST8;
                        temp32 = cinfo->nid;
                        sprintf(statstr, "cert %s 0x%x %s (%u) fs %u",
@@ -1446,8 +1470,8 @@ crypto_xmit(
  * XEVNT_PUB   bad or missing public key
  * XEVNT_SGL   bad signature length
  * XEVNT_SIG   signature not verified
- * XEVNT_PER   certificate expired
  * XEVNT_ERR   protocol error
+ * XEVNT_SRV   server certificate expired
  */
 static int
 crypto_verify(
@@ -1563,9 +1587,12 @@ crypto_verify(
 
        } else if (siglen != (u_int)EVP_PKEY_size(pkey)) {
                rval = XEVNT_SGL;
-       } else if (tstamp < peer->first || tstamp > peer->last){
-               rval = XEVNT_PER;
        } else {
+               tstamp = crypto_time();
+               if (peer->flags & CRYPTO_FLAG_INVLD || tstamp <
+                   peer->first || tstamp > peer->last)
+                       return (XEVNT_SRV);
+
                EVP_VerifyInit(&ctx, peer->digest);
                EVP_VerifyUpdate(&ctx, (u_char *)&ep->tstamp, vallen +
                    12);
@@ -1599,6 +1626,7 @@ crypto_verify(
  * XEVNT_OK    success
  * XEVNT_PUB   bad or missing public key
  * XEVNT_CKY   bad or missing cookie
+ * XEVNT_PER   host certificate expired
  */
 static int
 crypto_encrypt(
@@ -1649,6 +1677,9 @@ crypto_encrypt(
        if (tstamp == 0)
                return (XEVNT_OK);
 
+       if (tstamp < cinfo->first || tstamp > cinfo->last)
+               return (XEVNT_PER);
+
        vp->sig = emalloc(sign_siglen);
        EVP_SignInit(&ctx, sign_digest);
        EVP_SignUpdate(&ctx, (u_char *)&vp->tstamp, 12);
@@ -1859,6 +1890,11 @@ crypto_update(void)
        if ((tstamp = crypto_time()) == 0)
                return;
 
+       if (tstamp < cinfo->first || tstamp > cinfo->last) {
+               msyslog(
+                   LOG_ERR, "crypto_update: expired certificate\n");
+               return;
+       }
        hostval.tstamp = htonl(tstamp);
 
        /*
@@ -2120,6 +2156,9 @@ crypto_alice(
        if (tstamp == 0)
                return (XEVNT_OK);
 
+       if (tstamp < cinfo->first || tstamp > cinfo->last)
+               return (XEVNT_PER);
+
        vp->sig = emalloc(sign_siglen);
        EVP_SignInit(&ctx, sign_digest);
        EVP_SignUpdate(&ctx, (u_char *)&vp->tstamp, 12);
@@ -2137,6 +2176,7 @@ crypto_alice(
  * XEVNT_OK    success
  * XEVNT_ID    bad or missing group key
  * XEVNT_ERR   protocol error
+ * XEVNT_PER   host expired certificate
  */
 static int
 crypto_bob(
@@ -2213,6 +2253,9 @@ crypto_bob(
        if (tstamp == 0)
                return (XEVNT_OK);
 
+       if (tstamp < cinfo->first || tstamp > cinfo->last)
+               return (XEVNT_PER);
+
        vp->sig = emalloc(sign_siglen);
        EVP_SignInit(&ctx, sign_digest);
        EVP_SignUpdate(&ctx, (u_char *)&vp->tstamp, 12);
@@ -2363,6 +2406,7 @@ crypto_iff(
  * XEVNT_OK    success
  * XEVNT_PUB   bad or missing public key
  * XEVNT_ID    bad or missing group key
+ * XEVNT_PER   host certificate expired
  */
 static int
 crypto_alice2(
@@ -2414,6 +2458,9 @@ crypto_alice2(
        if (tstamp == 0)
                return (XEVNT_OK);
 
+       if (tstamp < cinfo->first || tstamp > cinfo->last)
+               return (XEVNT_PER);
+
        vp->sig = emalloc(sign_siglen);
        EVP_SignInit(&ctx, sign_digest);
        EVP_SignUpdate(&ctx, (u_char *)&vp->tstamp, 12);
@@ -2431,6 +2478,7 @@ crypto_alice2(
  * XEVNT_OK    success
  * XEVNT_ID    bad or missing group key
  * XEVNT_ERR   protocol error
+ * XEVNT_PER   host certificate expired
  */
 static int
 crypto_bob2(
@@ -2507,6 +2555,9 @@ crypto_bob2(
        if (tstamp == 0)
                return (XEVNT_OK);
 
+       if (tstamp < cinfo->first || tstamp > cinfo->last)
+               return (XEVNT_PER);
+
        vp->sig = emalloc(sign_siglen);
        EVP_SignInit(&ctx, sign_digest);
        EVP_SignUpdate(&ctx, (u_char *)&vp->tstamp, 12);
@@ -2681,6 +2732,7 @@ crypto_gq(
  * XEVNT_OK    success
  * XEVNT_PUB   bad or missing public key
  * XEVNT_ID    bad or missing group key
+ * XEVNT_PER   host certificate expired
  */
 static int
 crypto_alice3(
@@ -2732,6 +2784,9 @@ crypto_alice3(
        if (tstamp == 0)
                return (XEVNT_OK);
 
+       if (tstamp < cinfo->first || tstamp > cinfo->last)
+               return (XEVNT_PER);
+
        vp->sig = emalloc(sign_siglen);
        EVP_SignInit(&ctx, sign_digest);
        EVP_SignUpdate(&ctx, (u_char *)&vp->tstamp, 12);
@@ -2748,6 +2803,7 @@ crypto_alice3(
  * Returns
  * XEVNT_OK    success
  * XEVNT_ERR   protocol error
+ * XEVNT_PER   host certificate expired
  */
 static int
 crypto_bob3(
@@ -2829,6 +2885,9 @@ crypto_bob3(
        if (tstamp == 0)
                return (XEVNT_OK);
 
+       if (tstamp < cinfo->first || tstamp > cinfo->last)
+               return (XEVNT_PER);
+
        vp->sig = emalloc(sign_siglen);
        EVP_SignInit(&ctx, sign_digest);
        EVP_SignUpdate(&ctx, (u_char *)&vp->tstamp, 12);
@@ -3119,13 +3178,15 @@ cert_parse(
  * serial number, issuer name and validity interval of the server. The
  * validity interval extends from the current time to the same time one
  * year hence. For NTP purposes, it is convenient to use the NTP seconds
- * of the current time as the serial number.
+ * of the current time as the serial number. By default, the valid
+ * period is one year.
  *
  * Returns
  * XEVNT_OK    success
  * XEVNT_PUB   bad or missing public key
  * XEVNT_CRT   bad or missing certificate
  * XEVNT_VFY   certificate not verified
+ * XEVNT_PER   host certificate expired
  */
 static int
 cert_sign(
@@ -3152,6 +3213,9 @@ cert_sign(
        if (tstamp == 0)
                return (XEVNT_TSP);
 
+       if (tstamp < cinfo->first || tstamp > cinfo->last)
+               return (XEVNT_PER);
+
        ptr = (u_char *)ep->pkt;
        if ((req = d2i_X509(NULL, &ptr, ntohl(ep->vallen))) == NULL) {
                msyslog(LOG_ERR, "cert_sign %s\n",
index d7eaba3f4cf7a238a5a74e9d2fe707144a8767b0..5c7bc8ea96b0ee7214acece50fa128a59e65a667 100644 (file)
@@ -496,8 +496,9 @@ local_clock(
        if (tpt != NULL) {
                for (i = 0; i < len; i++) {
                        togo = ntohl(tpt[i]) - peer->rec.l_ui;
-                       if (togo > 0 && togo < CLOCK_JUNE) {
-                               leap_next |= LEAP_ADDSECOND;
+                       if (togo > 0) {
+                               if (togo < CLOCK_JUNE)
+                                       leap_next |= LEAP_ADDSECOND;
                                break;
                        }
                }
@@ -582,7 +583,7 @@ local_clock(
                        tm = gmtime(&tstamp);
                        if (tm != NULL) {
                                if ((tm->tm_mon == 6 && tm->tm_mday ==
-                                   30) || (tm->tm_mon == 12 &&
+                                   30) || (tm->tm_mon + 1 == 12 &&
                                    tm->tm_mday == 31)) {
                                        if (leap_next & LEAP_ADDSECOND)
                                                ntv.status |= STA_INS;
@@ -595,7 +596,7 @@ local_clock(
                                        printf(
                                            "local_clock: leap %d status %x date %d/%d\n",
                                            leap_next, ntv.status,
-                                           tm->tm_mon, tm->tm_mday);
+                                           tm->tm_mon + 1, tm->tm_mday);
 #endif
                        }
 
@@ -870,7 +871,9 @@ loop_config(
                 * Call out the safety patrol. If ntpdate mode or if the
                 * step threshold has been increased by the -x option or
                 * tinker command, kernel discipline is unsafe, so don't
-                * do any of this stuff.
+                * do any of this stuff. Otherwise, initialize the
+                * kernel to appear unsynchronized until the first
+                * update is received.
                 */
                if (mode_ntpdate || clock_max > CLOCK_MAX)
                        break;
@@ -909,6 +912,11 @@ loop_config(
 #else /* SIGSYS */
                ntp_adjtime(&ntv);
 #endif /* SIGSYS */
+
+               /*
+                * Save the result status and light up nanoseconds
+                * and/or an external clock if available.
+                */
                pll_status = ntv.status;
                if (pll_control) {
 #ifdef STA_NANO
index e35c98f9ded551b6afef0fe9d17f9852d1302027..c441fea65f9abfef00ddaea5b3c67fdc2bb1266e 100644 (file)
@@ -3026,9 +3026,9 @@ peer_unfit(
         * server as the local peer, but only if the remote peer is not
         * the orphan parent.
         */
-       if (peer->stratum > 1 && (peer->refid ==
-           peer->dstadr->addr_refid || (peer->refid == sys_refid &&
-           peer->refid != htonl(LOOPBACKADR))))
+       if (peer->stratum > 1 && peer->refid != htonl(LOOPBACKADR) &&
+           (peer->refid == peer->dstadr->addr_refid || peer->refid ==
+           sys_refid))
                rval |= TEST12;         /* synch loop */
 
        /*