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