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