Bitcoin Core  22.99.0
P2P Digital Currency
request.cpp
Go to the documentation of this file.
1 // Copyright (c) 2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2021 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 
10 #include <random.h>
11 #include <rpc/protocol.h>
12 #include <util/system.h>
13 #include <util/strencodings.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, const UniValue& id)
30 {
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 
38 UniValue JSONRPCReplyObj(const UniValue& result, const UniValue& error, const UniValue& id)
39 {
40  UniValue reply(UniValue::VOBJ);
41  if (!error.isNull())
42  reply.pushKV("result", NullUniValue);
43  else
44  reply.pushKV("result", result);
45  reply.pushKV("error", error);
46  reply.pushKV("id", id);
47  return reply;
48 }
49 
50 std::string JSONRPCReply(const UniValue& result, const UniValue& error, const UniValue& id)
51 {
52  UniValue reply = JSONRPCReplyObj(result, error, id);
53  return reply.write() + "\n";
54 }
55 
56 UniValue JSONRPCError(int code, const std::string& message)
57 {
59  error.pushKV("code", code);
60  error.pushKV("message", message);
61  return error;
62 }
63 
67 static const std::string COOKIEAUTH_USER = "__cookie__";
69 static const std::string COOKIEAUTH_FILE = ".cookie";
70 
72 static fs::path GetAuthCookieFile(bool temp=false)
73 {
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 {
83  const size_t COOKIE_SIZE = 32;
84  unsigned char rand_pwd[COOKIE_SIZE];
85  GetRandBytes(rand_pwd, COOKIE_SIZE);
86  std::string cookie = COOKIEAUTH_USER + ":" + HexStr(rand_pwd);
87 
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", fs::PathToString(filepath_tmp));
96  return false;
97  }
98  file << cookie;
99  file.close();
100 
101  fs::path filepath = GetAuthCookieFile(false);
102  if (!RenameOver(filepath_tmp, filepath)) {
103  LogPrintf("Unable to rename cookie authentication file %s to %s\n", fs::PathToString(filepath_tmp), fs::PathToString(filepath));
104  return false;
105  }
106  LogPrintf("Generated RPC authentication cookie %s\n", fs::PathToString(filepath));
107 
108  if (cookie_out)
109  *cookie_out = cookie;
110  return true;
111 }
112 
113 bool GetAuthCookie(std::string *cookie_out)
114 {
115  std::ifstream file;
116  std::string cookie;
117  fs::path filepath = GetAuthCookieFile();
118  file.open(filepath);
119  if (!file.is_open())
120  return false;
121  std::getline(file, cookie);
122  file.close();
123 
124  if (cookie_out)
125  *cookie_out = cookie;
126  return true;
127 }
128 
130 {
131  try {
132  fs::remove(GetAuthCookieFile());
133  } catch (const fs::filesystem_error& e) {
134  LogPrintf("%s: Unable to remove random auth cookie file: %s\n", __func__, fsbridge::get_filesystem_error_message(e));
135  }
136 }
137 
138 std::vector<UniValue> JSONRPCProcessBatchReply(const UniValue& in)
139 {
140  if (!in.isArray()) {
141  throw std::runtime_error("Batch must be an array");
142  }
143  const size_t num {in.size()};
144  std::vector<UniValue> batch(num);
145  for (const UniValue& rec : in.getValues()) {
146  if (!rec.isObject()) {
147  throw std::runtime_error("Batch member must be an object");
148  }
149  size_t id = rec["id"].get_int();
150  if (id >= num) {
151  throw std::runtime_error("Batch member id is larger than batch size");
152  }
153  batch[id] = rec;
154  }
155  return batch;
156 }
157 
158 void JSONRPCRequest::parse(const UniValue& valRequest)
159 {
160  // Parse request
161  if (!valRequest.isObject())
162  throw JSONRPCError(RPC_INVALID_REQUEST, "Invalid Request object");
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  if (!valMethod.isStr())
173  throw JSONRPCError(RPC_INVALID_REQUEST, "Method must be a string");
174  strMethod = valMethod.get_str();
175  if (fLogIPs)
176  LogPrint(BCLog::RPC, "ThreadRPCServer method=%s user=%s peeraddr=%s\n", SanitizeString(strMethod),
177  this->authUser, this->peerAddr);
178  else
179  LogPrint(BCLog::RPC, "ThreadRPCServer method=%s user=%s\n", SanitizeString(strMethod), this->authUser);
180 
181  // Parse params
182  UniValue valParams = find_value(request, "params");
183  if (valParams.isArray() || valParams.isObject())
184  params = valParams;
185  else if (valParams.isNull())
187  else
188  throw JSONRPCError(RPC_INVALID_REQUEST, "Params must be an array or object");
189 }
RPC_INVALID_REQUEST
@ RPC_INVALID_REQUEST
Standard JSON-RPC 2.0 errors.
Definition: protocol.h:28
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:1363
fLogIPs
bool fLogIPs
Definition: logging.cpp:39
UniValue::VOBJ
@ VOBJ
Definition: univalue.h:19
GenerateAuthCookie
bool GenerateAuthCookie(std::string *cookie_out)
Generate a new RPC authentication cookie and write it to disk.
Definition: request.cpp:81
fs.h
JSONRPCReply
std::string JSONRPCReply(const UniValue &result, const UniValue &error, const UniValue &id)
Definition: request.cpp:50
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:140
protocol.h
GetAuthCookie
bool GetAuthCookie(std::string *cookie_out)
Read the RPC authentication cookie from disk.
Definition: request.cpp:113
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:67
UniValue::isNull
bool isNull() const
Definition: univalue.h:75
JSONRPCReplyObj
UniValue JSONRPCReplyObj(const UniValue &result, const UniValue &error, const UniValue &id)
Definition: request.cpp:38
fs::PathToString
static std::string PathToString(const path &path)
Convert path object to a byte string.
Definition: fs.h:112
UniValue::write
std::string write(unsigned int prettyIndent=0, unsigned int indentLevel=0) const
Definition: univalue_write.cpp:28
UniValue::pushKV
bool pushKV(const std::string &key, const UniValue &val)
Definition: univalue.cpp:133
UniValue
Definition: univalue.h:17
JSONRPCRequest::peerAddr
std::string peerAddr
Definition: request.h:37
BCLog::RPC
@ RPC
Definition: logging.h:46
UniValue::get_str
const std::string & get_str() const
Definition: univalue_get.cpp:98
strencodings.h
UniValue::isStr
bool isStr() const
Definition: univalue.h:79
RenameOver
bool RenameOver(fs::path src, fs::path dest)
Rename src to dest.
Definition: system.cpp:1063
random.h
UniValue::get_obj
const UniValue & get_obj() const
Definition: univalue_get.cpp:135
fs::path
Path class wrapper to block calls to the fs::path(std::string) implicit constructor and the fs::path:...
Definition: fs.h:29
JSONRPCRequest::strMethod
std::string strMethod
Definition: request.h:32
GetRandBytes
void GetRandBytes(unsigned char *buf, int num) noexcept
Overall design of the RNG and entropy sources.
Definition: random.cpp:581
JSONRPCRequestObj
UniValue JSONRPCRequestObj(const std::string &strMethod, const UniValue &params, const UniValue &id)
JSON-RPC protocol.
Definition: request.cpp:29
ArgsManager::GetArg
std::string GetArg(const std::string &strArg, const std::string &strDefault) const
Return string argument or default value.
Definition: system.cpp:588
LogPrintf
#define LogPrintf(...)
Definition: logging.h:188
GetAuthCookieFile
static fs::path GetAuthCookieFile(bool temp=false)
Get name of RPC authentication cookie file.
Definition: request.cpp:72
id
static NodeId id
Definition: denialofservice_tests.cpp:37
fs::PathFromString
static path PathFromString(const std::string &string)
Convert byte string to path object.
Definition: fs.h:135
LogPrint
#define LogPrint(category,...)
Definition: logging.h:192
request.h
UniValue::isArray
bool isArray() const
Definition: univalue.h:81
gArgs
ArgsManager gArgs
Definition: system.cpp:87
JSONRPCRequest::parse
void parse(const UniValue &valRequest)
Definition: request.cpp:158
JSONRPCRequest::params
UniValue params
Definition: request.h:33
system.h
DeleteAuthCookie
void DeleteAuthCookie()
Delete RPC authentication cookie from disk.
Definition: request.cpp:129
SanitizeString
std::string SanitizeString(const std::string &str, int rule)
Remove unsafe chars.
Definition: strencodings.cpp:27
JSONRPCProcessBatchReply
std::vector< UniValue > JSONRPCProcessBatchReply(const UniValue &in)
Parse JSON-RPC batch reply into a vector.
Definition: request.cpp:138
JSONRPCError
UniValue JSONRPCError(int code, const std::string &message)
Definition: request.cpp:56
UniValue::getValues
const std::vector< UniValue > & getValues() const
Definition: univalue_get.cpp:84
UniValue::size
size_t size() const
Definition: univalue.h:66
find_value
const UniValue & find_value(const UniValue &obj, const std::string &name)
Definition: univalue.cpp:236
COOKIEAUTH_FILE
static const std::string COOKIEAUTH_FILE
Default name for auth cookie file.
Definition: request.cpp:69
error
bool error(const char *fmt, const Args &... args)
Definition: system.h:49
UniValue::VARR
@ VARR
Definition: univalue.h:19
HexStr
std::string HexStr(const Span< const uint8_t > s)
Convert a span of bytes to a lower-case hexadecimal string.
Definition: strencodings.cpp:511
JSONRPCRequest::authUser
std::string authUser
Definition: request.h:36
UniValue::isObject
bool isObject() const
Definition: univalue.h:82