1 /*
2 * Copyright (c) 2023-2024 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 "iptables_rule_plugin.h"
17
18 #include "edm_constants.h"
19 #include "edm_ipc_interface_code.h"
20 #include "edm_log.h"
21 #include "func_code_utils.h"
22 #include "netsys_controller.h"
23 #include "iplugin_manager.h"
24
25 namespace OHOS {
26 namespace EDM {
27 const bool REGISTER_RESULT = IPluginManager::GetInstance()->AddPlugin(std::make_shared<IptablesRulePlugin>());
28 const std::string EDM_CHAIN_ALLOW_INPUT = "edm_allow_input";
29 const std::string EDM_CHAIN_ALLOW_OUTPUT = "edm_allow_output";
30 const std::string EDM_CHAIN_DENY_INPUT = "edm_deny_input";
31 const std::string EDM_CHAIN_DENY_OUTPUT = "edm_deny_output";
32
33 bool IptablesRulePlugin::isChainInit_ = false;
34
IptablesRulePlugin()35 IptablesRulePlugin::IptablesRulePlugin()
36 {
37 policyCode_ = EdmInterfaceCode::IPTABLES_RULE;
38 policyName_ = PolicyName::POLICY_IPTABLES_RULE;
39 permissionConfig_.typePermissions.emplace(IPlugin::PermissionType::SUPER_DEVICE_ADMIN,
40 EdmPermission::PERMISSION_ENTERPRISE_MANAGE_NETWORK);
41 permissionConfig_.apiType = IPlugin::ApiType::SYSTEM;
42 needSave_ = false;
43 }
44
OnHandlePolicy(std::uint32_t funcCode,MessageParcel & data,MessageParcel & reply,HandlePolicyData & policyData,int32_t userId)45 ErrCode IptablesRulePlugin::OnHandlePolicy(std::uint32_t funcCode, MessageParcel &data, MessageParcel &reply,
46 HandlePolicyData &policyData, int32_t userId)
47 {
48 uint32_t typeCode = FUNC_TO_OPERATE(funcCode);
49 FuncOperateType type = FuncCodeUtils::ConvertOperateType(typeCode);
50 if (type == FuncOperateType::SET) {
51 return AddIptablesFilterRule(data);
52 } else if (type == FuncOperateType::REMOVE) {
53 return RemoveIptablesFilterRule(data);
54 } else {
55 return EdmReturnErrCode::SYSTEM_ABNORMALLY;
56 }
57 }
58
OnGetPolicy(std::string & policyData,MessageParcel & data,MessageParcel & reply,int32_t userId)59 ErrCode IptablesRulePlugin::OnGetPolicy(std::string &policyData, MessageParcel &data, MessageParcel &reply,
60 int32_t userId)
61 {
62 std::string result;
63 std::string command("-t filter -n -v -L --line-number");
64 int32_t ret = NetManagerStandard::NetsysController::GetInstance().SetIptablesCommandForRes(command, result);
65 EDMLOGI("IptablesRulePlugin::OnGetPolicy end retCode = %{public}d", ret);
66 if (ret == ERR_OK) {
67 reply.WriteInt32(ERR_OK);
68 reply.WriteString(result);
69 return ERR_OK;
70 }
71 reply.WriteInt32(EdmReturnErrCode::SYSTEM_ABNORMALLY);
72 return EdmReturnErrCode::SYSTEM_ABNORMALLY;
73 }
74
AddIptablesFilterRule(MessageParcel & data)75 ErrCode IptablesRulePlugin::AddIptablesFilterRule(MessageParcel &data)
76 {
77 IPTABLES::AddFilter addFilter;
78 IPTABLES::IptablesUtils::ReadAddFilterConfig(addFilter, data);
79 std::string command;
80 if (!ConvertAddFilterToIptablesCommand(addFilter, command)) {
81 EDMLOGE("ConvertAddFilterToIptablesCommand failed");
82 return EdmReturnErrCode::PARAM_ERROR;
83 }
84 InitFirewallChain();
85 std::string result;
86 int32_t ret = NetManagerStandard::NetsysController::GetInstance().SetIptablesCommandForRes(command, result);
87 EDMLOGI("AddIptablesFilterRule errcode = %{public}d, response = %{public}s", ret, result.c_str());
88 return ret;
89 }
90
RemoveIptablesFilterRule(MessageParcel & data)91 ErrCode IptablesRulePlugin::RemoveIptablesFilterRule(MessageParcel &data)
92 {
93 IPTABLES::RemoveFilter removeFilter;
94 IPTABLES::IptablesUtils::ReadRemoveFilterConfig(removeFilter, data);
95 return ExecRemoveFilterIptablesCommand(removeFilter);
96 }
97
InitFirewallChain()98 void IptablesRulePlugin::InitFirewallChain()
99 {
100 if (isChainInit_) {
101 EDMLOGD("no need init firewall chain");
102 return;
103 }
104 std::string allowInputChain = "-t filter -N " + EDM_CHAIN_ALLOW_INPUT;
105 std::string allowOutputChain = "-t filter -N " + EDM_CHAIN_ALLOW_OUTPUT;
106 std::string denyInputChain = "-t filter -N " + EDM_CHAIN_DENY_INPUT;
107 std::string denyOutputChain = "-t filter -N " + EDM_CHAIN_DENY_OUTPUT;
108
109 std::string result;
110 NetManagerStandard::NetsysController::GetInstance().SetIptablesCommandForRes(allowInputChain, result);
111 NetManagerStandard::NetsysController::GetInstance().SetIptablesCommandForRes(allowOutputChain, result);
112 NetManagerStandard::NetsysController::GetInstance().SetIptablesCommandForRes(denyInputChain, result);
113 NetManagerStandard::NetsysController::GetInstance().SetIptablesCommandForRes(denyOutputChain, result);
114
115 std::string refDenyOutputChain = "-t filter -I OUTPUT -j " + EDM_CHAIN_DENY_OUTPUT;
116 std::string refDenyInputChain = "-t filter -I INPUT -j " + EDM_CHAIN_DENY_INPUT;
117 std::string refAllowOutputChain = "-t filter -I OUTPUT -j " + EDM_CHAIN_ALLOW_OUTPUT;
118 std::string refAllowInputChain = "-t filter -I INPUT -j " + EDM_CHAIN_ALLOW_INPUT;
119 NetManagerStandard::NetsysController::GetInstance().SetIptablesCommandForRes(refDenyOutputChain, result);
120 NetManagerStandard::NetsysController::GetInstance().SetIptablesCommandForRes(refDenyInputChain, result);
121 NetManagerStandard::NetsysController::GetInstance().SetIptablesCommandForRes(refAllowOutputChain, result);
122 NetManagerStandard::NetsysController::GetInstance().SetIptablesCommandForRes(refAllowInputChain, result);
123 isChainInit_ = true;
124 EDMLOGD("InitFirewallChain success");
125 }
126
ConvertAddFilterToIptablesCommand(const IPTABLES::AddFilter & addFilter,std::string & command)127 bool IptablesRulePlugin::ConvertAddFilterToIptablesCommand(const IPTABLES::AddFilter &addFilter, std::string &command)
128 {
129 command = "-t filter";
130 if (addFilter.method == IPTABLES::AddMethod::APPEND) {
131 command.append(" -A");
132 } else if (addFilter.method == IPTABLES::AddMethod::INSERT) {
133 command.append(" -I");
134 } else {
135 EDMLOGE("ConvertFirewallToIptablesCommand AddMethod must specify");
136 return false;
137 }
138 if (!ConvertChainCommand(addFilter.action, addFilter.direction, command)) {
139 EDMLOGE("ConvertFirewallToIptablesCommand action and direction must specify");
140 return false;
141 }
142 ConvertRuleNoCommand(addFilter.method, addFilter.ruleNo, command);
143 ConvertProtocolCommand(addFilter.protocol, command);
144 ConvertIpAddressCommand(addFilter.srcAddr, true, command);
145 ConvertIpAddressCommand(addFilter.destAddr, false, command);
146 ConvertPortCommand(addFilter.srcPort, true, command);
147 ConvertPortCommand(addFilter.destPort, false, command);
148 ConvertUidCommand(addFilter.uid, command);
149 return ConvertActionCommand(addFilter.action, command);
150 }
151
ExecRemoveFilterIptablesCommand(const IPTABLES::RemoveFilter & removeFilter)152 ErrCode IptablesRulePlugin::ExecRemoveFilterIptablesCommand(const IPTABLES::RemoveFilter &removeFilter)
153 {
154 if (removeFilter.direction == IPTABLES::Direction::INVALID) {
155 return EdmReturnErrCode::PARAM_ERROR;
156 }
157 if (removeFilter.srcAddr.empty() && removeFilter.destAddr.empty() && removeFilter.srcPort.empty() &&
158 removeFilter.destPort.empty() && removeFilter.uid.empty() && removeFilter.action == IPTABLES::Action::INVALID &&
159 removeFilter.protocol == IPTABLES::Protocol::INVALID) {
160 return ExecRemoveFilterBySimpleCommand(removeFilter.direction);
161 }
162 return ExecRemoveFilterByDetailedCommand(removeFilter);
163 }
164
ExecRemoveFilterBySimpleCommand(const IPTABLES::Direction & direction)165 ErrCode IptablesRulePlugin::ExecRemoveFilterBySimpleCommand(const IPTABLES::Direction &direction)
166 {
167 std::string commandAllow("-t filter -F");
168 std::string commandDeny("-t filter -F");
169 switch (direction) {
170 case IPTABLES::Direction::INPUT:
171 commandAllow.append(" " + EDM_CHAIN_ALLOW_INPUT);
172 commandDeny.append(" " + EDM_CHAIN_DENY_INPUT);
173 break;
174 case IPTABLES::Direction::OUTPUT:
175 commandAllow.append(" " + EDM_CHAIN_ALLOW_OUTPUT);
176 commandDeny.append(" " + EDM_CHAIN_DENY_OUTPUT);
177 break;
178 default:
179 return EdmReturnErrCode::PARAM_ERROR;
180 }
181 std::string result;
182 NetManagerStandard::NetsysController::GetInstance().SetIptablesCommandForRes(commandAllow, result);
183 NetManagerStandard::NetsysController::GetInstance().SetIptablesCommandForRes(commandDeny, result);
184 return ERR_OK;
185 }
186
ExecRemoveFilterByDetailedCommand(const IPTABLES::RemoveFilter & removeFilter)187 ErrCode IptablesRulePlugin::ExecRemoveFilterByDetailedCommand(const IPTABLES::RemoveFilter &removeFilter)
188 {
189 std::string command = "-t filter -D";
190 ConvertChainCommand(removeFilter.action, removeFilter.direction, command);
191 ConvertProtocolCommand(removeFilter.protocol, command);
192 ConvertIpAddressCommand(removeFilter.srcAddr, true, command);
193 ConvertIpAddressCommand(removeFilter.destAddr, false, command);
194 ConvertPortCommand(removeFilter.srcPort, true, command);
195 ConvertPortCommand(removeFilter.destPort, false, command);
196 ConvertUidCommand(removeFilter.uid, command);
197 ConvertActionCommand(removeFilter.action, command);
198 std::string result;
199 return NetManagerStandard::NetsysController::GetInstance().SetIptablesCommandForRes(command, result);
200 }
201
ConvertChainCommand(const IPTABLES::Action & action,const IPTABLES::Direction & direction,std::string & command)202 bool IptablesRulePlugin::ConvertChainCommand(const IPTABLES::Action &action, const IPTABLES::Direction &direction,
203 std::string &command)
204 {
205 if (action == IPTABLES::Action::ALLOW && direction == IPTABLES::Direction::INPUT) {
206 command.append(" " + EDM_CHAIN_ALLOW_INPUT);
207 } else if (action == IPTABLES::Action::ALLOW && direction == IPTABLES::Direction::OUTPUT) {
208 command.append(" " + EDM_CHAIN_ALLOW_OUTPUT);
209 } else if (action == IPTABLES::Action::DENY && direction == IPTABLES::Direction::INPUT) {
210 command.append(" " + EDM_CHAIN_DENY_INPUT);
211 } else if (action == IPTABLES::Action::DENY && direction == IPTABLES::Direction::OUTPUT) {
212 command.append(" " + EDM_CHAIN_DENY_OUTPUT);
213 } else {
214 return false;
215 }
216 return true;
217 }
218
ConvertProtocolCommand(const IPTABLES::Protocol & protocol,std::string & command)219 void IptablesRulePlugin::ConvertProtocolCommand(const IPTABLES::Protocol &protocol, std::string &command)
220 {
221 switch (protocol) {
222 case IPTABLES::Protocol::TCP:
223 command.append(" -p tcp");
224 break;
225 case IPTABLES::Protocol::UDP:
226 command.append(" -p udp");
227 break;
228 case IPTABLES::Protocol::ICMP:
229 command.append(" -p icmp");
230 break;
231 case IPTABLES::Protocol::ALL:
232 command.append(" -p all");
233 break;
234 default:
235 break;
236 }
237 }
238
ConvertActionCommand(const IPTABLES::Action & action,std::string & command)239 bool IptablesRulePlugin::ConvertActionCommand(const IPTABLES::Action &action, std::string &command)
240 {
241 switch (action) {
242 case IPTABLES::Action::ALLOW:
243 command.append(" -j ACCEPT");
244 break;
245 case IPTABLES::Action::DENY:
246 command.append(" -j REJECT");
247 break;
248 default:
249 return false;
250 }
251 return true;
252 }
253
ConvertIpAddressCommand(const std::string & ipAddress,const bool isSourceIp,std::string & command)254 void IptablesRulePlugin::ConvertIpAddressCommand(const std::string &ipAddress, const bool isSourceIp,
255 std::string &command)
256 {
257 if (ipAddress.empty()) {
258 return;
259 }
260 std::string splitStr = "-";
261 std::string::size_type idx = ipAddress.find(splitStr);
262 if (idx == std::string::npos) {
263 if (isSourceIp) {
264 command.append(" -s " + ipAddress);
265 } else {
266 command.append(" -d " + ipAddress);
267 }
268 } else {
269 if (isSourceIp) {
270 command.append(" -m iprange --src-range " + ipAddress);
271 } else {
272 command.append(" -m iprange --dst-range " + ipAddress);
273 }
274 }
275 }
276
ConvertPortCommand(const std::string & port,const bool isSourcePort,std::string & command)277 void IptablesRulePlugin::ConvertPortCommand(const std::string &port, const bool isSourcePort, std::string &command)
278 {
279 if (port.empty()) {
280 return;
281 }
282 if (isSourcePort) {
283 command.append(" --sport " + port);
284 } else {
285 command.append(" --dport " + port);
286 }
287 }
288
ConvertUidCommand(const std::string & uid,std::string & command)289 void IptablesRulePlugin::ConvertUidCommand(const std::string &uid, std::string &command)
290 {
291 if (uid.empty()) {
292 return;
293 }
294 command.append(" -m owner --uid-owner " + uid);
295 }
296
ConvertRuleNoCommand(const IPTABLES::AddMethod & method,uint32_t ruleNo,std::string & command)297 void IptablesRulePlugin::ConvertRuleNoCommand(const IPTABLES::AddMethod &method, uint32_t ruleNo, std::string &command)
298 {
299 if (method == IPTABLES::AddMethod::INSERT && ruleNo != 0) {
300 command.append(" " + std::to_string(ruleNo));
301 }
302 }
303 } // namespace EDM
304 } // namespace OHOS
305