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