]>
Commit | Line | Data |
---|---|---|
98e0c0a0 RG |
1 | import dns |
2 | import os | |
3 | import socket | |
b2d3e2b0 | 4 | import unittest |
98e0c0a0 RG |
5 | |
6 | import paddingoption | |
7 | ||
8 | from recursortests import RecursorTest | |
9 | ||
8ba588d0 | 10 | class RecursorEDNSPaddingTest(RecursorTest): |
98e0c0a0 RG |
11 | |
12 | @classmethod | |
13 | def setUpClass(cls): | |
14 | cls.setUpSockets() | |
15 | ||
16 | cls.startResponders() | |
17 | ||
18 | confdir = os.path.join('configs', cls._confdir) | |
19 | cls.createConfigDir(confdir) | |
20 | cls.generateAllAuthConfig(confdir) | |
21 | ||
22 | # we only need these auths and this cuts the needed time in half | |
23 | if cls._auth_zones: | |
24 | for auth_suffix in ['8', '9', '10']: | |
25 | authconfdir = os.path.join(confdir, 'auth-%s' % auth_suffix) | |
26 | ipaddress = cls._PREFIX + '.' + auth_suffix | |
27 | cls.startAuth(authconfdir, ipaddress) | |
28 | ||
29 | cls.generateRecursorConfig(confdir) | |
30 | cls.startRecursor(confdir, cls._recursorPort) | |
31 | ||
32 | print("Launching tests..") | |
33 | ||
34 | def checkPadding(self, message, numberOfBytes=None): | |
b2d3e2b0 | 35 | self.assertEqual(message.edns, 0) |
4bfebc93 | 36 | self.assertEqual(len(message.options), 1) |
b2d3e2b0 | 37 | for option in message.options: |
4bfebc93 | 38 | self.assertEqual(option.otype, 12) |
b2d3e2b0 | 39 | if numberOfBytes: |
4bfebc93 | 40 | self.assertEqual(option.olen, numberOfBytes) |
98e0c0a0 RG |
41 | |
42 | def checkNoPadding(self, message): | |
b2d3e2b0 | 43 | self.assertEqual(message.edns, 0) |
4bfebc93 | 44 | self.assertEqual(len(message.options), 0) |
98e0c0a0 | 45 | |
8ba588d0 | 46 | def checkNoEDNS(self, message): |
b2d3e2b0 RG |
47 | self.assertEqual(message.edns, -1) |
48 | ||
49 | def sendUDPQueryTo(self, query, toAddr, v6=True, timeout=2.0): | |
50 | if v6: | |
51 | sock = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM) | |
52 | else: | |
53 | sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) | |
54 | ||
55 | sock.settimeout(2.0) | |
56 | sock.connect((toAddr, self._recursorPort)) | |
57 | ||
98e0c0a0 | 58 | if timeout: |
b2d3e2b0 | 59 | sock.settimeout(timeout) |
98e0c0a0 | 60 | |
b2d3e2b0 RG |
61 | try: |
62 | sock.send(query.to_wire()) | |
63 | data = sock.recv(4096) | |
64 | except socket.timeout: | |
65 | data = None | |
66 | ||
67 | sock.close() | |
68 | message = None | |
69 | if data: | |
70 | message = dns.message.from_wire(data) | |
71 | return message | |
98e0c0a0 | 72 | |
8ba588d0 RG |
73 | def testQueryWithoutEDNS(self): |
74 | name = 'secure.example.' | |
75 | expected = dns.rrset.from_text(name, 0, dns.rdataclass.IN, 'A', '192.0.2.17') | |
76 | query = dns.message.make_query(name, 'A', want_dnssec=False) | |
77 | query.flags |= dns.flags.CD | |
78 | res = self.sendUDPQuery(query) | |
79 | self.checkNoEDNS(res) | |
80 | self.assertRRsetInAnswer(res, expected) | |
81 | ||
82 | class PaddingDefaultTest(RecursorEDNSPaddingTest): | |
98e0c0a0 RG |
83 | |
84 | _confdir = 'PaddingDefault' | |
85 | ||
86 | def testQueryWithPadding(self): | |
87 | name = 'secure.example.' | |
88 | expected = dns.rrset.from_text(name, 0, dns.rdataclass.IN, 'A', '192.0.2.17') | |
89 | po = paddingoption.PaddingOption(64) | |
90 | query = dns.message.make_query(name, 'A', want_dnssec=True, options=[po]) | |
91 | query.flags |= dns.flags.CD | |
92 | res = self.sendUDPQuery(query) | |
93 | self.checkNoPadding(res) | |
94 | self.assertRRsetInAnswer(res, expected) | |
95 | ||
8ba588d0 | 96 | def testQueryWithoutPadding(self): |
98e0c0a0 RG |
97 | name = 'secure.example.' |
98 | expected = dns.rrset.from_text(name, 0, dns.rdataclass.IN, 'A', '192.0.2.17') | |
99 | query = dns.message.make_query(name, 'A', want_dnssec=True) | |
100 | query.flags |= dns.flags.CD | |
101 | res = self.sendUDPQuery(query) | |
102 | self.checkNoPadding(res) | |
103 | self.assertRRsetInAnswer(res, expected) | |
104 | ||
b2d3e2b0 RG |
105 | class PaddingDefaultNotAllowedTest(RecursorEDNSPaddingTest): |
106 | ||
107 | _confdir = 'PaddingDefaultNotAllowed' | |
108 | _config_template = """edns-padding-from=127.0.0.2 | |
109 | packetcache-ttl=60 | |
110 | """ | |
111 | ||
112 | def testQueryWithPadding(self): | |
113 | name = 'secure.example.' | |
114 | expected = dns.rrset.from_text(name, 0, dns.rdataclass.IN, 'A', '192.0.2.17') | |
115 | po = paddingoption.PaddingOption(64) | |
116 | query = dns.message.make_query(name, 'A', want_dnssec=True, options=[po]) | |
117 | query.flags |= dns.flags.CD | |
118 | res = self.sendUDPQuery(query) | |
119 | self.checkNoPadding(res) | |
120 | self.assertRRsetInAnswer(res, expected) | |
121 | ||
122 | def testQueryWithoutPadding(self): | |
123 | name = 'secure.example.' | |
124 | expected = dns.rrset.from_text(name, 0, dns.rdataclass.IN, 'A', '192.0.2.17') | |
125 | query = dns.message.make_query(name, 'A', want_dnssec=True) | |
126 | query.flags |= dns.flags.CD | |
127 | res = self.sendUDPQuery(query) | |
128 | self.checkNoPadding(res) | |
129 | self.assertRRsetInAnswer(res, expected) | |
130 | ||
131 | class PaddingAlwaysTest(RecursorEDNSPaddingTest): | |
98e0c0a0 RG |
132 | |
133 | _confdir = 'PaddingAlways' | |
134 | _config_template = """edns-padding-from=127.0.0.1 | |
135 | edns-padding-mode=always | |
136 | edns-padding-tag=7830 | |
b2d3e2b0 | 137 | packetcache-ttl=60 |
98e0c0a0 | 138 | """ |
48d7dc10 RG |
139 | _lua_dns_script_file = """ |
140 | function preresolve(dq) | |
141 | if dq.qname == newDN("host1.secure.example.") then | |
142 | -- check that EDNS Padding was enabled (default) | |
143 | if dq.addPaddingToResponse ~= true then | |
144 | -- and stop the process otherwise | |
145 | return true | |
146 | end | |
147 | -- disable EDNS Padding | |
148 | dq.addPaddingToResponse = false | |
149 | end | |
150 | return false | |
151 | end | |
152 | ||
153 | local ffi = require("ffi") | |
154 | ||
155 | ffi.cdef[[ | |
156 | typedef struct pdns_ffi_param pdns_ffi_param_t; | |
157 | ||
158 | const char* pdns_ffi_param_get_qname(pdns_ffi_param_t* ref); | |
159 | void pdns_ffi_param_set_padding_disabled(pdns_ffi_param_t* ref, bool disabled); | |
160 | ]] | |
161 | ||
162 | function gettag_ffi(ref) | |
163 | local qname = ffi.string(ffi.C.pdns_ffi_param_get_qname(ref)) | |
164 | if qname == 'host1.sub.secure.example' then | |
165 | ffi.C.pdns_ffi_param_set_padding_disabled(ref, true) | |
166 | end | |
167 | end | |
168 | """ | |
98e0c0a0 RG |
169 | |
170 | def testQueryWithPadding(self): | |
171 | name = 'secure.example.' | |
172 | expected = dns.rrset.from_text(name, 0, dns.rdataclass.IN, 'A', '192.0.2.17') | |
173 | po = paddingoption.PaddingOption(64) | |
174 | query = dns.message.make_query(name, 'A', want_dnssec=True, options=[po]) | |
175 | query.flags |= dns.flags.CD | |
176 | res = self.sendUDPQuery(query) | |
177 | self.checkPadding(res) | |
178 | self.assertRRsetInAnswer(res, expected) | |
179 | ||
48d7dc10 RG |
180 | def testQueryWithPaddingButDisabledViaLua(self): |
181 | name = 'host1.secure.example.' | |
182 | expected = dns.rrset.from_text(name, 0, dns.rdataclass.IN, 'A', '192.0.2.2') | |
183 | po = paddingoption.PaddingOption(64) | |
184 | query = dns.message.make_query(name, 'A', want_dnssec=True, options=[po]) | |
185 | query.flags |= dns.flags.CD | |
186 | res = self.sendUDPQuery(query) | |
187 | self.checkNoPadding(res) | |
188 | self.assertRRsetInAnswer(res, expected) | |
189 | ||
190 | def testQueryWithPaddingButDisabledViaGettagFFI(self): | |
191 | name = 'host1.sub.secure.example.' | |
192 | expected = dns.rrset.from_text(name, 0, dns.rdataclass.IN, 'A', '192.0.2.11') | |
193 | po = paddingoption.PaddingOption(64) | |
194 | query = dns.message.make_query(name, 'A', want_dnssec=True, options=[po]) | |
195 | query.flags |= dns.flags.CD | |
196 | query.flags |= dns.flags.RD | |
197 | res = self.sendUDPQuery(query) | |
198 | self.checkNoPadding(res) | |
199 | self.assertRRsetInAnswer(res, expected) | |
200 | ||
8ba588d0 | 201 | def testQueryWithoutPadding(self): |
98e0c0a0 RG |
202 | name = 'secure.example.' |
203 | expected = dns.rrset.from_text(name, 0, dns.rdataclass.IN, 'A', '192.0.2.17') | |
204 | query = dns.message.make_query(name, 'A', want_dnssec=True) | |
205 | query.flags |= dns.flags.CD | |
206 | res = self.sendUDPQuery(query) | |
207 | self.checkPadding(res) | |
208 | self.assertRRsetInAnswer(res, expected) | |
209 | ||
b2d3e2b0 RG |
210 | class PaddingNotAllowedAlwaysTest(RecursorEDNSPaddingTest): |
211 | ||
212 | _confdir = 'PaddingAlwaysNotAllowed' | |
213 | _config_template = """edns-padding-from=127.0.0.2 | |
214 | edns-padding-mode=always | |
215 | edns-padding-tag=7830 | |
216 | packetcache-ttl=60 | |
217 | """ | |
218 | ||
219 | def testQueryWithPadding(self): | |
220 | name = 'secure.example.' | |
221 | expected = dns.rrset.from_text(name, 0, dns.rdataclass.IN, 'A', '192.0.2.17') | |
222 | po = paddingoption.PaddingOption(64) | |
223 | query = dns.message.make_query(name, 'A', want_dnssec=True, options=[po]) | |
224 | query.flags |= dns.flags.CD | |
225 | res = self.sendUDPQuery(query) | |
226 | self.checkNoPadding(res) | |
227 | self.assertRRsetInAnswer(res, expected) | |
228 | ||
229 | def testQueryWithoutPadding(self): | |
230 | name = 'secure.example.' | |
231 | expected = dns.rrset.from_text(name, 0, dns.rdataclass.IN, 'A', '192.0.2.17') | |
232 | query = dns.message.make_query(name, 'A', want_dnssec=True) | |
233 | query.flags |= dns.flags.CD | |
234 | res = self.sendUDPQuery(query) | |
235 | self.checkNoPadding(res) | |
236 | self.assertRRsetInAnswer(res, expected) | |
237 | ||
238 | class PaddingWhenPaddedTest(RecursorEDNSPaddingTest): | |
98e0c0a0 RG |
239 | |
240 | _confdir = 'PaddingWhenPadded' | |
241 | _config_template = """edns-padding-from=127.0.0.1 | |
242 | edns-padding-mode=padded-queries-only | |
243 | edns-padding-tag=7830 | |
b2d3e2b0 RG |
244 | local-address=127.0.0.1 |
245 | packetcache-ttl=60 | |
98e0c0a0 RG |
246 | """ |
247 | ||
248 | def testQueryWithPadding(self): | |
249 | name = 'secure.example.' | |
250 | expected = dns.rrset.from_text(name, 0, dns.rdataclass.IN, 'A', '192.0.2.17') | |
251 | po = paddingoption.PaddingOption(64) | |
252 | query = dns.message.make_query(name, 'A', want_dnssec=True, options=[po]) | |
253 | query.flags |= dns.flags.CD | |
254 | res = self.sendUDPQuery(query) | |
255 | self.checkPadding(res) | |
256 | self.assertRRsetInAnswer(res, expected) | |
257 | ||
8ba588d0 | 258 | def testQueryWithoutPadding(self): |
98e0c0a0 RG |
259 | name = 'secure.example.' |
260 | expected = dns.rrset.from_text(name, 0, dns.rdataclass.IN, 'A', '192.0.2.17') | |
261 | query = dns.message.make_query(name, 'A', want_dnssec=True) | |
262 | query.flags |= dns.flags.CD | |
263 | res = self.sendUDPQuery(query) | |
264 | self.checkNoPadding(res) | |
265 | self.assertRRsetInAnswer(res, expected) | |
266 | ||
b2d3e2b0 RG |
267 | class PaddingWhenPaddedNotAllowedTest(RecursorEDNSPaddingTest): |
268 | ||
269 | _confdir = 'PaddingWhenPaddedNotAllowed' | |
270 | _config_template = """edns-padding-from=127.0.0.2 | |
271 | edns-padding-mode=padded-queries-only | |
272 | edns-padding-tag=7830 | |
273 | local-address=127.0.0.1 | |
274 | packetcache-ttl=60 | |
275 | """ | |
276 | ||
277 | def testQueryWithPadding(self): | |
278 | name = 'secure.example.' | |
279 | expected = dns.rrset.from_text(name, 0, dns.rdataclass.IN, 'A', '192.0.2.17') | |
280 | po = paddingoption.PaddingOption(64) | |
281 | query = dns.message.make_query(name, 'A', want_dnssec=True, options=[po]) | |
282 | query.flags |= dns.flags.CD | |
283 | res = self.sendUDPQuery(query) | |
284 | self.checkNoPadding(res) | |
285 | self.assertRRsetInAnswer(res, expected) | |
286 | ||
287 | def testQueryWithoutPadding(self): | |
288 | name = 'secure.example.' | |
289 | expected = dns.rrset.from_text(name, 0, dns.rdataclass.IN, 'A', '192.0.2.17') | |
290 | query = dns.message.make_query(name, 'A', want_dnssec=True) | |
291 | query.flags |= dns.flags.CD | |
292 | res = self.sendUDPQuery(query) | |
293 | self.checkNoPadding(res) | |
294 | self.assertRRsetInAnswer(res, expected) | |
295 | ||
296 | @unittest.skipIf('SKIP_IPV6_TESTS' in os.environ, 'IPv6 tests are disabled') | |
8ba588d0 | 297 | class PaddingAllowedAlwaysSameTagTest(RecursorEDNSPaddingTest): |
98e0c0a0 RG |
298 | |
299 | # we use the default tag (0) for padded responses, which will cause | |
300 | # the same packet cache entry (with padding ) to be returned to a client | |
301 | # not allowed by the edns-padding-from list | |
302 | _confdir = 'PaddingAlwaysSameTag' | |
303 | _config_template = """edns-padding-from=127.0.0.1 | |
304 | edns-padding-mode=always | |
305 | edns-padding-tag=0 | |
306 | local-address=127.0.0.1, ::1 | |
b2d3e2b0 | 307 | packetcache-ttl=60 |
98e0c0a0 RG |
308 | """ |
309 | ||
fc7a90f5 RG |
310 | @classmethod |
311 | def setUpClass(cls): | |
312 | if 'SKIP_IPV6_TESTS' in os.environ: | |
313 | raise unittest.SkipTest('IPv6 tests are disabled') | |
314 | ||
315 | super(PaddingAllowedAlwaysSameTagTest, cls).setUpClass() | |
316 | ||
98e0c0a0 RG |
317 | def testQueryWithPadding(self): |
318 | name = 'secure.example.' | |
319 | expected = dns.rrset.from_text(name, 0, dns.rdataclass.IN, 'A', '192.0.2.17') | |
320 | po = paddingoption.PaddingOption(64) | |
321 | query = dns.message.make_query(name, 'A', want_dnssec=True, options=[po]) | |
322 | query.flags |= dns.flags.CD | |
323 | res = self.sendUDPQuery(query) | |
324 | self.checkPadding(res) | |
325 | self.assertRRsetInAnswer(res, expected) | |
326 | ||
b2d3e2b0 | 327 | res = self.sendUDPQueryTo(query, '::1') |
98e0c0a0 RG |
328 | self.checkPadding(res) |
329 | self.assertRRsetInAnswer(res, expected) | |
330 | ||
8ba588d0 | 331 | def testQueryWithoutPadding(self): |
98e0c0a0 RG |
332 | name = 'secure.example.' |
333 | expected = dns.rrset.from_text(name, 0, dns.rdataclass.IN, 'A', '192.0.2.17') | |
334 | query = dns.message.make_query(name, 'A', want_dnssec=True) | |
335 | query.flags |= dns.flags.CD | |
336 | res = self.sendUDPQuery(query) | |
337 | self.checkPadding(res) | |
338 | self.assertRRsetInAnswer(res, expected) | |
339 | ||
b2d3e2b0 | 340 | res = self.sendUDPQueryTo(query, '::1') |
98e0c0a0 RG |
341 | self.checkPadding(res) |
342 | self.assertRRsetInAnswer(res, expected) |