• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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