rpc: Write authcookie atomically
Use POSIX rename atomicity at the `bitcoind` side to create a working cookie atomically: - Write `.cookie.tmp`, close file - Rename `.cookie.tmp` to `.cookie` This avoids clients reading invalid/partial cookies as in #11129.
This commit is contained in:
parent
3f726c99f8
commit
82dd7195e1
2 changed files with 16 additions and 7 deletions
|
@ -66,9 +66,14 @@ static const std::string COOKIEAUTH_USER = "__cookie__";
|
||||||
/** Default name for auth cookie file */
|
/** Default name for auth cookie file */
|
||||||
static const std::string COOKIEAUTH_FILE = ".cookie";
|
static const std::string COOKIEAUTH_FILE = ".cookie";
|
||||||
|
|
||||||
fs::path GetAuthCookieFile()
|
/** Get name of RPC authentication cookie file */
|
||||||
|
static fs::path GetAuthCookieFile(bool temp=false)
|
||||||
{
|
{
|
||||||
fs::path path(gArgs.GetArg("-rpccookiefile", COOKIEAUTH_FILE));
|
std::string arg = gArgs.GetArg("-rpccookiefile", COOKIEAUTH_FILE);
|
||||||
|
if (temp) {
|
||||||
|
arg += ".tmp";
|
||||||
|
}
|
||||||
|
fs::path path(arg);
|
||||||
if (!path.is_complete()) path = GetDataDir() / path;
|
if (!path.is_complete()) path = GetDataDir() / path;
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
@ -84,14 +89,20 @@ bool GenerateAuthCookie(std::string *cookie_out)
|
||||||
* these are set to 077 in init.cpp unless overridden with -sysperms.
|
* these are set to 077 in init.cpp unless overridden with -sysperms.
|
||||||
*/
|
*/
|
||||||
std::ofstream file;
|
std::ofstream file;
|
||||||
fs::path filepath = GetAuthCookieFile();
|
fs::path filepath_tmp = GetAuthCookieFile(true);
|
||||||
file.open(filepath.string().c_str());
|
file.open(filepath_tmp.string().c_str());
|
||||||
if (!file.is_open()) {
|
if (!file.is_open()) {
|
||||||
LogPrintf("Unable to open cookie authentication file %s for writing\n", filepath.string());
|
LogPrintf("Unable to open cookie authentication file %s for writing\n", filepath_tmp.string());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
file << cookie;
|
file << cookie;
|
||||||
file.close();
|
file.close();
|
||||||
|
|
||||||
|
fs::path filepath = GetAuthCookieFile(false);
|
||||||
|
if (!RenameOver(filepath_tmp, filepath)) {
|
||||||
|
LogPrintf("Unable to rename cookie authentication file %s to %s\n", filepath_tmp.string(), filepath.string());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
LogPrintf("Generated RPC authentication cookie %s\n", filepath.string());
|
LogPrintf("Generated RPC authentication cookie %s\n", filepath.string());
|
||||||
|
|
||||||
if (cookie_out)
|
if (cookie_out)
|
||||||
|
|
|
@ -91,8 +91,6 @@ UniValue JSONRPCReplyObj(const UniValue& result, const UniValue& error, const Un
|
||||||
std::string JSONRPCReply(const UniValue& result, const UniValue& error, const UniValue& id);
|
std::string JSONRPCReply(const UniValue& result, const UniValue& error, const UniValue& id);
|
||||||
UniValue JSONRPCError(int code, const std::string& message);
|
UniValue JSONRPCError(int code, const std::string& message);
|
||||||
|
|
||||||
/** Get name of RPC authentication cookie file */
|
|
||||||
fs::path GetAuthCookieFile();
|
|
||||||
/** Generate a new RPC authentication cookie and write it to disk */
|
/** Generate a new RPC authentication cookie and write it to disk */
|
||||||
bool GenerateAuthCookie(std::string *cookie_out);
|
bool GenerateAuthCookie(std::string *cookie_out);
|
||||||
/** Read the RPC authentication cookie from disk */
|
/** Read the RPC authentication cookie from disk */
|
||||||
|
|
Loading…
Reference in a new issue