]> git.ipfire.org Git - thirdparty/ntp.git/commitdiff
Changes from Dave Mills:
authorHarlan Stenn <stenn@ntp.org>
Thu, 12 Feb 2004 09:27:25 +0000 (04:27 -0500)
committerHarlan Stenn <stenn@ntp.org>
Thu, 12 Feb 2004 09:27:25 +0000 (04:27 -0500)
1. Servers presented with key IDs they don't have (a common mistake)
return a crypt-NAK. This also happens when the server rolls new private
values daily without telling the clients. To protect against bad guys
tossing an old duplicate over the wall, the client doesn't believe this
unless the timestamps pass the loopback check. If the server was
previously reachable, the client simply restarts the association without
missing a beat. If not, and to protect against a restart loop or later
server restart, the client disregards the NAK and continues (while
disabling burst mode). If really invalid, the association timeout will
eventually expire following which a persistent association is marked
permanently disabled or an ephemeral association is demobilized.

2. One of the most common mistakes is to goof up the identity
credentials. If the client received these credentials via mail, the
script in the message installs the file and link automatically. If done
by hand and done wrong, either the server or client will find the error
and disable the association. As in all such cases, a server or client
ephemeral association is demobilized and the resources recovered.

3. Symmetric modes have always been tricky, much more so with Autokey,
and even more so with misconfigured identity keys. It gets even wilder
when either peer is restarted in the middle of negotiations. All the
evil scenarios I can thing of seem to come out on the other side,
although there are a few that have to wait the association timeout to
properly close down and recover resources.

4. The association is permanently disabled upon kiss-o'-death or
unrecoverable crypto error. So, I re-enabled log reporting for these
smooches. At least the offender is notified.

5. When a really tenacious clogger shows up and lights the call-gap, the
server puts it in the restrict list. He stays there until the server is
restarted. Not only does this discourage the terriot, but evidence is
collected for possible further action.

What more do we have to do to turn this stuff into a real Secure
Timestamping Service? I think the security model, protocols, abuse
hardening and time performance are consistent with a bulletproof service
assuming, that is, PGP mail is used to get the keys and the server
certificates are properly signed.

bk: 402b46fd35bqymM6YLd1z1kCPbI7Ig

include/ntp.h
ntpd/ntp_crypto.c
ntpd/ntp_proto.c
ntpd/ntp_refclock.c

index 5b001edeb0c8ad0218282d119c72d30f11ad234b..9fad6681e33a756e06cd657771f8e2b7e2794ed2 100644 (file)
@@ -99,7 +99,7 @@ typedef char s_char;
 /*
  * Poll interval parameters
  */
-#define NTP_UNREACH    16      /* poll interval backoff count */
+#define NTP_UNREACH    12      /* poll unreach threshold */
 #define        NTP_MINPOLL     4       /* log2 min poll interval (16 s) */
 #define NTP_MINDPOLL   6       /* log2 default min poll (64 s) */
 #define NTP_MAXDPOLL   10      /* log2 default max poll (~17 m) */
