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