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