OpenVPN 3 Core Library
Loading...
Searching...
No Matches
test_optfilt.cpp
Go to the documentation of this file.
1// OpenVPN -- An application to securely tunnel IP networks
2// over a single port, with support for SSL/TLS-based
3// session authentication and key exchange,
4// packet encryption, packet authentication, and
5// packet compression.
6//
7// Copyright (C) 2012- OpenVPN Inc.
8//
9// SPDX-License-Identifier: MPL-2.0 OR AGPL-3.0-only WITH openvpn3-openssl-exception
10//
11
12
13#include "test_common.hpp"
14
16
17using namespace openvpn;
18
19const std::string nopull_options(
20 "ip-win32\n"
21 "tap-sleep\n"
22 "block-ipv6\n"
23 "client-nat\n"
24 "register-dns\n"
25
26 "dhcp-renew\n"
27 "dhcp-option\n"
28 "dhcp-release\n"
29 "dhcp-pre-release\n"
30
31 "route 1.2.3.4\n"
32 "route 192.168.0.0 255.255.255.0\n"
33 "route 10.0.0.0 255.0.0.0\n"
34 "route-ipv6\n"
35 "route-delay\n"
36 "route-metric\n"
37 "route-method\n"
38
39 "redirect-gateway\n"
40 "redirect-private\n");
41
42const std::string pull_filter_options(
43 "option1 arg1\n"
44 "option1 arg2\n"
45 "option2 \"arg with space\"\n"
46 "option2 \"arg with more space\"\n"
47 "option3 arg1 arg2\n"
48 "option3 arg1 arg2\n"
49 "option10 something else\n");
50
51TEST(PushedOptionsFilter, RouteNopullEnabled)
52{
53 OptionList cfg;
54 cfg.parse_from_config("route-nopull", nullptr);
55 cfg.update_map();
56
57 PushedOptionsFilter route_nopull_enabled(cfg);
58 const std::string extra_option("unfiltered-option");
59
60 OptionList src;
61 OptionList dst;
62
64 src.parse_from_config(nopull_options + extra_option, nullptr);
65 dst.extend(src, &route_nopull_enabled);
66 std::string filter_output(testLog->stopCollecting());
67
68 ASSERT_EQ(1u, dst.size())
69 << "Too few options have been filtered by --route-nopull" << std::endl
70 << filter_output;
71
72 dst.update_map();
73 ASSERT_TRUE(dst.exists(extra_option))
74 << "The wrong options have been filtered by --route-nopull:" << std::endl
75 << "expected: " << extra_option << " got: " << dst[0].ref(0) << std::endl
76 << filter_output;
77}
78
79TEST(PushedOptionsFilter, RouteNopullDisabled)
80{
81 OptionList cfg;
82
83 PushedOptionsFilter route_nopull_disabled(cfg);
84 const std::string extra_option("unfiltered-option");
85
86 OptionList src;
87 OptionList dst;
88
90 src.parse_from_config(nopull_options + extra_option, nullptr);
91 dst.extend(src, &route_nopull_disabled);
92 std::string filter_output(testLog->stopCollecting());
93
94 ASSERT_EQ(src.size(), dst.size())
95 << "Too many options have been filtered by --route-nopull" << std::endl
96 << filter_output;
97}
98
99TEST(PushedOptionsFilter, PullFilterAcceptAll)
100{
101 OptionList cfg;
102 cfg.parse_from_config("pull-filter accept option", nullptr);
103 cfg.update_map();
104
105 PushedOptionsFilter filter_none(cfg);
106
107 OptionList src;
108 OptionList dst;
109
112 dst.extend(src, &filter_none);
113 std::string filter_output(testLog->stopCollecting());
114
115 ASSERT_EQ(src.size(), dst.size())
116 << "Not all options have been accepted by --pull-filter" << std::endl
117 << filter_output;
118}
119
120TEST(PushedOptionsFilter, PullFilterMalformedAction)
121{
122 OptionList cfg;
123 cfg.parse_from_config("pull-filter myaction match", nullptr);
124 cfg.update_map();
125
126 ASSERT_THROW(PushedOptionsFilter x(cfg), option_error);
127}
128
129TEST(PushedOptionsFilter, PullFilterMalformedShort)
130{
131 OptionList cfg;
132 cfg.parse_from_config("pull-filter ignore", nullptr);
133 cfg.update_map();
134
135 ASSERT_THROW(PushedOptionsFilter x(cfg), option_error);
136}
137
138TEST(PushedOptionsFilter, PullFilterMalformedLong)
139{
140 OptionList cfg;
141 cfg.parse_from_config("pull-filter ignore one two", nullptr);
142 cfg.update_map();
143
144 ASSERT_THROW(PushedOptionsFilter x(cfg), option_error);
145}
146
147TEST(PushedOptionsFilter, PullFilterSingleQuote)
148{
149 OptionList cfg;
150 cfg.parse_from_config("pull-filter ignore 'route 1.2.3.4'", nullptr);
151 cfg.update_map();
152 PushedOptionsFilter filter(cfg);
153
154 OptionList src;
155 OptionList dst;
156
157 dst.extend(src, &filter);
158
160 src.parse_from_config("route 1.1.1.1\nroute 2.2.2.2\nroute 1.2.3.4", nullptr);
161 dst.extend(src, &filter);
162 std::string filter_output(testLog->stopCollecting());
163
164 ASSERT_EQ(2u, dst.size())
165 << "Too many options have been accepted by --pull-filter" << std::endl
166 << filter_output;
167}
168
169TEST(PushedOptionsFilter, PullFilterMisplacedQuote)
170{
171 OptionList cfg;
172 cfg.parse_from_config("pull-filter ignore 'a b' c", nullptr);
173 cfg.update_map();
174
175 ASSERT_THROW(PushedOptionsFilter x(cfg), option_error);
176}
177
178TEST(PushedOptionsFilter, PullFilterIgnoreAll)
179{
180 OptionList cfg;
181 cfg.parse_from_config("pull-filter ignore option", nullptr);
182 cfg.update_map();
183
184 PushedOptionsFilter filter_all(cfg);
185
186 OptionList src;
187 OptionList dst;
188
191 dst.extend(src, &filter_all);
192 std::string filter_output(testLog->stopCollecting());
193
194 ASSERT_EQ(0u, dst.size())
195 << "Not all options have been ignored by --pull-filter" << std::endl
196 << filter_output;
197}
198
199TEST(PushedOptionsFilter, PullFilterRejectOne)
200{
201 OptionList cfg;
202 cfg.parse_from_config("pull-filter reject option10", nullptr);
203 cfg.update_map();
204
205 PushedOptionsFilter reject_opt10(cfg);
206
207 OptionList src;
208 OptionList dst;
209
212 JY_EXPECT_THROW(dst.extend(src, &reject_opt10), Option::RejectedException, "option10")
214}
215
216TEST(PushedOptionsFilter, PullFilterAcceptWhitespace)
217{
218 OptionList cfg;
220 "pull-filter accept \"option3 arg1 arg2\"\n"
221 "pull-filter ignore option",
222 nullptr);
223 cfg.update_map();
224
225 PushedOptionsFilter accept_opt3(cfg);
226
227 OptionList src;
228 OptionList dst;
229
232 dst.extend(src, &accept_opt3);
233 std::string filter_output(testLog->stopCollecting());
234
235 ASSERT_EQ(2u, dst.size())
236 << "Not all option3's have been accepted by --pull-filter" << std::endl
237 << filter_output;
238}
239
240TEST(PushedOptionsFilter, PullFilterIgnoreQuotedWhitespace)
241{
242 OptionList cfg;
244 "pull-filter accept \"option2 \\\"arg with space\\\"\"\n"
245 "pull-filter ignore option",
246 nullptr);
247 cfg.update_map();
248
249 PushedOptionsFilter accept_opt2_single_space(cfg);
250
251 OptionList src;
252 OptionList dst;
253
256 dst.extend(src, &accept_opt2_single_space);
257 std::string filter_output(testLog->stopCollecting());
258
259 ASSERT_EQ(1u, dst.size())
260 << "Too many options have been accepted by --pull-filter" << std::endl
261 << filter_output;
262
263 dst.update_map();
264 ASSERT_EQ(dst[0].ref(1), "arg with space")
265 << "Too many options have been accepted by --pull-filter" << std::endl
266 << filter_output;
267}
268
269TEST(PushedOptionsFilter, PullFilterOverrideRouteNopull)
270{
271 OptionList cfg;
273 "pull-filter ignore \"route 1.2.3.4\"\n"
274 "pull-filter ignore route-\n"
275 "route-nopull\n"
276 "pull-filter accept route\n",
277 nullptr);
278 cfg.update_map();
279
280 PushedOptionsFilter override_route_nopull(cfg);
281
282 OptionList src;
283 OptionList dst;
284
286 src.parse_from_config(nopull_options, nullptr);
287 dst.extend(src, &override_route_nopull);
288 std::string filter_output(testLog->stopCollecting());
289
290 ASSERT_EQ(2u, dst.size())
291 << "Expected two route option to be accepted" << std::endl
292 << filter_output;
293
294 dst.update_map();
295 ASSERT_EQ(dst[0].ref(0), "route")
296 << dst[0].ref(0) << " instead of route option has been accepted" << std::endl
297 << filter_output;
298 ASSERT_EQ(dst[1].ref(0), "route")
299 << dst[1].ref(0) << " instead of route option has been accepted" << std::endl
300 << filter_output;
301 ASSERT_EQ(3u, dst[0].size())
302 << "The host route option has been accepted, expected network route" << std::endl
303 << filter_output;
304 ASSERT_EQ(3u, dst[1].size())
305 << "The host route option has been accepted, expected network route" << std::endl
306 << filter_output;
307}
308
309TEST(PushedOptionsFilter, RejectDnsServerPrioNegative)
310{
311 OptionList cfg;
312 PushedOptionsFilter filter_static(cfg);
313
314 const std::string opt = "dns server -1 address ::1";
315
316 OptionList src;
317 OptionList dst;
318 src.parse_from_config(opt, nullptr);
319 src.update_map();
320
322 JY_EXPECT_THROW(dst.extend(src, &filter_static), option_error, opt)
323 std::string filter_output(testLog->stopCollecting());
324}
void parse_from_config(const std::string &str, Limits *lim)
Definition options.hpp:985
void extend(const OptionList &other, FilterBase *filt=nullptr)
Definition options.hpp:1123
bool exists(const std::string &name) const
Definition options.hpp:1325
openvpn::LogOutputCollector * testLog
#define JY_EXPECT_THROW
TEST(PushedOptionsFilter, RouteNopullEnabled)
const std::string pull_filter_options("option1 arg1\n" "option1 arg2\n" "option2 \"arg with space\"\n" "option2 \"arg with more space\"\n" "option3 arg1 arg2\n" "option3 arg1 arg2\n" "option10 something else\n")
const std::string nopull_options("ip-win32\n" "tap-sleep\n" "block-ipv6\n" "client-nat\n" "register-dns\n" "dhcp-renew\n" "dhcp-option\n" "dhcp-release\n" "dhcp-pre-release\n" "route 1.2.3.4\n" "route 192.168.0.0 255.255.255.0\n" "route 10.0.0.0 255.0.0.0\n" "route-ipv6\n" "route-delay\n" "route-metric\n" "route-method\n" "redirect-gateway\n" "redirect-private\n")