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