Skip to content

Commit cbf3bf8

Browse files
committed
Add NTP packet validity checks
1 parent 296b0b6 commit cbf3bf8

File tree

1 file changed

+46
-10
lines changed

1 file changed

+46
-10
lines changed

NTPClient.cpp

Lines changed: 46 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,35 @@ void NTPClient::begin(unsigned int port) {
8181
this->_udpSetup = true;
8282
}
8383

84+
// Perform some validity checks on the packet
85+
// https://datatracker.ietf.org/doc/html/rfc4330#section-4
86+
// Check length before calling
87+
static bool isValid(byte const *ntpPacket)
88+
{
89+
unsigned long highWord = word(ntpPacket[16], ntpPacket[17]);
90+
unsigned long lowWord = word(ntpPacket[18], ntpPacket[19]);
91+
unsigned long refTimeInt = highWord << 16 | lowWord;
92+
highWord = word(ntpPacket[20], ntpPacket[21]);
93+
lowWord = word(ntpPacket[22], ntpPacket[23]);
94+
unsigned long refTimeFrac = highWord << 16 | lowWord;
95+
96+
byte leapIndicator = ((ntpPacket[0] & 0b11000000) >> 6);
97+
byte version = ((ntpPacket[0] & 0b00111000) >> 3);
98+
byte mode = ( ntpPacket[0] & 0b00000111 );
99+
byte stratum = ntpPacket[1];
100+
101+
return
102+
(
103+
(leapIndicator != 3) && // LI != UNSYNC
104+
(version >= 4) &&
105+
((mode == 4) || (mode == 5)) && // Mode == server or broadcast
106+
(stratum >= 1) &&
107+
(stratum <= 15) &&
108+
(refTimeInt != 0) &&
109+
(refTimeFrac != 0)
110+
);
111+
}
112+
84113
bool NTPClient::forceUpdate() {
85114
#ifdef DEBUG_NTPClient
86115
Serial.println("Update from NTP Server");
@@ -102,19 +131,26 @@ bool NTPClient::forceUpdate() {
102131
timeout++;
103132
} while (cb == 0);
104133

105-
this->_lastUpdate = millis() - (10 * (timeout + 1)); // Account for delay in reading the time
106-
107-
this->_udp->read(this->_packetBuffer, NTP_PACKET_SIZE);
134+
if ((cb >= NTP_PACKET_SIZE) &&
135+
(this->_udp->read(this->_packetBuffer, NTP_PACKET_SIZE) == NTP_PACKET_SIZE) &&
136+
isValid(this->_packetBuffer))
137+
{
138+
this->_lastUpdate = millis() - (10 * (timeout + 1)); // Account for delay in reading the time
108139

109-
unsigned long highWord = word(this->_packetBuffer[40], this->_packetBuffer[41]);
110-
unsigned long lowWord = word(this->_packetBuffer[42], this->_packetBuffer[43]);
111-
// combine the four bytes (two words) into a long integer
112-
// this is NTP time (seconds since Jan 1 1900):
113-
unsigned long secsSince1900 = highWord << 16 | lowWord;
140+
unsigned long highWord = word(this->_packetBuffer[40], this->_packetBuffer[41]);
141+
unsigned long lowWord = word(this->_packetBuffer[42], this->_packetBuffer[43]);
142+
// combine the four bytes (two words) into a long integer
143+
// this is NTP time (seconds since Jan 1 1900):
144+
unsigned long secsSince1900 = highWord << 16 | lowWord;
114145

115-
this->_currentEpoc = secsSince1900 - SEVENTYYEARS;
146+
this->_currentEpoc = secsSince1900 - SEVENTYYEARS;
116147

117-
return true; // return true after successful update
148+
return true; // return true after successful update
149+
}
150+
else
151+
{
152+
return false;
153+
}
118154
}
119155

120156
bool NTPClient::update() {

0 commit comments

Comments
 (0)