Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
180 changes: 102 additions & 78 deletions daemon/Daemon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@
#include <thread>
#include <memory>
#include <regex>
#include <array>
#include <utility>
#include <fstream>
#include <sstream>

#ifdef __OpenBSD__
# include<unistd.h>
Expand Down Expand Up @@ -39,6 +43,12 @@
#include "Timestamp.h"
#include "I18N.h"

#ifdef __OpenBSD__
#include <unistd.h>
#include <errno.h>
#include <cstring>
#endif

namespace i2p
{
namespace util
Expand Down Expand Up @@ -107,84 +117,6 @@ namespace util
i2p::config::ParseConfig(config);
i2p::config::Finalize();

#ifdef __OpenBSD__
auto init_pledge = []() {
std::string pledge_file; i2p::config::GetOption("openbsd.pledge_file", pledge_file);
if (pledge_file == "")
{
LogPrint(eLogDebug, "Use default pledge values");
// TODO: remove that not need
pledge("stdio rpath wpath cpath inet dns unix recvfd sendfd proc error mcast chown flock",nullptr);
} else {
std::ifstream f(pledge_file);
if(!f) {
std::cerr << "Can't open pledge file " << pledge_file<<std::endl;
exit(1);
}
std::string line;
std::vector<std::string> rules;
while(std::getline(f, line)){
rules.push_back(line);
}
if(f.bad()) {
std::cerr << "IO error with pledge file" << std::endl;
}
std::ostringstream out;
for(auto r : rules)
out << r << " ";
pledge(out.str().c_str(), nullptr);
}


};
auto init_unevil = []() {
unveil("/usr/lib", "r");
unveil("/usr/local/lib", "r");
unveil("/usr/libexec/ld.so", "r");
unveil("/dev/urandom", "r");
unveil("/tmp", "rw");
unveil("/etc/i2pd", "r"); // ваще не нужно вроде на весь прям каталог

#define UNVEIL_DIR(dir) unveil(dir.c_str(), "rwc")

std::string unevil_file; i2p::config::GetOption("openbsd.unevil_file",unevil_file);
UNVEIL_DIR(unevil_file);
std::string tunnelsdir, certsdir, logfile, datadir, reseed_file, openbsd_pledge_file;
i2p::config::GetOption("tunnelsdir", tunnelsdir);
UNVEIL_DIR(tunnelsdir);
i2p::config::GetOption("certsdir", certsdir);
UNVEIL_DIR(certsdir);
i2p::config::GetOption("datadir", datadir);
UNVEIL_DIR(datadir);
i2p::config::GetOption("reseed.file", reseed_file);
unveil(reseed_file.c_str(), "r");
i2p::config::GetOption("openbsd.pledge_file", openbsd_pledge_file);
unveil(openbsd_pledge_file.c_str(), "r");
std::string tunconf ;i2p::config::GetOption("tunconf", tunconf); unveil(tunconf.c_str(), "r");
std::string conf ;i2p::config::GetOption("tunconf", conf); unveil(conf.c_str(), "r");
std::string pidfile ;i2p::config::GetOption("pidfile", pidfile); unveil(pidfile.c_str(), "rwc");
i2p::config::GetOption("logfile", logfile); unveil(logfile.c_str(), "rwc");
if(unevil_file != "")
{
std::ifstream f(unevil_file);
if (!f) {
std::cerr << "Can't open unevil file" << std::endl;
exit(1);
}
std::string line;
while(std::getline(f, line)){
UNVEIL_DIR(line);
}
}
#undef UNVEIL_DIR
unveil(NULL, NULL);
};
bool openbsd_unevil_enabled; i2p::config::GetOption("openbsd.unevil_enabled", openbsd_unevil_enabled);
bool openbsd_pledge_enabled; i2p::config::GetOption("openbsd.pledge_enabled", openbsd_pledge_enabled);
if(openbsd_unevil_enabled) init_unevil();
if(openbsd_pledge_enabled) init_pledge();
#endif

i2p::config::GetOption("daemon", isDaemon);

std::string certsdir; i2p::config::GetOption("certsdir", certsdir);
Expand Down Expand Up @@ -395,6 +327,98 @@ namespace util
std::string httpLang; i2p::config::GetOption("http.lang", httpLang);
i2p::i18n::SetLanguage(httpLang);

#ifdef __OpenBSD__
auto unveilPath = [] (const std::string& path, const char * mask)
{
if (!path.empty ())
{
if (unveil (path.c_str (), mask) == -1)
LogPrint (eLogError, "Daemon: unveil failed for ", path, ": ", std::strerror (errno));
}
};

std::string tunconf; i2p::config::GetOption ("tunconf", tunconf);
if (tunconf.empty ()) tunconf = i2p::fs::DataDirPath ("tunnels.conf");
std::string tunnelsdir; i2p::config::GetOption ("tunnelsdir", tunnelsdir);
if (tunnelsdir.empty ()) tunnelsdir = i2p::fs::DataDirPath ("tunnels.d");
std::string pidfile; i2p::config::GetOption ("pidfile", pidfile);
if (pidfile.empty ()) pidfile = i2p::fs::DataDirPath ("i2pd.pid");
std::string reseedFile; i2p::config::GetOption ("reseed.file", reseedFile);
std::string reseedZipFile; i2p::config::GetOption ("reseed.zipfile", reseedZipFile);
std::string openbsdUnveilFile, openbsdUnevilFile, openbsdPledgeFile;
bool openbsdUnveilEnabled = true, openbsdPledgeEnabled = true;
i2p::config::GetOption ("openbsd.unveil_file", openbsdUnveilFile);
i2p::config::GetOption ("openbsd.unevil_file", openbsdUnevilFile); // backward-compatible typo
i2p::config::GetOption ("openbsd.unveil_enabled", openbsdUnveilEnabled);
i2p::config::GetOption ("openbsd.unevil_enabled", openbsdUnveilEnabled); // backward-compatible typo
i2p::config::GetOption ("openbsd.pledge_file", openbsdPledgeFile);
i2p::config::GetOption ("openbsd.pledge_enabled", openbsdPledgeEnabled);
if (openbsdUnveilFile.empty ()) openbsdUnveilFile = openbsdUnevilFile;

// local reseed file only; URLs are network inputs and don't need unveil
if (reseedFile.rfind ("https://", 0) == 0) reseedFile.clear ();

// limit filesystem access to runtime paths determined from effective config/defaults
const std::array<std::pair<std::string, const char *>, 9> unveilRules =
{{
{config, "r"},
{datadir, "rwc"},
{certsdir, "r"},
{tunconf, "r"},
{tunnelsdir, "r"},
{pidfile, "rwc"},
{logfile, "rwc"},
{reseedFile, "r"},
{reseedZipFile, "r"}
}};
if (openbsdUnveilEnabled)
{
for (const auto& rule: unveilRules)
unveilPath (rule.first, rule.second);
if (!openbsdUnveilFile.empty ())
{
std::ifstream extraRules (openbsdUnveilFile);
if (!extraRules)
LogPrint (eLogError, "Daemon: can't open OpenBSD unveil file ", openbsdUnveilFile);
else
{
std::string line;
while (std::getline (extraRules, line))
unveilPath (line, "rwc");
}
}

if (unveil (nullptr, nullptr) == -1)
{
LogPrint (eLogError, "Daemon: unveil lock failed: ", std::strerror (errno));
return false;
}
}
std::string pledgePromises = "stdio inet dns flock rpath wpath cpath";
if (openbsdPledgeEnabled && !openbsdPledgeFile.empty ())
{
std::ifstream promisesFile (openbsdPledgeFile);
if (!promisesFile)
LogPrint (eLogError, "Daemon: can't open OpenBSD pledge file ", openbsdPledgeFile);
else
{
std::ostringstream out;
std::string line;
while (std::getline (promisesFile, line))
{
if (!line.empty ()) out << line << ' ';
}
auto customPromises = out.str ();
if (!customPromises.empty ()) pledgePromises = customPromises;
}
}
if (openbsdPledgeEnabled && pledge (pledgePromises.c_str (), nullptr) == -1)
{
LogPrint (eLogError, "Daemon: pledge failed: ", std::strerror (errno));
return false;
}
#endif

return true;
}

