|
|
|
@ -217,25 +217,57 @@ namespace stream
@@ -217,25 +217,57 @@ namespace stream
|
|
|
|
|
|
|
|
|
|
void Stream::ProcessPacket (Packet * packet) |
|
|
|
|
{ |
|
|
|
|
// process flags
|
|
|
|
|
uint32_t receivedSeqn = packet->GetSeqn (); |
|
|
|
|
uint16_t flags = packet->GetFlags (); |
|
|
|
|
LogPrint (eLogDebug, "Streaming: Process seqn=", receivedSeqn, ", flags=", flags); |
|
|
|
|
|
|
|
|
|
const uint8_t * optionData = packet->GetOptionData (); |
|
|
|
|
if (!ProcessOptions (flags, packet)) |
|
|
|
|
{ |
|
|
|
|
m_LocalDestination.DeletePacket (packet); |
|
|
|
|
Terminate (); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
packet->offset = packet->GetPayload () - packet->buf; |
|
|
|
|
if (packet->GetLength () > 0) |
|
|
|
|
{ |
|
|
|
|
m_ReceiveQueue.push (packet); |
|
|
|
|
m_ReceiveTimer.cancel (); |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
m_LocalDestination.DeletePacket (packet); |
|
|
|
|
|
|
|
|
|
m_LastReceivedSequenceNumber = receivedSeqn; |
|
|
|
|
|
|
|
|
|
if (flags & PACKET_FLAG_RESET) |
|
|
|
|
{ |
|
|
|
|
LogPrint (eLogDebug, "Streaming: closing stream sSID=", m_SendStreamID, ", rSID=", m_RecvStreamID, ": reset flag received in packet #", receivedSeqn); |
|
|
|
|
m_Status = eStreamStatusReset; |
|
|
|
|
Close (); |
|
|
|
|
} |
|
|
|
|
else if (flags & PACKET_FLAG_CLOSE) |
|
|
|
|
{ |
|
|
|
|
if (m_Status != eStreamStatusClosed) |
|
|
|
|
SendClose (); |
|
|
|
|
m_Status = eStreamStatusClosed; |
|
|
|
|
Terminate (); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool Stream::ProcessOptions (uint16_t flags, Packet * packet) |
|
|
|
|
{ |
|
|
|
|
const uint8_t * optionData = packet->GetOptionData (); |
|
|
|
|
size_t optionSize = packet->GetOptionSize (); |
|
|
|
|
if (flags & PACKET_FLAG_DELAY_REQUESTED) |
|
|
|
|
optionData += 2; |
|
|
|
|
|
|
|
|
|
if (flags & PACKET_FLAG_FROM_INCLUDED) |
|
|
|
|
{ |
|
|
|
|
m_RemoteIdentity = std::make_shared<i2p::data::IdentityEx>(optionData, packet->GetOptionSize ()); |
|
|
|
|
m_RemoteIdentity = std::make_shared<i2p::data::IdentityEx>(optionData, optionSize); |
|
|
|
|
if (m_RemoteIdentity->IsRSA ()) |
|
|
|
|
{ |
|
|
|
|
LogPrint (eLogInfo, "Streaming: Incoming stream from RSA destination ", m_RemoteIdentity->GetIdentHash ().ToBase64 (), " Discarded"); |
|
|
|
|
m_LocalDestination.DeletePacket (packet); |
|
|
|
|
Terminate (); |
|
|
|
|
return; |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
optionData += m_RemoteIdentity->GetFullLen (); |
|
|
|
|
if (!m_RemoteLeaseSet) |
|
|
|
@ -249,6 +281,42 @@ namespace stream
@@ -249,6 +281,42 @@ namespace stream
|
|
|
|
|
optionData += 2; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (flags & PACKET_FLAG_OFFLINE_SIGNATURE) |
|
|
|
|
{ |
|
|
|
|
if (!m_RemoteIdentity) |
|
|
|
|
{ |
|
|
|
|
LogPrint (eLogInfo, "Streaming: offline signature without identity"); |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
const uint8_t * signedData = optionData; |
|
|
|
|
uint32_t expiresTimestamp = bufbe32toh (optionData); optionData += 4; // expires timestamp
|
|
|
|
|
if (expiresTimestamp < i2p::util::GetSecondsSinceEpoch ()) |
|
|
|
|
{ |
|
|
|
|
LogPrint (eLogInfo, "Streaming: offline signature transient key expired"); |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
uint16_t keyType = bufbe16toh (optionData); optionData += 2; // key type
|
|
|
|
|
m_TransientVerifier.reset (i2p::data::IdentityEx::CreateVerifier (keyType)); |
|
|
|
|
if (!m_TransientVerifier) |
|
|
|
|
{ |
|
|
|
|
LogPrint (eLogInfo, "Streaming: Unknown transient key type ", (int)keyType); |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
auto keyLen = m_TransientVerifier->GetPublicKeyLen (); |
|
|
|
|
if ((optionData - packet->GetOptionData ()) + keyLen + m_RemoteIdentity->GetSignatureLen () > optionSize) |
|
|
|
|
{ |
|
|
|
|
LogPrint (eLogInfo, "Streaming: Option data is too short ", (int)optionSize); |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
m_TransientVerifier->SetPublicKey (optionData); optionData += keyLen; // key
|
|
|
|
|
if (!m_RemoteIdentity->Verify (signedData, keyLen + 6, optionData)) |
|
|
|
|
{ |
|
|
|
|
LogPrint (eLogError, "Streaming: Transient key signature verification failed"); |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
optionData += m_RemoteIdentity->GetSignatureLen (); // signature
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (flags & PACKET_FLAG_SIGNATURE_INCLUDED) |
|
|
|
|
{ |
|
|
|
|
uint8_t signature[256]; |
|
|
|
@ -257,7 +325,10 @@ namespace stream
@@ -257,7 +325,10 @@ namespace stream
|
|
|
|
|
{ |
|
|
|
|
memcpy (signature, optionData, signatureLen); |
|
|
|
|
memset (const_cast<uint8_t *>(optionData), 0, signatureLen); |
|
|
|
|
if (!m_RemoteIdentity->Verify (packet->GetBuffer (), packet->GetLength (), signature)) |
|
|
|
|
bool verified = m_TransientVerifier ? |
|
|
|
|
m_TransientVerifier->Verify (packet->GetBuffer (), packet->GetLength (), signature) : |
|
|
|
|
m_RemoteIdentity->Verify (packet->GetBuffer (), packet->GetLength (), signature); |
|
|
|
|
if (!verified) |
|
|
|
|
{ |
|
|
|
|
LogPrint (eLogError, "Streaming: Signature verification failed, sSID=", m_SendStreamID, ", rSID=", m_RecvStreamID); |
|
|
|
|
Close (); |
|
|
|
@ -268,34 +339,11 @@ namespace stream
@@ -268,34 +339,11 @@ namespace stream
|
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
{ |
|
|
|
|
LogPrint(eLogError, "Streaming: Signature too big, ", signatureLen, " bytes"); |
|
|
|
|
LogPrint (eLogError, "Streaming: Signature too big, ", signatureLen, " bytes"); |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
packet->offset = packet->GetPayload () - packet->buf; |
|
|
|
|
if (packet->GetLength () > 0) |
|
|
|
|
{ |
|
|
|
|
m_ReceiveQueue.push (packet); |
|
|
|
|
m_ReceiveTimer.cancel (); |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
m_LocalDestination.DeletePacket (packet); |
|
|
|
|
|
|
|
|
|
m_LastReceivedSequenceNumber = receivedSeqn; |
|
|
|
|
|
|
|
|
|
if (flags & PACKET_FLAG_RESET) |
|
|
|
|
{ |
|
|
|
|
LogPrint (eLogDebug, "Streaming: closing stream sSID=", m_SendStreamID, ", rSID=", m_RecvStreamID, ": reset flag received in packet #", receivedSeqn); |
|
|
|
|
m_Status = eStreamStatusReset; |
|
|
|
|
Close (); |
|
|
|
|
} |
|
|
|
|
else if (flags & PACKET_FLAG_CLOSE) |
|
|
|
|
{ |
|
|
|
|
if (m_Status != eStreamStatusClosed) |
|
|
|
|
SendClose (); |
|
|
|
|
m_Status = eStreamStatusClosed; |
|
|
|
|
Terminate (); |
|
|
|
|
} |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void Stream::ProcessAck (Packet * packet) |
|
|
|
|