mirror of
https://github.com/PurpleI2P/i2pd.git
synced 2025-03-07 06:09:42 +00:00
Compare commits
2 Commits
master
...
ff34d3bd20
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ff34d3bd20 | ||
|
|
17399da399 |
2
.github/workflows/build-windows.yml
vendored
2
.github/workflows/build-windows.yml
vendored
@@ -231,7 +231,7 @@ jobs:
|
|||||||
cd MINGW-packages/mingw-w64-boost
|
cd MINGW-packages/mingw-w64-boost
|
||||||
MINGW_ARCH=mingw32 makepkg-mingw -sCLf --noconfirm --nocheck
|
MINGW_ARCH=mingw32 makepkg-mingw -sCLf --noconfirm --nocheck
|
||||||
- name: Install boost package
|
- name: Install boost package
|
||||||
run: pacman --noconfirm -U --overwrite MINGW-packages/mingw-w64-boost/mingw-w64-i686-*-any.pkg.tar.zst
|
run: pacman --noconfirm -U MINGW-packages/mingw-w64-boost/mingw-w64-i686-*-any.pkg.tar.zst
|
||||||
|
|
||||||
# Building i2pd
|
# Building i2pd
|
||||||
- name: Build application
|
- name: Build application
|
||||||
|
|||||||
13
contrib/docker/docker-compose.yml
Normal file
13
contrib/docker/docker-compose.yml
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
services:
|
||||||
|
i2pd:
|
||||||
|
container_name: i2pd2
|
||||||
|
image: purplei2p/i2pd
|
||||||
|
#optional
|
||||||
|
entrypoint: ["./entrypoint.sh", "--loglevel error"]
|
||||||
|
ports:
|
||||||
|
- 127.0.0.1:7656:7656
|
||||||
|
- 127.0.0.1:7070:7070
|
||||||
|
- 127.0.0.1:4444:4444
|
||||||
|
volumes:
|
||||||
|
- /path/to/i2pd/data:/home/i2pd/data # make sure data directory and it's contents are owned by 100:65533
|
||||||
|
- /path/to/i2pd/i2pd_certificates:/i2pd_certificates # make sure i2pd_certificates is owned by root:root and 755 permissions on the directory
|
||||||
@@ -42,29 +42,28 @@ namespace transport
|
|||||||
delete[] m_SessionConfirmedBuffer;
|
delete[] m_SessionConfirmedBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NTCP2Establisher::KeyDerivationFunction1 (const uint8_t * pub, i2p::crypto::X25519Keys& priv, const uint8_t * rs, const uint8_t * epub)
|
void NTCP2Establisher::KeyDerivationFunction1 (const uint8_t * pub, i2p::crypto::X25519Keys& priv, const uint8_t * rs, const uint8_t * epub)
|
||||||
{
|
{
|
||||||
i2p::crypto::InitNoiseXKState (*this, rs);
|
i2p::crypto::InitNoiseXKState (*this, rs);
|
||||||
// h = SHA256(h || epub)
|
// h = SHA256(h || epub)
|
||||||
MixHash (epub, 32);
|
MixHash (epub, 32);
|
||||||
// x25519 between pub and priv
|
// x25519 between pub and priv
|
||||||
uint8_t inputKeyMaterial[32];
|
uint8_t inputKeyMaterial[32];
|
||||||
if (!priv.Agree (pub, inputKeyMaterial)) return false;
|
priv.Agree (pub, inputKeyMaterial);
|
||||||
MixKey (inputKeyMaterial);
|
MixKey (inputKeyMaterial);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NTCP2Establisher::KDF1Alice ()
|
void NTCP2Establisher::KDF1Alice ()
|
||||||
{
|
{
|
||||||
return KeyDerivationFunction1 (m_RemoteStaticKey, *m_EphemeralKeys, m_RemoteStaticKey, GetPub ());
|
KeyDerivationFunction1 (m_RemoteStaticKey, *m_EphemeralKeys, m_RemoteStaticKey, GetPub ());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NTCP2Establisher::KDF1Bob ()
|
void NTCP2Establisher::KDF1Bob ()
|
||||||
{
|
{
|
||||||
return KeyDerivationFunction1 (GetRemotePub (), i2p::context.GetNTCP2StaticKeys (), i2p::context.GetNTCP2StaticPublicKey (), GetRemotePub ());
|
KeyDerivationFunction1 (GetRemotePub (), i2p::context.GetNTCP2StaticKeys (), i2p::context.GetNTCP2StaticPublicKey (), GetRemotePub ());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NTCP2Establisher::KeyDerivationFunction2 (const uint8_t * sessionRequest, size_t sessionRequestLen, const uint8_t * epub)
|
void NTCP2Establisher::KeyDerivationFunction2 (const uint8_t * sessionRequest, size_t sessionRequestLen, const uint8_t * epub)
|
||||||
{
|
{
|
||||||
MixHash (sessionRequest + 32, 32); // encrypted payload
|
MixHash (sessionRequest + 32, 32); // encrypted payload
|
||||||
|
|
||||||
@@ -75,35 +74,33 @@ namespace transport
|
|||||||
|
|
||||||
// x25519 between remote pub and ephemaral priv
|
// x25519 between remote pub and ephemaral priv
|
||||||
uint8_t inputKeyMaterial[32];
|
uint8_t inputKeyMaterial[32];
|
||||||
if (!m_EphemeralKeys->Agree (GetRemotePub (), inputKeyMaterial)) return false;
|
m_EphemeralKeys->Agree (GetRemotePub (), inputKeyMaterial);
|
||||||
|
|
||||||
MixKey (inputKeyMaterial);
|
MixKey (inputKeyMaterial);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NTCP2Establisher::KDF2Alice ()
|
void NTCP2Establisher::KDF2Alice ()
|
||||||
{
|
{
|
||||||
return KeyDerivationFunction2 (m_SessionRequestBuffer, m_SessionRequestBufferLen, GetRemotePub ());
|
KeyDerivationFunction2 (m_SessionRequestBuffer, m_SessionRequestBufferLen, GetRemotePub ());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NTCP2Establisher::KDF2Bob ()
|
void NTCP2Establisher::KDF2Bob ()
|
||||||
{
|
{
|
||||||
return KeyDerivationFunction2 (m_SessionRequestBuffer, m_SessionRequestBufferLen, GetPub ());
|
KeyDerivationFunction2 (m_SessionRequestBuffer, m_SessionRequestBufferLen, GetPub ());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NTCP2Establisher::KDF3Alice ()
|
void NTCP2Establisher::KDF3Alice ()
|
||||||
{
|
{
|
||||||
uint8_t inputKeyMaterial[32];
|
uint8_t inputKeyMaterial[32];
|
||||||
if (!i2p::context.GetNTCP2StaticKeys ().Agree (GetRemotePub (), inputKeyMaterial)) return false;
|
i2p::context.GetNTCP2StaticKeys ().Agree (GetRemotePub (), inputKeyMaterial);
|
||||||
MixKey (inputKeyMaterial);
|
MixKey (inputKeyMaterial);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NTCP2Establisher::KDF3Bob ()
|
void NTCP2Establisher::KDF3Bob ()
|
||||||
{
|
{
|
||||||
uint8_t inputKeyMaterial[32];
|
uint8_t inputKeyMaterial[32];
|
||||||
if (!m_EphemeralKeys->Agree (m_RemoteStaticKey, inputKeyMaterial)) return false;
|
m_EphemeralKeys->Agree (m_RemoteStaticKey, inputKeyMaterial);
|
||||||
MixKey (inputKeyMaterial);
|
MixKey (inputKeyMaterial);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void NTCP2Establisher::CreateEphemeralKey ()
|
void NTCP2Establisher::CreateEphemeralKey ()
|
||||||
@@ -111,7 +108,7 @@ namespace transport
|
|||||||
m_EphemeralKeys = i2p::transport::transports.GetNextX25519KeysPair ();
|
m_EphemeralKeys = i2p::transport::transports.GetNextX25519KeysPair ();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NTCP2Establisher::CreateSessionRequestMessage (std::mt19937& rng)
|
void NTCP2Establisher::CreateSessionRequestMessage (std::mt19937& rng)
|
||||||
{
|
{
|
||||||
// create buffer and fill padding
|
// create buffer and fill padding
|
||||||
auto paddingLength = rng () % (NTCP2_SESSION_REQUEST_MAX_SIZE - 64); // message length doesn't exceed 287 bytes
|
auto paddingLength = rng () % (NTCP2_SESSION_REQUEST_MAX_SIZE - 64); // message length doesn't exceed 287 bytes
|
||||||
@@ -124,7 +121,7 @@ namespace transport
|
|||||||
encryption.Encrypt (GetPub (), 32, m_SessionRequestBuffer); // X
|
encryption.Encrypt (GetPub (), 32, m_SessionRequestBuffer); // X
|
||||||
encryption.GetIV (m_IV); // save IV for SessionCreated
|
encryption.GetIV (m_IV); // save IV for SessionCreated
|
||||||
// encryption key for next block
|
// encryption key for next block
|
||||||
if (!KDF1Alice ()) return false;
|
KDF1Alice ();
|
||||||
// fill options
|
// fill options
|
||||||
uint8_t options[32]; // actual options size is 16 bytes
|
uint8_t options[32]; // actual options size is 16 bytes
|
||||||
memset (options, 0, 16);
|
memset (options, 0, 16);
|
||||||
@@ -150,10 +147,9 @@ namespace transport
|
|||||||
uint8_t nonce[12];
|
uint8_t nonce[12];
|
||||||
memset (nonce, 0, 12); // set nonce to zero
|
memset (nonce, 0, 12); // set nonce to zero
|
||||||
i2p::crypto::AEADChaCha20Poly1305 (options, 16, GetH (), 32, GetK (), nonce, m_SessionRequestBuffer + 32, 32, true); // encrypt
|
i2p::crypto::AEADChaCha20Poly1305 (options, 16, GetH (), 32, GetK (), nonce, m_SessionRequestBuffer + 32, 32, true); // encrypt
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NTCP2Establisher::CreateSessionCreatedMessage (std::mt19937& rng)
|
void NTCP2Establisher::CreateSessionCreatedMessage (std::mt19937& rng)
|
||||||
{
|
{
|
||||||
auto paddingLen = rng () % (NTCP2_SESSION_CREATED_MAX_SIZE - 64);
|
auto paddingLen = rng () % (NTCP2_SESSION_CREATED_MAX_SIZE - 64);
|
||||||
m_SessionCreatedBufferLen = paddingLen + 64;
|
m_SessionCreatedBufferLen = paddingLen + 64;
|
||||||
@@ -164,7 +160,7 @@ namespace transport
|
|||||||
encryption.SetIV (m_IV);
|
encryption.SetIV (m_IV);
|
||||||
encryption.Encrypt (GetPub (), 32, m_SessionCreatedBuffer); // Y
|
encryption.Encrypt (GetPub (), 32, m_SessionCreatedBuffer); // Y
|
||||||
// encryption key for next block (m_K)
|
// encryption key for next block (m_K)
|
||||||
if (!KDF2Bob ()) return false;
|
KDF2Bob ();
|
||||||
uint8_t options[16];
|
uint8_t options[16];
|
||||||
memset (options, 0, 16);
|
memset (options, 0, 16);
|
||||||
htobe16buf (options + 2, paddingLen); // padLen
|
htobe16buf (options + 2, paddingLen); // padLen
|
||||||
@@ -173,7 +169,7 @@ namespace transport
|
|||||||
uint8_t nonce[12];
|
uint8_t nonce[12];
|
||||||
memset (nonce, 0, 12); // set nonce to zero
|
memset (nonce, 0, 12); // set nonce to zero
|
||||||
i2p::crypto::AEADChaCha20Poly1305 (options, 16, GetH (), 32, GetK (), nonce, m_SessionCreatedBuffer + 32, 32, true); // encrypt
|
i2p::crypto::AEADChaCha20Poly1305 (options, 16, GetH (), 32, GetK (), nonce, m_SessionCreatedBuffer + 32, 32, true); // encrypt
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void NTCP2Establisher::CreateSessionConfirmedMessagePart1 (const uint8_t * nonce)
|
void NTCP2Establisher::CreateSessionConfirmedMessagePart1 (const uint8_t * nonce)
|
||||||
@@ -188,18 +184,17 @@ namespace transport
|
|||||||
i2p::crypto::AEADChaCha20Poly1305 (i2p::context.GetNTCP2StaticPublicKey (), 32, GetH (), 32, GetK (), nonce, m_SessionConfirmedBuffer, 48, true); // encrypt
|
i2p::crypto::AEADChaCha20Poly1305 (i2p::context.GetNTCP2StaticPublicKey (), 32, GetH (), 32, GetK (), nonce, m_SessionConfirmedBuffer, 48, true); // encrypt
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NTCP2Establisher::CreateSessionConfirmedMessagePart2 (const uint8_t * nonce)
|
void NTCP2Establisher::CreateSessionConfirmedMessagePart2 (const uint8_t * nonce)
|
||||||
{
|
{
|
||||||
// part 2
|
// part 2
|
||||||
// update AD again
|
// update AD again
|
||||||
MixHash (m_SessionConfirmedBuffer, 48);
|
MixHash (m_SessionConfirmedBuffer, 48);
|
||||||
// encrypt m3p2, it must be filled in SessionRequest
|
// encrypt m3p2, it must be filled in SessionRequest
|
||||||
if (!KDF3Alice ()) return false;
|
KDF3Alice ();
|
||||||
uint8_t * m3p2 = m_SessionConfirmedBuffer + 48;
|
uint8_t * m3p2 = m_SessionConfirmedBuffer + 48;
|
||||||
i2p::crypto::AEADChaCha20Poly1305 (m3p2, m3p2Len - 16, GetH (), 32, GetK (), nonce, m3p2, m3p2Len, true); // encrypt
|
i2p::crypto::AEADChaCha20Poly1305 (m3p2, m3p2Len - 16, GetH (), 32, GetK (), nonce, m3p2, m3p2Len, true); // encrypt
|
||||||
// update h again
|
// update h again
|
||||||
MixHash (m3p2, m3p2Len); //h = SHA256(h || ciphertext)
|
MixHash (m3p2, m3p2Len); //h = SHA256(h || ciphertext)
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool NTCP2Establisher::ProcessSessionRequestMessage (uint16_t& paddingLen, bool& clockSkew)
|
bool NTCP2Establisher::ProcessSessionRequestMessage (uint16_t& paddingLen, bool& clockSkew)
|
||||||
@@ -212,11 +207,7 @@ namespace transport
|
|||||||
decryption.Decrypt (m_SessionRequestBuffer, 32, GetRemotePub ());
|
decryption.Decrypt (m_SessionRequestBuffer, 32, GetRemotePub ());
|
||||||
decryption.GetIV (m_IV); // save IV for SessionCreated
|
decryption.GetIV (m_IV); // save IV for SessionCreated
|
||||||
// decryption key for next block
|
// decryption key for next block
|
||||||
if (!KDF1Bob ())
|
KDF1Bob ();
|
||||||
{
|
|
||||||
LogPrint (eLogWarning, "NTCP2: SessionRequest KDF failed");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// verify MAC and decrypt options block (32 bytes), use m_H as AD
|
// verify MAC and decrypt options block (32 bytes), use m_H as AD
|
||||||
uint8_t nonce[12], options[16];
|
uint8_t nonce[12], options[16];
|
||||||
memset (nonce, 0, 12); // set nonce to zero
|
memset (nonce, 0, 12); // set nonce to zero
|
||||||
@@ -271,11 +262,7 @@ namespace transport
|
|||||||
decryption.SetIV (m_IV);
|
decryption.SetIV (m_IV);
|
||||||
decryption.Decrypt (m_SessionCreatedBuffer, 32, GetRemotePub ());
|
decryption.Decrypt (m_SessionCreatedBuffer, 32, GetRemotePub ());
|
||||||
// decryption key for next block (m_K)
|
// decryption key for next block (m_K)
|
||||||
if (!KDF2Alice ())
|
KDF2Alice ();
|
||||||
{
|
|
||||||
LogPrint (eLogWarning, "NTCP2: SessionCreated KDF failed");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// decrypt and verify MAC
|
// decrypt and verify MAC
|
||||||
uint8_t payload[16];
|
uint8_t payload[16];
|
||||||
uint8_t nonce[12];
|
uint8_t nonce[12];
|
||||||
@@ -322,11 +309,7 @@ namespace transport
|
|||||||
// update AD again
|
// update AD again
|
||||||
MixHash (m_SessionConfirmedBuffer, 48);
|
MixHash (m_SessionConfirmedBuffer, 48);
|
||||||
|
|
||||||
if (!KDF3Bob ())
|
KDF3Bob ();
|
||||||
{
|
|
||||||
LogPrint (eLogWarning, "NTCP2: SessionConfirmed Part2 KDF failed");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (i2p::crypto::AEADChaCha20Poly1305 (m_SessionConfirmedBuffer + 48, m3p2Len - 16, GetH (), 32, GetK (), nonce, m3p2Buf, m3p2Len - 16, false)) // decrypt
|
if (i2p::crypto::AEADChaCha20Poly1305 (m_SessionConfirmedBuffer + 48, m3p2Len - 16, GetH (), 32, GetK (), nonce, m3p2Buf, m3p2Len - 16, false)) // decrypt
|
||||||
// calculate new h again for KDF data
|
// calculate new h again for KDF data
|
||||||
MixHash (m_SessionConfirmedBuffer + 48, m3p2Len); // h = SHA256(h || ciphertext)
|
MixHash (m_SessionConfirmedBuffer + 48, m3p2Len); // h = SHA256(h || ciphertext)
|
||||||
@@ -344,7 +327,6 @@ namespace transport
|
|||||||
m_Server (server), m_Socket (m_Server.GetService ()),
|
m_Server (server), m_Socket (m_Server.GetService ()),
|
||||||
m_IsEstablished (false), m_IsTerminated (false),
|
m_IsEstablished (false), m_IsTerminated (false),
|
||||||
m_Establisher (new NTCP2Establisher),
|
m_Establisher (new NTCP2Establisher),
|
||||||
m_SendKey (nullptr), m_ReceiveKey (nullptr),
|
|
||||||
#if OPENSSL_SIPHASH
|
#if OPENSSL_SIPHASH
|
||||||
m_SendMDCtx(nullptr), m_ReceiveMDCtx (nullptr),
|
m_SendMDCtx(nullptr), m_ReceiveMDCtx (nullptr),
|
||||||
#else
|
#else
|
||||||
@@ -484,12 +466,7 @@ namespace transport
|
|||||||
|
|
||||||
void NTCP2Session::SendSessionRequest ()
|
void NTCP2Session::SendSessionRequest ()
|
||||||
{
|
{
|
||||||
if (!m_Establisher->CreateSessionRequestMessage (m_Server.GetRng ()))
|
m_Establisher->CreateSessionRequestMessage (m_Server.GetRng ());
|
||||||
{
|
|
||||||
LogPrint (eLogWarning, "NTCP2: Send SessionRequest KDF failed");
|
|
||||||
boost::asio::post (m_Server.GetService (), std::bind (&NTCP2Session::Terminate, shared_from_this ()));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// send message
|
// send message
|
||||||
m_HandshakeInterval = i2p::util::GetMillisecondsSinceEpoch ();
|
m_HandshakeInterval = i2p::util::GetMillisecondsSinceEpoch ();
|
||||||
boost::asio::async_write (m_Socket, boost::asio::buffer (m_Establisher->m_SessionRequestBuffer, m_Establisher->m_SessionRequestBufferLen), boost::asio::transfer_all (),
|
boost::asio::async_write (m_Socket, boost::asio::buffer (m_Establisher->m_SessionRequestBuffer, m_Establisher->m_SessionRequestBufferLen), boost::asio::transfer_all (),
|
||||||
@@ -581,12 +558,7 @@ namespace transport
|
|||||||
|
|
||||||
void NTCP2Session::SendSessionCreated ()
|
void NTCP2Session::SendSessionCreated ()
|
||||||
{
|
{
|
||||||
if (!m_Establisher->CreateSessionCreatedMessage (m_Server.GetRng ()))
|
m_Establisher->CreateSessionCreatedMessage (m_Server.GetRng ());
|
||||||
{
|
|
||||||
LogPrint (eLogWarning, "NTCP2: Send SessionCreated KDF failed");
|
|
||||||
boost::asio::post (m_Server.GetService (), std::bind (&NTCP2Session::Terminate, shared_from_this ()));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// send message
|
// send message
|
||||||
m_HandshakeInterval = i2p::util::GetMillisecondsSinceEpoch ();
|
m_HandshakeInterval = i2p::util::GetMillisecondsSinceEpoch ();
|
||||||
boost::asio::async_write (m_Socket, boost::asio::buffer (m_Establisher->m_SessionCreatedBuffer, m_Establisher->m_SessionCreatedBufferLen), boost::asio::transfer_all (),
|
boost::asio::async_write (m_Socket, boost::asio::buffer (m_Establisher->m_SessionCreatedBuffer, m_Establisher->m_SessionCreatedBufferLen), boost::asio::transfer_all (),
|
||||||
@@ -665,12 +637,7 @@ namespace transport
|
|||||||
CreateNonce (1, nonce); // set nonce to 1
|
CreateNonce (1, nonce); // set nonce to 1
|
||||||
m_Establisher->CreateSessionConfirmedMessagePart1 (nonce);
|
m_Establisher->CreateSessionConfirmedMessagePart1 (nonce);
|
||||||
memset (nonce, 0, 12); // set nonce back to 0
|
memset (nonce, 0, 12); // set nonce back to 0
|
||||||
if (!m_Establisher->CreateSessionConfirmedMessagePart2 (nonce))
|
m_Establisher->CreateSessionConfirmedMessagePart2 (nonce);
|
||||||
{
|
|
||||||
LogPrint (eLogWarning, "NTCP2: Send SessionConfirmed Part2 KDF failed");
|
|
||||||
boost::asio::post (m_Server.GetService (), std::bind (&NTCP2Session::Terminate, shared_from_this ()));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// send message
|
// send message
|
||||||
boost::asio::async_write (m_Socket, boost::asio::buffer (m_Establisher->m_SessionConfirmedBuffer, m_Establisher->m3p2Len + 48), boost::asio::transfer_all (),
|
boost::asio::async_write (m_Socket, boost::asio::buffer (m_Establisher->m_SessionConfirmedBuffer, m_Establisher->m3p2Len + 48), boost::asio::transfer_all (),
|
||||||
std::bind(&NTCP2Session::HandleSessionConfirmedSent, shared_from_this (), std::placeholders::_1, std::placeholders::_2));
|
std::bind(&NTCP2Session::HandleSessionConfirmedSent, shared_from_this (), std::placeholders::_1, std::placeholders::_2));
|
||||||
@@ -722,7 +689,6 @@ namespace transport
|
|||||||
|
|
||||||
void NTCP2Session::HandleSessionConfirmedReceived (const boost::system::error_code& ecode, std::size_t bytes_transferred)
|
void NTCP2Session::HandleSessionConfirmedReceived (const boost::system::error_code& ecode, std::size_t bytes_transferred)
|
||||||
{
|
{
|
||||||
(void) bytes_transferred;
|
|
||||||
if (ecode)
|
if (ecode)
|
||||||
{
|
{
|
||||||
LogPrint (eLogWarning, "NTCP2: SessionConfirmed read error: ", ecode.message ());
|
LogPrint (eLogWarning, "NTCP2: SessionConfirmed read error: ", ecode.message ());
|
||||||
@@ -731,17 +697,6 @@ namespace transport
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_HandshakeInterval = i2p::util::GetMillisecondsSinceEpoch () - m_HandshakeInterval;
|
m_HandshakeInterval = i2p::util::GetMillisecondsSinceEpoch () - m_HandshakeInterval;
|
||||||
boost::asio::post (m_Server.GetEstablisherService (),
|
|
||||||
[s = shared_from_this ()] ()
|
|
||||||
{
|
|
||||||
s->ProcessSessionConfirmed ();;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void NTCP2Session::ProcessSessionConfirmed ()
|
|
||||||
{
|
|
||||||
// run on establisher thread
|
|
||||||
LogPrint (eLogDebug, "NTCP2: SessionConfirmed received");
|
LogPrint (eLogDebug, "NTCP2: SessionConfirmed received");
|
||||||
// part 1
|
// part 1
|
||||||
uint8_t nonce[12];
|
uint8_t nonce[12];
|
||||||
@@ -749,41 +704,10 @@ namespace transport
|
|||||||
if (m_Establisher->ProcessSessionConfirmedMessagePart1 (nonce))
|
if (m_Establisher->ProcessSessionConfirmedMessagePart1 (nonce))
|
||||||
{
|
{
|
||||||
// part 2
|
// part 2
|
||||||
auto buf = std::make_shared<std::vector<uint8_t> > (m_Establisher->m3p2Len - 16); // -MAC
|
std::vector<uint8_t> buf(m_Establisher->m3p2Len - 16); // -MAC
|
||||||
memset (nonce, 0, 12); // set nonce to 0 again
|
memset (nonce, 0, 12); // set nonce to 0 again
|
||||||
if (m_Establisher->ProcessSessionConfirmedMessagePart2 (nonce, buf->data ())) // TODO:handle in establisher thread
|
if (m_Establisher->ProcessSessionConfirmedMessagePart2 (nonce, buf.data ())) // TODO:handle in establisher thread
|
||||||
{
|
{
|
||||||
// payload
|
|
||||||
// RI block must be first
|
|
||||||
if ((*buf)[0] != eNTCP2BlkRouterInfo)
|
|
||||||
{
|
|
||||||
LogPrint (eLogWarning, "NTCP2: Unexpected block ", (int)(*buf)[0], " in SessionConfirmed");
|
|
||||||
boost::asio::post (m_Server.GetService (), std::bind (&NTCP2Session::Terminate, shared_from_this ()));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
auto size = bufbe16toh (buf->data () + 1);
|
|
||||||
if (size > buf->size () - 3 || size > i2p::data::MAX_RI_BUFFER_SIZE + 1)
|
|
||||||
{
|
|
||||||
LogPrint (eLogError, "NTCP2: Unexpected RouterInfo size ", size, " in SessionConfirmed");
|
|
||||||
boost::asio::post (m_Server.GetService (), std::bind (&NTCP2Session::Terminate, shared_from_this ()));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
boost::asio::post (m_Server.GetService (),
|
|
||||||
[s = shared_from_this (), buf, size] ()
|
|
||||||
{
|
|
||||||
s->EstablishSessionAfterSessionConfirmed (buf, size);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else
|
|
||||||
boost::asio::post (m_Server.GetService (), std::bind (&NTCP2Session::Terminate, shared_from_this ()));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
boost::asio::post (m_Server.GetService (), std::bind (&NTCP2Session::Terminate, shared_from_this ()));
|
|
||||||
}
|
|
||||||
|
|
||||||
void NTCP2Session::EstablishSessionAfterSessionConfirmed (std::shared_ptr<std::vector<uint8_t> > buf, size_t size)
|
|
||||||
{
|
|
||||||
// run on main NTCP2 thread
|
|
||||||
KeyDerivationFunctionDataPhase ();
|
KeyDerivationFunctionDataPhase ();
|
||||||
// Bob data phase keys
|
// Bob data phase keys
|
||||||
m_SendKey = m_Kba;
|
m_SendKey = m_Kba;
|
||||||
@@ -791,9 +715,23 @@ namespace transport
|
|||||||
SetSipKeys (m_Sipkeysba, m_Sipkeysab);
|
SetSipKeys (m_Sipkeysba, m_Sipkeysab);
|
||||||
memcpy (m_ReceiveIV.buf, m_Sipkeysab + 16, 8);
|
memcpy (m_ReceiveIV.buf, m_Sipkeysab + 16, 8);
|
||||||
memcpy (m_SendIV.buf, m_Sipkeysba + 16, 8);
|
memcpy (m_SendIV.buf, m_Sipkeysba + 16, 8);
|
||||||
// we need to set keys for SendTerminationAndTerminate
|
// payload
|
||||||
|
// process RI
|
||||||
|
if (buf[0] != eNTCP2BlkRouterInfo)
|
||||||
|
{
|
||||||
|
LogPrint (eLogWarning, "NTCP2: Unexpected block ", (int)buf[0], " in SessionConfirmed");
|
||||||
|
Terminate ();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto size = bufbe16toh (buf.data () + 1);
|
||||||
|
if (size > buf.size () - 3 || size > i2p::data::MAX_RI_BUFFER_SIZE + 1)
|
||||||
|
{
|
||||||
|
LogPrint (eLogError, "NTCP2: Unexpected RouterInfo size ", size, " in SessionConfirmed");
|
||||||
|
Terminate ();
|
||||||
|
return;
|
||||||
|
}
|
||||||
// TODO: check flag
|
// TODO: check flag
|
||||||
i2p::data::RouterInfo ri (buf->data () + 4, size - 1); // 1 byte block type + 2 bytes size + 1 byte flag
|
i2p::data::RouterInfo ri (buf.data () + 4, size - 1); // 1 byte block type + 2 bytes size + 1 byte flag
|
||||||
if (ri.IsUnreachable ())
|
if (ri.IsUnreachable ())
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "NTCP2: RouterInfo verification failed in SessionConfirmed from ", GetRemoteEndpoint ());
|
LogPrint (eLogError, "NTCP2: RouterInfo verification failed in SessionConfirmed from ", GetRemoteEndpoint ());
|
||||||
@@ -855,7 +793,7 @@ namespace transport
|
|||||||
SendTerminationAndTerminate (eNTCP2Banned);
|
SendTerminationAndTerminate (eNTCP2Banned);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// TODO: process options block
|
// TODO: process options
|
||||||
|
|
||||||
// ready to communicate
|
// ready to communicate
|
||||||
SetRemoteIdentity (ri1->GetRouterIdentity ());
|
SetRemoteIdentity (ri1->GetRouterIdentity ());
|
||||||
@@ -867,6 +805,13 @@ namespace transport
|
|||||||
else
|
else
|
||||||
Terminate ();
|
Terminate ();
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
Terminate ();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Terminate ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void NTCP2Session::SetSipKeys (const uint8_t * sendSipKey, const uint8_t * receiveSipKey)
|
void NTCP2Session::SetSipKeys (const uint8_t * sendSipKey, const uint8_t * receiveSipKey)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -95,21 +95,21 @@ namespace transport
|
|||||||
const uint8_t * GetCK () const { return m_CK; };
|
const uint8_t * GetCK () const { return m_CK; };
|
||||||
const uint8_t * GetH () const { return m_H; };
|
const uint8_t * GetH () const { return m_H; };
|
||||||
|
|
||||||
bool KDF1Alice ();
|
void KDF1Alice ();
|
||||||
bool KDF1Bob ();
|
void KDF1Bob ();
|
||||||
bool KDF2Alice ();
|
void KDF2Alice ();
|
||||||
bool KDF2Bob ();
|
void KDF2Bob ();
|
||||||
bool KDF3Alice (); // for SessionConfirmed part 2
|
void KDF3Alice (); // for SessionConfirmed part 2
|
||||||
bool KDF3Bob ();
|
void KDF3Bob ();
|
||||||
|
|
||||||
bool KeyDerivationFunction1 (const uint8_t * pub, i2p::crypto::X25519Keys& priv, const uint8_t * rs, const uint8_t * epub); // for SessionRequest, (pub, priv) for DH
|
void KeyDerivationFunction1 (const uint8_t * pub, i2p::crypto::X25519Keys& priv, const uint8_t * rs, const uint8_t * epub); // for SessionRequest, (pub, priv) for DH
|
||||||
bool KeyDerivationFunction2 (const uint8_t * sessionRequest, size_t sessionRequestLen, const uint8_t * epub); // for SessionCreate
|
void KeyDerivationFunction2 (const uint8_t * sessionRequest, size_t sessionRequestLen, const uint8_t * epub); // for SessionCreate
|
||||||
void CreateEphemeralKey ();
|
void CreateEphemeralKey ();
|
||||||
|
|
||||||
bool CreateSessionRequestMessage (std::mt19937& rng);
|
void CreateSessionRequestMessage (std::mt19937& rng);
|
||||||
bool CreateSessionCreatedMessage (std::mt19937& rng);
|
void CreateSessionCreatedMessage (std::mt19937& rng);
|
||||||
void CreateSessionConfirmedMessagePart1 (const uint8_t * nonce);
|
void CreateSessionConfirmedMessagePart1 (const uint8_t * nonce);
|
||||||
bool CreateSessionConfirmedMessagePart2 (const uint8_t * nonce);
|
void CreateSessionConfirmedMessagePart2 (const uint8_t * nonce);
|
||||||
|
|
||||||
bool ProcessSessionRequestMessage (uint16_t& paddingLen, bool& clockSkew);
|
bool ProcessSessionRequestMessage (uint16_t& paddingLen, bool& clockSkew);
|
||||||
bool ProcessSessionCreatedMessage (uint16_t& paddingLen);
|
bool ProcessSessionCreatedMessage (uint16_t& paddingLen);
|
||||||
@@ -180,8 +180,6 @@ namespace transport
|
|||||||
void HandleSessionCreatedPaddingReceived (const boost::system::error_code& ecode, std::size_t bytes_transferred);
|
void HandleSessionCreatedPaddingReceived (const boost::system::error_code& ecode, std::size_t bytes_transferred);
|
||||||
void HandleSessionConfirmedSent (const boost::system::error_code& ecode, std::size_t bytes_transferred);
|
void HandleSessionConfirmedSent (const boost::system::error_code& ecode, std::size_t bytes_transferred);
|
||||||
void HandleSessionConfirmedReceived (const boost::system::error_code& ecode, std::size_t bytes_transferred);
|
void HandleSessionConfirmedReceived (const boost::system::error_code& ecode, std::size_t bytes_transferred);
|
||||||
void ProcessSessionConfirmed ();
|
|
||||||
void EstablishSessionAfterSessionConfirmed (std::shared_ptr<std::vector<uint8_t> > buf, size_t size);
|
|
||||||
|
|
||||||
// data
|
// data
|
||||||
void ReceiveLength ();
|
void ReceiveLength ();
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ namespace stream
|
|||||||
m_LastConfirmedReceivedSequenceNumber (0), // for limit inbound speed
|
m_LastConfirmedReceivedSequenceNumber (0), // for limit inbound speed
|
||||||
m_Status (eStreamStatusNew), m_IsIncoming (false), m_IsAckSendScheduled (false), m_IsNAcked (false), m_IsFirstACK (false),
|
m_Status (eStreamStatusNew), m_IsIncoming (false), m_IsAckSendScheduled (false), m_IsNAcked (false), m_IsFirstACK (false),
|
||||||
m_IsResendNeeded (false), m_IsFirstRttSample (false), m_IsSendTime (true), m_IsWinDropped (false),
|
m_IsResendNeeded (false), m_IsFirstRttSample (false), m_IsSendTime (true), m_IsWinDropped (false),
|
||||||
m_IsTimeOutResend (false), m_IsImmediateAckRequested (false), m_IsRemoteLeaseChangeInProgress (false), m_DoubleWinIncCounter (false), m_LocalDestination (local),
|
m_IsTimeOutResend (false), m_IsImmediateAckRequested (false), m_IsRemoteLeaseChangeInProgress (false), m_LocalDestination (local),
|
||||||
m_RemoteLeaseSet (remote), m_ReceiveTimer (m_Service), m_SendTimer (m_Service), m_ResendTimer (m_Service),
|
m_RemoteLeaseSet (remote), m_ReceiveTimer (m_Service), m_SendTimer (m_Service), m_ResendTimer (m_Service),
|
||||||
m_AckSendTimer (m_Service), m_NumSentBytes (0), m_NumReceivedBytes (0), m_Port (port),
|
m_AckSendTimer (m_Service), m_NumSentBytes (0), m_NumReceivedBytes (0), m_Port (port),
|
||||||
m_RTT (INITIAL_RTT), m_SlowRTT (INITIAL_RTT), m_SlowRTT2 (INITIAL_RTT), m_WindowSize (INITIAL_WINDOW_SIZE), m_LastWindowDropSize (0),
|
m_RTT (INITIAL_RTT), m_SlowRTT (INITIAL_RTT), m_SlowRTT2 (INITIAL_RTT), m_WindowSize (INITIAL_WINDOW_SIZE), m_LastWindowDropSize (0),
|
||||||
@@ -101,7 +101,7 @@ namespace stream
|
|||||||
m_LastConfirmedReceivedSequenceNumber (0), // for limit inbound speed
|
m_LastConfirmedReceivedSequenceNumber (0), // for limit inbound speed
|
||||||
m_Status (eStreamStatusNew), m_IsIncoming (true), m_IsAckSendScheduled (false), m_IsNAcked (false), m_IsFirstACK (false),
|
m_Status (eStreamStatusNew), m_IsIncoming (true), m_IsAckSendScheduled (false), m_IsNAcked (false), m_IsFirstACK (false),
|
||||||
m_IsResendNeeded (false), m_IsFirstRttSample (false), m_IsSendTime (true), m_IsWinDropped (false),
|
m_IsResendNeeded (false), m_IsFirstRttSample (false), m_IsSendTime (true), m_IsWinDropped (false),
|
||||||
m_IsTimeOutResend (false), m_IsImmediateAckRequested (false), m_IsRemoteLeaseChangeInProgress (false), m_DoubleWinIncCounter (false), m_LocalDestination (local),
|
m_IsTimeOutResend (false), m_IsImmediateAckRequested (false), m_IsRemoteLeaseChangeInProgress (false), m_LocalDestination (local),
|
||||||
m_ReceiveTimer (m_Service), m_SendTimer (m_Service), m_ResendTimer (m_Service), m_AckSendTimer (m_Service),
|
m_ReceiveTimer (m_Service), m_SendTimer (m_Service), m_ResendTimer (m_Service), m_AckSendTimer (m_Service),
|
||||||
m_NumSentBytes (0), m_NumReceivedBytes (0), m_Port (0), m_RTT (INITIAL_RTT), m_SlowRTT (INITIAL_RTT), m_SlowRTT2 (INITIAL_RTT),
|
m_NumSentBytes (0), m_NumReceivedBytes (0), m_Port (0), m_RTT (INITIAL_RTT), m_SlowRTT (INITIAL_RTT), m_SlowRTT2 (INITIAL_RTT),
|
||||||
m_WindowSize (INITIAL_WINDOW_SIZE), m_LastWindowDropSize (0), m_WindowDropTargetSize (0), m_WindowIncCounter (0),
|
m_WindowSize (INITIAL_WINDOW_SIZE), m_LastWindowDropSize (0), m_WindowDropTargetSize (0), m_WindowIncCounter (0),
|
||||||
@@ -495,7 +495,6 @@ namespace stream
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
int rttSample = INT_MAX;
|
int rttSample = INT_MAX;
|
||||||
int incCounter = 0;
|
|
||||||
m_IsNAcked = false;
|
m_IsNAcked = false;
|
||||||
m_IsResendNeeded = false;
|
m_IsResendNeeded = false;
|
||||||
int nackCount = packet->GetNACKCount ();
|
int nackCount = packet->GetNACKCount ();
|
||||||
@@ -538,7 +537,8 @@ namespace stream
|
|||||||
m_LocalDestination.DeletePacket (sentPacket);
|
m_LocalDestination.DeletePacket (sentPacket);
|
||||||
acknowledged = true;
|
acknowledged = true;
|
||||||
if (m_WindowSize < MAX_WINDOW_SIZE && !m_IsFirstACK)
|
if (m_WindowSize < MAX_WINDOW_SIZE && !m_IsFirstACK)
|
||||||
incCounter++;
|
if (m_RTT < m_LocalDestination.GetRandom () % INITIAL_RTO) // dirty
|
||||||
|
m_WindowIncCounter++;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
@@ -552,7 +552,7 @@ namespace stream
|
|||||||
m_SlowRTT2 = rttSample;
|
m_SlowRTT2 = rttSample;
|
||||||
m_PrevRTTSample = rttSample;
|
m_PrevRTTSample = rttSample;
|
||||||
m_Jitter = rttSample / 10; // 10%
|
m_Jitter = rttSample / 10; // 10%
|
||||||
m_Jitter += 15; // for low-latency connections
|
m_Jitter += 5; // for low-latency connections
|
||||||
m_IsFirstRttSample = false;
|
m_IsFirstRttSample = false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -569,23 +569,9 @@ namespace stream
|
|||||||
jitter = m_PrevRTTSample - rttSample;
|
jitter = m_PrevRTTSample - rttSample;
|
||||||
else
|
else
|
||||||
jitter = rttSample / 10; // 10%
|
jitter = rttSample / 10; // 10%
|
||||||
jitter += 15; // for low-latency connections
|
jitter += 5; // for low-latency connections
|
||||||
m_Jitter = (0.05 * jitter) + (1.0 - 0.05) * m_Jitter;
|
m_Jitter = (0.05 * jitter) + (1.0 - 0.05) * m_Jitter;
|
||||||
}
|
}
|
||||||
if (rttSample > m_SlowRTT)
|
|
||||||
{
|
|
||||||
incCounter = 0;
|
|
||||||
m_DoubleWinIncCounter = 1;
|
|
||||||
}
|
|
||||||
else if (rttSample < m_SlowRTT)
|
|
||||||
{
|
|
||||||
if (m_DoubleWinIncCounter)
|
|
||||||
{
|
|
||||||
incCounter = incCounter * 2;
|
|
||||||
m_DoubleWinIncCounter = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
m_WindowIncCounter = m_WindowIncCounter + incCounter;
|
|
||||||
//
|
//
|
||||||
// delay-based CC
|
// delay-based CC
|
||||||
if ((m_SlowRTT2 > m_SlowRTT + m_Jitter && rttSample > m_SlowRTT2 && rttSample > m_PrevRTTSample) && !m_IsWinDropped) // Drop window if RTT grows too fast, late detection
|
if ((m_SlowRTT2 > m_SlowRTT + m_Jitter && rttSample > m_SlowRTT2 && rttSample > m_PrevRTTSample) && !m_IsWinDropped) // Drop window if RTT grows too fast, late detection
|
||||||
@@ -1311,6 +1297,8 @@ namespace stream
|
|||||||
else if (m_IsResendNeeded) // resend packets
|
else if (m_IsResendNeeded) // resend packets
|
||||||
ResendPacket ();
|
ResendPacket ();
|
||||||
// delay-based CC
|
// delay-based CC
|
||||||
|
else if (!m_IsWinDropped && int(m_SentPackets.size ()) == m_WindowSize) // we sending packets too fast, early detection
|
||||||
|
ProcessWindowDrop ();
|
||||||
else if (m_WindowSize > int(m_SentPackets.size ())) // send packets
|
else if (m_WindowSize > int(m_SentPackets.size ())) // send packets
|
||||||
SendBuffer ();
|
SendBuffer ();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,6 @@
|
|||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <boost/asio.hpp>
|
#include <boost/asio.hpp>
|
||||||
#include "Base.h"
|
#include "Base.h"
|
||||||
#include "Gzip.h"
|
|
||||||
#include "I2PEndian.h"
|
#include "I2PEndian.h"
|
||||||
#include "Identity.h"
|
#include "Identity.h"
|
||||||
#include "LeaseSet.h"
|
#include "LeaseSet.h"
|
||||||
@@ -55,7 +54,7 @@ namespace stream
|
|||||||
const size_t COMPRESSION_THRESHOLD_SIZE = 66;
|
const size_t COMPRESSION_THRESHOLD_SIZE = 66;
|
||||||
const int MAX_NUM_RESEND_ATTEMPTS = 10;
|
const int MAX_NUM_RESEND_ATTEMPTS = 10;
|
||||||
const int INITIAL_WINDOW_SIZE = 10;
|
const int INITIAL_WINDOW_SIZE = 10;
|
||||||
const int MIN_WINDOW_SIZE = 3;
|
const int MIN_WINDOW_SIZE = 2;
|
||||||
const int MAX_WINDOW_SIZE = 512;
|
const int MAX_WINDOW_SIZE = 512;
|
||||||
const double RTT_EWMA_ALPHA = 0.25;
|
const double RTT_EWMA_ALPHA = 0.25;
|
||||||
const double SLOWRTT_EWMA_ALPHA = 0.05;
|
const double SLOWRTT_EWMA_ALPHA = 0.05;
|
||||||
@@ -275,7 +274,6 @@ namespace stream
|
|||||||
bool m_IsTimeOutResend;
|
bool m_IsTimeOutResend;
|
||||||
bool m_IsImmediateAckRequested;
|
bool m_IsImmediateAckRequested;
|
||||||
bool m_IsRemoteLeaseChangeInProgress;
|
bool m_IsRemoteLeaseChangeInProgress;
|
||||||
bool m_DoubleWinIncCounter;
|
|
||||||
StreamingDestination& m_LocalDestination;
|
StreamingDestination& m_LocalDestination;
|
||||||
std::shared_ptr<const i2p::data::IdentityEx> m_RemoteIdentity;
|
std::shared_ptr<const i2p::data::IdentityEx> m_RemoteIdentity;
|
||||||
std::shared_ptr<const i2p::crypto::Verifier> m_TransientVerifier; // in case of offline key
|
std::shared_ptr<const i2p::crypto::Verifier> m_TransientVerifier; // in case of offline key
|
||||||
|
|||||||
@@ -375,10 +375,10 @@ namespace client
|
|||||||
}
|
}
|
||||||
|
|
||||||
I2PServerTunnelConnectionHTTP::I2PServerTunnelConnectionHTTP (I2PService * owner, std::shared_ptr<i2p::stream::Stream> stream,
|
I2PServerTunnelConnectionHTTP::I2PServerTunnelConnectionHTTP (I2PService * owner, std::shared_ptr<i2p::stream::Stream> stream,
|
||||||
const boost::asio::ip::tcp::endpoint& target, const std::string& host, const std::string& XI2P,
|
const boost::asio::ip::tcp::endpoint& target, const std::string& host,
|
||||||
std::shared_ptr<boost::asio::ssl::context> sslCtx):
|
std::shared_ptr<boost::asio::ssl::context> sslCtx):
|
||||||
I2PTunnelConnection (owner, stream, target, true, sslCtx), m_Host (host), m_XI2P (XI2P),
|
I2PTunnelConnection (owner, stream, target, true, sslCtx), m_Host (host),
|
||||||
m_HeaderSent (false), m_ResponseHeaderSent (false)
|
m_HeaderSent (false), m_ResponseHeaderSent (false), m_From (stream->GetRemoteIdentity ())
|
||||||
{
|
{
|
||||||
if (sslCtx)
|
if (sslCtx)
|
||||||
SSL_set_tlsext_host_name(GetSSL ()->native_handle(), host.c_str ());
|
SSL_set_tlsext_host_name(GetSSL ()->native_handle(), host.c_str ());
|
||||||
@@ -448,12 +448,17 @@ namespace client
|
|||||||
if (!connection)
|
if (!connection)
|
||||||
m_OutHeader << "Connection: close\r\n";
|
m_OutHeader << "Connection: close\r\n";
|
||||||
// add X-I2P fields
|
// add X-I2P fields
|
||||||
m_OutHeader << m_XI2P;
|
if (m_From)
|
||||||
// end of header
|
{
|
||||||
m_OutHeader << "\r\n";
|
m_OutHeader << X_I2P_DEST_B32 << ": " << context.GetAddressBook ().ToAddress(m_From->GetIdentHash ()) << "\r\n";
|
||||||
|
m_OutHeader << X_I2P_DEST_HASH << ": " << m_From->GetIdentHash ().ToBase64 () << "\r\n";
|
||||||
|
m_OutHeader << X_I2P_DEST_B64 << ": " << m_From->ToBase64 () << "\r\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
m_OutHeader << "\r\n"; // end of header
|
||||||
m_OutHeader << m_InHeader.str ().substr (m_InHeader.tellg ()); // data right after header
|
m_OutHeader << m_InHeader.str ().substr (m_InHeader.tellg ()); // data right after header
|
||||||
m_InHeader.str ("");
|
m_InHeader.str ("");
|
||||||
|
m_From = nullptr;
|
||||||
m_HeaderSent = true;
|
m_HeaderSent = true;
|
||||||
I2PTunnelConnection::Write ((uint8_t *)m_OutHeader.str ().c_str (), m_OutHeader.str ().length ());
|
I2PTunnelConnection::Write ((uint8_t *)m_OutHeader.str ().c_str (), m_OutHeader.str ().length ());
|
||||||
}
|
}
|
||||||
@@ -871,17 +876,7 @@ namespace client
|
|||||||
|
|
||||||
std::shared_ptr<I2PTunnelConnection> I2PServerTunnelHTTP::CreateI2PConnection (std::shared_ptr<i2p::stream::Stream> stream)
|
std::shared_ptr<I2PTunnelConnection> I2PServerTunnelHTTP::CreateI2PConnection (std::shared_ptr<i2p::stream::Stream> stream)
|
||||||
{
|
{
|
||||||
if (m_XI2P.empty () || stream->GetRemoteIdentity () != m_From.lock ())
|
return std::make_shared<I2PServerTunnelConnectionHTTP> (this, stream, GetEndpoint (), m_Host, GetSSLCtx ());
|
||||||
{
|
|
||||||
auto from = stream->GetRemoteIdentity ();
|
|
||||||
m_From = from;
|
|
||||||
std::stringstream ss;
|
|
||||||
ss << X_I2P_DEST_B32 << ": " << context.GetAddressBook ().ToAddress(from->GetIdentHash ()) << "\r\n";
|
|
||||||
ss << X_I2P_DEST_HASH << ": " << from->GetIdentHash ().ToBase64 () << "\r\n";
|
|
||||||
ss << X_I2P_DEST_B64 << ": " << from->ToBase64 () << "\r\n";
|
|
||||||
m_XI2P = ss.str ();
|
|
||||||
}
|
|
||||||
return std::make_shared<I2PServerTunnelConnectionHTTP> (this, stream, GetEndpoint (), m_Host, m_XI2P, GetSSLCtx ());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
I2PServerTunnelIRC::I2PServerTunnelIRC (const std::string& name, const std::string& address,
|
I2PServerTunnelIRC::I2PServerTunnelIRC (const std::string& name, const std::string& address,
|
||||||
|
|||||||
@@ -31,9 +31,9 @@ namespace client
|
|||||||
const int I2P_TUNNEL_CONNECTION_MAX_IDLE = 3600; // in seconds
|
const int I2P_TUNNEL_CONNECTION_MAX_IDLE = 3600; // in seconds
|
||||||
const int I2P_TUNNEL_DESTINATION_REQUEST_TIMEOUT = 10; // in seconds
|
const int I2P_TUNNEL_DESTINATION_REQUEST_TIMEOUT = 10; // in seconds
|
||||||
// for HTTP tunnels
|
// for HTTP tunnels
|
||||||
constexpr char X_I2P_DEST_HASH[] = "X-I2P-DestHash"; // hash in base64
|
const char X_I2P_DEST_HASH[] = "X-I2P-DestHash"; // hash in base64
|
||||||
constexpr char X_I2P_DEST_B64[] = "X-I2P-DestB64"; // full address in base64
|
const char X_I2P_DEST_B64[] = "X-I2P-DestB64"; // full address in base64
|
||||||
constexpr char X_I2P_DEST_B32[] = "X-I2P-DestB32"; // .b32.i2p address
|
const char X_I2P_DEST_B32[] = "X-I2P-DestB32"; // .b32.i2p address
|
||||||
const int I2P_TUNNEL_HTTP_MAX_HEADER_SIZE = 8192;
|
const int I2P_TUNNEL_HTTP_MAX_HEADER_SIZE = 8192;
|
||||||
|
|
||||||
class I2PTunnelConnection: public I2PServiceHandler, public std::enable_shared_from_this<I2PTunnelConnection>
|
class I2PTunnelConnection: public I2PServiceHandler, public std::enable_shared_from_this<I2PTunnelConnection>
|
||||||
@@ -107,7 +107,7 @@ namespace client
|
|||||||
public:
|
public:
|
||||||
|
|
||||||
I2PServerTunnelConnectionHTTP (I2PService * owner, std::shared_ptr<i2p::stream::Stream> stream,
|
I2PServerTunnelConnectionHTTP (I2PService * owner, std::shared_ptr<i2p::stream::Stream> stream,
|
||||||
const boost::asio::ip::tcp::endpoint& target, const std::string& host, const std::string& XI2P,
|
const boost::asio::ip::tcp::endpoint& target, const std::string& host,
|
||||||
std::shared_ptr<boost::asio::ssl::context> sslCtx = nullptr);
|
std::shared_ptr<boost::asio::ssl::context> sslCtx = nullptr);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
@@ -117,9 +117,10 @@ namespace client
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
std::string m_Host, m_XI2P;
|
std::string m_Host;
|
||||||
std::stringstream m_InHeader, m_OutHeader;
|
std::stringstream m_InHeader, m_OutHeader;
|
||||||
bool m_HeaderSent, m_ResponseHeaderSent;
|
bool m_HeaderSent, m_ResponseHeaderSent;
|
||||||
|
std::shared_ptr<const i2p::data::IdentityEx> m_From;
|
||||||
};
|
};
|
||||||
|
|
||||||
class I2PTunnelConnectionIRC: public I2PTunnelConnection
|
class I2PTunnelConnectionIRC: public I2PTunnelConnection
|
||||||
@@ -241,8 +242,7 @@ namespace client
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
std::string m_Host, m_XI2P;
|
std::string m_Host;
|
||||||
std::weak_ptr<const i2p::data::IdentityEx> m_From;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class I2PServerTunnelIRC: public I2PServerTunnel
|
class I2PServerTunnelIRC: public I2PServerTunnel
|
||||||
|
|||||||
Reference in New Issue
Block a user