From e4ab51329d1aa720c6cc64d25ed02f12bbf35b29 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 14 Aug 2018 14:01:04 -0400 Subject: [PATCH 01/26] move handshake messages processing to NTCP2Establisher --- libi2pd/NTCP2.cpp | 242 ++++++++++++++++++++++++++++------------------ libi2pd/NTCP2.h | 5 + 2 files changed, 152 insertions(+), 95 deletions(-) diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp index b54a83ef..325af961 100644 --- a/libi2pd/NTCP2.cpp +++ b/libi2pd/NTCP2.cpp @@ -244,6 +244,119 @@ namespace transport SHA256_Final (m_H, &ctx); //h = SHA256(h || ciphertext) } + bool NTCP2Establisher::ProcessSessionRequestMessage (uint16_t& paddingLen) + { + // decrypt X + i2p::crypto::CBCDecryption decryption; + decryption.SetKey (i2p::context.GetIdentHash ()); + decryption.SetIV (i2p::context.GetNTCP2IV ()); + decryption.Decrypt (m_SessionRequestBuffer, 32, GetRemotePub ()); + decryption.GetIV (m_IV); // save IV for SessionCreated + // decryption key for next block + KDF1Bob (); + // verify MAC and decrypt options block (32 bytes), use m_H as AD + uint8_t nonce[12], options[16]; + memset (nonce, 0, 12); // set nonce to zero + if (i2p::crypto::AEADChaCha20Poly1305 (m_SessionRequestBuffer + 32, 16, m_H, 32, m_K, nonce, options, 16, false)) // decrypt + { + if (options[1] == 2) + { + paddingLen = bufbe16toh (options + 2); + m_SessionRequestBufferLen = paddingLen + 64; + m3p2Len = bufbe16toh (options + 4); + // TODO: check tsA + } + else + { + LogPrint (eLogWarning, "NTCP2: SessionRequest version mismatch ", (int)options[1]); + return false; + } + } + else + { + LogPrint (eLogWarning, "NTCP2: SessionRequest AEAD verification failed "); + return false; + } + return true; + } + + bool NTCP2Establisher::ProcessSessionCreatedMessage (uint16_t& paddingLen) + { + m_SessionCreatedBufferLen = 64; + // decrypt Y + i2p::crypto::CBCDecryption decryption; + decryption.SetKey (m_RemoteIdentHash); + decryption.SetIV (m_IV); + decryption.Decrypt (m_SessionCreatedBuffer, 32, GetRemotePub ()); + // decryption key for next block (m_K) + KDF2Alice (); + // decrypt and verify MAC + uint8_t payload[16]; + uint8_t nonce[12]; + memset (nonce, 0, 12); // set nonce to zero + if (i2p::crypto::AEADChaCha20Poly1305 (m_SessionCreatedBuffer + 32, 16, m_H, 32, m_K, nonce, payload, 16, false)) // decrypt + { + paddingLen = bufbe16toh(payload + 2); + // TODO: check tsB + } + else + { + LogPrint (eLogWarning, "NTCP2: SessionCreated AEAD verification failed "); + return false; + } + return true; + } + + bool NTCP2Establisher::ProcessSessionConfirmedMessagePart1 (const uint8_t * nonce) + { + // update AD + SHA256_CTX ctx; + SHA256_Init (&ctx); + SHA256_Update (&ctx, m_H, 32); + SHA256_Update (&ctx, m_SessionCreatedBuffer + 32, 32); // encrypted payload + SHA256_Final (m_H, &ctx); + + int paddingLength = m_SessionCreatedBufferLen - 64; + if (paddingLength > 0) + { + SHA256_CTX ctx1; + SHA256_Init (&ctx1); + SHA256_Update (&ctx1, m_H, 32); + SHA256_Update (&ctx1, m_SessionCreatedBuffer + 64, paddingLength); + SHA256_Final (m_H, &ctx1); + } + if (!i2p::crypto::AEADChaCha20Poly1305 (m_SessionConfirmedBuffer, 32, m_H, 32, m_K, nonce, m_RemoteStaticKey, 32, false)) // decrypt S + { + LogPrint (eLogWarning, "NTCP2: SessionConfirmed Part1 AEAD verification failed "); + return false; + } + return true; + } + + bool NTCP2Establisher::ProcessSessionConfirmedMessagePart2 (const uint8_t * nonce, uint8_t * m3p2Buf) + { + // update AD again + SHA256_CTX ctx; + SHA256_Init (&ctx); + SHA256_Update (&ctx, m_H, 32); + SHA256_Update (&ctx, m_SessionConfirmedBuffer, 48); + SHA256_Final (m_H, &ctx); + + KDF3Bob (); + if (i2p::crypto::AEADChaCha20Poly1305 (m_SessionConfirmedBuffer + 48, m3p2Len - 16, m_H, 32, m_K, nonce, m3p2Buf, m3p2Len - 16, false)) // decrypt + { + // caclulate new h again for KDF data + memcpy (m_SessionConfirmedBuffer + 16, m_H, 32); // h || ciphertext + SHA256 (m_SessionConfirmedBuffer + 16, m3p2Len + 32, m_H); //h = SHA256(h || ciphertext); + } + else + { + LogPrint (eLogWarning, "NTCP2: SessionConfirmed Part2 AEAD verification failed "); + return false; + } + return true; + } + NTCP2Session::NTCP2Session (NTCP2Server& server, std::shared_ptr in_RemoteRouter): TransportSession (in_RemoteRouter, NTCP2_ESTABLISH_TIMEOUT), m_Server (server), m_Socket (m_Server.GetService ()), @@ -368,52 +481,28 @@ namespace transport } else { - // decrypt X - i2p::crypto::CBCDecryption decryption; - decryption.SetKey (i2p::context.GetIdentHash ()); - decryption.SetIV (i2p::context.GetNTCP2IV ()); - decryption.Decrypt (m_Establisher->m_SessionRequestBuffer, 32, m_Establisher->GetRemotePub ()); - decryption.GetIV (m_Establisher->m_IV); // save IV for SessionCreated - // decryption key for next block - m_Establisher->KDF1Bob (); - // verify MAC and decrypt options block (32 bytes), use m_H as AD - uint8_t nonce[12], options[16]; - memset (nonce, 0, 12); // set nonce to zero - if (i2p::crypto::AEADChaCha20Poly1305 (m_Establisher->m_SessionRequestBuffer + 32, 16, m_Establisher->GetH (), 32, m_Establisher->GetK (), nonce, options, 16, false)) // decrypt + LogPrint (eLogDebug, "NTCP2: SessionRequest received ", bytes_transferred); + uint16_t paddingLen = 0; + if (m_Establisher->ProcessSessionRequestMessage (paddingLen)) { - if (options[1] == 2) + if (paddingLen > 0) { - uint16_t paddingLen = bufbe16toh (options + 2); - m_Establisher->m_SessionRequestBufferLen = paddingLen + 64; - m_Establisher->m3p2Len = bufbe16toh (options + 4); - // TODO: check tsA - if (paddingLen > 0) + if (paddingLen <= 287 - 64) // session request is 287 bytes max { - if (paddingLen <= 287 - 64) // session request is 287 bytes max - { - boost::asio::async_read (m_Socket, boost::asio::buffer(m_Establisher->m_SessionRequestBuffer + 64, paddingLen), boost::asio::transfer_all (), - std::bind(&NTCP2Session::HandleSessionRequestPaddingReceived, shared_from_this (), std::placeholders::_1, std::placeholders::_2)); - } - else - { - LogPrint (eLogWarning, "NTCP2: SessionRequest padding length ", (int)paddingLen, " is too long"); - Terminate (); - } + boost::asio::async_read (m_Socket, boost::asio::buffer(m_Establisher->m_SessionRequestBuffer + 64, paddingLen), boost::asio::transfer_all (), + std::bind(&NTCP2Session::HandleSessionRequestPaddingReceived, shared_from_this (), std::placeholders::_1, std::placeholders::_2)); } else - SendSessionCreated (); + { + LogPrint (eLogWarning, "NTCP2: SessionRequest padding length ", (int)paddingLen, " is too long"); + Terminate (); + } } else - { - LogPrint (eLogWarning, "NTCP2: SessionRequest version mismatch ", (int)options[1]); - Terminate (); - } - } - else - { - LogPrint (eLogWarning, "NTCP2: SessionRequest AEAD verification failed "); - Terminate (); + SendSessionCreated (); } + else + Terminate (); } } @@ -446,23 +535,9 @@ namespace transport else { LogPrint (eLogDebug, "NTCP2: SessionCreated received ", bytes_transferred); - m_Establisher->m_SessionCreatedBufferLen = 64; - // decrypt Y - i2p::crypto::CBCDecryption decryption; - decryption.SetKey (GetRemoteIdentity ()->GetIdentHash ()); - decryption.SetIV (m_Establisher->m_IV); - decryption.Decrypt (m_Establisher->m_SessionCreatedBuffer, 32, m_Establisher->GetRemotePub ()); - // decryption key for next block (m_K) - m_Establisher->KDF2Alice (); - // decrypt and verify MAC - uint8_t payload[16]; - uint8_t nonce[12]; - memset (nonce, 0, 12); // set nonce to zero - if (i2p::crypto::AEADChaCha20Poly1305 (m_Establisher->m_SessionCreatedBuffer + 32, 16, m_Establisher->GetH (), 32, m_Establisher->GetK (), nonce, payload, 16, false)) // decrypt - { - uint16_t paddingLen = bufbe16toh(payload + 2); - LogPrint (eLogDebug, "NTCP2: padding length ", paddingLen); - // TODO: check tsB + uint16_t paddingLen = 0; + if (m_Establisher->ProcessSessionCreatedMessage (paddingLen)) + { if (paddingLen > 0) { if (paddingLen <= 287 - 64) // session created is 287 bytes max @@ -480,10 +555,7 @@ namespace transport SendSessionConfirmed (); } else - { - LogPrint (eLogWarning, "NTCP2: SessionCreated AEAD verification failed "); Terminate (); - } } } @@ -559,38 +631,16 @@ namespace transport else { LogPrint (eLogDebug, "NTCP2: SessionConfirmed received"); - // update AD - uint8_t h[80]; - memcpy (h, m_Establisher->GetH (), 32); - memcpy (h + 32, m_Establisher->m_SessionCreatedBuffer + 32, 32); // encrypted payload - SHA256 (h, 64, h); - int paddingLength = m_Establisher->m_SessionCreatedBufferLen - 64; - if (paddingLength > 0) - { - SHA256_CTX ctx; - SHA256_Init (&ctx); - SHA256_Update (&ctx, h, 32); - SHA256_Update (&ctx, m_Establisher->m_SessionCreatedBuffer + 64, paddingLength); - SHA256_Final (h, &ctx); - } // part 1 uint8_t nonce[12]; CreateNonce (1, nonce); - if (i2p::crypto::AEADChaCha20Poly1305 (m_Establisher->m_SessionConfirmedBuffer, 32, h, 32, m_Establisher->GetK (), nonce, m_Establisher->m_RemoteStaticKey, 32, false)) // decrypt S + if (m_Establisher->ProcessSessionConfirmedMessagePart1 (nonce)) { // part 2 - // update AD again - memcpy (h + 32, m_Establisher->m_SessionConfirmedBuffer, 48); - SHA256 (h, 80, m_Establisher->m_H); - std::vector buf(m_Establisher->m3p2Len - 16); // -MAC - m_Establisher->KDF3Bob (); memset (nonce, 0, 12); // set nonce to 0 again - if (i2p::crypto::AEADChaCha20Poly1305 (m_Establisher->m_SessionConfirmedBuffer + 48, m_Establisher->m3p2Len - 16, m_Establisher->GetH (), 32, m_Establisher->GetK (), nonce, buf.data (), m_Establisher->m3p2Len - 16, false)) // decrypt + if (m_Establisher->ProcessSessionConfirmedMessagePart2 (nonce, buf.data ())) { - // caclulate new h again for KDF data - memcpy (m_Establisher->m_SessionConfirmedBuffer + 16, m_Establisher->GetH (), 32); // h || ciphertext - SHA256 (m_Establisher->m_SessionConfirmedBuffer + 16, m_Establisher->m3p2Len + 32, m_Establisher->m_H); //h = SHA256(h || ciphertext); KeyDerivationFunctionDataPhase (); // Bob data phase keys m_SendKey = m_Kba; @@ -599,7 +649,7 @@ namespace transport m_ReceiveSipKey = m_Sipkeysab; memcpy (m_ReceiveIV.buf, m_Sipkeysab + 16, 8); memcpy (m_SendIV.buf, m_Sipkeysba + 16, 8); - + // payload // process RI if (buf[0] != eNTCP2BlkRouterInfo) { @@ -644,19 +694,13 @@ namespace transport SetRemoteIdentity (existing ? existing->GetRouterIdentity () : ri.GetRouterIdentity ()); m_Server.AddNTCP2Session (shared_from_this ()); Established (); - ReceiveLength (); - } + ReceiveLength (); + } else - { - LogPrint (eLogWarning, "NTCP2: SessionConfirmed Part2 AEAD verification failed "); Terminate (); - } } else - { - LogPrint (eLogWarning, "NTCP2: SessionConfirmed Part1 AEAD verification failed "); Terminate (); - } } } @@ -691,12 +735,20 @@ namespace transport else { i2p::crypto::Siphash<8> (m_ReceiveIV.buf, m_ReceiveIV.buf, 8, m_ReceiveSipKey); - // m_NextRecivedLen comes from the network in BigEndian + // m_NextReceivedLen comes from the network in BigEndian m_NextReceivedLen = be16toh (m_NextReceivedLen) ^ le16toh (m_ReceiveIV.key); LogPrint (eLogDebug, "NTCP2: received length ", m_NextReceivedLen); - if (m_NextReceivedBuffer) delete[] m_NextReceivedBuffer; - m_NextReceivedBuffer = new uint8_t[m_NextReceivedLen]; - Receive (); + if (m_NextReceivedLen >= 16) + { + if (m_NextReceivedBuffer) delete[] m_NextReceivedBuffer; + m_NextReceivedBuffer = new uint8_t[m_NextReceivedLen]; + Receive (); + } + else + { + LogPrint (eLogError, "NTCP2: received length ", m_NextReceivedLen, " is too short"); + Terminate (); + } } } diff --git a/libi2pd/NTCP2.h b/libi2pd/NTCP2.h index 3e202dc5..1f5700be 100644 --- a/libi2pd/NTCP2.h +++ b/libi2pd/NTCP2.h @@ -91,6 +91,11 @@ namespace transport void CreateSessionConfirmedMessagePart1 (const uint8_t * nonce); void CreateSessionConfirmedMessagePart2 (const uint8_t * nonce); + bool ProcessSessionRequestMessage (uint16_t& paddingLen); + bool ProcessSessionCreatedMessage (uint16_t& paddingLen); + bool ProcessSessionConfirmedMessagePart1 (const uint8_t * nonce); + bool ProcessSessionConfirmedMessagePart2 (const uint8_t * nonce, uint8_t * m3p2Buf); + BN_CTX * m_Ctx; uint8_t m_EphemeralPrivateKey[32], m_EphemeralPublicKey[32], m_RemoteEphemeralPublicKey[32]; // x25519 uint8_t m_RemoteStaticKey[32], m_IV[16], m_H[32] /*h*/, m_CK[33] /*ck*/, m_K[32] /*k*/; From db5a40d743e8e03f4614ea595997f3e26a0b73fe Mon Sep 17 00:00:00 2001 From: r4sas Date: Tue, 14 Aug 2018 22:39:57 +0300 Subject: [PATCH 02/26] enable NTCP2 for android, use L flag for bandwidth, additional change for multiarch build --- android/assets/i2pd.conf | 5 ++++- android/jni/Application.mk | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/android/assets/i2pd.conf b/android/assets/i2pd.conf index 8022b3d9..cf113da2 100644 --- a/android/assets/i2pd.conf +++ b/android/assets/i2pd.conf @@ -15,12 +15,15 @@ ipv6 = false # ntcpproxy = http://127.0.0.1:8118 # ssu = true -bandwidth = O +bandwidth = L # share = 100 # notransit = true # floodfill = true +[ntcp2] +enabled = true + [http] enabled = true address = 127.0.0.1 diff --git a/android/jni/Application.mk b/android/jni/Application.mk index b5b920fa..a7554706 100755 --- a/android/jni/Application.mk +++ b/android/jni/Application.mk @@ -2,7 +2,7 @@ #APP_ABI := armeabi-v7a x86 #APP_ABI := x86 #APP_ABI := x86_64 -APP_ABI := armeabi-v7a +#APP_ABI := armeabi-v7a #can be android-3 but will fail for x86 since arch-x86 is not present at ndkroot/platforms/android-3/ . libz is taken from there. APP_PLATFORM := android-14 From 331a23fc209ae2d2d9a1806238caa564bbfd117b Mon Sep 17 00:00:00 2001 From: r4sas Date: Tue, 14 Aug 2018 22:44:08 +0300 Subject: [PATCH 03/26] build JNI for arm v7a and x86 both --- android/jni/Application.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android/jni/Application.mk b/android/jni/Application.mk index a7554706..92622ee9 100755 --- a/android/jni/Application.mk +++ b/android/jni/Application.mk @@ -1,5 +1,5 @@ #APP_ABI := all -#APP_ABI := armeabi-v7a x86 +APP_ABI := armeabi-v7a x86 #APP_ABI := x86 #APP_ABI := x86_64 #APP_ABI := armeabi-v7a From db4c26a400ab1f8c6afe8e2697239e7fbf862622 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 15 Aug 2018 09:52:13 -0400 Subject: [PATCH 04/26] copy assets before daemon start --- .../src/org/purplei2p/i2pd/I2PDActivity.java | 27 ++++++++++++++----- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/android/src/org/purplei2p/i2pd/I2PDActivity.java b/android/src/org/purplei2p/i2pd/I2PDActivity.java index 28e30251..997b90ac 100755 --- a/android/src/org/purplei2p/i2pd/I2PDActivity.java +++ b/android/src/org/purplei2p/i2pd/I2PDActivity.java @@ -30,6 +30,7 @@ public class I2PDActivity extends Activity { public static final int GRACEFUL_DELAY_MILLIS = 10 * 60 * 1000; private TextView textView; + private boolean assetsCopied; private static final DaemonSingleton daemon = DaemonSingleton.getInstance(); @@ -37,7 +38,25 @@ public class I2PDActivity extends Activity { new DaemonSingleton.StateUpdateListener() { @Override - public void daemonStateUpdate() { + public void daemonStateUpdate() + { + try + { + // copy assets + if (!assetsCopied) + { + assetsCopied = true; + copyAsset("certificates"); + copyAsset("i2pd.conf"); + copyAsset("subsciptions.txt"); + copyAsset("tunnels.conf"); + } + } + catch (Throwable tr) + { + Log.e(TAG,"copy assets",tr); + }; + runOnUiThread(new Runnable(){ @Override @@ -79,12 +98,6 @@ public class I2PDActivity extends Activity { public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - // copy assets - copyAsset("certificates"); - copyAsset("i2pd.conf"); - copyAsset("subsciptions.txt"); - copyAsset("tunnels.conf"); - textView = new TextView(this); setContentView(textView); daemon.addStateChangeListener(daemonStateUpdatedListener); From c41081d35c237dcf79bb7f714ed876ea7cf4df94 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 15 Aug 2018 11:42:56 -0400 Subject: [PATCH 05/26] check timestamps --- libi2pd/NTCP2.cpp | 26 +++++++++++++++++++++----- libi2pd/NTCP2.h | 2 ++ 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp index 325af961..0cac7efa 100644 --- a/libi2pd/NTCP2.cpp +++ b/libi2pd/NTCP2.cpp @@ -259,12 +259,20 @@ namespace transport memset (nonce, 0, 12); // set nonce to zero if (i2p::crypto::AEADChaCha20Poly1305 (m_SessionRequestBuffer + 32, 16, m_H, 32, m_K, nonce, options, 16, false)) // decrypt { - if (options[1] == 2) + // options + if (options[1] == 2) // ver is always 2 { paddingLen = bufbe16toh (options + 2); m_SessionRequestBufferLen = paddingLen + 64; m3p2Len = bufbe16toh (options + 4); - // TODO: check tsA + // check timestamp + auto ts = i2p::util::GetSecondsSinceEpoch (); + uint32_t tsA = bufbe32toh (options + 8); + if (tsA < ts - NTCP2_CLOCK_SKEW || tsA > ts + NTCP2_CLOCK_SKEW) + { + LogPrint (eLogWarning, "NTCP2: SessionRequest time difference ", ts - tsA, " exceeds clock skew"); + return false; + } } else { @@ -295,9 +303,17 @@ namespace transport uint8_t nonce[12]; memset (nonce, 0, 12); // set nonce to zero if (i2p::crypto::AEADChaCha20Poly1305 (m_SessionCreatedBuffer + 32, 16, m_H, 32, m_K, nonce, payload, 16, false)) // decrypt - { + { + // options paddingLen = bufbe16toh(payload + 2); - // TODO: check tsB + // check timestamp + auto ts = i2p::util::GetSecondsSinceEpoch (); + uint32_t tsB = bufbe32toh (payload + 8); + if (tsB < ts - NTCP2_CLOCK_SKEW || tsB > ts + NTCP2_CLOCK_SKEW) + { + LogPrint (eLogWarning, "NTCP2: SessionCreated time difference ", ts - tsB, " exceeds clock skew"); + return false; + } } else { @@ -414,7 +430,7 @@ namespace transport m_IsEstablished = true; m_Establisher.reset (nullptr); SetTerminationTimeout (NTCP2_TERMINATION_TIMEOUT); - transports.PeerConnected (shared_from_this ()); + // transports.PeerConnected (shared_from_this ()); } void NTCP2Session::CreateNonce (uint64_t seqn, uint8_t * nonce) diff --git a/libi2pd/NTCP2.h b/libi2pd/NTCP2.h index 1f5700be..81395e46 100644 --- a/libi2pd/NTCP2.h +++ b/libi2pd/NTCP2.h @@ -26,6 +26,8 @@ namespace transport const int NTCP2_TERMINATION_TIMEOUT = 120; // 2 minutes const int NTCP2_TERMINATION_CHECK_TIMEOUT = 30; // 30 seconds + const int NTCP2_CLOCK_SKEW = 60; // in seconds + enum NTCP2BlockType { eNTCP2BlkDateTime = 0, From 02e8c5faca53e745c0c02afb7efe7e69a3ca0889 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 15 Aug 2018 13:23:10 -0400 Subject: [PATCH 06/26] fixed typo --- libi2pd/NTCP2.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp index 0cac7efa..d182e4a9 100644 --- a/libi2pd/NTCP2.cpp +++ b/libi2pd/NTCP2.cpp @@ -430,7 +430,7 @@ namespace transport m_IsEstablished = true; m_Establisher.reset (nullptr); SetTerminationTimeout (NTCP2_TERMINATION_TIMEOUT); - // transports.PeerConnected (shared_from_this ()); + transports.PeerConnected (shared_from_this ()); } void NTCP2Session::CreateNonce (uint64_t seqn, uint8_t * nonce) From 11142690a0830bc37f0b4ea414f9edafb3c17d92 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 16 Aug 2018 10:13:32 -0400 Subject: [PATCH 07/26] show correct value of time drift --- libi2pd/NTCP2.cpp | 4 ++-- libi2pd/NTCPSession.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp index d182e4a9..6d8814b4 100644 --- a/libi2pd/NTCP2.cpp +++ b/libi2pd/NTCP2.cpp @@ -270,7 +270,7 @@ namespace transport uint32_t tsA = bufbe32toh (options + 8); if (tsA < ts - NTCP2_CLOCK_SKEW || tsA > ts + NTCP2_CLOCK_SKEW) { - LogPrint (eLogWarning, "NTCP2: SessionRequest time difference ", ts - tsA, " exceeds clock skew"); + LogPrint (eLogWarning, "NTCP2: SessionRequest time difference ", (int)(ts - tsA), " exceeds clock skew"); return false; } } @@ -311,7 +311,7 @@ namespace transport uint32_t tsB = bufbe32toh (payload + 8); if (tsB < ts - NTCP2_CLOCK_SKEW || tsB > ts + NTCP2_CLOCK_SKEW) { - LogPrint (eLogWarning, "NTCP2: SessionCreated time difference ", ts - tsB, " exceeds clock skew"); + LogPrint (eLogWarning, "NTCP2: SessionCreated time difference ", (int)(ts - tsB), " exceeds clock skew"); return false; } } diff --git a/libi2pd/NTCPSession.cpp b/libi2pd/NTCPSession.cpp index caddd110..e9de08e2 100644 --- a/libi2pd/NTCPSession.cpp +++ b/libi2pd/NTCPSession.cpp @@ -402,7 +402,7 @@ namespace transport uint32_t tsA1 = be32toh (tsA); if (tsA1 < ts - NTCP_CLOCK_SKEW || tsA1 > ts + NTCP_CLOCK_SKEW) { - LogPrint (eLogError, "NTCP: Phase3 time difference ", ts - tsA1, " exceeds clock skew"); + LogPrint (eLogError, "NTCP: Phase3 time difference ", (int)(ts - tsA1), " exceeds clock skew"); Terminate (); return; } @@ -485,7 +485,7 @@ namespace transport auto ts = i2p::util::GetSecondsSinceEpoch (); if (tsB < ts - NTCP_CLOCK_SKEW || tsB > ts + NTCP_CLOCK_SKEW) { - LogPrint (eLogError, "NTCP: Phase4 time difference ", ts - tsB, " exceeds clock skew"); + LogPrint (eLogError, "NTCP: Phase4 time difference ", (int)(ts - tsB), " exceeds clock skew"); Terminate (); return; } From 863baeb68b4b75d08c33f865dd5821789a7e8316 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 16 Aug 2018 11:02:53 -0400 Subject: [PATCH 08/26] ignore unpublished addresses --- daemon/UPnP.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/daemon/UPnP.cpp b/daemon/UPnP.cpp index ba7b408c..3aad19c6 100644 --- a/daemon/UPnP.cpp +++ b/daemon/UPnP.cpp @@ -131,8 +131,8 @@ namespace transport const auto& a = context.GetRouterInfo().GetAddresses(); for (const auto& address : a) { - if (!address->host.is_v6 ()) - TryPortMapping (address); + if (!address->host.is_v6 () && address->port) + TryPortMapping (address); } m_Timer.expires_from_now (boost::posix_time::minutes(20)); // every 20 minutes m_Timer.async_wait ([this](const boost::system::error_code& ecode) @@ -148,7 +148,7 @@ namespace transport const auto& a = context.GetRouterInfo().GetAddresses(); for (const auto& address : a) { - if (!address->host.is_v6 ()) + if (!address->host.is_v6 () && address->port) CloseMapping (address); } } From 77a409935d2c37ac69cf7506bdf16b7d76d357bd Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 16 Aug 2018 13:46:59 -0400 Subject: [PATCH 09/26] license added --- libi2pd/NTCP2.cpp | 11 +++++++++++ libi2pd/NTCP2.h | 10 ++++++++++ 2 files changed, 21 insertions(+) diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp index 6d8814b4..31f3c999 100644 --- a/libi2pd/NTCP2.cpp +++ b/libi2pd/NTCP2.cpp @@ -1,3 +1,14 @@ +/* +* Copyright (c) 2013-2018, The PurpleI2P Project +* +* This file is part of Purple i2pd project and licensed under BSD3 +* +* See full license text in LICENSE file at top of project tree +* +* Kovri go write your own code +* +*/ + #include #include #include diff --git a/libi2pd/NTCP2.h b/libi2pd/NTCP2.h index 81395e46..2b6748ab 100644 --- a/libi2pd/NTCP2.h +++ b/libi2pd/NTCP2.h @@ -1,3 +1,13 @@ +/* +* Copyright (c) 2013-2018, The PurpleI2P Project +* +* This file is part of Purple i2pd project and licensed under BSD3 +* +* See full license text in LICENSE file at top of project tree +* +* Kovri go write your own code +* +*/ #ifndef NTCP2_H__ #define NTCP2_H__ From 5e110e9f7b2ec3cbab1d46ac28d3cc57a21c179a Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 16 Aug 2018 13:48:47 -0400 Subject: [PATCH 10/26] enable NTCP2 by default --- libi2pd/Config.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd/Config.cpp b/libi2pd/Config.cpp index 098a7baa..9eaaf068 100644 --- a/libi2pd/Config.cpp +++ b/libi2pd/Config.cpp @@ -233,7 +233,7 @@ namespace config { options_description ntcp2("NTCP2 Options"); ntcp2.add_options() - ("ntcp2.enabled", value()->default_value(false), "Enable NTCP2 (default: disabled)") + ("ntcp2.enabled", value()->default_value(true), "Enable NTCP2 (default: enabled)") ("ntcp2.published", value()->default_value(false), "Publish NTCP2 (default: disabled)") ("ntcp2.port", value()->default_value(0), "Port to listen for incoming NTCP2 connections (default: auto)") ; From f1fb42460add9b7efe370a25186f205e06e826ed Mon Sep 17 00:00:00 2001 From: r4sas Date: Wed, 15 Aug 2018 00:12:46 +0300 Subject: [PATCH 11/26] rename ipv6 transports --- daemon/HTTPServer.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/daemon/HTTPServer.cpp b/daemon/HTTPServer.cpp index cda3f2ec..90bd772f 100644 --- a/daemon/HTTPServer.cpp +++ b/daemon/HTTPServer.cpp @@ -262,7 +262,9 @@ namespace http { { if (address->IsNTCP2 () && !address->IsPublishedNTCP2 ()) { - s << "NTCP2   supported
\r\n"; + s << "NTCP2"; + if (address->host.is_v6 ()) s << "v6"; + s << "   supported
\r\n"; continue; } switch (address->transportStyle) @@ -271,13 +273,13 @@ namespace http { { s << "NTCP"; if (address->IsPublishedNTCP2 ()) s << "2"; - if (address->host.is_v6 ()) s << "6"; + if (address->host.is_v6 ()) s << "v6"; s << "  "; break; } case i2p::data::RouterInfo::eTransportSSU: if (address->host.is_v6 ()) - s << "SSU6     "; + s << "SSUv6     "; else s << "SSU     "; break; @@ -583,7 +585,7 @@ namespace http { } if (!tmp_s6.str ().empty ()) { - s << "
\r\n\r\n

