forked from PurpleI2P/i2pd
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
561 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
#include <string.h> | ||
#include "Log.h" | ||
#include "RouterContext.h" | ||
#include "I2NPProtocol.h" | ||
#include "Tunnel.h" | ||
#include "Transports.h" | ||
#include "TransitTunnel.h" | ||
|
||
namespace i2p | ||
{ | ||
namespace tunnel | ||
{ | ||
TransitTunnel::TransitTunnel (uint32_t receiveTunnelID, | ||
const uint8_t * nextIdent, uint32_t nextTunnelID, | ||
const uint8_t * layerKey,const uint8_t * ivKey, | ||
bool isGateway, bool isEndpoint) | ||
{ | ||
memcpy (m_LayerKey, layerKey, 32); | ||
memcpy (m_IVKey, ivKey, 32); | ||
memcpy (m_NextIdent, nextIdent, 32); | ||
m_IsGateway = isGateway; | ||
m_IsEndpoint = isEndpoint; | ||
m_TunnelID = receiveTunnelID; | ||
m_NextTunnelID = nextTunnelID; | ||
if (m_IsEndpoint) | ||
LogPrint ("TransitTunnel endpoint: ", m_TunnelID, " created"); | ||
else if (m_IsGateway) | ||
LogPrint ("TransitTunnel gateway: ", m_TunnelID, " created"); | ||
else | ||
LogPrint ("TransitTunnel: ",m_TunnelID,"->", m_NextTunnelID, " created"); | ||
} | ||
|
||
void TransitTunnel::Encrypt (uint8_t * payload) | ||
{ | ||
m_ECBEncryption.SetKey (m_IVKey, 32); | ||
m_ECBEncryption.ProcessData(payload, payload, 16); // iv | ||
|
||
m_CBCEncryption.SetKeyWithIV (m_LayerKey, 32, payload); | ||
m_CBCEncryption.ProcessData(payload + 16, payload + 16, 1008); // payload | ||
|
||
m_ECBEncryption.SetKey (m_IVKey, 32); | ||
m_ECBEncryption.ProcessData(payload, payload, 16); // double iv encryption | ||
|
||
} | ||
|
||
void TransitTunnel::HandleTunnelDataMsg (i2p::I2NPMessage * tunnelMsg) | ||
{ | ||
Encrypt (tunnelMsg->GetPayload () + 4); | ||
|
||
if (m_IsEndpoint) | ||
{ | ||
LogPrint ("TransitTunnel endpoint for ", m_TunnelID); | ||
m_Endpoint.HandleDecryptedTunnelDataMsg (tunnelMsg); | ||
} | ||
else | ||
{ | ||
LogPrint ("TransitTunnel: ",m_TunnelID,"->", m_NextTunnelID); | ||
*(uint32_t *)(tunnelMsg->GetPayload ()) = htobe32 (m_NextTunnelID); | ||
FillI2NPMessageHeader (tunnelMsg, eI2NPTunnelData); | ||
|
||
i2p::transports.SendMessage (m_NextIdent, tunnelMsg); | ||
} | ||
} | ||
|
||
void TransitTunnel::SendTunnelDataMsg (const uint8_t * gwHash, uint32_t gwTunnel, i2p::I2NPMessage * msg) | ||
{ | ||
if (m_IsGateway) | ||
{ | ||
m_Gateway.PutI2NPMsg (gwHash, gwTunnel, msg); | ||
auto tunnelMsgs = m_Gateway.GetTunnelDataMsgs (m_NextTunnelID); | ||
for (auto tunnelMsg : tunnelMsgs) | ||
{ | ||
Encrypt (tunnelMsg->GetPayload () + 4); | ||
FillI2NPMessageHeader (tunnelMsg, eI2NPTunnelData); | ||
i2p::transports.SendMessage (m_NextIdent, tunnelMsg); | ||
} | ||
} | ||
else | ||
{ | ||
LogPrint ("We are not a gateway for transit tunnel ", m_TunnelID); | ||
i2p::DeleteI2NPMessage (msg); | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
#ifndef TRANSIT_TUNNEL_H__ | ||
#define TRANSIT_TUNNEL_H__ | ||
|
||
#include <inttypes.h> | ||
#include <cryptopp/modes.h> | ||
#include <cryptopp/aes.h> | ||
#include "I2NPProtocol.h" | ||
#include "TunnelEndpoint.h" | ||
#include "TunnelGateway.h" | ||
|
||
namespace i2p | ||
{ | ||
namespace tunnel | ||
{ | ||
class TransitTunnel | ||
{ | ||
public: | ||
|
||
TransitTunnel (uint32_t receiveTunnelID, | ||
const uint8_t * nextIdent, uint32_t nextTunnelID, | ||
const uint8_t * layerKey,const uint8_t * ivKey, | ||
bool isGateway, bool isEndpoint); | ||
|
||
void HandleTunnelDataMsg (i2p::I2NPMessage * tunnelMsg); | ||
void SendTunnelDataMsg (const uint8_t * gwHash, uint32_t gwTunnel, i2p::I2NPMessage * msg); | ||
|
||
uint32_t GetTunnelID () const { return m_TunnelID; }; | ||
bool IsGateway () const { return m_IsGateway; }; | ||
bool IsEndpoint () const { return m_IsEndpoint; }; | ||
bool IsParticipant () const { return !IsGateway () && !IsEndpoint (); }; | ||
|
||
private: | ||
|
||
void Encrypt (uint8_t * payload); | ||
|
||
private: | ||
|
||
uint32_t m_TunnelID, m_NextTunnelID; | ||
uint8_t m_NextIdent[32]; | ||
uint8_t m_LayerKey[32]; | ||
uint8_t m_IVKey[32]; | ||
bool m_IsGateway, m_IsEndpoint; | ||
|
||
TunnelEndpoint m_Endpoint; | ||
TunnelGatewayBuffer m_Gateway; | ||
|
||
CryptoPP::ECB_Mode<CryptoPP::AES>::Encryption m_ECBEncryption; | ||
CryptoPP::CBC_Mode<CryptoPP::AES>::Encryption m_CBCEncryption; | ||
}; | ||
} | ||
} | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
#ifndef TUNNEL_BASE_H__ | ||
#define TUNNEL_BASE_H__ | ||
|
||
#include <inttypes.h> | ||
|
||
namespace i2p | ||
{ | ||
namespace tunnel | ||
{ | ||
enum TunnelDeliveryType | ||
{ | ||
eDeliveryTypeLocal = 0, | ||
eDeliveryTypeTunnel = 1, | ||
eDeliveryTypeRouter = 2 | ||
}; | ||
struct TunnelMessageBlock | ||
{ | ||
TunnelDeliveryType deliveryType; | ||
uint32_t tunnelID; | ||
uint8_t hash[32]; | ||
I2NPMessage * data; | ||
}; | ||
} | ||
} | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,159 @@ | ||
#include <string.h> | ||
#include "Log.h" | ||
#include "I2NPProtocol.h" | ||
#include "Transports.h" | ||
#include "TunnelEndpoint.h" | ||
|
||
namespace i2p | ||
{ | ||
namespace tunnel | ||
{ | ||
void TunnelEndpoint::HandleDecryptedTunnelDataMsg (I2NPMessage * msg) | ||
{ | ||
uint8_t * decrypted = msg->GetPayload () + 20; // 4 + 16 | ||
uint8_t * zero = (uint8_t *)memchr (decrypted + 4, 0, 1004); // witout checksum | ||
if (zero) | ||
{ | ||
LogPrint ("TunnelMessage: zero found at ", (int)(zero-decrypted)); | ||
uint8_t * fragment = zero + 1; | ||
while (fragment < decrypted + 1008) | ||
{ | ||
uint8_t flag = fragment[0]; | ||
fragment++; | ||
|
||
bool isFollowOnFragment = flag & 0x80, isLastFragment = true; | ||
uint32_t msgID = 0; | ||
TunnelMessageBlock m; | ||
if (!isFollowOnFragment) | ||
{ | ||
// first fragment | ||
|
||
m.deliveryType = (TunnelDeliveryType)((flag >> 5) & 0x03); | ||
switch (m.deliveryType) | ||
{ | ||
case eDeliveryTypeLocal: // 0 | ||
LogPrint ("Delivery type local"); | ||
break; | ||
case eDeliveryTypeTunnel: // 1 | ||
LogPrint ("Delivery type tunnel"); | ||
m.tunnelID = be32toh (*(uint32_t *)fragment); | ||
fragment += 4; // tunnelID | ||
memcpy (m.hash, fragment, 32); | ||
fragment += 32; // hash | ||
break; | ||
case eDeliveryTypeRouter: // 2 | ||
LogPrint ("Delivery type router"); | ||
memcpy (m.hash, fragment, 32); | ||
fragment += 32; // to hash | ||
break; | ||
default: | ||
; | ||
} | ||
|
||
bool isFragmented = flag & 0x08; | ||
if (isFragmented) | ||
{ | ||
// Message ID | ||
msgID = be32toh (*(uint32_t *)fragment); | ||
fragment += 4; | ||
LogPrint ("Fragmented message ", msgID); | ||
isLastFragment = false; | ||
} | ||
} | ||
else | ||
{ | ||
// follow on | ||
msgID = be32toh (*(uint32_t *)fragment); // MessageID | ||
fragment += 4; | ||
int fragmentNum = (flag >> 1) & 0x3F; // 6 bits | ||
isLastFragment = flag & 0x01; | ||
LogPrint ("Follow on fragment ", fragmentNum, " of message ", msgID, isLastFragment ? " last" : " non-last"); | ||
} | ||
|
||
uint16_t size = be16toh (*(uint16_t *)fragment); | ||
fragment += 2; | ||
LogPrint ("Fragment size=", (int)size); | ||
|
||
msg->offset = fragment - msg->buf; | ||
msg->len = msg->offset + size; | ||
bool isLastMessage = false; | ||
if (fragment + size < decrypted + 1008) | ||
{ | ||
// this is not last message. we have to copy it | ||
m.data = NewI2NPMessage (); | ||
m.data->offset += sizeof (TunnelGatewayHeader); // reserve room for TunnelGateway header | ||
m.data->len += sizeof (TunnelGatewayHeader); | ||
*(m.data) = *msg; | ||
} | ||
else | ||
{ | ||
m.data = msg; | ||
isLastMessage = true; | ||
} | ||
|
||
if (!isFollowOnFragment && isLastFragment) | ||
HandleNextMessage (m); | ||
else | ||
{ | ||
if (msgID) // msgID is presented, assume message is fragmented | ||
{ | ||
if (!isFollowOnFragment) // create new incomlete message | ||
m_IncompleteMessages[msgID] = m; | ||
else | ||
{ | ||
auto it = m_IncompleteMessages.find (msgID); | ||
if (it != m_IncompleteMessages.end()) | ||
{ | ||
I2NPMessage * incompleteMessage = it->second.data; | ||
memcpy (incompleteMessage->buf + incompleteMessage->len, fragment, size); // concatenate fragment | ||
incompleteMessage->len += size; | ||
// TODO: check fragmentNum sequence | ||
if (isLastFragment) | ||
{ | ||
// message complete | ||
HandleNextMessage (it->second); | ||
m_IncompleteMessages.erase (it); | ||
} | ||
} | ||
else | ||
LogPrint ("First fragment of message ", msgID, " not found. Discarded"); | ||
|
||
if (isLastMessage) | ||
// last message is follow-on fragment | ||
// not passed to anywhere because first fragment | ||
i2p::DeleteI2NPMessage (msg); | ||
} | ||
} | ||
else | ||
LogPrint ("Message is fragmented, but msgID is not presented"); | ||
} | ||
|
||
fragment += size; | ||
} | ||
} | ||
else | ||
{ | ||
LogPrint ("TunnelMessage: zero not found"); | ||
i2p::DeleteI2NPMessage (msg); | ||
} | ||
} | ||
|
||
void TunnelEndpoint::HandleNextMessage (const TunnelMessageBlock& msg) | ||
{ | ||
switch (msg.deliveryType) | ||
{ | ||
case eDeliveryTypeLocal: | ||
i2p::HandleI2NPMessage (msg.data); | ||
break; | ||
case eDeliveryTypeTunnel: | ||
i2p::transports.SendMessage (msg.hash, i2p::CreateTunnelGatewayMsg (msg.tunnelID, msg.data)); | ||
break; | ||
case eDeliveryTypeRouter: | ||
i2p::transports.SendMessage (msg.hash, msg.data); | ||
break; | ||
default: | ||
; | ||
}; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
#ifndef TUNNEL_ENDPOINT_H__ | ||
#define TUNNEL_ENDPOINT_H__ | ||
|
||
#include <inttypes.h> | ||
#include <map> | ||
#include <string> | ||
#include "I2NPProtocol.h" | ||
#include "TunnelBase.h" | ||
|
||
namespace i2p | ||
{ | ||
namespace tunnel | ||
{ | ||
class TunnelEndpoint | ||
{ | ||
public: | ||
|
||
void HandleDecryptedTunnelDataMsg (I2NPMessage * msg); | ||
|
||
private: | ||
|
||
void HandleNextMessage (const TunnelMessageBlock& msg); | ||
|
||
private: | ||
|
||
std::map<uint32_t, TunnelMessageBlock> m_IncompleteMessages; | ||
}; | ||
} | ||
} | ||
|
||
#endif |
Oops, something went wrong.