Expand Down
19 changes: 11 additions & 8 deletions libi2pd/Config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ namespace config {
("httpproxy.addresshelper", value<bool>()->default_value(true), "Enable or disable addresshelper")
("httpproxy.senduseragent", value<bool>()->default_value(false), "Pass through user's User-Agent if enabled. Disabled by default")
("httpproxy.i2cp.leaseSetType", value<std::string>()->default_value("3"), "Local destination's LeaseSet type")
#if OPENSSL_PQ
#if OPENSSL_MLKEM
("httpproxy.i2cp.leaseSetEncType", value<std::string>()->default_value("6,4,0"), "Local destination's LeaseSet encryption type")
#else
("httpproxy.i2cp.leaseSetEncType", value<std::string>()->default_value("4,0"), "Local destination's LeaseSet encryption type")
Expand Down Expand Up @@ -170,7 +170,7 @@ namespace config {
("socksproxy.outproxy", value<std::string>()->default_value("127.0.0.1"), "Upstream outproxy address for SOCKS Proxy")
("socksproxy.outproxyport", value<uint16_t>()->default_value(9050), "Upstream outproxy port for SOCKS Proxy")
("socksproxy.i2cp.leaseSetType", value<std::string>()->default_value("3"), "Local destination's LeaseSet type")
#if OPENSSL_PQ
#if OPENSSL_MLKEM
("socksproxy.i2cp.leaseSetEncType", value<std::string>()->default_value("6,4,0"), "Local destination's LeaseSet encryption type")
#else
("socksproxy.i2cp.leaseSetEncType", value<std::string>()->default_value("4,0"), "Local destination's LeaseSet encryption type")
Expand All @@ -191,7 +191,7 @@ namespace config {
("shareddest.inbound.quantity", value<std::string>()->default_value("3"), "Shared local destination inbound tunnels quantity")
("shareddest.outbound.quantity", value<std::string>()->default_value("3"), "Shared local destination outbound tunnels quantity")
("shareddest.i2cp.leaseSetType", value<std::string>()->default_value("3"), "Shared local destination's LeaseSet type")
#if OPENSSL_PQ
#if OPENSSL_MLKEM
("shareddest.i2cp.leaseSetEncType", value<std::string>()->default_value("6,4,0"), "Shared local destination's LeaseSet encryption type")
#else
("shareddest.i2cp.leaseSetEncType", value<std::string>()->default_value("4,0"), "Shared local destination's LeaseSet encryption type")
Expand Down Expand Up @@ -331,7 +331,7 @@ namespace config {
("ntcp2.port", value<uint16_t>()->default_value(0), "Port to listen for incoming NTCP2 connections (default: auto)")
("ntcp2.addressv6", value<std::string>()->default_value("::"), "Address to publish NTCP2 with")
("ntcp2.proxy", value<std::string>()->default_value(""), "Proxy URL for NTCP2 transport")
#if OPENSSL_PQ
#if OPENSSL_MLKEM
("ntcp2.version", value<int>()->default_value(4), "Protocol version. 2 - standard, 3,4,5 - post quantum (default: 4)")
#else
("ntcp2.version", value<int>()->default_value(2), "Protocol version. 2 - standard, 3,4,5 - post quantum (default: 2)")
Expand Down Expand Up @@ -394,10 +394,13 @@ namespace config {
#ifdef __OpenBSD__
options_description openbsd_specific("OpenBSD specific options");
openbsd_specific.add_options()
("openbsd.pledge_file", value<std::string>()->default_value(""), "OpenbSD file with pledge rules")
("openbsd.unevil_file", value<std::string>()->default_value(""), "OpenBSD file with unevil rules")
("openbsd.unevil_enabled", value<bool>()->default_value(true), "use unevil rues")
("openbsd.pledge_enabled", value<bool>()->default_value(true), "use pledge rules")
("openbsd.pledge_file", value<std::string>()->default_value(""), "OpenBSD file with custom pledge promises")
("openbsd.unveil_file", value<std::string>()->default_value(""), "OpenBSD file with extra unveil paths")
("openbsd.unveil_enabled", value<bool>()->default_value(true), "Enable unveil hardening (default: enabled)")
("openbsd.pledge_enabled", value<bool>()->default_value(true), "Enable pledge hardening (default: enabled)")
// deprecated misspelled options kept for backward compatibility
("openbsd.unevil_file", value<std::string>()->default_value(""), "Deprecated alias for openbsd.unveil_file")
("openbsd.unevil_enabled", value<bool>()->default_value(true), "Deprecated alias for openbsd.unveil_enabled")
;
#endif

Expand Down
10 changes: 9 additions & 1 deletion libi2pd/Crypto.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,18 @@
#if (!defined(LIBRESSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER != 0x030000000)) // 3.0.0, regression in SipHash, not implemented in LibreSSL
# define OPENSSL_SIPHASH 1
#endif
#if (OPENSSL_VERSION_NUMBER >= 0x030500000) || ( (defined(LIBRESSL_VERSION_NUMBER) && (LIBRESSL_VERSION_NUMBER >= 0x4030000fL)) ) // 3.5.0 openssl, 4.3.0 libressl
#if !defined(LIBRESSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER >= 0x030500000) // 3.5.0
# define OPENSSL_PQ 1
#endif

#if defined(OPENSSL_PQ) || defined(USE_LIBOQS_MLDSA)
# define OPENSSL_MLDSA 1
#endif

#if defined(OPENSSL_PQ) || (defined(LIBRESSL_VERSION_NUMBER) && (LIBRESSL_VERSION_NUMBER >= 0x4030000fL))
# define OPENSSL_MLKEM 1
#endif

namespace i2p
{
namespace crypto
Expand Down
6 changes: 3 additions & 3 deletions libi2pd/Destination.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -999,7 +999,7 @@ namespace client
try
{
i2p::data::CryptoKeyType cryptoType = std::stoi(it1);
#if !OPENSSL_PQ
#if !OPENSSL_MLKEM
if (cryptoType <= i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD) // skip PQ keys if not supported
#endif
{
Expand All @@ -1020,11 +1020,11 @@ namespace client
if (encryptionKeyTypes.empty ())
{
encryptionKeyTypes.insert ( { GetIdentity ()->GetCryptoKeyType (),
#if OPENSSL_PQ
#if OPENSSL_MLKEM
i2p::data::CRYPTO_KEY_TYPE_ECIES_MLKEM768_X25519_AEAD,
#endif
i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD });
#if OPENSSL_PQ
#if OPENSSL_MLKEM
m_PreferredCryptoType = i2p::data::CRYPTO_KEY_TYPE_ECIES_MLKEM768_X25519_AEAD;
#else
m_PreferredCryptoType = i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD;
Expand Down
Loading