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