From 79630e844b44083022a9dcd2ae0cf7b943012828 Mon Sep 17 00:00:00 2001 From: R4SAS Date: Fri, 7 Jun 2019 17:25:55 +0300 Subject: [PATCH 01/19] 2.26.0 --- ChangeLog | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index a8a382ca..f06a51b6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -3,7 +3,7 @@ ## [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 +11,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 From 213a292fd5432f671e75c24229ed82edd737ce59 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 7 Jun 2019 11:59:48 -0400 Subject: [PATCH 02/19] correct offsets for auth data --- libi2pd/LeaseSet.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/libi2pd/LeaseSet.cpp b/libi2pd/LeaseSet.cpp index 101f17d9..daacc7f1 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 @@ -542,12 +542,17 @@ namespace data 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 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] From 41f4f4713e21e1fc5400d56a744d26a077928fce Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 7 Jun 2019 14:51:08 -0400 Subject: [PATCH 03/19] handle i2cp.leaseSetPrivKey --- libi2pd/Destination.cpp | 12 +++++++++++- libi2pd/Destination.h | 2 ++ libi2pd/Tag.h | 8 ++++---- libi2pd_client/ClientContext.cpp | 2 ++ 4 files changed, 19 insertions(+), 5 deletions(-) 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/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_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 From e60549f8df64a105c9fc3bb03c1df299c98c7849 Mon Sep 17 00:00:00 2001 From: R4SAS Date: Sat, 8 Jun 2019 21:15:59 +0300 Subject: [PATCH 04/19] [qt] fix build --- qt/i2pd_qt/i2pd_qt.pro | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/qt/i2pd_qt/i2pd_qt.pro b/qt/i2pd_qt/i2pd_qt.pro index e24a3963..84acaea5 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,24 +66,23 @@ 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/UnixDaemon.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) From 48d02f7e0910329e1dc92fdc1b8ab6aefd00ccef Mon Sep 17 00:00:00 2001 From: R4SAS Date: Sat, 8 Jun 2019 22:24:11 +0300 Subject: [PATCH 05/19] [qt] update headers, fix ChaCha source name, remove duplicates --- qt/i2pd_qt/i2pd_qt.pro | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/qt/i2pd_qt/i2pd_qt.pro b/qt/i2pd_qt/i2pd_qt.pro index 84acaea5..46dd4a1b 100644 --- a/qt/i2pd_qt/i2pd_qt.pro +++ b/qt/i2pd_qt/i2pd_qt.pro @@ -12,7 +12,7 @@ SOURCES += DaemonQT.cpp mainwindow.cpp \ ../../libi2pd/Base.cpp \ ../../libi2pd/Blinding.cpp \ ../../libi2pd/BloomFilter.cpp \ - ../../libi2pd/Chacha20.cpp \ + ../../libi2pd/ChaCha20.cpp \ ../../libi2pd/Config.cpp \ ../../libi2pd/CPU.cpp \ ../../libi2pd/Crypto.cpp \ @@ -90,17 +90,22 @@ SOURCES += DaemonQT.cpp mainwindow.cpp \ #SOURCES += $$files(../../daemon/*.cpp) #SOURCES += $$files(./*.cpp) -SOURCES -= ../../daemon/UnixDaemon.cpp +#SOURCES -= ../../daemon/UnixDaemon.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 \ @@ -116,13 +121,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 \ @@ -152,6 +160,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 \ @@ -159,16 +171,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 From a74065f7758b3105afb043b81f1eefb92eaae6d5 Mon Sep 17 00:00:00 2001 From: R4SAS Date: Sun, 9 Jun 2019 01:04:43 +0300 Subject: [PATCH 06/19] [qt] dont build UnixDaemon.cpp --- qt/i2pd_qt/i2pd_qt.pro | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/qt/i2pd_qt/i2pd_qt.pro b/qt/i2pd_qt/i2pd_qt.pro index 46dd4a1b..9a978731 100644 --- a/qt/i2pd_qt/i2pd_qt.pro +++ b/qt/i2pd_qt/i2pd_qt.pro @@ -70,7 +70,6 @@ SOURCES += DaemonQT.cpp mainwindow.cpp \ ../../daemon/HTTPServer.cpp \ ../../daemon/I2PControl.cpp \ ../../daemon/i2pd.cpp \ - ../../daemon/UnixDaemon.cpp \ ../../daemon/UPnP.cpp \ ClientTunnelPane.cpp \ MainWindowItems.cpp \ @@ -82,15 +81,7 @@ SOURCES += DaemonQT.cpp mainwindow.cpp \ pagewithbackbutton.cpp \ widgetlock.cpp \ widgetlockregistry.cpp \ - logviewermanager.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 \ From f6f45eab3946d772d48c58c42a828485fd7044d2 Mon Sep 17 00:00:00 2001 From: orignal Date: Sat, 8 Jun 2019 21:23:25 -0400 Subject: [PATCH 07/19] flood encrypted LeaseSet2 with store hash --- libi2pd/I2NPProtocol.cpp | 4 ++-- libi2pd/I2NPProtocol.h | 2 +- libi2pd/NetDb.cpp | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) 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/NetDb.cpp b/libi2pd/NetDb.cpp index 952c8017..07272a83 100644 --- a/libi2pd/NetDb.cpp +++ b/libi2pd/NetDb.cpp @@ -909,7 +909,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); } } From c8eeefe19474c6447451b74f9e4205165b13d43a Mon Sep 17 00:00:00 2001 From: rszibele Date: Mon, 10 Jun 2019 23:04:59 +0200 Subject: [PATCH 08/19] fix build on BSDs, as "isset" is a defined macro. --- libi2pd_client/BOB.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libi2pd_client/BOB.cpp b/libi2pd_client/BOB.cpp index 023be3b4..c329d86b 100644 --- a/libi2pd_client/BOB.cpp +++ b/libi2pd_client/BOB.cpp @@ -350,8 +350,8 @@ namespace client 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 From 74e8610ec93522eee466688fec1e44eaa27adfa5 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 11 Jun 2019 10:40:53 -0400 Subject: [PATCH 09/19] DH auth for encrypted LeaseSet2 --- libi2pd/Crypto.cpp | 15 ++++++++--- libi2pd/Crypto.h | 2 +- libi2pd/LeaseSet.cpp | 64 ++++++++++++++++++++++++++++++++------------ 3 files changed, 60 insertions(+), 21 deletions(-) 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/LeaseSet.cpp b/libi2pd/LeaseSet.cpp index daacc7f1..1d555ac4 100644 --- a/libi2pd/LeaseSet.cpp +++ b/libi2pd/LeaseSet.cpp @@ -531,20 +531,63 @@ 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 + 32, 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 auth data"); + LogPrint (eLogError, "LeaseSet2: Too many clients ", numClients, " in PSK auth data"); return 0; } // calculate authCookie @@ -555,21 +598,8 @@ namespace data 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"); From 3e932a55f4050e4f26c667b38a5670bdcc797a8f Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 11 Jun 2019 15:09:10 -0400 Subject: [PATCH 10/19] fixed typo --- libi2pd/LeaseSet.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd/LeaseSet.cpp b/libi2pd/LeaseSet.cpp index 1d555ac4..69a29377 100644 --- a/libi2pd/LeaseSet.cpp +++ b/libi2pd/LeaseSet.cpp @@ -571,7 +571,7 @@ namespace data 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 + 32, subcredential, 36); + 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)) From 13732ac33369df365132eb43ed9146221c69ec50 Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 14 Jun 2019 15:43:03 -0400 Subject: [PATCH 11/19] fix #1363 try connect in SSU's thread --- libi2pd/Transports.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) 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); + }); } } } From 832a9ab6b5d2af3cc64723090de15181783bc162 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 18 Jun 2019 15:47:58 -0400 Subject: [PATCH 12/19] don't set random NTCP2 port if already set --- libi2pd/RouterContext.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/libi2pd/RouterContext.cpp b/libi2pd/RouterContext.cpp index d228b626..46681f77 100644 --- a/libi2pd/RouterContext.cpp +++ b/libi2pd/RouterContext.cpp @@ -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; From 8e919ddc8e20eb31cd9acfd56b93fca9df094492 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 19 Jun 2019 11:43:04 -0400 Subject: [PATCH 13/19] use monotonic clock for uptime --- libi2pd/NetDb.cpp | 5 +++-- libi2pd/RouterContext.cpp | 6 +++--- libi2pd/RouterContext.h | 6 +++--- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/libi2pd/NetDb.cpp b/libi2pd/NetDb.cpp index 07272a83..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; diff --git a/libi2pd/RouterContext.cpp b/libi2pd/RouterContext.cpp index 46681f77..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); @@ -716,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; From cb8373e48710f922aaf764daab23e16e1e83c3eb Mon Sep 17 00:00:00 2001 From: rszibele Date: Tue, 25 Jun 2019 17:59:44 +0200 Subject: [PATCH 14/19] BOB: status response now correctly starts with "OK DATA". --- libi2pd_client/BOB.cpp | 11 ++++++----- libi2pd_client/BOB.h | 2 +- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/libi2pd_client/BOB.cpp b/libi2pd_client/BOB.cpp index c329d86b..828b8e8a 100644 --- a/libi2pd_client/BOB.cpp +++ b/libi2pd_client/BOB.cpp @@ -341,10 +341,10 @@ 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) @@ -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,7 +655,7 @@ 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; } @@ -663,7 +664,7 @@ namespace client // add the current tunnel to the list BuildStatusLine(true, m_CurrentDestination, statusLine); LogPrint(eLogError, statusLine); - SendData(statusLine.c_str()); + SendRaw(statusLine.c_str()); } SendReplyOK ("Listing done"); } 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); From a23e845c03275a77f57e81b5af989806dcd5ebf8 Mon Sep 17 00:00:00 2001 From: rszibele Date: Tue, 25 Jun 2019 19:04:27 +0200 Subject: [PATCH 15/19] BOB: improve comment and remove error log in list command --- libi2pd_client/BOB.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libi2pd_client/BOB.cpp b/libi2pd_client/BOB.cpp index 828b8e8a..b88eea81 100644 --- a/libi2pd_client/BOB.cpp +++ b/libi2pd_client/BOB.cpp @@ -661,9 +661,9 @@ namespace client } 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); SendRaw(statusLine.c_str()); } SendReplyOK ("Listing done"); From b75929497551b9186f207f90913612c19f4ee909 Mon Sep 17 00:00:00 2001 From: rszibele Date: Tue, 25 Jun 2019 19:18:40 +0200 Subject: [PATCH 16/19] BOB: fix status command. --- libi2pd_client/BOB.cpp | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/libi2pd_client/BOB.cpp b/libi2pd_client/BOB.cpp index b88eea81..aba090dc 100644 --- a/libi2pd_client/BOB.cpp +++ b/libi2pd_client/BOB.cpp @@ -691,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 From fecc0c464070133bfb71b4fe794f4edb5e952e00 Mon Sep 17 00:00:00 2001 From: orignal Date: Tue, 25 Jun 2019 16:37:06 -0400 Subject: [PATCH 17/19] don't call destructor twice --- libi2pd/util.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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); } } From 6ccef669203707e0b22544cf1e6a04490cf73230 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 26 Jun 2019 10:47:16 -0400 Subject: [PATCH 18/19] call shutdown before close --- libi2pd/NTCP2.cpp | 4 ++++ 1 file changed, 4 insertions(+) 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 ()); From 3acfb129cd1171fbdbec758a21d2294119c68917 Mon Sep 17 00:00:00 2001 From: orignal Date: Wed, 3 Jul 2019 12:38:55 -0400 Subject: [PATCH 19/19] 2.27.0 --- ChangeLog | 10 ++++++++++ Win32/installer.iss | 2 +- android/build.gradle | 4 ++-- appveyor.yml | 2 +- contrib/rpm/i2pd-git.spec | 5 ++++- contrib/rpm/i2pd.spec | 5 ++++- debian/changelog | 6 ++++++ libi2pd/version.h | 4 ++-- qt/i2pd_qt/data/website.i2pd.i2pd.appdata.xml | 1 + 9 files changed, 31 insertions(+), 8 deletions(-) diff --git a/ChangeLog b/ChangeLog index f06a51b6..d52260ab 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,6 +1,16 @@ # 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 "PROPFIND" 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/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/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 @@ +