aboutsummaryrefslogtreecommitdiff
path: root/src/httprpc.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/httprpc.cpp')
-rw-r--r--src/httprpc.cpp68
1 files changed, 63 insertions, 5 deletions
diff --git a/src/httprpc.cpp b/src/httprpc.cpp
index 98ac750bb1..432a5c0792 100644
--- a/src/httprpc.cpp
+++ b/src/httprpc.cpp
@@ -1,17 +1,25 @@
+// Copyright (c) 2015 The Bitcoin Core developers
+// Distributed under the MIT software license, see the accompanying
+// file COPYING or http://www.opensource.org/licenses/mit-license.php.
+
#include "httprpc.h"
#include "base58.h"
#include "chainparams.h"
#include "httpserver.h"
-#include "rpcprotocol.h"
-#include "rpcserver.h"
+#include "rpc/protocol.h"
+#include "rpc/server.h"
#include "random.h"
#include "sync.h"
#include "util.h"
#include "utilstrencodings.h"
#include "ui_interface.h"
+#include "crypto/hmac_sha256.h"
+#include <stdio.h>
+#include "utilstrencodings.h"
#include <boost/algorithm/string.hpp> // boost::trim
+#include <boost/foreach.hpp> //BOOST_FOREACH
/** Simple one-shot callback timer to be used by the RPC mechanism to e.g.
* re-lock the wellet.
@@ -72,6 +80,50 @@ static void JSONErrorReply(HTTPRequest* req, const UniValue& objError, const Uni
req->WriteReply(nStatus, strReply);
}
+//This function checks username and password against -rpcauth
+//entries from config file.
+static bool multiUserAuthorized(std::string strUserPass)
+{
+ if (strUserPass.find(":") == std::string::npos) {
+ return false;
+ }
+ std::string strUser = strUserPass.substr(0, strUserPass.find(":"));
+ std::string strPass = strUserPass.substr(strUserPass.find(":") + 1);
+
+ if (mapMultiArgs.count("-rpcauth") > 0) {
+ //Search for multi-user login/pass "rpcauth" from config
+ BOOST_FOREACH(std::string strRPCAuth, mapMultiArgs["-rpcauth"])
+ {
+ std::vector<std::string> vFields;
+ boost::split(vFields, strRPCAuth, boost::is_any_of(":$"));
+ if (vFields.size() != 3) {
+ //Incorrect formatting in config file
+ continue;
+ }
+
+ std::string strName = vFields[0];
+ if (!TimingResistantEqual(strName, strUser)) {
+ continue;
+ }
+
+ std::string strSalt = vFields[1];
+ std::string strHash = vFields[2];
+
+ unsigned int KEY_SIZE = 32;
+ unsigned char *out = new unsigned char[KEY_SIZE];
+
+ CHMAC_SHA256(reinterpret_cast<const unsigned char*>(strSalt.c_str()), strSalt.size()).Write(reinterpret_cast<const unsigned char*>(strPass.c_str()), strPass.size()).Finalize(out);
+ std::vector<unsigned char> hexvec(out, out+KEY_SIZE);
+ std::string strHashFromPass = HexStr(hexvec);
+
+ if (TimingResistantEqual(strHashFromPass, strHash)) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
static bool RPCAuthorized(const std::string& strAuth)
{
if (strRPCUserColonPass.empty()) // Belt-and-suspenders measure if InitRPCAuthentication was not called
@@ -81,7 +133,12 @@ static bool RPCAuthorized(const std::string& strAuth)
std::string strUserPass64 = strAuth.substr(6);
boost::trim(strUserPass64);
std::string strUserPass = DecodeBase64(strUserPass64);
- return TimingResistantEqual(strUserPass, strRPCUserColonPass);
+
+ //Check if authorized under single-user field
+ if (TimingResistantEqual(strUserPass, strRPCUserColonPass)) {
+ return true;
+ }
+ return multiUserAuthorized(strUserPass);
}
static bool HTTPReq_JSONRPC(HTTPRequest* req, const std::string &)
@@ -157,6 +214,7 @@ static bool InitRPCAuthentication()
return false;
}
} 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.");
strRPCUserColonPass = mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"];
}
return true;
@@ -172,7 +230,7 @@ bool StartHTTPRPC()
assert(EventBase());
httpRPCTimerInterface = new HTTPRPCTimerInterface(EventBase());
- RPCRegisterTimerInterface(httpRPCTimerInterface);
+ RPCSetTimerInterface(httpRPCTimerInterface);
return true;
}
@@ -186,7 +244,7 @@ void StopHTTPRPC()
LogPrint("rpc", "Stopping HTTP RPC server\n");
UnregisterHTTPHandler("/", true);
if (httpRPCTimerInterface) {
- RPCUnregisterTimerInterface(httpRPCTimerInterface);
+ RPCUnsetTimerInterface(httpRPCTimerInterface);
delete httpRPCTimerInterface;
httpRPCTimerInterface = 0;
}