• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 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 "firewall_manager.h"
17 
18 #include <fstream>
19 #include <sstream>
20 
21 #include "iptables_wrapper.h"
22 #include "net_manager_constants.h"
23 #include "netnative_log_wrapper.h"
24 
25 namespace OHOS {
26 namespace nmd {
27 using namespace NetManagerStandard;
28 namespace {
29 static constexpr const char *CONFIG_FILE_PATH = "/proc/self/uid_map";
SetFireWallCommand(const std::string & chainName,std::string command)30 bool SetFireWallCommand(const std::string &chainName, std::string command)
31 {
32     bool ret = false;
33     ret = ret ||
34           (IptablesWrapper::GetInstance()->RunCommand(IPTYPE_IPV4, command) == NETMANAGER_ERROR);
35 
36     command = "-t filter -A " + chainName + " -i lo -j RETURN";
37     ret = ret ||
38           (IptablesWrapper::GetInstance()->RunCommand(IPTYPE_IPV4, command) == NETMANAGER_ERROR);
39     command = "-t filter -A " + chainName + " -o lo -j RETURN";
40     ret = ret ||
41           (IptablesWrapper::GetInstance()->RunCommand(IPTYPE_IPV4, command) == NETMANAGER_ERROR);
42     command = "-t filter -A " + chainName + " -p tcp --tcp-flags RST RST -j RETURN";
43     ret = ret ||
44           (IptablesWrapper::GetInstance()->RunCommand(IPTYPE_IPV4, command) == NETMANAGER_ERROR);
45     return ret;
46 }
47 } // namespace
48 
49 static constexpr uint32_t SYSTEM_UID_RANGE = 9999;
50 static constexpr uint32_t DEFAULT_MAX_UID_RANGE = UINT_MAX;
FirewallManager()51 FirewallManager::FirewallManager() : chainInitFlag_(false), firewallType_(FirewallType::TYPE_ALLOWED_LIST)
52 {
53     strMaxUid_ = ReadMaxUidConfig();
54     FirewallChainStatus status = {};
55     status.enable = false;
56     status.type = FirewallType::TYPE_ALLOWED_LIST;
57     firewallChainStatus_[ChainType::CHAIN_OHFW_DOZABLE] = status;
58     firewallChainStatus_[ChainType::CHAIN_OHFW_POWERSAVING] = status;
59     firewallChainStatus_[ChainType::CHAIN_OHFW_UNDOZABLE] = status;
60 }
61 
~FirewallManager()62 FirewallManager::~FirewallManager()
63 {
64     DeInitChain();
65 }
66 
CheckChainInitialization()67 inline void FirewallManager::CheckChainInitialization()
68 {
69     if (chainInitFlag_ == false) {
70         InitChain();
71         InitDefaultRules();
72     }
73 }
74 
ReadMaxUidConfig()75 std::string FirewallManager::ReadMaxUidConfig()
76 {
77     NETNATIVE_LOG_D("FirewallManager::ReadMaxUidConfig");
78     std::string maxUid;
79     std::string content;
80 
81     std::ifstream file(CONFIG_FILE_PATH);
82     if (!file.is_open()) {
83         NETNATIVE_LOGE("FirewallManager::ReadMaxUidConfig fstream failed");
84         return std::to_string(DEFAULT_MAX_UID_RANGE);
85     }
86 
87     std::ostringstream oss;
88     oss << file.rdbuf();
89     content = oss.str();
90     auto index = content.find_last_of(' ');
91     maxUid = content.substr(index + 1);
92     // if unavailable value use default value
93     if (maxUid.size() == 0) {
94         return std::to_string(DEFAULT_MAX_UID_RANGE);
95     }
96 
97     return maxUid;
98 }
99 
IsFirewallChian(ChainType chain)100 int32_t FirewallManager::IsFirewallChian(ChainType chain)
101 {
102     if (chain != ChainType::CHAIN_OHFW_DOZABLE && chain != ChainType::CHAIN_OHFW_POWERSAVING
103         && chain != ChainType::CHAIN_OHFW_UNDOZABLE) {
104         return NETMANAGER_ERROR;
105     }
106     return NETMANAGER_SUCCESS;
107 }
108 
FetchChainName(ChainType chain)109 std::string FirewallManager::FetchChainName(ChainType chain)
110 {
111     NETNATIVE_LOG_D("FirewallManager FetchChainName: chain=%{public}d", chain);
112     std::string chainName;
113     switch (chain) {
114         case ChainType::CHAIN_OHFW_INPUT:
115             chainName = "ohfw_INPUT";
116             break;
117         case ChainType::CHAIN_OHFW_OUTPUT:
118             chainName = "ohfw_OUTPUT";
119             break;
120         case ChainType::CHAIN_OHFW_FORWARD:
121             chainName = "ohfw_FORWARD";
122             break;
123         case ChainType::CHAIN_OHFW_DOZABLE:
124             chainName = "ohfw_dozable";
125             break;
126         case ChainType::CHAIN_OHFW_POWERSAVING:
127             chainName = "ohfw_powersaving";
128             break;
129         case ChainType::CHAIN_OHFW_UNDOZABLE:
130             chainName = "ohfw_undozable";
131             break;
132         default:
133             chainName = "oh_unusable";
134             break;
135     }
136     return chainName;
137 }
138 
FetchChainType(ChainType chain)139 FirewallType FirewallManager::FetchChainType(ChainType chain)
140 {
141     FirewallType firewallType;
142     switch (chain) {
143         case ChainType::CHAIN_OHFW_DOZABLE:
144             firewallType = FirewallType::TYPE_ALLOWED_LIST;
145             break;
146         case ChainType::CHAIN_OHFW_POWERSAVING:
147             firewallType = FirewallType::TYPE_ALLOWED_LIST;
148             break;
149         case ChainType::CHAIN_OHFW_UNDOZABLE:
150             firewallType = FirewallType::TYPE_DENIDE_LIST;
151             break;
152         default:
153             firewallType = FirewallType::TYPE_ALLOWED_LIST;
154             break;
155     }
156     return firewallType;
157 }
158 
InitChain()159 int32_t FirewallManager::InitChain()
160 {
161     NETNATIVE_LOG_D("FirewallManager InitChain");
162     bool ret = false;
163     ret = (IptablesNewChain(ChainType::CHAIN_OHFW_INPUT) == NETMANAGER_ERROR) ||
164           (IptablesNewChain(ChainType::CHAIN_OHFW_OUTPUT) == NETMANAGER_ERROR) ||
165           (IptablesNewChain(ChainType::CHAIN_OHFW_FORWARD) == NETMANAGER_ERROR) ||
166           (IptablesNewChain(ChainType::CHAIN_OHFW_DOZABLE) == NETMANAGER_ERROR) ||
167           (IptablesNewChain(ChainType::CHAIN_OHFW_POWERSAVING) == NETMANAGER_ERROR) ||
168           (IptablesNewChain(ChainType::CHAIN_OHFW_UNDOZABLE) == NETMANAGER_ERROR);
169     chainInitFlag_ = true;
170     return ret == false ? NETMANAGER_SUCCESS : NETMANAGER_ERROR;
171 }
172 
DeInitChain()173 int32_t FirewallManager::DeInitChain()
174 {
175     NETNATIVE_LOG_D("FirewallManager DeInitChain");
176     bool ret = false;
177     ret = (IptablesDeleteChain(ChainType::CHAIN_OHFW_INPUT) == NETMANAGER_ERROR) ||
178           (IptablesDeleteChain(ChainType::CHAIN_OHFW_OUTPUT) == NETMANAGER_ERROR) ||
179           (IptablesDeleteChain(ChainType::CHAIN_OHFW_FORWARD) == NETMANAGER_ERROR) ||
180           (IptablesDeleteChain(ChainType::CHAIN_OHFW_DOZABLE) == NETMANAGER_ERROR) ||
181           (IptablesDeleteChain(ChainType::CHAIN_OHFW_POWERSAVING) == NETMANAGER_ERROR) ||
182           (IptablesDeleteChain(ChainType::CHAIN_OHFW_UNDOZABLE) == NETMANAGER_ERROR);
183     chainInitFlag_ = false;
184     return ret == false ? NETMANAGER_SUCCESS : NETMANAGER_ERROR;
185 }
186 
InitDefaultRules()187 int32_t FirewallManager::InitDefaultRules()
188 {
189     NETNATIVE_LOG_D("FirewallManager InitDefaultRules");
190     bool ret = false;
191     std::string chainName = FetchChainName(ChainType::CHAIN_OHFW_INPUT);
192     std::string command = "-t filter -A INPUT -j " + chainName;
193     ret = ret ||
194           (IptablesWrapper::GetInstance()->RunCommand(IPTYPE_IPV4, command) == NETMANAGER_ERROR);
195     chainName = FetchChainName(ChainType::CHAIN_OHFW_OUTPUT);
196     command = "-t filter -A OUTPUT -j " + chainName;
197     ret = ret ||
198           (IptablesWrapper::GetInstance()->RunCommand(IPTYPE_IPV4, command) == NETMANAGER_ERROR);
199     return ret == false ? NETMANAGER_SUCCESS : NETMANAGER_ERROR;
200 }
201 
ClearAllRules()202 int32_t FirewallManager::ClearAllRules()
203 {
204     NETNATIVE_LOG_D("FirewallManager ClearAllRules");
205     bool ret = false;
206 
207     std::string chainName = FetchChainName(ChainType::CHAIN_OHFW_DOZABLE);
208     std::string command = "-t filter -F " + chainName;
209     ret = ret ||
210           (IptablesWrapper::GetInstance()->RunCommand(IPTYPE_IPV4, command) == NETMANAGER_ERROR);
211 
212     chainName = FetchChainName(ChainType::CHAIN_OHFW_POWERSAVING);
213     command = "-t filter -F " + chainName;
214     ret =
215         ret || (IptablesWrapper::GetInstance()->RunCommand(IPTYPE_IPV4, command) == NETMANAGER_ERROR);
216 
217     chainName = FetchChainName(ChainType::CHAIN_OHFW_UNDOZABLE);
218     command = "-t filter -F " + chainName;
219     ret =
220         ret || (IptablesWrapper::GetInstance()->RunCommand(IPTYPE_IPV4, command) == NETMANAGER_ERROR);
221 
222     chainName = FetchChainName(ChainType::CHAIN_OHFW_INPUT);
223     command = "-t filter -F " + chainName;
224     ret =
225         ret || (IptablesWrapper::GetInstance()->RunCommand(IPTYPE_IPV4, command) == NETMANAGER_ERROR);
226 
227     chainName = FetchChainName(ChainType::CHAIN_OHFW_OUTPUT);
228     command = "-t filter -F " + chainName;
229     ret = ret ||
230           (IptablesWrapper::GetInstance()->RunCommand(IPTYPE_IPV4, command) == NETMANAGER_ERROR);
231     chainName = FetchChainName(ChainType::CHAIN_OHFW_FORWARD);
232     command = "-t filter -F " + chainName;
233     ret = ret ||
234           (IptablesWrapper::GetInstance()->RunCommand(IPTYPE_IPV4, command) == NETMANAGER_ERROR);
235     return ret == false ? NETMANAGER_SUCCESS : NETMANAGER_ERROR;
236 }
237 
IptablesNewChain(ChainType chain)238 int32_t FirewallManager::IptablesNewChain(ChainType chain)
239 {
240     NETNATIVE_LOG_D("FirewallManager NewChain: chain=%{public}d", chain);
241     std::string command = "-t filter -N " + FetchChainName(chain);
242     return IptablesWrapper::GetInstance()->RunCommand(IPTYPE_IPV4, command);
243 }
244 
IptablesDeleteChain(ChainType chain)245 int32_t FirewallManager::IptablesDeleteChain(ChainType chain)
246 {
247     NETNATIVE_LOG_D("FirewallManager DeleteChain: chain=%{public}d", chain);
248     bool ret = false;
249     std::string command = "-t filter -F " + FetchChainName(chain);
250     ret = ret ||
251           (IptablesWrapper::GetInstance()->RunCommand(IPTYPE_IPV4, command) == NETMANAGER_ERROR);
252     command = "-t filter -X " + FetchChainName(chain);
253     ret = ret ||
254           (IptablesWrapper::GetInstance()->RunCommand(IPTYPE_IPV4, command) == NETMANAGER_ERROR);
255     return ret == false ? NETMANAGER_SUCCESS : NETMANAGER_ERROR;
256 }
257 
IptablesSetRule(const std::string & chainName,const std::string & option,const std::string & target,uint32_t uid)258 int32_t FirewallManager::IptablesSetRule(const std::string &chainName, const std::string &option,
259                                          const std::string &target, uint32_t uid)
260 {
261     NETNATIVE_LOG_D("FirewallManager IptablesSetRule");
262     std::string command =
263         "-t filter " + option + " " + chainName + " -m owner --uid-owner " + std::to_string(uid) + " -j " + target;
264     return IptablesWrapper::GetInstance()->RunCommand(IPTYPE_IPV4, command);
265 }
266 
SetUidsAllowedListChain(ChainType chain,const std::vector<uint32_t> & uids)267 int32_t FirewallManager::SetUidsAllowedListChain(ChainType chain, const std::vector<uint32_t> &uids)
268 {
269     NETNATIVE_LOG_D("FirewallManager SetUidsAllowedListChain: chain=%{public}d", chain);
270     if (chain != ChainType::CHAIN_OHFW_DOZABLE && chain != ChainType::CHAIN_OHFW_POWERSAVING) {
271         return NETMANAGER_ERROR;
272     }
273 
274     bool ret = false;
275     std::unique_lock<std::mutex> lock(firewallMutex_);
276     CheckChainInitialization();
277 
278     std::string command;
279     const auto &chainName = FetchChainName(chain);
280 
281     command = "-t filter -F " + chainName;
282     ret = ret ||
283           (IptablesWrapper::GetInstance()->RunCommand(IPTYPE_IPV4, command) == NETMANAGER_ERROR);
284 
285     std::for_each(uids.begin(), uids.end(), [&command, &chainName, &ret](uint32_t uid) {
286         std::string strUid = std::to_string(uid);
287         command = "-t filter -A " + chainName + " -m owner --uid-owner " + strUid + " -j RETURN";
288         ret = ret || (IptablesWrapper::GetInstance()->RunCommand(IPTYPE_IPV4, command) ==
289                       NETMANAGER_ERROR);
290     });
291 
292     command =
293         "-t filter -A " + chainName + " -m owner --uid-owner 0-" + std::to_string(SYSTEM_UID_RANGE) + " -j RETURN";
294     ret = ret ||
295           (IptablesWrapper::GetInstance()->RunCommand(IPTYPE_IPV4, command) == NETMANAGER_ERROR);
296     command = "-t filter -A " + chainName + " -m owner ! --uid-owner 0-" + strMaxUid_ + " -j RETURN";
297 
298     ret = SetFireWallCommand(chainName, command);
299 
300     command = "-t filter -A " + chainName + " -j DROP";
301     ret = ret ||
302           (IptablesWrapper::GetInstance()->RunCommand(IPTYPE_IPV4, command) == NETMANAGER_ERROR);
303     if (ret == false) {
304         FirewallChainStatus status = firewallChainStatus_[chain];
305         status.uids = uids;
306         firewallChainStatus_[chain] = status;
307     }
308 
309     return ret == false ? NETMANAGER_SUCCESS : NETMANAGER_ERROR;
310 }
311 
SetUidsDeniedListChain(ChainType chain,const std::vector<uint32_t> & uids)312 int32_t FirewallManager::SetUidsDeniedListChain(ChainType chain, const std::vector<uint32_t> &uids)
313 {
314     NETNATIVE_LOG_D("FirewallManager SetUidsDeniedListChain: chain=%{public}d", chain);
315     if (chain != ChainType::CHAIN_OHFW_UNDOZABLE) {
316         return NETMANAGER_ERROR;
317     }
318 
319     std::unique_lock<std::mutex> lock(firewallMutex_);
320     bool ret = false;
321     CheckChainInitialization();
322 
323     std::string command;
324     const auto &chainName = FetchChainName(chain);
325 
326     command = "-t filter -F " + chainName;
327 
328     ret = SetFireWallCommand(chainName, command);
329 
330     std::for_each(uids.begin(), uids.end(), [&command, &chainName, &ret](uint32_t uid) {
331         std::string strUid = std::to_string(uid);
332         command = "-t filter -A " + chainName + " -m owner --uid-owner " + strUid + " -j DROP";
333         ret = ret || (IptablesWrapper::GetInstance()->RunCommand(IPTYPE_IPV4, command) ==
334                       NETMANAGER_ERROR);
335     });
336 
337     if (ret == false) {
338         FirewallChainStatus status = firewallChainStatus_[chain];
339         status.uids = uids;
340         firewallChainStatus_[chain] = status;
341     }
342 
343     return ret == false ? NETMANAGER_SUCCESS : NETMANAGER_ERROR;
344 }
345 
EnableChain(ChainType chain,bool enable)346 int32_t FirewallManager::EnableChain(ChainType chain, bool enable)
347 {
348     NETNATIVE_LOG_D("FirewallManager EnableChain: chain=%{public}d, enable=%{public}d", chain, enable);
349     if (IsFirewallChian(chain) == NETMANAGER_ERROR) {
350         return NETMANAGER_ERROR;
351     }
352 
353     bool ret = false;
354     std::unique_lock<std::mutex> lock(firewallMutex_);
355     CheckChainInitialization();
356 
357     std::string chainName;
358     std::string fChainName;
359     chainName = FetchChainName(chain);
360     std::string command;
361 
362     if (enable == true && firewallChainStatus_[chain].enable == false) {
363         fChainName = FetchChainName(ChainType::CHAIN_OHFW_OUTPUT);
364         command = "-t filter -A " + fChainName + " -j " + chainName;
365         ret = ret || (IptablesWrapper::GetInstance()->RunCommand(IPTYPE_IPV4, command) ==
366                       NETMANAGER_ERROR);
367     } else if (enable == false && firewallChainStatus_[chain].enable == true) {
368         fChainName = FetchChainName(ChainType::CHAIN_OHFW_OUTPUT);
369         command = "-t filter -D " + fChainName + " -j " + chainName;
370         ret = ret || (IptablesWrapper::GetInstance()->RunCommand(IPTYPE_IPV4, command) ==
371                       NETMANAGER_ERROR);
372     } else {
373         NETNATIVE_LOGI("FirewallManager::EnableChain chain was %{public}s, do not repeat",
374                        enable == true ? "true" : "false");
375         return NETMANAGER_ERROR;
376     }
377 
378     if (ret == false) {
379         firewallType_ = FetchChainType(chain);
380         firewallChainStatus_[chain].enable = enable;
381     }
382 
383     return ret == false ? NETMANAGER_SUCCESS : NETMANAGER_ERROR;
384 }
385 
SetUidRule(ChainType chain,uint32_t uid,FirewallRule firewallRule)386 int32_t FirewallManager::SetUidRule(ChainType chain, uint32_t uid, FirewallRule firewallRule)
387 {
388     NETNATIVE_LOG_D("FirewallManager SetUidRule: chain=%{public}d, uid=%{public}d, firewallRule=%{public}d", chain,
389                     uid, firewallRule);
390     if (IsFirewallChian(chain) == NETMANAGER_ERROR) {
391         return NETMANAGER_ERROR;
392     }
393 
394     bool ret = false;
395     std::unique_lock<std::mutex> lock(firewallMutex_);
396     CheckChainInitialization();
397 
398     std::string op;
399     std::string target;
400     std::string chainName = FetchChainName(chain);
401     FirewallType firewallType = FetchChainType(chain);
402     if (firewallType == FirewallType::TYPE_DENIDE_LIST) {
403         target = "DROP";
404         op = (firewallRule == FirewallRule::RULE_DENY) ? "-A" : "-D";
405     } else {
406         target = "RETURN";
407         op = (firewallRule == FirewallRule::RULE_ALLOW) ? "-I" : "-D";
408     }
409 
410     FirewallChainStatus status = firewallChainStatus_[chain];
411     std::vector<uint32_t>::iterator iter = std::find(status.uids.begin(), status.uids.end(), uid);
412     if (op != "-D" && iter == status.uids.end()) {
413         status.uids.push_back(uid);
414         ret = ret || (IptablesSetRule(chainName, op, target, uid) == NETMANAGER_ERROR);
415     } else if (op == "-D" && iter != status.uids.end()) {
416         status.uids.erase(iter);
417         ret = ret || (IptablesSetRule(chainName, op, target, uid) == NETMANAGER_ERROR);
418     } else {
419         NETNATIVE_LOGE("FirewallManager::SetUidRule error");
420         return NETMANAGER_ERROR;
421     }
422 
423     if (ret == false) {
424         firewallChainStatus_[chain] = status;
425     }
426 
427     return ret == false ? NETMANAGER_SUCCESS : NETMANAGER_ERROR;
428 }
429 } // namespace nmd
430 } // namespace OHOS
431