diff --git a/daemon/I2PControl.cpp b/daemon/I2PControl.cpp index 9babce93..9f3a5778 100644 --- a/daemon/I2PControl.cpp +++ b/daemon/I2PControl.cpp @@ -16,6 +16,7 @@ #define BOOST_BIND_GLOBAL_PLACEHOLDERS #include +#include "Crypto.h" #include "FS.h" #include "Log.h" #include "Config.h" @@ -437,7 +438,7 @@ namespace client void I2PControlService::CreateCertificate (const char *crt_path, const char *key_path) { FILE *f = NULL; -#if (OPENSSL_VERSION_NUMBER >= 0x030000000) // since 3.0.0 + #if I2PD_OPENSSL_GE_3 // since 3.0.0 EVP_PKEY * pkey = EVP_RSA_gen(4096); // e = 65537 #else EVP_PKEY * pkey = EVP_PKEY_new (); diff --git a/daemon/UnixDaemon.cpp b/daemon/UnixDaemon.cpp index 0c182afe..f204beba 100644 --- a/daemon/UnixDaemon.cpp +++ b/daemon/UnixDaemon.cpp @@ -17,6 +17,11 @@ #include #include #include +#include +#if defined(__OpenBSD__) +#include +#include +#endif #include "Config.h" #include "FS.h" @@ -27,6 +32,114 @@ #include "Transports.h" #include "util.h" +#if defined(__OpenBSD__) +namespace +{ +std::string ParentDirectory(const std::string& path) +{ + if (path.empty()) + return ""; + auto pos = path.find_last_of('/'); + if (pos == std::string::npos) + return ""; + if (pos == 0) + return "/"; + return path.substr(0, pos); +} + +void AddRule(std::map& rules, const std::string& path, const char* perms) +{ + if (path.empty()) + return; + std::string normalized = path; + while (normalized.size() > 1 && normalized.back() == '/') + normalized.pop_back(); + auto it = rules.find(normalized); + if (it == rules.end()) + rules.emplace(std::move(normalized), std::string(perms)); + else + for (const char* p = perms; *p; ++p) + if (it->second.find(*p) == std::string::npos) + it->second.push_back(*p); +} +} + +static bool ConfigureOpenBSDSandbox(const std::string& pidfile, bool isDaemon) +{ + std::map rules; + const auto& dataDir = i2p::fs::GetDataDir(); + if (!dataDir.empty()) + AddRule(rules, dataDir, "rwc"); + const auto& certsDir = i2p::fs::GetCertsDir(); + if (!certsDir.empty()) + AddRule(rules, certsDir, "r"); + + AddRule(rules, "/etc", "r"); + AddRule(rules, "/dev/null", "rw"); + AddRule(rules, "/dev/urandom", "r"); + AddRule(rules, "/dev/log", "rw"); + + auto allowWritablePath = [&rules](const std::string& path) + { + if (path.empty() || path.front() != '/') + return; + auto parent = ParentDirectory(path); + if (parent.empty() || parent == "/") + AddRule(rules, path, "rwc"); + else + AddRule(rules, parent, "rwc"); + }; + + allowWritablePath(pidfile); + + std::string logsOption; + i2p::config::GetOption("log", logsOption); + bool logToFile = logsOption == "file"; + if (!logToFile && logsOption != "syslog") + { + if (isDaemon && (logsOption.empty() || logsOption == "stdout")) + logToFile = true; + } + + if (logToFile) + { + std::string logfile; + i2p::config::GetOption("logfile", logfile); + if (logfile.empty()) + logfile = i2p::fs::DataDirPath("i2pd.log"); + if (!logfile.empty()) + { + if (logfile.front() != '/') + logfile = i2p::fs::DataDirPath(logfile); + allowWritablePath(logfile); + } + } + + for (const auto& rule : rules) + { + if (unveil(rule.first.c_str(), rule.second.c_str()) == -1) + { + LogPrint(eLogError, "Daemon: unveil failed for ", rule.first, ": ", strerror(errno)); + return false; + } + } + + if (unveil(nullptr, nullptr) == -1) + { + LogPrint(eLogError, "Daemon: unveil lock failed: ", strerror(errno)); + return false; + } + + constexpr const char* promises = "stdio rpath wpath cpath inet dns proc fattr thread unix"; + if (pledge(promises, nullptr) == -1) + { + LogPrint(eLogError, "Daemon: pledge(", promises, ") failed: ", strerror(errno)); + return false; + } + return true; +} +#endif // __OpenBSD__ + void handle_signal(int sig) { switch (sig) @@ -152,6 +265,10 @@ namespace i2p if (pidfile == "") { pidfile = i2p::fs::DataDirPath("i2pd.pid"); } +#if defined(__OpenBSD__) + if (!ConfigureOpenBSDSandbox(pidfile, isDaemon)) + return false; +#endif if (pidfile != "") { pidFH = open(pidfile.c_str(), O_RDWR | O_CREAT, 0600); if (pidFH < 0) diff --git a/libi2pd/Crypto.cpp b/libi2pd/Crypto.cpp index dd43d045..27c673e7 100644 --- a/libi2pd/Crypto.cpp +++ b/libi2pd/Crypto.cpp @@ -11,18 +11,18 @@ #include #include #include +#include "Crypto.h" #include #include #include #include "TunnelBase.h" #include #include -#if (OPENSSL_VERSION_NUMBER >= 0x030000000) // since 3.0.0 +#if I2PD_OPENSSL_GE_3 // since 3.0.0 #include #include #endif #include "CPU.h" -#include "Crypto.h" #include "Ed25519.h" #include "I2PEndian.h" #include "Log.h" @@ -148,7 +148,7 @@ namespace crypto #define dsap GetCryptoConstants ().dsap #define dsaq GetCryptoConstants ().dsaq #define dsag GetCryptoConstants ().dsag -#if (OPENSSL_VERSION_NUMBER >= 0x030000000) // since 3.0.0 +#if I2PD_OPENSSL_GE_3 // since 3.0.0 EVP_PKEY * CreateDSA (BIGNUM * pubKey, BIGNUM * privKey) { EVP_PKEY * pkey = nullptr; diff --git a/libi2pd/Crypto.h b/libi2pd/Crypto.h index 3b9dfb93..b6646868 100644 --- a/libi2pd/Crypto.h +++ b/libi2pd/Crypto.h @@ -24,14 +24,22 @@ #include #include +#if defined(LIBRESSL_VERSION_NUMBER) +#define I2PD_OPENSSL_GE_3 0 +#define I2PD_OPENSSL_GE_3_5 0 +#else +#define I2PD_OPENSSL_GE_3 (OPENSSL_VERSION_NUMBER >= 0x030000000L) +#define I2PD_OPENSSL_GE_3_5 (OPENSSL_VERSION_NUMBER >= 0x030500000L) +#endif + #include "Base.h" #include "Tag.h" // recognize openssl version and features -#if (!defined(LIBRESSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER != 0x030000000)) // 3.0.0, regression in SipHash, not implemented in LibreSSL +#if (!defined(LIBRESSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER != 0x030000000L)) // 3.0.0, regression in SipHash, not implemented in LibreSSL # define OPENSSL_SIPHASH 1 #endif -#if (OPENSSL_VERSION_NUMBER >= 0x030500000) // 3.5.0 +#if I2PD_OPENSSL_GE_3_5 # define OPENSSL_PQ 1 #endif @@ -42,7 +50,7 @@ namespace crypto bool bn2buf (const BIGNUM * bn, uint8_t * buf, size_t len); // DSA -#if (OPENSSL_VERSION_NUMBER >= 0x030000000) // since 3.0.0 +#if I2PD_OPENSSL_GE_3 // since 3.0.0 EVP_PKEY * CreateDSA (BIGNUM * pubKey = nullptr, BIGNUM * privKey = nullptr); #else DSA * CreateDSA (); diff --git a/libi2pd/Family.cpp b/libi2pd/Family.cpp index 3a4e8890..c07ab238 100644 --- a/libi2pd/Family.cpp +++ b/libi2pd/Family.cpp @@ -52,7 +52,7 @@ namespace data if (pkey) { int curve = 0; -#if (OPENSSL_VERSION_NUMBER >= 0x030000000) // since 3.0.0 +#if I2PD_OPENSSL_GE_3 // since 3.0.0 char groupName[20]; if (EVP_PKEY_get_group_name(pkey, groupName, sizeof(groupName), NULL) == 1) curve = OBJ_txt2nid (groupName); @@ -157,7 +157,7 @@ namespace data SSL * ssl = SSL_new (ctx); EVP_PKEY * pkey = SSL_get_privatekey (ssl); int curve = 0; -#if (OPENSSL_VERSION_NUMBER >= 0x030000000) // since 3.0.0 +#if I2PD_OPENSSL_GE_3 // since 3.0.0 char groupName[20]; if (EVP_PKEY_get_group_name(pkey, groupName, sizeof(groupName), NULL) == 1) curve = OBJ_txt2nid (groupName); diff --git a/libi2pd/Reseed.cpp b/libi2pd/Reseed.cpp index 23dae8ff..ddcade3d 100644 --- a/libi2pd/Reseed.cpp +++ b/libi2pd/Reseed.cpp @@ -14,12 +14,12 @@ #include #include #include -#if (OPENSSL_VERSION_NUMBER >= 0x030000000) // since 3.0.0 +#include "Crypto.h" +#if I2PD_OPENSSL_GE_3 // since 3.0.0 #include #endif #include -#include "Crypto.h" #include "I2PEndian.h" #include "Reseed.h" #include "FS.h" @@ -485,7 +485,7 @@ namespace data // extract RSA key (we need n only, e = 65537) EVP_PKEY * pubKey = X509_get_pubkey (cert); const BIGNUM * n = nullptr; -#if (OPENSSL_VERSION_NUMBER >= 0x030000000) // since 3.0.0 +#if I2PD_OPENSSL_GE_3 // since 3.0.0 BIGNUM * n1 = BN_new (); if (EVP_PKEY_get_bn_param (pubKey, OSSL_PKEY_PARAM_RSA_N, &n1) > 0) n = n1; @@ -505,7 +505,7 @@ namespace data } else LogPrint (eLogError, "Reseed: Can't extract RSA key from ", filename); -#if (OPENSSL_VERSION_NUMBER >= 0x030000000) // since 3.0.0 +#if I2PD_OPENSSL_GE_3 // since 3.0.0 BN_free (n1); #endif } diff --git a/libi2pd/Signature.cpp b/libi2pd/Signature.cpp index cad7d484..96565a30 100644 --- a/libi2pd/Signature.cpp +++ b/libi2pd/Signature.cpp @@ -7,8 +7,9 @@ */ #include +#include "Crypto.h" #include -#if (OPENSSL_VERSION_NUMBER >= 0x030000000) // since 3.0.0 +#if I2PD_OPENSSL_GE_3 // since 3.0.0 #include #include #endif @@ -19,7 +20,7 @@ namespace i2p { namespace crypto { -#if (OPENSSL_VERSION_NUMBER >= 0x030000000) // since 3.0.0 +#if I2PD_OPENSSL_GE_3 // since 3.0.0 DSAVerifier::DSAVerifier (): m_PublicKey (nullptr) { @@ -172,7 +173,7 @@ namespace crypto } #endif -#if (OPENSSL_VERSION_NUMBER >= 0x030000000) // since 3.0.0 +#if I2PD_OPENSSL_GE_3 // since 3.0.0 ECDSAVerifier::ECDSAVerifier (int curve, size_t keyLen, const EVP_MD * hash): m_Curve(curve), m_KeyLen (keyLen), m_Hash (hash), m_PublicKey (nullptr) { @@ -405,7 +406,7 @@ namespace crypto LogPrint (eLogError, "EdDSA signing key is not set"); } -#if (OPENSSL_VERSION_NUMBER >= 0x030000000) +#if I2PD_OPENSSL_GE_3 static const OSSL_PARAM EDDSA25519phParams[] = { OSSL_PARAM_utf8_string ("instance", (char *)"Ed25519ph", 9), diff --git a/libi2pd/Signature.h b/libi2pd/Signature.h index 43f706bd..139a29ef 100644 --- a/libi2pd/Signature.h +++ b/libi2pd/Signature.h @@ -62,7 +62,7 @@ namespace crypto private: -#if (OPENSSL_VERSION_NUMBER >= 0x030000000) // since 3.0.0 +#if I2PD_OPENSSL_GE_3 // since 3.0.0 EVP_PKEY * m_PublicKey; #else DSA * m_PublicKey; @@ -82,7 +82,7 @@ namespace crypto private: -#if (OPENSSL_VERSION_NUMBER >= 0x030000000) // since 3.0.0 +#if I2PD_OPENSSL_GE_3 // since 3.0.0 EVP_PKEY * m_PrivateKey; #else DSA * m_PrivateKey; @@ -96,7 +96,7 @@ namespace crypto constexpr size_t ECDSAP384_KEY_LENGTH = 96; constexpr size_t ECDSAP521_KEY_LENGTH = 132; -#if (OPENSSL_VERSION_NUMBER >= 0x030000000) // since 3.0.0 +#if I2PD_OPENSSL_GE_3 // since 3.0.0 class ECDSAVerifier: public Verifier { public: @@ -377,7 +377,7 @@ namespace crypto EVP_PKEY * GetPkey () const { return m_Pkey; }; }; -#if (OPENSSL_VERSION_NUMBER >= 0x030000000) // since 3.0.0 +#if I2PD_OPENSSL_GE_3 // since 3.0.0 class EDDSA25519phVerifier: public EDDSA25519Verifier { public: @@ -423,7 +423,7 @@ namespace crypto EDDSA25519SignerCompat * m_Fallback; }; -#if (OPENSSL_VERSION_NUMBER >= 0x030000000) // since 3.0.0 +#if I2PD_OPENSSL_GE_3 // since 3.0.0 class EDDSA25519phSigner: public EDDSA25519Signer { public: