rippled
Loading...
Searching...
No Matches
Roles_test.cpp
1#include <test/jtx.h>
2#include <test/jtx/WSClient.h>
3
4#include <xrpl/beast/unit_test.h>
5
6#include <string>
7#include <unordered_map>
8
9namespace xrpl {
10
11namespace test {
12
14{
15 bool
17 {
18 boost::system::error_code ec;
19 boost::asio::ip::make_address(addr, ec);
20 return !ec.failed();
21 }
22
23 void
25 {
26 using namespace test::jtx;
27
28 {
29 Env env(*this);
30
31 BEAST_EXPECT(env.rpc("ping")["result"]["role"] == "admin");
32 BEAST_EXPECT(makeWSClient(env.app().config())->invoke("ping")["result"]["unlimited"].asBool());
33 }
34 {
35 Env env{*this, envconfig(no_admin)};
36
37 BEAST_EXPECT(!env.rpc("ping")["result"].isMember("role"));
38 auto wsRes = makeWSClient(env.app().config())->invoke("ping")["result"];
39 BEAST_EXPECT(!wsRes.isMember("unlimited") || !wsRes["unlimited"].asBool());
40 }
41 {
42 Env env{*this, envconfig(secure_gateway)};
43
44 BEAST_EXPECT(env.rpc("ping")["result"]["role"] == "proxied");
45 auto wsRes = makeWSClient(env.app().config())->invoke("ping")["result"];
46 BEAST_EXPECT(!wsRes.isMember("unlimited") || !wsRes["unlimited"].asBool());
47
49 Json::Value rpcRes;
50
51 // IPv4 tests.
52 headers["X-Forwarded-For"] = "12.34.56.78";
53 rpcRes = env.rpc(headers, "ping")["result"];
54 BEAST_EXPECT(rpcRes["role"] == "proxied");
55 BEAST_EXPECT(rpcRes["ip"] == "12.34.56.78");
56 BEAST_EXPECT(isValidIpAddress(rpcRes["ip"].asString()));
57
58 headers["X-Forwarded-For"] = "87.65.43.21, 44.33.22.11";
59 rpcRes = env.rpc(headers, "ping")["result"];
60 BEAST_EXPECT(rpcRes["ip"] == "87.65.43.21");
61 BEAST_EXPECT(isValidIpAddress(rpcRes["ip"].asString()));
62
63 headers["X-Forwarded-For"] = "87.65.43.21:47011, 44.33.22.11";
64 rpcRes = env.rpc(headers, "ping")["result"];
65 BEAST_EXPECT(rpcRes["ip"] == "87.65.43.21");
66 BEAST_EXPECT(isValidIpAddress(rpcRes["ip"].asString()));
67
68 headers = {};
69 headers["Forwarded"] = "for=88.77.66.55";
70 rpcRes = env.rpc(headers, "ping")["result"];
71 BEAST_EXPECT(rpcRes["ip"] == "88.77.66.55");
72 BEAST_EXPECT(isValidIpAddress(rpcRes["ip"].asString()));
73
74 headers["Forwarded"] =
75 "what=where;for=55.66.77.88;for=nobody;"
76 "who=3";
77 rpcRes = env.rpc(headers, "ping")["result"];
78 BEAST_EXPECT(rpcRes["ip"] == "55.66.77.88");
79 BEAST_EXPECT(isValidIpAddress(rpcRes["ip"].asString()));
80
81 headers["Forwarded"] =
82 "what=where; for=55.66.77.88, for=99.00.11.22;"
83 "who=3";
84 rpcRes = env.rpc(headers, "ping")["result"];
85 BEAST_EXPECT(rpcRes["ip"] == "55.66.77.88");
86 BEAST_EXPECT(isValidIpAddress(rpcRes["ip"].asString()));
87
88 headers["Forwarded"] =
89 "what=where; For=99.88.77.66, for=55.66.77.88;"
90 "who=3";
91 rpcRes = env.rpc(headers, "ping")["result"];
92 BEAST_EXPECT(rpcRes["ip"] == "99.88.77.66");
93 BEAST_EXPECT(isValidIpAddress(rpcRes["ip"].asString()));
94
95 headers["Forwarded"] =
96 "what=where; for=\"55.66.77.88:47011\";"
97 "who=3";
98 rpcRes = env.rpc(headers, "ping")["result"];
99 BEAST_EXPECT(rpcRes["ip"] == "55.66.77.88");
100 BEAST_EXPECT(isValidIpAddress(rpcRes["ip"].asString()));
101
102 headers["Forwarded"] =
103 "what=where; For= \" 99.88.77.66 \" ,for=11.22.33.44;"
104 "who=3";
105 rpcRes = env.rpc(headers, "ping")["result"];
106 BEAST_EXPECT(rpcRes["ip"] == "99.88.77.66");
107 BEAST_EXPECT(isValidIpAddress(rpcRes["ip"].asString()));
108
109 wsRes = makeWSClient(env.app().config(), true, 2, headers)->invoke("ping")["result"];
110 BEAST_EXPECT(!wsRes.isMember("unlimited") || !wsRes["unlimited"].asBool());
111
112 std::string const name = "xrposhi";
113 headers["X-User"] = name;
114 rpcRes = env.rpc(headers, "ping")["result"];
115 BEAST_EXPECT(rpcRes["role"] == "identified");
116 BEAST_EXPECT(rpcRes["username"] == name);
117 BEAST_EXPECT(rpcRes["ip"] == "99.88.77.66");
118 BEAST_EXPECT(isValidIpAddress(rpcRes["ip"].asString()));
119 wsRes = makeWSClient(env.app().config(), true, 2, headers)->invoke("ping")["result"];
120 BEAST_EXPECT(wsRes["unlimited"].asBool());
121
122 // IPv6 tests.
123 headers = {};
124 headers["X-Forwarded-For"] = "2001:db8:3333:4444:5555:6666:7777:8888";
125 rpcRes = env.rpc(headers, "ping")["result"];
126 BEAST_EXPECT(rpcRes["role"] == "proxied");
127 BEAST_EXPECT(rpcRes["ip"] == "2001:db8:3333:4444:5555:6666:7777:8888");
128 BEAST_EXPECT(isValidIpAddress(rpcRes["ip"].asString()));
129
130 headers["X-Forwarded-For"] =
131 "2001:db8:3333:4444:5555:6666:7777:9999, a:b:c:d:e:f, "
132 "g:h:i:j:k:l";
133 rpcRes = env.rpc(headers, "ping")["result"];
134 BEAST_EXPECT(rpcRes["role"] == "proxied");
135 BEAST_EXPECT(rpcRes["ip"] == "2001:db8:3333:4444:5555:6666:7777:9999");
136 BEAST_EXPECT(isValidIpAddress(rpcRes["ip"].asString()));
137
138 headers["X-Forwarded-For"] = "[2001:db8:3333:4444:5555:6666:7777:8888]";
139 rpcRes = env.rpc(headers, "ping")["result"];
140 BEAST_EXPECT(rpcRes["role"] == "proxied");
141 BEAST_EXPECT(rpcRes["ip"] == "2001:db8:3333:4444:5555:6666:7777:8888");
142 BEAST_EXPECT(isValidIpAddress(rpcRes["ip"].asString()));
143
144 headers["X-Forwarded-For"] =
145 "[2001:db8:3333:4444:5555:6666:7777:9999], [a:b:c:d:e:f], "
146 "[g:h:i:j:k:l]";
147 rpcRes = env.rpc(headers, "ping")["result"];
148 BEAST_EXPECT(rpcRes["role"] == "proxied");
149 BEAST_EXPECT(rpcRes["ip"] == "2001:db8:3333:4444:5555:6666:7777:9999");
150 BEAST_EXPECT(isValidIpAddress(rpcRes["ip"].asString()));
151
152 headers = {};
153 headers["Forwarded"] = "for=\"[2001:db8:3333:4444:5555:6666:7777:aaaa]\"";
154 rpcRes = env.rpc(headers, "ping")["result"];
155 BEAST_EXPECT(rpcRes["role"] == "proxied");
156 BEAST_EXPECT(rpcRes["ip"] == "2001:db8:3333:4444:5555:6666:7777:aaaa");
157 BEAST_EXPECT(isValidIpAddress(rpcRes["ip"].asString()));
158
159 headers["Forwarded"] = "For=\"[2001:db8:bb:cc:dd:ee:ff::]:2345\", for=99.00.11.22";
160 rpcRes = env.rpc(headers, "ping")["result"];
161 BEAST_EXPECT(rpcRes["role"] == "proxied");
162 BEAST_EXPECT(rpcRes["ip"] == "2001:db8:bb:cc:dd:ee:ff::");
163 BEAST_EXPECT(isValidIpAddress(rpcRes["ip"].asString()));
164
165 headers["Forwarded"] =
166 "proto=http;FOR=\"[2001:db8:11:22:33:44:55:66]\""
167 ";by=203.0.113.43";
168 rpcRes = env.rpc(headers, "ping")["result"];
169 BEAST_EXPECT(rpcRes["role"] == "proxied");
170 BEAST_EXPECT(rpcRes["ip"] == "2001:db8:11:22:33:44:55:66");
171 BEAST_EXPECT(isValidIpAddress(rpcRes["ip"].asString()));
172
173 // IPv6 (dual) tests.
174 headers = {};
175 headers["X-Forwarded-For"] = "2001:db8:3333:4444:5555:6666:1.2.3.4";
176 rpcRes = env.rpc(headers, "ping")["result"];
177 BEAST_EXPECT(rpcRes["role"] == "proxied");
178 BEAST_EXPECT(rpcRes["ip"] == "2001:db8:3333:4444:5555:6666:1.2.3.4");
179 BEAST_EXPECT(isValidIpAddress(rpcRes["ip"].asString()));
180
181 headers["X-Forwarded-For"] =
182 "2001:db8:3333:4444:5555:6666:5.6.7.8, a:b:c:d:e:f, "
183 "g:h:i:j:k:l";
184 rpcRes = env.rpc(headers, "ping")["result"];
185 BEAST_EXPECT(rpcRes["role"] == "proxied");
186 BEAST_EXPECT(rpcRes["ip"] == "2001:db8:3333:4444:5555:6666:5.6.7.8");
187 BEAST_EXPECT(isValidIpAddress(rpcRes["ip"].asString()));
188
189 headers["X-Forwarded-For"] = "[2001:db8:3333:4444:5555:6666:9.10.11.12]";
190 rpcRes = env.rpc(headers, "ping")["result"];
191 BEAST_EXPECT(rpcRes["role"] == "proxied");
192 BEAST_EXPECT(rpcRes["ip"] == "2001:db8:3333:4444:5555:6666:9.10.11.12");
193 BEAST_EXPECT(isValidIpAddress(rpcRes["ip"].asString()));
194
195 headers["X-Forwarded-For"] =
196 "[2001:db8:3333:4444:5555:6666:13.14.15.16], [a:b:c:d:e:f], "
197 "[g:h:i:j:k:l]";
198 rpcRes = env.rpc(headers, "ping")["result"];
199 BEAST_EXPECT(rpcRes["role"] == "proxied");
200 BEAST_EXPECT(rpcRes["ip"] == "2001:db8:3333:4444:5555:6666:13.14.15.16");
201 BEAST_EXPECT(isValidIpAddress(rpcRes["ip"].asString()));
202
203 headers = {};
204 headers["Forwarded"] = "for=\"[2001:db8:3333:4444:5555:6666:20.19.18.17]\"";
205 rpcRes = env.rpc(headers, "ping")["result"];
206 BEAST_EXPECT(rpcRes["role"] == "proxied");
207 BEAST_EXPECT(rpcRes["ip"] == "2001:db8:3333:4444:5555:6666:20.19.18.17");
208 BEAST_EXPECT(isValidIpAddress(rpcRes["ip"].asString()));
209
210 headers["Forwarded"] = "For=\"[2001:db8:bb:cc::24.23.22.21]\", for=99.00.11.22";
211 rpcRes = env.rpc(headers, "ping")["result"];
212 BEAST_EXPECT(rpcRes["role"] == "proxied");
213 BEAST_EXPECT(rpcRes["ip"] == "2001:db8:bb:cc::24.23.22.21");
214 BEAST_EXPECT(isValidIpAddress(rpcRes["ip"].asString()));
215
216 headers["Forwarded"] =
217 "proto=http;FOR=\"[::11:22:33:44:45.55.65.75]:234\""
218 ";by=203.0.113.43";
219 rpcRes = env.rpc(headers, "ping")["result"];
220 BEAST_EXPECT(rpcRes["role"] == "proxied");
221 BEAST_EXPECT(rpcRes["ip"] == "::11:22:33:44:45.55.65.75");
222 BEAST_EXPECT(isValidIpAddress(rpcRes["ip"].asString()));
223 }
224
225 {
226 Env env{*this, envconfig(admin_localnet)};
227 BEAST_EXPECT(env.rpc("ping")["result"]["role"] == "admin");
228 BEAST_EXPECT(makeWSClient(env.app().config())->invoke("ping")["result"]["unlimited"].asBool());
229 }
230
231 {
233 BEAST_EXPECT(env.rpc("ping")["result"]["role"] == "proxied");
234 auto wsRes = makeWSClient(env.app().config())->invoke("ping")["result"];
235 BEAST_EXPECT(!wsRes.isMember("unlimited") || !wsRes["unlimited"].asBool());
236
238 headers["X-Forwarded-For"] = "12.34.56.78";
239 Json::Value rpcRes = env.rpc(headers, "ping")["result"];
240 BEAST_EXPECT(rpcRes["role"] == "proxied");
241 BEAST_EXPECT(rpcRes["ip"] == "12.34.56.78");
242 BEAST_EXPECT(isValidIpAddress(rpcRes["ip"].asString()));
243 }
244 }
245
246 void
248 {
249 using namespace test::jtx;
250
251 {
252 Env env(*this);
253
255 Json::Value rpcRes;
256
257 // No "for=" in Forwarded.
258 headers["Forwarded"] = "for 88.77.66.55";
259 rpcRes = env.rpc(headers, "ping")["result"];
260 BEAST_EXPECT(rpcRes["role"] == "admin");
261 BEAST_EXPECT(!rpcRes.isMember("ip"));
262
263 headers["Forwarded"] = "by=88.77.66.55";
264 rpcRes = env.rpc(headers, "ping")["result"];
265 BEAST_EXPECT(rpcRes["role"] == "admin");
266 BEAST_EXPECT(!rpcRes.isMember("ip"));
267
268 // Empty field.
269 headers = {};
270 headers["Forwarded"] = "for=";
271 rpcRes = env.rpc(headers, "ping")["result"];
272 BEAST_EXPECT(rpcRes["role"] == "admin");
273 BEAST_EXPECT(!rpcRes.isMember("ip"));
274
275 headers = {};
276 headers["X-Forwarded-For"] = " ";
277 rpcRes = env.rpc(headers, "ping")["result"];
278 BEAST_EXPECT(rpcRes["role"] == "admin");
279 BEAST_EXPECT(!rpcRes.isMember("ip"));
280
281 // Empty quotes.
282 headers = {};
283 headers["Forwarded"] = "for= \" \" ";
284 rpcRes = env.rpc(headers, "ping")["result"];
285 BEAST_EXPECT(rpcRes["role"] == "admin");
286 BEAST_EXPECT(!rpcRes.isMember("ip"));
287
288 headers = {};
289 headers["X-Forwarded-For"] = "\"\"";
290 rpcRes = env.rpc(headers, "ping")["result"];
291 BEAST_EXPECT(rpcRes["role"] == "admin");
292 BEAST_EXPECT(!rpcRes.isMember("ip"));
293
294 // Unbalanced outer quotes.
295 headers = {};
296 headers["X-Forwarded-For"] = "\"12.34.56.78 ";
297 rpcRes = env.rpc(headers, "ping")["result"];
298 BEAST_EXPECT(rpcRes["role"] == "admin");
299 BEAST_EXPECT(!rpcRes.isMember("ip"));
300
301 headers["X-Forwarded-For"] = "12.34.56.78\"";
302 rpcRes = env.rpc(headers, "ping")["result"];
303 BEAST_EXPECT(rpcRes["role"] == "admin");
304 BEAST_EXPECT(!rpcRes.isMember("ip"));
305
306 // Unbalanced square brackets for IPv6.
307 headers = {};
308 headers["Forwarded"] = "FOR=[2001:db8:bb:cc::";
309 rpcRes = env.rpc(headers, "ping")["result"];
310 BEAST_EXPECT(rpcRes["role"] == "admin");
311 BEAST_EXPECT(!rpcRes.isMember("ip"));
312
313 headers = {};
314 headers["X-Forwarded-For"] = "2001:db8:bb:cc::24.23.22.21]";
315 rpcRes = env.rpc(headers, "ping")["result"];
316 BEAST_EXPECT(rpcRes["role"] == "admin");
317 BEAST_EXPECT(!rpcRes.isMember("ip"));
318
319 // Empty square brackets.
320 headers = {};
321 headers["Forwarded"] = "FOR=[]";
322 rpcRes = env.rpc(headers, "ping")["result"];
323 BEAST_EXPECT(rpcRes["role"] == "admin");
324 BEAST_EXPECT(!rpcRes.isMember("ip"));
325
326 headers = {};
327 headers["X-Forwarded-For"] = "\" [ ] \"";
328 rpcRes = env.rpc(headers, "ping")["result"];
329 BEAST_EXPECT(rpcRes["role"] == "admin");
330 BEAST_EXPECT(!rpcRes.isMember("ip"));
331 }
332 }
333
334public:
335 void
336 run() override
337 {
338 testRoles();
340 }
341};
342
343BEAST_DEFINE_TESTSUITE(Roles, rpc, xrpl);
344
345} // namespace test
346
347} // namespace xrpl
Represents a JSON value.
Definition json_value.h:130
bool isMember(char const *key) const
Return true if the object has a member named key.
A testsuite class.
Definition suite.h:51
virtual Config & config()=0
bool isValidIpAddress(std::string const &addr)
void run() override
Runs the suite.
A transaction testing environment.
Definition Env.h:119
Application & app()
Definition Env.h:251
Json::Value rpc(unsigned apiVersion, std::unordered_map< std::string, std::string > const &headers, std::string const &cmd, Args &&... args)
Execute an RPC command.
Definition Env.h:792
Set the expected result code for a JTx The test will fail if the code doesn't match.
Definition rpc.h:15
std::unique_ptr< Config > secure_gateway(std::unique_ptr< Config >)
Definition envconfig.cpp:65
std::unique_ptr< Config > admin_localnet(std::unique_ptr< Config >)
Definition envconfig.cpp:74
std::unique_ptr< Config > envconfig()
creates and initializes a default configuration for jtx::Env
Definition envconfig.h:34
std::unique_ptr< Config > secure_gateway_localnet(std::unique_ptr< Config >)
Definition envconfig.cpp:82
std::unique_ptr< Config > no_admin(std::unique_ptr< Config >)
adjust config so no admin ports are enabled
Definition envconfig.cpp:57
std::unique_ptr< WSClient > makeWSClient(Config const &cfg, bool v2, unsigned rpc_version, std::unordered_map< std::string, std::string > const &headers)
Returns a client operating through WebSockets/S.
Definition WSClient.cpp:285
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:5