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