rippled
Loading...
Searching...
No Matches
Roles_test.cpp
1//------------------------------------------------------------------------------
2/*
3 This file is part of rippled: https://github.com/ripple/rippled
4 Copyright (c) 2019 Ripple Labs Inc.
5
6 Permission to use, copy, modify, and/or distribute this software for any
7 purpose with or without fee is hereby granted, provided that the above
8 copyright notice and this permission notice appear in all copies.
9
10 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17*/
18//==============================================================================
19
20#include <test/jtx.h>
21#include <test/jtx/WSClient.h>
22#include <xrpl/beast/unit_test.h>
23
24#include <string>
25#include <unordered_map>
26
27namespace ripple {
28
29namespace test {
30
32{
33 bool
35 {
36 boost::system::error_code ec;
37 boost::asio::ip::make_address(addr, ec);
38 return !ec.failed();
39 }
40
41 void
43 {
44 using namespace test::jtx;
45
46 {
47 Env env(*this);
48
49 BEAST_EXPECT(env.rpc("ping")["result"]["role"] == "admin");
50 BEAST_EXPECT(makeWSClient(env.app().config())
51 ->invoke("ping")["result"]["unlimited"]
52 .asBool());
53 }
54 {
55 Env env{*this, envconfig(no_admin)};
56
57 BEAST_EXPECT(!env.rpc("ping")["result"].isMember("role"));
58 auto wsRes =
59 makeWSClient(env.app().config())->invoke("ping")["result"];
60 BEAST_EXPECT(
61 !wsRes.isMember("unlimited") || !wsRes["unlimited"].asBool());
62 }
63 {
64 Env env{*this, envconfig(secure_gateway)};
65
66 BEAST_EXPECT(env.rpc("ping")["result"]["role"] == "proxied");
67 auto wsRes =
68 makeWSClient(env.app().config())->invoke("ping")["result"];
69 BEAST_EXPECT(
70 !wsRes.isMember("unlimited") || !wsRes["unlimited"].asBool());
71
73 Json::Value rpcRes;
74
75 // IPv4 tests.
76 headers["X-Forwarded-For"] = "12.34.56.78";
77 rpcRes = env.rpc(headers, "ping")["result"];
78 BEAST_EXPECT(rpcRes["role"] == "proxied");
79 BEAST_EXPECT(rpcRes["ip"] == "12.34.56.78");
80 BEAST_EXPECT(isValidIpAddress(rpcRes["ip"].asString()));
81
82 headers["X-Forwarded-For"] = "87.65.43.21, 44.33.22.11";
83 rpcRes = env.rpc(headers, "ping")["result"];
84 BEAST_EXPECT(rpcRes["ip"] == "87.65.43.21");
85 BEAST_EXPECT(isValidIpAddress(rpcRes["ip"].asString()));
86
87 headers["X-Forwarded-For"] = "87.65.43.21:47011, 44.33.22.11";
88 rpcRes = env.rpc(headers, "ping")["result"];
89 BEAST_EXPECT(rpcRes["ip"] == "87.65.43.21");
90 BEAST_EXPECT(isValidIpAddress(rpcRes["ip"].asString()));
91
92 headers = {};
93 headers["Forwarded"] = "for=88.77.66.55";
94 rpcRes = env.rpc(headers, "ping")["result"];
95 BEAST_EXPECT(rpcRes["ip"] == "88.77.66.55");
96 BEAST_EXPECT(isValidIpAddress(rpcRes["ip"].asString()));
97
98 headers["Forwarded"] =
99 "what=where;for=55.66.77.88;for=nobody;"
100 "who=3";
101 rpcRes = env.rpc(headers, "ping")["result"];
102 BEAST_EXPECT(rpcRes["ip"] == "55.66.77.88");
103 BEAST_EXPECT(isValidIpAddress(rpcRes["ip"].asString()));
104
105 headers["Forwarded"] =
106 "what=where; for=55.66.77.88, for=99.00.11.22;"
107 "who=3";
108 rpcRes = env.rpc(headers, "ping")["result"];
109 BEAST_EXPECT(rpcRes["ip"] == "55.66.77.88");
110 BEAST_EXPECT(isValidIpAddress(rpcRes["ip"].asString()));
111
112 headers["Forwarded"] =
113 "what=where; For=99.88.77.66, for=55.66.77.88;"
114 "who=3";
115 rpcRes = env.rpc(headers, "ping")["result"];
116 BEAST_EXPECT(rpcRes["ip"] == "99.88.77.66");
117 BEAST_EXPECT(isValidIpAddress(rpcRes["ip"].asString()));
118
119 headers["Forwarded"] =
120 "what=where; for=\"55.66.77.88:47011\";"
121 "who=3";
122 rpcRes = env.rpc(headers, "ping")["result"];
123 BEAST_EXPECT(rpcRes["ip"] == "55.66.77.88");
124 BEAST_EXPECT(isValidIpAddress(rpcRes["ip"].asString()));
125
126 headers["Forwarded"] =
127 "what=where; For= \" 99.88.77.66 \" ,for=11.22.33.44;"
128 "who=3";
129 rpcRes = env.rpc(headers, "ping")["result"];
130 BEAST_EXPECT(rpcRes["ip"] == "99.88.77.66");
131 BEAST_EXPECT(isValidIpAddress(rpcRes["ip"].asString()));
132
133 wsRes = makeWSClient(env.app().config(), true, 2, headers)
134 ->invoke("ping")["result"];
135 BEAST_EXPECT(
136 !wsRes.isMember("unlimited") || !wsRes["unlimited"].asBool());
137
138 std::string const name = "xrposhi";
139 headers["X-User"] = name;
140 rpcRes = env.rpc(headers, "ping")["result"];
141 BEAST_EXPECT(rpcRes["role"] == "identified");
142 BEAST_EXPECT(rpcRes["username"] == name);
143 BEAST_EXPECT(rpcRes["ip"] == "99.88.77.66");
144 BEAST_EXPECT(isValidIpAddress(rpcRes["ip"].asString()));
145 wsRes = makeWSClient(env.app().config(), true, 2, headers)
146 ->invoke("ping")["result"];
147 BEAST_EXPECT(wsRes["unlimited"].asBool());
148
149 // IPv6 tests.
150 headers = {};
151 headers["X-Forwarded-For"] =
152 "2001:db8:3333:4444:5555:6666:7777:8888";
153 rpcRes = env.rpc(headers, "ping")["result"];
154 BEAST_EXPECT(rpcRes["role"] == "proxied");
155 BEAST_EXPECT(
156 rpcRes["ip"] == "2001:db8:3333:4444:5555:6666:7777:8888");
157 BEAST_EXPECT(isValidIpAddress(rpcRes["ip"].asString()));
158
159 headers["X-Forwarded-For"] =
160 "2001:db8:3333:4444:5555:6666:7777:9999, a:b:c:d:e:f, "
161 "g:h:i:j:k:l";
162 rpcRes = env.rpc(headers, "ping")["result"];
163 BEAST_EXPECT(rpcRes["role"] == "proxied");
164 BEAST_EXPECT(
165 rpcRes["ip"] == "2001:db8:3333:4444:5555:6666:7777:9999");
166 BEAST_EXPECT(isValidIpAddress(rpcRes["ip"].asString()));
167
168 headers["X-Forwarded-For"] =
169 "[2001:db8:3333:4444:5555:6666:7777:8888]";
170 rpcRes = env.rpc(headers, "ping")["result"];
171 BEAST_EXPECT(rpcRes["role"] == "proxied");
172 BEAST_EXPECT(
173 rpcRes["ip"] == "2001:db8:3333:4444:5555:6666:7777:8888");
174 BEAST_EXPECT(isValidIpAddress(rpcRes["ip"].asString()));
175
176 headers["X-Forwarded-For"] =
177 "[2001:db8:3333:4444:5555:6666:7777:9999], [a:b:c:d:e:f], "
178 "[g:h:i:j:k:l]";
179 rpcRes = env.rpc(headers, "ping")["result"];
180 BEAST_EXPECT(rpcRes["role"] == "proxied");
181 BEAST_EXPECT(
182 rpcRes["ip"] == "2001:db8:3333:4444:5555:6666:7777:9999");
183 BEAST_EXPECT(isValidIpAddress(rpcRes["ip"].asString()));
184
185 headers = {};
186 headers["Forwarded"] =
187 "for=\"[2001:db8:3333:4444:5555:6666:7777:aaaa]\"";
188 rpcRes = env.rpc(headers, "ping")["result"];
189 BEAST_EXPECT(rpcRes["role"] == "proxied");
190 BEAST_EXPECT(
191 rpcRes["ip"] == "2001:db8:3333:4444:5555:6666:7777:aaaa");
192 BEAST_EXPECT(isValidIpAddress(rpcRes["ip"].asString()));
193
194 headers["Forwarded"] =
195 "For=\"[2001:db8:bb:cc:dd:ee:ff::]:2345\", for=99.00.11.22";
196 rpcRes = env.rpc(headers, "ping")["result"];
197 BEAST_EXPECT(rpcRes["role"] == "proxied");
198 BEAST_EXPECT(rpcRes["ip"] == "2001:db8:bb:cc:dd:ee:ff::");
199 BEAST_EXPECT(isValidIpAddress(rpcRes["ip"].asString()));
200
201 headers["Forwarded"] =
202 "proto=http;FOR=\"[2001:db8:11:22:33:44:55:66]\""
203 ";by=203.0.113.43";
204 rpcRes = env.rpc(headers, "ping")["result"];
205 BEAST_EXPECT(rpcRes["role"] == "proxied");
206 BEAST_EXPECT(rpcRes["ip"] == "2001:db8:11:22:33:44:55:66");
207 BEAST_EXPECT(isValidIpAddress(rpcRes["ip"].asString()));
208
209 // IPv6 (dual) tests.
210 headers = {};
211 headers["X-Forwarded-For"] = "2001:db8:3333:4444:5555:6666:1.2.3.4";
212 rpcRes = env.rpc(headers, "ping")["result"];
213 BEAST_EXPECT(rpcRes["role"] == "proxied");
214 BEAST_EXPECT(
215 rpcRes["ip"] == "2001:db8:3333:4444:5555:6666:1.2.3.4");
216 BEAST_EXPECT(isValidIpAddress(rpcRes["ip"].asString()));
217
218 headers["X-Forwarded-For"] =
219 "2001:db8:3333:4444:5555:6666:5.6.7.8, a:b:c:d:e:f, "
220 "g:h:i:j:k:l";
221 rpcRes = env.rpc(headers, "ping")["result"];
222 BEAST_EXPECT(rpcRes["role"] == "proxied");
223 BEAST_EXPECT(
224 rpcRes["ip"] == "2001:db8:3333:4444:5555:6666:5.6.7.8");
225 BEAST_EXPECT(isValidIpAddress(rpcRes["ip"].asString()));
226
227 headers["X-Forwarded-For"] =
228 "[2001:db8:3333:4444:5555:6666:9.10.11.12]";
229 rpcRes = env.rpc(headers, "ping")["result"];
230 BEAST_EXPECT(rpcRes["role"] == "proxied");
231 BEAST_EXPECT(
232 rpcRes["ip"] == "2001:db8:3333:4444:5555:6666:9.10.11.12");
233 BEAST_EXPECT(isValidIpAddress(rpcRes["ip"].asString()));
234
235 headers["X-Forwarded-For"] =
236 "[2001:db8:3333:4444:5555:6666:13.14.15.16], [a:b:c:d:e:f], "
237 "[g:h:i:j:k:l]";
238 rpcRes = env.rpc(headers, "ping")["result"];
239 BEAST_EXPECT(rpcRes["role"] == "proxied");
240 BEAST_EXPECT(
241 rpcRes["ip"] == "2001:db8:3333:4444:5555:6666:13.14.15.16");
242 BEAST_EXPECT(isValidIpAddress(rpcRes["ip"].asString()));
243
244 headers = {};
245 headers["Forwarded"] =
246 "for=\"[2001:db8:3333:4444:5555:6666:20.19.18.17]\"";
247 rpcRes = env.rpc(headers, "ping")["result"];
248 BEAST_EXPECT(rpcRes["role"] == "proxied");
249 BEAST_EXPECT(
250 rpcRes["ip"] == "2001:db8:3333:4444:5555:6666:20.19.18.17");
251 BEAST_EXPECT(isValidIpAddress(rpcRes["ip"].asString()));
252
253 headers["Forwarded"] =
254 "For=\"[2001:db8:bb:cc::24.23.22.21]\", for=99.00.11.22";
255 rpcRes = env.rpc(headers, "ping")["result"];
256 BEAST_EXPECT(rpcRes["role"] == "proxied");
257 BEAST_EXPECT(rpcRes["ip"] == "2001:db8:bb:cc::24.23.22.21");
258 BEAST_EXPECT(isValidIpAddress(rpcRes["ip"].asString()));
259
260 headers["Forwarded"] =
261 "proto=http;FOR=\"[::11:22:33:44:45.55.65.75]:234\""
262 ";by=203.0.113.43";
263 rpcRes = env.rpc(headers, "ping")["result"];
264 BEAST_EXPECT(rpcRes["role"] == "proxied");
265 BEAST_EXPECT(rpcRes["ip"] == "::11:22:33:44:45.55.65.75");
266 BEAST_EXPECT(isValidIpAddress(rpcRes["ip"].asString()));
267 }
268
269 {
270 Env env{*this, envconfig(admin_localnet)};
271 BEAST_EXPECT(env.rpc("ping")["result"]["role"] == "admin");
272 BEAST_EXPECT(makeWSClient(env.app().config())
273 ->invoke("ping")["result"]["unlimited"]
274 .asBool());
275 }
276
277 {
279 BEAST_EXPECT(env.rpc("ping")["result"]["role"] == "proxied");
280 auto wsRes =
281 makeWSClient(env.app().config())->invoke("ping")["result"];
282 BEAST_EXPECT(
283 !wsRes.isMember("unlimited") || !wsRes["unlimited"].asBool());
284
286 headers["X-Forwarded-For"] = "12.34.56.78";
287 Json::Value rpcRes = env.rpc(headers, "ping")["result"];
288 BEAST_EXPECT(rpcRes["role"] == "proxied");
289 BEAST_EXPECT(rpcRes["ip"] == "12.34.56.78");
290 BEAST_EXPECT(isValidIpAddress(rpcRes["ip"].asString()));
291 }
292 }
293
294 void
296 {
297 using namespace test::jtx;
298
299 {
300 Env env(*this);
301
303 Json::Value rpcRes;
304
305 // No "for=" in Forwarded.
306 headers["Forwarded"] = "for 88.77.66.55";
307 rpcRes = env.rpc(headers, "ping")["result"];
308 BEAST_EXPECT(rpcRes["role"] == "admin");
309 BEAST_EXPECT(!rpcRes.isMember("ip"));
310
311 headers["Forwarded"] = "by=88.77.66.55";
312 rpcRes = env.rpc(headers, "ping")["result"];
313 BEAST_EXPECT(rpcRes["role"] == "admin");
314 BEAST_EXPECT(!rpcRes.isMember("ip"));
315
316 // Empty field.
317 headers = {};
318 headers["Forwarded"] = "for=";
319 rpcRes = env.rpc(headers, "ping")["result"];
320 BEAST_EXPECT(rpcRes["role"] == "admin");
321 BEAST_EXPECT(!rpcRes.isMember("ip"));
322
323 headers = {};
324 headers["X-Forwarded-For"] = " ";
325 rpcRes = env.rpc(headers, "ping")["result"];
326 BEAST_EXPECT(rpcRes["role"] == "admin");
327 BEAST_EXPECT(!rpcRes.isMember("ip"));
328
329 // Empty quotes.
330 headers = {};
331 headers["Forwarded"] = "for= \" \" ";
332 rpcRes = env.rpc(headers, "ping")["result"];
333 BEAST_EXPECT(rpcRes["role"] == "admin");
334 BEAST_EXPECT(!rpcRes.isMember("ip"));
335
336 headers = {};
337 headers["X-Forwarded-For"] = "\"\"";
338 rpcRes = env.rpc(headers, "ping")["result"];
339 BEAST_EXPECT(rpcRes["role"] == "admin");
340 BEAST_EXPECT(!rpcRes.isMember("ip"));
341
342 // Unbalanced outer quotes.
343 headers = {};
344 headers["X-Forwarded-For"] = "\"12.34.56.78 ";
345 rpcRes = env.rpc(headers, "ping")["result"];
346 BEAST_EXPECT(rpcRes["role"] == "admin");
347 BEAST_EXPECT(!rpcRes.isMember("ip"));
348
349 headers["X-Forwarded-For"] = "12.34.56.78\"";
350 rpcRes = env.rpc(headers, "ping")["result"];
351 BEAST_EXPECT(rpcRes["role"] == "admin");
352 BEAST_EXPECT(!rpcRes.isMember("ip"));
353
354 // Unbalanced square brackets for IPv6.
355 headers = {};
356 headers["Forwarded"] = "FOR=[2001:db8:bb:cc::";
357 rpcRes = env.rpc(headers, "ping")["result"];
358 BEAST_EXPECT(rpcRes["role"] == "admin");
359 BEAST_EXPECT(!rpcRes.isMember("ip"));
360
361 headers = {};
362 headers["X-Forwarded-For"] = "2001:db8:bb:cc::24.23.22.21]";
363 rpcRes = env.rpc(headers, "ping")["result"];
364 BEAST_EXPECT(rpcRes["role"] == "admin");
365 BEAST_EXPECT(!rpcRes.isMember("ip"));
366
367 // Empty square brackets.
368 headers = {};
369 headers["Forwarded"] = "FOR=[]";
370 rpcRes = env.rpc(headers, "ping")["result"];
371 BEAST_EXPECT(rpcRes["role"] == "admin");
372 BEAST_EXPECT(!rpcRes.isMember("ip"));
373
374 headers = {};
375 headers["X-Forwarded-For"] = "\" [ ] \"";
376 rpcRes = env.rpc(headers, "ping")["result"];
377 BEAST_EXPECT(rpcRes["role"] == "admin");
378 BEAST_EXPECT(!rpcRes.isMember("ip"));
379 }
380 }
381
382public:
383 void
384 run() override
385 {
386 testRoles();
388 }
389};
390
391BEAST_DEFINE_TESTSUITE(Roles, app, ripple);
392
393} // namespace test
394
395} // namespace ripple
Represents a JSON value.
Definition: json_value.h:148
bool isMember(const char *key) const
Return true if the object has a member named key.
Definition: json_value.cpp:949
A testsuite class.
Definition: suite.h:55
virtual Config & config()=0
bool isValidIpAddress(std::string const &addr)
Definition: Roles_test.cpp:34
void run() override
Runs the suite.
Definition: Roles_test.cpp:384
A transaction testing environment.
Definition: Env.h:118
Application & app()
Definition: Env.h:256
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:765
std::unique_ptr< Config > admin_localnet(std::unique_ptr< Config >)
Definition: envconfig.cpp:92
std::unique_ptr< Config > secure_gateway(std::unique_ptr< Config >)
Definition: envconfig.cpp:83
std::unique_ptr< Config > no_admin(std::unique_ptr< Config >)
adjust config so no admin ports are enabled
Definition: envconfig.cpp:75
std::unique_ptr< Config > envconfig()
creates and initializes a default configuration for jtx::Env
Definition: envconfig.h:54
std::unique_ptr< Config > secure_gateway_localnet(std::unique_ptr< Config >)
Definition: envconfig.cpp:100
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:301
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: algorithm.h:26