Home | History | Annotate | Download | only in firewalld
      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:
     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 
     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 
     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 
     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 
     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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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