]> git.ipfire.org Git - thirdparty/ntp.git/commitdiff
Crypto cleanup from Dave.
authorHarlan Stenn <stenn@ntp.org>
Thu, 27 Jun 2002 23:25:13 +0000 (19:25 -0400)
committerHarlan Stenn <stenn@ntp.org>
Thu, 27 Jun 2002 23:25:13 +0000 (19:25 -0400)
bk: 3d1b9ed9wMoRXsI3BrLS2QLmfH6pkA

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

index 798d1c1d707a19d66b34a4e86531e1ecb0cd26d2..49763dcba4df95ea9a4808b03233c7c90b08ea2d 100644 (file)
@@ -142,7 +142,7 @@ extern      void    resetmanycast   P((void));
 /* ntp_crypto.c */
 #ifdef OPENSSL
 extern void    crypto_recv     P((struct peer *, struct recvbuf *));
-extern int     crypto_xmit     P((struct pkt *, int, struct exten *, keyid_t));
+extern int     crypto_xmit     P((struct pkt *, struct sockaddr_in *, int, struct exten *, keyid_t));
 extern keyid_t session_key     P((struct sockaddr_in *, struct sockaddr_in *, keyid_t, keyid_t, u_long));
 extern void    make_keylist    P((struct peer *, struct interface *));
 extern void    key_expire      P((struct peer *));
@@ -150,7 +150,6 @@ extern      void    crypto_update   P((void));
 extern void    crypto_config   P((int, char *));
 extern void    crypto_setup    P((void));
 extern struct exten *crypto_args P((struct peer *, u_int, u_char *));
-extern int     crypto_check    P((struct recvbuf *));
 extern int     crypto_public   P((struct peer *, u_char *, u_int));
 extern void    value_free      P((struct value *));
 extern time_t  timegm          P((struct tm *));
