Bitcoin Core  0.19.99
P2P Digital Currency
request.cpp
Go to the documentation of this file.
1 // Copyright (c) 2010 Satoshi Nakamoto
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 
10 #include <random.h>
11 #include <rpc/protocol.h>
12 #include <util/system.h>
13 #include <util/strencodings.h>
14 
24 UniValue JSONRPCRequestObj(const std::string& strMethod, const UniValue& params, const UniValue& id)
25 {
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 
33 UniValue JSONRPCReplyObj(const UniValue& result, const UniValue& error, const UniValue& id)
34 {
35  UniValue reply(UniValue::VOBJ);
36  if (!error.isNull())
37  reply.pushKV("result", NullUniValue);
38  else
39  reply.pushKV("result", result);
40  reply.pushKV("error", error);
41  reply.pushKV("id", id);
42  return reply;
43 }
44 
45 std::string JSONRPCReply(const UniValue& result, const UniValue& error, const UniValue& id)
46 {
47  UniValue reply = JSONRPCReplyObj(result, error, id);
48  return reply.write() + "\n";
49 }
50 
51 UniValue JSONRPCError(int code, const std::string& message)
52 {
54  error.pushKV("code", code);
55  error.pushKV("message", message);
56  return error;
57 }
58 
62 static const std::string COOKIEAUTH_USER = "__cookie__";
64 static const std::string COOKIEAUTH_FILE = ".cookie";
65 
67 static fs::path GetAuthCookieFile(bool temp=false)
68 {
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 {
78  const size_t COOKIE_SIZE = 32;
79  unsigned char rand_pwd[COOKIE_SIZE];
80  GetRandBytes(rand_pwd, COOKIE_SIZE);
81  std::string cookie = COOKIEAUTH_USER + ":" + HexStr(rand_pwd, rand_pwd+COOKIE_SIZE);
82 
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", filepath_tmp.string());
91  return false;
92  }
93  file << cookie;
94  file.close();
95 
96  fs::path filepath = GetAuthCookieFile(false);
97  if (!RenameOver(filepath_tmp, filepath)) {
98  LogPrintf("Unable to rename cookie authentication file %s to %s\n", filepath_tmp.string(), filepath.string());
99  return false;
100  }
101  LogPrintf("Generated RPC authentication cookie %s\n", filepath.string());
102 
103  if (cookie_out)
104  *cookie_out = cookie;
105  return true;
106 }
107 
108 bool GetAuthCookie(std::string *cookie_out)
109 {
110  fsbridge::ifstream file;
111  std::string cookie;
112  fs::path filepath = GetAuthCookieFile();
113  file.open(filepath);
114  if (!file.is_open())
115  return false;
116  std::getline(file, cookie);
117  file.close();
118 
119  if (cookie_out)
120  *cookie_out = cookie;
121  return true;
122 }
123 
125 {
126  try {
127  fs::remove(GetAuthCookieFile());
128  } catch (const fs::filesystem_error& e) {
129  LogPrintf("%s: Unable to remove random auth cookie file: %s\n", __func__, fsbridge::get_filesystem_error_message(e));
130  }
131 }
132 
133 std::vector<UniValue> JSONRPCProcessBatchReply(const UniValue &in, size_t num)
134 {
135  if (!in.isArray()) {
136  throw std::runtime_error("Batch must be an array");
137  }
138  std::vector<UniValue> batch(num);
139  for (size_t i=0; i<in.size(); ++i) {
140  const UniValue &rec = in[i];
141  if (!rec.isObject()) {
142  throw std::runtime_error("Batch member must be object");
143  }
144  size_t id = rec["id"].get_int();
145  if (id >= num) {
146  throw std::runtime_error("Batch member id larger than size");
147  }
148  batch[id] = rec;
149  }
150  return batch;
151 }
152 
153 void JSONRPCRequest::parse(const UniValue& valRequest)
154 {
155  // Parse request
156  if (!valRequest.isObject())
157  throw JSONRPCError(RPC_INVALID_REQUEST, "Invalid Request object");
158  const UniValue& request = valRequest.get_obj();
159 
160  // Parse id now so errors from here on will have the id
161  id = find_value(request, "id");
162 
163  // Parse method
164  UniValue valMethod = find_value(request, "method");
165  if (valMethod.isNull())
166  throw JSONRPCError(RPC_INVALID_REQUEST, "Missing method");
167  if (!valMethod.isStr())
168  throw JSONRPCError(RPC_INVALID_REQUEST, "Method must be a string");
169  strMethod = valMethod.get_str();
170  if (fLogIPs)
171  LogPrint(BCLog::RPC, "ThreadRPCServer method=%s user=%s peeraddr=%s\n", SanitizeString(strMethod),
172  this->authUser, this->peerAddr);
173  else
174  LogPrint(BCLog::RPC, "ThreadRPCServer method=%s user=%s\n", SanitizeString(strMethod), this->authUser);
175 
176  // Parse params
177  UniValue valParams = find_value(request, "params");
178  if (valParams.isArray() || valParams.isObject())
179  params = valParams;
180  else if (valParams.isNull())
182  else
183  throw JSONRPCError(RPC_INVALID_REQUEST, "Params must be an array or object");
184 }
std::string SanitizeString(const std::string &str, int rule)
Remove unsafe chars.
bool isObject() const
Definition: univalue.h:84
std::vector< UniValue > JSONRPCProcessBatchReply(const UniValue &in, size_t num)
Parse JSON-RPC batch reply into a vector.
Definition: request.cpp:133
#define LogPrint(category,...)
Definition: logging.h:179
fs::ifstream ifstream
Definition: fs.h:90
static void LogPrintf(const char *fmt, const Args &... args)
Definition: logging.h:163
const std::string & get_str() const
bool isStr() const
Definition: univalue.h:81
void GetRandBytes(unsigned char *buf, int num) noexcept
Overall design of the RNG and entropy sources.
Definition: random.cpp:578
fs::ofstream ofstream
Definition: fs.h:91
void DeleteAuthCookie()
Delete RPC authentication cookie from disk.
Definition: request.cpp:124
const UniValue & find_value(const UniValue &obj, const std::string &name)
Definition: univalue.cpp:234
static const std::string COOKIEAUTH_FILE
Default name for auth cookie file.
Definition: request.cpp:64
std::string strMethod
Definition: request.h:31
std::string peerAddr
Definition: request.h:36
UniValue JSONRPCError(int code, const std::string &message)
Definition: request.cpp:51
UniValue params
Definition: request.h:32
std::string write(unsigned int prettyIndent=0, unsigned int indentLevel=0) const
bool pushKV(const std::string &key, const UniValue &val)
Definition: univalue.cpp:133
int get_int() const
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:1146
bool isNull() const
Definition: univalue.h:77
std::string JSONRPCReply(const UniValue &result, const UniValue &error, const UniValue &id)
Definition: request.cpp:45
bool RenameOver(fs::path src, fs::path dest)
Definition: system.cpp:891
std::string get_filesystem_error_message(const fs::filesystem_error &e)
Definition: fs.cpp:107
void parse(const UniValue &valRequest)
Definition: request.cpp:153
const UniValue & get_obj() const
std::string GetArg(const std::string &strArg, const std::string &strDefault) const
Return string argument or default value.
Definition: system.cpp:372
bool fLogIPs
Definition: logging.cpp:35
std::string authUser
Definition: request.h:35
UniValue JSONRPCReplyObj(const UniValue &result, const UniValue &error, const UniValue &id)
Definition: request.cpp:33
bool GenerateAuthCookie(std::string *cookie_out)
Generate a new RPC authentication cookie and write it to disk.
Definition: request.cpp:76
std::string HexStr(const T itbegin, const T itend)
Definition: strencodings.h:123
ArgsManager gArgs
Definition: system.cpp:76
UniValue JSONRPCRequestObj(const std::string &strMethod, const UniValue &params, const UniValue &id)
JSON-RPC protocol.
Definition: request.cpp:24
const UniValue NullUniValue
Definition: univalue.cpp:13
static fs::path GetAuthCookieFile(bool temp=false)
Get name of RPC authentication cookie file.
Definition: request.cpp:67
Standard JSON-RPC 2.0 errors.
Definition: protocol.h:28
size_t size() const
Definition: univalue.h:68
bool error(const char *fmt, const Args &... args)
Definition: system.h:49
bool GetAuthCookie(std::string *cookie_out)
Read the RPC authentication cookie from disk.
Definition: request.cpp:108
bool isArray() const
Definition: univalue.h:83
static const std::string COOKIEAUTH_USER
Username used when cookie authentication is in use (arbitrary, only for recognizability in debugging/...
Definition: request.cpp:62