Skip to content
This repository has been archived by the owner on Jan 29, 2023. It is now read-only.

Add packet validity checks #4

Merged
merged 1 commit into from
Jun 4, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 50 additions & 23 deletions src/NTPClient_Generic_Impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,40 +58,67 @@ void NTPClient::begin(int port)
this->_udpSetup = true;
}

bool NTPClient::checkResponse()
// Perform some validity checks on the packet
// https://datatracker.ietf.org/doc/html/rfc4330#section-4
// Check length before calling
static bool isValid(byte const *ntpPacket)
{
unsigned long highWord = word(ntpPacket[16], ntpPacket[17]);
unsigned long lowWord = word(ntpPacket[18], ntpPacket[19]);
unsigned long refTimeInt = highWord << 16 | lowWord;
highWord = word(ntpPacket[20], ntpPacket[21]);
lowWord = word(ntpPacket[22], ntpPacket[23]);
unsigned long refTimeFrac = highWord << 16 | lowWord;

byte leapIndicator = ((ntpPacket[0] & 0b11000000) >> 6);
byte version = ((ntpPacket[0] & 0b00111000) >> 3);
byte stratum = ntpPacket[1];

return
(
(leapIndicator != 3) && // LI != UNSYNC
(version >= 1) &&
(stratum >= 1) &&
(stratum <= 15) &&
((refTimeInt != 0) || (refTimeFrac != 0))
);
}

bool NTPClient::checkResponse()
{
if (this->_udp->parsePacket())
{
this->_lastUpdate = millis();
this->_lastRequest = 0; // no outstanding request
this->_udp->read(this->_packetBuffer, NTP_PACKET_SIZE);
int numBytesRead = this->_udp->read(this->_packetBuffer, NTP_PACKET_SIZE);

unsigned long highWord = word(this->_packetBuffer[40], this->_packetBuffer[41]);
unsigned long lowWord = word(this->_packetBuffer[42], this->_packetBuffer[43]);

// combine the four bytes (two words) into a long integer
// this is NTP time (seconds since Jan 1 1900):
unsigned long secsSince1900 = highWord << 16 | lowWord;
if ((numBytesRead == NTP_PACKET_SIZE) && isValid(this->_packetBuffer))
{
this->_lastUpdate = millis();

this->_currentEpoc = secsSince1900 - SEVENTYYEARS;
unsigned long highWord = word(this->_packetBuffer[40], this->_packetBuffer[41]);
unsigned long lowWord = word(this->_packetBuffer[42], this->_packetBuffer[43]);

highWord = word(this->_packetBuffer[44], this->_packetBuffer[45]);
lowWord = word(this->_packetBuffer[46], this->_packetBuffer[47]);
this->_currentFraction = highWord << 16 | lowWord;
// combine the four bytes (two words) into a long integer
// this is NTP time (seconds since Jan 1 1900):
unsigned long secsSince1900 = highWord << 16 | lowWord;

// if the user has set a callback function for when the time is updated, call it
if (_updateCallback)
{
_updateCallback(this);
}
this->_currentEpoc = secsSince1900 - SEVENTYYEARS;

return true;
}
else
{
return false;
highWord = word(this->_packetBuffer[44], this->_packetBuffer[45]);
lowWord = word(this->_packetBuffer[46], this->_packetBuffer[47]);
this->_currentFraction = highWord << 16 | lowWord;

// if the user has set a callback function for when the time is updated, call it
if (_updateCallback)
{
_updateCallback(this);
}

return true;
}
}

return false;
}

bool NTPClient::forceUpdate()
Expand Down
73 changes: 50 additions & 23 deletions src_cpp/NTPClient_Generic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,40 +58,67 @@ void NTPClient::begin(int port)
this->_udpSetup = true;
}

bool NTPClient::checkResponse()
// Perform some validity checks on the packet
// https://datatracker.ietf.org/doc/html/rfc4330#section-4
// Check length before calling
static bool isValid(byte const *ntpPacket)
{
unsigned long highWord = word(ntpPacket[16], ntpPacket[17]);
unsigned long lowWord = word(ntpPacket[18], ntpPacket[19]);
unsigned long refTimeInt = highWord << 16 | lowWord;
highWord = word(ntpPacket[20], ntpPacket[21]);
lowWord = word(ntpPacket[22], ntpPacket[23]);
unsigned long refTimeFrac = highWord << 16 | lowWord;

byte leapIndicator = ((ntpPacket[0] & 0b11000000) >> 6);
byte version = ((ntpPacket[0] & 0b00111000) >> 3);
byte stratum = ntpPacket[1];

return
(
(leapIndicator != 3) && // LI != UNSYNC
(version >= 1) &&
(stratum >= 1) &&
(stratum <= 15) &&
((refTimeInt != 0) || (refTimeFrac != 0))
);
}

