diff options
-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 | 4 |
4 files changed, 36 insertions, 9 deletions
diff --git a/src/httprpc.cpp b/src/httprpc.cpp index c72dbf10bc..66e0591c44 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> @@ -244,8 +247,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 fbf25a0341..6bbc0827bd 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -650,6 +650,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 b7acd62ee3..eae7c4ba18 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> @@ -82,7 +81,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]; @@ -96,7 +95,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; @@ -104,11 +103,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 a682c58d96..c7e723d962 100644 --- a/src/rpc/request.h +++ b/src/rpc/request.h @@ -7,9 +7,11 @@ #define BITCOIN_RPC_REQUEST_H #include <any> +#include <optional> #include <string> #include <univalue.h> +#include <util/fs.h> UniValue JSONRPCRequestObj(const std::string& strMethod, const UniValue& params, const UniValue& id); UniValue JSONRPCReplyObj(const UniValue& result, const UniValue& error, const UniValue& id); @@ -17,7 +19,7 @@ std::string JSONRPCReply(const UniValue& result, const UniValue& error, const Un 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 */ |