diff options
Diffstat (limited to 'ntpd/ntp_proto.c')
-rw-r--r-- | ntpd/ntp_proto.c | 423 |
1 files changed, 334 insertions, 89 deletions
diff --git a/ntpd/ntp_proto.c b/ntpd/ntp_proto.c index c5d7cc6db4a86..fb8a837db5c2c 100644 --- a/ntpd/ntp_proto.c +++ b/ntpd/ntp_proto.c @@ -1,7 +1,8 @@ /* * ntp_proto.c - NTP version 4 protocol machinery * - * ATTENTION: Get approval from Dave Mills on all changes to this file! + * ATTENTION: Get approval from Harlan on all changes to this file! + * (Harlan will be discussing these changes with Dave Mills.) * */ #ifdef HAVE_CONFIG_H @@ -37,29 +38,34 @@ #define AUTH(x, y) ((x) ? (y) == AUTH_OK \ : (y) == AUTH_OK || (y) == AUTH_NONE) -#define AUTH_NONE 0 /* authentication not required */ -#define AUTH_OK 1 /* authentication OK */ -#define AUTH_ERROR 2 /* authentication error */ -#define AUTH_CRYPTO 3 /* crypto_NAK */ +typedef enum +auth_state { + AUTH_UNKNOWN = -1, /* Unknown */ + AUTH_NONE, /* authentication not required */ + AUTH_OK, /* authentication OK */ + AUTH_ERROR, /* authentication error */ + AUTH_CRYPTO /* crypto_NAK */ +} auth_code; /* * Set up Kiss Code values */ -enum kiss_codes { +typedef enum +kiss_codes { NOKISS, /* No Kiss Code */ RATEKISS, /* Rate limit Kiss Code */ DENYKISS, /* Deny Kiss */ RSTRKISS, /* Restricted Kiss */ - XKISS, /* Experimental Kiss */ - UNKNOWNKISS /* Unknown Kiss Code */ -}; + XKISS /* Experimental Kiss */ +} kiss_code; -enum nak_error_codes { +typedef enum +nak_error_codes { NONAK, /* No NAK seen */ INVALIDNAK, /* NAK cannot be used */ VALIDNAK /* NAK is valid */ -}; +} nak_code; /* * traffic shaping parameters @@ -182,7 +188,7 @@ int unpeer_digest_early = 1; /* bad digest (TEST5) */ int dynamic_interleave = DYNAMIC_INTERLEAVE; /* Bug 2978 mitigation */ int kiss_code_check(u_char hisleap, u_char hisstratum, u_char hismode, u_int32 refid); -enum nak_error_codes valid_NAK(struct peer *peer, struct recvbuf *rbufp, u_char hismode); +nak_code valid_NAK (struct peer *peer, struct recvbuf *rbufp, u_char hismode); static double root_distance (struct peer *); static void clock_combine (peer_select *, int, int); static void peer_xmit (struct peer *); @@ -260,19 +266,16 @@ kiss_code_check( return (RSTRKISS); } else if(memcmp(&refid,"X", 1) == 0) { return (XKISS); - } else { - return (UNKNOWNKISS); } - } else { - return (NOKISS); } + return (NOKISS); } /* * Check that NAK is valid */ -enum nak_error_codes +nak_code valid_NAK( struct peer *peer, struct recvbuf *rbufp, @@ -583,14 +586,15 @@ receive( u_char hisleap; /* packet leap indicator */ u_char hismode; /* packet mode */ u_char hisstratum; /* packet stratum */ + r4addr r4a; /* address restrictions */ u_short restrict_mask; /* restrict bits */ const char *hm_str; /* hismode string */ const char *am_str; /* association match string */ int kissCode = NOKISS; /* Kiss Code */ int has_mac; /* length of MAC field */ int authlen; /* offset of MAC field */ - int is_authentic = AUTH_NONE; /* cryptosum ok */ - int crypto_nak_test; /* result of crypto-NAK check */ + auth_code is_authentic = AUTH_UNKNOWN; /* Was AUTH_NONE */ + nak_code crypto_nak_test; /* result of crypto-NAK check */ int retcode = AM_NOMATCH; /* match code */ keyid_t skeyid = 0; /* key IDs */ u_int32 opcode = 0; /* extension field opcode */ @@ -612,6 +616,13 @@ receive( #endif /* HAVE_NTP_SIGND */ /* + * Note that there are many places we do not call record_raw_stats(). + * + * We only want to call it *after* we've sent a response, or perhaps + * when we've decided to drop a packet. + */ + + /* * Monitor the packet and get restrictions. Note that the packet * length for control and private mode packets must be checked * by the service routines. Some restrictions have to be handled @@ -626,25 +637,33 @@ receive( sys_badlength++; return; /* bogus port */ } - restrict_mask = restrictions(&rbufp->recv_srcadr); + restrictions(&rbufp->recv_srcadr, &r4a); + restrict_mask = r4a.rflags; + pkt = &rbufp->recv_pkt; - DPRINTF(2, ("receive: at %ld %s<-%s flags %x restrict %03x org %#010x.%08x xmt %#010x.%08x\n", - current_time, stoa(&rbufp->dstadr->sin), - stoa(&rbufp->recv_srcadr), rbufp->dstadr->flags, - restrict_mask, ntohl(pkt->org.l_ui), ntohl(pkt->org.l_uf), - ntohl(pkt->xmt.l_ui), ntohl(pkt->xmt.l_uf))); hisversion = PKT_VERSION(pkt->li_vn_mode); hisleap = PKT_LEAP(pkt->li_vn_mode); hismode = (int)PKT_MODE(pkt->li_vn_mode); hisstratum = PKT_TO_STRATUM(pkt->stratum); + DPRINTF(2, ("receive: at %ld %s<-%s ippeerlimit %d mode %d iflags %s restrict %s org %#010x.%08x xmt %#010x.%08x\n", + current_time, stoa(&rbufp->dstadr->sin), + stoa(&rbufp->recv_srcadr), r4a.ippeerlimit, hismode, + build_iflags(rbufp->dstadr->flags), + build_rflags(restrict_mask), + ntohl(pkt->org.l_ui), ntohl(pkt->org.l_uf), + ntohl(pkt->xmt.l_ui), ntohl(pkt->xmt.l_uf))); + + /* See basic mode and broadcast checks, below */ INSIST(0 != hisstratum); if (restrict_mask & RES_IGNORE) { + DPRINTF(2, ("receive: drop: RES_IGNORE\n")); sys_restricted++; return; /* ignore everything */ } if (hismode == MODE_PRIVATE) { if (!ntp_mode7 || (restrict_mask & RES_NOQUERY)) { + DPRINTF(2, ("receive: drop: RES_NOQUERY\n")); sys_restricted++; return; /* no query private */ } @@ -654,6 +673,7 @@ receive( } if (hismode == MODE_CONTROL) { if (restrict_mask & RES_NOQUERY) { + DPRINTF(2, ("receive: drop: RES_NOQUERY\n")); sys_restricted++; return; /* no query control */ } @@ -661,6 +681,7 @@ receive( return; } if (restrict_mask & RES_DONTSERVE) { + DPRINTF(2, ("receive: drop: RES_DONTSERVE\n")); sys_restricted++; return; /* no time serve */ } @@ -671,12 +692,25 @@ receive( */ if (restrict_mask & RES_FLAKE) { if ((double)ntp_random() / 0x7fffffff < .1) { + DPRINTF(2, ("receive: drop: RES_FLAKE\n")); sys_restricted++; return; /* no flakeway */ } } /* + ** Format Layer Checks + ** + ** Validate the packet format. The packet size, packet header, + ** and any extension field lengths are checked. We identify + ** the beginning of the MAC, to identify the upper limit of + ** of the hash computation. + ** + ** In case of a format layer check violation, the packet is + ** discarded with no further processing. + */ + + /* * Version check must be after the query packets, since they * intentionally use an early version. */ @@ -686,6 +720,7 @@ receive( && hisversion >= NTP_OLDVERSION) { sys_oldversion++; /* previous version */ } else { + DPRINTF(2, ("receive: drop: RES_VERSION\n")); sys_badlength++; return; /* old version */ } @@ -700,6 +735,7 @@ receive( if (hisversion == NTP_OLDVERSION) { hismode = MODE_CLIENT; } else { + DPRINTF(2, ("receive: drop: MODE_UNSPEC\n")); sys_badlength++; return; /* invalid mode */ } @@ -716,6 +752,16 @@ receive( * is a runt and discarded forthwith. If greater than 6, an * extension field is present, so we subtract the length of the * field and go around again. + * + * Note the above description is lame. We should/could also check + * the two bytes that make up the EF type and subtype, and then + * check the two bytes that tell us the EF length. A legacy MAC + * has a 4 byte keyID, and for conforming symmetric keys its value + * must be <= 64k, meaning the top two bytes will always be zero. + * Since the EF Type of 0 is reserved/unused, there's no way a + * conforming legacy MAC could ever be misinterpreted as an EF. + * + * There is more, but this isn't the place to document it. */ authlen = LEN_PKT_NOMAC; @@ -728,9 +774,14 @@ receive( #endif /*AUTOKEY */ if (has_mac % 4 != 0 || has_mac < (int)MIN_MAC_LEN) { + DPRINTF(2, ("receive: drop: bad post-packet length\n")); sys_badlength++; return; /* bad length */ } + /* + * This next test is clearly wrong - it needlessly + * prohibits short EFs (which don't yet exist) + */ if (has_mac <= (int)MAX_MAC_LEN) { skeyid = ntohl(((u_int32 *)pkt)[authlen / 4]); break; @@ -741,6 +792,7 @@ receive( if ( len % 4 != 0 || len < 4 || (int)len + authlen > rbufp->recv_length) { + DPRINTF(2, ("receive: drop: bad EF length\n")); sys_badlength++; return; /* bad length */ } @@ -757,6 +809,7 @@ receive( if ( hostlen >= sizeof(hostname) || hostlen > len - offsetof(struct exten, pkt)) { + DPRINTF(2, ("receive: drop: bad autokey hostname length\n")); sys_badlength++; return; /* bad length */ } @@ -764,6 +817,7 @@ receive( hostname[hostlen] = '\0'; groupname = strchr(hostname, '@'); if (groupname == NULL) { + DPRINTF(2, ("receive: drop: empty autokey groupname\n")); sys_declined++; return; } @@ -779,14 +833,27 @@ receive( * If has_mac is < 0 we had a malformed packet. */ if (has_mac < 0) { + DPRINTF(2, ("receive: drop: post-packet under-read\n")); sys_badlength++; return; /* bad length */ } /* - * If authentication required, a MAC must be present. + ** Packet Data Verification Layer + ** + ** This layer verifies the packet data content. If + ** authentication is required, a MAC must be present. + ** If a MAC is present, it must validate. + ** Crypto-NAK? Look - a shiny thing! + ** + ** If authentication fails, we're done. + */ + + /* + * If authentication is explicitly required, a MAC must be present. */ if (restrict_mask & RES_DONTTRUST && has_mac == 0) { + DPRINTF(2, ("receive: drop: RES_DONTTRUST\n")); sys_restricted++; return; /* access denied */ } @@ -803,9 +870,12 @@ receive( if ( !(restrict_mask & RES_KOD) || MODE_BROADCAST == hismode || MODE_SERVER == hismode) { - if (MODE_SERVER == hismode) + if (MODE_SERVER == hismode) { DPRINTF(1, ("Possibly self-induced rate limiting of MODE_SERVER from %s\n", stoa(&rbufp->recv_srcadr))); + } else { + DPRINTF(2, ("receive: drop: RES_KOD\n")); + } return; /* rate exceeded */ } if (hismode == MODE_CLIENT) @@ -837,6 +907,7 @@ receive( * multicaster, the broadcast address is null, so we use the * unicast address anyway. Don't ask. */ + peer = findpeer(rbufp, hismode, &retcode); dstadr_sin = &rbufp->dstadr->sin; NTOHL_FP(&pkt->org, &p_org); @@ -921,6 +992,14 @@ receive( #endif /* HAVE_NTP_SIGND */ } else { + /* + * has_mac is not 0 + * Not a VALID_NAK + * Not an MS-SNTP SIGND packet + * + * So there is a MAC here. + */ + restrict_mask &= ~RES_MSSNTP; #ifdef AUTOKEY /* @@ -956,6 +1035,7 @@ receive( * % can't happen */ if (has_mac < (int)MAX_MD5_LEN) { + DPRINTF(2, ("receive: drop: MD5 digest too short\n")); sys_badauth++; return; } @@ -972,6 +1052,7 @@ receive( if ( crypto_flags && rbufp->dstadr == ANY_INTERFACE_CHOOSE(&rbufp->recv_srcadr)) { + DPRINTF(2, ("receive: drop: BCAST from wildcard\n")); sys_restricted++; return; /* no wildcard */ } @@ -1033,6 +1114,80 @@ receive( ntohl(pkt->xmt.l_ui), ntohl(pkt->xmt.l_uf))); } + + /* + * Bug 3454: + * + * Now come at this from a different perspective: + * - If we expect a MAC and it's not there, we drop it. + * - If we expect one keyID and get another, we drop it. + * - If we have a MAC ahd it hasn't been validated yet, try. + * - if the provided MAC doesn't validate, we drop it. + * + * There might be more to this. + */ + if (0 != peer && 0 != peer->keyid) { + /* Should we msyslog() any of these? */ + + /* + * This should catch: + * - no keyID where one is expected, + * - different keyID than what we expect. + */ + if (peer->keyid != skeyid) { + DPRINTF(2, ("receive: drop: Wanted keyID %d, got %d from %s\n", + peer->keyid, skeyid, + stoa(&rbufp->recv_srcadr))); + sys_restricted++; + return; /* drop: access denied */ + } + + /* + * if has_mac != 0 ... + * - If it has not yet been validated, do so. + * (under what circumstances might that happen?) + * - if missing or bad MAC, log and drop. + */ + if (0 != has_mac) { + if (is_authentic == AUTH_UNKNOWN) { + /* How can this happen? */ + DPRINTF(2, ("receive: 3454 check: AUTH_UNKNOWN from %s\n", + stoa(&rbufp->recv_srcadr))); + if (!authdecrypt(skeyid, (u_int32 *)pkt, authlen, + has_mac)) { + /* MAC invalid or not found */ + is_authentic = AUTH_ERROR; + } else { + is_authentic = AUTH_OK; + } + } + if (is_authentic != AUTH_OK) { + DPRINTF(2, ("receive: drop: missing or bad MAC from %s\n", + stoa(&rbufp->recv_srcadr))); + sys_restricted++; + return; /* drop: access denied */ + } + } + } + /**/ + + /* + ** On-Wire Protocol Layer + ** + ** Verify protocol operations consistent with the on-wire protocol. + ** The protocol discards bogus and duplicate packets as well as + ** minimizes disruptions doe to protocol restarts and dropped + ** packets. The operations are controlled by two timestamps: + ** the transmit timestamp saved in the client state variables, + ** and the origin timestamp in the server packet header. The + ** comparison of these two timestamps is called the loopback test. + ** The transmit timestamp functions as a nonce to verify that the + ** response corresponds to the original request. The transmit + ** timestamp also serves to discard replays of the most recent + ** packet. Upon failure of either test, the packet is discarded + ** with no further action. + */ + /* * The association matching rules are implemented by a set of * routines and an association table. A packet matching an @@ -1050,6 +1205,8 @@ receive( * an ordinary client, simply toss a server mode packet back * over the fence. If a manycast client, we have to work a * little harder. + * + * There are cases here where we do not call record_raw_stats(). */ case AM_FXMIT: @@ -1058,6 +1215,21 @@ receive( * send a crypto-NAK. */ if (!(rbufp->dstadr->flags & INT_MCASTOPEN)) { + /* HMS: would be nice to log FAST_XMIT|BADAUTH|RESTRICTED */ + record_raw_stats(&rbufp->recv_srcadr, + &rbufp->dstadr->sin, + &p_org, &p_rec, &p_xmt, &rbufp->recv_time, + PKT_LEAP(pkt->li_vn_mode), + PKT_VERSION(pkt->li_vn_mode), + PKT_MODE(pkt->li_vn_mode), + PKT_TO_STRATUM(pkt->stratum), + pkt->ppoll, + pkt->precision, + FPTOD(NTOHS_FP(pkt->rootdelay)), + FPTOD(NTOHS_FP(pkt->rootdisp)), + pkt->refid, + rbufp->recv_length - MIN_V4_PKT_LEN, (u_char *)&pkt->exten); + if (AUTH(restrict_mask & RES_DONTTRUST, is_authentic)) { fast_xmit(rbufp, MODE_SERVER, skeyid, @@ -1067,8 +1239,10 @@ receive( restrict_mask); sys_badauth++; } else { + DPRINTF(2, ("receive: AM_FXMIT drop: !mcast restricted\n")); sys_restricted++; } + return; /* hooray */ } @@ -1077,6 +1251,7 @@ receive( * configured as a manycast server. */ if (!sys_manycastserver) { + DPRINTF(2, ("receive: AM_FXMIT drop: Not manycastserver\n")); sys_restricted++; return; /* not enabled */ } @@ -1086,6 +1261,7 @@ receive( * Do not respond if not the same group. */ if (group_test(groupname, NULL)) { + DPRINTF(2, ("receive: AM_FXMIT drop: empty groupname\n")); sys_declined++; return; } @@ -1100,6 +1276,7 @@ receive( || sys_stratum >= hisstratum || (!sys_cohort && sys_stratum == hisstratum + 1) || rbufp->dstadr->addr_refid == pkt->refid) { + DPRINTF(2, ("receive: AM_FXMIT drop: LEAP_NOTINSYNC || stratum || loop\n")); sys_declined++; return; /* no help */ } @@ -1108,9 +1285,24 @@ receive( * Respond only if authentication succeeds. Don't do a * crypto-NAK, as that would not be useful. */ - if (AUTH(restrict_mask & RES_DONTTRUST, is_authentic)) + if (AUTH(restrict_mask & RES_DONTTRUST, is_authentic)) { + record_raw_stats(&rbufp->recv_srcadr, + &rbufp->dstadr->sin, + &p_org, &p_rec, &p_xmt, &rbufp->recv_time, + PKT_LEAP(pkt->li_vn_mode), + PKT_VERSION(pkt->li_vn_mode), + PKT_MODE(pkt->li_vn_mode), + PKT_TO_STRATUM(pkt->stratum), + pkt->ppoll, + pkt->precision, + FPTOD(NTOHS_FP(pkt->rootdelay)), + FPTOD(NTOHS_FP(pkt->rootdisp)), + pkt->refid, + rbufp->recv_length - MIN_V4_PKT_LEN, (u_char *)&pkt->exten); + fast_xmit(rbufp, MODE_SERVER, skeyid, restrict_mask); + } return; /* hooray */ /* @@ -1131,6 +1323,8 @@ receive( * There is an implosion hazard at the manycast client, since * the manycast servers send the server packet immediately. If * the guy is already here, don't fire up a duplicate. + * + * There are cases here where we do not call record_raw_stats(). */ case AM_MANYCAST: @@ -1139,18 +1333,23 @@ receive( * Do not respond if not the same group. */ if (group_test(groupname, NULL)) { + DPRINTF(2, ("receive: AM_MANYCAST drop: empty groupname\n")); sys_declined++; return; } #endif /* AUTOKEY */ if ((peer2 = findmanycastpeer(rbufp)) == NULL) { + DPRINTF(2, ("receive: AM_MANYCAST drop: No manycast peer\n")); sys_restricted++; return; /* not enabled */ } if (!AUTH( (!(peer2->cast_flags & MDF_POOL) && sys_authenticate) || (restrict_mask & (RES_NOPEER | - RES_DONTTRUST)), is_authentic)) { + RES_DONTTRUST)), is_authentic) + /* MC: RES_NOEPEER? */ + ) { + DPRINTF(2, ("receive: AM_MANYCAST drop: bad auth || (NOPEER|DONTTRUST)\n")); sys_restricted++; return; /* access denied */ } @@ -1162,15 +1361,17 @@ receive( if ( hisleap == LEAP_NOTINSYNC || hisstratum < sys_floor || hisstratum >= sys_ceiling) { + DPRINTF(2, ("receive: AM_MANYCAST drop: unsync/stratum\n")); sys_declined++; return; /* no help */ } peer = newpeer(&rbufp->recv_srcadr, NULL, rbufp->dstadr, - MODE_CLIENT, hisversion, peer2->minpoll, - peer2->maxpoll, FLAG_PREEMPT | - (FLAG_IBURST & peer2->flags), MDF_UCAST | - MDF_UCLNT, 0, skeyid, sys_ident); + r4a.ippeerlimit, MODE_CLIENT, hisversion, + peer2->minpoll, peer2->maxpoll, + FLAG_PREEMPT | (FLAG_IBURST & peer2->flags), + MDF_UCAST | MDF_UCLNT, 0, skeyid, sys_ident); if (NULL == peer) { + DPRINTF(2, ("receive: AM_MANYCAST drop: duplicate\n")); sys_declined++; return; /* ignore duplicate */ } @@ -1197,6 +1398,8 @@ receive( * the packet is authentic and we are enabled as broadcast * client, mobilize a broadcast client association. We don't * kiss any frogs here. + * + * There are cases here where we do not call record_raw_stats(). */ case AM_NEWBCL: @@ -1205,16 +1408,21 @@ receive( * Do not respond if not the same group. */ if (group_test(groupname, sys_ident)) { + DPRINTF(2, ("receive: AM_NEWBCL drop: groupname mismatch\n")); sys_declined++; return; } #endif /* AUTOKEY */ if (sys_bclient == 0) { + DPRINTF(2, ("receive: AM_NEWBCL drop: not a bclient\n")); sys_restricted++; return; /* not enabled */ } if (!AUTH(sys_authenticate | (restrict_mask & - (RES_NOPEER | RES_DONTTRUST)), is_authentic)) { + (RES_NOPEER | RES_DONTTRUST)), is_authentic) + /* NEWBCL: RES_NOEPEER? */ + ) { + DPRINTF(2, ("receive: AM_NEWBCL drop: AUTH failed\n")); sys_restricted++; return; /* access denied */ } @@ -1226,6 +1434,7 @@ receive( if ( hisleap == LEAP_NOTINSYNC || hisstratum < sys_floor || hisstratum >= sys_ceiling) { + DPRINTF(2, ("receive: AM_NEWBCL drop: Unsync or bad stratum\n")); sys_declined++; return; /* no help */ } @@ -1237,6 +1446,7 @@ receive( */ if ( crypto_flags && skeyid > NTP_MAXKEY && (opcode & 0xffff0000) != (CRYPTO_ASSOC | CRYPTO_RESP)) { + DPRINTF(2, ("receive: AM_NEWBCL drop: Autokey but not CRYPTO_ASSOC\n")); sys_declined++; return; /* protocol error */ } @@ -1267,6 +1477,7 @@ receive( */ if (crypto_flags && skeyid > NTP_MAXKEY) { sys_restricted++; + DPRINTF(2, ("receive: AM_NEWBCL drop: Autokey but not 2-way\n")); return; /* no autokey */ } #endif /* AUTOKEY */ @@ -1275,11 +1486,12 @@ receive( * Do not execute the volley. Start out in * broadcast client mode. */ - peer = newpeer(&rbufp->recv_srcadr, NULL, - match_ep, MODE_BCLIENT, hisversion, - pkt->ppoll, pkt->ppoll, FLAG_PREEMPT, - MDF_BCLNT, 0, skeyid, sys_ident); + peer = newpeer(&rbufp->recv_srcadr, NULL, match_ep, + r4a.ippeerlimit, MODE_BCLIENT, hisversion, + pkt->ppoll, pkt->ppoll, + FLAG_PREEMPT, MDF_BCLNT, 0, skeyid, sys_ident); if (NULL == peer) { + DPRINTF(2, ("receive: AM_NEWBCL drop: duplicate\n")); sys_restricted++; return; /* ignore duplicate */ @@ -1299,10 +1511,12 @@ receive( * is fixed at this value. */ peer = newpeer(&rbufp->recv_srcadr, NULL, match_ep, - MODE_CLIENT, hisversion, pkt->ppoll, pkt->ppoll, + r4a.ippeerlimit, MODE_CLIENT, hisversion, + pkt->ppoll, pkt->ppoll, FLAG_BC_VOL | FLAG_IBURST | FLAG_PREEMPT, MDF_BCLNT, 0, skeyid, sys_ident); if (NULL == peer) { + DPRINTF(2, ("receive: AM_NEWBCL drop: empty newpeer() failed\n")); sys_restricted++; return; /* ignore duplicate */ } @@ -1316,8 +1530,11 @@ receive( /* * This is the first packet received from a symmetric active - * peer. If the packet is authentic and the first he sent, - * mobilize a passive association. If not, kiss the frog. + * peer. If the packet is authentic, the first he sent, and + * RES_NOEPEER is not enabled, mobilize a passive association + * If not, kiss the frog. + * + * There are cases here where we do not call record_raw_stats(). */ case AM_NEWPASS: @@ -1326,38 +1543,42 @@ receive( * Do not respond if not the same group. */ if (group_test(groupname, sys_ident)) { + DPRINTF(2, ("receive: AM_NEWPASS drop: Autokey group mismatch\n")); sys_declined++; return; } #endif /* AUTOKEY */ if (!AUTH(sys_authenticate | (restrict_mask & - (RES_NOPEER | RES_DONTTRUST)), is_authentic)) { - - /* - * If authenticated but cannot mobilize an - * association, send a symmetric passive - * response without mobilizing an association. - * This is for drat broken Windows clients. See - * Microsoft KB 875424 for preferred workaround. - */ - if (AUTH(restrict_mask & RES_DONTTRUST, - is_authentic)) { - fast_xmit(rbufp, MODE_PASSIVE, skeyid, - restrict_mask); - return; /* hooray */ - } - if (is_authentic == AUTH_ERROR) { - fast_xmit(rbufp, MODE_ACTIVE, 0, - restrict_mask); - sys_restricted++; - return; + (RES_NOPEER | RES_DONTTRUST)), is_authentic) + ) { + if (0 == (restrict_mask & RES_NOEPEER)) { + /* + * If authenticated but cannot mobilize an + * association, send a symmetric passive + * response without mobilizing an association. + * This is for drat broken Windows clients. See + * Microsoft KB 875424 for preferred workaround. + */ + if (AUTH(restrict_mask & RES_DONTTRUST, + is_authentic)) { + fast_xmit(rbufp, MODE_PASSIVE, skeyid, + restrict_mask); + return; /* hooray */ + } + if (is_authentic == AUTH_ERROR) { + fast_xmit(rbufp, MODE_ACTIVE, 0, + restrict_mask); + sys_restricted++; + return; + } } /* [Bug 2941] * If we got here, the packet isn't part of an - * existing association, it isn't correctly - * authenticated, and it didn't meet either of - * the previous two special cases so we should - * just drop it on the floor. For example, + * existing association, either isn't correctly + * authenticated or it is but we are refusing + * ephemeral peer requests, and it didn't meet + * either of the previous two special cases so we + * should just drop it on the floor. For example, * crypto-NAKs (is_authentic == AUTH_CRYPTO) * will make it this far. This is just * debug-printed and not logged to avoid log @@ -1384,18 +1605,21 @@ receive( */ if ( hisleap != LEAP_NOTINSYNC && (hisstratum < sys_floor || hisstratum >= sys_ceiling)) { + DPRINTF(2, ("receive: AM_NEWPASS drop: Autokey group mismatch\n")); sys_declined++; return; /* no help */ } /* * The message is correctly authenticated and allowed. - * Mobilize a symmetric passive association. + * Mobilize a symmetric passive association, if we won't + * exceed the ippeerlimit. */ - if ((peer = newpeer(&rbufp->recv_srcadr, NULL, - rbufp->dstadr, MODE_PASSIVE, hisversion, pkt->ppoll, - NTP_MAXDPOLL, 0, MDF_UCAST, 0, skeyid, - sys_ident)) == NULL) { + if ((peer = newpeer(&rbufp->recv_srcadr, NULL, rbufp->dstadr, + r4a.ippeerlimit, MODE_PASSIVE, hisversion, + pkt->ppoll, NTP_MAXDPOLL, 0, MDF_UCAST, 0, + skeyid, sys_ident)) == NULL) { + DPRINTF(2, ("receive: AM_NEWPASS drop: newpeer() failed\n")); sys_declined++; return; /* ignore duplicate */ } @@ -1404,6 +1628,8 @@ receive( /* * Process regular packet. Nothing special. + * + * There are cases here where we do not call record_raw_stats(). */ case AM_PROCPKT: @@ -1412,6 +1638,7 @@ receive( * Do not respond if not the same group. */ if (group_test(groupname, peer->ident)) { + DPRINTF(2, ("receive: AM_PROCPKT drop: Autokey group mismatch\n")); sys_declined++; return; } @@ -1437,7 +1664,7 @@ receive( /* This is noteworthy, not error-worthy */ if (pkt->ppoll != peer->ppoll) { - msyslog(LOG_INFO, "receive: broadcast poll from %s changed from %ud to %ud", + msyslog(LOG_INFO, "receive: broadcast poll from %s changed from %u to %u", stoa(&rbufp->recv_srcadr), peer->ppoll, pkt->ppoll); } @@ -1445,7 +1672,7 @@ receive( /* This is error-worthy */ if (pkt->ppoll < peer->minpoll || pkt->ppoll > peer->maxpoll ) { - msyslog(LOG_INFO, "receive: broadcast poll of %ud from %s is out-of-range (%d to %d)!", + msyslog(LOG_INFO, "receive: broadcast poll of %u from %s is out-of-range (%d to %d)!", pkt->ppoll, stoa(&rbufp->recv_srcadr), peer->minpoll, peer->maxpoll); ++bail; @@ -1520,6 +1747,7 @@ receive( } if (bail) { + DPRINTF(2, ("receive: AM_PROCPKT drop: bail\n")); peer->timelastrec = current_time; sys_declined++; return; @@ -1535,6 +1763,7 @@ receive( * attempt to deny service, just ignore it. */ case AM_ERR: + DPRINTF(2, ("receive: AM_ERR drop.\n")); sys_declined++; return; @@ -1542,6 +1771,7 @@ receive( * For everything else there is the bit bucket. */ default: + DPRINTF(2, ("receive: default drop.\n")); sys_declined++; return; } @@ -1555,6 +1785,7 @@ receive( if ( is_authentic != AUTH_CRYPTO && ( ((peer->flags & FLAG_SKEY) && skeyid <= NTP_MAXKEY) || (!(peer->flags & FLAG_SKEY) && skeyid > NTP_MAXKEY))) { + DPRINTF(2, ("receive: drop: Autokey but wrong/bad auth\n")); sys_badauth++; return; } @@ -1575,9 +1806,12 @@ receive( * A KoD packet we pay attention to cannot have a 0 transmit * timestamp. */ + + kissCode = kiss_code_check(hisleap, hisstratum, hismode, pkt->refid); + if (L_ISZERO(&p_xmt)) { peer->flash |= TEST3; /* unsynch */ - if (STRATUM_UNSPEC == hisstratum) { /* KoD packet */ + if (kissCode != NOKISS) { /* KoD packet */ peer->bogusorg++; /* for TEST2 or TEST3 */ msyslog(LOG_INFO, "receive: Unexpected zero transmit timestamp in KoD from %s", @@ -1591,6 +1825,7 @@ receive( * the most recent packet, authenticated or not. */ } else if (L_ISEQU(&peer->xmt, &p_xmt)) { + DPRINTF(2, ("receive: drop: Duplicate xmit\n")); peer->flash |= TEST1; /* duplicate */ peer->oldpkt++; return; @@ -1601,13 +1836,13 @@ receive( * see if this is an interleave broadcast packet until after * we've validated the MAC that SHOULD be provided. * - * hisstratum should never be 0. + * hisstratum cannot be 0 - see assertion above. * If hisstratum is 15, then we'll advertise as UNSPEC but * at least we'll be able to sync with the broadcast server. */ } else if (hismode == MODE_BROADCAST) { - if ( 0 == hisstratum - || STRATUM_UNSPEC <= hisstratum) { + /* 0 is unexpected too, and impossible */ + if (STRATUM_UNSPEC <= hisstratum) { /* Is this a ++sys_declined or ??? */ msyslog(LOG_INFO, "receive: Unexpected stratum (%d) in broadcast from %s", @@ -1628,7 +1863,7 @@ receive( * (nonzero) org, rec, and xmt timestamps set to the xmt timestamp * that we have previously sent out. Watch interleave mode. */ - } else if (STRATUM_UNSPEC == hisstratum) { + } else if (kissCode != NOKISS) { DEBUG_INSIST(!L_ISZERO(&p_xmt)); if ( L_ISZERO(&p_org) /* We checked p_xmt above */ || L_ISZERO(&p_rec)) { @@ -1675,7 +1910,8 @@ receive( * should 'aorg' be all-zero because this really was the original * transmit timestamp, we'll ignore this reply. There is a window * of one nanosecond once every 136 years' time where this is - * possible. We currently ignore this situation. + * possible. We currently ignore this situation, as a completely + * zero timestamp is (quietly?) disallowed. * * Otherwise, check for bogus packet in basic mode. * If it is bogus, switch to interleaved mode and resynchronize, @@ -1684,11 +1920,11 @@ receive( * * This could also mean somebody is forging packets claiming to * be from us, attempting to cause our server to KoD us. + * + * We have earlier asserted that hisstratum cannot be 0. + * If hisstratum is STRATUM_UNSPEC, it means he's not sync'd. */ } else if (peer->flip == 0) { - INSIST(0 != hisstratum); - INSIST(STRATUM_UNSPEC != hisstratum); - if (0) { } else if (L_ISZERO(&p_org)) { const char *action; @@ -1767,10 +2003,13 @@ receive( */ } else if ( !L_ISZERO(&peer->dst) && !L_ISEQU(&p_org, &peer->dst)) { + DPRINTF(2, ("receive: drop: Bogus packet in interleaved symmetric mode\n")); peer->bogusorg++; peer->flags |= FLAG_XBOGUS; peer->flash |= TEST2; /* bogus */ +#ifdef BUG3453 return; /* Bogus packet, we are done */ +#endif } /**/ @@ -1788,6 +2027,7 @@ receive( if (unpeer_crypto_nak_early) { unpeer(peer); } + DPRINTF(2, ("receive: drop: PREEMPT crypto_NAK\n")); return; } #ifdef AUTOKEY @@ -1795,6 +2035,7 @@ receive( peer_clear(peer, "AUTH"); } #endif /* AUTOKEY */ + DPRINTF(2, ("receive: drop: crypto_NAK\n")); return; /* @@ -1832,6 +2073,7 @@ receive( peer_clear(peer, "AUTH"); } #endif /* AUTOKEY */ + DPRINTF(2, ("receive: drop: Bad or missing AUTH\n")); return; } @@ -1901,11 +2143,9 @@ receive( /* * Check for any kiss codes. Note this is only used when a server - * responds to a packet request + * responds to a packet request. */ - kissCode = kiss_code_check(hisleap, hisstratum, hismode, pkt->refid); - /* * Check to see if this is a RATE Kiss Code * Currently this kiss code will accept whatever poll @@ -2204,11 +2444,12 @@ process_packet( /* * Capture the header values in the client/peer association.. */ - record_raw_stats(&peer->srcadr, peer->dstadr ? - &peer->dstadr->sin : NULL, + record_raw_stats(&peer->srcadr, + peer->dstadr ? &peer->dstadr->sin : NULL, &p_org, &p_rec, &p_xmt, &peer->dst, pleap, pversion, pmode, pstratum, pkt->ppoll, pkt->precision, - p_del, p_disp, pkt->refid); + p_del, p_disp, pkt->refid, + len - MIN_V4_PKT_LEN, (u_char *)&pkt->exten); peer->leap = pleap; peer->stratum = min(pstratum, STRATUM_UNSPEC); peer->pmode = pmode; @@ -4301,6 +4542,7 @@ pool_xmit( int rc; struct interface * lcladr; sockaddr_u * rmtadr; + r4addr r4a; int restrict_mask; struct peer * p; l_fp xmt_tx; @@ -4337,11 +4579,12 @@ pool_xmit( /* copy_addrinfo_list ai_addr points to a sockaddr_u */ rmtadr = (sockaddr_u *)(void *)pool->ai->ai_addr; pool->ai = pool->ai->ai_next; - p = findexistingpeer(rmtadr, NULL, NULL, MODE_CLIENT, 0); + p = findexistingpeer(rmtadr, NULL, NULL, MODE_CLIENT, 0, NULL); } while (p != NULL && pool->ai != NULL); if (p != NULL) return; /* out of addresses, re-query DNS next poll */ - restrict_mask = restrictions(rmtadr); + restrictions(rmtadr, &r4a); + restrict_mask = r4a.rflags; if (RES_FLAGS & restrict_mask) restrict_source(rmtadr, 0, current_time + POOL_SOLICIT_WINDOW + 1); @@ -4932,4 +5175,6 @@ proto_clr_stats(void) sys_badauth = 0; sys_limitrejected = 0; sys_kodsent = 0; + sys_lamport = 0; + sys_tsrounding = 0; } |