OSDN Git Service

Add a test for StrictController.
authorLorenzo Colitti <lorenzo@google.com>
Sun, 27 Mar 2016 17:34:54 +0000 (02:34 +0900)
committerLorenzo Colitti <lorenzo@google.com>
Wed, 30 Mar 2016 07:43:53 +0000 (16:43 +0900)
Bug: 21725996
Bug: 25691379
Change-Id: I24b838161eaf98dede2ae897157ba42414fc926f

server/Android.mk
server/IptablesBaseTest.cpp
server/IptablesBaseTest.h
server/StrictController.cpp
server/StrictController.h
server/StrictControllerTest.cpp [new file with mode: 0644]

index f0c2d57..1135c5a 100644 (file)
@@ -128,7 +128,8 @@ LOCAL_SRC_FILES := \
         NetdConstants.cpp IptablesBaseTest.cpp \
         BandwidthController.cpp BandwidthControllerTest.cpp \
         FirewallControllerTest.cpp FirewallController.cpp \
-        SockDiagTest.cpp SockDiag.cpp
+        SockDiagTest.cpp SockDiag.cpp \
+        StrictController.cpp StrictControllerTest.cpp
 LOCAL_MODULE_TAGS := tests
 LOCAL_SHARED_LIBRARIES := liblog libbase libcutils liblogwrap
 include $(BUILD_NATIVE_TEST)
index b3065f5..3b96b81 100644 (file)
@@ -40,21 +40,63 @@ int IptablesBaseTest::fake_android_fork_exec(int argc, char* argv[], int *status
     return 0;
 }
 
+int IptablesBaseTest::fakeExecIptables(IptablesTarget target, ...) {
+    std::string cmd = " -w";
+    va_list args;
+    va_start(args, target);
+    const char *arg;
+    do {
+        arg = va_arg(args, const char *);
+        if (arg != nullptr) {
+            cmd += " ";
+            cmd += arg;
+        }
+    } while (arg);
+
+    if (target == V4 || target == V4V6) {
+        sCmds.push_back(IPTABLES_PATH + cmd);
+    }
+    if (target == V6 || target == V4V6) {
+        sCmds.push_back(IP6TABLES_PATH + cmd);
+    }
+
+    return 0;
+}
+
 int IptablesBaseTest::fakeExecIptablesRestore(IptablesTarget target, const std::string& commands) {
     EXPECT_EQ(V4V6, target);
     sRestoreCmds.push_back(commands);
     return 0;
 }
 
+int IptablesBaseTest::expectIptablesCommand(IptablesTarget target, int pos,
+                                            const std::string& cmd) {
+    if (target == V4 || target == V4V6) {
+        EXPECT_EQ("/system/bin/iptables -w " + cmd, sCmds[pos++]);
+    }
+    if (target == V6 || target == V4V6) {
+        EXPECT_EQ("/system/bin/ip6tables -w " + cmd, sCmds[pos++]);
+    }
+    return target == V4V6 ? 2 : 1;
+}
+
 void IptablesBaseTest::expectIptablesCommands(const std::vector<std::string>& expectedCmds) {
-    EXPECT_EQ(expectedCmds.size() * 2, sCmds.size());
-    if (expectedCmds.size() * 2 != sCmds.size()) return;
+    ExpectedIptablesCommands expected;
+    for (auto cmd : expectedCmds) {
+        expected.push_back({ V4V6, cmd });
+    }
+    expectIptablesCommands(expected);
+}
 
+void IptablesBaseTest::expectIptablesCommands(const ExpectedIptablesCommands& expectedCmds) {
+    size_t pos = 0;
     for (size_t i = 0; i < expectedCmds.size(); i ++) {
-        EXPECT_EQ("/system/bin/iptables -w " + expectedCmds[i], sCmds[2 * i]);
-        EXPECT_EQ("/system/bin/ip6tables -w " + expectedCmds[i], sCmds[2 * i + 1]);
+        auto target = expectedCmds[i].first;
+        auto cmd = expectedCmds[i].second;
+        pos += expectIptablesCommand(target, pos, cmd);
     }
 
+    EXPECT_EQ(pos, sCmds.size());
     sCmds.clear();
 }
 
index 11330c2..5516788 100644 (file)
@@ -22,13 +22,18 @@ class IptablesBaseTest : public ::testing::Test {
 public:
     IptablesBaseTest();
 
+    typedef std::vector<std::pair<IptablesTarget, std::string>> ExpectedIptablesCommands;
+
     static int fake_android_fork_exec(int argc, char* argv[], int *status, bool, bool);
+    static int fakeExecIptables(IptablesTarget target, ...);
     static int fakeExecIptablesRestore(IptablesTarget target, const std::string& commands);
     void expectIptablesCommands(const std::vector<std::string>& expectedCmds);
+    void expectIptablesCommands(const ExpectedIptablesCommands& expectedCmds);
     void expectIptablesRestoreCommands(const std::vector<std::string>& expectedCmds);
 
 protected:
     static std::vector<std::string> sCmds;
     static std::vector<std::string> sRestoreCmds;
+    int expectIptablesCommand(IptablesTarget target, int pos, const std::string& cmd);
 };
 
index a04124d..5aa679f 100644 (file)
@@ -28,6 +28,8 @@
 #include "NetdConstants.h"
 #include "StrictController.h"
 
+auto StrictController::execIptables = ::execIptables;
+
 const char* StrictController::LOCAL_OUTPUT = "st_OUTPUT";
 const char* StrictController::LOCAL_CLEAR_DETECT = "st_clear_detect";
 const char* StrictController::LOCAL_CLEAR_CAUGHT = "st_clear_caught";
