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