"; + s << "

\r\n\r\n

"; s << tmp_s6.str () << "

\r\n
\r\n"; } } @@ -628,7 +630,7 @@ namespace http { auto sessions6 = ssuServer->GetSessionsV6 (); if (!sessions6.empty ()) { - s << "
\r\n\r\n

"; + s << "

\r\n\r\n

"; for (const auto& it: sessions6) { auto endpoint = it.second->GetRemoteEndpoint (); From d009a29426e30a87da7b9e46cac238fce76bde0a Mon Sep 17 00:00:00 2001 From: r4sas Date: Wed, 15 Aug 2018 01:49:10 +0300 Subject: [PATCH 12/26] android - dont rewrite files from assets if they exist --- .../src/org/purplei2p/i2pd/I2PDActivity.java | 102 +++++++++--------- 1 file changed, 50 insertions(+), 52 deletions(-) diff --git a/android/src/org/purplei2p/i2pd/I2PDActivity.java b/android/src/org/purplei2p/i2pd/I2PDActivity.java index 997b90ac..21cb0572 100755 --- a/android/src/org/purplei2p/i2pd/I2PDActivity.java +++ b/android/src/org/purplei2p/i2pd/I2PDActivity.java @@ -28,17 +28,16 @@ import android.widget.Toast; public class I2PDActivity extends Activity { private static final String TAG = "i2pdActvt"; public static final int GRACEFUL_DELAY_MILLIS = 10 * 60 * 1000; - + private TextView textView; private boolean assetsCopied; - + private static final DaemonSingleton daemon = DaemonSingleton.getInstance(); - + private final DaemonSingleton.StateUpdateListener daemonStateUpdatedListener = new DaemonSingleton.StateUpdateListener() { - @Override - public void daemonStateUpdate() + public void daemonStateUpdate() { try { @@ -48,17 +47,17 @@ public class I2PDActivity extends Activity { assetsCopied = true; copyAsset("certificates"); copyAsset("i2pd.conf"); - copyAsset("subsciptions.txt"); + copyAsset("subscriptions.txt"); copyAsset("tunnels.conf"); } } - catch (Throwable tr) + catch (Throwable tr) { Log.e(TAG,"copy assets",tr); }; runOnUiThread(new Runnable(){ - + @Override public void run() { try { @@ -74,7 +73,7 @@ public class I2PDActivity extends Activity { (DaemonSingleton.State.startFailed.equals(state)?": "+daemon.getDaemonStartResult():"")+ (DaemonSingleton.State.gracefulShutdownInProgress.equals(state)?": "+formatGraceTimeRemaining()+" "+getText(R.string.remaining):"") ); - } catch (Throwable tr) { + } catch (Throwable tr) { Log.e(TAG,"error ignored",tr); } } @@ -83,7 +82,7 @@ public class I2PDActivity extends Activity { }; private static volatile long graceStartedMillis; private static final Object graceStartedMillis_LOCK=new Object(); - + private static String formatGraceTimeRemaining() { long remainingSeconds; synchronized (graceStartedMillis_LOCK){ @@ -93,19 +92,19 @@ public class I2PDActivity extends Activity { long remSec=remainingSeconds-remainingMinutes*60; return remainingMinutes+":"+(remSec/10)+remSec%10; } - + @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - + textView = new TextView(this); setContentView(textView); daemon.addStateChangeListener(daemonStateUpdatedListener); daemonStateUpdatedListener.daemonStateUpdate(); - + // set the app be foreground doBindService(); - + final Timer gracefulQuitTimer = getGracefulQuitTimer(); if(gracefulQuitTimer!=null){ long gracefulStopAtMillis; @@ -115,7 +114,7 @@ public class I2PDActivity extends Activity { rescheduleGraceStop(gracefulQuitTimer, gracefulStopAtMillis); } } - + @Override protected void onDestroy() { super.onDestroy(); @@ -128,7 +127,7 @@ public class I2PDActivity extends Activity { Log.e(TAG, "", tr); } } - + private static void cancelGracefulStop() { Timer gracefulQuitTimer = getGracefulQuitTimer(); if(gracefulQuitTimer!=null) { @@ -136,7 +135,7 @@ public class I2PDActivity extends Activity { setGracefulQuitTimer(null); } } - + private CharSequence throwableToString(Throwable tr) { StringWriter sw = new StringWriter(8192); PrintWriter pw = new PrintWriter(sw); @@ -144,9 +143,9 @@ public class I2PDActivity extends Activity { pw.close(); return sw.toString(); } - + // private LocalService mBoundService; - + private ServiceConnection mConnection = new ServiceConnection() { public void onServiceConnected(ComponentName className, IBinder service) { // This is called when the connection with the service has been @@ -155,12 +154,12 @@ public class I2PDActivity extends Activity { // service that we know is running in our own process, we can // cast its IBinder to a concrete class and directly access it. // mBoundService = ((LocalService.LocalBinder)service).getService(); - + // Tell the user about this for our demo. // Toast.makeText(Binding.this, R.string.local_service_connected, // Toast.LENGTH_SHORT).show(); } - + public void onServiceDisconnected(ComponentName className) { // This is called when the connection with the service has been // unexpectedly disconnected -- that is, its process crashed. @@ -171,10 +170,9 @@ public class I2PDActivity extends Activity { // Toast.LENGTH_SHORT).show(); } }; - - + private static volatile boolean mIsBound; - + private void doBindService() { synchronized (I2PDActivity.class) { if (mIsBound) return; @@ -186,7 +184,7 @@ public class I2PDActivity extends Activity { mIsBound = true; } } - + private void doUnbindService() { synchronized (I2PDActivity.class) { if (mIsBound) { @@ -196,21 +194,21 @@ public class I2PDActivity extends Activity { } } } - + @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.options_main, menu); return true; } - + @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); - + switch(id){ case R.id.action_stop: i2pdStop(); @@ -219,14 +217,14 @@ public class I2PDActivity extends Activity { i2pdGracefulStop(); return true; } - + return super.onOptionsItemSelected(item); } - + private void i2pdStop() { cancelGracefulStop(); new Thread(new Runnable(){ - + @Override public void run() { Log.d(TAG, "stopping"); @@ -236,12 +234,12 @@ public class I2PDActivity extends Activity { Log.e(TAG, "", tr); } } - + },"stop").start(); } - + private static volatile Timer gracefulQuitTimer; - + private void i2pdGracefulStop() { if(daemon.getState()==DaemonSingleton.State.stopped){ Toast.makeText(this, R.string.already_stopped, @@ -256,7 +254,7 @@ public class I2PDActivity extends Activity { Toast.makeText(this, R.string.graceful_stop_is_in_progress, Toast.LENGTH_SHORT).show(); new Thread(new Runnable(){ - + @Override public void run() { try{ @@ -276,21 +274,21 @@ public class I2PDActivity extends Activity { Log.e(TAG,"",tr); } } - + },"gracInit").start(); } - + private void rescheduleGraceStop(Timer gracefulQuitTimerOld, long gracefulStopAtMillis) { if(gracefulQuitTimerOld!=null)gracefulQuitTimerOld.cancel(); final Timer gracefulQuitTimer = new Timer(true); setGracefulQuitTimer(gracefulQuitTimer); gracefulQuitTimer.schedule(new TimerTask(){ - + @Override public void run() { i2pdStop(); } - + }, Math.max(0,gracefulStopAtMillis-System.currentTimeMillis())); final TimerTask tickerTask = new TimerTask() { @Override @@ -300,30 +298,30 @@ public class I2PDActivity extends Activity { }; gracefulQuitTimer.scheduleAtFixedRate(tickerTask,0/*start delay*/,1000/*millis period*/); } - + private static Timer getGracefulQuitTimer() { return gracefulQuitTimer; } - + private static void setGracefulQuitTimer(Timer gracefulQuitTimer) { I2PDActivity.gracefulQuitTimer = gracefulQuitTimer; } - + /** * Copy the asset at the specified path to this app's data directory. If the * asset is a directory, its contents are also copied. - * + * * @param path * Path to asset, relative to app's assets directory. */ private void copyAsset(String path) { AssetManager manager = getAssets(); - + // If we have a directory, we make it and recurse. If a file, we copy its // contents. try { String[] contents = manager.list(path); - + // The documentation suggests that list throws an IOException, but doesn't // say under what conditions. It'd be nice if it did so when the path was // to a file. That doesn't appear to be the case. If the returned array is @@ -331,30 +329,30 @@ public class I2PDActivity extends Activity { // directories will get turned into files. if (contents == null || contents.length == 0) throw new IOException(); - + // Make the directory. File dir = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/i2pd/", path); dir.mkdirs(); - + // Recurse on the contents. for (String entry : contents) { copyAsset(path + "/" + entry); } - } catch (IOException e) { + } catch (IOException e) { copyFileAsset(path); } } - + /** * Copy the asset file specified by path to app's data directory. Assumes * parent directories have already been created. - * + * * @param path * Path to asset, relative to app's assets directory. */ private void copyFileAsset(String path) { File file = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/i2pd/", path); - try { + if(!file.exists()) try { InputStream in = getAssets().open(path); OutputStream out = new FileOutputStream(file); byte[] buffer = new byte[1024]; @@ -365,7 +363,7 @@ public class I2PDActivity extends Activity { } out.close(); in.close(); - } catch (IOException e) { + } catch (IOException e) { Log.e(TAG, "", e); } } From 405429a300bf00e634785f9be3ffecd9e78eec1a Mon Sep 17 00:00:00 2001 From: r4sas Date: Thu, 16 Aug 2018 23:32:33 +0300 Subject: [PATCH 13/26] android - add file for notify about successful unpacking assets --- android/src/org/purplei2p/i2pd/I2PDActivity.java | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/android/src/org/purplei2p/i2pd/I2PDActivity.java b/android/src/org/purplei2p/i2pd/I2PDActivity.java index 21cb0572..78f67c8b 100755 --- a/android/src/org/purplei2p/i2pd/I2PDActivity.java +++ b/android/src/org/purplei2p/i2pd/I2PDActivity.java @@ -1,6 +1,7 @@ package org.purplei2p.i2pd; import java.io.File; +import java.io.FileWriter; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; @@ -25,6 +26,9 @@ import android.view.MenuItem; import android.widget.TextView; import android.widget.Toast; +// For future package update checking +import org.purplei2p.i2pd.BuildConfig; + public class I2PDActivity extends Activity { private static final String TAG = "i2pdActvt"; public static final int GRACEFUL_DELAY_MILLIS = 10 * 60 * 1000; @@ -44,11 +48,19 @@ public class I2PDActivity extends Activity { // copy assets if (!assetsCopied) { - assetsCopied = true; copyAsset("certificates"); copyAsset("i2pd.conf"); copyAsset("subscriptions.txt"); copyAsset("tunnels.conf"); + assetsCopied = true; + + // create holder file about successful copying + File file = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/i2pd/", "assets.ready"); + FileWriter writer = new FileWriter(file); + String versionName = BuildConfig.VERSION_NAME; // here will be 2.XX.0 + writer.append(versionName); + writer.flush(); + writer.close(); } } catch (Throwable tr) From 45596a0342849f31b2cb1d62dd38a4c4adf99fef Mon Sep 17 00:00:00 2001 From: r4sas Date: Fri, 17 Aug 2018 01:41:26 +0300 Subject: [PATCH 14/26] android - holder-based updater for certificate If holder exsists, check string (version) of assets creation. If it differs from current app version or null, try delete certificates forder contents for unpacking new certificates. --- .../src/org/purplei2p/i2pd/I2PDActivity.java | 91 +++++++++++++------ 1 file changed, 64 insertions(+), 27 deletions(-) diff --git a/android/src/org/purplei2p/i2pd/I2PDActivity.java b/android/src/org/purplei2p/i2pd/I2PDActivity.java index 78f67c8b..bc6f7209 100755 --- a/android/src/org/purplei2p/i2pd/I2PDActivity.java +++ b/android/src/org/purplei2p/i2pd/I2PDActivity.java @@ -1,7 +1,9 @@ package org.purplei2p.i2pd; import java.io.File; +import java.io.FileReader; import java.io.FileWriter; +import java.io.BufferedReader; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; @@ -35,6 +37,7 @@ public class I2PDActivity extends Activity { private TextView textView; private boolean assetsCopied; + private String i2pdpath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/i2pd/"; private static final DaemonSingleton daemon = DaemonSingleton.getInstance(); @@ -43,31 +46,7 @@ public class I2PDActivity extends Activity { @Override public void daemonStateUpdate() { - try - { - // copy assets - if (!assetsCopied) - { - copyAsset("certificates"); - copyAsset("i2pd.conf"); - copyAsset("subscriptions.txt"); - copyAsset("tunnels.conf"); - assetsCopied = true; - - // create holder file about successful copying - File file = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/i2pd/", "assets.ready"); - FileWriter writer = new FileWriter(file); - String versionName = BuildConfig.VERSION_NAME; // here will be 2.XX.0 - writer.append(versionName); - writer.flush(); - writer.close(); - } - } - catch (Throwable tr) - { - Log.e(TAG,"copy assets",tr); - }; - + processAssets(); runOnUiThread(new Runnable(){ @Override @@ -343,7 +322,7 @@ public class I2PDActivity extends Activity { throw new IOException(); // Make the directory. - File dir = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/i2pd/", path); + File dir = new File(i2pdpath, path); dir.mkdirs(); // Recurse on the contents. @@ -363,7 +342,7 @@ public class I2PDActivity extends Activity { * Path to asset, relative to app's assets directory. */ private void copyFileAsset(String path) { - File file = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/i2pd/", path); + File file = new File(i2pdpath, path); if(!file.exists()) try { InputStream in = getAssets().open(path); OutputStream out = new FileOutputStream(file); @@ -379,4 +358,62 @@ public class I2PDActivity extends Activity { Log.e(TAG, "", e); } } + + private void deleteRecursive(File fileOrDirectory) { + if (fileOrDirectory.isDirectory()) { + for (File child : fileOrDirectory.listFiles()) { + deleteRecursive(child); + } + } + fileOrDirectory.delete(); + } + + private void processAssets() { + if (!assetsCopied) try { + assetsCopied = true; // prevent from running on every state update + + File holderfile = new File(i2pdpath, "assets.ready"); + String versionName = BuildConfig.VERSION_NAME; // here will be app version, like 2.XX.XX + StringBuilder text = new StringBuilder(); + + if (holderfile.exists()) try { // if holder file exists, read assets version string + BufferedReader br = new BufferedReader(new FileReader(holderfile)); + String line; + + while ((line = br.readLine()) != null) { + text.append(line); + } + br.close(); + } + catch (IOException e) { + Log.e(TAG, "", e); + } + + // if version differs from current app version or null, try to delete certificates folder + if (!text.toString().contains(versionName)) try { + holderfile.delete(); + File certpath = new File(i2pdpath, "certificates"); + deleteRecursive(certpath); + } + catch (Throwable tr) { + Log.e(TAG, "", tr); + } + + // copy assets. If processed file exists, it won't be overwrited + copyAsset("certificates"); + copyAsset("i2pd.conf"); + copyAsset("subscriptions.txt"); + copyAsset("tunnels.conf"); + + // update holder file about successful copying + FileWriter writer = new FileWriter(holderfile); + writer.append(versionName); + writer.flush(); + writer.close(); + } + catch (Throwable tr) + { + Log.e(TAG,"copy assets",tr); + } + } } From e190a005db288f0c5ba64d6e043d2e06e3b6e315 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 17 Aug 2018 11:17:17 -0400 Subject: [PATCH 15/26] make sure assets are ready before proceed --- android/jni/DaemonAndroid.cpp | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/android/jni/DaemonAndroid.cpp b/android/jni/DaemonAndroid.cpp index 75584740..5ea5e495 100644 --- a/android/jni/DaemonAndroid.cpp +++ b/android/jni/DaemonAndroid.cpp @@ -1,10 +1,13 @@ -#include "DaemonAndroid.h" -#include "Daemon.h" #include +#include +#include +#include #include #include -#include //#include "mainwindow.h" +#include "FS.h" +#include "DaemonAndroid.h" +#include "Daemon.h" namespace i2p { @@ -80,6 +83,17 @@ namespace android //mutex=new QMutex(QMutex::Recursive); //setRunningCallback(0); //m_IsRunning=false; + + // make sure assets are ready before proceed + i2p::fs::DetectDataDir("", false); + int numAttempts = 0; + do + { + if (i2p::fs::Exists (i2p::fs::DataDirPath("assets.ready"))) break; // assets ready + numAttempts++; + std::this_thread::sleep_for (std::chrono::seconds(1)); // otherwise wait for 1 more second + } + while (numAttempts <= 10); // 10 seconds max return Daemon.init(argc,argv); } From 1dd003d26a62f2700df2e83219d638f9ed4bef5c Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 18 Aug 2018 08:27:36 -0400 Subject: [PATCH 16/26] check m2p3len --- libi2pd/NTCP2.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp index 31f3c999..14e5e333 100644 --- a/libi2pd/NTCP2.cpp +++ b/libi2pd/NTCP2.cpp @@ -276,6 +276,11 @@ namespace transport paddingLen = bufbe16toh (options + 2); m_SessionRequestBufferLen = paddingLen + 64; m3p2Len = bufbe16toh (options + 4); + if (m3p2Len < 16) + { + LogPrint (eLogWarning, "NTCP2: SessionRequest m3p2len=", m3p2Len, " is too short"); + return false; + } // check timestamp auto ts = i2p::util::GetSecondsSinceEpoch (); uint32_t tsA = bufbe32toh (options + 8); @@ -944,7 +949,7 @@ namespace transport payload[s] = eNTCP2BlkPadding; // blk htobe16buf (payload + s + 1, paddingSize); // size s += 3; - RAND_bytes (payload + s, paddingSize); + memset (payload + s, 0, paddingSize); s += paddingSize; // send SendNextFrame (payload, s); From 2d758ce9636da3fb33a030487d06dc643a0f0c39 Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 18 Aug 2018 13:52:35 -0400 Subject: [PATCH 17/26] change cost for NTCP and NTCP2 --- libi2pd/RouterInfo.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libi2pd/RouterInfo.cpp b/libi2pd/RouterInfo.cpp index 95e88963..79a70462 100644 --- a/libi2pd/RouterInfo.cpp +++ b/libi2pd/RouterInfo.cpp @@ -668,7 +668,7 @@ namespace data addr->host = boost::asio::ip::address::from_string (host); addr->port = port; addr->transportStyle = eTransportNTCP; - addr->cost = 2; + addr->cost = 6; addr->date = 0; for (const auto& it: *m_Addresses) // don't insert same address twice if (*it == *addr) return; @@ -703,7 +703,7 @@ namespace data auto addr = std::make_shared

