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