diff --git a/src/config.h b/src/config.h --- a/src/config.h +++ b/src/config.h @@ -32,6 +32,11 @@ virtual void SetMinFeePerKB(CFeeRate amt) = 0; virtual CFeeRate GetMinFeePerKB() const = 0; + + virtual void SetRPCUserAndPassword(std::string userAndPassword) = 0; + virtual std::string GetRPCUserAndPassword() const = 0; + virtual void SetRPCCORSDomain(std::string corsDomain) = 0; + virtual std::string GetRPCCORSDomain() const = 0; }; class GlobalConfig final : public Config { @@ -51,6 +56,11 @@ void SetMinFeePerKB(CFeeRate amt) override; CFeeRate GetMinFeePerKB() const override; + void SetRPCUserAndPassword(std::string userAndPassword) override; + std::string GetRPCUserAndPassword() const override; + void SetRPCCORSDomain(std::string corsDomain) override; + std::string GetRPCCORSDomain() const override; + private: bool useCashAddr; Amount excessUTXOCharge; @@ -83,6 +93,11 @@ return CFeeRate(Amount::zero()); } + void SetRPCUserAndPassword(std::string userAndPassword) override{}; + std::string GetRPCUserAndPassword() const override { return ""; }; + void SetRPCCORSDomain(std::string corsDomain) override{}; + std::string GetRPCCORSDomain() const override { return ""; }; + private: std::unique_ptr chainParams; }; diff --git a/src/config.cpp b/src/config.cpp --- a/src/config.cpp +++ b/src/config.cpp @@ -79,3 +79,19 @@ CFeeRate GlobalConfig::GetMinFeePerKB() const { return feePerKB; } + +void GlobalConfig::SetRPCUserAndPassword(std::string userAndPassword) { + rpcUserAndPassword = userAndPassword; +} + +std::string GlobalConfig::GetRPCUserAndPassword() const { + return rpcUserAndPassword; +} + +void GlobalConfig::SetRPCCORSDomain(std::string corsDomain) { + rpcCORSDomain = corsDomain; +} + +std::string GlobalConfig::GetRPCCORSDomain() const { + return rpcCORSDomain; +} diff --git a/src/globals.h b/src/globals.h --- a/src/globals.h +++ b/src/globals.h @@ -6,9 +6,18 @@ #define BITCOIN_GLOBALS_H #include +#include /** The largest block size this node will accept. */ extern uint64_t nMaxBlockSize; extern uint64_t nBlockPriorityPercentage; +/** RPC authentication configs */ + +// Pre-base64-encoded authentication token, with user and password separated +// by a colon. +extern std::string rpcUserAndPassword; +// CORS domain, the allowed Origin +extern std::string rpcCORSDomain; + #endif // BITCOIN_GLOBALS_H diff --git a/src/globals.cpp b/src/globals.cpp --- a/src/globals.cpp +++ b/src/globals.cpp @@ -9,3 +9,6 @@ uint64_t nMaxBlockSize = DEFAULT_MAX_BLOCK_SIZE; uint64_t nBlockPriorityPercentage = DEFAULT_BLOCK_PRIORITY_PERCENTAGE; + +std::string rpcUserAndPassword; +std::string rpcCORSDomain; diff --git a/src/httprpc.h b/src/httprpc.h --- a/src/httprpc.h +++ b/src/httprpc.h @@ -8,12 +8,13 @@ #include #include +class Config; class HTTPRequest; /** Start HTTP RPC subsystem. * Precondition; HTTP and RPC has been started. */ -bool StartHTTPRPC(); +bool StartHTTPRPC(Config &config); /** Interrupt HTTP RPC subsystem. */ void InterruptHTTPRPC(); diff --git a/src/httprpc.cpp b/src/httprpc.cpp --- a/src/httprpc.cpp +++ b/src/httprpc.cpp @@ -55,12 +55,8 @@ struct event_base *base; }; -/* Pre-base64-encoded authentication token */ -static std::string strRPCUserColonPass; /* Stored RPC timer interface (for unregistration) */ static HTTPRPCTimerInterface *httpRPCTimerInterface = 0; -/* RPC CORS Domain, allowed Origin */ -static std::string strRPCCORSDomain; static void JSONErrorReply(HTTPRequest *req, const UniValue &objError, const UniValue &id) { @@ -125,10 +121,10 @@ return false; } -static bool RPCAuthorized(const std::string &strAuth, +static bool RPCAuthorized(Config &config, const std::string &strAuth, std::string &strAuthUsernameOut) { // Belt-and-suspenders measure if InitRPCAuthentication was not called. - if (strRPCUserColonPass.empty()) { + if (config.GetRPCUserAndPassword().empty()) { return false; } @@ -145,13 +141,13 @@ } // Check if authorized under single-user field - if (TimingResistantEqual(strUserPass, strRPCUserColonPass)) { + if (TimingResistantEqual(strUserPass, config.GetRPCUserAndPassword())) { return true; } return multiUserAuthorized(strUserPass); } -static bool checkCORS(HTTPRequest *req) { +static bool checkCORS(Config &config, HTTPRequest *req) { // https://www.w3.org/TR/cors/#resource-requests // 1. If the Origin header is not present terminate this set of steps. @@ -166,7 +162,7 @@ // and terminate this set of steps. // Note: Always matching is acceptable since the list of origins can be // unbounded. - if (origin.second != strRPCCORSDomain) { + if (origin.second != config.GetRPCCORSDomain()) { return false; } @@ -275,7 +271,7 @@ static bool HTTPReq_JSONRPC(Config &config, HTTPRequest *req, const std::string &) { // First, check and/or set CORS headers - if (checkCORS(req)) { + if (checkCORS(config, req)) { return true; } @@ -294,7 +290,7 @@ } JSONRPCRequest jreq; - if (!RPCAuthorized(authHeader.second, jreq.authUser)) { + if (!RPCAuthorized(config, authHeader.second, jreq.authUser)) { LogPrintf("ThreadRPCServer incorrect password attempt from %s\n", req->GetPeer().ToString()); @@ -345,10 +341,11 @@ return true; } -static bool InitRPCAuthentication() { +static bool InitRPCAuthentication(Config &config) { if (gArgs.GetArg("-rpcpassword", "") == "") { LogPrintf("No rpcpassword set - using random cookie authentication\n"); - if (!GenerateAuthCookie(&strRPCUserColonPass)) { + std::string generatedUserAndPassword; + if (!GenerateAuthCookie(&generatedUserAndPassword)) { // Same message as AbortNode. uiInterface.ThreadSafeMessageBox( _("Error: A fatal internal error occurred, see debug.log for " @@ -356,22 +353,23 @@ "", CClientUIInterface::MSG_ERROR); return false; } + config.SetRPCUserAndPassword(generatedUserAndPassword); } else { LogPrintf("Config options rpcuser and rpcpassword will soon be " "deprecated. Locally-run instances may remove rpcuser to use " "cookie-based auth, or may be replaced with rpcauth. Please " "see share/rpcuser for rpcauth auth generation.\n"); - strRPCUserColonPass = gArgs.GetArg("-rpcuser", "") + ":" + - gArgs.GetArg("-rpcpassword", ""); + config.SetRPCUserAndPassword(gArgs.GetArg("-rpcuser", "") + ":" + + gArgs.GetArg("-rpcpassword", "")); } - strRPCCORSDomain = gArgs.GetArg("-rpccorsdomain", ""); + config.SetRPCCORSDomain(gArgs.GetArg("-rpccorsdomain", "")); return true; } -bool StartHTTPRPC() { +bool StartHTTPRPC(Config &config) { LogPrint(BCLog::RPC, "Starting HTTP RPC server\n"); - if (!InitRPCAuthentication()) return false; + if (!InitRPCAuthentication(config)) return false; RegisterHTTPHandler("/", true, HTTPReq_JSONRPC); #ifdef ENABLE_WALLET diff --git a/src/init.cpp b/src/init.cpp --- a/src/init.cpp +++ b/src/init.cpp @@ -1137,7 +1137,7 @@ if (!StartRPC()) { return false; } - if (!StartHTTPRPC()) { + if (!StartHTTPRPC(config)) { return false; } if (gArgs.GetBoolArg("-rest", DEFAULT_REST_ENABLE) && !StartREST()) {