diff --git a/Config.cpp b/Config.cpp index d8dd6a27..6f4014ba 100644 --- a/Config.cpp +++ b/Config.cpp @@ -41,6 +41,8 @@ namespace config { ("datadir", value()->default_value(""), "Path to storage of i2pd data (RI, keys, peer profiles, ...)") ("host", value()->default_value("0.0.0.0"), "External IP") ("ifname", value()->default_value(""), "Network interface to bind to") + ("ifname4", value()->default_value(""), "Network interface to bind to for ipv4") + ("ifname6", value()->default_value(""), "Network interface to bind to for ipv6") ("nat", value()->zero_tokens()->default_value(true), "Should we assume we are behind NAT?") ("port", value()->default_value(0), "Port to listen for incoming connections (default: auto)") ("ipv4", value()->zero_tokens()->default_value(true), "Enable communication through ipv4") @@ -59,7 +61,7 @@ namespace config { ("close", value()->default_value("ask"), "Action on close: minimize, exit, ask") // TODO: add custom validator or something #endif ; - + options_description limits("Limits options"); limits.add_options() ("limits.coresize", value()->default_value(0), "Maximum size of corefile in Kb (0 - use system limit)") @@ -192,7 +194,7 @@ namespace config { ("trust.family", value()->default_value(""), "Router Familiy to trust for first hops") ("trust.routers", value()->default_value(""), "Only Connect to these routers") ("trust.hidden", value()->default_value(false), "Should we hide our router from other routers?"); - + options_description websocket("Websocket Options"); websocket.add_options() ("websockets.enabled", value()->default_value(false), "enable websocket server") diff --git a/Crypto.cpp b/Crypto.cpp index 54180677..91b0ad08 100644 --- a/Crypto.cpp +++ b/Crypto.cpp @@ -308,12 +308,12 @@ namespace crypto BN_free (b1); } - void ElGamalEncryption::Encrypt (const uint8_t * data, int len, uint8_t * encrypted, bool zeroPadding) const + void ElGamalEncryption::Encrypt (const uint8_t * data, uint8_t * encrypted, bool zeroPadding) const { // create m uint8_t m[255]; m[0] = 0xFF; - memcpy (m+33, data, len); + memcpy (m+33, data, 222); SHA256 (m+33, 222, m+1); // calculate b = b1*m mod p BIGNUM * b = BN_new (); diff --git a/Crypto.h b/Crypto.h index b9d25216..a04a93da 100644 --- a/Crypto.h +++ b/Crypto.h @@ -54,7 +54,7 @@ namespace crypto ElGamalEncryption (const uint8_t * key); ~ElGamalEncryption (); - void Encrypt (const uint8_t * data, int len, uint8_t * encrypted, bool zeroPadding = false) const; + void Encrypt (const uint8_t * data, uint8_t * encrypted, bool zeroPadding = false) const; private: @@ -302,7 +302,11 @@ inline void DSA_SIG_get0(const DSA_SIG *sig, const BIGNUM **pr, const BIGNUM **p { *pr = sig->r; *ps = sig->s; } inline int ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s) - { sig->r = r; sig->s = s; return 1; } + { + if (sig->r) BN_free (sig->r); + if (sig->s) BN_free (sig->s); + sig->r = r; sig->s = s; return 1; + } inline void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps) { *pr = sig->r; *ps = sig->s; } diff --git a/Destination.cpp b/Destination.cpp index 7b2e896d..80951dc4 100644 --- a/Destination.cpp +++ b/Destination.cpp @@ -13,7 +13,7 @@ namespace i2p namespace client { LeaseSetDestination::LeaseSetDestination (bool isPublic, const std::map * params): - m_IsRunning (false), m_Thread (nullptr), m_Work (m_Service), m_IsPublic (isPublic), + m_IsRunning (false), m_Thread (nullptr), m_IsPublic (isPublic), m_PublishReplyToken (0), m_PublishConfirmationTimer (m_Service), m_PublishVerificationTimer (m_Service), m_CleanupTimer (m_Service) { @@ -85,9 +85,6 @@ namespace client { if (m_IsRunning) Stop (); - for (auto& it: m_LeaseSetRequests) - it.second->Complete (nullptr); - m_LeaseSetRequests.clear (); if (m_Pool) i2p::tunnel::tunnels.DeleteTunnelPool (m_Pool); } @@ -113,12 +110,12 @@ namespace client { m_IsRunning = true; m_Pool->SetLocalDestination (shared_from_this ()); - m_Pool->SetActive (true); - m_Thread = new std::thread (std::bind (&LeaseSetDestination::Run, shared_from_this ())); - + m_Pool->SetActive (true); m_CleanupTimer.expires_from_now (boost::posix_time::minutes (DESTINATION_CLEANUP_TIMEOUT)); m_CleanupTimer.async_wait (std::bind (&LeaseSetDestination::HandleCleanupTimer, - shared_from_this (), std::placeholders::_1)); + shared_from_this (), std::placeholders::_1)); + m_Thread = new std::thread (std::bind (&LeaseSetDestination::Run, shared_from_this ())); + return true; } else @@ -132,6 +129,14 @@ namespace client m_CleanupTimer.cancel (); m_PublishConfirmationTimer.cancel (); m_PublishVerificationTimer.cancel (); + + for (auto& it: m_LeaseSetRequests) + { + it.second->Complete (nullptr); + it.second->requestTimeoutTimer.cancel (); + } + m_LeaseSetRequests.clear (); + m_IsRunning = false; if (m_Pool) { @@ -145,6 +150,7 @@ namespace client delete m_Thread; m_Thread = 0; } + CleanUp (); // GarlicDestination return true; } else @@ -700,13 +706,20 @@ namespace client { m_ReadyChecker.cancel(); m_StreamingDestination->Stop (); + m_StreamingDestination->SetOwner (nullptr); m_StreamingDestination = nullptr; for (auto& it: m_StreamingDestinationsByPorts) + { it.second->Stop (); - if(m_DatagramDestination) - delete m_DatagramDestination; - m_DatagramDestination = nullptr; - return true; + it.second->SetOwner (nullptr); + } + m_StreamingDestinationsByPorts.clear (); + if (m_DatagramDestination) + { + delete m_DatagramDestination; + m_DatagramDestination = nullptr; + } + return true; } else return false; diff --git a/Destination.h b/Destination.h index 5b3ee655..1ccb0a9c 100644 --- a/Destination.h +++ b/Destination.h @@ -137,7 +137,6 @@ namespace client volatile bool m_IsRunning; std::thread * m_Thread; boost::asio::io_service m_Service; - boost::asio::io_service::work m_Work; mutable std::mutex m_RemoteLeaseSetsMutex; std::map > m_RemoteLeaseSets; std::map > m_LeaseSetRequests; diff --git a/Garlic.cpp b/Garlic.cpp index 94ca82eb..ab20ac8f 100644 --- a/Garlic.cpp +++ b/Garlic.cpp @@ -188,7 +188,7 @@ namespace garlic RAND_bytes (elGamal.preIV, 32); // Pre-IV uint8_t iv[32]; // IV is first 16 bytes SHA256(elGamal.preIV, 32, iv); - m_ElGamalEncryption->Encrypt ((uint8_t *)&elGamal, sizeof(elGamal), buf, true); + m_ElGamalEncryption->Encrypt ((uint8_t *)&elGamal, buf, true); m_Encryption.SetIV (iv); buf += 514; len += 514; @@ -394,6 +394,12 @@ namespace garlic { } + void GarlicDestination::CleanUp () + { + m_Sessions.clear (); + m_DeliveryStatusSessions.clear (); + m_Tags.clear (); + } void GarlicDestination::AddSessionKey (const uint8_t * key, const uint8_t * tag) { if (key) diff --git a/Garlic.h b/Garlic.h index 010338cd..a7e2d264 100644 --- a/Garlic.h +++ b/Garlic.h @@ -156,6 +156,7 @@ namespace garlic GarlicDestination (): m_NumTags (32) {}; // 32 tags by default ~GarlicDestination (); + void CleanUp (); void SetNumTags (int numTags) { m_NumTags = numTags; }; std::shared_ptr GetRoutingSession (std::shared_ptr destination, bool attachLeaseSet); void CleanupExpiredTags (); diff --git a/RouterContext.cpp b/RouterContext.cpp index 7847bef7..3c37e88c 100644 --- a/RouterContext.cpp +++ b/RouterContext.cpp @@ -53,6 +53,8 @@ namespace i2p bool ipv6; i2p::config::GetOption("ipv6", ipv6); bool nat; i2p::config::GetOption("nat", nat); std::string ifname; i2p::config::GetOption("ifname", ifname); + std::string ifname4; i2p::config::GetOption("ifname4", ifname4); + std::string ifname6; i2p::config::GetOption("ifname6", ifname6); if (ipv4) { std::string host = "127.0.0.1"; @@ -61,6 +63,10 @@ namespace i2p else if (!nat && !ifname.empty()) /* bind to interface, we have no NAT so set external address too */ host = i2p::util::net::GetInterfaceAddress(ifname, false).to_string(); // v4 + + if(ifname4.size()) + host = i2p::util::net::GetInterfaceAddress(ifname4, false).to_string(); + routerInfo.AddSSUAddress (host.c_str(), port, routerInfo.GetIdentHash ()); routerInfo.AddNTCPAddress (host.c_str(), port); } @@ -71,9 +77,14 @@ namespace i2p i2p::config::GetOption("host", host); else if (!ifname.empty()) host = i2p::util::net::GetInterfaceAddress(ifname, true).to_string(); // v6 + + if(ifname6.size()) + host = i2p::util::net::GetInterfaceAddress(ifname6, true).to_string(); + routerInfo.AddSSUAddress (host.c_str(), port, routerInfo.GetIdentHash ()); routerInfo.AddNTCPAddress (host.c_str(), port); } + routerInfo.SetCaps (i2p::data::RouterInfo::eReachable | i2p::data::RouterInfo::eSSUTesting | i2p::data::RouterInfo::eSSUIntroducer); // LR, BC routerInfo.SetProperty ("netId", std::to_string (m_NetID)); diff --git a/Signature.h b/Signature.h index 1d90d8a3..a4f37980 100644 --- a/Signature.h +++ b/Signature.h @@ -155,9 +155,10 @@ namespace crypto ECDSAVerifier (const uint8_t * signingKey) { m_PublicKey = EC_KEY_new_by_curve_name (curve); - EC_KEY_set_public_key_affine_coordinates (m_PublicKey, - BN_bin2bn (signingKey, keyLen/2, NULL), - BN_bin2bn (signingKey + keyLen/2, keyLen/2, NULL)); + BIGNUM * x = BN_bin2bn (signingKey, keyLen/2, NULL); + BIGNUM * y = BN_bin2bn (signingKey + keyLen/2, keyLen/2, NULL); + EC_KEY_set_public_key_affine_coordinates (m_PublicKey, x, y); + BN_free (x); BN_free (y); } ~ECDSAVerifier () diff --git a/Streaming.h b/Streaming.h index e4a1562c..65a8d8b4 100644 --- a/Streaming.h +++ b/Streaming.h @@ -224,6 +224,7 @@ namespace stream void ResetAcceptor (); bool IsAcceptorSet () const { return m_Acceptor != nullptr; }; std::shared_ptr GetOwner () const { return m_Owner; }; + void SetOwner (std::shared_ptr owner) { m_Owner = owner; }; uint16_t GetLocalPort () const { return m_LocalPort; }; void HandleDataMessagePayload (const uint8_t * buf, size_t len); diff --git a/TunnelConfig.h b/TunnelConfig.h index 23417ed9..cb31243f 100644 --- a/TunnelConfig.h +++ b/TunnelConfig.h @@ -102,7 +102,7 @@ namespace tunnel 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::ElGamalEncryption elGamalEncryption (ident->GetEncryptionPublicKey ()); - elGamalEncryption.Encrypt (clearText, BUILD_REQUEST_RECORD_CLEAR_TEXT_SIZE, record + BUILD_REQUEST_RECORD_ENCRYPTED_OFFSET); + elGamalEncryption.Encrypt (clearText, record + BUILD_REQUEST_RECORD_ENCRYPTED_OFFSET); memcpy (record + BUILD_REQUEST_RECORD_TO_PEER_OFFSET, (const uint8_t *)ident->GetIdentHash (), 16); } }; diff --git a/docs/building/unix.md b/docs/building/unix.md index 17623159..b5c38aed 100644 --- a/docs/building/unix.md +++ b/docs/building/unix.md @@ -64,12 +64,10 @@ You will need a compiler and other tools that could be installed with `build-ess Also you will need a bunch of development libraries: sudo apt-get install \ - libboost-chrono-dev \ libboost-date-time-dev \ libboost-filesystem-dev \ libboost-program-options-dev \ libboost-system-dev \ - libboost-thread-dev \ libssl-dev If you need UPnP support miniupnpc development library should be installed (don't forget to rerun CMake with needed option):