@@ -205,13 +205,13 @@ struct interface {
 #define TEST2          0x0002  /* bogus packet received */
 #define TEST3          0x0004  /* protocol unsynchronized */
 #define TEST4          0x0008  /* access denied */
-#define TEST5          0x0010  /* authentication failed */
+#define TEST5          0x0010  /* MAC error */
 #define TEST6          0x0020  /* peer clock unsynchronized */
 #define TEST7          0x0040  /* peer stratum out of bounds */
 #define TEST8          0x0080  /* root delay/dispersion bounds check */
 #define TEST9          0x0100  /* peer delay/dispersion bounds check */
-#define TEST10         0x0200  /* autokey failed */
-#define        TEST11          0x0400  /* proventic not confirmed */
+#define TEST10         0x0200  /* autokey error */
+#define        TEST11          0x0400  /* protocol error */
 
 /*
  * The peer structure. Holds state information relating to the guys
@@ -230,7 +230,6 @@ struct peer {
        u_char  kpoll;          /* last poll interval */
        u_char  minpoll;        /* min poll interval */
        u_char  maxpoll;        /* max poll interval */
-       u_char  burst;          /* packets remaining in burst */
        u_int   flags;          /* association flags */
        u_char  cast_flags;     /* additional flags */
        u_int   flash;          /* protocol error test tally bits */
@@ -241,10 +240,12 @@ struct peer {
        /*
         * Variables used by reference clock support
         */
+#ifdef REFCLOCK
        struct refclockproc *procptr; /* refclock structure pointer */
        u_char  refclktype;     /* reference clock type */
        u_char  refclkunit;     /* reference clock unit number */
        u_char  sstclktype;     /* clock type for system status word */
+#endif /* REFCLOCK */
 
        /*
         * Variables set by received packet
@@ -297,6 +298,7 @@ struct peer {
        u_char  status;         /* peer status */
        u_char  reach;          /* reachability register */
        u_long  epoch;          /* reference epoch */
+       u_int   burst;          /* packets remaining in burst */
        u_short filter_nextpt;  /* index into filter shift register */
        double  filter_delay[NTP_SHIFT]; /* delay shift register */
        double  filter_offset[NTP_SHIFT]; /* offset shift register */
index 3e677032a164c717181877e7ceefd15930d445de..a97d1fb5c599363c9120de6e75b7ec7e6f84f536 100644 (file)
@@ -288,7 +288,8 @@ make_keylist(
         * included in the hash is zero if broadcast mode, the peer
         * cookie if client mode or the host cookie if symmetric modes.
         */
-       lifetime = min(sys_automax, (unsigned long) NTP_MAXSESSION * (1 <<(peer->kpoll)));
+       lifetime = min(sys_automax, (unsigned long) NTP_MAXSESSION *
+           (1 <<(peer->kpoll)));
        if (peer->hmode == MODE_BROADCAST)
                cookie = 0;
        else
@@ -1100,24 +1101,26 @@ crypto_recv(
                }
 
                /*
-                * We log everything except length/format errors and
+                * We don't log length/format/timestamp errors and
                 * duplicates, which are log clogging vulnerabilities.
                 * The first error found terminates the extension field
-                * scan and we return the laundry to the caller.
+                * scan and we return the laundry to the caller. A
+                * length/format/timestamp error on transmit is
+                * cheerfully ignored, as the message is not sent.
                 */
-               if (rval != XEVNT_OK) {
+               if (rval > XEVNT_TSP) {
                        sprintf(statstr,
                            "error %x opcode %x ts %u fs %u", rval,
                            code, tstamp, fstamp);
-                       if (rval > XEVNT_TSP)
-                               record_crypto_stats(&peer->srcadr,
-                                   statstr);
+                       record_crypto_stats(&peer->srcadr, statstr);
                        report_event(rval, peer);
 #ifdef DEBUG
                        if (debug)
                                printf("crypto_recv: %s\n", statstr);
 #endif
                        break;
+               } else if (rval > XEVNT_OK && (code & CRYPTO_RESP)) {
+                       rval = XEVNT_OK;
                }
                authlen += len;
        }
@@ -1181,10 +1184,7 @@ crypto_xmit(
        case CRYPTO_ASSOC | CRYPTO_RESP:
        case CRYPTO_ASSOC:
                len += crypto_send(fp, &hostval);
-               if (crypto_time() == 0)
-                       fp->fstamp = 0;
-               else
-                       fp->fstamp = htonl(crypto_flags);
+               fp->fstamp = htonl(crypto_flags);
                break;
 
        /*
@@ -1216,7 +1216,6 @@ crypto_xmit(
                } else if (vallen == 0 || vallen > MAXHOSTNAME) {
                        opcode |= CRYPTO_ERROR;
                        break;
-
                } else {
                        memcpy(certname, ep->pkt, vallen);
                        certname[vallen] = '\0';
@@ -1642,9 +1641,6 @@ crypto_ident(
         * been found and the CRYPTO_FLAG_VALID bit is set, so the
         * certificate issuer is valid.
         */
-       if (peer->crypto & CRYPTO_FLAG_VRFY)
-               return (0);
-
        if (peer->ident_pkey != NULL)
                EVP_PKEY_free(peer->ident_pkey);
        if (peer->crypto & CRYPTO_FLAG_GQ) {
@@ -1688,8 +1684,7 @@ crypto_ident(
        }
 
        /*
-        * No compatible identity scheme is available. Use the default
-        * TC scheme.
+        * No compatible identity scheme is available. Life is hard.
         */
        msyslog(LOG_INFO,
            "crypto_ident: no compatible identity scheme found");
@@ -1724,6 +1719,9 @@ crypto_args(
                len += strlen(str);
        ep = emalloc(len);
        memset(ep, 0, len);
+       if (opcode == 0)
+               return (ep);
+
        ep->opcode = htonl(opcode + len);
 
        /*
@@ -1820,6 +1818,7 @@ crypto_update(void)
 
        if ((tstamp = crypto_time()) == 0)
                return;
+
        hostval.tstamp = htonl(tstamp);
 
        /*
index eb1d3264890c72c4b077c20abb1e34a82c70d361..aed4ec6309bc05de874b7672a797cd352b62c600 100644 (file)
@@ -148,34 +148,6 @@ transmit(
                        peer->ttl++;
                hpoll = sys_poll;
        } else {
-
-               /*
-                * For associations expecting a reply, the watchdog
-                * counter is bumped by one if the peer has not been
-                * heard since the previous poll. If the counter reaches
-                * the max, the poll interval is doubled and the peer is
-                * demobilized if not configured.
-                */
-               peer->unreach++;
-               if (peer->unreach >= NTP_UNREACH) {
-                       hpoll++;
-                       if (peer->flags & FLAG_CONFIG) {
-
-                               /*
-                                * If nothing is likely to change in
-                                * future, flash the access denied bit
-                                * so we won't bother the dude again.
-                                */
-                               if (memcmp((char *)&peer->refid,
-                                   "DENY", 4) == 0 ||
-                                   memcmp((char *)&peer->refid,
-                                   "CRYP", 4) == 0)
-                                       peer->flash |= TEST4;
-                       } else {
-                               unpeer(peer);
-                               return;
-                       }
-               }
                if (peer->burst == 0) {
                        u_char oreach;
 
@@ -202,8 +174,31 @@ transmit(
                                                return;
                                        }
                                }
-                               if (peer->flags & FLAG_IBURST)
-                                       peer->burst = NTP_BURST;
+
+                               /*
+                                * If a configured association has been
+                                * unreachable for a long time, double
+                                * it at each poll and send a single
+                                * packet instead of a burst. If not
+                                * configured, off it. If it flashes
+                                * authentic error, mark it
+                                * cryptographically dead.
+                                */
+                               if (peer->unreach < NTP_UNREACH) {
+                                       peer->unreach++;
+                                       if (peer->flags & FLAG_IBURST &&
+                                           !(peer->flash & TEST5))
+                                               peer->burst = NTP_BURST;
+                               } else if (!(peer->flags &
+                                   FLAG_CONFIG)) {
+                                       unpeer(peer);
+                                       return;
+                               } else if (peer->flash & TEST5) {
+                                       peer_clear(peer, "CRYPTO");
+                                       peer->flash += TEST4;
+                               } else {
+                                       hpoll++;
+                               }
                        } else {
                                /*
                                 * Here the peer is reachable. If it has
@@ -214,6 +209,7 @@ transmit(
                                 * increase it by one; otherwise, use
                                 * the system poll interval. 
                                 */
+                               peer->unreach = 0;
                                if (!(peer->reach & 0x07)) {
                                        clock_filter(peer, 0., 0.,
                                            MAXDISPERSE);
@@ -229,11 +225,10 @@ transmit(
                } else {
 
                        /*
-                        * Source rate control. If we are restrained,
-                        * each burst consists of only one packet.
+                        * Call-gap control. If we are restrained, each
+                        * burst consists of only one packet.
                         */
-                       if (memcmp((char *)&peer->refid, "RSTR", 4) ==
-                           0)
+                       if (memcmp(&peer->refid, "RSTR", 4) == 0)
                                peer->burst = 0;
                        else
                                peer->burst--;
@@ -252,9 +247,6 @@ transmit(
                                        key_expire(peer);
 #endif /* OPENSSL */
                                }
-                               poll_update(peer, hpoll);
-                               if (peer->reach & ((1 << NTP_BURST) - 1))
-                                       clock_select();
 
                                /*
                                 * If ntpdate mode and the clock has not
@@ -264,15 +256,13 @@ transmit(
                                 */
                                if (mode_ntpdate) {
                                        peer_ntpdate--;
-                                       if (peer_ntpdate > 0) {
-                                               poll_update(
-                                                   peer, hpoll);
-                                               return;
+                                       if (peer_ntpdate == 0) {
+                                               msyslog(LOG_NOTICE,
+                                                   "no reply; clock not set");
+                                               exit (0);
                                        }
-                                       msyslog(LOG_NOTICE,
-                                           "no reply; clock not set");
-                                       exit (0);
                                }
+                               clock_select();
                                poll_update(peer, hpoll);
                                return;
                        }
@@ -281,10 +271,9 @@ transmit(
        peer->outdate = current_time;
 
        /*
-        * Do not transmit if in broadcast cclient mode or access has
-        * been denied. 
+        * Do not transmit if in broadcast client mode. 
         */
-       if (peer->hmode == MODE_BCLIENT || peer->flash & TEST4) {
+       if (peer->hmode == MODE_BCLIENT) {
                poll_update(peer, hpoll);
                return;
 
@@ -295,7 +284,18 @@ transmit(
                poll_update(peer, hpoll);
                return;
        }
-       peer_xmit(peer);
+
+       /*
+        * Do not transmit if in access-deny or crypto jail.
+        */
+       if (peer->flash & TEST4) {
+               if (!(peer->flags & FLAG_CONFIG)) {
+                       unpeer(peer);
+                       return;
+               }
+       } else {
+               peer_xmit(peer);
+       }
        poll_update(peer, hpoll);
 }
 
@@ -643,7 +643,8 @@ receive(
                         * Do not respond to multicast if not configured
                         * as a manycast server.
                         */
-                       if (hismode == MODE_CLIENT && !sys_manycastserver)
+                       if (hismode == MODE_CLIENT &&
+                           !sys_manycastserver)
                                return;
 
                        /*
@@ -655,8 +656,8 @@ receive(
                            PKT_TO_STRATUM(pkt->stratum) <
                            sys_stratum || (sys_cohort &&
                            PKT_TO_STRATUM(pkt->stratum) ==
-                           sys_stratum) ||
-                           rbufp->dstadr->addr_refid == pkt->refid)
+                           sys_stratum) || rbufp->dstadr->addr_refid ==
+                           pkt->refid)
                                return;         /* manycast dropped */
                }
 
@@ -697,7 +698,6 @@ receive(
                        sys_restricted++;
                        return;                 /* no trust */
                }
-
                if (sys_authenticate && !is_authentic)
                        return;                 /* bad auth */
 
@@ -822,7 +822,6 @@ receive(
                 * Seattle. If not authentic, leave a light on and
                 * continue.
                 */
-               peer->flash = 0;
                if (restrict_mask & RES_DONTTRUST) {
                        sys_restricted++;
                        if (peer->flags & FLAG_CONFIG)
@@ -831,8 +830,6 @@ receive(
                                unpeer(peer);
                        return;                 /* no trust */
                }
-               if (has_mac && !is_authentic)
-                       peer->flash |= TEST5;   /* bad auth */
                break;
 
        default:
@@ -858,22 +855,25 @@ receive(
 
        /*
         * We do a little homework. Note we can get here with an
-        * authentication error. We Need to do this in order to validate
+        * authentication error. We need to do this in order to validate
         * a crypto-NAK later. Note the order of processing; it is very
         * important to avoid livelocks, deadlocks and lockpicks.
         */
-       peer->timereceived = current_time;
        peer->received++;
-       if (peer->flash & TEST5)
-               peer->flags &= ~FLAG_AUTHENTIC;
-       else
-               peer->flags |= FLAG_AUTHENTIC;
+       peer->timereceived = current_time;
+       peer->flash = 0;
+       peer->flags &= ~FLAG_AUTHENTIC;
+       if (has_mac) {
+               if (is_authentic)
+                       peer->flags |= FLAG_AUTHENTIC;
+               else if (sys_authenticate)
+                       peer->flash |= TEST5;   /* bad auth */
+       }
        NTOHL_FP(&pkt->org, &p_org);
        NTOHL_FP(&pkt->xmt, &p_xmt);
 
        /*
-        * If the packet is an old duplicate, we let it through so the
-        * extension fields will be processed.
+        * If the packet is an old duplicate, drop it.
         */
        if (L_ISEQU(&peer->org, &p_xmt)) {      /* test 1 */
                peer->flash |= TEST1;           /* dupe */
@@ -897,19 +897,22 @@ receive(
         * timestamp matches the packet originate timestamp, loopback is
         * confirmed. Note in symmetric modes this also happens when the
         * first packet from the active peer arrives at the newly
-        * mobilized passive peer.  An authentication error probably
+        * mobilized passive peer. An authentication error probably
         * means the server or peer restarted or rolled a new private
         * value, but could be an intruder trying to stir up trouble.
-        * However, if this is a crypto-NAK, we know it is authentic, so
-        * dump the association and wait for the next message.
+        * However, if this is a crypto-NAK, we know it is authentic. If
+        * the server is reachable, restart the protocol; if not, ignore
+        * it and wait for timeout.
         */
        } else if (L_ISEQU(&peer->xmt, &p_org)) {
                if (peer->flash & TEST5) {
-                       if (has_mac == 4 && pkt->exten[0] == 0) {
-                               if (peer->flags & FLAG_CONFIG)
+                       if (has_mac == 4 && pkt->exten[0] == 0 &&
+                               peer->reach) {
+                               if (peer->flags & FLAG_CONFIG) {
                                        peer_clear(peer, "AUTH");
-                               else
+                               } else {
                                        unpeer(peer);
+                               }
                        }
                        return;
                }
@@ -997,13 +1000,15 @@ receive(
         *    matches the previous key ID or ultimate original key ID
         *    obtained from the broadcaster or symmetric peer. If no
         *    match, sit the dance and wait for timeout.
+        *
+        * In case of crypto error, fire the orchestra and stop dancing.
         */
        if (crypto_flags && (peer->flags & FLAG_SKEY)) {
                peer->flash |= TEST10;
                rval = crypto_recv(peer, rbufp);
                if (rval != XEVNT_OK) {
-                       /* fall through */
-
+                       peer_clear(peer, "CRYP");
+                       peer->flash |= TEST4;   /* crypto error */
                } else if (hismode == MODE_SERVER) {
                        if (skeyid == peer->keyid)
                                peer->flash &= ~TEST10;
@@ -1038,63 +1043,45 @@ receive(
                        peer->ppoll = pkt->ppoll;
                        poll_update(peer, 0);
                }
-
-               /*
-                * If the return code from extension field processing is
-                * not okay, we scrub the association and start over.
-                */
-               if (rval != XEVNT_OK) {
-
-                       /*
-                        * If the return code is bad, the crypto machine
-                        * may be jammed or an intruder may lurk. First,
-                        * we demobilize the association, then see if
-                        * the error is recoverable.
-                        */
-                       if (peer->flags & FLAG_CONFIG)
-                               peer_clear(peer, "CRYP");
-                       else
-                               unpeer(peer);
-#ifdef DEBUG
-                       if (debug)
-                               printf("packet: bad exten %x\n", rval);
-#endif
-                       return;
-               }
-
-               /*
-                * If TEST10 is lit, the autokey sequence has broken,
-                * which probably means the server has refreshed its
-                * private value. We reset the poll interval to the
-                & minimum and scrub the association clean.
-                */
-               if (peer->flash & TEST10 && peer->crypto &
-                   CRYPTO_FLAG_AUTO) {
-                       poll_update(peer, peer->minpoll);
-#ifdef DEBUG
-                       if (debug)
-                               printf(
-                                   "packet: bad auto %03x\n",
-                                   peer->flash);
-#endif
-                       if (peer->flags & FLAG_CONFIG)
-                               peer_clear(peer, "AUTO");
-                       else
-                               unpeer(peer);
-                       return;
-               }
        }
 #endif /* OPENSSL */
 
        /*
-        * We have survived the gaunt. Forward to the packet routine. If
-        * a symmetric passive association has been mobilized and the
-        * association doesn't deserve to live, it will die in the
-        * transmit routine if not reachable after timeout. However, if
-        * either symmetric mode and the crypto code has something
-        * urgent to say, we expedite the response.
+        * The dance is complete and the flash bits have been lit. Toss
+        * the packet over the fence for processing, which may light up
+        * more flashers.
         */
        process_packet(peer, pkt, &rbufp->recv_time);
+
+       /*
+        * Well, that was nice. If TEST4 is lit, either the crypto
+        * machine jammed or a kiss-o'-death packet flew in, either of
+        * which is fatal.
+        */
+       if (peer->flash & TEST4) {
+               msyslog(LOG_INFO, "receive: fatal error %03x for %s",
+                   peer->flash, stoa(&peer->srcadr));
+               if (!(peer->flags & FLAG_CONFIG))
+                       unpeer(peer);
+               return;
+       }
+
+       /*
+        * If TEST10 is lit, the autokey sequence has broken, which
+        * probably means the server has refreshed its private value.
+        * Not to worry, reset and wait for the next time.
+        */
+       if (peer->flash & TEST10 && peer->crypto & CRYPTO_FLAG_AUTO) {
+#ifdef DEBUG
+               if (debug)
+                       printf(
+                           "receive: bad auto %03x\n", peer->flash);
+#endif
+               if (peer->flags & FLAG_CONFIG)
+                       peer_clear(peer, "AUTO");
+               else
+                       unpeer(peer);
+       }
 }
 
 
@@ -1139,6 +1126,19 @@ process_packet(
                p_org = peer->rec;
        pstratum = PKT_TO_STRATUM(pkt->stratum);
 
+       /*
+        * Test for kiss-o'death packet (DENY or CRYP)
+        */
+       if (pleap == LEAP_NOTINSYNC && pstratum == STRATUM_UNSPEC) {
+               if (memcmp(&pkt->refid, "DENY", 4) == 0) {
+                       peer_clear(peer, "DENY");
+                       peer->flash |= TEST4;   /* access deny */
+               } else if (memcmp(&pkt->refid, "CRYP", 4) == 0) {
+                       peer_clear(peer, "CRYP");
+                       peer->flash |= TEST4;   /* crypto error */
+               }
+       }
+
        /*
         * Test for unsynchronized server.
         */
@@ -1163,7 +1163,7 @@ process_packet(
        if (peer->flash) {
 #ifdef DEBUG
                if (debug)
-                       printf("packet: bad data %03x from address: %s\n",
+                       printf("packet: bad data %03x from %s\n",
                            peer->flash, stoa(&peer->srcadr));
 #endif
                return;
@@ -1218,7 +1218,6 @@ process_packet(
                peer->timereachable = current_time;
        }
        peer->reach |= 1;
-       peer->unreach = 0;
        poll_update(peer, 0);
 
        /*
@@ -1233,16 +1232,16 @@ process_packet(
         *
         * It is very important to respect the hazards of overflow. The
         * only permitted operation on raw timestamps is subtraction,
-        * where the result is a signed quantity spanning from 68 years in
-        * the past to 68 years in the future. To avoid loss of precision,
-        * these calculations are done using 64-bit integer arithmetic.
-        * However, the offset and delay calculations are sums and
-        * differences of these first-order differences, which if done
-        * using 64-bit integer arithmetic, would be valid over only half
-        * that span. Since the typical first-order differences are
-        * usually very small, they are converted to 64-bit doubles and
-        * all remaining calculations done in floating-point arithmetic.
-        * This preserves the accuracy while retaining the 68-year span.
+        * where the result is a signed quantity spanning from 68 years
+        * in the past to 68 years in the future. To avoid loss of
+        * precision, these calculations are done using 64-bit integer
+        * arithmetic. However, the offset and delay calculations are
+        * sums and differences of these first-order differences, which
+        * if done using 64-bit integer arithmetic, would be valid over
+        * only half that span. Since the typical first-order
+        * differences are usually very small, they are converted to 64-\v        * bit doubles and all remaining calculations done in floating-
+        * point arithmetic. This preserves the accuracy while retaining
+        * the 68-year span.
         *
         * Let t1 = p_org, t2 = p_rec, t3 = p_xmt, t4 = peer->rec:
         */
@@ -1299,7 +1298,7 @@ process_packet(
                return;
        }
        clock_filter(peer, p_offset, p_del, p_disp);
-       if (peer->burst == 0)
+       if (peer->burst == 0 || sys_leap == LEAP_NOTINSYNC)
                clock_select();
        record_peer_stats(&peer->srcadr, ctlpeerstatus(peer),
            peer->offset, peer->delay, peer->disp,
@@ -1456,7 +1455,7 @@ poll_update(
        } else if (peer->cast_flags & MDF_ACAST) {
                if (sys_survivors >= sys_minclock || peer->ttl >=
                    sys_ttlmax)
-                       peer->kpoll = (u_char) (peer->hpoll + 3);
+                       peer->kpoll = (u_char)(peer->hpoll + 3);
                else
                        peer->kpoll = peer->hpoll;
                peer->nextdate = peer->outdate + RANDPOLL(peer->kpoll);
@@ -1488,7 +1487,7 @@ poll_update(
 
 
 /*
- * clear - clear peer filter registers.  See Section 3.4.8 of the spec.
+ * peer_clear - clear peer filter registers.  See Section 3.4.8 of the spec.
  */
 void
 peer_clear(
@@ -1566,14 +1565,13 @@ peer_clear(
         * intervals.
         */
        peer->nextdate = peer->update = peer->outdate = current_time;
-       peer->burst = 0;
        if (oreach)
                poll_update(peer, 0);
        else if (initializing)
                peer->nextdate = current_time + peer_associations;
        else
-               peer->nextdate = current_time + (u_int)RANDOM %
-                   peer_associations;
+               peer->nextdate = current_time + max((u_int)RANDOM %
+                   peer_associations, BURST_DELAY);
 #ifdef DEBUG
        if (debug)
                printf("peer_clear: at %ld assoc ID %d refid %s\n",
@@ -1732,8 +1730,8 @@ clock_filter(
         * consider the update a popcorn spike and ignore it.
         */
        if (m > 1 && etemp > CLOCK_SGATE * dtemp &&
-           (long)(peer->filter_epoch[k] - peer->epoch) < (1 << (sys_poll +
-           1))) {
+           (long)(peer->filter_epoch[k] - peer->epoch) < (1 <<
+           (sys_poll + 1))) {
 #ifdef DEBUG
                if (debug)
                        printf("clock_filter: popcorn %.6f %.6f\n",
@@ -2287,8 +2285,8 @@ clock_select(void)
 #endif
                         src = ntoa(&sys_peer->srcadr);
                NLOG(NLOG_SYNCSTATUS)
-                   msyslog(LOG_INFO, "synchronized to %s, stratum=%d", src,
-                           sys_peer->stratum);
+                   msyslog(LOG_INFO, "synchronized to %s, stratum %d",
+                       src, sys_peer->stratum);
        }
        clock_update();
 }
@@ -2346,7 +2344,7 @@ peer_xmit(
        l_fp    xmt_tx;
 
        /*
-        * Initialize transmit packet header fields.
+        * Initialize the transmit packet header fields.
         */
        xpkt.li_vn_mode = PKT_LI_VN_MODE(sys_leap, peer->version,
            peer->hmode);
@@ -2394,7 +2392,6 @@ peer_xmit(
 #ifdef OPENSSL
        if (crypto_flags && (peer->flags & FLAG_SKEY)) {
                struct exten *exten;    /* extension field */
-               u_int   opcode;
 
                /*
                 * The Public Key Dance (PKD): Cryptographic credentials
@@ -2451,6 +2448,7 @@ peer_xmit(
                                key_expire(peer);
                }
                peer->keyid = xkeyid;
+               exten = NULL;
                switch (peer->hmode) {
 
                /*
@@ -2467,9 +2465,6 @@ peer_xmit(
                        else
                                exten = crypto_args(peer, CRYPTO_ASSOC |
                                    CRYPTO_RESP, NULL);
-                       sendlen += crypto_xmit(&xpkt, &peer->srcadr,
-                           sendlen, exten, 0);
-                       free(exten);
                        break;
 
                /*
@@ -2483,16 +2478,6 @@ peer_xmit(
                 */
                case MODE_ACTIVE:
                case MODE_PASSIVE:
-                       if (peer->cmmd != NULL) {
-                               peer->cmmd->associd =
-                                   htonl(peer->associd);
-                               sendlen += crypto_xmit(&xpkt,
-                                   &peer->srcadr, sendlen, peer->cmmd,
-                                   0);
-                               free(peer->cmmd);
-                               peer->cmmd = NULL;
-                       }
-                       exten = NULL;
                        if (!peer->crypto)
                                exten = crypto_args(peer, CRYPTO_ASSOC,
                                    sys_hostname);
@@ -2506,8 +2491,9 @@ peer_xmit(
                         * deadlock when the passive peer is walking the
                         * certificate trail. Awesome.
                         */
-                       else if ((opcode = crypto_ident(peer)) != 0)
-                               exten = crypto_args(peer, opcode, NULL);
+                       else if (!(peer->crypto & CRYPTO_FLAG_VRFY))
+                               exten = crypto_args(peer,
+                                   crypto_ident(peer), NULL);
                        else if (sys_leap != LEAP_NOTINSYNC &&
                           !(peer->crypto & CRYPTO_FLAG_SIGN))
                                exten = crypto_args(peer, CRYPTO_SIGN,
@@ -2545,11 +2531,6 @@ peer_xmit(
                            !(peer->crypto & CRYPTO_FLAG_LEAP))
                                exten = crypto_args(peer, CRYPTO_TAI,
                                    NULL);
-                       if (exten != NULL) {
-                               sendlen += crypto_xmit(&xpkt,
-                                   &peer->srcadr, sendlen, exten, 0);
-                               free(exten);
-                       }
                        break;
 
                /*
@@ -2571,16 +2552,6 @@ peer_xmit(
                 * the parameters but the server does not.
                 */
                case MODE_CLIENT:
-                       if (peer->cmmd != NULL) {
-                               peer->cmmd->associd =
-                                   htonl(peer->associd);
-                               sendlen += crypto_xmit(&xpkt,
-                                   &peer->srcadr, sendlen, peer->cmmd,
-                                   0);
-                               free(peer->cmmd);
-                               peer->cmmd = NULL;
-                       }
-                       exten = NULL;
                        if (!peer->crypto)
                                exten = crypto_args(peer, CRYPTO_ASSOC,
                                    sys_hostname);
@@ -2589,10 +2560,11 @@ peer_xmit(
                                    peer->issuer);
 
                        /*
-                        * Identity.
+                        * Identity
                         */
-                       else if ((opcode = crypto_ident(peer)) != 0)
-                               exten = crypto_args(peer, opcode, NULL);
+                       else if (!(peer->crypto & CRYPTO_FLAG_VRFY))
+                               exten = crypto_args(peer,
+                                   crypto_ident(peer), NULL);
 
                        /*
                         * Autokey
@@ -2618,36 +2590,63 @@ peer_xmit(
                            !(peer->crypto & CRYPTO_FLAG_LEAP))
                                exten = crypto_args(peer, CRYPTO_TAI,
                                    NULL);
-                       if (exten != NULL) {
+                       break;
+               }
+
+               /*
+                * Build the extension fields if available. If an error
+                * occured, the crypto machinery broke or was
+                * misconfigured, so plaint the log and douse the
+                * boiler.
+                */
+               if (peer->cmmd != NULL) {
+                       peer->cmmd->associd = htonl(peer->associd);
+                       sendlen += crypto_xmit(&xpkt, &peer->srcadr,
+                           sendlen, peer->cmmd, 0);
+                       free(peer->cmmd);
+                       peer->cmmd = NULL;
+               }
+               if (exten != NULL) {
+                       if (exten->opcode != 0) {
                                sendlen += crypto_xmit(&xpkt,
                                    &peer->srcadr, sendlen, exten, 0);
-                               free(exten);
+                       } else {
+                               peer_clear(peer, "CRYP");
+                               peer->flash |= TEST4; /* crypto error */
+                               msyslog(LOG_INFO,
+                                   "transmit: crypto error for %s",
+                                   stoa(&peer->srcadr));
                        }
-                       break;
+                       free(exten);
                }
 
                /*
                 * If extension fields are present, we must use a
-                * private value of zero and force min poll interval.
-                * Most intricate.
+                * private cookie value of zero. Most intricate.
                 */
                if (sendlen > LEN_PKT_NOMAC)
                        session_key(&peer->dstadr->sin, &peer->srcadr,
                            xkeyid, 0, 2);
        } 
 #endif /* OPENSSL */
+
+       /*
+        * If something broke go directly to jail without sending the
+        * packet.
+        */
+       if (peer->flash & TEST4)
+               return;
+
        xkeyid = peer->keyid;
        get_systime(&peer->xmt);
        L_ADD(&peer->xmt, &sys_authdelay);
        HTONL_FP(&peer->xmt, &xpkt.xmt);
        authlen = authencrypt(xkeyid, (u_int32 *)&xpkt, sendlen);
        if (authlen == 0) {
-               msyslog(LOG_INFO,
-                   "transmit: encryption key %d not found", xkeyid);
-               if (peer->flags & FLAG_CONFIG)
-                       peer_clear(peer, "NKEY");
-               else
-                       unpeer(peer);
+               peer_clear(peer, "NKEY");
+               peer->flash |= TEST4;           /* no key found */
+               msyslog(LOG_INFO, "transmit: key %u not found for %s",
+                   xkeyid, stoa(&peer->srcadr));
                return;
        }
        sendlen += authlen;
@@ -2722,8 +2721,8 @@ fast_xmit(
        /*
         * Initialize transmit packet header fields from the receive
         * buffer provided. We leave some fields intact as received. If
-        * the gazinta was from a multicast address, the gazouta must go
-        * out another way.
+        * the gazinta was from a multicast address, the gazoutta must
+        * go out another way.
         */
        rpkt = &rbufp->recv_pkt;
        if (rbufp->dstadr->flags & INT_MULTICAST)
@@ -2745,11 +2744,13 @@ fast_xmit(
                }
 
                /*
-                * Here we light up a kiss-of-death packet. Note the
-                * rate limit on these packets. Once a second initialize
-                * a bucket counter. Every packet sent decrements the
-                * counter until reaching zero. If the counter is zero,
-                * drop the kod.
+                * Here we light up a kiss-of-death (KoD) packet. KoD
+                * packets have leap bits unsynchronized, stratum zero
+                * and reference ID the four-character error code. Note
+                * the rate limit on these packets. Once a second
+                * initialize a bucket counter. Every packet sent
+                * decrements the counter until reaching zero. If the
+                * counter is zero, drop the kod.
                 */
                if (sys_kod == 0 || !(mask & RES_DEMOBILIZE))
                        return;
@@ -3205,8 +3206,8 @@ proto_config(
                 * Log this error.
                 */
                msyslog(LOG_INFO,
-                       "proto_config: illegal item %d, value %ld",
-                       item, value);
+                   "proto_config: illegal item %d, value %ld", item,
+                   value);
        }
 }
 
index eb7f86a17443d4509d5a1bb857f82b8f792d77bb..41a4ba4de8e7e17897684cfa1da4b01537ffafd9 100644 (file)
@@ -542,9 +542,8 @@ refclock_receive(
         * the median filter samples and give the data to the clock
         * filter.
         */
-       peer->received++;
        pp = peer->procptr;
-       peer->processed++;
+       peer->received++;
        peer->timereceived = current_time;
        peer->leap = pp->leap;
        if (peer->leap == LEAP_NOTINSYNC) {