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