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