]> git.ipfire.org Git - thirdparty/pdns.git/blame - regression-tests.dnsdist/test_Trailing.py
Merge pull request #14036 from romeroalx/meson-auth-ci
[thirdparty/pdns.git] / regression-tests.dnsdist / test_Trailing.py
CommitLineData
55baa1f2
RG
1#!/usr/bin/env python
2import threading
3import dns
630eb526 4from dnsdisttests import DNSDistTest, pickAvailablePort
55baa1f2 5
4aa08b62 6class TestTrailingDataToBackend(DNSDistTest):
55baa1f2
RG
7
8 # this test suite uses a different responder port
9 # because, contrary to the other ones, its
10 # responders allow trailing data and we don't want
11 # to mix things up.
630eb526 12 _testServerPort = pickAvailablePort()
51f07ad4 13 _verboseMode = True
55baa1f2
RG
14 _config_template = """
15 newServer{address="127.0.0.1:%s"}
93446f2d
RG
16
17 function replaceTrailingData(dq)
7d243a5e 18 local success = dq:setTrailingData("ABC")
93446f2d
RG
19 if not success then
20 return DNSAction.ServFail, ""
21 end
22 return DNSAction.None, ""
23 end
955de53b 24 addAction("added.trailing.tests.powerdns.com.", LuaAction(replaceTrailingData))
93446f2d
RG
25
26 function fillBuffer(dq)
f1c712f7
RG
27 local available = 4096 - dq.len
28 if dq.tcp then
29 available = 65535 - dq.len
30 end
7d243a5e 31 local tail = string.rep("A", available)
93446f2d
RG
32 local success = dq:setTrailingData(tail)
33 if not success then
34 return DNSAction.ServFail, ""
35 end
36 return DNSAction.None, ""
37 end
955de53b 38 addAction("max.trailing.tests.powerdns.com.", LuaAction(fillBuffer))
93446f2d
RG
39
40 function exceedBuffer(dq)
f1c712f7
RG
41 local available = 4096 - dq.len
42 if dq.tcp then
43 available = 65535 - dq.len
44 end
7d243a5e 45 local tail = string.rep("A", available + 1)
93446f2d
RG
46 local success = dq:setTrailingData(tail)
47 if not success then
48 return DNSAction.ServFail, ""
49 end
50 return DNSAction.None, ""
51 end
955de53b 52 addAction("limited.trailing.tests.powerdns.com.", LuaAction(exceedBuffer))
55baa1f2
RG
53 """
54 @classmethod
55 def startResponders(cls):
56 print("Launching responders..")
57
93446f2d
RG
58 # Respond REFUSED to queries with trailing data.
59 cls._UDPResponder = threading.Thread(name='UDP Responder', target=cls.UDPResponder, args=[cls._testServerPort, cls._toResponderQueue, cls._fromResponderQueue, dns.rcode.REFUSED])
630eb526 60 cls._UDPResponder.daemon = True
55baa1f2 61 cls._UDPResponder.start()
5df86a8a 62
93446f2d
RG
63 # Respond REFUSED to queries with trailing data.
64 cls._TCPResponder = threading.Thread(name='TCP Responder', target=cls.TCPResponder, args=[cls._testServerPort, cls._toResponderQueue, cls._fromResponderQueue, dns.rcode.REFUSED])
630eb526 65 cls._TCPResponder.daemon = True
55baa1f2
RG
66 cls._TCPResponder.start()
67
4aa08b62 68 def testTrailingPassthrough(self):
55baa1f2 69 """
4aa08b62 70 Trailing data: Pass through
55baa1f2
RG
71
72 """
4aa08b62 73 name = 'passthrough.trailing.tests.powerdns.com.'
55baa1f2
RG
74 query = dns.message.make_query(name, 'A', 'IN')
75 response = dns.message.make_response(query)
76 rrset = dns.rrset.from_text(name,
77 3600,
78 dns.rdataclass.IN,
79 dns.rdatatype.A,
80 '127.0.0.1')
81 response.answer.append(rrset)
4aa08b62 82 expectedResponse = dns.message.make_response(query)
93446f2d 83 expectedResponse.set_rcode(dns.rcode.REFUSED)
55baa1f2
RG
84
85 raw = query.to_wire()
b4f23783 86 raw = raw + b'A'* 20
55baa1f2 87
4aa08b62
RG
88 for method in ("sendUDPQuery", "sendTCPQuery"):
89 sender = getattr(self, method)
4aa08b62
RG
90 (receivedQuery, receivedResponse) = sender(raw, response, rawQuery=True)
91 self.assertTrue(receivedQuery)
92 self.assertTrue(receivedResponse)
93 receivedQuery.id = query.id
4bfebc93
CH
94 self.assertEqual(receivedQuery, query)
95 self.assertEqual(receivedResponse, expectedResponse)
4aa08b62 96
93446f2d
RG
97 def testTrailingCapacity(self):
98 """
99 Trailing data: Fill buffer
100
101 """
102 name = 'max.trailing.tests.powerdns.com.'
103 query = dns.message.make_query(name, 'A', 'IN')
104 response = dns.message.make_response(query)
105 rrset = dns.rrset.from_text(name,
106 3600,
107 dns.rdataclass.IN,
108 dns.rdatatype.A,
109 '127.0.0.1')
110 response.answer.append(rrset)
111 expectedResponse = dns.message.make_response(query)
112 expectedResponse.set_rcode(dns.rcode.REFUSED)
113
114 for method in ("sendUDPQuery", "sendTCPQuery"):
115 sender = getattr(self, method)
93446f2d
RG
116 (receivedQuery, receivedResponse) = sender(query, response)
117 self.assertTrue(receivedQuery)
118 self.assertTrue(receivedResponse)
119 receivedQuery.id = query.id
4bfebc93
CH
120 self.assertEqual(receivedQuery, query)
121 self.assertEqual(receivedResponse, expectedResponse)
93446f2d
RG
122
123 def testTrailingLimited(self):
124 """
125 Trailing data: Reject buffer overflows
126
127 """
128 name = 'limited.trailing.tests.powerdns.com.'
129 query = dns.message.make_query(name, 'A', 'IN')
130 response = dns.message.make_response(query)
131 rrset = dns.rrset.from_text(name,
132 3600,
133 dns.rdataclass.IN,
134 dns.rdatatype.A,
135 '127.0.0.1')
136 response.answer.append(rrset)
137 expectedResponse = dns.message.make_response(query)
138 expectedResponse.set_rcode(dns.rcode.SERVFAIL)
139
140 for method in ("sendUDPQuery", "sendTCPQuery"):
141 sender = getattr(self, method)
90186270 142 (_, receivedResponse) = sender(query, response, useQueue=False)
93446f2d 143 self.assertTrue(receivedResponse)
4bfebc93 144 self.assertEqual(receivedResponse, expectedResponse)
93446f2d
RG
145
146 def testTrailingAdded(self):
147 """
148 Trailing data: Add
149
150 """
151 name = 'added.trailing.tests.powerdns.com.'
152 query = dns.message.make_query(name, 'A', 'IN')
153 response = dns.message.make_response(query)
154 rrset = dns.rrset.from_text(name,
155 3600,
156 dns.rdataclass.IN,
157 dns.rdatatype.A,
158 '127.0.0.1')
159 response.answer.append(rrset)
160 expectedResponse = dns.message.make_response(query)
161 expectedResponse.set_rcode(dns.rcode.REFUSED)
162
163 for method in ("sendUDPQuery", "sendTCPQuery"):
164 sender = getattr(self, method)
93446f2d
RG
165 (receivedQuery, receivedResponse) = sender(query, response)
166 self.assertTrue(receivedQuery)
167 self.assertTrue(receivedResponse)
168 receivedQuery.id = query.id
4bfebc93
CH
169 self.assertEqual(receivedQuery, query)
170 self.assertEqual(receivedResponse, expectedResponse)
93446f2d 171
4aa08b62 172class TestTrailingDataToDnsdist(DNSDistTest):
51f07ad4 173 _verboseMode = True
4aa08b62
RG
174 _config_template = """
175 newServer{address="127.0.0.1:%s"}
93446f2d
RG
176
177 addAction(AndRule({QNameRule("dropped.trailing.tests.powerdns.com."), TrailingDataRule()}), DropAction())
178
179 function removeTrailingData(dq)
7d243a5e 180 local success = dq:setTrailingData("")
93446f2d 181 if not success then
51f07ad4 182 print("Trailing removal failed")
93446f2d
RG
183 return DNSAction.ServFail, ""
184 end
185 return DNSAction.None, ""
186 end
955de53b 187 addAction("removed.trailing.tests.powerdns.com.", LuaAction(removeTrailingData))
93446f2d 188
157445b5 189 function reportTrailingData(dq)
7d243a5e
RG
190 local tail = dq:getTrailingData()
191 return DNSAction.Spoof, "-" .. tail .. ".echoed.trailing.tests.powerdns.com."
157445b5 192 end
955de53b 193 addAction("echoed.trailing.tests.powerdns.com.", LuaAction(reportTrailingData))
93446f2d
RG
194
195 function replaceTrailingData(dq)
7d243a5e 196 local success = dq:setTrailingData("ABC")
93446f2d
RG
197 if not success then
198 return DNSAction.ServFail, ""
199 end
200 return DNSAction.None, ""
201 end
955de53b
PD
202 addAction("replaced.trailing.tests.powerdns.com.", LuaAction(replaceTrailingData))
203 addAction("replaced.trailing.tests.powerdns.com.", LuaAction(reportTrailingData))
6b32cb3e
RG
204
205 function reportTrailingHex(dq)
206 local tail = dq:getTrailingData()
207 local hex = string.gsub(tail, ".", function(ch)
bf0ff88f 208 return string.sub(string.format("\\x2502X", string.byte(ch)), -2)
6b32cb3e
RG
209 end)
210 return DNSAction.Spoof, "-0x" .. hex .. ".echoed-hex.trailing.tests.powerdns.com."
211 end
955de53b 212 addAction("echoed-hex.trailing.tests.powerdns.com.", LuaAction(reportTrailingHex))
6b32cb3e
RG
213
214 function replaceTrailingData_unsafe(dq)
bf0ff88f 215 local success = dq:setTrailingData("\\xB0\\x00\\xDE\\xADB\\xF0\\x9F\\x91\\xBB\\xC3\\xBE")
6b32cb3e
RG
216 if not success then
217 return DNSAction.ServFail, ""
218 end
219 return DNSAction.None, ""
220 end
955de53b
PD
221 addAction("replaced-unsafe.trailing.tests.powerdns.com.", LuaAction(replaceTrailingData_unsafe))
222 addAction("replaced-unsafe.trailing.tests.powerdns.com.", LuaAction(reportTrailingHex))
4aa08b62 223 """
55baa1f2
RG
224
225 def testTrailingDropped(self):
226 """
4aa08b62 227 Trailing data: Drop query
55baa1f2
RG
228
229 """
230 name = 'dropped.trailing.tests.powerdns.com.'
4aa08b62
RG
231 query = dns.message.make_query(name, 'A', 'IN')
232 response = dns.message.make_response(query)
233 rrset = dns.rrset.from_text(name,
234 3600,
235 dns.rdataclass.IN,
236 dns.rdatatype.A,
237 '127.0.0.1')
238 response.answer.append(rrset)
55baa1f2
RG
239
240 raw = query.to_wire()
b4f23783 241 raw = raw + b'A'* 20
55baa1f2 242
4aa08b62
RG
243 for method in ("sendUDPQuery", "sendTCPQuery"):
244 sender = getattr(self, method)
245
246 # Verify that queries with no trailing data make it through.
4aa08b62
RG
247 (receivedQuery, receivedResponse) = sender(query, response)
248 self.assertTrue(receivedQuery)
249 self.assertTrue(receivedResponse)
250 receivedQuery.id = query.id
4bfebc93
CH
251 self.assertEqual(query, receivedQuery)
252 self.assertEqual(response, receivedResponse)
4aa08b62
RG
253
254 # Verify that queries with trailing data don't make it through.
90186270 255 (_, receivedResponse) = sender(raw, response, rawQuery=True, useQueue=False)
4bfebc93 256 self.assertEqual(receivedResponse, None)
157445b5 257
93446f2d
RG
258 def testTrailingRemoved(self):
259 """
260 Trailing data: Remove
261
262 """
263 name = 'removed.trailing.tests.powerdns.com.'
264 query = dns.message.make_query(name, 'A', 'IN')
265 response = dns.message.make_response(query)
266 rrset = dns.rrset.from_text(name,
267 3600,
268 dns.rdataclass.IN,
269 dns.rdatatype.A,
270 '127.0.0.1')
271 response.answer.append(rrset)
272
273 raw = query.to_wire()
274 raw = raw + b'A'* 20
275
276 for method in ("sendUDPQuery", "sendTCPQuery"):
277 sender = getattr(self, method)
93446f2d
RG
278 (receivedQuery, receivedResponse) = sender(raw, response, rawQuery=True)
279 self.assertTrue(receivedQuery)
280 self.assertTrue(receivedResponse)
281 receivedQuery.id = query.id
4bfebc93
CH
282 self.assertEqual(receivedQuery, query)
283 self.assertEqual(receivedResponse, response)
93446f2d 284
157445b5
RG
285 def testTrailingRead(self):
286 """
6b32cb3e 287 Trailing data: Echo
157445b5
RG
288
289 """
290 name = 'echoed.trailing.tests.powerdns.com.'
291 query = dns.message.make_query(name, 'A', 'IN')
292 response = dns.message.make_response(query)
293 response.set_rcode(dns.rcode.SERVFAIL)
294 expectedResponse = dns.message.make_response(query)
295 rrset = dns.rrset.from_text(name,
296 60,
297 dns.rdataclass.IN,
298 dns.rdatatype.CNAME,
93446f2d
RG
299 '-TrailingData.echoed.trailing.tests.powerdns.com.')
300 expectedResponse.answer.append(rrset)
301
302 raw = query.to_wire()
303 raw = raw + b'TrailingData'
304
305 for method in ("sendUDPQuery", "sendTCPQuery"):
306 sender = getattr(self, method)
90186270 307 (_, receivedResponse) = sender(raw, response=None, rawQuery=True, useQueue=False)
93446f2d
RG
308 self.assertTrue(receivedResponse)
309 expectedResponse.flags = receivedResponse.flags
4bfebc93 310 self.assertEqual(receivedResponse, expectedResponse)
93446f2d
RG
311
312 def testTrailingReplaced(self):
313 """
314 Trailing data: Replace
315
316 """
317 name = 'replaced.trailing.tests.powerdns.com.'
318 query = dns.message.make_query(name, 'A', 'IN')
319 response = dns.message.make_response(query)
320 response.set_rcode(dns.rcode.SERVFAIL)
321 expectedResponse = dns.message.make_response(query)
322 rrset = dns.rrset.from_text(name,
323 60,
324 dns.rdataclass.IN,
325 dns.rdatatype.CNAME,
326 '-ABC.echoed.trailing.tests.powerdns.com.')
157445b5
RG
327 expectedResponse.answer.append(rrset)
328
329 raw = query.to_wire()
330 raw = raw + b'TrailingData'
331
332 for method in ("sendUDPQuery", "sendTCPQuery"):
333 sender = getattr(self, method)
90186270 334 (_, receivedResponse) = sender(raw, response=None, rawQuery=True, useQueue=False)
157445b5
RG
335 self.assertTrue(receivedResponse)
336 expectedResponse.flags = receivedResponse.flags
4bfebc93 337 self.assertEqual(receivedResponse, expectedResponse)
6b32cb3e
RG
338
339 def testTrailingReadUnsafe(self):
340 """
341 Trailing data: Echo as hex
342
343 """
344 name = 'echoed-hex.trailing.tests.powerdns.com.'
345 query = dns.message.make_query(name, 'A', 'IN')
346 response = dns.message.make_response(query)
347 response.set_rcode(dns.rcode.SERVFAIL)
348 expectedResponse = dns.message.make_response(query)
349 rrset = dns.rrset.from_text(name,
350 60,
351 dns.rdataclass.IN,
352 dns.rdatatype.CNAME,
353 '-0x0000DEAD.echoed-hex.trailing.tests.powerdns.com.')
354 expectedResponse.answer.append(rrset)
355
356 raw = query.to_wire()
357 raw = raw + b'\x00\x00\xDE\xAD'
358
359 for method in ("sendUDPQuery", "sendTCPQuery"):
360 sender = getattr(self, method)
90186270 361 (_, receivedResponse) = sender(raw, response=None, rawQuery=True, useQueue=False)
6b32cb3e
RG
362 self.assertTrue(receivedResponse)
363 expectedResponse.flags = receivedResponse.flags
4bfebc93 364 self.assertEqual(receivedResponse, expectedResponse)
6b32cb3e
RG
365
366 def testTrailingReplacedUnsafe(self):
367 """
368 Trailing data: Replace with null and/or non-ASCII bytes
369
370 """
371 name = 'replaced-unsafe.trailing.tests.powerdns.com.'
372 query = dns.message.make_query(name, 'A', 'IN')
373 response = dns.message.make_response(query)
374 response.set_rcode(dns.rcode.SERVFAIL)
375 expectedResponse = dns.message.make_response(query)
376 rrset = dns.rrset.from_text(name,
377 60,
378 dns.rdataclass.IN,
379 dns.rdatatype.CNAME,
bf0ff88f 380 '-0xB000DEAD42F09F91BBC3BE.echoed-hex.trailing.tests.powerdns.com.')
6b32cb3e
RG
381 expectedResponse.answer.append(rrset)
382
383 raw = query.to_wire()
384 raw = raw + b'TrailingData'
385
386 for method in ("sendUDPQuery", "sendTCPQuery"):
387 sender = getattr(self, method)
90186270 388 (_, receivedResponse) = sender(raw, response=None, rawQuery=True, useQueue=False)
6b32cb3e
RG
389 self.assertTrue(receivedResponse)
390 expectedResponse.flags = receivedResponse.flags
4bfebc93 391 self.assertEqual(receivedResponse, expectedResponse)