diff --git a/ChangeLog b/ChangeLog index a8a382ca..d52260ab 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,9 +1,19 @@ # for this file format description, # see https://github.com/olivierlacan/keep-a-changelog +## [2.27.0] - 2019-07-03 +### Added +- Support of PSK and DH authentication for encrypted LeaseSet2 +### Changed +- Uptime is based on monotonic timer +### Fixed +- BOB status command response +- Correct NTCP2 port if NTCP is disabled +- Flood encrypted LeaseSet2 with store hash + ## [2.26.0] - 2019-06-07 ### Added -- HTTP method "PROFIND" +- HTTP method "PROPFIND" - Detection of external ipv6 address through the SSU - NTCP2 publishing depends on network status ### Changed @@ -11,6 +21,7 @@ - Response to BOB's "list" command - ipv6 address is not longer NTCP's local endpoint's address - Reseeds list +- HTTP_REFERER stripping in httpproxy (#823) ### Fixed - Check and handle incorrect BOB input - Ignore introducers for NTCP or NTCP2 addresses diff --git a/Win32/installer.iss b/Win32/installer.iss index 28df9ea8..b00523da 100644 --- a/Win32/installer.iss +++ b/Win32/installer.iss @@ -1,5 +1,5 @@ #define I2Pd_AppName "i2pd" -#define I2Pd_ver "2.26.0" +#define I2Pd_ver "2.27.0" #define I2Pd_Publisher "PurpleI2P" [Setup] diff --git a/android/build.gradle b/android/build.gradle index 327d3ec1..b2a83710 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -29,8 +29,8 @@ android { applicationId "org.purplei2p.i2pd" targetSdkVersion 28 minSdkVersion 14 - versionCode 2260 - versionName "2.26.0" + versionCode 2270 + versionName "2.27.0" ndk { abiFilters 'armeabi-v7a' abiFilters 'x86' diff --git a/appveyor.yml b/appveyor.yml index ddcd651a..dfbc656c 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,4 +1,4 @@ -version: 2.26.0.{build} +version: 2.27.0.{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 098084d7..1dda44b1 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.26.0 +Version: 2.27.0 Release: git%{git_hash}%{?dist} Summary: I2P router written in C++ Conflicts: i2pd @@ -110,6 +110,9 @@ getent passwd i2pd >/dev/null || \ %changelog +* Wed Jul 3 2019 orignal - 2.27.0 +- update to 2.27.0 + * Fri Jun 7 2019 orignal - 2.26.0 - update to 2.26.0 diff --git a/contrib/rpm/i2pd.spec b/contrib/rpm/i2pd.spec index 84fad674..67c7f4bf 100644 --- a/contrib/rpm/i2pd.spec +++ b/contrib/rpm/i2pd.spec @@ -1,5 +1,5 @@ Name: i2pd -Version: 2.26.0 +Version: 2.27.0 Release: 1%{?dist} Summary: I2P router written in C++ Conflicts: i2pd-git @@ -108,6 +108,9 @@ getent passwd i2pd >/dev/null || \ %changelog +* Wed Jul 3 2019 orignal - 2.27.0 +- update to 2.27.0 + * Fri Jun 7 2019 orignal - 2.26.0 - update to 2.26.0 diff --git a/debian/changelog b/debian/changelog index 1bd32f03..0f30a066 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,9 @@ +i2pd (2.27.0-1) unstable; urgency=medium + + * updated to version 2.27.0/0.9.41 + + -- orignal Wed, 3 Jul 2019 16:00:00 +0000 + i2pd (2.26.0-1) unstable; urgency=medium * updated to version 2.26.0 diff --git a/libi2pd/Crypto.cpp b/libi2pd/Crypto.cpp index cd6d5b8e..3c51a033 100644 --- a/libi2pd/Crypto.cpp +++ b/libi2pd/Crypto.cpp @@ -296,11 +296,20 @@ namespace crypto #if OPENSSL_X25519 m_Pkey = EVP_PKEY_new_raw_private_key (EVP_PKEY_X25519, NULL, priv, 32); m_Ctx = EVP_PKEY_CTX_new (m_Pkey, NULL); - memcpy (m_PublicKey, pub, 32); // TODO: verify against m_Pkey + if (pub) + memcpy (m_PublicKey, pub, 32); // TODO: verify against m_Pkey + else + { + size_t len = 32; + EVP_PKEY_get_raw_public_key (m_Pkey, m_PublicKey, &len); + } #else + m_Ctx = BN_CTX_new (); memcpy (m_PrivateKey, priv, 32); - memcpy (m_PublicKey, pub, 32); - m_Ctx = BN_CTX_new (); + if (pub) + memcpy (m_PublicKey, pub, 32); + else + GetEd25519 ()->ScalarMulB (m_PrivateKey, m_PublicKey, m_Ctx); #endif } diff --git a/libi2pd/Crypto.h b/libi2pd/Crypto.h index 5afc4c52..a4b6c2de 100644 --- a/libi2pd/Crypto.h +++ b/libi2pd/Crypto.h @@ -74,7 +74,7 @@ namespace crypto public: X25519Keys (); - X25519Keys (const uint8_t * priv, const uint8_t * pub); // for RouterContext + X25519Keys (const uint8_t * priv, const uint8_t * pub); // if pub is null, derive from priv ~X25519Keys (); void GenerateKeys (); diff --git a/libi2pd/Destination.cpp b/libi2pd/Destination.cpp index ba90342c..5187fedc 100644 --- a/libi2pd/Destination.cpp +++ b/libi2pd/Destination.cpp @@ -70,6 +70,16 @@ namespace client it = params->find (I2CP_PARAM_LEASESET_TYPE); if (it != params->end ()) m_LeaseSetType = std::stoi(it->second); + it = params->find (I2CP_PARAM_LEASESET_PRIV_KEY); + if (it != params->end ()) + { + m_LeaseSetPrivKey.reset (new i2p::data::Tag<32>()); + if (m_LeaseSetPrivKey->FromBase64 (it->second) != 32) + { + LogPrint(eLogError, "Destination: invalid value i2cp.leaseSetPrivKey ", it->second); + m_LeaseSetPrivKey.reset (nullptr); + } + } } } catch (std::exception & ex) @@ -422,7 +432,7 @@ namespace client auto it2 = m_LeaseSetRequests.find (key); if (it2 != m_LeaseSetRequests.end () && it2->second->requestedBlindedKey) { - auto ls2 = std::make_shared (buf + offset, len - offset, it2->second->requestedBlindedKey); + auto ls2 = std::make_shared (buf + offset, len - offset, it2->second->requestedBlindedKey, m_LeaseSetPrivKey ? *m_LeaseSetPrivKey : nullptr); if (ls2->IsValid ()) { m_RemoteLeaseSets[ls2->GetIdentHash ()] = ls2; // ident is not key diff --git a/libi2pd/Destination.h b/libi2pd/Destination.h index 64dd0b58..35a9dbae 100644 --- a/libi2pd/Destination.h +++ b/libi2pd/Destination.h @@ -55,6 +55,7 @@ namespace client const char I2CP_PARAM_LEASESET_TYPE[] = "i2cp.leaseSetType"; const int DEFAULT_LEASESET_TYPE = 1; const char I2CP_PARAM_LEASESET_ENCRYPTION_TYPE[] = "i2cp.leaseSetEncType"; + const char I2CP_PARAM_LEASESET_PRIV_KEY[] = "i2cp.leaseSetPrivKey"; // PSK decryption key, base64 // latency const char I2CP_PARAM_MIN_TUNNEL_LATENCY[] = "latency.min"; @@ -175,6 +176,7 @@ namespace client m_PublishDelayTimer, m_CleanupTimer; std::string m_Nickname; int m_LeaseSetType; + std::unique_ptr > m_LeaseSetPrivKey; // non-null if presented public: diff --git a/libi2pd/I2NPProtocol.cpp b/libi2pd/I2NPProtocol.cpp index 9f6c609b..afdd8dc5 100644 --- a/libi2pd/I2NPProtocol.cpp +++ b/libi2pd/I2NPProtocol.cpp @@ -258,12 +258,12 @@ namespace i2p return m; } - std::shared_ptr CreateDatabaseStoreMsg (std::shared_ptr leaseSet) + std::shared_ptr CreateDatabaseStoreMsg (const i2p::data::IdentHash& storeHash, std::shared_ptr leaseSet) { if (!leaseSet) return nullptr; auto m = NewI2NPShortMessage (); uint8_t * payload = m->GetPayload (); - memcpy (payload + DATABASE_STORE_KEY_OFFSET, leaseSet->GetIdentHash (), 32); + memcpy (payload + DATABASE_STORE_KEY_OFFSET, storeHash, 32); payload[DATABASE_STORE_TYPE_OFFSET] = leaseSet->GetStoreType (); // 1 for LeaseSet htobe32buf (payload + DATABASE_STORE_REPLY_TOKEN_OFFSET, 0); size_t size = DATABASE_STORE_HEADER_SIZE; diff --git a/libi2pd/I2NPProtocol.h b/libi2pd/I2NPProtocol.h index 5160acec..ca074aed 100644 --- a/libi2pd/I2NPProtocol.h +++ b/libi2pd/I2NPProtocol.h @@ -247,7 +247,7 @@ namespace tunnel std::shared_ptr CreateDatabaseSearchReply (const i2p::data::IdentHash& ident, std::vector routers); std::shared_ptr CreateDatabaseStoreMsg (std::shared_ptr router = nullptr, uint32_t replyToken = 0); - std::shared_ptr CreateDatabaseStoreMsg (std::shared_ptr leaseSet); // for floodfill only + std::shared_ptr CreateDatabaseStoreMsg (const i2p::data::IdentHash& storeHash, std::shared_ptr leaseSet); // for floodfill only std::shared_ptr CreateDatabaseStoreMsg (std::shared_ptr leaseSet, uint32_t replyToken = 0, std::shared_ptr replyTunnel = nullptr); bool IsRouterInfoMsg (std::shared_ptr msg); diff --git a/libi2pd/LeaseSet.cpp b/libi2pd/LeaseSet.cpp index 101f17d9..69a29377 100644 --- a/libi2pd/LeaseSet.cpp +++ b/libi2pd/LeaseSet.cpp @@ -479,7 +479,7 @@ namespace data } else { - LogPrint (eLogError, "LeaseSet2: Unexpected blinded key type ", blindedKeyType, " instread ", key->GetBlindedSigType ()); + LogPrint (eLogError, "LeaseSet2: Unexpected blinded key type ", blindedKeyType, " instead ", key->GetBlindedSigType ()); return; } // outer key @@ -506,7 +506,7 @@ namespace data if (authDataLen > 0) { memcpy (innerInput + 32, subcredential, 36); - i2p::crypto::HKDF (outerPlainText.data () + 1, innerInput, 68, "ELS2_L2K", keys); + i2p::crypto::HKDF (outerPlainText.data () + 1 + authDataLen, innerInput, 68, "ELS2_L2K", keys); } else // no authData presented, innerInput = subcredential || publishedTimestamp @@ -531,40 +531,75 @@ namespace data } } + // helper for ExtractClientAuthData + static inline bool GetAuthCookie (const uint8_t * authClients, int numClients, const uint8_t * okm, uint8_t * authCookie) + { + // try to find clientCookie_i for clientID_i = okm[44:51] + for (int i = 0; i < numClients; i++) + { + if (!memcmp (okm + 44, authClients + i*40, 8)) // clientID_i + { + // clientKey_i = okm[0:31] + // clientIV_i = okm[32:43] + i2p::crypto::ChaCha20 (authClients + i*40 + 8, 32, okm, okm + 32, authCookie); // clientCookie_i + return true; + } + } + return false; + } + size_t LeaseSet2::ExtractClientAuthData (const uint8_t * buf, size_t len, const uint8_t * secret, const uint8_t * subcredential, uint8_t * authCookie) const { size_t offset = 0; uint8_t flag = buf[offset]; offset++; // flag if (flag & 0x01) // client auth { - if (flag & 0x02) // PSK, bit 1 is set to 1 + if (!(flag & 0x0E)) // DH, bit 1-3 all zeroes + { + const uint8_t * ephemeralPublicKey = buf + offset; offset += 32; // ephemeralPublicKey + uint16_t numClients = bufbe16toh (buf + offset); offset += 2; // clients + const uint8_t * authClients = buf + offset; offset += numClients*40; // authClients + if (offset > len) + { + LogPrint (eLogError, "LeaseSet2: Too many clients ", numClients, " in DH auth data"); + return 0; + } + // calculate authCookie + if (secret) + { + i2p::crypto::X25519Keys ck (secret, nullptr); // derive cpk_i from csk_i + uint8_t authInput[100]; + ck.Agree (ephemeralPublicKey, authInput); // sharedSecret is first 32 bytes of authInput + memcpy (authInput + 32, ck.GetPublicKey (), 32); // cpk_i + memcpy (authInput + 64, subcredential, 36); + uint8_t okm[64]; // 52 actual data + i2p::crypto::HKDF (ephemeralPublicKey, authInput, 100, "ELS2_XCA", okm); + if (!GetAuthCookie (authClients, numClients, okm, authCookie)) + LogPrint (eLogError, "LeaseSet2: Client cookie DH not found"); + } + else + LogPrint (eLogError, "LeaseSet2: Can't calculate authCookie: csk_i is not provided"); + } + else if (flag & 0x02) // PSK, bit 1 is set to 1 { const uint8_t * authSalt = buf + offset; offset += 32; // authSalt uint16_t numClients = bufbe16toh (buf + offset); offset += 2; // clients const uint8_t * authClients = buf + offset; offset += numClients*40; // authClients + if (offset > len) + { + LogPrint (eLogError, "LeaseSet2: Too many clients ", numClients, " in PSK auth data"); + return 0; + } // calculate authCookie if (secret) { uint8_t authInput[68]; memcpy (authInput, secret, 32); - memcpy (authInput, subcredential, 36); + memcpy (authInput + 32, subcredential, 36); uint8_t okm[64]; // 52 actual data i2p::crypto::HKDF (authSalt, authInput, 68, "ELS2PSKA", okm); - // try to find clientCookie_i for clientID_i = okm[44:51] - bool found = false; - for (int i = 0; i < numClients; i++) - { - if (!memcmp (okm + 44, authClients + i*40, 8)) // clientID_i - { - // clientKey_i = okm[0:31] - // clientIV_i = okm[32:43] - i2p::crypto::ChaCha20 (authClients + i*40 + 8, 32, okm, okm + 32, authCookie); // clientCookie_i - found = true; - break; - } - } - if (!found) - LogPrint (eLogError, "LeaseSet2: Client cookie not found"); + if (!GetAuthCookie (authClients, numClients, okm, authCookie)) + LogPrint (eLogError, "LeaseSet2: Client cookie PSK not found"); } else LogPrint (eLogError, "LeaseSet2: Can't calculate authCookie: psk_i is not provided"); diff --git a/libi2pd/NTCP2.cpp b/libi2pd/NTCP2.cpp index 5b5073f9..368f1b3e 100644 --- a/libi2pd/NTCP2.cpp +++ b/libi2pd/NTCP2.cpp @@ -396,6 +396,10 @@ namespace transport { m_IsTerminated = true; m_IsEstablished = false; + boost::system::error_code ec; + m_Socket.shutdown(boost::asio::ip::tcp::socket::shutdown_both, ec); + if (ec) + LogPrint (eLogDebug, "NTCP2: Couldn't shutdown socket: ", ec.message ()); m_Socket.close (); transports.PeerDisconnected (shared_from_this ()); m_Server.RemoveNTCP2Session (shared_from_this ()); diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index 952c8017..b7479744 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -523,9 +523,10 @@ namespace data auto total = m_RouterInfos.size (); uint64_t expirationTimeout = NETDB_MAX_EXPIRATION_TIMEOUT*1000LL; uint64_t ts = i2p::util::GetMillisecondsSinceEpoch(); + auto uptime = i2p::context.GetUptime (); // routers don't expire if less than 90 or uptime is less than 1 hour - bool checkForExpiration = total > NETDB_MIN_ROUTERS && ts > (i2p::context.GetStartupTime () + 600)*1000LL; // 10 minutes - if (checkForExpiration && ts > (i2p::context.GetStartupTime () + 3600)*1000LL) // 1 hour + bool checkForExpiration = total > NETDB_MIN_ROUTERS && uptime > 600; // 10 minutes + if (checkForExpiration && uptime > 3600) // 1 hour expirationTimeout = i2p::context.IsFloodfill () ? NETDB_FLOODFILL_EXPIRATION_TIMEOUT*1000LL : NETDB_MIN_EXPIRATION_TIMEOUT*1000LL + (NETDB_MAX_EXPIRATION_TIMEOUT - NETDB_MIN_EXPIRATION_TIMEOUT)*1000LL*NETDB_MIN_ROUTERS/total; @@ -909,7 +910,7 @@ namespace data else if (!leaseSet->IsExpired ()) // we don't send back our LeaseSets { LogPrint (eLogDebug, "NetDb: requested LeaseSet ", key, " found"); - replyMsg = CreateDatabaseStoreMsg (leaseSet); + replyMsg = CreateDatabaseStoreMsg (ident, leaseSet); } } diff --git a/libi2pd/RouterContext.cpp b/libi2pd/RouterContext.cpp index d228b626..5ac26f7c 100644 --- a/libi2pd/RouterContext.cpp +++ b/libi2pd/RouterContext.cpp @@ -19,7 +19,7 @@ namespace i2p RouterContext::RouterContext (): m_LastUpdateTime (0), m_AcceptsTunnels (true), m_IsFloodfill (false), - m_StartupTime (0), m_ShareRatio (100), m_Status (eRouterStatusOK), + m_ShareRatio (100), m_Status (eRouterStatusOK), m_Error (eRouterErrorNone), m_NetID (I2PD_NET_ID) { } @@ -27,7 +27,7 @@ namespace i2p void RouterContext::Init () { srand (i2p::util::GetMillisecondsSinceEpoch () % 1000); - m_StartupTime = i2p::util::GetSecondsSinceEpoch (); + m_StartupTime = std::chrono::steady_clock::now(); if (!Load ()) CreateNewRouter (); m_Decryptor = m_Keys.CreateDecryptor (nullptr); @@ -183,17 +183,18 @@ namespace i2p void RouterContext::PublishNTCP2Address (int port, bool publish, bool v4only) { if (!m_NTCP2Keys) return; - if (!port) - { - port = rand () % (30777 - 9111) + 9111; // I2P network ports range - if (port == 9150) port = 9151; // Tor browser - } bool updated = false; for (auto& address : m_RouterInfo.GetAddresses ()) { if (address->IsNTCP2 () && (address->port != port || address->ntcp2->isPublished != publish) && (!v4only || address->host.is_v4 ())) { - address->port = port; + if (!port && !address->port) + { + // select random port only if address's port is not set + port = rand () % (30777 - 9111) + 9111; // I2P network ports range + if (port == 9150) port = 9151; // Tor browser + } + if (port) address->port = port; address->cost = publish ? 3 : 14; address->ntcp2->isPublished = publish; address->ntcp2->iv = m_NTCP2Keys->iv; @@ -715,7 +716,7 @@ namespace i2p uint32_t RouterContext::GetUptime () const { - return i2p::util::GetSecondsSinceEpoch () - m_StartupTime; + return std::chrono::duration_cast (std::chrono::steady_clock::now() - m_StartupTime).count (); } bool RouterContext::Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx) const diff --git a/libi2pd/RouterContext.h b/libi2pd/RouterContext.h index e680eff8..fc4b90dc 100644 --- a/libi2pd/RouterContext.h +++ b/libi2pd/RouterContext.h @@ -5,6 +5,7 @@ #include #include #include +#include #include #include "Identity.h" #include "RouterInfo.h" @@ -64,8 +65,7 @@ namespace i2p const uint8_t * GetNTCP2IV () const { return m_NTCP2Keys ? m_NTCP2Keys->iv : nullptr; }; i2p::crypto::X25519Keys& GetStaticKeys (); - uint32_t GetUptime () const; - uint32_t GetStartupTime () const { return m_StartupTime; }; + uint32_t GetUptime () const; // in seconds uint64_t GetLastUpdateTime () const { return m_LastUpdateTime; }; uint64_t GetBandwidthLimit () const { return m_BandwidthLimit; }; uint64_t GetTransitBandwidthLimit () const { return (m_BandwidthLimit*m_ShareRatio)/100LL; }; @@ -137,7 +137,7 @@ namespace i2p std::shared_ptr m_Decryptor; uint64_t m_LastUpdateTime; // in seconds bool m_AcceptsTunnels, m_IsFloodfill; - uint64_t m_StartupTime; // in seconds since epoch + std::chrono::time_point m_StartupTime; uint64_t m_BandwidthLimit; // allowed bandwidth int m_ShareRatio; RouterStatus m_Status; diff --git a/libi2pd/Tag.h b/libi2pd/Tag.h index 03e3bc06..8af82241 100644 --- a/libi2pd/Tag.h +++ b/libi2pd/Tag.h @@ -71,14 +71,14 @@ public: return std::string (str, str + l); } - void FromBase32 (const std::string& s) + size_t FromBase32 (const std::string& s) { - i2p::data::Base32ToByteStream (s.c_str (), s.length (), m_Buf, sz); + return i2p::data::Base32ToByteStream (s.c_str (), s.length (), m_Buf, sz); } - void FromBase64 (const std::string& s) + size_t FromBase64 (const std::string& s) { - i2p::data::Base64ToByteStream (s.c_str (), s.length (), m_Buf, sz); + return i2p::data::Base64ToByteStream (s.c_str (), s.length (), m_Buf, sz); } private: diff --git a/libi2pd/Transports.cpp b/libi2pd/Transports.cpp index b76d9312..a2783f6c 100644 --- a/libi2pd/Transports.cpp +++ b/libi2pd/Transports.cpp @@ -562,7 +562,10 @@ namespace transport { auto addr = router->GetSSUV6Address (); if (addr) - m_SSUServer->CreateDirectSession (router, { addr->host, (uint16_t)addr->port }, false); + m_SSUServer->GetServiceV6 ().post ([this, router, addr] + { + m_SSUServer->CreateDirectSession (router, { addr->host, (uint16_t)addr->port }, false); + }); } } } diff --git a/libi2pd/util.h b/libi2pd/util.h index 6da20ad6..eccdadf7 100644 --- a/libi2pd/util.h +++ b/libi2pd/util.h @@ -46,7 +46,7 @@ namespace util { auto tmp = m_Head; m_Head = static_cast(*(void * *)m_Head); // next - delete tmp; + ::operator delete ((void *)tmp); } } diff --git a/libi2pd/version.h b/libi2pd/version.h index 4ac7a7b0..cd96c677 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 26 +#define I2PD_VERSION_MINOR 27 #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 40 +#define I2P_VERSION_MICRO 41 #define I2P_VERSION_PATCH 0 #define I2P_VERSION MAKE_VERSION(I2P_VERSION_MAJOR, I2P_VERSION_MINOR, I2P_VERSION_MICRO) diff --git a/libi2pd_client/BOB.cpp b/libi2pd_client/BOB.cpp index 023be3b4..aba090dc 100644 --- a/libi2pd_client/BOB.cpp +++ b/libi2pd_client/BOB.cpp @@ -341,17 +341,17 @@ namespace client SendReplyOK(); } - void BOBCommandSession::SendData (const char * data) + void BOBCommandSession::SendRaw (const char * data) { std::ostream os(&m_SendBuffer); - os << "DATA " << data << std::endl; + os << data << std::endl; } void BOBCommandSession::BuildStatusLine(bool currentTunnel, BOBDestination *dest, std::string &out) { // helper lambdas - const auto isset = [](const std::string &str) { return str.empty() ? "not_set" : str; }; // for inhost, outhost - const auto issetNum = [&isset](const int p) { return isset(p == 0 ? "" : std::to_string(p)); }; // for inport, outport + const auto issetStr = [](const std::string &str) { return str.empty() ? "not_set" : str; }; // for inhost, outhost + const auto issetNum = [&issetStr](const int p) { return issetStr(p == 0 ? "" : std::to_string(p)); }; // for inport, outport const auto destExists = [](const BOBDestination * const dest) { return dest != nullptr; }; const auto destReady = [](const BOBDestination * const dest) { return dest->GetLocalDestination()->IsReady(); }; const auto bool_str = [](const bool v) { return v ? "true" : "false"; }; // bool -> str @@ -359,8 +359,8 @@ namespace client // tunnel info const std::string nickname = currentTunnel ? m_Nickname : dest->GetNickname(); const bool quiet = currentTunnel ? m_IsQuiet : dest->GetQuiet(); - const std::string inhost = isset(currentTunnel ? m_InHost : dest->GetInHost()); - const std::string outhost = isset(currentTunnel ? m_OutHost : dest->GetOutHost()); + const std::string inhost = issetStr(currentTunnel ? m_InHost : dest->GetInHost()); + const std::string outhost = issetStr(currentTunnel ? m_OutHost : dest->GetOutHost()); const std::string inport = issetNum(currentTunnel ? m_InPort : dest->GetInPort()); const std::string outport = issetNum(currentTunnel ? m_OutPort : dest->GetOutPort()); const bool keys = destExists(dest); // key must exist when destination is created @@ -370,7 +370,8 @@ namespace client // build line std::stringstream ss; - ss << "NICKNAME: " << nickname << " " << "STARTING: " << bool_str(starting) << " " + ss << "DATA " + << "NICKNAME: " << nickname << " " << "STARTING: " << bool_str(starting) << " " << "RUNNING: " << bool_str(running) << " " << "STOPPING: " << bool_str(stopping) << " " << "KEYS: " << bool_str(keys) << " " << "QUIET: " << bool_str(quiet) << " " << "INPORT: " << inport << " " << "INHOST: " << inhost << " " @@ -654,16 +655,16 @@ namespace client for (const auto& it: destinations) { BuildStatusLine(false, it.second, statusLine); - SendData (statusLine.c_str()); + SendRaw(statusLine.c_str()); if(m_Nickname.compare(it.second->GetNickname()) == 0) sentCurrent = true; } if(!sentCurrent && !m_Nickname.empty()) { - // add the current tunnel to the list + // add the current tunnel to the list. + // this is for the incomplete tunnel which has not been started yet. BuildStatusLine(true, m_CurrentDestination, statusLine); - LogPrint(eLogError, statusLine); - SendData(statusLine.c_str()); + SendRaw(statusLine.c_str()); } SendReplyOK ("Listing done"); } @@ -690,21 +691,23 @@ namespace client void BOBCommandSession::StatusCommandHandler (const char * operand, size_t len) { LogPrint (eLogDebug, "BOB: status ", operand); + const std::string name = operand; std::string statusLine; - if (m_Nickname == operand) + + // always prefer destination + auto ptr = m_Owner.FindDestination(name); + if(ptr != nullptr) { - // check current tunnel - BuildStatusLine(true, nullptr, statusLine); + // tunnel destination exists + BuildStatusLine(false, ptr, statusLine); SendReplyOK(statusLine.c_str()); } else { - // check other - std::string name = operand; - auto ptr = m_Owner.FindDestination(name); - if(ptr != nullptr) + if(m_Nickname == name && !name.empty()) { - BuildStatusLine(false, ptr, statusLine); + // tunnel is incomplete / has not been started yet + BuildStatusLine(true, nullptr, statusLine); SendReplyOK(statusLine.c_str()); } else diff --git a/libi2pd_client/BOB.h b/libi2pd_client/BOB.h index d531a13d..8f1af185 100644 --- a/libi2pd_client/BOB.h +++ b/libi2pd_client/BOB.h @@ -213,7 +213,7 @@ namespace client void HandleSent (const boost::system::error_code& ecode, std::size_t bytes_transferred); void SendReplyOK (const char * msg = nullptr); void SendReplyError (const char * msg); - void SendData (const char * data); + void SendRaw (const char * data); void BuildStatusLine(bool currentTunnel, BOBDestination *destination, std::string &out); diff --git a/libi2pd_client/ClientContext.cpp b/libi2pd_client/ClientContext.cpp index 3292419a..c286007c 100644 --- a/libi2pd_client/ClientContext.cpp +++ b/libi2pd_client/ClientContext.cpp @@ -395,6 +395,8 @@ namespace client options[I2CP_PARAM_LEASESET_TYPE] = GetI2CPOption(section, I2CP_PARAM_LEASESET_TYPE, DEFAULT_LEASESET_TYPE); std::string encType = GetI2CPStringOption(section, I2CP_PARAM_LEASESET_ENCRYPTION_TYPE, ""); if (encType.length () > 0) options[I2CP_PARAM_LEASESET_ENCRYPTION_TYPE] = encType; + std::string privKey = GetI2CPStringOption(section, I2CP_PARAM_LEASESET_PRIV_KEY, ""); + if (privKey.length () > 0) options[I2CP_PARAM_LEASESET_PRIV_KEY] = privKey; } void ClientContext::ReadI2CPOptionsFromConfig (const std::string& prefix, std::map& options) const diff --git a/qt/i2pd_qt/data/website.i2pd.i2pd.appdata.xml b/qt/i2pd_qt/data/website.i2pd.i2pd.appdata.xml index efb8a4d6..b16d0d5c 100644 --- a/qt/i2pd_qt/data/website.i2pd.i2pd.appdata.xml +++ b/qt/i2pd_qt/data/website.i2pd.i2pd.appdata.xml @@ -35,6 +35,7 @@ + diff --git a/qt/i2pd_qt/i2pd_qt.pro b/qt/i2pd_qt/i2pd_qt.pro index e24a3963..9a978731 100644 --- a/qt/i2pd_qt/i2pd_qt.pro +++ b/qt/i2pd_qt/i2pd_qt.pro @@ -4,19 +4,22 @@ greaterThan(QT_MAJOR_VERSION, 4): QT += widgets TARGET = i2pd_qt TEMPLATE = app -QMAKE_CXXFLAGS *= -std=c++11 -ggdb +QMAKE_CXXFLAGS *= -std=c++11 -Wno-unused-parameter -Wno-maybe-uninitialized DEFINES += USE_UPNP SOURCES += DaemonQT.cpp mainwindow.cpp \ ../../libi2pd/api.cpp \ ../../libi2pd/Base.cpp \ + ../../libi2pd/Blinding.cpp \ ../../libi2pd/BloomFilter.cpp \ + ../../libi2pd/ChaCha20.cpp \ ../../libi2pd/Config.cpp \ ../../libi2pd/CPU.cpp \ ../../libi2pd/Crypto.cpp \ - ../../libi2pd/CryptoKey.cpp \ + ../../libi2pd/CryptoKey.cpp \ ../../libi2pd/Datagram.cpp \ ../../libi2pd/Destination.cpp \ + ../../libi2pd/Ed25519.cpp \ ../../libi2pd/Event.cpp \ ../../libi2pd/Family.cpp \ ../../libi2pd/FS.cpp \ @@ -31,7 +34,9 @@ SOURCES += DaemonQT.cpp mainwindow.cpp \ ../../libi2pd/Log.cpp \ ../../libi2pd/NetDb.cpp \ ../../libi2pd/NetDbRequests.cpp \ + ../../libi2pd/NTCP2.cpp \ ../../libi2pd/NTCPSession.cpp \ + ../../libi2pd/Poly1305.cpp \ ../../libi2pd/Profiling.cpp \ ../../libi2pd/Reseed.cpp \ ../../libi2pd/RouterContext.cpp \ @@ -49,9 +54,6 @@ SOURCES += DaemonQT.cpp mainwindow.cpp \ ../../libi2pd/TunnelGateway.cpp \ ../../libi2pd/TunnelPool.cpp \ ../../libi2pd/util.cpp \ - ../../libi2pd/Ed25519.cpp \ - ../../libi2pd/Chacha20.cpp \ - ../../libi2pd/Poly1305.cpp \ ../../libi2pd_client/AddressBook.cpp \ ../../libi2pd_client/BOB.cpp \ ../../libi2pd_client/ClientContext.cpp \ @@ -64,42 +66,37 @@ SOURCES += DaemonQT.cpp mainwindow.cpp \ ../../libi2pd_client/SOCKS.cpp \ ../../libi2pd_client/Websocket.cpp \ ../../libi2pd_client/WebSocks.cpp \ + ../../daemon/Daemon.cpp \ + ../../daemon/HTTPServer.cpp \ + ../../daemon/I2PControl.cpp \ + ../../daemon/i2pd.cpp \ + ../../daemon/UPnP.cpp \ ClientTunnelPane.cpp \ MainWindowItems.cpp \ ServerTunnelPane.cpp \ SignatureTypeComboboxFactory.cpp \ TunnelConfig.cpp \ TunnelPane.cpp \ - ../../daemon/Daemon.cpp \ - ../../daemon/HTTPServer.cpp \ - ../../daemon/i2pd.cpp \ - ../../daemon/I2PControl.cpp \ - ../../daemon/UnixDaemon.cpp \ - ../../daemon/UPnP.cpp \ textbrowsertweaked1.cpp \ pagewithbackbutton.cpp \ widgetlock.cpp \ widgetlockregistry.cpp \ - logviewermanager.cpp \ - ../../libi2pd/NTCP2.cpp - -#qt creator does not handle this well -#SOURCES += $$files(../../libi2pd/*.cpp) -#SOURCES += $$files(../../libi2pd_client/*.cpp) -#SOURCES += $$files(../../daemon/*.cpp) -#SOURCES += $$files(./*.cpp) - -SOURCES -= ../../daemon/UnixDaemon.cpp + logviewermanager.cpp HEADERS += DaemonQT.h mainwindow.h \ ../../libi2pd/api.h \ ../../libi2pd/Base.h \ + ../../libi2pd/Blinding.h \ ../../libi2pd/BloomFilter.h \ + ../../libi2pd/ChaCha20.h \ ../../libi2pd/Config.h \ + ../../libi2pd/CPU.h \ ../../libi2pd/Crypto.h \ - ../../libi2pd/CryptoKey.h \ + ../../libi2pd/CryptoKey.h \ + ../../libi2pd/CryptoWorker.h \ ../../libi2pd/Datagram.h \ ../../libi2pd/Destination.h \ + ../../libi2pd/Ed25519.h \ ../../libi2pd/Event.h \ ../../libi2pd/Family.h \ ../../libi2pd/FS.h \ @@ -115,13 +112,16 @@ HEADERS += DaemonQT.h mainwindow.h \ ../../libi2pd/Log.h \ ../../libi2pd/NetDb.hpp \ ../../libi2pd/NetDbRequests.h \ + ../../libi2pd/NTCP2.h \ ../../libi2pd/NTCPSession.h \ + ../../libi2pd/Poly1305.h \ ../../libi2pd/Profiling.h \ ../../libi2pd/Queue.h \ ../../libi2pd/Reseed.h \ ../../libi2pd/RouterContext.h \ ../../libi2pd/RouterInfo.h \ ../../libi2pd/Signature.h \ + ../../libi2pd/Siphash.h \ ../../libi2pd/SSU.h \ ../../libi2pd/SSUData.h \ ../../libi2pd/SSUSession.h \ @@ -151,6 +151,10 @@ HEADERS += DaemonQT.h mainwindow.h \ ../../libi2pd_client/SOCKS.h \ ../../libi2pd_client/Websocket.h \ ../../libi2pd_client/WebSocks.h \ + ../../daemon/Daemon.h \ + ../../daemon/HTTPServer.h \ + ../../daemon/I2PControl.h \ + ../../daemon/UPnP.h \ ClientTunnelPane.h \ MainWindowItems.h \ ServerTunnelPane.h \ @@ -158,16 +162,11 @@ HEADERS += DaemonQT.h mainwindow.h \ TunnelConfig.h \ TunnelPane.h \ TunnelsPageUpdateListener.h \ - ../../daemon/Daemon.h \ - ../../daemon/HTTPServer.h \ - ../../daemon/I2PControl.h \ - ../../daemon/UPnP.h \ textbrowsertweaked1.h \ pagewithbackbutton.h \ widgetlock.h \ widgetlockregistry.h \ i2pd.rc \ - i2pd.rc \ logviewermanager.h INCLUDEPATH += ../../libi2pd