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