1 /*
2  * Copyright (c) 2023 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_chain_rule.h"
17 
18 #include <algorithm>
19 #include <iostream>
20 #include <sstream>
21 #include <string>
22 
23 #include "rule_utils.h"
24 
25 namespace OHOS {
26 namespace EDM {
27 namespace IPTABLES {
28 
FirewallChainRule()29 FirewallChainRule::FirewallChainRule(): ChainRule()
30 {
31     target_ = ACCEPT_TARGET;
32     state_ = "RELATED,ESTABLISHED";
33 }
34 
FirewallChainRule(FirewallRule firewallTuple)35 FirewallChainRule::FirewallChainRule(FirewallRule firewallTuple) : ChainRule(),
36     srcPort_(std::get<FIREWALL_SRCPORT_IND>(firewallTuple)),
37     destPort_(std::get<FIREWALL_DESTPORT_IND>(firewallTuple)),
38     appUid_(std::get<FIREWALL_APPUID_IND>(firewallTuple))
39 {
40     target_ = RuleUtils::EnumToString(std::get<FIREWALL_ACTION_IND>(firewallTuple));
41     prot_ = RuleUtils::EnumToString(std::get<FIREWALL_PROT_IND>(firewallTuple));
42     srcAddr_ = std::get<FIREWALL_SRCADDR_IND>(firewallTuple);
43     destAddr_ = std::get<FIREWALL_DESTADDR_IND>(firewallTuple);
44 }
45 
FirewallChainRule(const std::string & rule)46 FirewallChainRule::FirewallChainRule(const std::string &rule) : ChainRule(rule)
47 {
48     GetOption(otherOptions_, "source IP range", srcAddr_);
49     GetOption(otherOptions_, "destination IP range", destAddr_);
50     std::string spt;
51     GetOption(otherOptions_, "spt:", spt);
52     if (spt.empty()) {
53         GetOption(otherOptions_, "spts:", spt);
54         if (spt.empty()) {
55             GetOption(otherOptions_, "multiport sports", spt);
56         }
57     }
58     srcPort_ = spt;
59     std::string dpt;
60     GetOption(otherOptions_, "dpt:", dpt);
61     if (dpt.empty()) {
62         GetOption(otherOptions_, "dpts:", dpt);
63         if (dpt.empty()) {
64             GetOption(otherOptions_, "multiport dports", dpt);
65         }
66     }
67     destPort_ = dpt;
68     GetOption(otherOptions_, "owner UID match", appUid_);
69 }
70 
Parameter() const71 std::string FirewallChainRule::Parameter() const
72 {
73     std::ostringstream parameterString;
74     if (!prot_.empty()) {
75         parameterString << " -p ";
76         parameterString << prot_;
77     }
78     parameterString << IpToParameter(srcAddr_, "-s");
79     parameterString << IpToParameter(destAddr_, "-d");
80 
81     std::string splitStr = ",";
82     auto sidx = srcPort_.find(splitStr);
83     auto didx = destPort_.find(splitStr);
84     std::string portOption = SPACE_OPTION;
85     if (sidx != std::string::npos || didx != std::string::npos) {
86         portOption = " -m multiport ";
87     }
88     parameterString << PortToParameter(srcPort_, "--sport", portOption);
89     parameterString << PortToParameter(destPort_, "--dport", portOption);
90     if (!appUid_.empty()) {
91         parameterString << " -m owner --uid-owner " << appUid_;
92     }
93     if (!state_.empty()) {
94         parameterString << " -m state --state " << state_;
95     }
96     return parameterString.str();
97 }
98 
IpToParameter(const std::string & ip,const std::string & ipType)99 std::string FirewallChainRule::IpToParameter(const std::string &ip, const std::string &ipType)
100 {
101     if (ip.empty()) {
102         return {};
103     }
104     std::ostringstream parameterString;
105     std::string splitStr = "-";
106     auto idx = ip.find(splitStr);
107     if (idx == std::string::npos) {
108         parameterString << SPACE_OPTION << ipType << SPACE_OPTION << ip;
109     } else {
110         if (ipType == "-s") {
111             parameterString << " -m iprange --src-range " << ip;
112         } else {
113             parameterString << " -m iprange --dst-range " << ip;
114         }
115     }
116     return parameterString.str();
117 }
118 
PortToParameter(const std::string & port,const std::string & portType,const std::string & portOption)119 std::string FirewallChainRule::PortToParameter(const std::string &port, const std::string &portType,
120     const std::string &portOption)
121 {
122     if (port.empty()) {
123         return {};
124     }
125     std::ostringstream parameterString;
126     parameterString << portOption << portType << SPACE_OPTION << port;
127     return parameterString.str();
128 }
129 
ToFilterRule(Direction direction)130 FirewallRule FirewallChainRule::ToFilterRule(Direction direction)
131 {
132     Action action = RuleUtils::StringToAction(target_);
133     Protocol protocl = RuleUtils::StringProtocl(prot_);
134     return {direction, action, protocl, srcAddr_, destAddr_, srcPort_, destPort_, appUid_};
135 }
136 
137 } // namespace IPTABLES
138 } // namespace EDM
139 } // namespace OHOS