]>
Commit | Line | Data |
---|---|---|
12471842 PL |
1 | /* |
2 | * This file is part of PowerDNS or dnsdist. | |
3 | * Copyright -- PowerDNS.COM B.V. and its contributors | |
4 | * | |
5 | * This program is free software; you can redistribute it and/or modify | |
6 | * it under the terms of version 2 of the GNU General Public License as | |
7 | * published by the Free Software Foundation. | |
8 | * | |
9 | * In addition, for the avoidance of any doubt, permission is granted to | |
10 | * link this program with OpenSSL and to (re)distribute the binaries | |
11 | * produced as the result of such linking. | |
12 | * | |
13 | * This program is distributed in the hope that it will be useful, | |
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 | * GNU General Public License for more details. | |
17 | * | |
18 | * You should have received a copy of the GNU General Public License | |
19 | * along with this program; if not, write to the Free Software | |
20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |
21 | */ | |
644dd1da | 22 | #include "filterpo.hh" |
23 | #include <iostream> | |
24 | #include "namespaces.hh" | |
25 | #include "dnsrecords.hh" | |
26 | ||
27 | DNSFilterEngine::DNSFilterEngine() | |
28 | { | |
29 | } | |
30 | ||
a2d0450e | 31 | static bool findNamedPolicy(const std::unordered_map<DNSName, DNSFilterEngine::Policy>& polmap, const DNSName& qname, DNSFilterEngine::Policy& pol) |
644dd1da | 32 | { |
5678437b PL |
33 | /* for www.powerdns.com, we need to check: |
34 | www.powerdns.com. | |
35 | *.powerdns.com. | |
36 | *.com. | |
37 | *. | |
38 | */ | |
0a273054 | 39 | |
a2d0450e RG |
40 | std::unordered_map<DNSName, DNSFilterEngine::Policy>::const_iterator iter; |
41 | iter = polmap.find(qname); | |
bef458b2 PL |
42 | |
43 | if(iter != polmap.end()) { | |
44 | pol=iter->second; | |
45 | return true; | |
46 | } | |
5678437b | 47 | |
a2d0450e | 48 | DNSName s(qname); |
bef458b2 | 49 | while(s.chopOff()){ |
12c06211 | 50 | iter = polmap.find(g_wildcarddnsname+s); |
5678437b PL |
51 | if(iter != polmap.end()) { |
52 | pol=iter->second; | |
53 | return true; | |
54 | } | |
bef458b2 | 55 | } |
644dd1da | 56 | return false; |
57 | } | |
58 | ||
0a273054 | 59 | DNSFilterEngine::Policy DNSFilterEngine::getProcessingPolicy(const DNSName& qname, const std::unordered_map<std::string,bool>& discardedPolicies) const |
644dd1da | 60 | { |
39ec5d29 | 61 | // cout<<"Got question for nameserver name "<<qname<<endl; |
1f1ca368 | 62 | Policy pol; |
644dd1da | 63 | for(const auto& z : d_zones) { |
6b972d59 RG |
64 | const auto zoneName = z->getName(); |
65 | if(zoneName && discardedPolicies.find(*zoneName) != discardedPolicies.end()) { | |
0a273054 RG |
66 | continue; |
67 | } | |
68 | ||
6b972d59 | 69 | if(findNamedPolicy(z->d_propolName, qname, pol)) { |
de0f72ba | 70 | // cerr<<"Had a hit on the nameserver ("<<qname<<") used to process the query"<<endl; |
644dd1da | 71 | return pol; |
72 | } | |
73 | } | |
74 | return pol; | |
b8470add | 75 | } |
644dd1da | 76 | |
0a273054 | 77 | DNSFilterEngine::Policy DNSFilterEngine::getProcessingPolicy(const ComboAddress& address, const std::unordered_map<std::string,bool>& discardedPolicies) const |
b8470add PL |
78 | { |
79 | // cout<<"Got question for nameserver IP "<<address.toString()<<endl; | |
80 | for(const auto& z : d_zones) { | |
6b972d59 RG |
81 | const auto zoneName = z->getName(); |
82 | if(zoneName && discardedPolicies.find(*zoneName) != discardedPolicies.end()) { | |
0a273054 RG |
83 | continue; |
84 | } | |
85 | ||
6b972d59 | 86 | if(auto fnd=z->d_propolNSAddr.lookup(address)) { |
b8470add PL |
87 | // cerr<<"Had a hit on the nameserver ("<<address.toString()<<") used to process the query"<<endl; |
88 | return fnd->second;; | |
89 | } | |
90 | } | |
1f1ca368 | 91 | return Policy(); |
b8470add | 92 | } |
644dd1da | 93 | |
0a273054 | 94 | DNSFilterEngine::Policy DNSFilterEngine::getQueryPolicy(const DNSName& qname, const ComboAddress& ca, const std::unordered_map<std::string,bool>& discardedPolicies) const |
644dd1da | 95 | { |
de0f72ba | 96 | // cout<<"Got question for "<<qname<<" from "<<ca.toString()<<endl; |
1f1ca368 | 97 | Policy pol; |
644dd1da | 98 | for(const auto& z : d_zones) { |
6b972d59 RG |
99 | const auto zoneName = z->getName(); |
100 | if(zoneName && discardedPolicies.find(*zoneName) != discardedPolicies.end()) { | |
0a273054 RG |
101 | continue; |
102 | } | |
103 | ||
6b972d59 | 104 | if(findNamedPolicy(z->d_qpolName, qname, pol)) { |
de0f72ba | 105 | // cerr<<"Had a hit on the name of the query"<<endl; |
644dd1da | 106 | return pol; |
107 | } | |
108 | ||
6b972d59 | 109 | if(auto fnd=z->d_qpolAddr.lookup(ca)) { |
0e760497 | 110 | // cerr<<"Had a hit on the IP address ("<<ca.toString()<<") of the client"<<endl; |
111 | return fnd->second; | |
644dd1da | 112 | } |
113 | } | |
114 | ||
39ec5d29 | 115 | return pol; |
644dd1da | 116 | } |
117 | ||
0a273054 | 118 | DNSFilterEngine::Policy DNSFilterEngine::getPostPolicy(const vector<DNSRecord>& records, const std::unordered_map<std::string,bool>& discardedPolicies) const |
644dd1da | 119 | { |
120 | ComboAddress ca; | |
644dd1da | 121 | for(const auto& r : records) { |
589ad24b | 122 | if(r.d_place != DNSResourceRecord::ANSWER) |
644dd1da | 123 | continue; |
ba3c54cb RG |
124 | if(r.d_type == QType::A) { |
125 | if (auto rec = getRR<ARecordContent>(r)) { | |
126 | ca = rec->getCA(); | |
127 | } | |
128 | } | |
129 | else if(r.d_type == QType::AAAA) { | |
130 | if (auto rec = getRR<AAAARecordContent>(r)) { | |
131 | ca = rec->getCA(); | |
132 | } | |
133 | } | |
644dd1da | 134 | else |
135 | continue; | |
136 | ||
137 | for(const auto& z : d_zones) { | |
6b972d59 RG |
138 | const auto zoneName = z->getName(); |
139 | if(zoneName && discardedPolicies.find(*zoneName) != discardedPolicies.end()) { | |
0a273054 RG |
140 | continue; |
141 | } | |
142 | ||
6b972d59 | 143 | if(auto fnd=z->d_postpolAddr.lookup(ca)) |
0e760497 | 144 | return fnd->second; |
644dd1da | 145 | } |
146 | } | |
1f1ca368 | 147 | return Policy(); |
644dd1da | 148 | } |
149 | ||
0a273054 | 150 | void DNSFilterEngine::assureZones(size_t zone) |
644dd1da | 151 | { |
0a273054 | 152 | if(d_zones.size() <= zone) |
644dd1da | 153 | d_zones.resize(zone+1); |
644dd1da | 154 | } |
155 | ||
6b972d59 | 156 | void DNSFilterEngine::Zone::addClientTrigger(const Netmask& nm, Policy pol) |
7eafc52f | 157 | { |
6b972d59 RG |
158 | pol.d_name = d_name; |
159 | d_qpolAddr.insert(nm).second=pol; | |
7eafc52f | 160 | } |
161 | ||
6b972d59 | 162 | void DNSFilterEngine::Zone::addResponseTrigger(const Netmask& nm, Policy pol) |
0a7ef1b8 | 163 | { |
6b972d59 RG |
164 | pol.d_name = d_name; |
165 | d_postpolAddr.insert(nm).second=pol; | |
644dd1da | 166 | } |
167 | ||
6b972d59 | 168 | void DNSFilterEngine::Zone::addQNameTrigger(const DNSName& n, Policy pol) |
644dd1da | 169 | { |
6b972d59 RG |
170 | pol.d_name = d_name; |
171 | d_qpolName[n]=pol; | |
644dd1da | 172 | } |
173 | ||
6b972d59 | 174 | void DNSFilterEngine::Zone::addNSTrigger(const DNSName& n, Policy pol) |
644dd1da | 175 | { |
6b972d59 RG |
176 | pol.d_name = d_name; |
177 | d_propolName[n]=pol; | |
644dd1da | 178 | } |
179 | ||
6b972d59 | 180 | void DNSFilterEngine::Zone::addNSIPTrigger(const Netmask& nm, Policy pol) |
644dd1da | 181 | { |
6b972d59 RG |
182 | pol.d_name = d_name; |
183 | d_propolNSAddr.insert(nm).second = pol; | |
644dd1da | 184 | } |
39ec5d29 | 185 | |
6b972d59 | 186 | bool DNSFilterEngine::Zone::rmClientTrigger(const Netmask& nm, Policy pol) |
b8470add | 187 | { |
6b972d59 | 188 | d_qpolAddr.erase(nm); |
39ec5d29 | 189 | return true; |
190 | } | |
191 | ||
6b972d59 | 192 | bool DNSFilterEngine::Zone::rmResponseTrigger(const Netmask& nm, Policy pol) |
39ec5d29 | 193 | { |
6b972d59 | 194 | d_postpolAddr.erase(nm); |
39ec5d29 | 195 | return true; |
196 | } | |
197 | ||
6b972d59 | 198 | bool DNSFilterEngine::Zone::rmQNameTrigger(const DNSName& n, Policy pol) |
39ec5d29 | 199 | { |
6b972d59 | 200 | d_qpolName.erase(n); // XXX verify we had identical policy? |
39ec5d29 | 201 | return true; |
202 | } | |
203 | ||
6b972d59 | 204 | bool DNSFilterEngine::Zone::rmNSTrigger(const DNSName& n, Policy pol) |
39ec5d29 | 205 | { |
6b972d59 | 206 | d_propolName.erase(n); // XXX verify policy matched? =pol; |
39ec5d29 | 207 | return true; |
208 | } | |
b8470add | 209 | |
6b972d59 | 210 | bool DNSFilterEngine::Zone::rmNSIPTrigger(const Netmask& nm, Policy pol) |
b8470add | 211 | { |
6b972d59 | 212 | d_propolNSAddr.erase(nm); |
b8470add PL |
213 | return true; |
214 | } | |
a9e029ee RG |
215 | |
216 | DNSRecord DNSFilterEngine::Policy::getCustomRecord(const DNSName& qname) const | |
217 | { | |
218 | if (d_kind != PolicyKind::Custom) { | |
219 | throw std::runtime_error("Asking for a custom record from a filtering policy of a non-custom type"); | |
220 | } | |
221 | ||
222 | DNSRecord result; | |
223 | result.d_name = qname; | |
224 | result.d_type = d_custom->getType(); | |
225 | result.d_ttl = d_ttl; | |
226 | result.d_class = QClass::IN; | |
227 | result.d_place = DNSResourceRecord::ANSWER; | |
228 | result.d_content = d_custom; | |
229 | ||
230 | if (result.d_type == QType::CNAME) { | |
231 | const auto content = std::dynamic_pointer_cast<CNAMERecordContent>(d_custom); | |
232 | if (content) { | |
233 | DNSName target = content->getTarget(); | |
234 | if (target.isWildcard()) { | |
235 | target.chopOff(); | |
236 | result.d_content = std::make_shared<CNAMERecordContent>(qname + target); | |
237 | } | |
238 | } | |
239 | } | |
240 | ||
241 | return result; | |
242 | } |