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