1 /*
2 * Copyright (c) 2023 Huawei Device Co., Ltd.
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
16 #include "iexecuter.h"
17
18 #include <iostream>
19 #include <sstream>
20
21 #include "edm_log.h"
22 #include "executer_utils.h"
23 #include "rule_utils.h"
24
25 namespace OHOS {
26 namespace EDM {
27 namespace IPTABLES {
28
29 const std::string NEW_OPTION = " -N ";
30 const std::string SELECT_TABLE_OPTION = "-t ";
31 const std::string INSERT_OPTION = " -I ";
32 const std::string APPEND_OPTION = " -A ";
33 const std::string DELETE_OPTION = " -D ";
34 const std::string FLUSH_OPTION = " -F ";
35 const std::string JUMP_OPTION = " -j ";
36 const std::string JUMP_LOG_OPTION = " -j LOG --log-prefix ";
37 const std::string LOG_TAG_DROP = "iptables-edm-drop:";
38 const std::string LOG_TAG_REJECT = "iptables-edm-reject:";
39 const uint32_t RESULT_MIN_SIZE = 3;
40
IExecuter(std::string chainName)41 IExecuter::IExecuter(std::string chainName) : chainName_(std::move(chainName))
42 {
43 tableName_ = "filter";
44 }
45
CreateChain()46 ErrCode IExecuter::CreateChain()
47 {
48 std::ostringstream oss;
49 oss << SELECT_TABLE_OPTION << tableName_ << NEW_OPTION << chainName_;
50 std::string result;
51 return ExecuterUtils::GetInstance()->Execute(oss.str(), result);
52 }
53
Add(const std::shared_ptr<ChainRule> & rule)54 ErrCode IExecuter::Add(const std::shared_ptr<ChainRule>& rule)
55 {
56 if (rule == nullptr) {
57 EDMLOGE("Add: error param.");
58 return EdmReturnErrCode::PARAM_ERROR;
59 }
60 std::ostringstream oss;
61 oss << SELECT_TABLE_OPTION << tableName_;
62 oss << APPEND_OPTION << chainName_;
63 return ExecWithOption(oss, rule);
64 }
65
Remove(const std::shared_ptr<ChainRule> & rule)66 ErrCode IExecuter::Remove(const std::shared_ptr<ChainRule>& rule)
67 {
68 std::ostringstream oss;
69 oss << SELECT_TABLE_OPTION << tableName_;
70 if (rule == nullptr || rule->Parameter().empty()) {
71 oss << FLUSH_OPTION << chainName_;
72 } else {
73 oss << DELETE_OPTION << chainName_;
74 return ExecWithOption(oss, rule);
75 }
76 std::string result;
77 return ExecuterUtils::GetInstance()->Execute(oss.str(), result);
78 }
79
ExecWithOption(std::ostringstream & oss,const std::shared_ptr<ChainRule> & rule)80 ErrCode IExecuter::ExecWithOption(std::ostringstream& oss, const std::shared_ptr<ChainRule>& rule)
81 {
82 oss << rule->Parameter();
83 // for interception rules, log needs to be recorded.
84 std::string rulePrefix = oss.str();
85 std::string ruleTarget = rule->Target();
86 if (ruleTarget == REJECT_TARGET) {
87 // no need to use the "" symbol
88 oss << JUMP_LOG_OPTION << LOG_TAG_REJECT;
89 } else if (ruleTarget == DROP_TARGET) {
90 // no need to use the "" symbol
91 oss << JUMP_LOG_OPTION << LOG_TAG_DROP;
92 } else {
93 oss << JUMP_OPTION << rule->Target();
94 std::string result;
95 return ExecuterUtils::GetInstance()->Execute(oss.str(), result);
96 }
97
98 std::string logRule = oss.str();
99
100 oss.str({});
101 oss << rulePrefix << JUMP_OPTION << rule->Target();
102 std::string interceptRule = oss.str();
103
104 std::string result;
105 // "-j LOG" must be before "-j REJECT"/"-j DROP"
106 ErrCode ret = ExecuterUtils::GetInstance()->Execute(logRule, result);
107 if (ret != ERR_OK) {
108 EDMLOGE("ExecWithOption: exec interception rule log fail.");
109 }
110 return ExecuterUtils::GetInstance()->Execute(interceptRule, result);
111 }
112
GetAll(std::vector<std::string> & ruleList)113 ErrCode IExecuter::GetAll(std::vector<std::string>& ruleList)
114 {
115 std::ostringstream oss;
116 oss << SELECT_TABLE_OPTION << tableName_ << " -n -v -L " << chainName_ << " --line-number";
117 std::string result;
118 ErrCode ret = ExecuterUtils::GetInstance()->Execute(oss.str(), result);
119 if (ret != ERR_OK) {
120 return ret;
121 }
122 std::istringstream iss(result);
123 std::vector<std::string> ruleLines;
124 std::string line;
125 while (getline(iss, line)) {
126 EDMLOGD("GetAll: line: %{public}s", line.c_str());
127 ruleLines.emplace_back(line);
128 }
129 if (ruleLines.size() < RESULT_MIN_SIZE) {
130 EDMLOGI("GetAll: ruleLines is empty");
131 return ERR_OK;
132 }
133
134 for (uint32_t i = RESULT_MIN_SIZE - 1; i < ruleLines.size(); ++i) {
135 auto index = ruleLines[i].find(LOG_TAG_REJECT);
136 if (index != std::string ::npos) {
137 continue;
138 }
139 index = ruleLines[i].find(LOG_TAG_DROP);
140 if (index != std::string ::npos) {
141 continue;
142 }
143 ruleList.emplace_back(ruleLines[i]);
144 }
145 return ERR_OK;
146 }
147 } // namespace IPTABLES
148 } // namespace EDM
149 } // namespace OHOS