(); addr->port = 0; addr->transportStyle = eTransportNTCP; - addr->cost = 14; + addr->cost = 3; addr->date = 0; addr->ntcp2.reset (new NTCP2Ext ()); addr->ntcp2->isNTCP2Only = true; // NTCP2 only address From 9882365ab45b8e0ae75fdbd102820ae83be3ea69 Mon Sep 17 00:00:00 2001 From: r4sas Date: Sat, 18 Aug 2018 22:56:31 +0000 Subject: [PATCH 18/26] fix NTCP IPv6 category name in transports, add conversion for leasesets expiring time --- daemon/HTTPServer.cpp | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/daemon/HTTPServer.cpp b/daemon/HTTPServer.cpp index 90bd772f..09b00707 100644 --- a/daemon/HTTPServer.cpp +++ b/daemon/HTTPServer.cpp @@ -92,6 +92,8 @@ namespace http { const char HTTP_PARAM_SAM_SESSION_ID[] = "id"; const char HTTP_PARAM_ADDRESS[] = "address"; + static std::string ConvertTime (uint64_t time); + static void ShowUptime (std::stringstream& s, int seconds) { int num; @@ -464,14 +466,14 @@ namespace http { s << "
!! Invalid !!
\r\n"; s << "
\r\n"; s << "\r\n

