1 // Copyright 2014 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "iptables.h"
16
17 #include <gtest/gtest.h>
18
19 #include "mock_iptables.h"
20
21 namespace {
22 #if defined(__ANDROID__)
23 const char kIpTablesPath[] = "/system/bin/iptables";
24 const char kIp6TablesPath[] = "/system/bin/ip6tables";
25 #else
26 const char kIpTablesPath[] = "/sbin/iptables";
27 const char kIp6TablesPath[] = "/sbin/ip6tables";
28 #endif // __ANDROID__
29 } // namespace
30
31 namespace firewalld {
32
33 using testing::_;
34 using testing::Return;
35
36 class IpTablesTest : public testing::Test {
37 public:
38 IpTablesTest() = default;
39 ~IpTablesTest() override = default;
40
41 protected:
SetMockExpectations(MockIpTables * iptables,bool success)42 void SetMockExpectations(MockIpTables* iptables, bool success) {
43 EXPECT_CALL(*iptables, AddAcceptRule(_, _, _, _))
44 .WillRepeatedly(Return(success));
45 EXPECT_CALL(*iptables, DeleteAcceptRule(_, _, _, _))
46 .WillRepeatedly(Return(success));
47 }
48
SetMockExpectationsPerExecutable(MockIpTables * iptables,bool ip4_success,bool ip6_success)49 void SetMockExpectationsPerExecutable(MockIpTables* iptables,
50 bool ip4_success,
51 bool ip6_success) {
52 EXPECT_CALL(*iptables, AddAcceptRule(kIpTablesPath, _, _, _))
53 .WillRepeatedly(Return(ip4_success));
54 EXPECT_CALL(*iptables, AddAcceptRule(kIp6TablesPath, _, _, _))
55 .WillRepeatedly(Return(ip6_success));
56 EXPECT_CALL(*iptables, DeleteAcceptRule(kIpTablesPath, _, _, _))
57 .WillRepeatedly(Return(ip4_success));
58 EXPECT_CALL(*iptables, DeleteAcceptRule(kIp6TablesPath, _, _, _))
59 .WillRepeatedly(Return(ip6_success));
60 }
61
62 private:
63 DISALLOW_COPY_AND_ASSIGN(IpTablesTest);
64 };
65
TEST_F(IpTablesTest,Port0Fails)66 TEST_F(IpTablesTest, Port0Fails) {
67 MockIpTables mock_iptables;
68 // We should not be adding any rules for port 0.
69 EXPECT_CALL(mock_iptables, AddAcceptRule(_, _, _, _)).Times(0);
70 EXPECT_CALL(mock_iptables, DeleteAcceptRule(_, _, _, _)).Times(0);
71 // Try to punch hole for TCP port 0, port 0 is not a valid port.
72 EXPECT_FALSE(mock_iptables.PunchTcpHole(0, "iface"));
73 // Try to punch hole for UDP port 0, port 0 is not a valid port.
74 EXPECT_FALSE(mock_iptables.PunchUdpHole(0, "iface"));
75 }
76
TEST_F(IpTablesTest,ValidInterfaceName)77 TEST_F(IpTablesTest, ValidInterfaceName) {
78 MockIpTables mock_iptables;
79 SetMockExpectations(&mock_iptables, true /* success */);
80
81 EXPECT_TRUE(mock_iptables.PunchTcpHole(80, "shortname"));
82 EXPECT_TRUE(mock_iptables.PunchUdpHole(53, "shortname"));
83 EXPECT_TRUE(mock_iptables.PunchTcpHole(80, "middle-dash"));
84 EXPECT_TRUE(mock_iptables.PunchUdpHole(53, "middle-dash"));
85 EXPECT_TRUE(mock_iptables.PunchTcpHole(80, "middle.dot"));
86 EXPECT_TRUE(mock_iptables.PunchUdpHole(53, "middle.dot"));
87 }
88
TEST_F(IpTablesTest,InvalidInterfaceName)89 TEST_F(IpTablesTest, InvalidInterfaceName) {
90 MockIpTables mock_iptables;
91 // We should not be adding any rules for invalid interface names.
92 EXPECT_CALL(mock_iptables, AddAcceptRule(_, _, _, _)).Times(0);
93 EXPECT_CALL(mock_iptables, DeleteAcceptRule(_, _, _, _)).Times(0);
94
95 EXPECT_FALSE(mock_iptables.PunchTcpHole(80, "reallylonginterfacename"));
96 EXPECT_FALSE(mock_iptables.PunchTcpHole(80, "with spaces"));
97 EXPECT_FALSE(mock_iptables.PunchTcpHole(80, "with$ymbols"));
98 EXPECT_FALSE(mock_iptables.PunchTcpHole(80, "-startdash"));
99 EXPECT_FALSE(mock_iptables.PunchTcpHole(80, "enddash-"));
100 EXPECT_FALSE(mock_iptables.PunchTcpHole(80, ".startdot"));
101 EXPECT_FALSE(mock_iptables.PunchTcpHole(80, "enddot."));
102
103 EXPECT_FALSE(mock_iptables.PunchUdpHole(53, "reallylonginterfacename"));
104 EXPECT_FALSE(mock_iptables.PunchUdpHole(53, "with spaces"));
105 EXPECT_FALSE(mock_iptables.PunchUdpHole(53, "with$ymbols"));
106 EXPECT_FALSE(mock_iptables.PunchUdpHole(53, "-startdash"));
107 EXPECT_FALSE(mock_iptables.PunchUdpHole(53, "enddash-"));
108 EXPECT_FALSE(mock_iptables.PunchUdpHole(53, ".startdot"));
109 EXPECT_FALSE(mock_iptables.PunchUdpHole(53, "enddot."));
110 }
111
TEST_F(IpTablesTest,PunchTcpHoleSucceeds)112 TEST_F(IpTablesTest, PunchTcpHoleSucceeds) {
113 MockIpTables mock_iptables;
114 SetMockExpectations(&mock_iptables, true /* success */);
115
116 // Punch hole for TCP port 80, should succeed.
117 EXPECT_TRUE(mock_iptables.PunchTcpHole(80, "iface"));
118 // Punch again, should still succeed.
119 EXPECT_TRUE(mock_iptables.PunchTcpHole(80, "iface"));
120 // Plug the hole, should succeed.
121 EXPECT_TRUE(mock_iptables.PlugTcpHole(80, "iface"));
122 }
123
TEST_F(IpTablesTest,PlugTcpHoleSucceeds)124 TEST_F(IpTablesTest, PlugTcpHoleSucceeds) {
125 MockIpTables mock_iptables;
126 SetMockExpectations(&mock_iptables, true /* success */);
127
128 // Punch hole for TCP port 80, should succeed.
129 EXPECT_TRUE(mock_iptables.PunchTcpHole(80, "iface"));
130 // Plug the hole, should succeed.
131 EXPECT_TRUE(mock_iptables.PlugTcpHole(80, "iface"));
132 // Plug again, should fail.
133 EXPECT_FALSE(mock_iptables.PlugTcpHole(80, "iface"));
134 }
135
TEST_F(IpTablesTest,PunchUdpHoleSucceeds)136 TEST_F(IpTablesTest, PunchUdpHoleSucceeds) {
137 MockIpTables mock_iptables;
138 SetMockExpectations(&mock_iptables, true /* success */);
139
140 // Punch hole for UDP port 53, should succeed.
141 EXPECT_TRUE(mock_iptables.PunchUdpHole(53, "iface"));
142 // Punch again, should still succeed.
143 EXPECT_TRUE(mock_iptables.PunchUdpHole(53, "iface"));
144 // Plug the hole, should succeed.
145 EXPECT_TRUE(mock_iptables.PlugUdpHole(53, "iface"));
146 }
147
TEST_F(IpTablesTest,PlugUdpHoleSucceeds)148 TEST_F(IpTablesTest, PlugUdpHoleSucceeds) {
149 MockIpTables mock_iptables;
150 SetMockExpectations(&mock_iptables, true /* success */);
151
152 // Punch hole for UDP port 53, should succeed.
153 EXPECT_TRUE(mock_iptables.PunchUdpHole(53, "iface"));
154 // Plug the hole, should succeed.
155 EXPECT_TRUE(mock_iptables.PlugUdpHole(53, "iface"));
156 // Plug again, should fail.
157 EXPECT_FALSE(mock_iptables.PlugUdpHole(53, "iface"));
158 }
159
TEST_F(IpTablesTest,PunchTcpHoleFails)160 TEST_F(IpTablesTest, PunchTcpHoleFails) {
161 MockIpTables mock_iptables;
162 SetMockExpectations(&mock_iptables, false /* success */);
163 // Punch hole for TCP port 80, should fail.
164 ASSERT_FALSE(mock_iptables.PunchTcpHole(80, "iface"));
165 }
166
TEST_F(IpTablesTest,PunchUdpHoleFails)167 TEST_F(IpTablesTest, PunchUdpHoleFails) {
168 MockIpTables mock_iptables;
169 SetMockExpectations(&mock_iptables, false /* success */);
170 // Punch hole for UDP port 53, should fail.
171 ASSERT_FALSE(mock_iptables.PunchUdpHole(53, "iface"));
172 }
173
TEST_F(IpTablesTest,PunchTcpHoleIpv6Fails)174 TEST_F(IpTablesTest, PunchTcpHoleIpv6Fails) {
175 MockIpTables mock_iptables;
176 SetMockExpectationsPerExecutable(
177 &mock_iptables, true /* ip4_success */, false /* ip6_success */);
178 // Punch hole for TCP port 80, should fail because 'ip6tables' fails.
179 ASSERT_FALSE(mock_iptables.PunchTcpHole(80, "iface"));
180 }
181
TEST_F(IpTablesTest,PunchUdpHoleIpv6Fails)182 TEST_F(IpTablesTest, PunchUdpHoleIpv6Fails) {
183 MockIpTables mock_iptables;
184 SetMockExpectationsPerExecutable(
185 &mock_iptables, true /* ip4_success */, false /* ip6_success */);
186 // Punch hole for UDP port 53, should fail because 'ip6tables' fails.
187 ASSERT_FALSE(mock_iptables.PunchUdpHole(53, "iface"));
188 }
189
TEST_F(IpTablesTest,ApplyVpnSetupAdd_Success)190 TEST_F(IpTablesTest, ApplyVpnSetupAdd_Success) {
191 const std::vector<std::string> usernames = {"testuser0", "testuser1"};
192 const std::string interface = "ifc0";
193 const bool add = true;
194
195 MockIpTables mock_iptables;
196 EXPECT_CALL(mock_iptables, ApplyMasquerade(interface, add))
197 .WillOnce(Return(true));
198
199 EXPECT_CALL(mock_iptables, ApplyMarkForUserTraffic(usernames[0], add))
200 .WillOnce(Return(true));
201 EXPECT_CALL(mock_iptables, ApplyMarkForUserTraffic(usernames[1], add))
202 .WillOnce(Return(true));
203
204 EXPECT_CALL(mock_iptables, ApplyRuleForUserTraffic(add))
205 .WillOnce(Return(true));
206
207 ASSERT_TRUE(
208 mock_iptables.ApplyVpnSetup(usernames, interface, add));
209 }
210
TEST_F(IpTablesTest,ApplyVpnSetupAdd_FailureInUsername)211 TEST_F(IpTablesTest, ApplyVpnSetupAdd_FailureInUsername) {
212 const std::vector<std::string> usernames = {"testuser0", "testuser1"};
213 const std::string interface = "ifc0";
214 const bool remove = false;
215 const bool add = true;
216
217 MockIpTables mock_iptables;
218 EXPECT_CALL(mock_iptables, ApplyMasquerade(interface, add))
219 .Times(1)
220 .WillOnce(Return(true));
221
222 EXPECT_CALL(mock_iptables,
223 ApplyMarkForUserTraffic(usernames[0], add))
224 .Times(1)
225 .WillOnce(Return(true));
226 EXPECT_CALL(mock_iptables,
227 ApplyMarkForUserTraffic(usernames[1], add))
228 .Times(1)
229 .WillOnce(Return(false));
230
231 EXPECT_CALL(mock_iptables, ApplyRuleForUserTraffic(add))
232 .Times(1)
233 .WillOnce(Return(true));
234
235 EXPECT_CALL(mock_iptables, ApplyMasquerade(interface, remove))
236 .Times(1)
237 .WillOnce(Return(true));
238
239 EXPECT_CALL(mock_iptables,
240 ApplyMarkForUserTraffic(usernames[0], remove))
241 .Times(1)
242 .WillOnce(Return(false));
243 EXPECT_CALL(mock_iptables,
244 ApplyMarkForUserTraffic(usernames[1], remove))
245 .Times(0);
246
247 EXPECT_CALL(mock_iptables, ApplyRuleForUserTraffic(remove))
248 .Times(1)
249 .WillOnce(Return(false));
250
251 ASSERT_FALSE(
252 mock_iptables.ApplyVpnSetup(usernames, interface, add));
253 }
254
TEST_F(IpTablesTest,ApplyVpnSetupAdd_FailureInMasquerade)255 TEST_F(IpTablesTest, ApplyVpnSetupAdd_FailureInMasquerade) {
256 const std::vector<std::string> usernames = {"testuser0", "testuser1"};
257 const std::string interface = "ifc0";
258 const bool remove = false;
259 const bool add = true;
260
261 MockIpTables mock_iptables;
262 EXPECT_CALL(mock_iptables, ApplyMasquerade(interface, add))
263 .Times(1)
264 .WillOnce(Return(false));
265
266 EXPECT_CALL(mock_iptables, ApplyMarkForUserTraffic(_, _)).Times(0);
267
268 EXPECT_CALL(mock_iptables, ApplyRuleForUserTraffic(add))
269 .Times(1)
270 .WillOnce(Return(true));
271
272 EXPECT_CALL(mock_iptables, ApplyMasquerade(interface, remove))
273 .Times(1)
274 .WillOnce(Return(true));
275
276 EXPECT_CALL(mock_iptables, ApplyRuleForUserTraffic(remove))
277 .Times(1)
278 .WillOnce(Return(true));
279
280 ASSERT_FALSE(
281 mock_iptables.ApplyVpnSetup(usernames, interface, add));
282 }
283
TEST_F(IpTablesTest,ApplyVpnSetupAdd_FailureInRuleForUserTraffic)284 TEST_F(IpTablesTest, ApplyVpnSetupAdd_FailureInRuleForUserTraffic) {
285 const std::vector<std::string> usernames = {"testuser0", "testuser1"};
286 const std::string interface = "ifc0";
287 const bool remove = false;
288 const bool add = true;
289
290 MockIpTables mock_iptables;
291 EXPECT_CALL(mock_iptables, ApplyMasquerade(interface, _)).Times(0);
292 EXPECT_CALL(mock_iptables, ApplyMarkForUserTraffic(_, _)).Times(0);
293 EXPECT_CALL(mock_iptables, ApplyRuleForUserTraffic(add))
294 .Times(1)
295 .WillOnce(Return(false));
296
297 EXPECT_CALL(mock_iptables, ApplyRuleForUserTraffic(remove)).Times(1);
298
299 ASSERT_FALSE(mock_iptables.ApplyVpnSetup(usernames, interface, add));
300 }
301
TEST_F(IpTablesTest,ApplyVpnSetupRemove_Success)302 TEST_F(IpTablesTest, ApplyVpnSetupRemove_Success) {
303 const std::vector<std::string> usernames = {"testuser0", "testuser1"};
304 const std::string interface = "ifc0";
305 const bool remove = false;
306 const bool add = true;
307
308 MockIpTables mock_iptables;
309 EXPECT_CALL(mock_iptables, ApplyMasquerade(interface, remove))
310 .Times(1)
311 .WillOnce(Return(true));
312 EXPECT_CALL(mock_iptables, ApplyMarkForUserTraffic(_, remove))
313 .Times(2)
314 .WillRepeatedly(Return(true));
315 EXPECT_CALL(mock_iptables, ApplyRuleForUserTraffic(remove))
316 .Times(1)
317 .WillOnce(Return(true));
318
319 EXPECT_CALL(mock_iptables, ApplyMasquerade(interface, add)).Times(0);
320 EXPECT_CALL(mock_iptables, ApplyMarkForUserTraffic(_, add)).Times(0);
321 EXPECT_CALL(mock_iptables, ApplyRuleForUserTraffic(add)).Times(0);
322
323 ASSERT_TRUE(mock_iptables.ApplyVpnSetup(usernames, interface, remove));
324 }
325
TEST_F(IpTablesTest,ApplyVpnSetupRemove_Failure)326 TEST_F(IpTablesTest, ApplyVpnSetupRemove_Failure) {
327 const std::vector<std::string> usernames = {"testuser0", "testuser1"};
328 const std::string interface = "ifc0";
329 const bool remove = false;
330 const bool add = true;
331
332 MockIpTables mock_iptables;
333 EXPECT_CALL(mock_iptables, ApplyMasquerade(interface, remove))
334 .Times(1)
335 .WillRepeatedly(Return(false));
336
337 EXPECT_CALL(mock_iptables, ApplyMarkForUserTraffic(_, remove))
338 .Times(2)
339 .WillRepeatedly(Return(false));
340
341 EXPECT_CALL(mock_iptables, ApplyRuleForUserTraffic(remove))
342 .Times(1)
343 .WillRepeatedly(Return(false));
344
345 EXPECT_CALL(mock_iptables, ApplyMasquerade(interface, add)).Times(0);
346
347 EXPECT_CALL(mock_iptables, ApplyMarkForUserTraffic(_, add)).Times(0);
348 EXPECT_CALL(mock_iptables, ApplyRuleForUserTraffic(add)).Times(0);
349
350 ASSERT_FALSE(mock_iptables.ApplyVpnSetup(usernames, interface, remove));
351 }
352
353 } // namespace firewalld
354