Bitcoin ABC  0.26.3
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 
15 #include <fstream>
16 #include <stdexcept>
17 #include <string>
18 #include <vector>
19 
29 UniValue JSONRPCRequestObj(const std::string &strMethod, const UniValue &params,
30  const UniValue &id) {
31  UniValue request(UniValue::VOBJ);
32  request.pushKV("method", strMethod);
33  request.pushKV("params", params);
34  request.pushKV("id", id);
35  return request;
36 }
37 
39  const UniValue &id) {
40  UniValue reply(UniValue::VOBJ);
41  if (!error.isNull()) {
42  reply.pushKV("result", NullUniValue);
43  } else {
44  reply.pushKV("result", result);
45  }
46  reply.pushKV("error", error);
47  reply.pushKV("id", id);
48  return reply;
49 }
50 
51 std::string JSONRPCReply(const UniValue &result, const UniValue &error,
52  const UniValue &id) {
53  UniValue reply = JSONRPCReplyObj(result, error, id);
54  return reply.write() + "\n";
55 }
56 
57 UniValue JSONRPCError(int code, const std::string &message) {
59  error.pushKV("code", code);
60  error.pushKV("message", message);
61  return error;
62 }
63 
68 static const std::string COOKIEAUTH_USER = "__cookie__";
70 static const std::string COOKIEAUTH_FILE = ".cookie";
71 
73 static fs::path GetAuthCookieFile(bool temp = false) {
74  std::string arg = gArgs.GetArg("-rpccookiefile", COOKIEAUTH_FILE);
75  if (temp) {
76  arg += ".tmp";
77  }
79 }
80 
81 bool GenerateAuthCookie(std::string *cookie_out) {
82  const size_t COOKIE_SIZE = 32;
83  uint8_t rand_pwd[COOKIE_SIZE];
84  GetRandBytes(rand_pwd);
85  std::string cookie = COOKIEAUTH_USER + ":" + HexStr(rand_pwd);
86 
91  std::ofstream file;
92  fs::path filepath_tmp = GetAuthCookieFile(true);
93  file.open(filepath_tmp);
94  if (!file.is_open()) {
95  LogPrintf("Unable to open cookie authentication file %s for writing\n",
96  fs::PathToString(filepath_tmp));
97  return false;
98  }
99  file << cookie;
100  file.close();
101 
102  fs::path filepath = GetAuthCookieFile(false);
103  if (!RenameOver(filepath_tmp, filepath)) {
104  LogPrintf("Unable to rename cookie authentication file %s to %s\n",
105  fs::PathToString(filepath_tmp), fs::PathToString(filepath));
106  return false;
107  }
108  LogPrintf("Generated RPC authentication cookie %s\n",
109  fs::PathToString(filepath));
110 
111  if (cookie_out) {
112  *cookie_out = cookie;
113  }
114  return true;
115 }
116 
117 bool GetAuthCookie(std::string *cookie_out) {
118  std::ifstream file;
119  std::string cookie;
120  fs::path filepath = GetAuthCookieFile();
121  file.open(filepath);
122  if (!file.is_open()) {
123  return false;
124  }
125  std::getline(file, cookie);
126  file.close();
127 
128  if (cookie_out) {
129  *cookie_out = cookie;
130  }
131  return true;
132 }
133 
135  try {
136  fs::remove(GetAuthCookieFile());
137  } catch (const fs::filesystem_error &e) {
138  LogPrintf("%s: Unable to remove random auth cookie file: %s\n",
140  }
141 }
142 
143 std::vector<UniValue> JSONRPCProcessBatchReply(const UniValue &in) {
144  if (!in.isArray()) {
145  throw std::runtime_error("Batch must be an array");
146  }
147  const size_t num{in.size()};
148  std::vector<UniValue> batch(num);
149  for (const UniValue &rec : in.getValues()) {
150  if (!rec.isObject()) {
151  throw std::runtime_error("Batch member must be an object");
152  }
153  size_t id = rec["id"].get_int();
154  if (id >= num) {
155  throw std::runtime_error(
156  "Batch member id is larger than batch size");
157  }
158  batch[id] = rec;
159  }
160  return batch;
161 }
162 
163 void JSONRPCRequest::parse(const UniValue &valRequest) {
164  // Parse request
165  if (!valRequest.isObject()) {
166  throw JSONRPCError(RPC_INVALID_REQUEST, "Invalid Request object");
167  }
168 
169  const UniValue &request = valRequest.get_obj();
170 
171  // Parse id now so errors from here on will have the id
172  id = request.find_value("id");
173 
174  // Parse method
175  const UniValue &valMethod{request.find_value("method")};
176  if (valMethod.isNull()) {
177  throw JSONRPCError(RPC_INVALID_REQUEST, "Missing method");
178  }
179  if (!valMethod.isStr()) {
180  throw JSONRPCError(RPC_INVALID_REQUEST, "Method must be a string");
181  }
182  strMethod = valMethod.get_str();
183  if (fLogIPs) {
184  LogPrint(BCLog::RPC, "ThreadRPCServer method=%s user=%s peeraddr=%s\n",
185  SanitizeString(strMethod), this->authUser, this->peerAddr);
186  } else {
187  LogPrint(BCLog::RPC, "ThreadRPCServer method=%s user=%s\n",
189  }
190 
191  // Parse params
192  const UniValue &valParams{request.find_value("params")};
193  if (valParams.isArray() || valParams.isObject()) {
194  params = valParams;
195  } else if (valParams.isNull()) {
197  } else {
199  "Params must be an array or object");
200  }
201 }
std::string GetArg(const std::string &strArg, const std::string &strDefault) const
Return string argument or default value.
Definition: system.cpp:602
UniValue params
Definition: request.h:34
std::string strMethod
Definition: request.h:33
std::string peerAddr
Definition: request.h:38
void parse(const UniValue &valRequest)
Definition: request.cpp:163
std::string authUser
Definition: request.h:37
bool isArray() const
Definition: univalue.h:95
const UniValue & find_value(std::string_view key) const
Definition: univalue.cpp:234
@ VOBJ
Definition: univalue.h:27
@ VARR
Definition: univalue.h:27
std::string write(unsigned int prettyIndent=0, unsigned int indentLevel=0) const
const UniValue & get_obj() const
size_t size() const
Definition: univalue.h:80
const std::vector< UniValue > & getValues() const
bool pushKV(const std::string &key, const UniValue &val)
Definition: univalue.cpp:133
bool isObject() const
Definition: univalue.h:96
Path class wrapper to block calls to the fs::path(std::string) implicit constructor and the fs::path:...
Definition: fs.h:29
bool fLogIPs
Definition: logging.cpp:17
#define LogPrint(category,...)
Definition: logging.h:210
#define LogPrintf(...)
Definition: logging.h:206
@ RPC
Definition: logging.h:47
static std::string PathToString(const path &path)
Convert path object to byte string.
Definition: fs.h:141
static path PathFromString(const std::string &string)
Convert byte string to path object.
Definition: fs.h:164
std::string get_filesystem_error_message(const fs::filesystem_error &e)
Definition: fs.cpp:140
void GetRandBytes(Span< uint8_t > bytes) noexcept
Overall design of the RNG and entropy sources.
Definition: random.cpp:639
static fs::path GetAuthCookieFile(bool temp=false)
Get name of RPC authentication cookie file.
Definition: request.cpp:73
std::vector< UniValue > JSONRPCProcessBatchReply(const UniValue &in)
Parse JSON-RPC batch reply into a vector.
Definition: request.cpp:143
bool GetAuthCookie(std::string *cookie_out)
Read the RPC authentication cookie from disk.
Definition: request.cpp:117
std::string JSONRPCReply(const UniValue &result, const UniValue &error, const UniValue &id)
Definition: request.cpp:51
UniValue JSONRPCRequestObj(const std::string &strMethod, const UniValue &params, const UniValue &id)
JSON-RPC protocol.
Definition: request.cpp:29
UniValue JSONRPCError(int code, const std::string &message)
Definition: request.cpp:57
void DeleteAuthCookie()
Delete RPC authentication cookie from disk.
Definition: request.cpp:134
static const std::string COOKIEAUTH_FILE
Default name for auth cookie file.
Definition: request.cpp:70
bool GenerateAuthCookie(std::string *cookie_out)
Generate a new RPC authentication cookie and write it to disk.
Definition: request.cpp:81
UniValue JSONRPCReplyObj(const UniValue &result, const UniValue &error, const UniValue &id)
Definition: request.cpp:38
static const std::string COOKIEAUTH_USER
Username used when cookie authentication is in use (arbitrary, only for recognizability in debugging/...
Definition: request.cpp:68
@ RPC_INVALID_REQUEST
Standard JSON-RPC 2.0 errors.
Definition: protocol.h:26
std::string HexStr(const Span< const uint8_t > s)
Convert a span of bytes to a lower-case hexadecimal string.
std::string SanitizeString(const std::string &str, int rule)
Remove unsafe chars.
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:1452
bool RenameOver(fs::path src, fs::path dest)
Definition: system.cpp:1201
ArgsManager gArgs
Definition: system.cpp:79
bool error(const char *fmt, const Args &...args)
Definition: system.h:45
const UniValue NullUniValue
Definition: univalue.cpp:13