Bitcoin ABC  0.24.7
P2P Digital Currency
request.cpp
Go to the documentation of this file.
1 // Copyright (c) 2018-2019 The Bitcoin developers
2 // Copyright (c) 2009-2019 The Bitcoin Core developers
3 // Distributed under the MIT software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5 
6 #include <rpc/request.h>
7 
8 #include <fs.h>
9 #include <logging.h>
10 #include <random.h>
11 #include <rpc/protocol.h>
12 #include <util/strencodings.h>
13 #include <util/system.h>
14 
24 UniValue JSONRPCRequestObj(const std::string &strMethod, const UniValue &params,
25  const UniValue &id) {
26  UniValue request(UniValue::VOBJ);
27  request.pushKV("method", strMethod);
28  request.pushKV("params", params);
29  request.pushKV("id", id);
30  return request;
31 }
32 
34  const UniValue &id) {
35  UniValue reply(UniValue::VOBJ);
36  if (!error.isNull()) {
37  reply.pushKV("result", NullUniValue);
38  } else {
39  reply.pushKV("result", result);
40  }
41  reply.pushKV("error", error);
42  reply.pushKV("id", id);
43  return reply;
44 }
45 
46 std::string JSONRPCReply(const UniValue &result, const UniValue &error,
47  const UniValue &id) {
48  UniValue reply = JSONRPCReplyObj(result, error, id);
49  return reply.write() + "\n";
50 }
51 
52 UniValue JSONRPCError(int code, const std::string &message) {
54  error.pushKV("code", code);
55  error.pushKV("message", message);
56  return error;
57 }
58 
63 static const std::string COOKIEAUTH_USER = "__cookie__";
65 static const std::string COOKIEAUTH_FILE = ".cookie";
66 
68 static fs::path GetAuthCookieFile(bool temp = false) {
69  std::string arg = gArgs.GetArg("-rpccookiefile", COOKIEAUTH_FILE);
70  if (temp) {
71  arg += ".tmp";
72  }
73  return AbsPathForConfigVal(fs::path(arg));
74 }
75 
76 bool GenerateAuthCookie(std::string *cookie_out) {
77  const size_t COOKIE_SIZE = 32;
78  uint8_t rand_pwd[COOKIE_SIZE];
79  GetRandBytes(rand_pwd, COOKIE_SIZE);
80  std::string cookie = COOKIEAUTH_USER + ":" + HexStr(rand_pwd);
81 
86  fsbridge::ofstream file;
87  fs::path filepath_tmp = GetAuthCookieFile(true);
88  file.open(filepath_tmp);
89  if (!file.is_open()) {
90  LogPrintf("Unable to open cookie authentication file %s for writing\n",
91  filepath_tmp.string());
92  return false;
93  }
94  file << cookie;
95  file.close();
96 
97  fs::path filepath = GetAuthCookieFile(false);
98  if (!RenameOver(filepath_tmp, filepath)) {
99  LogPrintf("Unable to rename cookie authentication file %s to %s\n",
100  filepath_tmp.string(), filepath.string());
101  return false;
102  }
103  LogPrintf("Generated RPC authentication cookie %s\n", filepath.string());
104 
105  if (cookie_out) {
106  *cookie_out = cookie;
107  }
108  return true;
109 }
110 
111 bool GetAuthCookie(std::string *cookie_out) {
112  fsbridge::ifstream file;
113  std::string cookie;
114  fs::path filepath = GetAuthCookieFile();
115  file.open(filepath);
116  if (!file.is_open()) {
117  return false;
118  }
119  std::getline(file, cookie);
120  file.close();
121 
122  if (cookie_out) {
123  *cookie_out = cookie;
124  }
125  return true;
126 }
127 
129  try {
130  fs::remove(GetAuthCookieFile());
131  } catch (const fs::filesystem_error &e) {
132  LogPrintf("%s: Unable to remove random auth cookie file: %s\n",
134  }
135 }
136 
137 std::vector<UniValue> JSONRPCProcessBatchReply(const UniValue &in) {
138  if (!in.isArray()) {
139  throw std::runtime_error("Batch must be an array");
140  }
141  const size_t num{in.size()};
142  std::vector<UniValue> batch(num);
143  for (const UniValue &rec : in.getValues()) {
144  if (!rec.isObject()) {
145  throw std::runtime_error("Batch member must be an object");
146  }
147  size_t id = rec["id"].get_int();
148  if (id >= num) {
149  throw std::runtime_error(
150  "Batch member id is larger than batch size");
151  }
152  batch[id] = rec;
153  }
154  return batch;
155 }
156 
157 void JSONRPCRequest::parse(const UniValue &valRequest) {
158  // Parse request
159  if (!valRequest.isObject()) {
160  throw JSONRPCError(RPC_INVALID_REQUEST, "Invalid Request object");
161  }
162 
163  const UniValue &request = valRequest.get_obj();
164 
165  // Parse id now so errors from here on will have the id
166  id = find_value(request, "id");
167 
168  // Parse method
169  UniValue valMethod = find_value(request, "method");
170  if (valMethod.isNull()) {
171  throw JSONRPCError(RPC_INVALID_REQUEST, "Missing method");
172  }
173  if (!valMethod.isStr()) {
174  throw JSONRPCError(RPC_INVALID_REQUEST, "Method must be a string");
175  }
176  strMethod = valMethod.get_str();
177  if (fLogIPs) {
178  LogPrint(BCLog::RPC, "ThreadRPCServer method=%s user=%s peeraddr=%s\n",
179  SanitizeString(strMethod), this->authUser, this->peerAddr);
180  } else {
181  LogPrint(BCLog::RPC, "ThreadRPCServer method=%s user=%s\n",
183  }
184 
185  // Parse params
186  UniValue valParams = find_value(request, "params");
187  if (valParams.isArray() || valParams.isObject()) {
188  params = valParams;
189  } else if (valParams.isNull()) {
191  } else {
193  "Params must be an array or object");
194  }
195 }
RPC_INVALID_REQUEST
@ RPC_INVALID_REQUEST
Standard JSON-RPC 2.0 errors.
Definition: protocol.h:26
fLogIPs
bool fLogIPs
Definition: logging.cpp:12
fsbridge::ifstream
fs::ifstream ifstream
Definition: fs.h:98
UniValue::VOBJ
@ VOBJ
Definition: univalue.h:27
AbsPathForConfigVal
fs::path AbsPathForConfigVal(const fs::path &path, bool net_specific)
Most paths passed as configuration arguments are treated as relative to the datadir if they are not a...
Definition: system.cpp:1371
GenerateAuthCookie
bool GenerateAuthCookie(std::string *cookie_out)
Generate a new RPC authentication cookie and write it to disk.
Definition: request.cpp:76
fs.h
JSONRPCReply
std::string JSONRPCReply(const UniValue &result, const UniValue &error, const UniValue &id)
Definition: request.cpp:46
NullUniValue
const UniValue NullUniValue
Definition: univalue.cpp:13
fsbridge::get_filesystem_error_message
std::string get_filesystem_error_message(const fs::filesystem_error &e)
Definition: fs.cpp:131
RenameOver
bool RenameOver(fs::path src, fs::path dest)
Definition: system.cpp:1110
protocol.h
GetAuthCookie
bool GetAuthCookie(std::string *cookie_out)
Read the RPC authentication cookie from disk.
Definition: request.cpp:111
COOKIEAUTH_USER
static const std::string COOKIEAUTH_USER
Username used when cookie authentication is in use (arbitrary, only for recognizability in debugging/...
Definition: request.cpp:63
UniValue::isNull
bool isNull() const
Definition: univalue.h:89
GetRandBytes
void GetRandBytes(uint8_t *buf, int num) noexcept
Overall design of the RNG and entropy sources.
Definition: random.cpp:634
JSONRPCReplyObj
UniValue JSONRPCReplyObj(const UniValue &result, const UniValue &error, const UniValue &id)
Definition: request.cpp:33
UniValue::write
std::string write(unsigned int prettyIndent=0, unsigned int indentLevel=0) const
Definition: univalue_write.cpp:159
UniValue::pushKV
bool pushKV(const std::string &key, const UniValue &val)
Definition: univalue.cpp:133
UniValue
Definition: univalue.h:23
JSONRPCRequest::peerAddr
std::string peerAddr
Definition: request.h:41
BCLog::RPC
@ RPC
Definition: logging.h:45
UniValue::get_str
const std::string & get_str() const
Definition: univalue_get.cpp:98
fsbridge::ofstream
fs::ofstream ofstream
Definition: fs.h:99
strencodings.h
UniValue::isStr
bool isStr() const
Definition: univalue.h:93
random.h
UniValue::get_obj
const UniValue & get_obj() const
Definition: univalue_get.cpp:135
JSONRPCRequest::strMethod
std::string strMethod
Definition: request.h:36
JSONRPCRequestObj
UniValue JSONRPCRequestObj(const std::string &strMethod, const UniValue &params, const UniValue &id)
JSON-RPC protocol.
Definition: request.cpp:24
ArgsManager::GetArg
std::string GetArg(const std::string &strArg, const std::string &strDefault) const
Return string argument or default value.
Definition: system.cpp:498
GetAuthCookieFile
static fs::path GetAuthCookieFile(bool temp=false)
Get name of RPC authentication cookie file.
Definition: request.cpp:68
LogPrint
#define LogPrint(category,...)
Definition: logging.h:193
request.h
UniValue::isArray
bool isArray() const
Definition: univalue.h:95
JSONRPCRequest::parse
void parse(const UniValue &valRequest)
Definition: request.cpp:157
JSONRPCRequest::params
UniValue params
Definition: request.h:37
system.h
DeleteAuthCookie
void DeleteAuthCookie()
Delete RPC authentication cookie from disk.
Definition: request.cpp:128
SanitizeString
std::string SanitizeString(const std::string &str, int rule)
Remove unsafe chars.
Definition: strencodings.cpp:31
JSONRPCProcessBatchReply
std::vector< UniValue > JSONRPCProcessBatchReply(const UniValue &in)
Parse JSON-RPC batch reply into a vector.
Definition: request.cpp:137
JSONRPCError
UniValue JSONRPCError(int code, const std::string &message)
Definition: request.cpp:52
gArgs
ArgsManager gArgs
Definition: system.cpp:75
logging.h
UniValue::getValues
const std::vector< UniValue > & getValues() const
Definition: univalue_get.cpp:84
UniValue::size
size_t size() const
Definition: univalue.h:80
find_value
const UniValue & find_value(const UniValue &obj, const std::string &name)
Definition: univalue.cpp:234
COOKIEAUTH_FILE
static const std::string COOKIEAUTH_FILE
Default name for auth cookie file.
Definition: request.cpp:65
error
bool error(const char *fmt, const Args &... args)
Definition: system.h:48
UniValue::VARR
@ VARR
Definition: univalue.h:27
HexStr
std::string HexStr(const Span< const uint8_t > s)
Convert a span of bytes to a lower-case hexadecimal string.
Definition: strencodings.cpp:656
JSONRPCRequest::authUser
std::string authUser
Definition: request.h:40
LogPrintf
static void LogPrintf(const char *fmt, const Args &... args)
Definition: logging.h:175
UniValue::isObject
bool isObject() const
Definition: univalue.h:96