diff --git a/AddressBook.cpp b/AddressBook.cpp index 3b630a65..f66387db 100644 --- a/AddressBook.cpp +++ b/AddressBook.cpp @@ -193,11 +193,7 @@ namespace client delete m_Storage; m_Storage = nullptr; } - if (m_DefaultSubscription) - { - delete m_DefaultSubscription; - m_DefaultSubscription = nullptr; - } + m_DefaultSubscription = nullptr; for (auto it: m_Subscriptions) delete it; m_Subscriptions.clear (); @@ -278,19 +274,6 @@ namespace client LoadHostsFromStream (f); m_IsLoaded = true; } - else - { - // if not found download it from http://i2p-projekt.i2p/hosts.txt - LogPrint (eLogInfo, "Addressbook: hosts.txt not found, trying to download it from default subscription."); - if (!m_IsDownloading) - { - m_IsDownloading = true; - if (!m_DefaultSubscription) - m_DefaultSubscription = new AddressBookSubscription (*this, DEFAULT_SUBSCRIPTION_ADDRESS); - m_DefaultSubscription->CheckSubscription (); - } - } - } void AddressBook::LoadHostsFromStream (std::istream& f) @@ -357,6 +340,11 @@ namespace client void AddressBook::DownloadComplete (bool success) { m_IsDownloading = false; + if (success && m_DefaultSubscription) + { + m_DefaultSubscription.reset (nullptr); + m_IsLoaded = true; + } if (m_SubscriptionsUpdateTimer) { m_SubscriptionsUpdateTimer->expires_from_now (boost::posix_time::minutes( @@ -369,8 +357,8 @@ namespace client void AddressBook::StartSubscriptions () { LoadSubscriptions (); - if (!m_Subscriptions.size ()) return; - + if (m_IsLoaded && m_Subscriptions.empty ()) return; + auto dest = i2p::client::context.GetSharedLocalDestination (); if (dest) { @@ -398,12 +386,24 @@ namespace client LogPrint(eLogWarning, "Addressbook: missing local destination, skip subscription update"); return; } - if (m_IsLoaded && !m_IsDownloading && dest->IsReady () && !m_Subscriptions.empty ()) + if (!m_IsDownloading && dest->IsReady ()) { - // pick random subscription - auto ind = rand () % m_Subscriptions.size(); - m_IsDownloading = true; - m_Subscriptions[ind]->CheckSubscription (); + if (!m_IsLoaded) + { + // download it from http://i2p-projekt.i2p/hosts.txt + LogPrint (eLogInfo, "Addressbook: trying to download it from default subscription."); + if (!m_DefaultSubscription) + m_DefaultSubscription.reset (new AddressBookSubscription (*this, DEFAULT_SUBSCRIPTION_ADDRESS)); + m_IsDownloading = true; + m_DefaultSubscription->CheckSubscription (); + } + else if (!m_Subscriptions.empty ()) + { + // pick random subscription + auto ind = rand () % m_Subscriptions.size(); + m_IsDownloading = true; + m_Subscriptions[ind]->CheckSubscription (); + } } else { @@ -461,6 +461,8 @@ namespace client << "Host: " << u.host_ << "\r\n" << "Accept: */*\r\n" << "User-Agent: Wget/1.11.4\r\n" + //<< "Accept-Encoding: gzip\r\n" + << "X-Accept-Encoding: x-i2p-gzip;q=1.0, identity;q=0.5, deflate;q=0, gzip;q=0, *;q=0\r\n" << "Connection: close\r\n"; if (m_Etag.length () > 0) // etag request << i2p::util::http::IF_NONE_MATCH << ": \"" << m_Etag << "\"\r\n"; @@ -499,7 +501,7 @@ namespace client response >> status; // status if (status == 200) // OK { - bool isChunked = false; + bool isChunked = false, isGzip = false; std::string header, statusMessage; std::getline (response, statusMessage); // read until new line meaning end of header @@ -510,6 +512,8 @@ namespace client if (colon != std::string::npos) { std::string field = header.substr (0, colon); + boost::to_lower (field); // field are not case-sensitive + colon++; header.resize (header.length () - 1); // delete \r if (field == i2p::util::http::ETAG) m_Etag = header.substr (colon + 1); @@ -517,6 +521,9 @@ namespace client m_LastModified = header.substr (colon + 1); else if (field == i2p::util::http::TRANSFER_ENCODING) isChunked = !header.compare (colon + 1, std::string::npos, "chunked"); + else if (field == i2p::util::http::CONTENT_ENCODING) + isGzip = !header.compare (colon + 1, std::string::npos, "gzip") || + !header.compare (colon + 1, std::string::npos, "x-i2p-gzip"); } } LogPrint (eLogInfo, "Addressbook: ", m_Link, " ETag: ", m_Etag, " Last-Modified: ", m_LastModified); @@ -524,13 +531,13 @@ namespace client { success = true; if (!isChunked) - m_Book.LoadHostsFromStream (response); + success = ProcessResponse (response, isGzip); else { // merge chunks std::stringstream merged; i2p::util::http::MergeChunkedResponse (response, merged); - m_Book.LoadHostsFromStream (merged); + success = ProcessResponse (merged, isGzip); } } } @@ -553,6 +560,23 @@ namespace client m_Book.DownloadComplete (success); } + + bool AddressBookSubscription::ProcessResponse (std::stringstream& s, bool isGzip) + { + if (isGzip) + { + std::stringstream uncompressed; + i2p::data::GzipInflator inflator; + inflator.Inflate (s, uncompressed); + if (!uncompressed.fail ()) + m_Book.LoadHostsFromStream (uncompressed); + else + return false; + } + else + m_Book.LoadHostsFromStream (s); + return true; + } } } diff --git a/AddressBook.h b/AddressBook.h index 16403e1e..46df12d0 100644 --- a/AddressBook.h +++ b/AddressBook.h @@ -77,7 +77,7 @@ namespace client AddressBookStorage * m_Storage; volatile bool m_IsLoaded, m_IsDownloading; std::vector m_Subscriptions; - AddressBookSubscription * m_DefaultSubscription; // in case if we don't know any addresses yet + std::unique_ptr m_DefaultSubscription; // in case if we don't know any addresses yet boost::asio::deadline_timer * m_SubscriptionsUpdateTimer; }; @@ -91,6 +91,7 @@ namespace client private: void Request (); + bool ProcessResponse (std::stringstream& s, bool isGzip = false); private: diff --git a/Base.cpp b/Base.cpp index dbf887cf..e894b694 100644 --- a/Base.cpp +++ b/Base.cpp @@ -314,6 +314,44 @@ namespace data } } + bool GzipInflator::Inflate (const uint8_t * in, size_t inLen, std::ostream& s) + { + m_IsDirty = true; + uint8_t * out = new uint8_t[GZIP_CHUNK_SIZE]; + m_Inflator.next_in = const_cast(in); + m_Inflator.avail_in = inLen; + int ret; + do + { + m_Inflator.next_out = out; + m_Inflator.avail_out = GZIP_CHUNK_SIZE; + ret = inflate (&m_Inflator, Z_NO_FLUSH); + if (ret < 0) + { + LogPrint (eLogError, "Decompression error ", ret); + inflateEnd (&m_Inflator); + s.setstate(std::ios_base::failbit); + break; + } + else + s.write ((char *)out, GZIP_CHUNK_SIZE - m_Inflator.avail_out); + } + while (!m_Inflator.avail_out); // more data to read + delete[] out; + return ret == Z_STREAM_END || ret < 0; + } + + void GzipInflator::Inflate (std::istream& in, std::ostream& out) + { + uint8_t * buf = new uint8_t[GZIP_CHUNK_SIZE]; + while (!in.eof ()) + { + in.read ((char *)buf, GZIP_CHUNK_SIZE); + Inflate (buf, in.gcount (), out); + } + delete[] buf; + } + GzipDeflator::GzipDeflator (): m_IsDirty (false) { memset (&m_Deflator, 0, sizeof (m_Deflator)); diff --git a/Base.h b/Base.h index 0f48a78a..0c38725e 100644 --- a/Base.h +++ b/Base.h @@ -5,6 +5,7 @@ #include #include #include +#include namespace i2p { @@ -93,6 +94,7 @@ namespace data }; }; + const size_t GZIP_CHUNK_SIZE = 16384; class GzipInflator { public: @@ -101,7 +103,10 @@ namespace data ~GzipInflator (); size_t Inflate (const uint8_t * in, size_t inLen, uint8_t * out, size_t outLen); - + bool Inflate (const uint8_t * in, size_t inLen, std::ostream& s); + // return true when finshed or error, s failbit will be set in case of error + void Inflate (std::istream& in, std::ostream& out); + private: z_stream m_Inflator; diff --git a/ClientContext.cpp b/ClientContext.cpp index 072e6e24..bfa94ad1 100644 --- a/ClientContext.cpp +++ b/ClientContext.cpp @@ -37,6 +37,8 @@ namespace client m_SharedLocalDestination->Start (); } + m_AddressBook.Start (); + std::shared_ptr localDestination; bool httproxy; i2p::config::GetOption("httpproxy.enabled", httproxy); if (httproxy) { @@ -94,25 +96,19 @@ namespace client m_BOBCommandChannel = new BOBCommandChannel (bobAddr, bobPort); m_BOBCommandChannel->Start (); } - - m_AddressBook.Start (); } void ClientContext::Stop () { - if (m_HttpProxy) { - LogPrint(eLogInfo, "Clients: stopping HTTP Proxy"); - m_HttpProxy->Stop(); - delete m_HttpProxy; - m_HttpProxy = nullptr; - } + LogPrint(eLogInfo, "Clients: stopping HTTP Proxy"); + m_HttpProxy->Stop(); + delete m_HttpProxy; + m_HttpProxy = nullptr; - if (m_SocksProxy) { - LogPrint(eLogInfo, "Clients: stopping SOCKS Proxy"); - m_SocksProxy->Stop(); - delete m_SocksProxy; - m_SocksProxy = nullptr; - } + LogPrint(eLogInfo, "Clients: stopping SOCKS Proxy"); + m_SocksProxy->Stop(); + delete m_SocksProxy; + m_SocksProxy = nullptr; for (auto& it: m_ClientTunnels) { diff --git a/Config.cpp b/Config.cpp index 9e9582ea..8e212360 100644 --- a/Config.cpp +++ b/Config.cpp @@ -191,7 +191,7 @@ namespace config { | boost::program_options::command_line_style::allow_long_disguise; style &= ~ boost::program_options::command_line_style::allow_guessing; store(parse_command_line(argc, argv, m_OptionsDesc, style, old_syntax_parser), m_Options); - } catch (boost::program_options::error e) { + } catch (boost::program_options::error& e) { std::cerr << "args: " << e.what() << std::endl; exit(EXIT_FAILURE); } @@ -204,19 +204,22 @@ namespace config { } void ParseConfig(const std::string& path) { - if (path == "") - return; + if (path == "") return; std::ifstream config(path, std::ios::in); - if (!config.is_open()) { + if (!config.is_open()) + { std::cerr << "missing/unreadable config file: " << path << std::endl; exit(EXIT_FAILURE); } - try { - store(boost::program_options::parse_config_file(config, m_OptionsDesc), m_Options); - } catch (boost::program_options::error e) { + try + { + store(boost::program_options::parse_config_file(config, m_OptionsDesc), m_Options); + } + catch (boost::program_options::error& e) + { std::cerr << e.what() << std::endl; exit(EXIT_FAILURE); }; diff --git a/Destination.cpp b/Destination.cpp index 3509fe80..5163f99d 100644 --- a/Destination.cpp +++ b/Destination.cpp @@ -18,7 +18,8 @@ namespace client const std::map * params): m_IsRunning (false), m_Thread (nullptr), m_Work (m_Service), m_Keys (keys), m_IsPublic (isPublic), m_PublishReplyToken (0), - m_DatagramDestination (nullptr), m_PublishConfirmationTimer (m_Service), m_CleanupTimer (m_Service) + m_DatagramDestination (nullptr), m_PublishConfirmationTimer (m_Service), + m_PublishVerificationTimer (m_Service), m_CleanupTimer (m_Service) { if (m_IsPublic) PersistTemporaryKeys (); @@ -140,7 +141,7 @@ namespace client m_IsRunning = true; m_Pool->SetLocalDestination (shared_from_this ()); m_Pool->SetActive (true); - m_Thread = new std::thread (std::bind (&ClientDestination::Run, this)); + m_Thread = new std::thread (std::bind (&ClientDestination::Run, shared_from_this ())); m_StreamingDestination = std::make_shared (shared_from_this ()); // TODO: m_StreamingDestination->Start (); for (auto it: m_StreamingDestinationsByPorts) @@ -148,7 +149,7 @@ namespace client m_CleanupTimer.expires_from_now (boost::posix_time::minutes (DESTINATION_CLEANUP_TIMEOUT)); m_CleanupTimer.async_wait (std::bind (&ClientDestination::HandleCleanupTimer, - this, std::placeholders::_1)); + shared_from_this (), std::placeholders::_1)); } } @@ -157,6 +158,8 @@ namespace client if (m_IsRunning) { m_CleanupTimer.cancel (); + m_PublishConfirmationTimer.cancel (); + m_PublishVerificationTimer.cancel (); m_IsRunning = false; m_StreamingDestination->Stop (); m_StreamingDestination = nullptr; @@ -196,7 +199,7 @@ namespace client else { auto ls = i2p::data::netdb.FindLeaseSet (ident); - if (ls) + if (ls && !ls->IsExpired ()) { ls->PopulateLeases (); // since we don't store them in netdb m_RemoteLeaseSets[ident] = ls; @@ -227,21 +230,22 @@ namespace client } data; memcpy (data.k, key, 32); memcpy (data.t, tag, 32); - m_Service.post ([this,data](void) + auto s = shared_from_this (); + m_Service.post ([s,data](void) { - this->AddSessionKey (data.k, data.t); + s->AddSessionKey (data.k, data.t); }); return true; } void ClientDestination::ProcessGarlicMessage (std::shared_ptr msg) { - m_Service.post (std::bind (&ClientDestination::HandleGarlicMessage, this, msg)); + m_Service.post (std::bind (&ClientDestination::HandleGarlicMessage, shared_from_this (), msg)); } void ClientDestination::ProcessDeliveryStatusMessage (std::shared_ptr msg) { - m_Service.post (std::bind (&ClientDestination::HandleDeliveryStatusMessage, this, msg)); + m_Service.post (std::bind (&ClientDestination::HandleDeliveryStatusMessage, shared_from_this (), msg)); } void ClientDestination::HandleI2NPMessage (const uint8_t * buf, size_t len, std::shared_ptr from) @@ -284,23 +288,33 @@ namespace client if (it != m_RemoteLeaseSets.end ()) { leaseSet = it->second; - leaseSet->Update (buf + offset, len - offset); - if (leaseSet->IsValid ()) - LogPrint (eLogDebug, "Remote LeaseSet updated"); - else - { - LogPrint (eLogDebug, "Remote LeaseSet update failed"); - m_RemoteLeaseSets.erase (it); - leaseSet = nullptr; + if (leaseSet->IsNewer (buf + offset, len - offset)) + { + leaseSet->Update (buf + offset, len - offset); + if (leaseSet->IsValid ()) + LogPrint (eLogDebug, "Remote LeaseSet updated"); + else + { + LogPrint (eLogDebug, "Remote LeaseSet update failed"); + m_RemoteLeaseSets.erase (it); + leaseSet = nullptr; + } } + else + LogPrint (eLogDebug, "Remote LeaseSet is older. Not updated"); } else { leaseSet = std::make_shared (buf + offset, len - offset); if (leaseSet->IsValid ()) { - LogPrint (eLogDebug, "New remote LeaseSet added"); - m_RemoteLeaseSets[buf + DATABASE_STORE_KEY_OFFSET] = leaseSet; + if (leaseSet->GetIdentHash () != GetIdentHash ()) + { + LogPrint (eLogDebug, "New remote LeaseSet added"); + m_RemoteLeaseSets[buf + DATABASE_STORE_KEY_OFFSET] = leaseSet; + } + else + LogPrint (eLogDebug, "Own remote LeaseSet dropped"); } else { @@ -372,6 +386,10 @@ namespace client LogPrint (eLogDebug, "Destination: Publishing LeaseSet confirmed"); m_ExcludedFloodfills.clear (); m_PublishReplyToken = 0; + // schedule verification + m_PublishVerificationTimer.expires_from_now (boost::posix_time::seconds(PUBLISH_VERIFICATION_TIMEOUT)); + m_PublishVerificationTimer.async_wait (std::bind (&ClientDestination::HandlePublishVerificationTimer, + shared_from_this (), std::placeholders::_1)); } else i2p::garlic::GarlicDestination::HandleDeliveryStatusMessage (msg); @@ -382,7 +400,10 @@ namespace client i2p::garlic::GarlicDestination::SetLeaseSetUpdated (); UpdateLeaseSet (); if (m_IsPublic) + { + m_PublishVerificationTimer.cancel (); Publish (); + } } void ClientDestination::Publish () @@ -403,7 +424,6 @@ namespace client LogPrint (eLogError, "Destination: Can't publish LeaseSet. No outbound tunnels"); return; } - std::set excluded; auto floodfill = i2p::data::netdb.GetClosestFloodfill (m_LeaseSet->GetIdentHash (), m_ExcludedFloodfills); if (!floodfill) { @@ -417,7 +437,7 @@ namespace client auto msg = WrapMessage (floodfill, i2p::CreateDatabaseStoreMsg (m_LeaseSet, m_PublishReplyToken)); m_PublishConfirmationTimer.expires_from_now (boost::posix_time::seconds(PUBLISH_CONFIRMATION_TIMEOUT)); m_PublishConfirmationTimer.async_wait (std::bind (&ClientDestination::HandlePublishConfirmationTimer, - this, std::placeholders::_1)); + shared_from_this (), std::placeholders::_1)); outbound->SendTunnelDataMsg (floodfill->GetIdentHash (), 0, msg); } @@ -434,6 +454,33 @@ namespace client } } + void ClientDestination::HandlePublishVerificationTimer (const boost::system::error_code& ecode) + { + if (ecode != boost::asio::error::operation_aborted) + { + auto s = shared_from_this (); + RequestLeaseSet (GetIdentHash (), + [s](std::shared_ptr leaseSet) + { + if (leaseSet) + { + if (s->m_LeaseSet && *s->m_LeaseSet == *leaseSet) + { + // we got latest LeasetSet + LogPrint (eLogDebug, "Destination: published LeaseSet verified"); + s->m_PublishVerificationTimer.expires_from_now (boost::posix_time::seconds(PUBLISH_REGULAR_VERIFICATION_INTERNAL)); + s->m_PublishVerificationTimer.async_wait (std::bind (&ClientDestination::HandlePublishVerificationTimer, s, std::placeholders::_1)); + return; + } + } + else + LogPrint (eLogWarning, "Destination: couldn't find published LeaseSet"); + // we have to publish again + s->Publish (); + }); + } + } + void ClientDestination::HandleDataMessage (const uint8_t * buf, size_t len) { uint32_t length = bufbe32toh (buf); @@ -465,18 +512,24 @@ namespace client } } - void ClientDestination::CreateStream (StreamRequestComplete streamRequestComplete, const i2p::data::IdentHash& dest, int port) { - assert(streamRequestComplete); + void ClientDestination::CreateStream (StreamRequestComplete streamRequestComplete, const i2p::data::IdentHash& dest, int port) + { + if (!streamRequestComplete) + { + LogPrint (eLogError, "Destination: request callback is not specified in CreateStream"); + return; + } auto leaseSet = FindLeaseSet (dest); if (leaseSet) streamRequestComplete(CreateStream (leaseSet, port)); else { + auto s = shared_from_this (); RequestDestination (dest, - [this, streamRequestComplete, port](std::shared_ptr ls) + [s, streamRequestComplete, port](std::shared_ptr ls) { if (ls) - streamRequestComplete(CreateStream (ls, port)); + streamRequestComplete(s->CreateStream (ls, port)); else streamRequestComplete (nullptr); }); @@ -557,7 +610,11 @@ namespace client { auto it = s->m_LeaseSetRequests.find (dest); if (it != s->m_LeaseSetRequests.end ()) - s->m_LeaseSetRequests.erase (it); + { + auto requestComplete = it->second->requestComplete; + s->m_LeaseSetRequests.erase (it); + if (requestComplete) requestComplete (nullptr); + } }); } @@ -575,8 +632,8 @@ namespace client if (!SendLeaseSetRequest (dest, floodfill, request)) { // request failed - if (request->requestComplete) request->requestComplete (nullptr); m_LeaseSetRequests.erase (dest); + if (request->requestComplete) request->requestComplete (nullptr); } } else // duplicate @@ -587,7 +644,10 @@ namespace client } } else + { LogPrint (eLogError, "Destination: Can't request LeaseSet, no floodfills found"); + if (requestComplete) requestComplete (nullptr); + } } bool ClientDestination::SendLeaseSetRequest (const i2p::data::IdentHash& dest, @@ -623,7 +683,7 @@ namespace client }); request->requestTimeoutTimer.expires_from_now (boost::posix_time::seconds(LEASESET_REQUEST_TIMEOUT)); request->requestTimeoutTimer.async_wait (std::bind (&ClientDestination::HandleRequestTimoutTimer, - this, std::placeholders::_1, dest)); + shared_from_this (), std::placeholders::_1, dest)); } else return false; @@ -655,8 +715,9 @@ namespace client if (done) { - if (it->second->requestComplete) it->second->requestComplete (nullptr); + auto requestComplete = it->second->requestComplete; m_LeaseSetRequests.erase (it); + if (requestComplete) requestComplete (nullptr); } } } diff --git a/Destination.h b/Destination.h index c45a20ec..34e7fa38 100644 --- a/Destination.h +++ b/Destination.h @@ -26,6 +26,8 @@ namespace client const uint8_t PROTOCOL_TYPE_DATAGRAM = 17; const uint8_t PROTOCOL_TYPE_RAW = 18; const int PUBLISH_CONFIRMATION_TIMEOUT = 5; // in seconds + const int PUBLISH_VERIFICATION_TIMEOUT = 10; // in seconds after successfull publish + const int PUBLISH_REGULAR_VERIFICATION_INTERNAL = 100; // in seconds periodically const int LEASESET_REQUEST_TIMEOUT = 5; // in seconds const int MAX_LEASESET_REQUEST_TIMEOUT = 40; // in seconds const int DESTINATION_CLEANUP_TIMEOUT = 3; // in minutes @@ -116,6 +118,7 @@ namespace client void UpdateLeaseSet (); void Publish (); void HandlePublishConfirmationTimer (const boost::system::error_code& ecode); + void HandlePublishVerificationTimer (const boost::system::error_code& ecode); void HandleDatabaseStoreMessage (const uint8_t * buf, size_t len); void HandleDatabaseSearchReplyMessage (const uint8_t * buf, size_t len); void HandleDeliveryStatusMessage (std::shared_ptr msg); @@ -148,7 +151,7 @@ namespace client std::map > m_StreamingDestinationsByPorts; i2p::datagram::DatagramDestination * m_DatagramDestination; - boost::asio::deadline_timer m_PublishConfirmationTimer, m_CleanupTimer; + boost::asio::deadline_timer m_PublishConfirmationTimer, m_PublishVerificationTimer, m_CleanupTimer; public: diff --git a/Family.cpp b/Family.cpp new file mode 100644 index 00000000..a93e31ef --- /dev/null +++ b/Family.cpp @@ -0,0 +1,122 @@ +#include +#include "util.h" +#include +#include +#include "Log.h" +#include "Crypto.h" +#include "Family.h" + +namespace i2p +{ +namespace data +{ + Families::Families () + { + } + + Families::~Families () + { + } + + void Families::LoadCertificate (const std::string& filename) + { + SSL_CTX * ctx = SSL_CTX_new (TLSv1_method ()); + int ret = SSL_CTX_use_certificate_file (ctx, filename.c_str (), SSL_FILETYPE_PEM); + if (ret) + { + SSL * ssl = SSL_new (ctx); + X509 * cert = SSL_get_certificate (ssl); + if (cert) + { + std::shared_ptr verifier; + // extract issuer name + char name[100]; + X509_NAME_oneline (X509_get_issuer_name(cert), name, 100); + char * family = strstr (name, ".family"); + if (family) family[0] = 0; + auto pkey = X509_get_pubkey (cert); + int keyType = EVP_PKEY_type(pkey->type); + switch (keyType) + { + case EVP_PKEY_DSA: + // TODO: + break; + case EVP_PKEY_EC: + { + EC_KEY * ecKey = EVP_PKEY_get1_EC_KEY (pkey); + if (ecKey) + { + auto group = EC_KEY_get0_group (ecKey); + if (group) + { + int curve = EC_GROUP_get_curve_name (group); + if (curve == NID_X9_62_prime256v1) + { + uint8_t signingKey[64]; + BIGNUM * x = BN_new(), * y = BN_new(); + EC_POINT_get_affine_coordinates_GFp (group, + EC_KEY_get0_public_key (ecKey), x, y, NULL); + i2p::crypto::bn2buf (x, signingKey, 32); + i2p::crypto::bn2buf (y, signingKey + 32, 32); + BN_free (x); BN_free (y); + verifier = std::make_shared(signingKey); + } + else + LogPrint (eLogWarning, "Family: elliptic curve ", curve, " is not supported"); + } + EC_KEY_free (ecKey); + } + break; + } + default: + LogPrint (eLogWarning, "Family: Certificate key type ", keyType, " is not supported"); + } + EVP_PKEY_free (pkey); + if (verifier) + m_SigningKeys[name] = verifier; + } + SSL_free (ssl); + } + else + LogPrint (eLogError, "Family: Can't open certificate file ", filename); + SSL_CTX_free (ctx); + } + + void Families::LoadCertificates () + { + boost::filesystem::path familyDir = i2p::util::filesystem::GetCertificatesDir() / "family"; + + if (!boost::filesystem::exists (familyDir)) return; + int numCertificates = 0; + boost::filesystem::directory_iterator end; // empty + for (boost::filesystem::directory_iterator it (familyDir); it != end; ++it) + { + if (boost::filesystem::is_regular_file (it->status()) && it->path ().extension () == ".crt") + { + LoadCertificate (it->path ().string ()); + numCertificates++; + } + } + if (numCertificates > 0) + LogPrint (eLogInfo, "Family: ", numCertificates, " certificates loaded"); + } + + bool Families::VerifyFamily (const std::string& family, const IdentHash& ident, + const char * signature, const char * key) + { + uint8_t buf[50], signatureBuf[64]; + size_t len = family.length (), signatureLen = strlen (signature); + memcpy (buf, family.c_str (), len); + memcpy (buf + len, (const uint8_t *)ident, 32); + len += 32; + Base64ToByteStream (signature, signatureLen, signatureBuf, 64); + auto it = m_SigningKeys.find (family); + if (it != m_SigningKeys.end ()) + return it->second->Verify (buf, len, signatureBuf); + // TODO: process key + return true; + } + +} +} + diff --git a/Family.h b/Family.h new file mode 100644 index 00000000..51cf6bf5 --- /dev/null +++ b/Family.h @@ -0,0 +1,35 @@ +#ifndef FAMILY_H__ +#define FAMILY_H_ + +#include +#include +#include +#include "Signature.h" +#include "Identity.h" + +namespace i2p +{ +namespace data +{ + class Families + { + public: + + Families (); + ~Families (); + void LoadCertificates (); + bool VerifyFamily (const std::string& family, const IdentHash& ident, + const char * signature, const char * key = nullptr); + + private: + + void LoadCertificate (const std::string& filename); + + private: + + std::map > m_SigningKeys; + }; +} +} + +#endif diff --git a/Garlic.cpp b/Garlic.cpp index f967a1e2..e11f8ec8 100644 --- a/Garlic.cpp +++ b/Garlic.cpp @@ -47,17 +47,22 @@ namespace garlic { if (!m_SharedRoutingPath) return nullptr; uint32_t ts = i2p::util::GetSecondsSinceEpoch (); - if (!m_SharedRoutingPath->outboundTunnel->IsEstablished () || + if (m_SharedRoutingPath->numTimesUsed >= ROUTING_PATH_MAX_NUM_TIMES_USED || + !m_SharedRoutingPath->outboundTunnel->IsEstablished () || ts*1000LL > m_SharedRoutingPath->remoteLease->endDate || ts > m_SharedRoutingPath->updateTime + ROUTING_PATH_EXPIRATION_TIMEOUT) m_SharedRoutingPath = nullptr; + if (m_SharedRoutingPath) m_SharedRoutingPath->numTimesUsed++; return m_SharedRoutingPath; } void GarlicRoutingSession::SetSharedRoutingPath (std::shared_ptr path) { if (path && path->outboundTunnel && path->remoteLease) + { path->updateTime = i2p::util::GetSecondsSinceEpoch (); + path->numTimesUsed = 0; + } else path = nullptr; m_SharedRoutingPath = path; diff --git a/Garlic.h b/Garlic.h index 95a59e72..ea53dd03 100644 --- a/Garlic.h +++ b/Garlic.h @@ -44,6 +44,7 @@ namespace garlic const int OUTGOING_TAGS_CONFIRMATION_TIMEOUT = 10; // 10 seconds const int LEASET_CONFIRMATION_TIMEOUT = 4000; // in milliseconds const int ROUTING_PATH_EXPIRATION_TIMEOUT = 30; // 30 seconds + const int ROUTING_PATH_MAX_NUM_TIMES_USED = 100; // how many times might be used struct SessionTag: public i2p::data::Tag<32> { @@ -62,7 +63,9 @@ namespace garlic { std::shared_ptr outboundTunnel; std::shared_ptr remoteLease; + int rtt; // RTT uint32_t updateTime; // seconds since epoch + int numTimesUsed; }; class GarlicDestination; diff --git a/HTTPProxy.cpp b/HTTPProxy.cpp index c417d904..f0166a4a 100644 --- a/HTTPProxy.cpp +++ b/HTTPProxy.cpp @@ -176,28 +176,39 @@ namespace proxy m_request.push_back('\r'); m_request.push_back('\n'); m_request.append("Connection: close\r\n"); - m_request.append(reinterpret_cast(http_buff),len); + // TODO: temporary shortcut. Must be implemented properly + uint8_t * eol = nullptr; + bool isEndOfHeader = false; + while (!isEndOfHeader && len && (eol = (uint8_t *)memchr (http_buff, '\r', len))) + { + if (eol) + { + *eol = 0; eol++; + if (strncmp ((const char *)http_buff, "Referer", 7)) // strip out referer + { + if (!strncmp ((const char *)http_buff, "User-Agent", 10)) // replace UserAgent + m_request.append("User-Agent: MYOB/6.66 (AN/ON)"); + else + m_request.append ((const char *)http_buff); + m_request.append ("\r\n"); + } + isEndOfHeader = !http_buff[0]; + auto l = eol - http_buff; + http_buff = eol; + len -= l; + if (len > 0) // \r + { + http_buff++; + len--; + } + } + } + m_request.append(reinterpret_cast(http_buff),len); return true; } bool HTTPProxyHandler::HandleData(uint8_t *http_buff, std::size_t len) { - // TODO: we should srtrip 'Referer' better, because it might be inside message body - /*assert(len); // This should always be called with a least a byte left to parse - - // remove "Referer" from http requst - http_buff[len] = 0; - auto start = strstr((char *)http_buff, "\nReferer:"); - if (start) - { - auto end = strchr (start + 1, '\n'); - if (end) - { - strncpy(start, end, (char *)(http_buff + len) - end); - len -= (end - start); - } - }*/ - while (len > 0) { //TODO: fallback to finding HOst: header if needed diff --git a/I2PTunnel.cpp b/I2PTunnel.cpp index e936834d..07b9bd83 100644 --- a/I2PTunnel.cpp +++ b/I2PTunnel.cpp @@ -114,10 +114,25 @@ namespace client void I2PTunnelConnection::StreamReceive () { if (m_Stream) - m_Stream->AsyncReceive (boost::asio::buffer (m_StreamBuffer, I2P_TUNNEL_CONNECTION_BUFFER_SIZE), - std::bind (&I2PTunnelConnection::HandleStreamReceive, shared_from_this (), - std::placeholders::_1, std::placeholders::_2), - I2P_TUNNEL_CONNECTION_MAX_IDLE); + { + if (m_Stream->GetStatus () == i2p::stream::eStreamStatusNew || + m_Stream->GetStatus () == i2p::stream::eStreamStatusOpen) // regular + { + m_Stream->AsyncReceive (boost::asio::buffer (m_StreamBuffer, I2P_TUNNEL_CONNECTION_BUFFER_SIZE), + std::bind (&I2PTunnelConnection::HandleStreamReceive, shared_from_this (), + std::placeholders::_1, std::placeholders::_2), + I2P_TUNNEL_CONNECTION_MAX_IDLE); + } + else // closed by peer + { + // get remaning data + auto len = m_Stream->ReadSome (m_StreamBuffer, I2P_TUNNEL_CONNECTION_BUFFER_SIZE); + if (len > 0) // still some data + Write (m_StreamBuffer, len); + else // no more data + Terminate (); + } + } } void I2PTunnelConnection::HandleStreamReceive (const boost::system::error_code& ecode, std::size_t bytes_transferred) @@ -126,7 +141,12 @@ namespace client { LogPrint (eLogError, "I2PTunnel: stream read error: ", ecode.message ()); if (ecode != boost::asio::error::operation_aborted) - Terminate (); + { + if (bytes_transferred > 0) + Write (m_StreamBuffer, bytes_transferred); // postpone termination + else + Terminate (); + } } else Write (m_StreamBuffer, bytes_transferred); diff --git a/LeaseSet.cpp b/LeaseSet.cpp index 677f19ca..5d259b33 100644 --- a/LeaseSet.cpp +++ b/LeaseSet.cpp @@ -42,10 +42,13 @@ namespace data auto signingKeyLen = localDestination->GetIdentity ()->GetSigningPublicKeyLen (); memset (m_Buffer + m_BufferLen, 0, signingKeyLen); m_BufferLen += signingKeyLen; - auto tunnels = pool->GetInboundTunnels (5); // 5 tunnels maximum + int numTunnels = pool->GetNumInboundTunnels () + 2; // 2 backup tunnels + if (numTunnels > 16) numTunnels = 16; // 16 tunnels maximum + auto tunnels = pool->GetInboundTunnels (numTunnels); m_Buffer[m_BufferLen] = tunnels.size (); // num leases m_BufferLen++; // leases + auto currentTime = i2p::util::GetMillisecondsSinceEpoch (); for (auto it: tunnels) { memcpy (m_Buffer + m_BufferLen, it->GetNextIdentHash (), 32); @@ -54,8 +57,9 @@ namespace data m_BufferLen += 4; // tunnel id uint64_t ts = it->GetCreationTime () + i2p::tunnel::TUNNEL_EXPIRATION_TIMEOUT - i2p::tunnel::TUNNEL_EXPIRATION_THRESHOLD; // 1 minute before expiration ts *= 1000; // in milliseconds - ts += rand () % 6; // + random milliseconds 0-5 if (ts > m_ExpirationTime) m_ExpirationTime = ts; + // make sure leaseset is newer than previous, but adding some time to expiration date + ts += (currentTime - it->GetCreationTime ()*1000LL)*2/i2p::tunnel::TUNNEL_EXPIRATION_TIMEOUT; // up to 2 secs htobe64buf (m_Buffer + m_BufferLen, ts); m_BufferLen += 8; // end date } @@ -130,7 +134,7 @@ namespace data leases += 4; // tunnel ID lease.endDate = bufbe64toh (leases); leases += 8; // end date - if (ts < lease.endDate) + if (ts < lease.endDate + LEASE_ENDDATE_THRESHOLD) { if (lease.endDate > m_ExpirationTime) m_ExpirationTime = lease.endDate; @@ -157,6 +161,7 @@ namespace data m_IsValid = false; return; } + m_ExpirationTime += LEASE_ENDDATE_THRESHOLD; // delete old leases if (m_StoreLeases) { @@ -179,7 +184,35 @@ namespace data m_IsValid = false; } } - + + uint64_t LeaseSet::ExtractTimestamp (const uint8_t * buf, size_t len) const + { + if (!m_Identity) return 0; + size_t size = m_Identity->GetFullLen (); + if (size > len) return 0; + size += 256; // encryption key + size += m_Identity->GetSigningPublicKeyLen (); // unused signing key + if (size > len) return 0; + uint8_t num = buf[size]; + size++; // num + if (size + num*44 > len) return 0; + uint64_t timestamp= 0 ; + for (int i = 0; i < num; i++) + { + size += 36; // gateway (32) + tunnelId(4) + auto endDate = bufbe64toh (buf + size); + size += 8; // end date + if (!timestamp || endDate < timestamp) + timestamp = endDate; + } + return timestamp; + } + + bool LeaseSet::IsNewer (const uint8_t * buf, size_t len) const + { + return ExtractTimestamp (buf, len) > ExtractTimestamp (m_Buffer, m_BufferLen); + } + const std::vector > LeaseSet::GetNonExpiredLeases (bool withThreshold) const { auto ts = i2p::util::GetMillisecondsSinceEpoch (); @@ -187,8 +220,10 @@ namespace data for (auto it: m_Leases) { auto endDate = it->endDate; - if (!withThreshold) - endDate -= i2p::tunnel::TUNNEL_EXPIRATION_THRESHOLD*1000; + if (withThreshold) + endDate += LEASE_ENDDATE_THRESHOLD; + else + endDate -= LEASE_ENDDATE_THRESHOLD; if (ts < endDate) leases.push_back (it); } diff --git a/LeaseSet.h b/LeaseSet.h index aed27683..0afca269 100644 --- a/LeaseSet.h +++ b/LeaseSet.h @@ -17,6 +17,7 @@ namespace tunnel namespace data { + const int LEASE_ENDDATE_THRESHOLD = 31000; // in milliseconds struct Lease { IdentHash tunnelGateway; @@ -46,6 +47,7 @@ namespace data LeaseSet (std::shared_ptr pool); ~LeaseSet () { delete[] m_Buffer; }; void Update (const uint8_t * buf, size_t len); + bool IsNewer (const uint8_t * buf, size_t len) const; void PopulateLeases (); // from buffer std::shared_ptr GetIdentity () const { return m_Identity; }; @@ -57,6 +59,8 @@ namespace data bool IsExpired () const; bool IsEmpty () const { return m_Leases.empty (); }; uint64_t GetExpirationTime () const { return m_ExpirationTime; }; + bool operator== (const LeaseSet& other) const + { return m_BufferLen == other.m_BufferLen && !memcmp (m_Buffer, other.m_Buffer, m_BufferLen); }; // implements RoutingDestination const IdentHash& GetIdentHash () const { return m_Identity->GetIdentHash (); }; @@ -66,6 +70,7 @@ namespace data private: void ReadFromBuffer (bool readIdentity = true); + uint64_t ExtractTimestamp (const uint8_t * buf, size_t len) const; // min expiration time private: diff --git a/NetDb.cpp b/NetDb.cpp index 9253dcdc..428f1c36 100644 --- a/NetDb.cpp +++ b/NetDb.cpp @@ -37,6 +37,7 @@ namespace data void NetDb::Start () { + m_Families.LoadCertificates (); Load (); if (m_RouterInfos.size () < 25) // reseed if # of router less than 50 Reseed (); @@ -149,22 +150,30 @@ namespace data } } - void NetDb::AddRouterInfo (const uint8_t * buf, int len) + bool NetDb::AddRouterInfo (const uint8_t * buf, int len) { IdentityEx identity; if (identity.FromBuffer (buf, len)) - AddRouterInfo (identity.GetIdentHash (), buf, len); + return AddRouterInfo (identity.GetIdentHash (), buf, len); + return false; } - void NetDb::AddRouterInfo (const IdentHash& ident, const uint8_t * buf, int len) + bool NetDb::AddRouterInfo (const IdentHash& ident, const uint8_t * buf, int len) { + bool updated = true; auto r = FindRouter (ident); if (r) { - auto ts = r->GetTimestamp (); - r->Update (buf, len); - if (r->GetTimestamp () > ts) + if (r->IsNewer (buf, len)) + { + r->Update (buf, len); LogPrint (eLogInfo, "NetDb: RouterInfo updated: ", ident.ToBase64()); + } + else + { + LogPrint (eLogDebug, "NetDb: RouterInfo is older: ", ident.ToBase64()); + updated = false; + } } else { @@ -182,27 +191,39 @@ namespace data m_Floodfills.push_back (r); } } + else + updated = false; } // take care about requested destination m_Requests.RequestComplete (ident, r); + return updated; } - void NetDb::AddLeaseSet (const IdentHash& ident, const uint8_t * buf, int len, + bool NetDb::AddLeaseSet (const IdentHash& ident, const uint8_t * buf, int len, std::shared_ptr from) { + bool updated = false; if (!from) // unsolicited LS must be received directly { auto it = m_LeaseSets.find(ident); if (it != m_LeaseSets.end ()) { - it->second->Update (buf, len); - if (it->second->IsValid ()) - LogPrint (eLogInfo, "NetDb: LeaseSet updated: ", ident.ToBase64()); - else + if (it->second->IsNewer (buf, len)) { - LogPrint (eLogWarning, "NetDb: LeaseSet update failed: ", ident.ToBase64()); - m_LeaseSets.erase (it); - } + it->second->Update (buf, len); + if (it->second->IsValid ()) + { + LogPrint (eLogInfo, "NetDb: LeaseSet updated: ", ident.ToBase64()); + updated = true; + } + else + { + LogPrint (eLogWarning, "NetDb: LeaseSet update failed: ", ident.ToBase64()); + m_LeaseSets.erase (it); + } + } + else + LogPrint (eLogDebug, "NetDb: LeaseSet is older: ", ident.ToBase64()); } else { @@ -211,11 +232,13 @@ namespace data { LogPrint (eLogInfo, "NetDb: LeaseSet added: ", ident.ToBase64()); m_LeaseSets[ident] = leaseSet; + updated = true; } else LogPrint (eLogError, "NetDb: new LeaseSet validation failed: ", ident.ToBase64()); } } + return updated; } std::shared_ptr NetDb::FindRouter (const IdentHash& ident) const @@ -326,10 +349,21 @@ namespace data it.second->SetUnreachable (true); total--; } - } else if (total > 300) { - if (ts > it.second->GetTimestamp () + 30*3600*1000LL) { // 30 hours - it.second->SetUnreachable (true); - total--; + else if (total > 2500) + { + if (ts > it.second->GetTimestamp () + 12*3600*1000LL) // 12 hours + { + it.second->SetUnreachable (true); + total--; + } + } + else if (total > 300) + { + if (ts > it.second->GetTimestamp () + 30*3600*1000LL) // 30 hours + { + it.second->SetUnreachable (true); + total--; + } } } else if (total > 120) { if (ts > it.second->GetTimestamp () + 72*3600*1000LL) { // 72 hours @@ -418,37 +452,14 @@ namespace data LogPrint (eLogError, "NetDb: no outbound tunnels for DatabaseStore reply found"); } offset += 32; - - if (context.IsFloodfill ()) - { - // flood it - auto floodMsg = NewI2NPShortMessage (); - uint8_t * payload = floodMsg->GetPayload (); - memcpy (payload, buf, 33); // key + type - htobe32buf (payload + DATABASE_STORE_REPLY_TOKEN_OFFSET, 0); // zero reply token - auto msgLen = len - offset; - floodMsg->len += DATABASE_STORE_HEADER_SIZE + msgLen; - if (floodMsg->len < floodMsg->maxLen) - { - memcpy (payload + DATABASE_STORE_HEADER_SIZE, buf + offset, msgLen); - floodMsg->FillI2NPMessageHeader (eI2NPDatabaseStore); - std::set excluded; - for (int i = 0; i < 3; i++) - { - auto floodfill = GetClosestFloodfill (ident, excluded); - if (floodfill) - transports.SendMessage (floodfill->GetIdentHash (), floodMsg); - } - } - else - LogPrint (eLogError, "Database store message is too long ", floodMsg->len); - } } - + size_t payloadOffset = offset; + + bool updated = false; if (buf[DATABASE_STORE_TYPE_OFFSET]) // type { LogPrint (eLogDebug, "NetDb: store request: LeaseSet"); - AddLeaseSet (ident, buf + offset, len - offset, m->from); + updated = AddLeaseSet (ident, buf + offset, len - offset, m->from); } else { @@ -463,7 +474,34 @@ namespace data uint8_t uncompressed[2048]; size_t uncompressedSize = m_Inflator.Inflate (buf + offset, size, uncompressed, 2048); if (uncompressedSize) - AddRouterInfo (ident, uncompressed, uncompressedSize); + updated = AddRouterInfo (ident, uncompressed, uncompressedSize); + } + + if (replyToken && context.IsFloodfill () && updated) + { + // flood updated + auto floodMsg = NewI2NPShortMessage (); + uint8_t * payload = floodMsg->GetPayload (); + memcpy (payload, buf, 33); // key + type + htobe32buf (payload + DATABASE_STORE_REPLY_TOKEN_OFFSET, 0); // zero reply token + auto msgLen = len - payloadOffset; + floodMsg->len += DATABASE_STORE_HEADER_SIZE + msgLen; + if (floodMsg->len < floodMsg->maxLen) + { + memcpy (payload + DATABASE_STORE_HEADER_SIZE, buf + payloadOffset, msgLen); + floodMsg->FillI2NPMessageHeader (eI2NPDatabaseStore); + std::set excluded; + for (int i = 0; i < 3; i++) + { + auto floodfill = GetClosestFloodfill (ident, excluded); + if (floodfill) + transports.SendMessage (floodfill->GetIdentHash (), floodMsg); + else + break; + } + } + else + LogPrint (eLogError, "Database store message is too long ", floodMsg->len); } } @@ -627,7 +665,7 @@ namespace data lookupType == DATABASE_LOOKUP_TYPE_NORMAL_LOOKUP)) { auto leaseSet = FindLeaseSet (ident); - if (leaseSet) // we don't send back our LeaseSets + if (leaseSet && !leaseSet->IsExpired ()) // we don't send back our LeaseSets { LogPrint (eLogDebug, "NetDb: requested LeaseSet ", key, " found"); replyMsg = CreateDatabaseStoreMsg (leaseSet); @@ -824,12 +862,15 @@ namespace data } std::shared_ptr NetDb::GetClosestFloodfill (const IdentHash& destination, - const std::set& excluded) const + const std::set& excluded, bool closeThanUsOnly) const { std::shared_ptr r; XORMetric minMetric; IdentHash destKey = CreateRoutingKey (destination); - minMetric.SetMax (); + if (closeThanUsOnly) + minMetric = destKey ^ i2p::context.GetIdentHash (); + else + minMetric.SetMax (); std::unique_lock l(m_FloodfillsMutex); for (auto it: m_Floodfills) { diff --git a/NetDb.h b/NetDb.h index 855faa3c..0c59ff0f 100644 --- a/NetDb.h +++ b/NetDb.h @@ -17,6 +17,7 @@ #include "TunnelPool.h" #include "Reseed.h" #include "NetDbRequests.h" +#include "Family.h" namespace i2p { @@ -32,9 +33,9 @@ namespace data void Start (); void Stop (); - void AddRouterInfo (const uint8_t * buf, int len); - void AddRouterInfo (const IdentHash& ident, const uint8_t * buf, int len); - void AddLeaseSet (const IdentHash& ident, const uint8_t * buf, int len, std::shared_ptr from); + bool AddRouterInfo (const uint8_t * buf, int len); + bool AddRouterInfo (const IdentHash& ident, const uint8_t * buf, int len); + bool AddLeaseSet (const IdentHash& ident, const uint8_t * buf, int len, std::shared_ptr from); std::shared_ptr FindRouter (const IdentHash& ident) const; std::shared_ptr FindLeaseSet (const IdentHash& destination) const; std::shared_ptr FindRouterProfile (const IdentHash& ident) const; @@ -50,7 +51,7 @@ namespace data std::shared_ptr GetHighBandwidthRandomRouter (std::shared_ptr compatibleWith) const; std::shared_ptr GetRandomPeerTestRouter () const; std::shared_ptr GetRandomIntroducer () const; - std::shared_ptr GetClosestFloodfill (const IdentHash& destination, const std::set& excluded) const; + std::shared_ptr GetClosestFloodfill (const IdentHash& destination, const std::set& excluded, bool closeThanUsOnly = false) const; std::vector GetClosestFloodfills (const IdentHash& destination, size_t num, std::set& excluded) const; std::shared_ptr GetClosestNonFloodfill (const IdentHash& destination, const std::set& excluded) const; @@ -59,6 +60,7 @@ namespace data void PostI2NPMsg (std::shared_ptr msg); void Reseed (); + Families& GetFamilies () { return m_Families; }; // for web interface int GetNumRouters () const { return m_RouterInfos.size (); }; @@ -94,6 +96,7 @@ namespace data GzipInflator m_Inflator; Reseeder * m_Reseeder; + Families m_Families; friend class NetDbRequests; NetDbRequests m_Requests; diff --git a/Reseed.cpp b/Reseed.cpp index 506b0a0f..380babb5 100644 --- a/Reseed.cpp +++ b/Reseed.cpp @@ -26,15 +26,16 @@ namespace data static std::vector httpsReseedHostList = { "https://reseed.i2p-projekt.de/", // Only HTTPS - "https://i2pseed.zarrenspry.info/", // Only HTTPS and SU3 (v3) support + //"https://i2pseed.zarrenspry.info/", // Only HTTPS and SU3 (v3) support "https://i2p.mooo.com/netDb/", "https://netdb.i2p2.no/", // Only SU3 (v3) support, SNI required "https://us.reseed.i2p2.no:444/", "https://uk.reseed.i2p2.no:444/", - "https://www.torontocrypto.org:8443/" + "https://www.torontocrypto.org:8443/", + "https://i2p-0.manas.ca:8443/" "https://reseed.i2p.vzaws.com:8443/", // Only SU3 (v3) support "https://user.mx24.eu/", // Only HTTPS and SU3 (v3) support - "https://ieb9oopo.mooo.com/" // Only HTTPS and SU3 (v3) support + "https://download.xxlspeed.com/" // Only HTTPS and SU3 (v3) support }; Reseeder::Reseeder() diff --git a/RouterInfo.cpp b/RouterInfo.cpp index 56482234..ec9a4acd 100644 --- a/RouterInfo.cpp +++ b/RouterInfo.cpp @@ -8,6 +8,7 @@ #include "Base.h" #include "Timestamp.h" #include "Log.h" +#include "NetDb.h" #include "RouterInfo.h" namespace i2p @@ -262,11 +263,26 @@ namespace data if (!strcmp (key, "caps")) ExtractCaps (value); // check netId - if (!strcmp (key, "netId") && atoi (value) != I2PD_NET_ID) + else if (!strcmp (key, "netId") && atoi (value) != I2PD_NET_ID) { LogPrint (eLogError, "Unexpected netid=", value); m_IsUnreachable = true; } + // family + else if (!strcmp (key, "family")) + { + m_Family = value; + boost::to_lower (m_Family); + } + else if (!strcmp (key, "family.sig")) + { + if (!netdb.GetFamilies ().VerifyFamily (m_Family, GetIdentHash (), value)) + { + LogPrint (eLogWarning, "RouterInfo: family signature verification failed"); + m_Family.clear (); + } + } + if (!s) return; } @@ -459,6 +475,14 @@ namespace data s.write (properties.str ().c_str (), properties.str ().size ()); } + bool RouterInfo::IsNewer (const uint8_t * buf, size_t len) const + { + if (!m_RouterIdentity) return false; + size_t size = m_RouterIdentity->GetFullLen (); + if (size + 8 > len) return false; + return bufbe64toh (buf + size) > m_Timestamp; + } + const uint8_t * RouterInfo::LoadBuffer () { if (!m_Buffer) diff --git a/RouterInfo.h b/RouterInfo.h index 2d32edef..57212be9 100644 --- a/RouterInfo.h +++ b/RouterInfo.h @@ -157,7 +157,8 @@ namespace data void Update (const uint8_t * buf, int len); void DeleteBuffer () { delete[] m_Buffer; m_Buffer = nullptr; }; - + bool IsNewer (const uint8_t * buf, size_t len) const; + // implements RoutingDestination const IdentHash& GetIdentHash () const { return m_RouterIdentity->GetIdentHash (); }; const uint8_t * GetEncryptionPublicKey () const { return m_RouterIdentity->GetStandardIdentity ().publicKey; }; @@ -179,7 +180,7 @@ namespace data private: - std::string m_FullPath; + std::string m_FullPath, m_Family; std::shared_ptr m_RouterIdentity; uint8_t * m_Buffer; size_t m_BufferLen; diff --git a/Streaming.cpp b/Streaming.cpp index 1e9cdd84..085129bb 100644 --- a/Streaming.cpp +++ b/Streaming.cpp @@ -88,7 +88,7 @@ namespace stream } LogPrint (eLogDebug, "Streaming: Received seqn=", receivedSeqn); - if (isSyn || receivedSeqn == m_LastReceivedSequenceNumber + 1) + if (receivedSeqn == m_LastReceivedSequenceNumber + 1) { // we have received next in sequence message ProcessPacket (packet); @@ -113,7 +113,9 @@ namespace stream if (!m_IsAckSendScheduled) { m_IsAckSendScheduled = true; - m_AckSendTimer.expires_from_now (boost::posix_time::milliseconds(ACK_SEND_TIMEOUT)); + auto ackTimeout = m_RTT/10; + if (ackTimeout > ACK_SEND_TIMEOUT) ackTimeout = ACK_SEND_TIMEOUT; + m_AckSendTimer.expires_from_now (boost::posix_time::milliseconds(ackTimeout)); m_AckSendTimer.async_wait (std::bind (&Stream::HandleAckSendTimer, shared_from_this (), std::placeholders::_1)); } @@ -274,7 +276,7 @@ namespace stream if (!seqn && m_RoutingSession) // first message confirmed m_RoutingSession->SetSharedRoutingPath ( std::make_shared ( - i2p::garlic::GarlicRoutingPath{m_CurrentOutboundTunnel, m_CurrentRemoteLease, 0})); + i2p::garlic::GarlicRoutingPath{m_CurrentOutboundTunnel, m_CurrentRemoteLease, m_RTT, 0, 0})); } else break; @@ -605,6 +607,8 @@ namespace stream { m_CurrentOutboundTunnel = routingPath->outboundTunnel; m_CurrentRemoteLease = routingPath->remoteLease; + m_RTT = routingPath->rtt; + m_RTO = m_RTT*1.5; // TODO: implement it better } } } @@ -619,7 +623,7 @@ namespace stream auto ts = i2p::util::GetMillisecondsSinceEpoch (); if (!m_CurrentRemoteLease || ts >= m_CurrentRemoteLease->endDate - i2p::tunnel::TUNNEL_EXPIRATION_THRESHOLD*1000) UpdateCurrentRemoteLease (true); - if (m_CurrentRemoteLease && ts < m_CurrentRemoteLease->endDate) + if (m_CurrentRemoteLease && ts < m_CurrentRemoteLease->endDate + i2p::data::LEASE_ENDDATE_THRESHOLD) { std::vector msgs; for (auto it: packets) @@ -769,6 +773,7 @@ namespace stream m_RemoteLeaseSet = nullptr; m_CurrentRemoteLease = nullptr; // re-request expired + m_LocalDestination.GetOwner ()->RequestDestination (m_RemoteIdentity->GetIdentHash ()); } } else diff --git a/TunnelPool.cpp b/TunnelPool.cpp index 72d6735a..c74ff475 100644 --- a/TunnelPool.cpp +++ b/TunnelPool.cpp @@ -201,7 +201,14 @@ namespace tunnel void TunnelPool::TestTunnels () { - for (auto it: m_Tests) + decltype(m_Tests) tests; + { + std::unique_lock l(m_TestsMutex); + tests = m_Tests; + m_Tests.clear (); + } + + for (auto it: tests) { LogPrint (eLogWarning, "Tunnels: test of tunnel ", it.first, " failed"); // if test failed again with another tunnel we consider it failed @@ -232,7 +239,7 @@ namespace tunnel it.second.second->SetState (eTunnelStateTestFailed); } } - m_Tests.clear (); + // new tests auto it1 = m_OutboundTunnels.begin (); auto it2 = m_InboundTunnels.begin (); @@ -253,7 +260,10 @@ namespace tunnel { uint32_t msgID; RAND_bytes ((uint8_t *)&msgID, 4); - m_Tests[msgID] = std::make_pair (*it1, *it2); + { + std::unique_lock l(m_TestsMutex); + m_Tests[msgID] = std::make_pair (*it1, *it2); + } (*it1)->SendTunnelDataMsg ((*it2)->GetNextIdentHash (), (*it2)->GetNextTunnelID (), CreateDeliveryStatusMsg (msgID)); it1++; it2++; @@ -276,16 +286,26 @@ namespace tunnel buf += 4; uint64_t timestamp = bufbe64toh (buf); - auto it = m_Tests.find (msgID); - if (it != m_Tests.end ()) + decltype(m_Tests)::mapped_type test; + bool found = false; + { + std::unique_lock l(m_TestsMutex); + auto it = m_Tests.find (msgID); + if (it != m_Tests.end ()) + { + found = true; + test = it->second; + m_Tests.erase (it); + } + } + if (found) { // restore from test failed state if any - if (it->second.first->GetState () == eTunnelStateTestFailed) - it->second.first->SetState (eTunnelStateEstablished); - if (it->second.second->GetState () == eTunnelStateTestFailed) - it->second.second->SetState (eTunnelStateEstablished); - LogPrint (eLogDebug, "Tunnels: test of ", it->first, " successful. ", i2p::util::GetMillisecondsSinceEpoch () - timestamp, " milliseconds"); - m_Tests.erase (it); + if (test.first->GetState () == eTunnelStateTestFailed) + test.first->SetState (eTunnelStateEstablished); + if (test.second->GetState () == eTunnelStateTestFailed) + test.second->SetState (eTunnelStateEstablished); + LogPrint (eLogDebug, "Tunnels: test of ", msgID, " successful. ", i2p::util::GetMillisecondsSinceEpoch () - timestamp, " milliseconds"); } else { diff --git a/TunnelPool.h b/TunnelPool.h index 83b163d4..0cd2057d 100644 --- a/TunnelPool.h +++ b/TunnelPool.h @@ -53,6 +53,9 @@ namespace tunnel bool IsActive () const { return m_IsActive; }; void SetActive (bool isActive) { m_IsActive = isActive; }; void DetachTunnels (); + + int GetNumInboundTunnels () const { return m_NumInboundTunnels; }; + int GetNumOutboundTunnels () const { return m_NumOutboundTunnels; }; private: @@ -74,6 +77,7 @@ namespace tunnel std::set, TunnelCreationTimeCmp> m_InboundTunnels; // recent tunnel appears first mutable std::mutex m_OutboundTunnelsMutex; std::set, TunnelCreationTimeCmp> m_OutboundTunnels; + mutable std::mutex m_TestsMutex; std::map, std::shared_ptr > > m_Tests; bool m_IsActive; diff --git a/build/CMakeLists.txt b/build/CMakeLists.txt index 7227f4ea..577dcc66 100644 --- a/build/CMakeLists.txt +++ b/build/CMakeLists.txt @@ -46,6 +46,7 @@ set (LIBI2PD_SRC "${CMAKE_SOURCE_DIR}/Base.cpp" "${CMAKE_SOURCE_DIR}/util.cpp" "${CMAKE_SOURCE_DIR}/Datagram.cpp" + "${CMAKE_SOURCE_DIR}/Family.cpp" "${CMAKE_SOURCE_DIR}/Signature.cpp" "${CMAKE_SOURCE_DIR}/api.cpp" ) diff --git a/contrib/certificates/family/i2p-dev.crt b/contrib/certificates/family/i2p-dev.crt new file mode 100644 index 00000000..a5796514 --- /dev/null +++ b/contrib/certificates/family/i2p-dev.crt @@ -0,0 +1,13 @@ +-----BEGIN CERTIFICATE----- +MIICCjCCAa2gAwIBAgIEfT9YJTAMBggqhkjOPQQDAgUAMHkxCzAJBgNVBAYTAlhY +MQswCQYDVQQIEwJYWDELMAkGA1UEBxMCWFgxHjAcBgNVBAoTFUkyUCBBbm9ueW1v +dXMgTmV0d29yazEPMA0GA1UECxMGZmFtaWx5MR8wHQYDVQQDExZpMnAtZGV2LmZh +bWlseS5pMnAubmV0MB4XDTE1MTIwOTIxNDIzM1oXDTI1MTIwODIxNDIzM1oweTEL +MAkGA1UEBhMCWFgxCzAJBgNVBAgTAlhYMQswCQYDVQQHEwJYWDEeMBwGA1UEChMV +STJQIEFub255bW91cyBOZXR3b3JrMQ8wDQYDVQQLEwZmYW1pbHkxHzAdBgNVBAMT +FmkycC1kZXYuZmFtaWx5LmkycC5uZXQwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNC +AAR7FPSglYrxeSPzv74A1fTwjajZWV0TljqEMBS/56juZQB/7xOwrsHFHA0eEEF9 +dTH64wx3lhV/9sh/stwPU2MToyEwHzAdBgNVHQ4EFgQUQh4uRP1aaX8TJX5dljrS +CeFNjcAwDAYIKoZIzj0EAwIFAANJADBGAiEAhXlEKGCjJ4urpi2db3OIMl9pB+9t +M+oVtAqBamWvVBICIQDBaIqfwLzFameO5ULgGRMysKQkL0O5mH6xo910YQV8jQ== +-----END CERTIFICATE----- diff --git a/contrib/certificates/reseed/j_at_torontocrypto.org.crt b/contrib/certificates/reseed/j_at_torontocrypto.org.crt new file mode 100644 index 00000000..4a2789ec --- /dev/null +++ b/contrib/certificates/reseed/j_at_torontocrypto.org.crt @@ -0,0 +1,34 @@ +-----BEGIN CERTIFICATE----- +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 +-----END CERTIFICATE----- diff --git a/contrib/certificates/reseed/matt_at_drollette.com.crt b/contrib/certificates/reseed/matt_at_drollette.com.crt deleted file mode 100644 index e490a152..00000000 --- a/contrib/certificates/reseed/matt_at_drollette.com.crt +++ /dev/null @@ -1,32 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIFgzCCA2ugAwIBAgIEB52rdjANBgkqhkiG9w0BAQ0FADByMQswCQYDVQQGEwJY -WDELMAkGA1UECBMCWFgxCzAJBgNVBAcTAlhYMR4wHAYDVQQKExVJMlAgQW5vbnlt -b3VzIE5ldHdvcmsxDDAKBgNVBAsTA0kyUDEbMBkGA1UEAwwSbWF0dEBkcm9sbGV0 -dGUuY29tMB4XDTE0MDcyMTEzMjYxM1oXDTI0MDcyMDEzMjYxM1owcjELMAkGA1UE -BhMCWFgxCzAJBgNVBAgTAlhYMQswCQYDVQQHEwJYWDEeMBwGA1UEChMVSTJQIEFu -b255bW91cyBOZXR3b3JrMQwwCgYDVQQLEwNJMlAxGzAZBgNVBAMMEm1hdHRAZHJv -bGxldHRlLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAL5M9wKT -csNLg4EA3fW7LleTQdrm3stPnoUvFmsNZHGgsKt1Nc1qCNis3kr2QEY+4Z398U7r -7xGEQFa7D/9SPHf6n1uVXc9DIcmwBtEB0FPB1XPFp2h00ZXIv24yiLN3GQT1woAM -yEbBWsUgn8K/iMBeA5dU2vPwAbGO/0ibD62frgGdYqU2EeiJ/U6vBmKxvC+q2noL -gnyfQJEJANXgf+Cw/gBaS6yn5ZsYcenLNenID2TQKQ6Q/NxYrDYRdWdId29iwldt -dmNSmASv8C7g9d/isZkpmtYNkE4J4m0W9wKziOoyvLSMo8ec67QmCKaPaYKTHTjx -aUuja02+mnlV4DSdZo6nPkSdokRY0+5e6q7+dIPefu8ealGEAE5oedEfl5iM5Fnz -phTR+ePodBK3sB+bMi1NMppbWugpFpdqs1hg2KNKSSG8C4/eTqf2nnlDiVvvFANc -imt6tk0pZcKqveRiDSgI8mTzTcrNgVClsCLoInY5Vab7onZjY9bGijPQ2i1P6+qu -5G6LiLFW7xFq2BcX1DnTztcJ8Yu9NYHhR21J6u7Dr8YHntes3mnth1F0BX3FVA1s -9SaE9/pNhdqap9owpEhNoE1Ke3LorVLL8jyQsqgRHx8VdhWdi9Ao0mzzeI9HYX0j -nZ7uXK5DqGG74K6eWoS9jZSDJLj3IBkIr3B/AgMBAAGjITAfMB0GA1UdDgQWBBTK -YjH+9Jv82Zqi86r95/1sXUCOnDANBgkqhkiG9w0BAQ0FAAOCAgEAsDyl3dS/5pR1 -iDN0zE70HN1Sjv55c5um6N39rgz8JSObbAMihhpjRXPR6yl0PdfVcswdCuEaaykp -ppPNY5ObqZIdqI92XOaOhSA3AkZwZffbwaoXFYiawq1aQG1HP7oxXzWwbnbPOxgz -6ThNP5DJan53Mk8TAhxoJkEJxVlMwIiC+QEgqDNYrP8oNOR2J1EXgzsHheEKObyP -xTwRYFqZU/7BQlFeB0LG1LIy9zXAHlb/XIor10w6ChPDW7DiDwGq3zDJw1d8eiUn -RoPRmFjTqn+3rGaEkk+vUFHoWo7cLCEIC3+P9wlY4Kel+ldXMmuJ+BZ1glFXeO3L -VO85n7iVIyBbwo7RLtNaBvrRQIEG3ld5UOKklLlWwhrX/FXksEhdFvmuF9sbiYNr -cg81sbwZlX7Gi7VicXkykFFXwRRr3UblDtfeevouxk4nMVzcDsmzGeAZKQBvcxHa -Pzc70YwnVRqTc87c0bEwPoxK1Vb26+DILyDjKb/AkTw/rwj6vcJZP2ad+hpiz5Ka -nlbY2cI3JJb0TQiDiOIk+xFqC5oHUTSEmfqA6sA5o/RqdwDpkfpgI5mCwhYzDSLD -jfS+263ylhanl7oz0sM+GtH63owVbYJAFT2EozT9siTIErvJESL4Z80yUQG63d/7 -fss8T6gOo19esb/KEMZGZE4pAApakWM= ------END CERTIFICATE----- diff --git a/contrib/certificates/ssl/193.150.121.66.crt b/contrib/certificates/ssl/193.150.121.66.crt deleted file mode 100644 index 450581d2..00000000 --- a/contrib/certificates/ssl/193.150.121.66.crt +++ /dev/null @@ -1,21 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDgDCCAmgCCQCAKEkFUJcEezANBgkqhkiG9w0BAQUFADCBgTELMAkGA1UEBhMC -Tk8xDTALBgNVBAgMBE9zbG8xDTALBgNVBAcMBE9zbG8xDDAKBgNVBAoMA0kyUDEM -MAoGA1UECwwDSTJQMRcwFQYDVQQDDA4xOTMuMTUwLjEyMS42NjEfMB0GCSqGSIb3 -DQEJARYQbWVlaEBpMnBtYWlsLm9yZzAeFw0xMzA2MjcxODM2MjhaFw0yMDA2MjUx -ODM2MjhaMIGBMQswCQYDVQQGEwJOTzENMAsGA1UECAwET3NsbzENMAsGA1UEBwwE -T3NsbzEMMAoGA1UECgwDSTJQMQwwCgYDVQQLDANJMlAxFzAVBgNVBAMMDjE5My4x -NTAuMTIxLjY2MR8wHQYJKoZIhvcNAQkBFhBtZWVoQGkycG1haWwub3JnMIIBIjAN -BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuBuFY4ZFvsbr5l1/s/GeUBLIWQLB -nqrRkonrwCyxgjSnnG1uz/Z5nf6QDUjiVnFKMXenLaDn4KCmEi4LjWQllhK9r6pj -BRkR7C0DTHq7WqfyvWnGSZZsOJDiH2vLlivV8N9oGdjxvv0N9No3AJcsmLYrxSLi -6/JF8xZ2HGuT/oWW6aWvpIOKpIqti865BJw5P5KgYAS24J8vHRFM3FA4dfLNTBA2 -IGqPqYLQA+2zfOC4z01aArmcYnT1iJLT7krgKnr/BXdJfGQ2GjxkRSt8IwB6WmXA -byz6QdNYM/0eubi102/zpD/DrySTU2kc8xKjknGUqBJvVdsL+iLK98uJrQIDAQAB -MA0GCSqGSIb3DQEBBQUAA4IBAQCTimMu3X7+ztXxlIFhwGh42GfMjeBYT0NHOLAy -ZtQNRqhNvkl3jZ4ERPLxP99+bcAfCX0wgVpgD32OWEZopwveRyMImP8HfFr4NnZ+ -edbM37fRYiVJv57kbi6O0rhEC7J5JF+fnCaZVLCuvYIrIXTdxTjvxuLhyan6Ej7V -7iGDJ8t16tpLVJgcXfRg+dvAa6aDOK6x3w78j0bvh6rhvpOd9sW/Nk3LBKP4Xgkx -PHkqm3hNfDIu8Hubeav9SA1kLVMS/uce52VyYMEDauObfC65ds0GRmCtYhZqMvj+ -FFCbssLraVJE9Hi/ZKGu33jNngDCG+wG+nmleksMYE1yTSRt ------END CERTIFICATE----- diff --git a/contrib/certificates/ssl/download.xxlspeed.com.crt b/contrib/certificates/ssl/download.xxlspeed.com.crt new file mode 100644 index 00000000..253c0509 --- /dev/null +++ b/contrib/certificates/ssl/download.xxlspeed.com.crt @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDLDCCArKgAwIBAgIJAMOgj4vE9qpcMAoGCCqGSM49BAMEMIHTMQswCQYDVQQG +EwJERTEeMBwGA1UECAwVZG93bmxvYWQueHhsc3BlZWQuY29tMR4wHAYDVQQHDBVk +b3dubG9hZC54eGxzcGVlZC5jb20xHjAcBgNVBAoMFWRvd25sb2FkLnh4bHNwZWVk +LmNvbTEeMBwGA1UECwwVZG93bmxvYWQueHhsc3BlZWQuY29tMR4wHAYDVQQDDBVk +b3dubG9hZC54eGxzcGVlZC5jb20xJDAiBgkqhkiG9w0BCQEWFWRvd25sb2FkLnh4 +bHNwZWVkLmNvbTAeFw0xNTEyMzAxMTI4NDJaFw0yMTA2MjExMTI4NDJaMIHTMQsw +CQYDVQQGEwJERTEeMBwGA1UECAwVZG93bmxvYWQueHhsc3BlZWQuY29tMR4wHAYD +VQQHDBVkb3dubG9hZC54eGxzcGVlZC5jb20xHjAcBgNVBAoMFWRvd25sb2FkLnh4 +bHNwZWVkLmNvbTEeMBwGA1UECwwVZG93bmxvYWQueHhsc3BlZWQuY29tMR4wHAYD +VQQDDBVkb3dubG9hZC54eGxzcGVlZC5jb20xJDAiBgkqhkiG9w0BCQEWFWRvd25s +b2FkLnh4bHNwZWVkLmNvbTB2MBAGByqGSM49AgEGBSuBBAAiA2IABFObW+pRshVD +gvMPvGdPGji2DAfdvkl3gvpyiQ0PUqxuTxwtBlwBo6cz2cMnkKdActuvE/VOTRG5 +/z7CcvG7b0+qgrHDffg7C2wWlAN0dSjuoV2Av7VoN1vEU96TCtheSqNQME4wHQYD +VR0OBBYEFPbEZH9oidjadUfvsnsh23b1jZnVMB8GA1UdIwQYMBaAFPbEZH9oidja +dUfvsnsh23b1jZnVMAwGA1UdEwQFMAMBAf8wCgYIKoZIzj0EAwQDaAAwZQIwT1py +AV2hLFL/5ZgwmybdaCBBUsj3cGYroXb/Z2BHLDYmH8enK0DhhWyPdN1a7eCsAjEA +oQRU7lhXrisckjA2911Q5mA8y2sFAN/PDPrUeU9PI5vDF/ezTi20zULMOqbU1uRz +-----END CERTIFICATE----- diff --git a/contrib/certificates/ssl/i2p.mooo.com.crt b/contrib/certificates/ssl/i2p.mooo.com.crt index ac10e1ff..839767b3 100644 --- a/contrib/certificates/ssl/i2p.mooo.com.crt +++ b/contrib/certificates/ssl/i2p.mooo.com.crt @@ -1,23 +1,23 @@ -----BEGIN CERTIFICATE----- -MIIDvjCCAyegAwIBAgICZhcwDQYJKoZIhvcNAQEFBQAwdTELMAkGA1UEBhMCVVMx -DTALBgNVBAgMBG5vbmUxDTALBgNVBAcMBG5vbmUxDTALBgNVBAoMBG5vbmUxDTAL -BgNVBAsMBG5vbmUxFTATBgNVBAMMDGkycC5tb29vLmNvbTETMBEGCSqGSIb3DQEJ -ARYEbm9uZTAeFw0xMTEwMjMyMTM2NDFaFw0xOTEwMjMyMTM2NDFaMGYxCzAJBgNV -BAYTAlVTMQ0wCwYDVQQIDARub25lMQ0wCwYDVQQKDARub25lMQ0wCwYDVQQLDARu -b25lMRUwEwYDVQQDDAxpMnAubW9vby5jb20xEzARBgkqhkiG9w0BCQEWBG5vbmUw -ggGPMA0GCSqGSIb3DQEBAQUAA4IBfAAwggF3AoIBbgMG1O7HRVa7UoiKbQTmKy5m -x79Na8vjD3etcOwfc4TSenQFvn+GbAWkJwKpM8uvOcgj1CxNeHWdSaeTFH1OwJsw -vl3leJ7clMdo3hpQDhPeGzBLyOiWwFHVn15YKa9xcM7S9Op5Q6rKBHUyyx1vGSz+ -/NBmkktpI6rcGFfP3ISRL0auR+db+adWv4TS6W8YiwQIVZNbSlKP6FNO9Mv1kxQZ -KoHPn8vT/LtAh1fcI6ryBuy3F5oHfbGumIwsS5dpowryFxQzwg5vtMA7AMCMKyXv -hP/W6OuaaEP5MCIxkWjQs35gOYa8eF1dLoy3AD9yVVhoNrA8Bc5FnVFJ32Qv7agy -qRY85cXBA6hT/Qzs/wWwp7WrrnZuifaSv/u/Ayi5vX42/bf86PSM2IRNIESoA98A -NFz4U2KGq9s1K2JbkQmnFy8IU0w7CMq6PvNEm/uNjSk6OE1rcCXML+EuX0zmXy8d -PjRbLzC9csSg2CqMtQIDAQABo3sweTAJBgNVHRMEAjAAMCwGCWCGSAGG+EIBDQQf -Fh1PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUdjuOczdG -hUpYzH0UXqKrOleT8GkwHwYDVR0jBBgwFoAU+SKWC49cM5sCodv89AFin3pkS0Yw -DQYJKoZIhvcNAQEFBQADgYEAKYyWlDIStjjbn/ZzVScKR174I8whTbdqrX/vp9dr -2hMv5m4F+aswX4Jr58WneKg2LvRaL6xEhoL7OAQ6aB/7xVSpDjIrrBLZd513NAam -X6bOPYJ6IH7Vw9ClFY3AlfzsNlgRMXno7rySKKzhg24kusNwKDH2yCphZy4BgjMn -y6A= +MIIDvTCCAqWgAwIBAgIJAOeW0ejPrHimMA0GCSqGSIb3DQEBCwUAMHUxCzAJBgNV +BAYTAlVTMQ0wCwYDVQQIDARub25lMQ0wCwYDVQQHDARub25lMQ0wCwYDVQQKDARu +b25lMQ0wCwYDVQQLDARub25lMRUwEwYDVQQDDAxpMnAubW9vby5jb20xEzARBgkq +hkiG9w0BCQEWBG5vbmUwHhcNMTUwMjA4MTczMzA5WhcNMTkwMzE5MTczMzA5WjB1 +MQswCQYDVQQGEwJVUzENMAsGA1UECAwEbm9uZTENMAsGA1UEBwwEbm9uZTENMAsG +A1UECgwEbm9uZTENMAsGA1UECwwEbm9uZTEVMBMGA1UEAwwMaTJwLm1vb28uY29t +MRMwEQYJKoZIhvcNAQkBFgRub25lMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB +CgKCAQEAqxej7oRl9GOb8benIBCENrJXoow1iWhI9M+2nU0SaonrCDql5M2YMlwd +HzYUWtFbRjz2NinjB0fgFq9cfzHfr1Sc8k/OeGg1jvNfqt8wWo9tryQNjiHtDQUZ +6lQ5T13I+lj0CBasowgbApKQfrYjvaeuTaVYTfP8IVA60hoUQ+sy9JN+Unsx3/0Y +PLLd98+bT27qYuBNRB1g/ifUTd9Wosj2PevGBlCxYDaUjmCG4Q8kcQr87KvM6RTu +3AV61s/Wyy1j2YemlGG/ZhJ44YnlVMSu1vTjt9HInVf3lRRx/+RzbQO3lqeVC8LC +Bq3KbSlfJVx4vHslfHwBFw9A4rmD1QIDAQABo1AwTjAdBgNVHQ4EFgQUsSUvX0ED +yivB67iksVwZ+b8vLtQwHwYDVR0jBBgwFoAUsSUvX0EDyivB67iksVwZ+b8vLtQw +DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAde4wts7Q8TylFEc38ftJ +2f285fFIR7P1SSbBcHPK2eBwLEg0zJyFrCeiHuEpPrn+d5GqL2zOskjfcESGmDBT +aFajj8jPBJj/AmpkdWJG6a1YKro5tu9wrlenGwHOHu2/Cl0IJvafxrOs2x4G+2Nl +5Hcw/FIy8mK7eIch4pACfi0zNMZ6KMCKfX9bxPrQo78WdBfVjbrIBlgyOQJ5NJEF +JlWvS7Butv7eERi4I2huN5VRJSCFzjbuO+tjP3I8IB6WgdBmTeqq8ObtXRgahBuD +ZmkvqVSfIzK5JN4GjO8FOdCBomuwm9A92kgmAptwQwAHM9qCDJpH8L07/7poxlGb +iA== -----END CERTIFICATE----- diff --git a/contrib/certificates/ssl/i2p.mooo.com2.crt b/contrib/certificates/ssl/i2p.mooo.com2.crt deleted file mode 100644 index 839767b3..00000000 --- a/contrib/certificates/ssl/i2p.mooo.com2.crt +++ /dev/null @@ -1,23 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDvTCCAqWgAwIBAgIJAOeW0ejPrHimMA0GCSqGSIb3DQEBCwUAMHUxCzAJBgNV -BAYTAlVTMQ0wCwYDVQQIDARub25lMQ0wCwYDVQQHDARub25lMQ0wCwYDVQQKDARu -b25lMQ0wCwYDVQQLDARub25lMRUwEwYDVQQDDAxpMnAubW9vby5jb20xEzARBgkq -hkiG9w0BCQEWBG5vbmUwHhcNMTUwMjA4MTczMzA5WhcNMTkwMzE5MTczMzA5WjB1 -MQswCQYDVQQGEwJVUzENMAsGA1UECAwEbm9uZTENMAsGA1UEBwwEbm9uZTENMAsG -A1UECgwEbm9uZTENMAsGA1UECwwEbm9uZTEVMBMGA1UEAwwMaTJwLm1vb28uY29t -MRMwEQYJKoZIhvcNAQkBFgRub25lMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB -CgKCAQEAqxej7oRl9GOb8benIBCENrJXoow1iWhI9M+2nU0SaonrCDql5M2YMlwd -HzYUWtFbRjz2NinjB0fgFq9cfzHfr1Sc8k/OeGg1jvNfqt8wWo9tryQNjiHtDQUZ -6lQ5T13I+lj0CBasowgbApKQfrYjvaeuTaVYTfP8IVA60hoUQ+sy9JN+Unsx3/0Y -PLLd98+bT27qYuBNRB1g/ifUTd9Wosj2PevGBlCxYDaUjmCG4Q8kcQr87KvM6RTu -3AV61s/Wyy1j2YemlGG/ZhJ44YnlVMSu1vTjt9HInVf3lRRx/+RzbQO3lqeVC8LC -Bq3KbSlfJVx4vHslfHwBFw9A4rmD1QIDAQABo1AwTjAdBgNVHQ4EFgQUsSUvX0ED -yivB67iksVwZ+b8vLtQwHwYDVR0jBBgwFoAUsSUvX0EDyivB67iksVwZ+b8vLtQw -DAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAde4wts7Q8TylFEc38ftJ -2f285fFIR7P1SSbBcHPK2eBwLEg0zJyFrCeiHuEpPrn+d5GqL2zOskjfcESGmDBT -aFajj8jPBJj/AmpkdWJG6a1YKro5tu9wrlenGwHOHu2/Cl0IJvafxrOs2x4G+2Nl -5Hcw/FIy8mK7eIch4pACfi0zNMZ6KMCKfX9bxPrQo78WdBfVjbrIBlgyOQJ5NJEF -JlWvS7Butv7eERi4I2huN5VRJSCFzjbuO+tjP3I8IB6WgdBmTeqq8ObtXRgahBuD -ZmkvqVSfIzK5JN4GjO8FOdCBomuwm9A92kgmAptwQwAHM9qCDJpH8L07/7poxlGb -iA== ------END CERTIFICATE----- diff --git a/contrib/certificates/ssl/ieb9oopo.mooo.com.crt b/contrib/certificates/ssl/ieb9oopo.mooo.com.crt deleted file mode 100644 index 8be9eef8..00000000 --- a/contrib/certificates/ssl/ieb9oopo.mooo.com.crt +++ /dev/null @@ -1,25 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIESzCCAzOgAwIBAgIJAKII1waVnWddMA0GCSqGSIb3DQEBCwUAMIG7MQswCQYD -VQQGEwJERTEaMBgGA1UECAwRaWViOW9vcG8ubW9vby5jb20xGjAYBgNVBAcMEWll -Yjlvb3BvLm1vb28uY29tMRowGAYDVQQKDBFpZWI5b29wby5tb29vLmNvbTEaMBgG -A1UECwwRaWViOW9vcG8ubW9vby5jb20xGjAYBgNVBAMMEWllYjlvb3BvLm1vb28u -Y29tMSAwHgYJKoZIhvcNAQkBFhFpZWI5b29wby5tb29vLmNvbTAeFw0xNDExMjIx -MzQzNThaFw0yMDA1MTQxMzQzNThaMIG7MQswCQYDVQQGEwJERTEaMBgGA1UECAwR -aWViOW9vcG8ubW9vby5jb20xGjAYBgNVBAcMEWllYjlvb3BvLm1vb28uY29tMRow -GAYDVQQKDBFpZWI5b29wby5tb29vLmNvbTEaMBgGA1UECwwRaWViOW9vcG8ubW9v -by5jb20xGjAYBgNVBAMMEWllYjlvb3BvLm1vb28uY29tMSAwHgYJKoZIhvcNAQkB -FhFpZWI5b29wby5tb29vLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC -ggEBAMhcnkSifOMw5bd66UlvYVsc42H22Nuy64qhtJHtggofrwBooF38kRCBVFL8 -9Xjzr0xsSshvO6p7E+CEUtA8v55l5vNbUTAvGP9WmzeZyZuCFg9Heo3orNMbIK7m -ppwKhwh6tFEIEpUTz/+xF5NRt0+CqcS4aNHuH3JPwNugfTBuSa86GeSaqL7K4eEZ -bZXqQ16Onvi0yyMqRJDp/ijRFxr2eKGPWb55kuRSET9PxVhlgRKULZkr39Dh9q1c -wb9lAMLMRZIzPVnyvC9jWkIqSDl5bkAAto0n1Jkw92rRp6EVKgSLA/4vl9wTb6xf -WfT5cs7pykAE0WXBr9TqpS3okncCAwEAAaNQME4wHQYDVR0OBBYEFGeEOHhWiKwZ -TGbc7uuK3DD7YjYZMB8GA1UdIwQYMBaAFGeEOHhWiKwZTGbc7uuK3DD7YjYZMAwG -A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAAzRA/0OpJtCO4kQkTn/hux9 -dRi9T6B54Xav5jG53iAPLTeMxsaLkvweh2pZ3kvEUrQhvW0JF8QBrHTsgxzb4Wd6 -FNDHSgJbZv3uCjFtWeuUh+GTG1k9uwgNIEnx7J9Vp0JCi4ezi/HMNI7c+LjinM9f -hrAzclkeRPLYg645DkxckLyDUbrc9v1qWFoTpezXSBPO7n3Wk4sCytdoA1FkTdXh -RF4BWCl/3uOxcrn0TqoC9vCh8RcxnllOiOO5j4+PQ1Z6NkQ/5oRCK/jjaWc3Lr6/ -FicOZJe29BVnrPGynqe0Ky1o+kTdXFflKowfr7g8dwn8k9YavjtGbl1ZSHeuMF8= ------END CERTIFICATE----- diff --git a/contrib/certificates/ssl/link.mx24.eu.crt b/contrib/certificates/ssl/link.mx24.eu.crt deleted file mode 100644 index 8e0d910f..00000000 --- a/contrib/certificates/ssl/link.mx24.eu.crt +++ /dev/null @@ -1,24 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIEDzCCAvegAwIBAgIJAMsPNG1k0yV4MA0GCSqGSIb3DQEBCwUAMIGdMQswCQYD -VQQGEwJERTEVMBMGA1UECAwMbGluay5teDI0LmV1MRUwEwYDVQQHDAxsaW5rLm14 -MjQuZXUxFTATBgNVBAoMDGxpbmsubXgyNC5ldTEVMBMGA1UECwwMbGluay5teDI0 -LmV1MRUwEwYDVQQDDAxsaW5rLm14MjQuZXUxGzAZBgkqhkiG9w0BCQEWDGxpbmsu -bXgyNC5ldTAeFw0xNDExMTkxOTE4NTRaFw0yMDA1MTExOTE4NTRaMIGdMQswCQYD -VQQGEwJERTEVMBMGA1UECAwMbGluay5teDI0LmV1MRUwEwYDVQQHDAxsaW5rLm14 -MjQuZXUxFTATBgNVBAoMDGxpbmsubXgyNC5ldTEVMBMGA1UECwwMbGluay5teDI0 -LmV1MRUwEwYDVQQDDAxsaW5rLm14MjQuZXUxGzAZBgkqhkiG9w0BCQEWDGxpbmsu -bXgyNC5ldTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL8modDBRkyh -SHSm92pTfguO3F6n5ocsBJ4vaVoosYq3ILCsapjqmynMHZUef6gEB7+Gn5cKXsH2 -JaKOeb8DHrOFCaxfj187x1QfZj1UNMQblx2T9q4th12tqp+k4JuLwgemr+2uAUpM -xx/uHRJXD0hf67+fHQFYNVfa+WvT46xlKGsWDQ0LBsA/z4YGnyeaV4PrS5nj3euA -IbdfDj7rJea3bfhSqYA1ZH1cquKlsXOOYO5cIcXsa5dxDWX51QS+i7+ocph+JN1X -dRh6ZirE9OXZVXwXXVRnJSYjgBlP/DQBdE7YkE1R3LyCVZsgxJaaLV/ujijOIK61 -SqEhHvFNRe0CAwEAAaNQME4wHQYDVR0OBBYEFB6XRz6VZlrAE+3xL6AyKrkq+y2X -MB8GA1UdIwQYMBaAFB6XRz6VZlrAE+3xL6AyKrkq+y2XMAwGA1UdEwQFMAMBAf8w -DQYJKoZIhvcNAQELBQADggEBADhxBA5GHisDVf5a+1hIi7FBGBjJJLqzlaKh+bFB -gTCYfk3F4wYzndr1HpdCZSSYDtY3mXFNMWQCpwvwvy1DM+9AMRY68wKNXHa/WypW -zQSqTfEH8cdaIXUALB7pdWFVr3rx0f7/8I0Gj/ByUbJ94rzd22vduX5riY0Rag6B -dPtW0M9bJrC1AIjexzDcStupj9v/ceGYZQYC4zb2tZ7Ek/6q+vei8TxWZjku7Dl4 -YRPXXufyB24uQ1hJVy2fSyIJ63tIRJoEFLBNaKDOB53i10xLWBcsJpXKY57AOQMn -flqW4HG8uGJ/o1WjhiOB9eI7T9toy08zNzt+kSI/blFIoek= ------END CERTIFICATE----- diff --git a/contrib/certificates/ssl/netdb.rows.io.crt b/contrib/certificates/ssl/netdb.rows.io.crt deleted file mode 100644 index 5d99233c..00000000 --- a/contrib/certificates/ssl/netdb.rows.io.crt +++ /dev/null @@ -1,33 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIFszCCA52gAwIBAgIRALWZzF745GPT8GVUcZ0RMg0wCwYJKoZIhvcNAQELMG0x -CzAJBgNVBAYTAlhYMR4wHAYDVQQKExVJMlAgQW5vbnltb3VzIE5ldHdvcmsxDDAK -BgNVBAsTA0kyUDELMAkGA1UEBxMCWFgxCzAJBgNVBAkTAlhYMRYwFAYDVQQDEw1u -ZXRkYi5yb3dzLmlvMB4XDTE0MTIyMDE2NDIwNVoXDTE2MTIxOTE2NDIwNVowbTEL -MAkGA1UEBhMCWFgxHjAcBgNVBAoTFUkyUCBBbm9ueW1vdXMgTmV0d29yazEMMAoG -A1UECxMDSTJQMQswCQYDVQQHEwJYWDELMAkGA1UECRMCWFgxFjAUBgNVBAMTDW5l -dGRiLnJvd3MuaW8wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCTZyJF -Im9pnc7OO5DfQy4SuotUztO5BJX7xniTqD4fKLQQXzZFeT4XHrkDste8TsTzUfxt -CWDEBH3af5cpnwWMT28rlRw2DlPr+LnAgt7VjFXdhFZr1N5VfNlTI1K3OiZ/DRlB -92CoTypyx4ebNfLtZfh+TPLOdg5UqROpHIrybsUj2IaG3IpGHJK8FuH79b/X5oVI -FlDZJs5QsJEARzq2QMJd6fnNqkCBSSjNpeL7TtDar9EKa6+O7s351kH8MVFNSogB -F0Hqu8LYaRC1L1JCz5lsOYKepp3MMIOdDOhy+FTd8NuNZXYkUTdTNI4dB6w4Z6o+ -xlnHEPpezIAAlPXLiupvlEi0om69/TMS+pLDBLAOlCZ2YaXS18UrSbmYYlekg40J -nEeALt8ZdsU/is7Q6SJZ3UltFIPCuMD+ixvaIvakkhNiqEWPxdg0XxAK1ZJYFup+ -2aVtPLQIzWePkG/VbdA5cxQKNtRwOgvCoKIE29nUbxuq2PCmMhLAfXHeieSzP5c7 -Q8A23qX94hwCIePj1YA9uNtStjECfVS1wjyXV4M1tTFUdSJv4aVtFjtya7PY+6SG -Srz11SqBWSqyJ/C14Su0QY/HquglzMRnkJ49Scwb+79hl7kPslO1iIgPLE5S2fIW -ZwJ/4AgGb6BZT8XPEYYANEA5y7KGanYNo8KdYwIDAQABo1IwUDAOBgNVHQ8BAf8E -BAMCAKQwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDwYDVR0TAQH/BAUwAwEB/zAYBgNV -HREEETAPgg1uZXRkYi5yb3dzLmlvMAsGCSqGSIb3DQEBCwOCAgEAMjQSHPR/p9If -mJA1y489D1NB2CxfwO+CgAIs9HA7OsdneQBZTldMgBHoQGifkpD1uSl8DHoZqnJ8 -wo5YWcT1rYkP+V1jGfZj92VvfQL0/R4G4hWdQwYY0CcXN8ixS36UDQVSFKb4zvNG -j9iIN57WToEmxp5noHguKrpViwhXCMCpAXr3ZIv/Fd+QACNEXuvdZgbtwfOTPLKh -ZlkUPgVHiQopeQnZhZCT3aLZ5lndrUtWlQYiGN/OolVyRie+ysuxjRR4L5brt4Rz -hrwFBswbQZlgxJ3Nod9/wEdEJWP4+X69ggzOkBB+PgpOFpuDlJxNTcPA/WFIlsm0 -CzCv/o8Vg+MMWFPMwEZrk6UQXXACr1AEF+MUnZq3o5JaLvHoUcikewbZPcTCNvDp -nqT1RN9vq/MGdlRfPJkF028IXPz7T9DXXPXhJvv+FAfnOkREeUYpzBIftyYf92ol -l63z0FooVUTKWYPvFFgl5ShNnINTMVXPCZp8j7myLGSLOAFFwiaL1OtvftgxXfzC -B7Qj42SNhFUrHmO9fH3H2ptm/iW/Xe5eqgeb6MVGQ/eQJpdp0AvpDa50/AYNt1Iq -CcMKmBgzUezrIN24XXW/LZwazlc7I8e5RzgbEgXEDBZu21TApTKlmOqEYle8294W -fWThMdwk1kTrWxLooiVrS5A1hXqADqE= ------END CERTIFICATE----- diff --git a/contrib/certificates/ssl/reseed.i2p.vzaws.com.crt b/contrib/certificates/ssl/reseed.i2p.vzaws.com.crt new file mode 100644 index 00000000..25f9e369 --- /dev/null +++ b/contrib/certificates/ssl/reseed.i2p.vzaws.com.crt @@ -0,0 +1,33 @@ +-----BEGIN CERTIFICATE----- +MIIFyDCCA7KgAwIBAgIRAJD+6g+eAsWKlwas0Ymsq24wCwYJKoZIhvcNAQELMHQx +CzAJBgNVBAYTAlhYMR4wHAYDVQQKExVJMlAgQW5vbnltb3VzIE5ldHdvcmsxDDAK +BgNVBAsTA0kyUDELMAkGA1UEBxMCWFgxCzAJBgNVBAkTAlhYMR0wGwYDVQQDExRy +ZXNlZWQuaTJwLnZ6YXdzLmNvbTAeFw0xNTA1MTkyMDIwNTRaFw0xNzA1MTgyMDIw +NTRaMHQxCzAJBgNVBAYTAlhYMR4wHAYDVQQKExVJMlAgQW5vbnltb3VzIE5ldHdv +cmsxDDAKBgNVBAsTA0kyUDELMAkGA1UEBxMCWFgxCzAJBgNVBAkTAlhYMR0wGwYD +VQQDExRyZXNlZWQuaTJwLnZ6YXdzLmNvbTCCAiIwDQYJKoZIhvcNAQEBBQADggIP +ADCCAgoCggIBAJCAUT9WD2kLPgh5tK5Pb9xpvjKZU5o4HxzM2Nja34+AESnjDwSw +vIuQgjUQ3mqlHS292sdy30nk8kLJvnQ8rRVFrBn9xWdWzSp53thm5rn8h+7cUsBG +r51w0VY/5Zo8b3oxd8PWDd91otuRgJc6xSqIz5i3G1IvTIhHjXfqPwIFvaAbgGOb +xyf5q/LNz9KPAE9DzI4g63AM7+EIBUd/3+TO/27+s6rOWQlIBpHmd+YvyyG9PwM/ +bpj9sVpz8S6THSu8srxoI/L4vxsMp0KkySxPAVdmZi8Z5HyJ8b7LtabeEmXaOeIh +F9ZRWyIZWqPZm+dTfM6GyT/JWunBNXWVFlUDJqPCsFB7gdN1GBGW7uv4c6Lq0h7g +Xqd6R2hcthmH8vRasrYisZdfaODZtdUM16Sk6MIl2ALoA6tyAJNGlRKHJutLnY7l +dsD81VfU9Q8ovZ+kb4EHYJx53enW7CUswvKyN2VPKYH3qNoiWW2fGdrEsjdbX575 +2bRn7f2BEDTuQgKSTdFjVMZ/d7ljddwNcPS7TS24X2i6lWFAAQpCarHzSE0uwzhZ +ikqhOEKdYwrmzYKv6QFszq2ALiWk1lrasB4zkMl1RY2nwGuh7OfsrXlaehDYZLOe +M9Ib7MfqXpdBFN5oHGXRKFc+1Bz7ZlOhC/OYiwqhSR9uZPEEg/YSMFsnAgMBAAGj +WTBXMA4GA1UdDwEB/wQEAwIApDATBgNVHSUEDDAKBggrBgEFBQcDATAPBgNVHRMB +Af8EBTADAQH/MB8GA1UdEQQYMBaCFHJlc2VlZC5pMnAudnphd3MuY29tMAsGCSqG +SIb3DQEBCwOCAgEASxpWtby7DBoSlHfJFwoQhp4n8WQTK9xt8HZ7vrmrq5XDkXef +QftjxEEhchGb/QPSt8RippKZqnFAGsoVeWb+tjQH1ijFHanifiuYz77C/08bCcfR +T+fNPhgCixnnGY9ZN+fKE0bQSrZAtGGl/q4rpRcZMQJ5TfhxJA6dC5ZiGAsFZwRQ +ziNUKRGxrLf7Wj2/J4vuHEezPA0XyNJMbG7MLRDWBS4Q9yHtmeVdduxn81WdgnlZ +ToYEEgh68i2sehDUQ+1ro/oLCISDP+hZF3OIUDmz13x7peFFpMb4lKbyoc1siOlV +7/e+XboYKDsTb6fb/mTVL4GjnRvdmXx4cOAkGM2LHbGSIZKGkIEvQWrXwRol3WUn +AcEMWY8KGaee23Syg4fG/4ejVuRZYz8fbk8es6Z6W1vw6gnra434dnYmCrEO6hQl +/77LntLODSgAkus6polZ5O1c7Aj0USMNDW/EFP98APVokT1RGK1wStZVxSUDqBDF +RRPSpEsOGJ6qA7GJuAWi9I3Msy2lBlKMK6Xgk3l/e7ZPU0he95JfxySldl0JzR2N +EGvUCRPDXAMVnp3eP/41MrODdyGo2wBf/0IutfkpJf+Xmbu4ZbgkdPDEwG1+4VZH +MMsGAo3fOR4sI0Wu9W92rXEbzkxwekfnG6D7QQI64AAr0p4w2yO1ALbqW2A= +-----END CERTIFICATE----- diff --git a/contrib/certificates/ssl/user.mx24.eu.crt b/contrib/certificates/ssl/user.mx24.eu.crt new file mode 100644 index 00000000..38c68ab5 --- /dev/null +++ b/contrib/certificates/ssl/user.mx24.eu.crt @@ -0,0 +1,17 @@ +-----BEGIN CERTIFICATE----- +MIICwDCCAkagAwIBAgIJAKXCoCBjd/C0MAoGCCqGSM49BAMEMIGdMQswCQYDVQQG +EwJERTEVMBMGA1UECAwMdXNlci5teDI0LmV1MRUwEwYDVQQHDAx1c2VyLm14MjQu +ZXUxFTATBgNVBAoMDHVzZXIubXgyNC5ldTEVMBMGA1UECwwMdXNlci5teDI0LmV1 +MRUwEwYDVQQDDAx1c2VyLm14MjQuZXUxGzAZBgkqhkiG9w0BCQEWDHVzZXIubXgy +NC5ldTAeFw0xNTA5MDMxNjMyNDVaFw0yMTAyMjMxNjMyNDVaMIGdMQswCQYDVQQG +EwJERTEVMBMGA1UECAwMdXNlci5teDI0LmV1MRUwEwYDVQQHDAx1c2VyLm14MjQu +ZXUxFTATBgNVBAoMDHVzZXIubXgyNC5ldTEVMBMGA1UECwwMdXNlci5teDI0LmV1 +MRUwEwYDVQQDDAx1c2VyLm14MjQuZXUxGzAZBgkqhkiG9w0BCQEWDHVzZXIubXgy +NC5ldTB2MBAGByqGSM49AgEGBSuBBAAiA2IABPlKs5fYTqVhIOMiR6U9U4TimxS3 +P5NBDVzeeIAgbw5KBC8UImScZVt9g4V1wQe5kPs7TxA2BfanAPZ+ekQiRRvMVQxD +bSlRYupEWhq5BrJI6Lq/HDc7VJe9UUWffWKUoKNQME4wHQYDVR0OBBYEFBGJ0Yr+ +PZXnrk5RafQEALUpAU6ZMB8GA1UdIwQYMBaAFBGJ0Yr+PZXnrk5RafQEALUpAU6Z +MAwGA1UdEwQFMAMBAf8wCgYIKoZIzj0EAwQDaAAwZQIxAPcovePHMCosrAQNzS5i +VDUiyPNLOxHyRBm79yKXGl13LxysB6OK+2M7t8j8E/udBwIwXVVjxN6aSgXYTJ7d +p+Hg/2CuBMwf41/ENRcYQA+oGS9bU6A+7U9KJ1xTWWoqsUEs +-----END CERTIFICATE----- diff --git a/docs/build_notes_unix.md b/docs/build_notes_unix.md index 882a8ece..292849a7 100644 --- a/docs/build_notes_unix.md +++ b/docs/build_notes_unix.md @@ -23,6 +23,13 @@ After successfull build i2pd could be installed with: ```bash make install ``` +or you can just use 'make' once you have all dependacies (boost and openssl) installed + +```bash +git clone https://github.com/PurpleI2P/i2pd.git +cd i2pd +make +``` Debian/Ubuntu ------------- diff --git a/filelist.mk b/filelist.mk index 4417ba9b..c35edcf0 100644 --- a/filelist.mk +++ b/filelist.mk @@ -4,7 +4,8 @@ LIB_SRC = \ Reseed.cpp RouterContext.cpp RouterInfo.cpp Signature.cpp SSU.cpp \ SSUSession.cpp SSUData.cpp Streaming.cpp Identity.cpp TransitTunnel.cpp \ Transports.cpp Tunnel.cpp TunnelEndpoint.cpp TunnelPool.cpp TunnelGateway.cpp \ - Destination.cpp Base.cpp I2PEndian.cpp FS.cpp Config.cpp util.cpp api.cpp + Destination.cpp Base.cpp I2PEndian.cpp FS.cpp Config.cpp Family.cpp \ + util.cpp api.cpp LIB_CLIENT_SRC = \ AddressBook.cpp BOB.cpp ClientContext.cpp I2PTunnel.cpp I2PService.cpp \ diff --git a/util.cpp b/util.cpp index 7c11d280..e871dac1 100644 --- a/util.cpp +++ b/util.cpp @@ -81,6 +81,7 @@ namespace http if (colon != std::string::npos) { std::string field = header.substr (0, colon); + boost::to_lower (field); if (field == i2p::util::http::TRANSFER_ENCODING) isChunked = (header.find ("chunked", colon + 1) != std::string::npos); } diff --git a/util.h b/util.h index d1d7f41a..13200591 100644 --- a/util.h +++ b/util.h @@ -12,12 +12,15 @@ namespace util { namespace http { - const char ETAG[] = "ETag"; + // in (lower case) + const char ETAG[] = "etag"; // ETag + const char LAST_MODIFIED[] = "last-modified"; // Last-Modified + const char TRANSFER_ENCODING[] = "transfer-encoding"; // Transfer-Encoding + const char CONTENT_ENCODING[] = "content-encoding"; // Content-Encoding + // out const char IF_NONE_MATCH[] = "If-None-Match"; - const char IF_MODIFIED_SINCE[] = "If-Modified-Since"; - const char LAST_MODIFIED[] = "Last-Modified"; - const char TRANSFER_ENCODING[] = "Transfer-Encoding"; - + const char IF_MODIFIED_SINCE[] = "If-Modified-Since"; + std::string GetHttpContent (std::istream& response); void MergeChunkedResponse (std::istream& response, std::ostream& merged); std::string urlDecode(const std::string& data);