index 274ad56f1eca9c509feb6195356d8cc2d8ddabc0..9521b199c490000e1d3dac36bf90a9431f96640a 100644 (file)
@@ -375,6 +375,7 @@ crypto_recv(
                code = ntohl(ep->opcode) & 0xffff0000;
                len = ntohl(ep->opcode) & 0x0000ffff;
                associd = ntohl(pkt[1]);
+               rval = XEVNT_OK;
 #ifdef DEBUG
                if (debug)
                        printf(
@@ -384,7 +385,8 @@ crypto_recv(
 #endif
 
                /*
-                * Check version number and field length.
+                * Check version number and field length. If bad,
+                * quietly ignore the packet.
                 */
                if (((code >> 24) & 0x3f) != CRYPTO_VN || len < 8 ||
                    (len < VALUE_LEN && (code & CRYPTO_RESP))) {
@@ -394,8 +396,8 @@ crypto_recv(
                                printf(
                                    "crypto_recv: incorrect version or field length\n");
 #endif
-                       peer->flash |= TEST12;
-                       code |= CRYPTO_ERROR;;
+                       rval = XEVNT_LEN;
+                       break;
                }
 
                /*
@@ -413,11 +415,7 @@ crypto_recv(
                        tstamp = ntohl(ep->tstamp);
                        fstamp = ntohl(ep->fstamp);
                        vallen = ntohl(ep->vallen);
-               } else {
-                       tstamp = fstamp = 0;
-                       vallen = 0;
                }
-               rval = XEVNT_OK;
                switch (code) {
 
                /*
@@ -446,16 +444,62 @@ crypto_recv(
                case CRYPTO_ASSOC | CRYPTO_RESP:
 
                        /*
-                        * Discard the message if it has invalid length
-                        * or the status word has already been stored.
+                        * Discard the message if it has already been
+                        * stored or has invalid length.
+                        */
+                       if (peer->crypto)
+                               break;
+
+                       if (len < VALUE_LEN + vallen) {
+                               rval = XEVNT_LEN;
+                               break;
+                       }
+
+                       /*
+                        * Check the identity schemes are compatible. If
+                        * no scheme is in use for both server and
+                        * client, the default TC scheme is used. If the
+                        * both server and client have private
+                        * certificates, the server public key and
+                        * identity are presumed valid, so we skip the
+                        * certificate and identity stages and move
+                        * immediately to the cookie stage which
+                        * confirms the server signature. If either both
+                        * server and client agree on either IFF or GQ
+                        * schemes, that survives. If this is a server
+                        * reply from a configured client, we use either
+                        * the IFF or GQ schemes if both agree, or the
+                        * default scheme if not. If none of the above,
+                        * raise blow the whistle and dump the
+                        * association.
+                        */
+                       temp32 = PKT_MODE(rbufp->recv_pkt.li_vn_mode);
+                       if (crypto_flags & CRYPTO_FLAG_PRIV) {
+                               peer->crypto |= CRYPTO_FLAG_SIGN;
+                               if (fstamp & CRYPTO_FLAG_PRIV)
+                                       fstamp |= CRYPTO_FLAG_VALID |
+                                           CRYPTO_FLAG_VRFY;
+                               else if (temp32 != MODE_SERVER)
+                                       rval = XEVNT_ID;
+                       } else if (!(temp32 == MODE_SERVER ||
+                           !(crypto_flags & (CRYPTO_FLAG_IFF |
+                           CRYPTO_FLAG_GQ)) || (crypto_flags & fstamp &
+                           CRYPTO_FLAG_IFF) || (crypto_flags & fstamp &
+                           CRYPTO_FLAG_GQ))) {
+                               rval = XEVNT_ID;
+                       }
+
+                       /*
+                        * Discard the message if identity error or from
+                        * unsynchronized host.
                         */
-                       if (peer->crypto || len < VALUE_LEN + vallen)
+                       if (rval != XEVNT_OK || !fstamp)
                                break;
 
                        /*
-                        * Discard the message and report an error if
-                        * the host name length is unreasonable or the
-                        * signature digest NID is not supported.
+                        * Discard the message if the host name length
+                        * is unreasonable or the signature digest NID
+                        * is not supported.
                         */
                        temp32 = (fstamp >> 16) & 0xffff;
                        dp =
@@ -465,44 +509,22 @@ crypto_recv(
                                rval = XEVNT_LEN;
                        else if (dp == NULL)
                                rval = XEVNT_MD;
-                       if (rval != XEVNT_OK) {
-                               report_event(rval, peer);
-                               peer->flash |= TEST12;
+                       if (rval != XEVNT_OK)
                                break;
-                       }
 
                        /*
                         * Save status word, host name and message
                         * digest/signature type.
                         */
-                       peer->crypto = fstamp;
+                       peer->crypto |= fstamp;
                        peer->digest = dp;
                        peer->subject = emalloc(vallen + 1);
                        memcpy(peer->subject, ep->pkt, vallen);
                        peer->subject[vallen] = '\0';
-
-                       /*
-                        * If the certificates of both server and client
-                        * are private, the server public key and
-                        * identity are presumed valid. We skip the
-                        * certificate and identity stages and move
-                        * immediately to the cookie stage, which
-                        * confirms the server signature. If server and
-                        * client do not have identical public key and
-                        * identity values, nothing further will work.
-                        * Note we have not verified the server
-                        * signature yet.
-                        */
-                       if (crypto_flags & CRYPTO_FLAG_PRIV) {
-                               peer->crypto |= CRYPTO_FLAG_SIGN;
-                               if (peer->crypto & CRYPTO_FLAG_PRIV) {
-                                       peer->crypto |=
-                                           CRYPTO_FLAG_VALID |
-                                           CRYPTO_FLAG_VRFY;
-                               }
-                       }
-                       sprintf(statstr, "host %s %s (%u)",
-                           peer->subject, OBJ_nid2ln(temp32), temp32);
+                       temp32 = (fstamp >> 16) & 0xffff;
+                       sprintf(statstr,
+                           "flags 0x%x host %s signature %s", fstamp,
+                           peer->subject, OBJ_nid2ln(temp32));
                        record_crypto_stats(&peer->srcadr, statstr);
 #ifdef DEBUG
                        if (debug)
@@ -522,7 +544,8 @@ crypto_recv(
                        /*
                         * Discard the message if invalid.
                         */
-                       if (crypto_verify(ep, NULL, peer) != XEVNT_OK)
+                       if ((rval = crypto_verify(ep, NULL, peer)) !=
+                           XEVNT_OK)
                                break;
 
                        /*
@@ -530,14 +553,8 @@ crypto_recv(
                         * versions and link the newest version first on
                         * the list.
                         */
-                       rval = cert_install(ep, peer);
-                       if (rval != XEVNT_OK) {
-                               if (rval != XEVNT_TSP) {
-                                       report_event(rval, peer);
-                                       peer->flash |= TEST12;
-                               }
+                       if ((rval = cert_install(ep, peer)) != XEVNT_OK)
                                break;
-                       }
 
                        /*
                         * If we snatch the certificate before the
@@ -601,7 +618,8 @@ crypto_recv(
                        /*
                         * Discard the message if invalid.
                         */
-                       if (crypto_verify(ep, NULL, peer) != XEVNT_OK)
+                       if ((rval = crypto_verify(ep, NULL, peer)) !=
+                           XEVNT_OK)
                                break;
 
                        /*
@@ -613,14 +631,9 @@ crypto_recv(
                         * certificate stages and move immediately to
                         * the cookie stage.
                         */
-                       rval = crypto_iff(ep, peer);
-                       if (rval != XEVNT_OK) {
-                               if (rval != XEVNT_TSP) {
-                                       report_event(rval, peer);
-                                       peer->flash |= TEST12;
-                               }
+                       if ((rval = crypto_iff(ep, peer)) != XEVNT_OK)
                                break;
-                       }
+
                        peer->crypto |= CRYPTO_FLAG_VRFY |
                            CRYPTO_FLAG_PROV;
                        peer->flash &= ~TEST10;
@@ -648,7 +661,8 @@ crypto_recv(
                        /*
                         * Discard the message if invalid.
                         */
-                       if (crypto_verify(ep, NULL, peer) != XEVNT_OK)
+                       if ((rval = crypto_verify(ep, NULL, peer)) !=
+                           XEVNT_OK)
                                break;
 
                        /*
@@ -660,14 +674,9 @@ crypto_recv(
                         * certificate stages and move immediately to
                         * the cookie stage.
                         */
-                       rval = crypto_gq(ep, peer);
-                       if (rval != XEVNT_OK) {
-                               if (rval != XEVNT_TSP) {
-                                       report_event(rval, peer);
-                                       peer->flash |= TEST12;
-                               }
+                       if ((rval = crypto_gq(ep, peer)) != XEVNT_OK)
                                break;
-                       }
+
                        peer->crypto |= CRYPTO_FLAG_VRFY |
                            CRYPTO_FLAG_PROV;
                        peer->flash &= ~TEST10;
@@ -697,7 +706,7 @@ crypto_recv(
                        if (!(peer->crypto & CRYPTO_FLAG_VRFY))
                                break;
 
-                       if (crypto_verify(ep, &pubkey, peer) !=
+                       if ((rval = crypto_verify(ep, &pubkey, peer)) !=
                            XEVNT_OK)
                                break;
 
@@ -706,14 +715,8 @@ crypto_recv(
                         * versions and link the newest version first on
                         * the list.
                         */
-                       rval = cert_install(ep, peer);
-                       if (rval != XEVNT_OK) {
-                               if (rval != XEVNT_TSP) {
-                                       report_event(rval, peer);
-                                       peer->flash |= TEST12;
-                               }
-                               break;
-                       }
+                       if ((rval = cert_install(ep, peer)) != XEVNT_OK)                                break;
+
                        peer->crypto |= CRYPTO_FLAG_SIGN;
                        peer->flash &= ~TEST10;
                        temp32 = cinfo->nid;
@@ -742,12 +745,13 @@ crypto_recv(
                        if (!(peer->crypto & CRYPTO_FLAG_VRFY))
                                break;
 
-                       if (crypto_verify(ep, NULL, peer) != XEVNT_OK)
+                       if ((rval = crypto_verify(ep, NULL, peer)) !=
+                           XEVNT_OK)
                                break;
 
                        /*
                         * Pass the extension field to the transmit
-                        * side.
+                        * side. If already agreed, walk away.
                         */
                        fp = emalloc(len);
                        memcpy(fp, ep, len);
@@ -796,8 +800,8 @@ crypto_recv(
                        if (!(peer->crypto & CRYPTO_FLAG_VRFY))
                                break;
 
-                       else if (crypto_verify(ep, &peer->cookval,
-                           peer) != XEVNT_OK)
+                       if ((rval = crypto_verify(ep, &peer->cookval,
+                           peer)) != XEVNT_OK)
                                break;
 
                        /*
@@ -812,8 +816,7 @@ crypto_recv(
                                    RSA_PKCS1_OAEP_PADDING);
                                cookie = ntohl(temp32);
                        } else {
-                               report_event(XEVNT_CKY, peer);
-                               peer->flash |= TEST12;
+                               rval = XEVNT_CKY;
                                break;
                        }
 
@@ -866,13 +869,13 @@ crypto_recv(
                        if (!(peer->crypto & CRYPTO_FLAG_VRFY))
                                break;
 
-                       if (crypto_verify(ep, &peer->recval, peer) !=
-                           XEVNT_OK)
+                       if ((rval = crypto_verify(ep, &peer->recval,
+                           peer)) != XEVNT_OK)
                                break;
 
                        /*
                         * Install autokey values and light the
-                        * autokey bit.This is not hard.
+                        * autokey bit. This is not hard.
                         */
                        if (peer->recval.ptr == NULL)
                                peer->recval.ptr =
@@ -915,7 +918,8 @@ crypto_recv(
                        if (!(peer->crypto & CRYPTO_FLAG_VRFY))
                                break;
 
-                       if (crypto_verify(ep, NULL, peer) != XEVNT_OK)
+                       if ((rval = crypto_verify(ep, NULL, peer)) !=
+                           XEVNT_OK)
                                break;
 
                        /*
@@ -944,8 +948,8 @@ crypto_recv(
                        if (!(peer->crypto & CRYPTO_FLAG_VRFY))
                                break;
 
-                       if (crypto_verify(ep, &peer->tai_leap, peer) !=
-                           XEVNT_OK)
+                       if ((rval = crypto_verify(ep, &peer->tai_leap,
+                           peer)) != XEVNT_OK)
                                break;
 
                        /*
@@ -1009,8 +1013,10 @@ crypto_recv(
                case CRYPTO_IFF:
                case CRYPTO_GQ:
                case CRYPTO_SIGN:
-                       if (len < VALUE_LEN)
+                       if (len < VALUE_LEN) {
+                               rval = XEVNT_LEN;
                                break;
+                       }
 
                        /* fall through */
 
@@ -1025,7 +1031,8 @@ crypto_recv(
                        if (code & CRYPTO_RESP)
                                break;
 
-                       if (crypto_verify(ep, NULL, peer) != XEVNT_OK)
+                       if ((rval = crypto_verify(ep, NULL, peer)) !=
+                           XEVNT_OK)
                                break;
 
                        fp = emalloc(len);
@@ -1034,6 +1041,23 @@ crypto_recv(
                        fp->opcode |= htonl(temp32);
                        peer->cmmd = fp;
                }
+
+               /*
+                * We ignore length/format errors and duplicates. Other
+                * errors are reported to the log and traps.
+                */
+               if (rval > XEVNT_TSP) {
+                       sprintf(statstr,
+                           "error %x opcode %x ts %u fs %u", rval,
+                           code, tstamp, fstamp);
+                       record_crypto_stats(&peer->srcadr, statstr);
+                       report_event(rval, peer);
+                       peer->flash |= TEST12;
+#ifdef DEBUG
+                       if (debug)
+                               printf("crypto_recv: %s\n", statstr);
+#endif
+               }
                authlen += len;
        }
        return;
@@ -1053,6 +1077,7 @@ crypto_recv(
 int
 crypto_xmit(
        struct pkt *xpkt,       /* transmit packet pointer */
+       struct sockaddr_in *srcadr_sin, /* active runway */
        int     start,          /* offset to extension field */
        struct exten *ep,       /* extension pointer */
        keyid_t cookie          /* session cookie */
@@ -1064,10 +1089,13 @@ crypto_xmit(
        struct exten *fp;       /* extension pointers */
        struct cert_info *cp;   /* certificate info/value pointer */
        char    certname[MAX_HOSTLEN + 1]; /* subject name buffer */
+       u_char  statstr[NTP_MAXSTRLEN]; /* statistics for filegen */
        u_int   vallen;
        struct value vtemp;
        associd_t associd;
+       int     rval;
        u_int   len;
+       u_int32 temp32;
        keyid_t tcookie;
 
        /*
@@ -1081,17 +1109,33 @@ crypto_xmit(
        associd = ntohl(ep->associd);
        fp->associd = htonl(associd);
        len = 8;
+       rval = XEVNT_OK;
        switch (opcode & 0xffff0000) {
 
        /*
         * Send association request and response with status word and
         * host name. Note, this message is not signed and the filestamp
-        * contains only the status word.
+        * contains only the status word. We check at this point whether
+        * the identity schemes are compatible to save tears later on.
         */
-       case CRYPTO_ASSOC:
        case CRYPTO_ASSOC | CRYPTO_RESP:
+               temp32 = ntohl(fp->fstamp);
+
+printf("xxx %x %x\n", temp32, crypto_flags);
+
+               if (!((crypto_flags & temp32 & CRYPTO_FLAG_PRIV) ||
+                   (crypto_flags & temp32 & CRYPTO_FLAG_IFF) ||
+                   (crypto_flags & temp32 & CRYPTO_FLAG_GQ) ||
+                   !(crypto_flags & (CRYPTO_FLAG_PRIV |
+                   CRYPTO_FLAG_IFF | CRYPTO_FLAG_GQ))))
+                       rval = XEVNT_ID;
+
+       case CRYPTO_ASSOC:
                len += crypto_send(fp, &hostval);
-               fp->fstamp = htonl(crypto_flags);
+               if (crypto_time() == 0)
+                       fp->fstamp = 0;
+               else
+                       fp->fstamp = htonl(crypto_flags);
                break;
 
        /*
@@ -1149,10 +1193,8 @@ crypto_xmit(
                        opcode |= CRYPTO_ERROR;
                        break;
                }
-               if (crypto_alice(peer, &vtemp) == XEVNT_OK)
+               if ((rval = crypto_alice(peer, &vtemp)) == XEVNT_OK)
                        len += crypto_send(fp, &vtemp);
-               else
-                       opcode |= CRYPTO_ERROR;
                value_free(&vtemp);
                break;
 
@@ -1160,10 +1202,8 @@ crypto_xmit(
         * Send response in Schnorr (IFF) identity scheme.
         */
        case CRYPTO_IFF | CRYPTO_RESP:
-               if (crypto_bob(ep, &vtemp) == XEVNT_OK)
+               if ((rval = crypto_bob(ep, &vtemp)) == XEVNT_OK)
                        len += crypto_send(fp, &vtemp);
-               else
-                       opcode |= CRYPTO_ERROR;
                value_free(&vtemp);
                break;
 
@@ -1175,10 +1215,8 @@ crypto_xmit(
                        opcode |= CRYPTO_ERROR;
                        break;
                }
-               if (crypto_alice2(peer, &vtemp) == XEVNT_OK)
+               if ((rval = crypto_alice2(peer, &vtemp)) == XEVNT_OK)
                        len += crypto_send(fp, &vtemp);
-               else
-                       opcode |= CRYPTO_ERROR;
                value_free(&vtemp);
                break;
 
@@ -1186,10 +1224,8 @@ crypto_xmit(
         * Send response in Guillou-Quisquater (GQ) identity scheme.
         */
        case CRYPTO_GQ | CRYPTO_RESP:
-               if (crypto_bob2(ep, &vtemp) == XEVNT_OK)
+               if ((rval = crypto_bob2(ep, &vtemp)) == XEVNT_OK)
                        len += crypto_send(fp, &vtemp);
-               else
-                       opcode |= CRYPTO_ERROR;
                value_free(&vtemp);
                break;
 
@@ -1202,10 +1238,8 @@ crypto_xmit(
         * invalid or contains an unverified signature.
         */
        case CRYPTO_SIGN | CRYPTO_RESP:
-               if (cert_sign(ep, &vtemp) == XEVNT_OK)
+               if ((rval = cert_sign(ep, &vtemp)) == XEVNT_OK)
                        len += crypto_send(fp, &vtemp);
-               else
-                       opcode |= CRYPTO_ERROR;
                value_free(&vtemp);
                break;
 
@@ -1235,10 +1269,9 @@ crypto_xmit(
                        }
                        tcookie = peer->pcookie;
                }
-               if (crypto_encrypt(ep, &vtemp, &tcookie) == XEVNT_OK)
+               if ((rval = crypto_encrypt(ep, &vtemp, &tcookie)) ==
+                   XEVNT_OK)
                        len += crypto_send(fp, &vtemp);
-               else
-                       opcode |= CRYPTO_ERROR;
                value_free(&vtemp);
                break;
 
@@ -1279,6 +1312,20 @@ crypto_xmit(
                break;
        }
 
+       /*
+        * We ignore length/format errors and duplicates. Other errors
+        * are reported to the log.
+        */
+       if (rval > XEVNT_TSP) {
+               opcode |= CRYPTO_ERROR;
+               sprintf(statstr, "error %x opcode %x", rval, opcode);
+               record_crypto_stats(srcadr_sin, statstr);
+#ifdef DEBUG
+               if (debug)
+                       printf("crypto_xmit: %s\n", statstr);
+#endif
+       }
+
        /*
         * Round up the field length to a multiple of 8 bytes and save
         * the request code and length.
@@ -1320,7 +1367,6 @@ crypto_verify(
        tstamp_t fstamp;        /* filestamp */
        u_int   vallen;         /* value length */
        u_int   siglen;         /* signature length */
-       u_char  statstr[NTP_MAXSTRLEN];
        u_int   opcode, len;
        int     rval;
        int     i;
@@ -1433,22 +1479,6 @@ crypto_verify(
                    "crypto_recv: verify %x vallen %u siglen %u ts %u fs %u\n",
                    rval, vallen, siglen, tstamp, fstamp);
 #endif
-
-       /*
-        * We don't log opcode, length and timestamp errors, mostly to
-        * crisp the logs and reduce clogging hazards.
-        */
-       if (rval > XEVNT_TSP) {
-               sprintf(statstr, "error %x code %x ts %u fs %u", rval,
-                   opcode, tstamp, fstamp);
-               record_crypto_stats(&peer->srcadr, statstr);
-               report_event(rval, peer);
-               peer->flash |= TEST12;
-#ifdef DEBUG
-               if (debug)
-                       printf("crypto_verify: %s\n", statstr);
-#endif
-       }
        return (rval);
 }
 
@@ -1569,38 +1599,6 @@ crypto_args(
        return (ep);
 }
 
-/*
- * crypto_check - check for compatible identity scheme before an
- * association is mobilized.
- *
- * This is called for the first packet received that may mobilize a new
- * association in broadcast, symmetric passive and manycast modes. It
- * requires the first packet to be an ASSOC request and the status word
- * to be compatible with the host status word.
- */
-int
-crypto_check(
-       struct recvbuf *rbufp   /* packet buffer pointer */
-       )
-{
-       u_int32 *pkt;           /* receive packet pointer */
-       struct exten *ep;       /* extension pointer */
-       int     authlen;        /* offset of MAC field */
-       u_int   code;           /* extension field opcode */
-       u_int   len;            /* extension field length */
-       tstamp_t fstamp;        /* filestamp */
-
-       authlen = LEN_PKT_NOMAC;
-       pkt = (u_int32 *)&rbufp->recv_pkt + authlen / 4;
-       ep = (struct exten *)pkt;
-       code = ntohl(ep->opcode) & 0xffff0000;
-       len = ntohl(ep->opcode) & 0x0000ffff;
-       if (len < VALUE_LEN)
-               return (0);
-       fstamp = ntohl(ep->fstamp);
-       return (1);
-}
-
 
 /*
  * crypto_send - construct extension field from value components
@@ -2830,7 +2828,15 @@ cert_install(
                        xp->flags |= CERT_SIGN;
 
                        /*
-                        * If X is trusted, then Y is trusted.
+                        * If X is trusted, then Y is trusted. Note that
+                        * we might stumble over a self signed
+                        * certificate that is not trusted, at least
+                        * temporarily. This can happen when a dude
+                        * first comes up, but has not synchronized the
+                        * clock and had its certificate signed by its
+                        * server. In case of broken certificate trail,
+                        * this might result in a loop that could
+                        * persist until timeout.
                         */
                        if (!(xp->flags & CERT_TRUST))
                                continue;
@@ -2839,8 +2845,7 @@ cert_install(
 
                        /*
                         * If subject Y matches the server subject name,
-                        * then Y has completed the certificate trail
-                        * and the server is declared valid.
+                        * then Y has completed the certificate trail.
                         */
                        if (strcmp(yp->subject, peer->subject) != 0)
                                continue;
@@ -3458,8 +3463,9 @@ crypto_setup(void)
        crypto_tai(leap_file);
 #ifdef DEBUG
        if (debug)
-               printf("crypto_setup: flags 0x%x signature scheme %s\n",
-                   crypto_flags, OBJ_nid2ln(cinfo->nid));
+               printf(
+                   "crypto_setup: flags 0x%x host %s signature %s\n",
+                   crypto_flags, sys_hostname, OBJ_nid2ln(cinfo->nid));
 #endif
 }
 
index 016166fb463fffde1c733e1876a17d66b0136a67..fb5e5be78c971e27d859971ef38e281741f241c6 100644 (file)
@@ -43,7 +43,8 @@ u_long        sys_automax;            /* maximum session key lifetime */
 /*
  * Nonspecified system state variables.
  */
-int    sys_bclient;            /* we set our time to broadcasts */
+int    sys_bclient;            /* we set oukiss
+r time to broadcasts */
 double sys_bdelay;             /* broadcast client default delay */
 int    sys_authenticate;       /* requre authentication for config */
 l_fp   sys_authdelay;          /* authentication delay */
@@ -90,7 +91,6 @@ static        void    fast_xmit       P((struct recvbuf *, int, keyid_t, int));
 static void    clock_update    P((void));
 int    default_get_precision   P((void));
 
-
 /*
  * transmit - Transmit Procedure. See Section 3.4.2 of the
  *     specification.
@@ -290,6 +290,7 @@ receive(
        int     is_authentic;           /* cryptosum ok */
        keyid_t skeyid;                 /* cryptographic keys */
        struct sockaddr_in *dstadr_sin; /* active runway */
+       struct sockaddr_in mskadr_sin;  /* mask for restrict */
        l_fp    p_org;                  /* originate timestamp */
        l_fp    p_xmt;                  /* transmit timestamp */
 #ifdef OPENSSL
@@ -601,13 +602,13 @@ receive(
                /*
                 * Note that we don't require an authentication check
                 * here, since we can't set the system clock; but, we do
-                * set the key ID to zero to tell the caller about this.
+                * send a crypto-NAK to tell the caller about this.
                 */
-               if (is_authentic)
+               if (has_mac && sys_authenticate && !is_authentic)
+                       fast_xmit(rbufp, MODE_SERVER, 0, restrict_mask);
+               else
                        fast_xmit(rbufp, MODE_SERVER, skeyid,
                            restrict_mask);
-               else
-                       fast_xmit(rbufp, MODE_SERVER, 0, restrict_mask);
                return;
 
 #ifdef OPENSSL
@@ -642,13 +643,6 @@ receive(
                if (peer2 == 0)
                        return;
 
-               /*
-                * Check for compatible identity scheme before
-                * mobilizing an association.
-                */
-               if (!crypto_check(rbufp))
-                       return;
-
                peer = newpeer(&rbufp->recv_srcadr, rbufp->dstadr,
                    MODE_CLIENT, PKT_VERSION(pkt->li_vn_mode),
                    sys_minpoll, NTP_MAXDPOLL, FLAG_IBURST |
@@ -675,20 +669,12 @@ receive(
                 * incompatible.
                 */
                if ((restrict_mask & (RES_DONTSERVE | RES_LIMITED |
-                   RES_NOPEER)) || (sys_authenticate &&
+                   RES_NOPEER)) || (has_mac && sys_authenticate &&
                    !is_authentic)) {
                        fast_xmit(rbufp, MODE_PASSIVE, 0,
                            restrict_mask);
                        return;
                }
-
-               /*
-                * Check for compatible identity scheme before
-                * mobilizing an association.
-                */
-               if (!crypto_check(rbufp))
-                       return;
-
                peer = newpeer(&rbufp->recv_srcadr, rbufp->dstadr,
                    MODE_PASSIVE, PKT_VERSION(pkt->li_vn_mode),
                    sys_minpoll, NTP_MAXDPOLL, sys_authenticate ?
@@ -711,13 +697,6 @@ receive(
                    !is_authentic) || !sys_bclient)
                        return;
 
-               /*
-                * Check for compatible identity scheme before
-                * mobilizing an association.
-                */
-               if (!crypto_check(rbufp))
-                       return;
-
                peer = newpeer(&rbufp->recv_srcadr, rbufp->dstadr,
                    MODE_CLIENT, PKT_VERSION(pkt->li_vn_mode),
                    sys_minpoll, NTP_MAXDPOLL, FLAG_MCAST |
@@ -729,12 +708,18 @@ receive(
                /*
                 * Danger looms. If this is autokey, go process the
                 * extension fields. If something goes wrong, abandon
-                8 ship.
+                * ship. We know this must be an ephemeral association.
                 */
                if (crypto_flags && (peer->flags & FLAG_SKEY)) {
                        crypto_recv(peer, rbufp);
-                       if (peer->flash)
+                       if (peer->flash) {
                                unpeer(peer);
+                               mskadr_sin.sin_addr.s_addr =
+                                   ~(u_int32)0;
+                               hack_restrict(RESTRICT_FLAGS,
+                                   &rbufp->recv_srcadr, &mskadr_sin,
+                                   RESM_NTPONLY, RES_DONTSERVE);
+                       }
                }
 #endif /* OPENSSL */
                return;
@@ -750,9 +735,17 @@ receive(
        default:
 
                /*
-                * Invalid mode combination. Leave the island
-                * immediately.
+                * Invalid mode combination. This happens when a passive
+                * mode packet arrives and matches another passive
+                * association or no association at all, or when a
+                * server mode packet arrives and matches a broadcast
+                * client association. This is usually the result of
+                * reconfiguring a client on-fly. If authenticated
+                * passive mode packet, send a crypto-NAK; otherwise,
+                * ignore it.
                 */
+               if (has_mac && hismode == MODE_PASSIVE)
+                       fast_xmit(rbufp, MODE_ACTIVE, 0, restrict_mask);
 #ifdef DEBUG
                if (debug)
                        printf("receive: bad protocol %d\n", retcode);
@@ -907,14 +900,15 @@ receive(
                         * originate timestamp must be nonzero. We need
                         * to send something to the active peer that
                         * will cause it to restart. If this happens or
-                        * we light or fail authentication, send a
+                        * we light or dim authentication, send a
                         * crypto_NAK, which is tha analog of the TCP
                         * RESET and get out of Dodge City.
                         */ 
                        if (L_ISZERO(&peer->xmt) || peer->flash &
                            TEST5) {
-                               fast_xmit(rbufp, MODE_PASSIVE, 0,
-                                   restrict_mask);
+                               if (has_mac)
+                                       fast_xmit(rbufp, MODE_PASSIVE,
+                                           0, restrict_mask);
                                unpeer(peer);
                                return;
                        }
@@ -974,10 +968,6 @@ receive(
        if (crypto_flags && (peer->flags & FLAG_SKEY)) {
                peer->flash |= TEST10;
                crypto_recv(peer, rbufp);
-               if (peer->cmmd != 0) {
-                       peer->ppoll = pkt->ppoll;
-                       poll_update(peer, 0);
-               }
                if (peer->flash & TEST12) {
                        /* fall through */
 
@@ -1004,43 +994,82 @@ receive(
                                    tkeyid, pkeyid, 0);
                        }
                }
+               if (!(peer->crypto & CRYPTO_FLAG_PROV)) /* test 11 */
+                       peer->flash |= TEST11;  /* not proventic */
 
                /*
-                * If errors flash at this point and loopback, clamp the
-                * poll to minimum. If the certificate has been stored,
-                * scratch the association. If the server is not
-                * reachable, assume this is the first symmetric mode
-                * packet that warmed up the association and let it by.
-                * It will die later after leaving the originate and
-                * receive timestamp in the dust for the reply.
+                * If the transmit queue is nonempty, clamp the host
+                * poll interval to the packet poll interval.
+                */
+               if (peer->cmmd != 0) {
+                       peer->ppoll = pkt->ppoll;
+                       poll_update(peer, 0);
+               }
+               /*
+                * There are three error bits that can flash at this
+                * point: TEST10, which indicates an autokey sequence
+                * error, TEST11, which indicates non-proventic, and
+                * TEST12, which indicates a catastrophic error. If any
+                * flash at this point, clamp the host poll interval to
+                * the minimum.
                 */
                if (peer->flash) {
                        poll_update(peer, peer->minpoll);
-                       if (peer->crypto & CRYPTO_FLAG_PROV) {
+
+                       /*
+                        * If TEST12 is lit, the crypto machine is
+                        * jammed or an intruder lurks. We demobilize
+                        * the association and him on the the restrict
+                        * list. If the packet mode is not broadcast or
+                        * server, we add KOD restrict as well.
+                        */
+                       if (peer->flash & TEST12) {
+                               int resflag;
+
+                               if (!(peer->flags & FLAG_CONFIG))
+                                       unpeer(peer);
+                               else
+                                       peer_clear(peer);
+                               mskadr_sin.sin_addr.s_addr =
+                                   ~(u_int32)0;
+                               if (hismode == MODE_BROADCAST ||
+                                   hismode == MODE_SERVER)
+                                       resflag = RES_DONTSERVE;
+                               else
+                                       resflag = RES_DONTSERVE |
+                                           RES_DEMOBILIZE;
+                               hack_restrict(RESTRICT_FLAGS,
+                                   &rbufp->recv_srcadr, &mskadr_sin,
+                                   RESM_NTPONLY, resflag);
 #ifdef DEBUG
                                if (debug)
                                        printf(
                                            "packet: bad crypto %03x\n",
                                            peer->flash);
 #endif
-                               if (!(peer->flags & FLAG_CONFIG)) {
-                                       unpeer(peer);
-                                       return;
-                               } else {
-                                       peer_clear(peer);
-                               }
                                return;
                        }
-               }
-               if (!(peer->crypto & CRYPTO_FLAG_PROV)) /* test 11 */
-                       peer->flash |= TEST11;  /* autokey failed */
-               if (peer->flash && peer->reach) {
+
+                       /*
+                        * If TEST10 is lit and we have installed the
+                        * autokey values, the server has probably
+                        * restarted. We demobilize the association and
+                        * wait for better times.
+                        */
+                       if (peer->flash & TEST10 && peer->crypto &
+                           CRYPTO_FLAG_AUTO) {
+                               if (!(peer->flags & FLAG_CONFIG))
+                                       unpeer(peer);
+                               else
+                                       peer_clear(peer);
 #ifdef DEBUG
-                       if (debug)
-                               printf("packet: bad autokey %03x\n",
-                                   peer->flash);
+                               if (debug)
+                                       printf(
+                                           "packet: bad auto %03x\n",
+                                           peer->flash);
 #endif
-                       return;
+                               return;
+                       }
                }
        }
 #endif /* OPENSSL */
@@ -1116,7 +1145,6 @@ process_packet(
         * timestamp and the receive timestamp is copied from the
         * packet receive timestamp.
         */
-       peer->leap = pleap;
        peer->org = p_xmt;
        peer->rec = *recv_ts;
        if (peer->flash) {
@@ -1190,6 +1218,7 @@ process_packet(
         */
        record_raw_stats(&peer->srcadr, &peer->dstadr->sin, &p_org,
            &p_rec, &p_xmt, &peer->rec);
+       peer->leap = pleap;
        peer->pmode = pmode;
        peer->stratum = pstratum;
        peer->ppoll = pkt->ppoll;
@@ -2358,8 +2387,8 @@ peer_xmit(
                        else
                                exten = crypto_args(peer, CRYPTO_ASSOC |
                                    CRYPTO_RESP, NULL);
-                       sendlen += crypto_xmit(&xpkt, sendlen, exten,
-                           0);
+                       sendlen += crypto_xmit(&xpkt, &peer->srcadr,
+                           sendlen, exten, 0);
                        free(exten);
                        break;
 
@@ -2377,14 +2406,14 @@ peer_xmit(
                        if (peer->cmmd != NULL) {
                                peer->cmmd->associd =
                                    htonl(peer->associd);
-                               sendlen += crypto_xmit(&xpkt, sendlen,
-                                   peer->cmmd, 0);
+                               sendlen += crypto_xmit(&xpkt,
+                                   &peer->srcadr, sendlen, peer->cmmd,
+                                   0);
                                free(peer->cmmd);
                                peer->cmmd = NULL;
                        }
                        exten = NULL;
-                       if (peer->leap == LEAP_NOTINSYNC ||
-                           !peer->crypto)
+                       if (!peer->crypto)
                                exten = crypto_args(peer, CRYPTO_ASSOC,
                                    sys_hostname);
                        else if (!(peer->crypto & CRYPTO_FLAG_VALID))
@@ -2439,8 +2468,8 @@ peer_xmit(
                                exten = crypto_args(peer, CRYPTO_TAI,
                                    NULL);
                        if (exten != NULL) {
-                               sendlen += crypto_xmit(&xpkt, sendlen,
-                                   exten, 0);
+                               sendlen += crypto_xmit(&xpkt,
+                                   &peer->srcadr, sendlen, exten, 0);
                                free(exten);
                        }
                        break;
@@ -2467,14 +2496,14 @@ peer_xmit(
                        if (peer->cmmd != NULL) {
                                peer->cmmd->associd =
                                    htonl(peer->associd);
-                               sendlen += crypto_xmit(&xpkt, sendlen,
-                                   peer->cmmd, 0);
+                               sendlen += crypto_xmit(&xpkt,
+                                   &peer->srcadr, sendlen, peer->cmmd,
+                                   0);
                                free(peer->cmmd);
                                peer->cmmd = NULL;
                        }
                        exten = NULL;
-                       if (peer->leap == LEAP_NOTINSYNC ||
-                           !peer->crypto)
+                       if (!peer->crypto)
                                exten = crypto_args(peer, CRYPTO_ASSOC,
                                    sys_hostname);
                        else if (!(peer->crypto & CRYPTO_FLAG_VALID))
@@ -2523,8 +2552,8 @@ peer_xmit(
                                exten = crypto_args(peer, CRYPTO_TAI,
                                    NULL);
                        if (exten != NULL) {
-                               sendlen += crypto_xmit(&xpkt, sendlen,
-                                   exten, 0);
+                               sendlen += crypto_xmit(&xpkt,
+                                   &peer->srcadr, sendlen, exten, 0);
                                free(exten);
                        }
                        break;
@@ -2707,7 +2736,8 @@ fast_xmit(
                            &rbufp->recv_srcadr, xkeyid, 0, 2);
                        temp32 = CRYPTO_RESP;
                        rpkt->exten[0] |= htonl(temp32);
-                       sendlen += crypto_xmit(&xpkt, sendlen,
+                       sendlen += crypto_xmit(&xpkt,
+                           &rbufp->recv_srcadr, sendlen,
                            (struct exten *)rpkt->exten, cookie);
                } else {
                        session_key(&rbufp->dstadr->sin,