code = ntohl(ep->opcode) & 0xffff0000;
len = ntohl(ep->opcode) & 0x0000ffff;
associd = ntohl(pkt[1]);
+ rval = XEVNT_OK;
#ifdef DEBUG
if (debug)
printf(
#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))) {
printf(
"crypto_recv: incorrect version or field length\n");
#endif
- peer->flash |= TEST12;
- code |= CRYPTO_ERROR;;
+ rval = XEVNT_LEN;
+ break;
}
/*
tstamp = ntohl(ep->tstamp);
fstamp = ntohl(ep->fstamp);
vallen = ntohl(ep->vallen);
- } else {
- tstamp = fstamp = 0;
- vallen = 0;
}
- rval = XEVNT_OK;
switch (code) {
/*
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 =
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)
/*
* Discard the message if invalid.
*/
- if (crypto_verify(ep, NULL, peer) != XEVNT_OK)
+ if ((rval = crypto_verify(ep, NULL, peer)) !=
+ XEVNT_OK)
break;
/*
* 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
/*
* Discard the message if invalid.
*/
- if (crypto_verify(ep, NULL, peer) != XEVNT_OK)
+ if ((rval = crypto_verify(ep, NULL, peer)) !=
+ XEVNT_OK)
break;
/*
* 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;
/*
* Discard the message if invalid.
*/
- if (crypto_verify(ep, NULL, peer) != XEVNT_OK)
+ if ((rval = crypto_verify(ep, NULL, peer)) !=
+ XEVNT_OK)
break;
/*
* 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;
if (!(peer->crypto & CRYPTO_FLAG_VRFY))
break;
- if (crypto_verify(ep, &pubkey, peer) !=
+ if ((rval = crypto_verify(ep, &pubkey, peer)) !=
XEVNT_OK)
break;
* 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;
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);
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;
/*
RSA_PKCS1_OAEP_PADDING);
cookie = ntohl(temp32);
} else {
- report_event(XEVNT_CKY, peer);
- peer->flash |= TEST12;
+ rval = XEVNT_CKY;
break;
}
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 =
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;
/*
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;
/*
case CRYPTO_IFF:
case CRYPTO_GQ:
case CRYPTO_SIGN:
- if (len < VALUE_LEN)
+ if (len < VALUE_LEN) {
+ rval = XEVNT_LEN;
break;
+ }
/* fall through */
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);
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;
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 */
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;
/*
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;
/*
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;
* 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;
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;
* 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;
* 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;
}
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;
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.
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;
"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);
}
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
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;
/*
* 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;
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
}
/*
* 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 */
static void clock_update P((void));
int default_get_precision P((void));
-
/*
* transmit - Transmit Procedure. See Section 3.4.2 of the
* specification.
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
/*
* 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
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 |
* 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 ?
!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 |
/*
* 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;
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);
* 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;
}
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 */
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 */
* 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) {
*/
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;
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;
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))
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;
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))
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;
&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,