diff --git a/HTTPServer.cpp b/HTTPServer.cpp
index 2e9a02ca..2e469f98 100644
--- a/HTTPServer.cpp
+++ b/HTTPServer.cpp
@@ -180,6 +180,7 @@ namespace http {
case eRouterStatusOK: s << "OK"; break;
case eRouterStatusTesting: s << "Testing"; break;
case eRouterStatusFirewalled: s << "Firewalled"; break;
+ case eRouterStatusError: s << "Error"; break;
default: s << "Unknown";
}
s << "
\r\n";
diff --git a/RouterContext.h b/RouterContext.h
index 27e0947d..23c03593 100644
--- a/RouterContext.h
+++ b/RouterContext.h
@@ -20,7 +20,8 @@ namespace i2p
{
eRouterStatusOK = 0,
eRouterStatusTesting = 1,
- eRouterStatusFirewalled = 2
+ eRouterStatusFirewalled = 2,
+ eRouterStatusError = 3
};
class RouterContext: public i2p::garlic::GarlicDestination
diff --git a/SSUSession.cpp b/SSUSession.cpp
index 26c14570..ca714aed 100644
--- a/SSUSession.cpp
+++ b/SSUSession.cpp
@@ -272,6 +272,16 @@ namespace transport
s.Insert (payload, 8); // relayTag and signed on time
m_RelayTag = bufbe32toh (payload);
payload += 4; // relayTag
+ if (i2p::context.GetStatus () == eRouterStatusTesting)
+ {
+ auto ts = i2p::util::GetSecondsSinceEpoch ();
+ uint32_t signedOnTime = bufbe32toh(payload);
+ if (signedOnTime < ts - SSU_CLOCK_SKEW || signedOnTime > ts + SSU_CLOCK_SKEW)
+ {
+ LogPrint (eLogError, "SSU: clock skew detected ", (int)ts - signedOnTime, ". Check your clock");
+ i2p::context.SetStatus (eRouterStatusError);
+ }
+ }
payload += 4; // signed on time
// decrypt signature
size_t signatureLen = m_RemoteIdentity->GetSignatureLen ();
@@ -310,6 +320,14 @@ namespace transport
SetRemoteIdentity (std::make_shared (payload, identitySize));
m_Data.UpdatePacketSize (m_RemoteIdentity->GetIdentHash ());
payload += identitySize; // identity
+ auto ts = i2p::util::GetSecondsSinceEpoch ();
+ uint32_t signedOnTime = bufbe32toh(payload);
+ if (signedOnTime < ts - SSU_CLOCK_SKEW || signedOnTime > ts + SSU_CLOCK_SKEW)
+ {
+ LogPrint (eLogError, "SSU message 'confirmed' time difference ", (int)ts - signedOnTime, " exceeds clock skew");
+ Failed ();
+ return;
+ }
if (m_SignedData)
m_SignedData->Insert (payload, 4); // insert Alice's signed on time
payload += 4; // signed-on time
diff --git a/SSUSession.h b/SSUSession.h
index 69669187..4838be2a 100644
--- a/SSUSession.h
+++ b/SSUSession.h
@@ -27,6 +27,7 @@ namespace transport
const int SSU_CONNECT_TIMEOUT = 5; // 5 seconds
const int SSU_TERMINATION_TIMEOUT = 330; // 5.5 minutes
+ const int SSU_CLOCK_SKEW = 60; // in seconds
// payload types (4 bits)
const uint8_t PAYLOAD_TYPE_SESSION_REQUEST = 0;