diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/httprpc.cpp | 19 | ||||
-rw-r--r-- | src/init.cpp | 1 | ||||
-rw-r--r-- | src/rpc/request.cpp | 21 | ||||
-rw-r--r-- | src/rpc/request.h | 3 | ||||
-rw-r--r-- | src/util/fs_helpers.cpp | 40 | ||||
-rw-r--r-- | src/util/fs_helpers.h | 14 |
6 files changed, 89 insertions, 9 deletions
diff --git a/src/httprpc.cpp b/src/httprpc.cpp index 128597157d..af809eaf38 100644 --- a/src/httprpc.cpp +++ b/src/httprpc.cpp @@ -11,6 +11,8 @@ #include <netaddress.h> #include <rpc/protocol.h> #include <rpc/server.h> +#include <util/fs.h> +#include <util/fs_helpers.h> #include <util/strencodings.h> #include <util/string.h> #include <walletinitinterface.h> @@ -19,6 +21,7 @@ #include <iterator> #include <map> #include <memory> +#include <optional> #include <set> #include <string> #include <vector> @@ -291,8 +294,20 @@ static bool InitRPCAuthentication() { if (gArgs.GetArg("-rpcpassword", "") == "") { - LogPrintf("Using random cookie authentication.\n"); - if (!GenerateAuthCookie(&strRPCUserColonPass)) { + LogInfo("Using random cookie authentication.\n"); + + std::optional<fs::perms> cookie_perms{std::nullopt}; + auto cookie_perms_arg{gArgs.GetArg("-rpccookieperms")}; + if (cookie_perms_arg) { + auto perm_opt = InterpretPermString(*cookie_perms_arg); + if (!perm_opt) { + LogInfo("Invalid -rpccookieperms=%s; must be one of 'owner', 'group', or 'all'.\n", *cookie_perms_arg); + return false; + } + cookie_perms = *perm_opt; + } + + if (!GenerateAuthCookie(&strRPCUserColonPass, cookie_perms)) { return false; } } else { diff --git a/src/init.cpp b/src/init.cpp index c6ef62372e..c9405153b4 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -659,6 +659,7 @@ void SetupServerArgs(ArgsManager& argsman) argsman.AddArg("-rpcbind=<addr>[:port]", "Bind to given address to listen for JSON-RPC connections. Do not expose the RPC server to untrusted networks such as the public internet! This option is ignored unless -rpcallowip is also passed. Port is optional and overrides -rpcport. Use [host]:port notation for IPv6. This option can be specified multiple times (default: 127.0.0.1 and ::1 i.e., localhost)", ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY, OptionsCategory::RPC); argsman.AddArg("-rpcdoccheck", strprintf("Throw a non-fatal error at runtime if the documentation for an RPC is incorrect (default: %u)", DEFAULT_RPC_DOC_CHECK), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::RPC); argsman.AddArg("-rpccookiefile=<loc>", "Location of the auth cookie. Relative paths will be prefixed by a net-specific datadir location. (default: data dir)", ArgsManager::ALLOW_ANY, OptionsCategory::RPC); + argsman.AddArg("-rpccookieperms=<readable-by>", strprintf("Set permissions on the RPC auth cookie file so that it is readable by [owner|group|all] (default: owner [via umask 0077])"), ArgsManager::ALLOW_ANY, OptionsCategory::RPC); argsman.AddArg("-rpcpassword=<pw>", "Password for JSON-RPC connections", ArgsManager::ALLOW_ANY | ArgsManager::SENSITIVE, OptionsCategory::RPC); argsman.AddArg("-rpcport=<port>", strprintf("Listen for JSON-RPC connections on <port> (default: %u, testnet: %u, signet: %u, regtest: %u)", defaultBaseParams->RPCPort(), testnetBaseParams->RPCPort(), signetBaseParams->RPCPort(), regtestBaseParams->RPCPort()), ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY, OptionsCategory::RPC); argsman.AddArg("-rpcservertimeout=<n>", strprintf("Timeout during HTTP requests (default: %d)", DEFAULT_HTTP_SERVER_TIMEOUT), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::RPC); diff --git a/src/rpc/request.cpp b/src/rpc/request.cpp index 87b9f18b33..083d1be44f 100644 --- a/src/rpc/request.cpp +++ b/src/rpc/request.cpp @@ -5,12 +5,11 @@ #include <rpc/request.h> -#include <util/fs.h> - #include <common/args.h> #include <logging.h> #include <random.h> #include <rpc/protocol.h> +#include <util/fs.h> #include <util/fs_helpers.h> #include <util/strencodings.h> @@ -95,7 +94,7 @@ static fs::path GetAuthCookieFile(bool temp=false) static bool g_generated_cookie = false; -bool GenerateAuthCookie(std::string *cookie_out) +bool GenerateAuthCookie(std::string* cookie_out, std::optional<fs::perms> cookie_perms) { const size_t COOKIE_SIZE = 32; unsigned char rand_pwd[COOKIE_SIZE]; @@ -109,7 +108,7 @@ bool GenerateAuthCookie(std::string *cookie_out) fs::path filepath_tmp = GetAuthCookieFile(true); file.open(filepath_tmp); if (!file.is_open()) { - LogPrintf("Unable to open cookie authentication file %s for writing\n", fs::PathToString(filepath_tmp)); + LogInfo("Unable to open cookie authentication file %s for writing\n", fs::PathToString(filepath_tmp)); return false; } file << cookie; @@ -117,11 +116,21 @@ bool GenerateAuthCookie(std::string *cookie_out) fs::path filepath = GetAuthCookieFile(false); if (!RenameOver(filepath_tmp, filepath)) { - LogPrintf("Unable to rename cookie authentication file %s to %s\n", fs::PathToString(filepath_tmp), fs::PathToString(filepath)); + LogInfo("Unable to rename cookie authentication file %s to %s\n", fs::PathToString(filepath_tmp), fs::PathToString(filepath)); return false; } + if (cookie_perms) { + std::error_code code; + fs::permissions(filepath, cookie_perms.value(), fs::perm_options::replace, code); + if (code) { + LogInfo("Unable to set permissions on cookie authentication file %s\n", fs::PathToString(filepath_tmp)); + return false; + } + } + g_generated_cookie = true; - LogPrintf("Generated RPC authentication cookie %s\n", fs::PathToString(filepath)); + LogInfo("Generated RPC authentication cookie %s\n", fs::PathToString(filepath)); + LogInfo("Permissions used for cookie: %s\n", PermsToSymbolicString(fs::status(filepath).permissions())); if (cookie_out) *cookie_out = cookie; diff --git a/src/rpc/request.h b/src/rpc/request.h index 9968426636..24887e8691 100644 --- a/src/rpc/request.h +++ b/src/rpc/request.h @@ -11,6 +11,7 @@ #include <string> #include <univalue.h> +#include <util/fs.h> enum class JSONRPCVersion { V1_LEGACY, @@ -23,7 +24,7 @@ UniValue JSONRPCReplyObj(UniValue result, UniValue error, std::optional<UniValue UniValue JSONRPCError(int code, const std::string& message); /** Generate a new RPC authentication cookie and write it to disk */ -bool GenerateAuthCookie(std::string *cookie_out); +bool GenerateAuthCookie(std::string* cookie_out, std::optional<fs::perms> cookie_perms=std::nullopt); /** Read the RPC authentication cookie from disk */ bool GetAuthCookie(std::string *cookie_out); /** Delete RPC authentication cookie from disk */ diff --git a/src/util/fs_helpers.cpp b/src/util/fs_helpers.cpp index 8952f20f79..41c8fe3b8f 100644 --- a/src/util/fs_helpers.cpp +++ b/src/util/fs_helpers.cpp @@ -16,6 +16,7 @@ #include <fstream> #include <map> #include <memory> +#include <optional> #include <string> #include <system_error> #include <utility> @@ -269,3 +270,42 @@ bool TryCreateDirectories(const fs::path& p) // create_directories didn't create the directory, it had to have existed already return false; } + +std::string PermsToSymbolicString(fs::perms p) +{ + std::string perm_str(9, '-'); + + auto set_perm = [&](size_t pos, fs::perms required_perm, char letter) { + if ((p & required_perm) != fs::perms::none) { + perm_str[pos] = letter; + } + }; + + set_perm(0, fs::perms::owner_read, 'r'); + set_perm(1, fs::perms::owner_write, 'w'); + set_perm(2, fs::perms::owner_exec, 'x'); + set_perm(3, fs::perms::group_read, 'r'); + set_perm(4, fs::perms::group_write, 'w'); + set_perm(5, fs::perms::group_exec, 'x'); + set_perm(6, fs::perms::others_read, 'r'); + set_perm(7, fs::perms::others_write, 'w'); + set_perm(8, fs::perms::others_exec, 'x'); + + return perm_str; +} + +std::optional<fs::perms> InterpretPermString(const std::string& s) +{ + if (s == "owner") { + return fs::perms::owner_read | fs::perms::owner_write; + } else if (s == "group") { + return fs::perms::owner_read | fs::perms::owner_write | + fs::perms::group_read; + } else if (s == "all") { + return fs::perms::owner_read | fs::perms::owner_write | + fs::perms::group_read | + fs::perms::others_read; + } else { + return std::nullopt; + } +} diff --git a/src/util/fs_helpers.h b/src/util/fs_helpers.h index ea3778eac3..28dd6d979d 100644 --- a/src/util/fs_helpers.h +++ b/src/util/fs_helpers.h @@ -12,6 +12,7 @@ #include <cstdio> #include <iosfwd> #include <limits> +#include <optional> /** * Ensure file contents are fully committed to disk, using a platform-specific @@ -62,6 +63,19 @@ void ReleaseDirectoryLocks(); bool TryCreateDirectories(const fs::path& p); fs::path GetDefaultDataDir(); +/** Convert fs::perms to symbolic string of the form 'rwxrwxrwx' + * + * @param[in] p the perms to be converted + * @return Symbolic permissions string + */ +std::string PermsToSymbolicString(fs::perms p); +/** Interpret a custom permissions level string as fs::perms + * + * @param[in] s Permission level string + * @return Permissions as fs::perms + */ +std::optional<fs::perms> InterpretPermString(const std::string& s); + #ifdef WIN32 fs::path GetSpecialFolderPath(int nFolder, bool fCreate = true); #endif |