index 52a6779..6f5fed2 100644 (file)
@@ -19,6 +19,8 @@
 
 #include <string>
 
+#include "NetdConstants.h"
+
 enum StrictPenalty { INVALID, ACCEPT, LOG, REJECT };
 
 /*
@@ -39,6 +41,11 @@ public:
     static const char* LOCAL_CLEAR_CAUGHT;
     static const char* LOCAL_PENALTY_LOG;
     static const char* LOCAL_PENALTY_REJECT;
+
+protected:
+    // For testing.
+    friend class StrictControllerTest;
+    static int (*execIptables)(IptablesTarget target, ...);
 };
 
 #endif
diff --git a/server/StrictControllerTest.cpp b/server/StrictControllerTest.cpp
new file mode 100644 (file)
index 0000000..038c971
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * StrictControllerTest.cpp - unit tests for StrictController.cpp
+ */
+
+#include <string>
+#include <vector>
+
+#include <gtest/gtest.h>
+
+#include <android-base/strings.h>
+
+#include "StrictController.h"
+#include "IptablesBaseTest.h"
+
+class StrictControllerTest : public IptablesBaseTest {
+public:
+    StrictControllerTest() {
+        StrictController::execIptables = fakeExecIptables;
+    }
+    StrictController mStrictCtrl;
+};
+
+TEST_F(StrictControllerTest, TestEnableStrict) {
+    mStrictCtrl.enableStrict();
+
+    std::vector<std::pair<IptablesTarget, std::string>> expected = {
+        { V4V6, "-F st_OUTPUT" },
+        { V4V6, "-F st_penalty_log" },
+        { V4V6, "-F st_penalty_reject" },
+        { V4V6, "-F st_clear_caught" },
+        { V4V6, "-F st_clear_detect" },
+        { V4V6, "-X st_penalty_log" },
+        { V4V6, "-X st_penalty_reject" },
+        { V4V6, "-X st_clear_caught" },
+        { V4V6, "-X st_clear_detect" },
+        { V4V6, "-N st_penalty_log" },
+        { V4V6, "-A st_penalty_log -j CONNMARK --or-mark 0x1000000" },
+        { V4V6, "-A st_penalty_log -j NFLOG --nflog-group 0" },
+        { V4V6, "-N st_penalty_reject" },
+        { V4V6, "-A st_penalty_reject -j CONNMARK --or-mark 0x2000000" },
+        { V4V6, "-A st_penalty_reject -j NFLOG --nflog-group 0" },
+        { V4V6, "-A st_penalty_reject -j REJECT" },
+        { V4V6, "-N st_clear_detect" },
+        { V4V6, "-N st_clear_caught" },
+        { V4V6, "-A st_clear_detect -m connmark --mark 0x2000000/0x2000000 -j REJECT" },
+        { V4V6, "-A st_clear_detect -m connmark --mark 0x1000000/0x1000000 -j RETURN" },
+        { V4, "-A st_clear_detect -p tcp -m u32 --u32 "
+              "0>>22&0x3C@ 12>>26&0x3C@ 0&0xFFFF0000=0x16030000 &&"
+              "0>>22&0x3C@ 12>>26&0x3C@ 4&0x00FF0000=0x00010000 "
+              "-j CONNMARK --or-mark 0x1000000" },
+        { V4, "-A st_clear_detect -p udp -m u32 --u32 "
+              "0>>22&0x3C@ 8&0xFFFF0000=0x16FE0000 &&"
+              "0>>22&0x3C@ 20&0x00FF0000=0x00010000"
+              " -j CONNMARK --or-mark 0x1000000" },
+        { V6, "-A st_clear_detect -p tcp -m u32 --u32 "
+              "52>>26&0x3C@ 40&0xFFFF0000=0x16030000 &&"
+              "52>>26&0x3C@ 44&0x00FF0000=0x00010000"
+              " -j CONNMARK --or-mark 0x1000000" },
+        { V6, "-A st_clear_detect -p udp -m u32 --u32 "
+              "48&0xFFFF0000=0x16FE0000 &&60&0x00FF0000=0x00010000"
+              " -j CONNMARK --or-mark 0x1000000" },
+        { V4V6, "-A st_clear_detect -m connmark --mark 0x1000000/0x1000000 -j RETURN" },
+        { V4, "-A st_clear_detect -p tcp -m state --state ESTABLISHED -m u32 --u32 "
+              "0>>22&0x3C@ 12>>26&0x3C@ 0&0x0=0x0"
+              " -j st_clear_caught" },
+        { V6, "-A st_clear_detect -p tcp -m state --state ESTABLISHED -m u32 --u32 "
+              "52>>26&0x3C@ 40&0x0=0x0"
+              " -j st_clear_caught" },
+        { V4V6, "-A st_clear_detect -p udp -j st_clear_caught" },
+    };
+    expectIptablesCommands(expected);
+}
+
+TEST_F(StrictControllerTest, TestDisableStrict) {
+    mStrictCtrl.disableStrict();
+
+    std::vector<std::string> expected = {
+        "-F st_OUTPUT",
+        "-F st_penalty_log",
+        "-F st_penalty_reject",
+        "-F st_clear_caught",
+        "-F st_clear_detect",
+        "-X st_penalty_log",
+        "-X st_penalty_reject",
+        "-X st_clear_caught",
+        "-X st_clear_detect",
+    };
+    expectIptablesCommands(expected);
+}