\r\n"; - s << "Expires: " << ls.GetExpirationTime() << "
\r\n"; + s << "Expires: " << ConvertTime(ls.GetExpirationTime()) << "
\r\n"; auto leases = ls.GetNonExpiredLeases(); s << "Non Expired Leases: " << leases.size() << "
\r\n"; for ( auto & l : leases ) { s << "Gateway: " << l->tunnelGateway.ToBase64() << "
\r\n"; s << "TunnelID: " << l->tunnelID << "
\r\n"; - s << "EndDate: " << l->endDate << "
\r\n"; + s << "EndDate: " << ConvertTime(l->endDate) << "
\r\n"; } s << "

\r\n
\r\n
\r\n"; } @@ -585,7 +587,7 @@ namespace http { } if (!tmp_s6.str ().empty ()) { - s << "
\r\n\r\n

"; + s << "

\r\n\r\n

"; s << tmp_s6.str () << "

\r\n
\r\n"; } } @@ -765,6 +767,16 @@ namespace http { } } + std::string ConvertTime (uint64_t time) + { + ldiv_t divTime = ldiv(time,1000); + time_t t = divTime.quot; + struct tm *tm = localtime(&t); + char date[128]; + snprintf(date, sizeof(date), "%02d/%02d/%d %02d:%02d:%02d.%03ld", tm->tm_mday, tm->tm_mon + 1, tm->tm_year + 1900, tm->tm_hour, tm->tm_min, tm->tm_sec, divTime.rem); + return date; + } + HTTPConnection::HTTPConnection (std::string hostname, std::shared_ptr socket): m_Socket (socket), m_Timer (socket->get_io_service ()), m_BufferLen (0), expected_host(hostname) From d9476fb5cae256d41005df96785cd7e7a06d3d48 Mon Sep 17 00:00:00 2001 From: orignal Date: Sun, 19 Aug 2018 16:17:57 -0400 Subject: [PATCH 19/26] set correct IV when NTCP2 address gets published --- libi2pd/RouterContext.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libi2pd/RouterContext.cpp b/libi2pd/RouterContext.cpp index b2774aa2..a3d33113 100644 --- a/libi2pd/RouterContext.cpp +++ b/libi2pd/RouterContext.cpp @@ -164,6 +164,7 @@ namespace i2p void RouterContext::PublishNTCP2Address (int port, bool publish) { + if (!m_NTCP2Keys) return; if (!port) port = rand () % (30777 - 9111) + 9111; // I2P network ports range bool updated = false; @@ -173,6 +174,7 @@ namespace i2p { address->port = port; address->ntcp2->isPublished = publish; + address->ntcp2->iv = m_NTCP2Keys->iv; updated = true; } } From 65cf14bfce16fecc1c862203627390a1d70c43ac Mon Sep 17 00:00:00 2001 From: r4sas Date: Mon, 20 Aug 2018 01:01:27 +0300 Subject: [PATCH 20/26] update android miniupnpc to 2.1 --- android/jni/Android.mk | 4 ++-- android_binary_only/jni/Android.mk | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/android/jni/Android.mk b/android/jni/Android.mk index d5a8f05f..80935236 100755 --- a/android/jni/Android.mk +++ b/android/jni/Android.mk @@ -68,6 +68,6 @@ include $(PREBUILT_STATIC_LIBRARY) LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := miniupnpc -LOCAL_SRC_FILES := $(MINIUPNP_PATH)/miniupnp-2.0/$(TARGET_ARCH_ABI)/lib/libminiupnpc.a -LOCAL_EXPORT_C_INCLUDES := $(MINIUPNP_PATH)/miniupnp-2.0/include +LOCAL_SRC_FILES := $(MINIUPNP_PATH)/miniupnpc-2.1/$(TARGET_ARCH_ABI)/lib/libminiupnpc.a +LOCAL_EXPORT_C_INCLUDES := $(MINIUPNP_PATH)/miniupnpc-2.1/include include $(PREBUILT_STATIC_LIBRARY) diff --git a/android_binary_only/jni/Android.mk b/android_binary_only/jni/Android.mk index ae56110c..fa677c83 100755 --- a/android_binary_only/jni/Android.mk +++ b/android_binary_only/jni/Android.mk @@ -69,6 +69,6 @@ include $(PREBUILT_STATIC_LIBRARY) LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := miniupnpc -LOCAL_SRC_FILES := $(MINIUPNP_PATH)/miniupnp-2.0/$(TARGET_ARCH_ABI)/lib/libminiupnpc.a -LOCAL_EXPORT_C_INCLUDES := $(MINIUPNP_PATH)/miniupnp-2.0/include +LOCAL_SRC_FILES := $(MINIUPNP_PATH)/miniupnpc-2.1/$(TARGET_ARCH_ABI)/lib/libminiupnpc.a +LOCAL_EXPORT_C_INCLUDES := $(MINIUPNP_PATH)/miniupnpc-2.1/include include $(PREBUILT_STATIC_LIBRARY) From b259ee89aa15b0a88f15789d64756678f6fe6fe6 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 22 Aug 2018 12:33:43 -0400 Subject: [PATCH 21/26] send RouterInfo from NTCP2Server's thread --- libi2pd/NTCP2.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp index 14e5e333..ff6eb01e 100644 --- a/libi2pd/NTCP2.cpp +++ b/libi2pd/NTCP2.cpp @@ -1005,7 +1005,7 @@ namespace transport void NTCP2Session::SendLocalRouterInfo () { if (!IsOutgoing ()) // we send it in SessionConfirmed - SendRouterInfo (); + m_Server.GetService ().post (std::bind (&NTCP2Session::SendRouterInfo, shared_from_this ())); } NTCP2Server::NTCP2Server (): From a83a839cffc33162c128b467a265f6cd685b9b6c Mon Sep 17 00:00:00 2001 From: l-n-s Date: Wed, 22 Aug 2018 18:22:54 -0400 Subject: [PATCH 22/26] Build docker image from openssl branch --- contrib/docker/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/docker/Dockerfile b/contrib/docker/Dockerfile index e7e60f37..22990995 100644 --- a/contrib/docker/Dockerfile +++ b/contrib/docker/Dockerfile @@ -2,7 +2,7 @@ FROM alpine:latest LABEL authors "Mikal Villa , Darknet Villain " # Expose git branch, tag and URL variables as arguments -ARG GIT_BRANCH="master" +ARG GIT_BRANCH="openssl" ENV GIT_BRANCH=${GIT_BRANCH} ARG GIT_TAG="" ENV GIT_TAG=${GIT_TAG} From 022f4d2c119a6d2ccc37d22d487ef806c9e506cb Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 23 Aug 2018 07:23:50 -0400 Subject: [PATCH 23/26] don't send message to not established session --- libi2pd/NTCP2.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp index ff6eb01e..58f928b4 100644 --- a/libi2pd/NTCP2.cpp +++ b/libi2pd/NTCP2.cpp @@ -959,6 +959,7 @@ namespace transport void NTCP2Session::SendRouterInfo () { + if (!IsEstablished ()) return; auto riLen = i2p::context.GetRouterInfo ().GetBufferLen (); int paddingSize = (riLen*NTCP2_MAX_PADDING_RATIO)/100; size_t payloadLen = riLen + paddingSize + 7; // 7 = 2*3 bytes header + 1 byte RI flag @@ -976,6 +977,7 @@ namespace transport void NTCP2Session::SendTermination (NTCP2TerminationReason reason) { + if (!IsEstablished ()) return; uint8_t payload[12] = { eNTCP2BlkTermination, 0, 9 }; htobe64buf (payload + 3, m_ReceiveSequenceNumber); payload[11] = (uint8_t)reason; From 71ac0286b1dd43491de669da30762f2a715d3078 Mon Sep 17 00:00:00 2001 From: orignal Date: Thu, 23 Aug 2018 10:24:44 -0400 Subject: [PATCH 24/26] 2.20.0 --- ChangeLog | 11 +++++++++++ Win32/installer.iss | 2 +- android/AndroidManifest.xml | 2 +- android/build.gradle | 2 +- contrib/rpm/i2pd.spec | 3 +++ debian/changelog | 6 ++++++ libi2pd/version.h | 4 ++-- 7 files changed, 25 insertions(+), 5 deletions(-) diff --git a/ChangeLog b/ChangeLog index 59a19a3c..d8ab87de 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,17 @@ # for this file format description, # see https://github.com/olivierlacan/keep-a-changelog +## [2.20.0] - 2018-08-23 +### Added +- Full implementation of NTCP2 +- Assets for android +### Changed +- armeabi-v7a and x86 in one apk for android +- NTCP2 is enabled by default +- Show lease's expiration time in readable format in the web console +### Fixed +- Correct names for transports in the web console + ## [2.19.0] - 2018-06-26 ### Added - ECIES support for RouterInfo diff --git a/Win32/installer.iss b/Win32/installer.iss index c4e1fffd..e340c65f 100644 --- a/Win32/installer.iss +++ b/Win32/installer.iss @@ -1,5 +1,5 @@ #define I2Pd_AppName "i2pd" -#define I2Pd_ver "2.19.0" +#define I2Pd_ver "2.20.0" #define I2Pd_Publisher "PurpleI2P" [Setup] diff --git a/android/AndroidManifest.xml b/android/AndroidManifest.xml index 705cce4e..9a2cffd5 100755 --- a/android/AndroidManifest.xml +++ b/android/AndroidManifest.xml @@ -3,7 +3,7 @@ package="org.purplei2p.i2pd" android:installLocation="auto" android:versionCode="1" - android:versionName="2.19.0"> + android:versionName="2.20.0"> /dev/null || \ %changelog +* Thu Aug 23 2018 orignal - 2.20.0 +- update to 2.20.0 + * Tue Jun 26 2018 orignal - 2.19.0 - update to 2.19.0 diff --git a/debian/changelog b/debian/changelog index 74c366d1..9d721eb8 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +i2pd (2.20.0-1) unstable; urgency=medium + + * updated to version 2.20.0/0.9.36 + + -- orignal Thu, 23 Aug 2018 16:00:00 +0000 + i2pd (2.19.0-1) unstable; urgency=medium * updated to version 2.19.0/0.9.35 diff --git a/libi2pd/version.h b/libi2pd/version.h index 129035ad..7c015e84 100644 --- a/libi2pd/version.h +++ b/libi2pd/version.h @@ -7,7 +7,7 @@ #define MAKE_VERSION(a,b,c) STRINGIZE(a) "." STRINGIZE(b) "." STRINGIZE(c) #define I2PD_VERSION_MAJOR 2 -#define I2PD_VERSION_MINOR 19 +#define I2PD_VERSION_MINOR 20 #define I2PD_VERSION_MICRO 0 #define I2PD_VERSION_PATCH 0 #define I2PD_VERSION MAKE_VERSION(I2PD_VERSION_MAJOR, I2PD_VERSION_MINOR, I2PD_VERSION_MICRO) @@ -21,7 +21,7 @@ #define I2P_VERSION_MAJOR 0 #define I2P_VERSION_MINOR 9 -#define I2P_VERSION_MICRO 35 +#define I2P_VERSION_MICRO 36 #define I2P_VERSION_PATCH 0 #define I2P_VERSION MAKE_VERSION(I2P_VERSION_MAJOR, I2P_VERSION_MINOR, I2P_VERSION_MICRO) From e70feceafe29c74ea59a25a130cb06ac648b5800 Mon Sep 17 00:00:00 2001 From: r4sas Date: Thu, 23 Aug 2018 18:06:37 +0300 Subject: [PATCH 25/26] add install target in OSX Makefile for homebrew formula --- Makefile.osx | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/Makefile.osx b/Makefile.osx index 3358cb10..13376040 100644 --- a/Makefile.osx +++ b/Makefile.osx @@ -31,6 +31,14 @@ endif # Disabled, since it will be the default make rule. I think its better # to define the default rule in Makefile and not Makefile. - torkel -#install: all -# test -d ${PREFIX} || mkdir -p ${PREFIX}/ -# cp -r i2p ${PREFIX}/ +install-brew: all + install -d ${PREFIX}/bin ${PREFIX}/etc/i2pd ${PREFIX}/share/doc/i2pd ${PREFIX}/share/i2pd ${PREFIX}/share/man/man1 ${PREFIX}/var/lib/i2pd + install -m 755 ${I2PD} ${PREFIX}/bin/ + install -m 644 contrib/i2pd.conf contrib/subscriptions.txt contrib/tunnels.conf ${PREFIX}/etc/i2pd + @cp -R contrib/certificates ${PREFIX}/share/i2pd/ + install -m 644 ChangeLog LICENSE README.md contrib/i2pd.conf contrib/subscriptions.txt contrib/tunnels.conf ${PREFIX}/share/doc/i2pd + @gzip debian/i2pd.1 && install debian/i2pd.1.gz ${PREFIX}/share/man/man1 + @ln -sf ${PREFIX}/share/i2pd/certificates ${PREFIX}/var/lib/i2pd/ + @ln -sf ${PREFIX}/etc/i2pd/i2pd.conf ${PREFIX}/var/lib/i2pd/i2pd.conf + @ln -sf ${PREFIX}/etc/i2pd/subscriptions.txt ${PREFIX}/var/lib/i2pd/subscriptions.txt + @ln -sf ${PREFIX}/etc/i2pd/tunnels.conf ${PREFIX}/var/lib/i2pd/tunnels.conf From c0d1e2c07aac4bf2282b9244aafb8bce15069835 Mon Sep 17 00:00:00 2001 From: r4sas Date: Thu, 23 Aug 2018 18:10:05 +0300 Subject: [PATCH 26/26] 2.20 --- appveyor.yml | 2 +- contrib/rpm/i2pd-git.spec | 2 +- contrib/rpm/i2pd.spec | 2 +- qt/i2pd_qt/android/AndroidManifest.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 27f563ef..e0c09fc1 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,4 +1,4 @@ -version: 2.19.{build} +version: 2.20.{build} pull_requests: do_not_increment_build_number: true branches: diff --git a/contrib/rpm/i2pd-git.spec b/contrib/rpm/i2pd-git.spec index 02986475..3539c19b 100644 --- a/contrib/rpm/i2pd-git.spec +++ b/contrib/rpm/i2pd-git.spec @@ -1,7 +1,7 @@ %define git_hash %(git rev-parse HEAD | cut -c -7) Name: i2pd-git -Version: 2.19.0 +Version: 2.20.0 Release: git%{git_hash}%{?dist} Summary: I2P router written in C++ Conflicts: i2pd diff --git a/contrib/rpm/i2pd.spec b/contrib/rpm/i2pd.spec index 1a20e483..edad8228 100644 --- a/contrib/rpm/i2pd.spec +++ b/contrib/rpm/i2pd.spec @@ -1,5 +1,5 @@ Name: i2pd -Version: 2.19.0 +Version: 2.20.0 Release: 1%{?dist} Summary: I2P router written in C++ Conflicts: i2pd-git diff --git a/qt/i2pd_qt/android/AndroidManifest.xml b/qt/i2pd_qt/android/AndroidManifest.xml index d98e24d4..c62e118e 100644 --- a/qt/i2pd_qt/android/AndroidManifest.xml +++ b/qt/i2pd_qt/android/AndroidManifest.xml @@ -1,5 +1,5 @@ - +