From 5b3e4db7f164da107b275639f621571467d5a64a Mon Sep 17 00:00:00 2001 From: acetone <63557806+freeacetone@users.noreply.github.com> Date: Wed, 23 Sep 2026 10:48:32 -0400 Subject: [PATCH] create key files readable by owner only --- daemon/I2PControl.cpp | 1 + libi2pd/Destination.cpp | 2 +- libi2pd/FS.cpp | 11 +++++++++++ libi2pd/FS.h | 2 ++ libi2pd/Garlic.cpp | 2 +- libi2pd/RouterContext.cpp | 6 +++--- libi2pd_client/ClientContext.cpp | 2 +- 7 files changed, 20 insertions(+), 6 deletions(-) diff --git a/daemon/I2PControl.cpp b/daemon/I2PControl.cpp index a1bc9594..62bef5b7 100644 --- a/daemon/I2PControl.cpp +++ b/daemon/I2PControl.cpp @@ -527,6 +527,7 @@ namespace client X509_free (x509); // save key + i2p::fs::CreatePrivateFile (key_path); if ((f = fopen (key_path, "wb")) != NULL) { LogPrint (eLogInfo, "I2PControl: saving cert key to ", key_path); diff --git a/libi2pd/Destination.cpp b/libi2pd/Destination.cpp index 3af6fdd6..4e900031 100644 --- a/libi2pd/Destination.cpp +++ b/libi2pd/Destination.cpp @@ -1549,7 +1549,7 @@ namespace client memset (keys->pub.data (), 0, keys->pub.size ()); keys->GenerateKeys (); - std::ofstream f1 (path, std::ofstream::binary | std::ofstream::out); + std::ofstream f1 (i2p::fs::CreatePrivateFile (path), std::ofstream::binary | std::ofstream::out); if (f1) { f1.write ((char *)keys->pub.data (), keys->pub.size ()); diff --git a/libi2pd/FS.cpp b/libi2pd/FS.cpp index aa6d5b04..f0b69123 100644 --- a/libi2pd/FS.cpp +++ b/libi2pd/FS.cpp @@ -302,6 +302,17 @@ namespace fs { return fs_lib::create_directory(path); } + std::filesystem::path CreatePrivateFile (const std::filesystem::path& path) + { + std::ofstream f (path, std::ofstream::out | std::ofstream::app); + std::error_code ec; + std::filesystem::permissions (path, std::filesystem::perms::owner_read | std::filesystem::perms::owner_write, + std::filesystem::perm_options::replace, ec); + if (ec) + LogPrint (eLogWarning, "FS: Can't restrict access to ", path.string (), ": ", ec.message ()); + return path; + } + void HashedStorage::SetPlace(const std::string &path) { root = path + i2p::fs::dirSep + name; } diff --git a/libi2pd/FS.h b/libi2pd/FS.h index ec197692..4de6992b 100644 --- a/libi2pd/FS.h +++ b/libi2pd/FS.h @@ -14,6 +14,7 @@ #include #include #include +#include #include #ifndef STD_FILESYSTEM @@ -151,6 +152,7 @@ namespace fs { uint32_t GetLastUpdateTime (const std::string & path); // seconds since epoch bool CreateDirectory (const std::string& path); + std::filesystem::path CreatePrivateFile (const std::filesystem::path& path); template void _ExpandPath(std::stringstream & path, T c) { diff --git a/libi2pd/Garlic.cpp b/libi2pd/Garlic.cpp index 0953647d..2039b2a9 100644 --- a/libi2pd/Garlic.cpp +++ b/libi2pd/Garlic.cpp @@ -955,7 +955,7 @@ namespace garlic if (m_Tags.empty ()) return; std::string ident = GetIdentHash().ToBase32(); std::string path = i2p::fs::DataDirPath("tags", (ident + ".tags")); - std::ofstream f (path, std::ofstream::binary | std::ofstream::out | std::ofstream::trunc); + std::ofstream f (i2p::fs::CreatePrivateFile (path), std::ofstream::binary | std::ofstream::out | std::ofstream::trunc); uint32_t ts = i2p::util::GetSecondsSinceEpoch (); // 4 bytes timestamp, 32 bytes tag, 32 bytes key for (auto it: m_Tags) diff --git a/libi2pd/RouterContext.cpp b/libi2pd/RouterContext.cpp index ba5357f5..140601ed 100644 --- a/libi2pd/RouterContext.cpp +++ b/libi2pd/RouterContext.cpp @@ -309,7 +309,7 @@ namespace i2p memcpy (m_NTCP2Keys->staticPublicKey, m_NTCP2StaticKeys->GetPublicKey (), 32); RAND_bytes (m_NTCP2Keys->iv, 16); // save - std::ofstream fk (i2p::fs::DataDirPath (NTCP2_KEYS), std::ofstream::binary | std::ofstream::out); + std::ofstream fk (i2p::fs::CreatePrivateFile (i2p::fs::DataDirPath (NTCP2_KEYS)), std::ofstream::binary | std::ofstream::out); fk.write ((char *)m_NTCP2Keys.get (), sizeof (NTCP2PrivateKeys)); } @@ -322,7 +322,7 @@ namespace i2p memcpy (m_SSU2Keys->staticPublicKey, m_SSU2StaticKeys->GetPublicKey (), 32); RAND_bytes (m_SSU2Keys->intro, 32); // save - std::ofstream fk (i2p::fs::DataDirPath (SSU2_KEYS), std::ofstream::binary | std::ofstream::out); + std::ofstream fk (i2p::fs::CreatePrivateFile (i2p::fs::DataDirPath (SSU2_KEYS)), std::ofstream::binary | std::ofstream::out); fk.write ((char *)m_SSU2Keys.get (), sizeof (SSU2PrivateKeys)); } @@ -1246,7 +1246,7 @@ namespace i2p void RouterContext::SaveKeys () { // save in the same format as .dat files - std::ofstream fk (i2p::fs::DataDirPath (ROUTER_KEYS), std::ofstream::binary | std::ofstream::out); + std::ofstream fk (i2p::fs::CreatePrivateFile (i2p::fs::DataDirPath (ROUTER_KEYS)), std::ofstream::binary | std::ofstream::out); size_t len = m_Keys.GetFullLen (); uint8_t * buf = new uint8_t[len]; m_Keys.ToBuffer (buf, len); diff --git a/libi2pd_client/ClientContext.cpp b/libi2pd_client/ClientContext.cpp index 86a0580a..6d89c0a3 100644 --- a/libi2pd_client/ClientContext.cpp +++ b/libi2pd_client/ClientContext.cpp @@ -323,7 +323,7 @@ namespace client { LogPrint (eLogInfo, "Clients: Can't open file ", fullPath, " Creating new one with signature type ", sigType, " crypto type ", cryptoType); keys = i2p::data::PrivateKeys::CreateRandomKeys (sigType, cryptoType, true); - std::ofstream f (fullPath, std::ofstream::binary | std::ofstream::out); + std::ofstream f (i2p::fs::CreatePrivateFile (fullPath), std::ofstream::binary | std::ofstream::out); size_t len = keys.GetFullLen (); uint8_t * buf = new uint8_t[len]; len = keys.ToBuffer (buf, len);