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:
Wladimir J. van der Laan 2017-08-25 12:39:30 +02:00
parent 3f726c99f8
commit 82dd7195e1
2 changed files with 16 additions and 7 deletions

View file

@ -66,9 +66,14 @@ static const std::string COOKIEAUTH_USER = "__cookie__";
/** Default name for auth cookie file */
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;
return path;
}
@ -84,14 +89,20 @@ bool GenerateAuthCookie(std::string *cookie_out)
* these are set to 077 in init.cpp unless overridden with -sysperms.
*/
std::ofstream file;
fs::path filepath = GetAuthCookieFile();
file.open(filepath.string().c_str());
fs::path filepath_tmp = GetAuthCookieFile(true);
file.open(filepath_tmp.string().c_str());
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;
}
file << cookie;
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());
if (cookie_out)

View file

@ -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);
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 */
bool GenerateAuthCookie(std::string *cookie_out);
/** Read the RPC authentication cookie from disk */