Home | History | Annotate | Download | only in server
      1 /*
      2  * Copyright 2016 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  * http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  *
     16  * FirewallControllerTest.cpp - unit tests for FirewallController.cpp
     17  */
     18 
     19 #include <string>
     20 #include <vector>
     21 #include <stdio.h>
     22 
     23 #include <gtest/gtest.h>
     24 
     25 #include <android-base/strings.h>
     26 #include <android-base/stringprintf.h>
     27 
     28 #include "FirewallController.h"
     29 #include "IptablesBaseTest.h"
     30 
     31 using android::base::Join;
     32 using android::base::StringPrintf;
     33 
     34 class FirewallControllerTest : public IptablesBaseTest {
     35 protected:
     36     FirewallControllerTest() {
     37         FirewallController::execIptablesRestore = fakeExecIptablesRestore;
     38         mFw.mUseBpfOwnerMatch = false;
     39     }
     40     FirewallController mFw;
     41 
     42     std::string makeUidRules(IptablesTarget a, const char* b, bool c,
     43                              const std::vector<int32_t>& d) {
     44         return mFw.makeUidRules(a, b, c, d);
     45     }
     46 
     47     int createChain(const char* a, FirewallType b) {
     48         return mFw.createChain(a, b);
     49     }
     50 };
     51 
     52 
     53 TEST_F(FirewallControllerTest, TestCreateWhitelistChain) {
     54     std::vector<std::string> expectedRestore4 = {
     55         "*filter",
     56         ":fw_whitelist -",
     57         "-A fw_whitelist -m owner --uid-owner 0-9999 -j RETURN",
     58         "-A fw_whitelist -m owner ! --uid-owner 0-4294967294 -j RETURN",
     59         "-A fw_whitelist -p esp -j RETURN",
     60         "-A fw_whitelist -i lo -j RETURN",
     61         "-A fw_whitelist -o lo -j RETURN",
     62         "-A fw_whitelist -p tcp --tcp-flags RST RST -j RETURN",
     63         "-A fw_whitelist -j DROP",
     64         "COMMIT\n"
     65     };
     66     std::vector<std::string> expectedRestore6 = {
     67         "*filter",
     68         ":fw_whitelist -",
     69         "-A fw_whitelist -m owner --uid-owner 0-9999 -j RETURN",
     70         "-A fw_whitelist -m owner ! --uid-owner 0-4294967294 -j RETURN",
     71         "-A fw_whitelist -p esp -j RETURN",
     72         "-A fw_whitelist -i lo -j RETURN",
     73         "-A fw_whitelist -o lo -j RETURN",
     74         "-A fw_whitelist -p tcp --tcp-flags RST RST -j RETURN",
     75         "-A fw_whitelist -p icmpv6 --icmpv6-type packet-too-big -j RETURN",
     76         "-A fw_whitelist -p icmpv6 --icmpv6-type router-solicitation -j RETURN",
     77         "-A fw_whitelist -p icmpv6 --icmpv6-type router-advertisement -j RETURN",
     78         "-A fw_whitelist -p icmpv6 --icmpv6-type neighbour-solicitation -j RETURN",
     79         "-A fw_whitelist -p icmpv6 --icmpv6-type neighbour-advertisement -j RETURN",
     80         "-A fw_whitelist -p icmpv6 --icmpv6-type redirect -j RETURN",
     81         "-A fw_whitelist -j DROP",
     82         "COMMIT\n"
     83     };
     84     std::vector<std::pair<IptablesTarget, std::string>> expectedRestoreCommands = {
     85         { V4, android::base::Join(expectedRestore4, '\n') },
     86         { V6, android::base::Join(expectedRestore6, '\n') },
     87     };
     88 
     89     createChain("fw_whitelist", WHITELIST);
     90     expectIptablesRestoreCommands(expectedRestoreCommands);
     91 }
     92 
     93 TEST_F(FirewallControllerTest, TestCreateBlacklistChain) {
     94     std::vector<std::string> expectedRestore = {
     95         "*filter",
     96         ":fw_blacklist -",
     97         "-A fw_blacklist -i lo -j RETURN",
     98         "-A fw_blacklist -o lo -j RETURN",
     99         "-A fw_blacklist -p tcp --tcp-flags RST RST -j RETURN",
    100         "COMMIT\n"
    101     };
    102     std::vector<std::pair<IptablesTarget, std::string>> expectedRestoreCommands = {
    103         { V4, android::base::Join(expectedRestore, '\n') },
    104         { V6, android::base::Join(expectedRestore, '\n') },
    105     };
    106 
    107     createChain("fw_blacklist", BLACKLIST);
    108     expectIptablesRestoreCommands(expectedRestoreCommands);
    109 }
    110 
    111 TEST_F(FirewallControllerTest, TestSetStandbyRule) {
    112     ExpectedIptablesCommands expected = {
    113         { V4V6, "*filter\n-D fw_standby -m owner --uid-owner 12345 -j DROP\nCOMMIT\n" }
    114     };
    115     mFw.setUidRule(STANDBY, 12345, ALLOW);
    116     expectIptablesRestoreCommands(expected);
    117 
    118     expected = {
    119         { V4V6, "*filter\n-A fw_standby -m owner --uid-owner 12345 -j DROP\nCOMMIT\n" }
    120     };
    121     mFw.setUidRule(STANDBY, 12345, DENY);
    122     expectIptablesRestoreCommands(expected);
    123 }
    124 
    125 TEST_F(FirewallControllerTest, TestSetDozeRule) {
    126     ExpectedIptablesCommands expected = {
    127         { V4V6, "*filter\n-I fw_dozable -m owner --uid-owner 54321 -j RETURN\nCOMMIT\n" }
    128     };
    129     mFw.setUidRule(DOZABLE, 54321, ALLOW);
    130     expectIptablesRestoreCommands(expected);
    131 
    132     expected = {
    133         { V4V6, "*filter\n-D fw_dozable -m owner --uid-owner 54321 -j RETURN\nCOMMIT\n" }
    134     };
    135     mFw.setUidRule(DOZABLE, 54321, DENY);
    136     expectIptablesRestoreCommands(expected);
    137 }
    138 
    139 TEST_F(FirewallControllerTest, TestSetFirewallRule) {
    140     ExpectedIptablesCommands expected = {
    141         { V4V6, "*filter\n"
    142                 "-A fw_INPUT -m owner --uid-owner 54321 -j DROP\n"
    143                 "-A fw_OUTPUT -m owner --uid-owner 54321 -j DROP\n"
    144                 "COMMIT\n" }
    145     };
    146     mFw.setUidRule(NONE, 54321, DENY);
    147     expectIptablesRestoreCommands(expected);
    148 
    149     expected = {
    150         { V4V6, "*filter\n"
    151                 "-D fw_INPUT -m owner --uid-owner 54321 -j DROP\n"
    152                 "-D fw_OUTPUT -m owner --uid-owner 54321 -j DROP\n"
    153                 "COMMIT\n" }
    154     };
    155     mFw.setUidRule(NONE, 54321, ALLOW);
    156     expectIptablesRestoreCommands(expected);
    157 }
    158 
    159 TEST_F(FirewallControllerTest, TestReplaceWhitelistUidRule) {
    160     std::string expected =
    161             "*filter\n"
    162             ":FW_whitechain -\n"
    163             "-A FW_whitechain -m owner --uid-owner 10023 -j RETURN\n"
    164             "-A FW_whitechain -m owner --uid-owner 10059 -j RETURN\n"
    165             "-A FW_whitechain -m owner --uid-owner 10124 -j RETURN\n"
    166             "-A FW_whitechain -m owner --uid-owner 10111 -j RETURN\n"
    167             "-A FW_whitechain -m owner --uid-owner 110122 -j RETURN\n"
    168             "-A FW_whitechain -m owner --uid-owner 210153 -j RETURN\n"
    169             "-A FW_whitechain -m owner --uid-owner 210024 -j RETURN\n"
    170             "-A FW_whitechain -m owner --uid-owner 0-9999 -j RETURN\n"
    171             "-A FW_whitechain -m owner ! --uid-owner 0-4294967294 -j RETURN\n"
    172             "-A FW_whitechain -p esp -j RETURN\n"
    173             "-A FW_whitechain -i lo -j RETURN\n"
    174             "-A FW_whitechain -o lo -j RETURN\n"
    175             "-A FW_whitechain -p tcp --tcp-flags RST RST -j RETURN\n"
    176             "-A FW_whitechain -p icmpv6 --icmpv6-type packet-too-big -j RETURN\n"
    177             "-A FW_whitechain -p icmpv6 --icmpv6-type router-solicitation -j RETURN\n"
    178             "-A FW_whitechain -p icmpv6 --icmpv6-type router-advertisement -j RETURN\n"
    179             "-A FW_whitechain -p icmpv6 --icmpv6-type neighbour-solicitation -j RETURN\n"
    180             "-A FW_whitechain -p icmpv6 --icmpv6-type neighbour-advertisement -j RETURN\n"
    181             "-A FW_whitechain -p icmpv6 --icmpv6-type redirect -j RETURN\n"
    182             "-A FW_whitechain -j DROP\n"
    183             "COMMIT\n";
    184 
    185     std::vector<int32_t> uids = { 10023, 10059, 10124, 10111, 110122, 210153, 210024 };
    186     EXPECT_EQ(expected, makeUidRules(V6, "FW_whitechain", true, uids));
    187 }
    188 
    189 TEST_F(FirewallControllerTest, TestReplaceBlacklistUidRule) {
    190     std::string expected =
    191             "*filter\n"
    192             ":FW_blackchain -\n"
    193             "-A FW_blackchain -i lo -j RETURN\n"
    194             "-A FW_blackchain -o lo -j RETURN\n"
    195             "-A FW_blackchain -p tcp --tcp-flags RST RST -j RETURN\n"
    196             "-A FW_blackchain -m owner --uid-owner 10023 -j DROP\n"
    197             "-A FW_blackchain -m owner --uid-owner 10059 -j DROP\n"
    198             "-A FW_blackchain -m owner --uid-owner 10124 -j DROP\n"
    199             "COMMIT\n";
    200 
    201     std::vector<int32_t> uids = { 10023, 10059, 10124 };
    202     EXPECT_EQ(expected, makeUidRules(V4 ,"FW_blackchain", false, uids));
    203 }
    204 
    205 TEST_F(FirewallControllerTest, TestEnableChildChains) {
    206     std::vector<std::string> expected = {
    207         "*filter\n"
    208         "-A fw_INPUT -j fw_dozable\n"
    209         "-A fw_OUTPUT -j fw_dozable\n"
    210         "COMMIT\n"
    211     };
    212     EXPECT_EQ(0, mFw.enableChildChains(DOZABLE, true));
    213     expectIptablesRestoreCommands(expected);
    214 
    215     expected = {
    216         "*filter\n"
    217         "-D fw_INPUT -j fw_powersave\n"
    218         "-D fw_OUTPUT -j fw_powersave\n"
    219         "COMMIT\n"
    220     };
    221     EXPECT_EQ(0, mFw.enableChildChains(POWERSAVE, false));
    222     expectIptablesRestoreCommands(expected);
    223 }
    224 
    225 TEST_F(FirewallControllerTest, TestFirewall) {
    226     std::vector<std::string> enableCommands = {
    227         "*filter\n"
    228         "-A fw_INPUT -j DROP\n"
    229         "-A fw_OUTPUT -j REJECT\n"
    230         "-A fw_FORWARD -j REJECT\n"
    231         "COMMIT\n"
    232     };
    233     std::vector<std::string> disableCommands = {
    234         "*filter\n"
    235         ":fw_INPUT -\n"
    236         ":fw_OUTPUT -\n"
    237         ":fw_FORWARD -\n"
    238         "COMMIT\n"
    239     };
    240     std::vector<std::string> noCommands = {};
    241 
    242     EXPECT_EQ(0, mFw.disableFirewall());
    243     expectIptablesRestoreCommands(disableCommands);
    244 
    245     EXPECT_EQ(0, mFw.disableFirewall());
    246     expectIptablesRestoreCommands(disableCommands);
    247 
    248     EXPECT_EQ(0, mFw.enableFirewall(BLACKLIST));
    249     expectIptablesRestoreCommands(disableCommands);
    250 
    251     EXPECT_EQ(0, mFw.enableFirewall(BLACKLIST));
    252     expectIptablesRestoreCommands(noCommands);
    253 
    254     std::vector<std::string> disableEnableCommands;
    255     disableEnableCommands.insert(
    256             disableEnableCommands.end(), disableCommands.begin(), disableCommands.end());
    257     disableEnableCommands.insert(
    258             disableEnableCommands.end(), enableCommands.begin(), enableCommands.end());
    259 
    260     EXPECT_EQ(0, mFw.enableFirewall(WHITELIST));
    261     expectIptablesRestoreCommands(disableEnableCommands);
    262 
    263     std::vector<std::string> ifaceCommands = {
    264         "*filter\n"
    265         "-I fw_INPUT -i rmnet_data0 -j RETURN\n"
    266         "-I fw_OUTPUT -o rmnet_data0 -j RETURN\n"
    267         "COMMIT\n"
    268     };
    269     EXPECT_EQ(0, mFw.setInterfaceRule("rmnet_data0", ALLOW));
    270     expectIptablesRestoreCommands(ifaceCommands);
    271 
    272     EXPECT_EQ(0, mFw.setInterfaceRule("rmnet_data0", ALLOW));
    273     expectIptablesRestoreCommands(noCommands);
    274 
    275     ifaceCommands = {
    276         "*filter\n"
    277         "-D fw_INPUT -i rmnet_data0 -j RETURN\n"
    278         "-D fw_OUTPUT -o rmnet_data0 -j RETURN\n"
    279         "COMMIT\n"
    280     };
    281     EXPECT_EQ(0, mFw.setInterfaceRule("rmnet_data0", DENY));
    282     expectIptablesRestoreCommands(ifaceCommands);
    283 
    284     EXPECT_EQ(0, mFw.setInterfaceRule("rmnet_data0", DENY));
    285     expectIptablesRestoreCommands(noCommands);
    286 
    287     EXPECT_EQ(0, mFw.enableFirewall(WHITELIST));
    288     expectIptablesRestoreCommands(noCommands);
    289 
    290     EXPECT_EQ(0, mFw.disableFirewall());
    291     expectIptablesRestoreCommands(disableCommands);
    292 
    293     // TODO: calling disableFirewall and then enableFirewall(WHITELIST) does
    294     // nothing. This seems like a clear bug.
    295     EXPECT_EQ(0, mFw.enableFirewall(WHITELIST));
    296     expectIptablesRestoreCommands(noCommands);
    297 }
    298