bool NTPClient::checkResponse()
{
if (this->_udp->parsePacket())
{
this->_lastUpdate = millis();
this->_lastRequest = 0; // no outstanding request
this->_udp->read(this->_packetBuffer, NTP_PACKET_SIZE);
int numBytesRead = this->_udp->read(this->_packetBuffer, NTP_PACKET_SIZE);

unsigned long highWord = word(this->_packetBuffer[40], this->_packetBuffer[41]);
unsigned long lowWord = word(this->_packetBuffer[42], this->_packetBuffer[43]);

// combine the four bytes (two words) into a long integer
// this is NTP time (seconds since Jan 1 1900):
unsigned long secsSince1900 = highWord << 16 | lowWord;
if ((numBytesRead == NTP_PACKET_SIZE) && isValid(this->_packetBuffer))
{
this->_lastUpdate = millis();

this->_currentEpoc = secsSince1900 - SEVENTYYEARS;
unsigned long highWord = word(this->_packetBuffer[40], this->_packetBuffer[41]);
unsigned long lowWord = word(this->_packetBuffer[42], this->_packetBuffer[43]);

highWord = word(this->_packetBuffer[44], this->_packetBuffer[45]);
lowWord = word(this->_packetBuffer[46], this->_packetBuffer[47]);
this->_currentFraction = highWord << 16 | lowWord;
// combine the four bytes (two words) into a long integer
// this is NTP time (seconds since Jan 1 1900):
unsigned long secsSince1900 = highWord << 16 | lowWord;

// if the user has set a callback function for when the time is updated, call it
if (_updateCallback)
{
_updateCallback(this);
}
this->_currentEpoc = secsSince1900 - SEVENTYYEARS;

return true;
}
else
{
return false;
highWord = word(this->_packetBuffer[44], this->_packetBuffer[45]);
lowWord = word(this->_packetBuffer[46], this->_packetBuffer[47]);
this->_currentFraction = highWord << 16 | lowWord;

// if the user has set a callback function for when the time is updated, call it
if (_updateCallback)
{
_updateCallback(this);
}

return true;
}
}

return false;
}

bool NTPClient::forceUpdate()
Expand Down
73 changes: 50 additions & 23 deletions src_h/NTPClient_Generic_Impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,40 +58,67 @@ void NTPClient::begin(int port)
this->_udpSetup = true;
}

bool NTPClient::checkResponse()
// Perform some validity checks on the packet
// https://datatracker.ietf.org/doc/html/rfc4330#section-4
// Check length before calling
static bool isValid(byte const *ntpPacket)
{
unsigned long highWord = word(ntpPacket[16], ntpPacket[17]);
unsigned long lowWord = word(ntpPacket[18], ntpPacket[19]);
unsigned long refTimeInt = highWord << 16 | lowWord;
highWord = word(ntpPacket[20], ntpPacket[21]);
lowWord = word(ntpPacket[22], ntpPacket[23]);
unsigned long refTimeFrac = highWord << 16 | lowWord;

byte leapIndicator = ((ntpPacket[0] & 0b11000000) >> 6);
byte version = ((ntpPacket[0] & 0b00111000) >> 3);
byte stratum = ntpPacket[1];

return
(
(leapIndicator != 3) && // LI != UNSYNC
(version >= 1) &&
(stratum >= 1) &&
(stratum <= 15) &&
((refTimeInt != 0) || (refTimeFrac != 0))
);
}

bool NTPClient::checkResponse()
{
if (this->_udp->parsePacket())
{
this->_lastUpdate = millis();
this->_lastRequest = 0; // no outstanding request
this->_udp->read(this->_packetBuffer, NTP_PACKET_SIZE);
int numBytesRead = this->_udp->read(this->_packetBuffer, NTP_PACKET_SIZE);

unsigned long highWord = word(this->_packetBuffer[40], this->_packetBuffer[41]);
unsigned long lowWord = word(this->_packetBuffer[42], this->_packetBuffer[43]);

// combine the four bytes (two words) into a long integer
// this is NTP time (seconds since Jan 1 1900):
unsigned long secsSince1900 = highWord << 16 | lowWord;
if ((numBytesRead == NTP_PACKET_SIZE) && isValid(this->_packetBuffer))
{
this->_lastUpdate = millis();

this->_currentEpoc = secsSince1900 - SEVENTYYEARS;
unsigned long highWord = word(this->_packetBuffer[40], this->_packetBuffer[41]);
unsigned long lowWord = word(this->_packetBuffer[42], this->_packetBuffer[43]);

highWord = word(this->_packetBuffer[44], this->_packetBuffer[45]);
lowWord = word(this->_packetBuffer[46], this->_packetBuffer[47]);
this->_currentFraction = highWord << 16 | lowWord;
// combine the four bytes (two words) into a long integer
// this is NTP time (seconds since Jan 1 1900):
unsigned long secsSince1900 = highWord << 16 | lowWord;

// if the user has set a callback function for when the time is updated, call it
if (_updateCallback)
{
_updateCallback(this);
}
this->_currentEpoc = secsSince1900 - SEVENTYYEARS;

return true;
}
else
{
return false;
highWord = word(this->_packetBuffer[44], this->_packetBuffer[45]);
lowWord = word(this->_packetBuffer[46], this->_packetBuffer[47]);
this->_currentFraction = highWord << 16 | lowWord;

// if the user has set a callback function for when the time is updated, call it
if (_updateCallback)
{
_updateCallback(this);
}

return true;
}
}

return false;
}

bool NTPClient::forceUpdate()
Expand Down