mirror of
https://github.com/PurpleI2P/i2pd.git
synced 2025-02-02 02:54:01 +01:00
Merge remote-tracking branch 'purple/openssl' into fix-ntcp-threading-race
This commit is contained in:
commit
ff5c26adf2
6
Makefile
6
Makefile
|
@ -30,12 +30,12 @@ ifneq (, $(findstring darwin, $(SYS)))
|
|||
else
|
||||
include Makefile.osx
|
||||
endif
|
||||
else ifneq (, $(findstring linux, $(SYS))$(findstring gnu, $(SYS)))
|
||||
DAEMON_SRC += $(DAEMON_SRC_DIR)/UnixDaemon.cpp
|
||||
include Makefile.linux
|
||||
else ifneq (, $(findstring freebsd, $(SYS))$(findstring openbsd, $(SYS)))
|
||||
DAEMON_SRC += $(DAEMON_SRC_DIR)/UnixDaemon.cpp
|
||||
include Makefile.bsd
|
||||
else ifneq (, $(findstring linux, $(SYS)))
|
||||
DAEMON_SRC += $(DAEMON_SRC_DIR)/UnixDaemon.cpp
|
||||
include Makefile.linux
|
||||
else ifneq (, $(findstring mingw, $(SYS))$(findstring cygwin, $(SYS)))
|
||||
DAEMON_SRC += Win32/DaemonWin32.cpp Win32/Win32Service.cpp Win32/Win32App.cpp
|
||||
include Makefile.mingw
|
||||
|
|
|
@ -94,13 +94,17 @@ endif()
|
|||
|
||||
add_library(libi2pd ${LIBI2PD_SRC})
|
||||
set_target_properties(libi2pd PROPERTIES PREFIX "")
|
||||
install(TARGETS libi2pd
|
||||
EXPORT libi2pd
|
||||
ARCHIVE DESTINATION lib
|
||||
COMPONENT Libraries)
|
||||
|
||||
if (WITH_LIBRARY)
|
||||
install(TARGETS libi2pd
|
||||
EXPORT libi2pd
|
||||
ARCHIVE DESTINATION lib
|
||||
LIBRARY DESTINATION lib
|
||||
COMPONENT Libraries)
|
||||
# TODO Make libi2pd available to 3rd party projects via CMake as imported target
|
||||
# FIXME This pulls stdafx
|
||||
# install(EXPORT libi2pd DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
||||
endif()
|
||||
|
||||
set (CLIENT_SRC
|
||||
"${LIBI2PD_CLIENT_SRC_DIR}/AddressBook.cpp"
|
||||
|
@ -119,7 +123,17 @@ set (CLIENT_SRC
|
|||
if(WITH_WEBSOCKETS)
|
||||
list (APPEND CLIENT_SRC "${LIBI2PD_CLIENT_SRC_DIR}/Websocket.cpp")
|
||||
endif ()
|
||||
add_library(i2pdclient ${CLIENT_SRC})
|
||||
|
||||
add_library(libi2pdclient ${CLIENT_SRC})
|
||||
set_target_properties(libi2pdclient PROPERTIES PREFIX "")
|
||||
|
||||
if (WITH_LIBRARY)
|
||||
install(TARGETS libi2pdclient
|
||||
EXPORT libi2pdclient
|
||||
ARCHIVE DESTINATION lib
|
||||
LIBRARY DESTINATION lib
|
||||
COMPONENT Libraries)
|
||||
endif()
|
||||
|
||||
set(DAEMON_SRC_DIR ../daemon)
|
||||
|
||||
|
@ -303,7 +317,7 @@ if (WITH_PCH)
|
|||
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
|
||||
)
|
||||
target_compile_options(libi2pd PRIVATE /FIstdafx.h /Yustdafx.h /Zm155 "/Fp${CMAKE_BINARY_DIR}/stdafx.dir/$<CONFIG>/stdafx.pch")
|
||||
target_compile_options(i2pdclient PRIVATE /FIstdafx.h /Yustdafx.h /Zm155 "/Fp${CMAKE_BINARY_DIR}/stdafx.dir/$<CONFIG>/stdafx.pch")
|
||||
target_compile_options(libi2pdclient PRIVATE /FIstdafx.h /Yustdafx.h /Zm155 "/Fp${CMAKE_BINARY_DIR}/stdafx.dir/$<CONFIG>/stdafx.pch")
|
||||
else()
|
||||
string(TOUPPER ${CMAKE_BUILD_TYPE} BTU)
|
||||
get_directory_property(DEFS DEFINITIONS)
|
||||
|
@ -312,12 +326,12 @@ if (WITH_PCH)
|
|||
COMMAND ${CMAKE_CXX_COMPILER} ${FLAGS} -c ${CMAKE_CURRENT_SOURCE_DIR}/../libi2pd/stdafx.h -o ${CMAKE_BINARY_DIR}/stdafx.h.gch
|
||||
)
|
||||
target_compile_options(libi2pd PRIVATE -include libi2pd/stdafx.h)
|
||||
target_compile_options(i2pdclient PRIVATE -include libi2pd/stdafx.h)
|
||||
target_compile_options(libi2pdclient PRIVATE -include libi2pd/stdafx.h)
|
||||
endif()
|
||||
target_link_libraries(libi2pd stdafx)
|
||||
endif()
|
||||
|
||||
target_link_libraries(i2pdclient libi2pd)
|
||||
target_link_libraries(libi2pdclient libi2pd)
|
||||
|
||||
find_package ( Boost COMPONENTS system filesystem program_options date_time REQUIRED )
|
||||
if(NOT DEFINED Boost_INCLUDE_DIRS)
|
||||
|
@ -450,7 +464,7 @@ if (WITH_BINARY)
|
|||
if (WITH_STATIC)
|
||||
set(DL_LIB ${CMAKE_DL_LIBS})
|
||||
endif()
|
||||
target_link_libraries( "${PROJECT_NAME}" libi2pd i2pdclient ${DL_LIB} ${Boost_LIBRARIES} ${OPENSSL_LIBRARIES} ${ZLIB_LIBRARY} ${CMAKE_THREAD_LIBS_INIT} ${MINGW_EXTRA} ${DL_LIB} ${CMAKE_REQUIRED_LIBRARIES})
|
||||
target_link_libraries( "${PROJECT_NAME}" libi2pd libi2pdclient ${DL_LIB} ${Boost_LIBRARIES} ${OPENSSL_LIBRARIES} ${ZLIB_LIBRARY} ${CMAKE_THREAD_LIBS_INIT} ${MINGW_EXTRA} ${DL_LIB} ${CMAKE_REQUIRED_LIBRARIES})
|
||||
|
||||
install(TARGETS "${PROJECT_NAME}" RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT Runtime)
|
||||
set (APPS "\${CMAKE_INSTALL_PREFIX}/bin/${PROJECT_NAME}${CMAKE_EXECUTABLE_SUFFIX}")
|
||||
|
|
|
@ -8,6 +8,8 @@ User=i2pd
|
|||
Group=i2pd
|
||||
RuntimeDirectory=i2pd
|
||||
RuntimeDirectoryMode=0700
|
||||
LogsDirectory=i2pd
|
||||
LogsDirectoryMode=0700
|
||||
Type=simple
|
||||
ExecStart=/usr/sbin/i2pd --conf=/etc/i2pd/i2pd.conf --tunconf=/etc/i2pd/tunnels.conf --pidfile=/var/run/i2pd/i2pd.pid --logfile=/var/log/i2pd/i2pd.log --daemon --service
|
||||
ExecReload=/bin/kill -HUP $MAINPID
|
||||
|
|
|
@ -65,6 +65,7 @@ namespace client
|
|||
m_MethodHandlers["RouterInfo"] = &I2PControlService::RouterInfoHandler;
|
||||
m_MethodHandlers["RouterManager"] = &I2PControlService::RouterManagerHandler;
|
||||
m_MethodHandlers["NetworkSetting"] = &I2PControlService::NetworkSettingHandler;
|
||||
m_MethodHandlers["ClientServicesInfo"] = &I2PControlService::ClientServicesInfoHandler;
|
||||
|
||||
// I2PControl
|
||||
m_I2PControlHandlers["i2pcontrol.password"] = &I2PControlService::PasswordHandler;
|
||||
|
@ -92,6 +93,14 @@ namespace client
|
|||
// NetworkSetting
|
||||
m_NetworkSettingHandlers["i2p.router.net.bw.in"] = &I2PControlService::InboundBandwidthLimit;
|
||||
m_NetworkSettingHandlers["i2p.router.net.bw.out"] = &I2PControlService::OutboundBandwidthLimit;
|
||||
|
||||
// ClientServicesInfo
|
||||
m_ClientServicesInfoHandlers["I2PTunnel"] = &I2PControlService::I2PTunnelInfoHandler;
|
||||
m_ClientServicesInfoHandlers["HTTPProxy"] = &I2PControlService::HTTPProxyInfoHandler;
|
||||
m_ClientServicesInfoHandlers["SOCKS"] = &I2PControlService::SOCKSInfoHandler;
|
||||
m_ClientServicesInfoHandlers["SAM"] = &I2PControlService::SAMInfoHandler;
|
||||
m_ClientServicesInfoHandlers["BOB"] = &I2PControlService::BOBInfoHandler;
|
||||
m_ClientServicesInfoHandlers["I2CP"] = &I2PControlService::I2CPInfoHandler;
|
||||
}
|
||||
|
||||
I2PControlService::~I2PControlService ()
|
||||
|
@ -289,6 +298,13 @@ namespace client
|
|||
ss << "\"" << name << "\":" << std::fixed << std::setprecision(2) << value;
|
||||
}
|
||||
|
||||
void I2PControlService::InsertParam (std::ostringstream& ss, const std::string& name, const boost::property_tree::ptree& value) const
|
||||
{
|
||||
std::ostringstream buf;
|
||||
boost::property_tree::write_json (buf, value, false);
|
||||
ss << "\"" << name << "\":" << buf.str();
|
||||
}
|
||||
|
||||
void I2PControlService::SendResponse (std::shared_ptr<ssl_socket> socket,
|
||||
std::shared_ptr<I2PControlBuffer> buf, std::ostringstream& response, bool isHtml)
|
||||
{
|
||||
|
@ -457,6 +473,7 @@ namespace client
|
|||
InsertParam (results, "i2p.router.net.total.sent.bytes", (double)i2p::transport::transports.GetTotalSentBytes ());
|
||||
}
|
||||
|
||||
|
||||
// RouterManager
|
||||
|
||||
void I2PControlService::RouterManagerHandler (const boost::property_tree::ptree& params, std::ostringstream& results)
|
||||
|
@ -586,5 +603,178 @@ namespace client
|
|||
}
|
||||
EVP_PKEY_free (pkey);
|
||||
}
|
||||
|
||||
// ClientServicesInfo
|
||||
|
||||
void I2PControlService::ClientServicesInfoHandler (const boost::property_tree::ptree& params, std::ostringstream& results)
|
||||
{
|
||||
for (auto it = params.begin (); it != params.end (); it++)
|
||||
{
|
||||
LogPrint (eLogDebug, "I2PControl: ClientServicesInfo request: ", it->first);
|
||||
auto it1 = m_ClientServicesInfoHandlers.find (it->first);
|
||||
if (it1 != m_ClientServicesInfoHandlers.end ())
|
||||
{
|
||||
if (it != params.begin ()) results << ",";
|
||||
(this->*(it1->second))(results);
|
||||
}
|
||||
else
|
||||
LogPrint (eLogError, "I2PControl: ClientServicesInfo unknown request ", it->first);
|
||||
}
|
||||
}
|
||||
|
||||
void I2PControlService::I2PTunnelInfoHandler (std::ostringstream& results)
|
||||
{
|
||||
boost::property_tree::ptree pt;
|
||||
boost::property_tree::ptree client_tunnels, server_tunnels;
|
||||
|
||||
for (auto& it: i2p::client::context.GetClientTunnels ())
|
||||
{
|
||||
auto& ident = it.second->GetLocalDestination ()->GetIdentHash();
|
||||
boost::property_tree::ptree ct;
|
||||
ct.put("address", i2p::client::context.GetAddressBook ().ToAddress(ident));
|
||||
client_tunnels.add_child(it.second->GetName (), ct);
|
||||
}
|
||||
|
||||
auto& serverTunnels = i2p::client::context.GetServerTunnels ();
|
||||
if (!serverTunnels.empty ()) {
|
||||
for (auto& it: serverTunnels)
|
||||
{
|
||||
auto& ident = it.second->GetLocalDestination ()->GetIdentHash();
|
||||
boost::property_tree::ptree st;
|
||||
st.put("address", i2p::client::context.GetAddressBook ().ToAddress(ident));
|
||||
st.put("port", it.second->GetLocalPort ());
|
||||
server_tunnels.add_child(it.second->GetName (), st);
|
||||
}
|
||||
}
|
||||
|
||||
auto& clientForwards = i2p::client::context.GetClientForwards ();
|
||||
if (!clientForwards.empty ())
|
||||
{
|
||||
for (auto& it: clientForwards)
|
||||
{
|
||||
auto& ident = it.second->GetLocalDestination ()->GetIdentHash();
|
||||
boost::property_tree::ptree ct;
|
||||
ct.put("address", i2p::client::context.GetAddressBook ().ToAddress(ident));
|
||||
client_tunnels.add_child(it.second->GetName (), ct);
|
||||
}
|
||||
}
|
||||
|
||||
auto& serverForwards = i2p::client::context.GetServerForwards ();
|
||||
if (!serverForwards.empty ())
|
||||
{
|
||||
for (auto& it: serverForwards)
|
||||
{
|
||||
auto& ident = it.second->GetLocalDestination ()->GetIdentHash();
|
||||
boost::property_tree::ptree st;
|
||||
st.put("address", i2p::client::context.GetAddressBook ().ToAddress(ident));
|
||||
server_tunnels.add_child(it.second->GetName (), st);
|
||||
}
|
||||
}
|
||||
|
||||
pt.add_child("client", client_tunnels);
|
||||
pt.add_child("server", server_tunnels);
|
||||
|
||||
InsertParam (results, "I2PTunnel", pt);
|
||||
}
|
||||
|
||||
void I2PControlService::HTTPProxyInfoHandler (std::ostringstream& results)
|
||||
{
|
||||
boost::property_tree::ptree pt;
|
||||
|
||||
auto httpProxy = i2p::client::context.GetHttpProxy ();
|
||||
if (httpProxy)
|
||||
{
|
||||
auto& ident = httpProxy->GetLocalDestination ()->GetIdentHash();
|
||||
pt.put("enabled", true);
|
||||
pt.put("address", i2p::client::context.GetAddressBook ().ToAddress(ident));
|
||||
}
|
||||
else
|
||||
pt.put("enabled", false);
|
||||
|
||||
InsertParam (results, "HTTPProxy", pt);
|
||||
}
|
||||
|
||||
void I2PControlService::SOCKSInfoHandler (std::ostringstream& results)
|
||||
{
|
||||
boost::property_tree::ptree pt;
|
||||
|
||||
auto socksProxy = i2p::client::context.GetSocksProxy ();
|
||||
if (socksProxy)
|
||||
{
|
||||
auto& ident = socksProxy->GetLocalDestination ()->GetIdentHash();
|
||||
pt.put("enabled", true);
|
||||
pt.put("address", i2p::client::context.GetAddressBook ().ToAddress(ident));
|
||||
}
|
||||
else
|
||||
pt.put("enabled", false);
|
||||
|
||||
InsertParam (results, "SOCKS", pt);
|
||||
}
|
||||
|
||||
void I2PControlService::SAMInfoHandler (std::ostringstream& results)
|
||||
{
|
||||
boost::property_tree::ptree pt;
|
||||
auto sam = i2p::client::context.GetSAMBridge ();
|
||||
if (sam)
|
||||
{
|
||||
pt.put("enabled", true);
|
||||
boost::property_tree::ptree sam_sessions;
|
||||
for (auto& it: sam->GetSessions ())
|
||||
{
|
||||
boost::property_tree::ptree sam_session, sam_session_sockets;
|
||||
auto& name = it.second->localDestination->GetNickname ();
|
||||
auto& ident = it.second->localDestination->GetIdentHash();
|
||||
sam_session.put("name", name);
|
||||
sam_session.put("address", i2p::client::context.GetAddressBook ().ToAddress(ident));
|
||||
|
||||
for (const auto& socket: it.second->ListSockets())
|
||||
{
|
||||
boost::property_tree::ptree stream;
|
||||
stream.put("type", socket->GetSocketType ());
|
||||
stream.put("peer", socket->GetSocket ().remote_endpoint());
|
||||
|
||||
sam_session_sockets.push_back(std::make_pair("", stream));
|
||||
}
|
||||
sam_session.add_child("sockets", sam_session_sockets);
|
||||
sam_sessions.add_child(it.first, sam_session);
|
||||
}
|
||||
|
||||
pt.add_child("sessions", sam_sessions);
|
||||
}
|
||||
else
|
||||
pt.put("enabled", false);
|
||||
|
||||
InsertParam (results, "SAM", pt);
|
||||
}
|
||||
|
||||
void I2PControlService::BOBInfoHandler (std::ostringstream& results)
|
||||
{
|
||||
boost::property_tree::ptree pt;
|
||||
auto bob = i2p::client::context.GetBOBCommandChannel ();
|
||||
if (bob)
|
||||
{
|
||||
/* TODO more info */
|
||||
pt.put("enabled", true);
|
||||
}
|
||||
else
|
||||
pt.put("enabled", false);
|
||||
|
||||
InsertParam (results, "BOB", pt);
|
||||
}
|
||||
|
||||
void I2PControlService::I2CPInfoHandler (std::ostringstream& results)
|
||||
{
|
||||
boost::property_tree::ptree pt;
|
||||
auto i2cp = i2p::client::context.GetI2CPServer ();
|
||||
if (i2cp)
|
||||
{
|
||||
/* TODO more info */
|
||||
pt.put("enabled", true);
|
||||
}
|
||||
else
|
||||
pt.put("enabled", false);
|
||||
|
||||
InsertParam (results, "I2CP", pt);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -57,6 +57,7 @@ namespace client
|
|||
void InsertParam (std::ostringstream& ss, const std::string& name, int value) const;
|
||||
void InsertParam (std::ostringstream& ss, const std::string& name, double value) const;
|
||||
void InsertParam (std::ostringstream& ss, const std::string& name, const std::string& value) const;
|
||||
void InsertParam (std::ostringstream& ss, const std::string& name, const boost::property_tree::ptree& value) const;
|
||||
|
||||
// methods
|
||||
typedef void (I2PControlService::*MethodHandler)(const boost::property_tree::ptree& params, std::ostringstream& results);
|
||||
|
@ -67,6 +68,7 @@ namespace client
|
|||
void RouterInfoHandler (const boost::property_tree::ptree& params, std::ostringstream& results);
|
||||
void RouterManagerHandler (const boost::property_tree::ptree& params, std::ostringstream& results);
|
||||
void NetworkSettingHandler (const boost::property_tree::ptree& params, std::ostringstream& results);
|
||||
void ClientServicesInfoHandler (const boost::property_tree::ptree& params, std::ostringstream& results);
|
||||
|
||||
// I2PControl
|
||||
typedef void (I2PControlService::*I2PControlRequestHandler)(const std::string& value);
|
||||
|
@ -98,6 +100,15 @@ namespace client
|
|||
void InboundBandwidthLimit (const std::string& value, std::ostringstream& results);
|
||||
void OutboundBandwidthLimit (const std::string& value, std::ostringstream& results);
|
||||
|
||||
// ClientServicesInfo
|
||||
typedef void (I2PControlService::*ClientServicesInfoRequestHandler)(std::ostringstream& results);
|
||||
void I2PTunnelInfoHandler (std::ostringstream& results);
|
||||
void HTTPProxyInfoHandler (std::ostringstream& results);
|
||||
void SOCKSInfoHandler (std::ostringstream& results);
|
||||
void SAMInfoHandler (std::ostringstream& results);
|
||||
void BOBInfoHandler (std::ostringstream& results);
|
||||
void I2CPInfoHandler (std::ostringstream& results);
|
||||
|
||||
private:
|
||||
|
||||
std::string m_Password;
|
||||
|
@ -115,6 +126,7 @@ namespace client
|
|||
std::map<std::string, RouterInfoRequestHandler> m_RouterInfoHandlers;
|
||||
std::map<std::string, RouterManagerRequestHandler> m_RouterManagerHandlers;
|
||||
std::map<std::string, NetworkSettingRequestHandler> m_NetworkSettingHandlers;
|
||||
std::map<std::string, ClientServicesInfoRequestHandler> m_ClientServicesInfoHandlers;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -373,7 +373,7 @@ namespace crypto
|
|||
}
|
||||
|
||||
// ECIES
|
||||
void ECIESEncrypt (const EC_GROUP * curve, const EC_POINT * key, const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx)
|
||||
void ECIESEncrypt (const EC_GROUP * curve, const EC_POINT * key, const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx, bool zeroPadding)
|
||||
{
|
||||
BN_CTX_start (ctx);
|
||||
BIGNUM * q = BN_CTX_get (ctx);
|
||||
|
@ -386,10 +386,19 @@ namespace crypto
|
|||
EC_POINT_mul (curve, p, k, nullptr, nullptr, ctx);
|
||||
BIGNUM * x = BN_CTX_get (ctx), * y = BN_CTX_get (ctx);
|
||||
EC_POINT_get_affine_coordinates_GFp (curve, p, x, y, nullptr);
|
||||
encrypted[0] = 0;
|
||||
bn2buf (x, encrypted + 1, len);
|
||||
bn2buf (y, encrypted + 1 + len, len);
|
||||
RAND_bytes (encrypted + 1 + 2*len, 256 - 2*len);
|
||||
if (zeroPadding)
|
||||
{
|
||||
encrypted[0] = 0;
|
||||
bn2buf (x, encrypted + 1, len);
|
||||
bn2buf (y, encrypted + 1 + len, len);
|
||||
RAND_bytes (encrypted + 1 + 2*len, 256 - 2*len);
|
||||
}
|
||||
else
|
||||
{
|
||||
bn2buf (x, encrypted, len);
|
||||
bn2buf (y, encrypted + len, len);
|
||||
RAND_bytes (encrypted + 2*len, 256 - 2*len);
|
||||
}
|
||||
// ecryption key and iv
|
||||
EC_POINT_mul (curve, p, nullptr, key, k, ctx);
|
||||
EC_POINT_get_affine_coordinates_GFp (curve, p, x, y, nullptr);
|
||||
|
@ -403,16 +412,21 @@ namespace crypto
|
|||
memcpy (m+33, data, 222);
|
||||
SHA256 (m+33, 222, m+1);
|
||||
// encrypt
|
||||
encrypted[257] = 0;
|
||||
CBCEncryption encryption;
|
||||
encryption.SetKey (shared);
|
||||
encryption.SetIV (iv);
|
||||
encryption.Encrypt (m, 256, encrypted + 258);
|
||||
if (zeroPadding)
|
||||
{
|
||||
encrypted[257] = 0;
|
||||
encryption.Encrypt (m, 256, encrypted + 258);
|
||||
}
|
||||
else
|
||||
encryption.Encrypt (m, 256, encrypted + 256);
|
||||
EC_POINT_free (p);
|
||||
BN_CTX_end (ctx);
|
||||
}
|
||||
|
||||
bool ECIESDecrypt (const EC_GROUP * curve, const BIGNUM * key, const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx)
|
||||
bool ECIESDecrypt (const EC_GROUP * curve, const BIGNUM * key, const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx, bool zeroPadding)
|
||||
{
|
||||
bool ret = true;
|
||||
BN_CTX_start (ctx);
|
||||
|
@ -421,8 +435,16 @@ namespace crypto
|
|||
int len = BN_num_bytes (q);
|
||||
// point for shared secret
|
||||
BIGNUM * x = BN_CTX_get (ctx), * y = BN_CTX_get (ctx);
|
||||
BN_bin2bn (encrypted + 1, len, x);
|
||||
BN_bin2bn (encrypted + 1 + len, len, y);
|
||||
if (zeroPadding)
|
||||
{
|
||||
BN_bin2bn (encrypted + 1, len, x);
|
||||
BN_bin2bn (encrypted + 1 + len, len, y);
|
||||
}
|
||||
else
|
||||
{
|
||||
BN_bin2bn (encrypted, len, x);
|
||||
BN_bin2bn (encrypted + len, len, y);
|
||||
}
|
||||
auto p = EC_POINT_new (curve);
|
||||
if (EC_POINT_set_affine_coordinates_GFp (curve, p, x, y, nullptr))
|
||||
{
|
||||
|
@ -439,7 +461,10 @@ namespace crypto
|
|||
CBCDecryption decryption;
|
||||
decryption.SetKey (shared);
|
||||
decryption.SetIV (iv);
|
||||
decryption.Decrypt (encrypted + 258, 256, m);
|
||||
if (zeroPadding)
|
||||
decryption.Decrypt (encrypted + 258, 256, m);
|
||||
else
|
||||
decryption.Decrypt (encrypted + 256, 256, m);
|
||||
// verify and copy
|
||||
uint8_t hash[32];
|
||||
SHA256 (m + 33, 222, hash);
|
||||
|
|
|
@ -54,8 +54,8 @@ namespace crypto
|
|||
void GenerateElGamalKeyPair (uint8_t * priv, uint8_t * pub);
|
||||
|
||||
// ECIES
|
||||
void ECIESEncrypt (const EC_GROUP * curve, const EC_POINT * key, const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx); // 222 bytes data, 514 bytes encrypted
|
||||
bool ECIESDecrypt (const EC_GROUP * curve, const BIGNUM * key, const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx);
|
||||
void ECIESEncrypt (const EC_GROUP * curve, const EC_POINT * key, const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx, bool zeroPadding = false); // 222 bytes data, 514 bytes encrypted with zeropadding, 512 without
|
||||
bool ECIESDecrypt (const EC_GROUP * curve, const BIGNUM * key, const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx, bool zeroPadding = false);
|
||||
void GenerateECIESKeyPair (const EC_GROUP * curve, BIGNUM *& priv, EC_POINT *& pub);
|
||||
|
||||
// HMAC
|
||||
|
|
|
@ -12,9 +12,9 @@ namespace crypto
|
|||
memcpy (m_PublicKey, pub, 256);
|
||||
}
|
||||
|
||||
void ElGamalEncryptor::Encrypt (const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx)
|
||||
void ElGamalEncryptor::Encrypt (const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx, bool zeroPadding)
|
||||
{
|
||||
ElGamalEncrypt (m_PublicKey, data, encrypted, ctx, true);
|
||||
ElGamalEncrypt (m_PublicKey, data, encrypted, ctx, zeroPadding);
|
||||
}
|
||||
|
||||
ElGamalDecryptor::ElGamalDecryptor (const uint8_t * priv)
|
||||
|
@ -22,9 +22,9 @@ namespace crypto
|
|||
memcpy (m_PrivateKey, priv, 256);
|
||||
}
|
||||
|
||||
bool ElGamalDecryptor::Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx)
|
||||
bool ElGamalDecryptor::Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx, bool zeroPadding)
|
||||
{
|
||||
return ElGamalDecrypt (m_PrivateKey, encrypted, data, ctx, true);
|
||||
return ElGamalDecrypt (m_PrivateKey, encrypted, data, ctx, zeroPadding);
|
||||
}
|
||||
|
||||
ECIESP256Encryptor::ECIESP256Encryptor (const uint8_t * pub)
|
||||
|
@ -44,10 +44,10 @@ namespace crypto
|
|||
if (m_PublicKey) EC_POINT_free (m_PublicKey);
|
||||
}
|
||||
|
||||
void ECIESP256Encryptor::Encrypt (const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx)
|
||||
void ECIESP256Encryptor::Encrypt (const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx, bool zeroPadding)
|
||||
{
|
||||
if (m_Curve && m_PublicKey)
|
||||
ECIESEncrypt (m_Curve, m_PublicKey, data, encrypted, ctx);
|
||||
ECIESEncrypt (m_Curve, m_PublicKey, data, encrypted, ctx, zeroPadding);
|
||||
}
|
||||
|
||||
ECIESP256Decryptor::ECIESP256Decryptor (const uint8_t * priv)
|
||||
|
@ -62,10 +62,10 @@ namespace crypto
|
|||
if (m_PrivateKey) BN_free (m_PrivateKey);
|
||||
}
|
||||
|
||||
bool ECIESP256Decryptor::Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx)
|
||||
bool ECIESP256Decryptor::Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx, bool zeroPadding)
|
||||
{
|
||||
if (m_Curve && m_PrivateKey)
|
||||
return ECIESDecrypt (m_Curve, m_PrivateKey, encrypted, data, ctx);
|
||||
return ECIESDecrypt (m_Curve, m_PrivateKey, encrypted, data, ctx, zeroPadding);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -104,10 +104,10 @@ namespace crypto
|
|||
if (m_PublicKey) EC_POINT_free (m_PublicKey);
|
||||
}
|
||||
|
||||
void ECIESGOSTR3410Encryptor::Encrypt (const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx)
|
||||
void ECIESGOSTR3410Encryptor::Encrypt (const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx, bool zeroPadding)
|
||||
{
|
||||
if (m_PublicKey)
|
||||
ECIESEncrypt (GetGOSTR3410Curve (eGOSTR3410CryptoProA)->GetGroup (), m_PublicKey, data, encrypted, ctx);
|
||||
ECIESEncrypt (GetGOSTR3410Curve (eGOSTR3410CryptoProA)->GetGroup (), m_PublicKey, data, encrypted, ctx, zeroPadding);
|
||||
}
|
||||
|
||||
ECIESGOSTR3410Decryptor::ECIESGOSTR3410Decryptor (const uint8_t * priv)
|
||||
|
@ -120,10 +120,10 @@ namespace crypto
|
|||
if (m_PrivateKey) BN_free (m_PrivateKey);
|
||||
}
|
||||
|
||||
bool ECIESGOSTR3410Decryptor::Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx)
|
||||
bool ECIESGOSTR3410Decryptor::Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx, bool zeroPadding)
|
||||
{
|
||||
if (m_PrivateKey)
|
||||
return ECIESDecrypt (GetGOSTR3410Curve (eGOSTR3410CryptoProA)->GetGroup (), m_PrivateKey, encrypted, data, ctx);
|
||||
return ECIESDecrypt (GetGOSTR3410Curve (eGOSTR3410CryptoProA)->GetGroup (), m_PrivateKey, encrypted, data, ctx, zeroPadding);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ namespace crypto
|
|||
public:
|
||||
|
||||
virtual ~CryptoKeyEncryptor () {};
|
||||
virtual void Encrypt (const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx) = 0; // 222 bytes data, 512 bytes encrypted
|
||||
virtual void Encrypt (const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx, bool zeroPadding) = 0; // 222 bytes data, 512/514 bytes encrypted
|
||||
};
|
||||
|
||||
class CryptoKeyDecryptor
|
||||
|
@ -21,7 +21,7 @@ namespace crypto
|
|||
public:
|
||||
|
||||
virtual ~CryptoKeyDecryptor () {};
|
||||
virtual bool Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx) = 0; // 512 bytes encrypted, 222 bytes data
|
||||
virtual bool Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx, bool zeroPadding) = 0; // 512/514 bytes encrypted, 222 bytes data
|
||||
};
|
||||
|
||||
// ElGamal
|
||||
|
@ -30,7 +30,7 @@ namespace crypto
|
|||
public:
|
||||
|
||||
ElGamalEncryptor (const uint8_t * pub);
|
||||
void Encrypt (const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx);
|
||||
void Encrypt (const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx, bool zeroPadding);
|
||||
|
||||
private:
|
||||
|
||||
|
@ -42,7 +42,7 @@ namespace crypto
|
|||
public:
|
||||
|
||||
ElGamalDecryptor (const uint8_t * priv);
|
||||
bool Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx);
|
||||
bool Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx, bool zeroPadding);
|
||||
|
||||
private:
|
||||
|
||||
|
@ -57,7 +57,7 @@ namespace crypto
|
|||
|
||||
ECIESP256Encryptor (const uint8_t * pub);
|
||||
~ECIESP256Encryptor ();
|
||||
void Encrypt (const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx);
|
||||
void Encrypt (const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx, bool zeroPadding);
|
||||
|
||||
private:
|
||||
|
||||
|
@ -72,7 +72,7 @@ namespace crypto
|
|||
|
||||
ECIESP256Decryptor (const uint8_t * priv);
|
||||
~ECIESP256Decryptor ();
|
||||
bool Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx);
|
||||
bool Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx, bool zeroPadding);
|
||||
|
||||
private:
|
||||
|
||||
|
@ -90,7 +90,7 @@ namespace crypto
|
|||
|
||||
ECIESGOSTR3410Encryptor (const uint8_t * pub);
|
||||
~ECIESGOSTR3410Encryptor ();
|
||||
void Encrypt (const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx);
|
||||
void Encrypt (const uint8_t * data, uint8_t * encrypted, BN_CTX * ctx, bool zeroPadding);
|
||||
|
||||
private:
|
||||
|
||||
|
@ -104,7 +104,7 @@ namespace crypto
|
|||
|
||||
ECIESGOSTR3410Decryptor (const uint8_t * priv);
|
||||
~ECIESGOSTR3410Decryptor ();
|
||||
bool Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx);
|
||||
bool Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx, bool zeroPadding);
|
||||
|
||||
private:
|
||||
|
||||
|
|
|
@ -169,6 +169,46 @@ namespace client
|
|||
return false;
|
||||
}
|
||||
|
||||
bool LeaseSetDestination::Reconfigure(std::map<std::string, std::string> params)
|
||||
{
|
||||
|
||||
auto itr = params.find("i2cp.dontPublishLeaseSet");
|
||||
if (itr != params.end())
|
||||
{
|
||||
m_IsPublic = itr->second != "true";
|
||||
}
|
||||
|
||||
int inLen, outLen, inQuant, outQuant, numTags, minLatency, maxLatency;
|
||||
std::map<std::string, int&> intOpts = {
|
||||
{I2CP_PARAM_INBOUND_TUNNEL_LENGTH, inLen},
|
||||
{I2CP_PARAM_OUTBOUND_TUNNEL_LENGTH, outLen},
|
||||
{I2CP_PARAM_INBOUND_TUNNELS_QUANTITY, inQuant},
|
||||
{I2CP_PARAM_OUTBOUND_TUNNELS_QUANTITY, outQuant},
|
||||
{I2CP_PARAM_TAGS_TO_SEND, numTags},
|
||||
{I2CP_PARAM_MIN_TUNNEL_LATENCY, minLatency},
|
||||
{I2CP_PARAM_MAX_TUNNEL_LATENCY, maxLatency}
|
||||
};
|
||||
|
||||
auto pool = GetTunnelPool();
|
||||
inLen = pool->GetNumInboundHops();
|
||||
outLen = pool->GetNumOutboundHops();
|
||||
inQuant = pool->GetNumInboundTunnels();
|
||||
outQuant = pool->GetNumOutboundTunnels();
|
||||
minLatency = 0;
|
||||
maxLatency = 0;
|
||||
|
||||
for (auto & opt : intOpts)
|
||||
{
|
||||
itr = params.find(opt.first);
|
||||
if(itr != params.end())
|
||||
{
|
||||
opt.second = std::stoi(itr->second);
|
||||
}
|
||||
}
|
||||
pool->RequireLatency(minLatency, maxLatency);
|
||||
return pool->Reconfigure(inLen, outLen, inQuant, outQuant);
|
||||
}
|
||||
|
||||
std::shared_ptr<const i2p::data::LeaseSet> LeaseSetDestination::FindLeaseSet (const i2p::data::IdentHash& ident)
|
||||
{
|
||||
std::shared_ptr<i2p::data::LeaseSet> remoteLS;
|
||||
|
@ -241,8 +281,12 @@ namespace client
|
|||
i2p::garlic::GarlicDestination::SetLeaseSetUpdated ();
|
||||
if (m_IsPublic)
|
||||
{
|
||||
m_PublishVerificationTimer.cancel ();
|
||||
Publish ();
|
||||
auto s = shared_from_this ();
|
||||
m_Service.post ([s](void)
|
||||
{
|
||||
s->m_PublishVerificationTimer.cancel ();
|
||||
s->Publish ();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -984,7 +1028,7 @@ namespace client
|
|||
bool ClientDestination::Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx) const
|
||||
{
|
||||
if (m_Decryptor)
|
||||
return m_Decryptor->Decrypt (encrypted, data, ctx);
|
||||
return m_Decryptor->Decrypt (encrypted, data, ctx, true);
|
||||
else
|
||||
LogPrint (eLogError, "Destinations: decryptor is not set");
|
||||
return false;
|
||||
|
|
|
@ -96,6 +96,10 @@ namespace client
|
|||
|
||||
virtual bool Start ();
|
||||
virtual bool Stop ();
|
||||
|
||||
/** i2cp reconfigure */
|
||||
virtual bool Reconfigure(std::map<std::string, std::string> i2cpOpts);
|
||||
|
||||
bool IsRunning () const { return m_IsRunning; };
|
||||
boost::asio::io_service& GetService () { return m_Service; };
|
||||
std::shared_ptr<i2p::tunnel::TunnelPool> GetTunnelPool () { return m_Pool; };
|
||||
|
|
|
@ -327,7 +327,7 @@ namespace i2p
|
|||
{
|
||||
LogPrint (eLogDebug, "I2NP: Build request record ", i, " is ours");
|
||||
BN_CTX * ctx = BN_CTX_new ();
|
||||
i2p::crypto::ElGamalDecrypt (i2p::context.GetPrivateKeys ().GetPrivateKey () , record + BUILD_REQUEST_RECORD_ENCRYPTED_OFFSET, clearText, ctx);
|
||||
i2p::context.DecryptTunnelBuildRecord (record + BUILD_REQUEST_RECORD_ENCRYPTED_OFFSET, clearText, ctx);
|
||||
BN_CTX_free (ctx);
|
||||
// replace record to reply
|
||||
if (i2p::context.AcceptsTunnels () &&
|
||||
|
|
|
@ -212,7 +212,7 @@ namespace data
|
|||
{
|
||||
auto encryptor = m_Identity->CreateEncryptor (m_EncryptionKey);
|
||||
if (encryptor)
|
||||
encryptor->Encrypt (data, encrypted, ctx);
|
||||
encryptor->Encrypt (data, encrypted, ctx, true);
|
||||
}
|
||||
|
||||
LocalLeaseSet::LocalLeaseSet (std::shared_ptr<const IdentityEx> identity, const uint8_t * encryptionPublicKey, std::vector<std::shared_ptr<i2p::tunnel::InboundTunnel> > tunnels):
|
||||
|
|
|
@ -184,7 +184,7 @@ namespace transport
|
|||
}
|
||||
// TODO: check for number of pending keys
|
||||
auto work = new NTCPWork{shared_from_this()};
|
||||
m_Server.Work(work->session, [work]() -> std::function<void(void)> {
|
||||
m_Server.Work(work->session, [work, this]() -> std::function<void(void)> {
|
||||
if (!work->session->m_DHKeysPair)
|
||||
work->session->m_DHKeysPair = transports.GetNextDHKeysPair ();
|
||||
work->session->CreateAESKey (work->session->m_Establisher->phase1.pubKey);
|
||||
|
@ -250,7 +250,7 @@ namespace transport
|
|||
else
|
||||
{
|
||||
auto work = new NTCPWork{shared_from_this()};
|
||||
m_Server.Work(work->session, [work]() -> std::function<void(void)> {
|
||||
m_Server.Work(work->session, [work, this]() -> std::function<void(void)> {
|
||||
work->session->CreateAESKey (work->session->m_Establisher->phase2.pubKey);
|
||||
return std::bind(&NTCPSession::HandlePhase2, work->session, work);
|
||||
});
|
||||
|
|
|
@ -34,11 +34,7 @@ namespace i2p
|
|||
|
||||
void RouterContext::CreateNewRouter ()
|
||||
{
|
||||
#if defined(__x86_64__) || defined(__i386__) || defined(_MSC_VER)
|
||||
m_Keys = i2p::data::PrivateKeys::CreateRandomKeys (i2p::data::SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519);
|
||||
#else
|
||||
m_Keys = i2p::data::PrivateKeys::CreateRandomKeys (i2p::data::SIGNING_KEY_TYPE_DSA_SHA1);
|
||||
#endif
|
||||
SaveKeys ();
|
||||
NewRouterInfo ();
|
||||
}
|
||||
|
@ -482,6 +478,11 @@ namespace i2p
|
|||
|
||||
bool RouterContext::Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx) const
|
||||
{
|
||||
return m_Decryptor ? m_Decryptor->Decrypt (encrypted, data, ctx) : false;
|
||||
return m_Decryptor ? m_Decryptor->Decrypt (encrypted, data, ctx, true) : false;
|
||||
}
|
||||
|
||||
bool RouterContext::DecryptTunnelBuildRecord (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx) const
|
||||
{
|
||||
return m_Decryptor ? m_Decryptor->Decrypt (encrypted, data, ctx, false) : false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -61,6 +61,7 @@ namespace i2p
|
|||
void SetError (RouterError error) { m_Status = eRouterStatusError; m_Error = error; };
|
||||
int GetNetID () const { return m_NetID; };
|
||||
void SetNetID (int netID) { m_NetID = netID; };
|
||||
bool DecryptTunnelBuildRecord (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx) const;
|
||||
|
||||
void UpdatePort (int port); // called from Daemon
|
||||
void UpdateAddress (const boost::asio::ip::address& host); // called from SSU or Daemon
|
||||
|
|
|
@ -840,7 +840,7 @@ namespace data
|
|||
{
|
||||
auto encryptor = m_RouterIdentity->CreateEncryptor (nullptr);
|
||||
if (encryptor)
|
||||
encryptor->Encrypt (data, encrypted, ctx);
|
||||
encryptor->Encrypt (data, encrypted, ctx, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -670,10 +670,13 @@ namespace tunnel
|
|||
{
|
||||
if (!tunnel->IsRecreated () && ts + TUNNEL_RECREATION_THRESHOLD > tunnel->GetCreationTime () + TUNNEL_EXPIRATION_TIMEOUT)
|
||||
{
|
||||
tunnel->SetIsRecreated ();
|
||||
auto pool = tunnel->GetTunnelPool ();
|
||||
if (pool)
|
||||
// let it die if the tunnel pool has been reconfigured and this is old
|
||||
if (pool && tunnel->GetNumHops() == pool->GetNumOutboundHops())
|
||||
{
|
||||
tunnel->SetIsRecreated ();
|
||||
pool->RecreateOutboundTunnel (tunnel);
|
||||
}
|
||||
}
|
||||
if (ts + TUNNEL_EXPIRATION_THRESHOLD > tunnel->GetCreationTime () + TUNNEL_EXPIRATION_TIMEOUT)
|
||||
tunnel->SetState (eTunnelStateExpiring);
|
||||
|
@ -721,10 +724,13 @@ namespace tunnel
|
|||
{
|
||||
if (!tunnel->IsRecreated () && ts + TUNNEL_RECREATION_THRESHOLD > tunnel->GetCreationTime () + TUNNEL_EXPIRATION_TIMEOUT)
|
||||
{
|
||||
tunnel->SetIsRecreated ();
|
||||
auto pool = tunnel->GetTunnelPool ();
|
||||
if (pool)
|
||||
// let it die if the tunnel pool was reconfigured and has different number of hops
|
||||
if (pool && tunnel->GetNumHops() == pool->GetNumInboundHops())
|
||||
{
|
||||
tunnel->SetIsRecreated ();
|
||||
pool->RecreateInboundTunnel (tunnel);
|
||||
}
|
||||
}
|
||||
|
||||
if (ts + TUNNEL_EXPIRATION_THRESHOLD > tunnel->GetCreationTime () + TUNNEL_EXPIRATION_TIMEOUT)
|
||||
|
|
|
@ -105,6 +105,7 @@ namespace tunnel
|
|||
bool IsFailed () const { return m_State == eTunnelStateFailed; };
|
||||
bool IsRecreated () const { return m_IsRecreated; };
|
||||
void SetIsRecreated () { m_IsRecreated = true; };
|
||||
int GetNumHops () const { return m_Hops.size (); };
|
||||
virtual bool IsInbound() const = 0;
|
||||
|
||||
std::shared_ptr<TunnelPool> GetTunnelPool () const { return m_Pool; };
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
#include <sstream>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include "Crypto.h"
|
||||
#include "Identity.h"
|
||||
#include "RouterContext.h"
|
||||
#include "Timestamp.h"
|
||||
|
@ -35,6 +34,7 @@ namespace tunnel
|
|||
RAND_bytes (replyKey, 32);
|
||||
RAND_bytes (replyIV, 16);
|
||||
RAND_bytes ((uint8_t *)&tunnelID, 4);
|
||||
if (!tunnelID) tunnelID = 1; // tunnelID can't be zero
|
||||
isGateway = true;
|
||||
isEndpoint = true;
|
||||
ident = r;
|
||||
|
@ -50,6 +50,7 @@ namespace tunnel
|
|||
nextIdent = ident;
|
||||
isEndpoint = false;
|
||||
RAND_bytes ((uint8_t *)&nextTunnelID, 4);
|
||||
if (!nextTunnelID) nextTunnelID = 1; // tunnelID can't be zero
|
||||
}
|
||||
|
||||
void SetReplyHop (uint32_t replyTunnelID, const i2p::data::IdentHash& replyIdent)
|
||||
|
@ -101,7 +102,9 @@ namespace tunnel
|
|||
htobe32buf (clearText + BUILD_REQUEST_RECORD_REQUEST_TIME_OFFSET, i2p::util::GetHoursSinceEpoch ());
|
||||
htobe32buf (clearText + BUILD_REQUEST_RECORD_SEND_MSG_ID_OFFSET, replyMsgID);
|
||||
RAND_bytes (clearText + BUILD_REQUEST_RECORD_PADDING_OFFSET, BUILD_REQUEST_RECORD_CLEAR_TEXT_SIZE - BUILD_REQUEST_RECORD_PADDING_OFFSET);
|
||||
i2p::crypto::ElGamalEncrypt (ident->GetEncryptionPublicKey (), clearText, record + BUILD_REQUEST_RECORD_ENCRYPTED_OFFSET, ctx);
|
||||
auto encryptor = ident->CreateEncryptor (nullptr);
|
||||
if (encryptor)
|
||||
encryptor->Encrypt (clearText, record + BUILD_REQUEST_RECORD_ENCRYPTED_OFFSET, ctx, false);
|
||||
memcpy (record + BUILD_REQUEST_RECORD_TO_PEER_OFFSET, (const uint8_t *)ident->GetIdentHash (), 16);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -69,6 +69,18 @@ namespace tunnel
|
|||
m_Tests.clear ();
|
||||
}
|
||||
|
||||
bool TunnelPool::Reconfigure(int inHops, int outHops, int inQuant, int outQuant) {
|
||||
if( inHops >= 0 && outHops >= 0 && inQuant > 0 && outQuant > 0)
|
||||
{
|
||||
m_NumInboundHops = inHops;
|
||||
m_NumOutboundHops = outHops;
|
||||
m_NumInboundTunnels = inQuant;
|
||||
m_NumOutboundTunnels = outQuant;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void TunnelPool::TunnelCreated (std::shared_ptr<InboundTunnel> createdTunnel)
|
||||
{
|
||||
if (!m_IsActive) return;
|
||||
|
@ -479,11 +491,17 @@ namespace tunnel
|
|||
outboundTunnel = tunnels.GetNextOutboundTunnel ();
|
||||
LogPrint (eLogDebug, "Tunnels: Re-creating destination inbound tunnel...");
|
||||
std::shared_ptr<TunnelConfig> config;
|
||||
if (m_NumInboundHops > 0) config = std::make_shared<TunnelConfig>(tunnel->GetPeers ());
|
||||
auto newTunnel = tunnels.CreateInboundTunnel (config, outboundTunnel);
|
||||
newTunnel->SetTunnelPool (shared_from_this());
|
||||
if (newTunnel->IsEstablished ()) // zero hops
|
||||
TunnelCreated (newTunnel);
|
||||
if (m_NumInboundHops > 0 && tunnel->GetPeers().size())
|
||||
{
|
||||
config = std::make_shared<TunnelConfig>(tunnel->GetPeers ());
|
||||
}
|
||||
if (m_NumInboundHops == 0 || config)
|
||||
{
|
||||
auto newTunnel = tunnels.CreateInboundTunnel (config, outboundTunnel);
|
||||
newTunnel->SetTunnelPool (shared_from_this());
|
||||
if (newTunnel->IsEstablished ()) // zero hops
|
||||
TunnelCreated (newTunnel);
|
||||
}
|
||||
}
|
||||
|
||||
void TunnelPool::CreateOutboundTunnel ()
|
||||
|
@ -521,12 +539,17 @@ namespace tunnel
|
|||
{
|
||||
LogPrint (eLogDebug, "Tunnels: Re-creating destination outbound tunnel...");
|
||||
std::shared_ptr<TunnelConfig> config;
|
||||
if (m_NumOutboundHops > 0)
|
||||
if (m_NumOutboundHops > 0 && tunnel->GetPeers().size())
|
||||
{
|
||||
config = std::make_shared<TunnelConfig>(tunnel->GetPeers (), inboundTunnel->GetNextTunnelID (), inboundTunnel->GetNextIdentHash ());
|
||||
auto newTunnel = tunnels.CreateOutboundTunnel (config);
|
||||
newTunnel->SetTunnelPool (shared_from_this ());
|
||||
if (newTunnel->IsEstablished ()) // zero hops
|
||||
TunnelCreated (newTunnel);
|
||||
}
|
||||
if(m_NumOutboundHops == 0 || config)
|
||||
{
|
||||
auto newTunnel = tunnels.CreateOutboundTunnel (config);
|
||||
newTunnel->SetTunnelPool (shared_from_this ());
|
||||
if (newTunnel->IsEstablished ()) // zero hops
|
||||
TunnelCreated (newTunnel);
|
||||
}
|
||||
}
|
||||
else
|
||||
LogPrint (eLogDebug, "Tunnels: Can't re-create outbound tunnel, no inbound tunnels found");
|
||||
|
|
|
@ -78,7 +78,12 @@ namespace tunnel
|
|||
|
||||
int GetNumInboundTunnels () const { return m_NumInboundTunnels; };
|
||||
int GetNumOutboundTunnels () const { return m_NumOutboundTunnels; };
|
||||
int GetNumInboundHops() const { return m_NumInboundHops; };
|
||||
int GetNumOutboundHops() const { return m_NumOutboundHops; };
|
||||
|
||||
/** i2cp reconfigure */
|
||||
bool Reconfigure(int inboundHops, int outboundHops, int inboundQuant, int outboundQuant);
|
||||
|
||||
void SetCustomPeerSelector(ITunnelPeerSelector * selector);
|
||||
void UnsetCustomPeerSelector();
|
||||
bool HasCustomPeerSelector();
|
||||
|
|
|
@ -37,7 +37,7 @@ namespace client
|
|||
bool I2CPDestination::Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx) const
|
||||
{
|
||||
if (m_Decryptor)
|
||||
return m_Decryptor->Decrypt (encrypted, data, ctx);
|
||||
return m_Decryptor->Decrypt (encrypted, data, ctx, true);
|
||||
else
|
||||
LogPrint (eLogError, "I2CP: decryptor is not set");
|
||||
return false;
|
||||
|
@ -416,9 +416,60 @@ namespace client
|
|||
|
||||
void I2CPSession::ReconfigureSessionMessageHandler (const uint8_t * buf, size_t len)
|
||||
{
|
||||
// TODO: implement actual reconfiguration
|
||||
SendSessionStatusMessage (2); // updated
|
||||
}
|
||||
uint8_t status = 3; // rejected
|
||||
if(len > sizeof(uint16_t))
|
||||
{
|
||||
uint16_t sessionID = bufbe16toh(buf);
|
||||
if(sessionID == m_SessionID)
|
||||
{
|
||||
buf += sizeof(uint16_t);
|
||||
const uint8_t * body = buf;
|
||||
i2p::data::IdentityEx ident;
|
||||
if(ident.FromBuffer(buf, len - sizeof(uint16_t)))
|
||||
{
|
||||
if (ident == *m_Destination->GetIdentity())
|
||||
{
|
||||
size_t identsz = ident.GetFullLen();
|
||||
buf += identsz;
|
||||
uint16_t optssize = bufbe16toh(buf);
|
||||
if (optssize <= len - sizeof(uint16_t) - sizeof(uint64_t) - identsz - ident.GetSignatureLen() - sizeof(uint16_t))
|
||||
{
|
||||
buf += sizeof(uint16_t);
|
||||
std::map<std::string, std::string> opts;
|
||||
ExtractMapping(buf, optssize, opts);
|
||||
buf += optssize;
|
||||
//uint64_t date = bufbe64toh(buf);
|
||||
buf += sizeof(uint64_t);
|
||||
const uint8_t * sig = buf;
|
||||
if(ident.Verify(body, len - sizeof(uint16_t) - ident.GetSignatureLen(), sig))
|
||||
{
|
||||
if(m_Destination->Reconfigure(opts))
|
||||
{
|
||||
LogPrint(eLogInfo, "I2CP: reconfigured destination");
|
||||
status = 2; // updated
|
||||
}
|
||||
else
|
||||
LogPrint(eLogWarning, "I2CP: failed to reconfigure destination");
|
||||
}
|
||||
else
|
||||
LogPrint(eLogError, "I2CP: invalid reconfigure message signature");
|
||||
}
|
||||
else
|
||||
LogPrint(eLogError, "I2CP: mapping size missmatch");
|
||||
}
|
||||
else
|
||||
LogPrint(eLogError, "I2CP: destination missmatch");
|
||||
}
|
||||
else
|
||||
LogPrint(eLogError, "I2CP: malfromed destination");
|
||||
}
|
||||
else
|
||||
LogPrint(eLogError, "I2CP: session missmatch");
|
||||
}
|
||||
else
|
||||
LogPrint(eLogError, "I2CP: short message");
|
||||
SendSessionStatusMessage (status);
|
||||
}
|
||||
|
||||
void I2CPSession::SendSessionStatusMessage (uint8_t status)
|
||||
{
|
||||
|
|
|
@ -107,6 +107,21 @@ namespace client
|
|||
std::placeholders::_1, std::placeholders::_2));
|
||||
}
|
||||
|
||||
static bool SAMVersionAcceptable(const std::string & ver)
|
||||
{
|
||||
return ver == "3.0" || ver == "3.1";
|
||||
}
|
||||
|
||||
static bool SAMVersionTooLow(const std::string & ver)
|
||||
{
|
||||
return ver.size() && ver[0] < '3';
|
||||
}
|
||||
|
||||
static bool SAMVersionTooHigh(const std::string & ver)
|
||||
{
|
||||
return ver.size() && ver > "3.1";
|
||||
}
|
||||
|
||||
void SAMSocket::HandleHandshakeReceived (const boost::system::error_code& ecode, std::size_t bytes_transferred)
|
||||
{
|
||||
if (ecode)
|
||||
|
@ -132,19 +147,37 @@ namespace client
|
|||
|
||||
if (!strcmp (m_Buffer, SAM_HANDSHAKE))
|
||||
{
|
||||
std::string version("3.0");
|
||||
std::string maxver("3.1");
|
||||
std::string minver("3.0");
|
||||
// try to find MIN and MAX, 3.0 if not found
|
||||
if (separator)
|
||||
{
|
||||
separator++;
|
||||
std::map<std::string, std::string> params;
|
||||
ExtractParams (separator, params);
|
||||
//auto it = params.find (SAM_PARAM_MAX);
|
||||
// TODO: check MIN as well
|
||||
//if (it != params.end ())
|
||||
// version = it->second;
|
||||
auto it = params.find (SAM_PARAM_MAX);
|
||||
if (it != params.end ())
|
||||
maxver = it->second;
|
||||
it = params.find(SAM_PARAM_MIN);
|
||||
if (it != params.end ())
|
||||
minver = it->second;
|
||||
}
|
||||
if (version[0] == '3') // we support v3 (3.0 and 3.1) only
|
||||
// version negotiation
|
||||
std::string version;
|
||||
if (SAMVersionAcceptable(maxver))
|
||||
{
|
||||
version = maxver;
|
||||
}
|
||||
else if (SAMVersionAcceptable(minver))
|
||||
{
|
||||
version = minver;
|
||||
}
|
||||
else if (SAMVersionTooLow(minver) && SAMVersionTooHigh(maxver))
|
||||
{
|
||||
version = "3.0";
|
||||
}
|
||||
|
||||
if (SAMVersionAcceptable(version))
|
||||
{
|
||||
#ifdef _MSC_VER
|
||||
size_t l = sprintf_s (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_HANDSHAKE_REPLY, version.c_str ());
|
||||
|
@ -156,7 +189,7 @@ namespace client
|
|||
std::placeholders::_1, std::placeholders::_2));
|
||||
}
|
||||
else
|
||||
SendMessageReply (SAM_HANDSHAKE_I2P_ERROR, strlen (SAM_HANDSHAKE_I2P_ERROR), true);
|
||||
SendMessageReply (SAM_HANDSHAKE_NOVERSION, strlen (SAM_HANDSHAKE_NOVERSION), true);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -23,6 +23,7 @@ namespace client
|
|||
const int SAM_SESSION_READINESS_CHECK_INTERVAL = 20; // in seconds
|
||||
const char SAM_HANDSHAKE[] = "HELLO VERSION";
|
||||
const char SAM_HANDSHAKE_REPLY[] = "HELLO REPLY RESULT=OK VERSION=%s\n";
|
||||
const char SAM_HANDSHAKE_NOVERSION[] = "HELLO REPLY RESULT=NOVERSION\n";
|
||||
const char SAM_HANDSHAKE_I2P_ERROR[] = "HELLO REPLY RESULT=I2P_ERROR\n";
|
||||
const char SAM_SESSION_CREATE[] = "SESSION CREATE";
|
||||
const char SAM_SESSION_CREATE_REPLY_OK[] = "SESSION STATUS RESULT=OK DESTINATION=%s\n";
|
||||
|
|
Loading…
Reference in a new issue