]>
git.ipfire.org Git - thirdparty/pdns.git/blob - regression-tests.recursor-dnssec/recursortests.py
3 from __future__
import print_function
16 class RecursorTest ( unittest
. TestCase
):
18 Setup all recursors and auths required for the tests
23 _recursorStartupDelay
= 2.0
28 _PREFIX
= os
. environ
[ 'PREFIX' ]
30 _config_template_default
= """
34 local-address=127.0.0.1
36 packetcache-servfail-ttl=0
42 _config_template
= """
45 _lua_config_file
= None
46 _lua_dns_script_file
= None
49 ns.root. 3600 IN A %s .8
51 _root_DS
= "63149 13 1 a59da3f5c1b97fcd5fa2b3b2b0ac91d38a60d33a"
53 # The default SOA for zones in the authoritative servers
54 _SOA
= "ns1.example.net. hostmaster.example.net. 1 3600 1800 1209600 300"
56 # The definitions of the zones on the authoritative servers, the key is the
57 # zonename and the value is the zonefile content. several strings are replaced:
58 # - {soa} => value of _SOA
59 # - {prefix} value of _PREFIX
64 ns.root. 3600 IN A {prefix} .8
66 example. 3600 IN NS ns1.example.
67 example. 3600 IN NS ns2.example.
68 example. 3600 IN DS 53174 13 1 50c9e913818767c236c06c2d8272723cb78cbf26
70 ns1.example. 3600 IN A {prefix} .10
71 ns2.example. 3600 IN A {prefix} .11
74 example. 3600 IN SOA {soa}
75 example. 3600 IN NS ns1.example.
76 example. 3600 IN NS ns2.example.
77 ns1.example. 3600 IN A {prefix} .10
78 ns2.example. 3600 IN A {prefix} .11
80 secure.example. 3600 IN NS ns.secure.example.
81 secure.example. 3600 IN DS 64723 13 1 53eb985040d3a89bacf29dbddb55a65834706f33
82 ns.secure.example. 3600 IN A {prefix} .9
84 cname-secure.example. 3600 IN NS ns.cname-secure.example.
85 cname-secure.example. 3600 IN DS 49148 13 1 a10314452d5ec4d97fcc6d7e275d217261fe790f
86 ns.cname-secure.example. 3600 IN A {prefix} .15
88 dname-secure.example. 3600 IN NS ns.dname-secure.example.
89 dname-secure.example. 3600 IN DS 42043 13 2 11c67f46b7c4d5968bc5f6cc944d58377b762bda53ddb4f3a6dbe6faf7a9940f
90 ns.dname-secure.example. 3600 IN A {prefix} .13
92 bogus.example. 3600 IN NS ns.bogus.example.
93 bogus.example. 3600 IN DS 65034 13 1 6df3bb50ea538e90eacdd7ae5419730783abb0ee
94 ns.bogus.example. 3600 IN A {prefix} .12
96 insecure.example. 3600 IN NS ns.insecure.example.
97 ns.insecure.example. 3600 IN A {prefix} .13
99 optout.example. 3600 IN NS ns1.optout.example.
100 optout.example. 3600 IN DS 59332 13 1 e664f886ae1b5df03d918bc1217d22afc29925b9
101 ns1.optout.example. 3600 IN A {prefix} .14
103 insecure-formerr.example. 3600 IN NS ns1.insecure-formerr.example.
104 ns1.insecure-formerr.example. 3600 IN A {prefix} .2
106 ecs-echo.example. 3600 IN NS ns1.ecs-echo.example.
107 ns1.ecs-echo.example. 3600 IN A {prefix} .21
109 islandofsecurity.example. 3600 IN NS ns1.islandofsecurity.example.
110 ns1.islandofsecurity.example. 3600 IN A {prefix} .9
112 sortcname.example. 3600 IN CNAME sort
113 sort.example. 3600 IN A 17.38.42.80
114 sort.example. 3600 IN A 192.168.0.1
115 sort.example. 3600 IN A 17.238.240.5
116 sort.example. 3600 IN MX 25 mx
118 'secure.example' : """
119 secure.example. 3600 IN SOA {soa}
120 secure.example. 3600 IN NS ns.secure.example.
121 ns.secure.example. 3600 IN A {prefix} .9
123 secure.example. 3600 IN A 192.0.2.17
125 host1.secure.example. 3600 IN A 192.0.2.2
126 cname.secure.example. 3600 IN CNAME host1.secure.example.
127 cname-to-insecure.secure.example. 3600 IN CNAME node1.insecure.example.
128 cname-to-bogus.secure.example. 3600 IN CNAME ted.bogus.example.
129 cname-to-islandofsecurity.secure.example. 3600 IN CNAME node1.islandofsecurity.example.
131 host1.sub.secure.example. 3600 IN A 192.0.2.11
134 sub2.secure.example. 3600 IN CNAME doesnotmatter.insecure.example.
135 insecure.sub2.secure.example. 3600 IN NS ns1.insecure.example.
137 *.wildcard.secure.example. 3600 IN A 192.0.2.10
139 *.cnamewildcard.secure.example. 3600 IN CNAME host1.secure.example.
141 *.cnamewildcardnxdomain.secure.example. 3600 IN CNAME doesntexist.secure.example.
143 cname-to-formerr.secure.example. 3600 IN CNAME host1.insecure-formerr.example.
145 dname-secure.secure.example. 3600 IN DNAME dname-secure.example.
146 dname-insecure.secure.example. 3600 IN DNAME insecure.example.
147 dname-bogus.secure.example. 3600 IN DNAME bogus.example.
149 'dname-secure.example' : """
150 dname-secure.example. 3600 IN SOA {soa}
151 dname-secure.example. 3600 IN NS ns.dname-secure.example.
152 ns.dname-secure.example. 3600 IN A {prefix} .13
154 host1.dname-secure.example. IN A 192.0.2.21
156 cname-to-secure.dname-secure.example. 3600 IN CNAME host1.secure.example.
157 cname-to-insecure.dname-secure.example. 3600 IN CNAME node1.insecure.example.
158 cname-to-bogus.dname-secure.example. 3600 IN CNAME ted.bogus.example.
160 'cname-secure.example' : """
161 cname-secure.example. 3600 IN SOA {soa}
162 cname-secure.example. 3600 IN NS ns.cname-secure.example.
163 ns.cname-secure.example. 3600 IN A {prefix} .15
164 cname-secure.example. 3600 IN CNAME secure.example.
167 bogus.example. 3600 IN SOA {soa}
168 bogus.example. 3600 IN NS ns1.bogus.example.
169 ns1.bogus.example. 3600 IN A {prefix} .12
170 ted.bogus.example. 3600 IN A 192.0.2.1
171 bill.bogus.example. 3600 IN AAAA 2001:db8:12::3
173 'insecure.sub2.secure.example' : """
174 insecure.sub2.secure.example. 3600 IN SOA {soa}
175 insecure.sub2.secure.example. 3600 IN NS ns1.insecure.example.
177 node1.insecure.sub2.secure.example. 3600 IN A 192.0.2.18
179 'insecure.example' : """
180 insecure.example. 3600 IN SOA {soa}
181 insecure.example. 3600 IN NS ns1.insecure.example.
182 ns1.insecure.example. 3600 IN A {prefix} .13
184 node1.insecure.example. 3600 IN A 192.0.2.6
186 cname-to-secure.insecure.example. 3600 IN CNAME host1.secure.example.
188 dname-to-secure.insecure.example. 3600 IN DNAME dname-secure.example.
190 'optout.example' : """
191 optout.example. 3600 IN SOA {soa}
192 optout.example. 3600 IN NS ns1.optout.example.
193 ns1.optout.example. 3600 IN A {prefix} .14
195 insecure.optout.example. 3600 IN NS ns1.insecure.optout.example.
196 ns1.insecure.optout.example. 3600 IN A {prefix} .15
198 secure.optout.example. 3600 IN NS ns1.secure.optout.example.
199 secure.optout.example. 3600 IN DS 64215 13 1 b88284d7a8d8605c398e8942262f97b9a5a31787
200 ns1.secure.optout.example. 3600 IN A {prefix} .15
202 'insecure.optout.example' : """
203 insecure.optout.example. 3600 IN SOA {soa}
204 insecure.optout.example. 3600 IN NS ns1.insecure.optout.example.
205 ns1.insecure.optout.example. 3600 IN A {prefix} .15
207 node1.insecure.optout.example. 3600 IN A 192.0.2.7
209 'secure.optout.example' : """
210 secure.optout.example. 3600 IN SOA {soa}
211 secure.optout.example. 3600 IN NS ns1.secure.optout.example.
212 ns1.secure.optout.example. 3600 IN A {prefix} .15
214 node1.secure.optout.example. 3600 IN A 192.0.2.8
216 'islandofsecurity.example' : """
217 islandofsecurity.example. 3600 IN SOA {soa}
218 islandofsecurity.example. 3600 IN NS ns1.islandofsecurity.example.
219 ns1.islandofsecurity.example. 3600 IN A {prefix} .9
221 node1.islandofsecurity.example. 3600 IN A 192.0.2.20
223 'undelegated.secure.example' : """
224 undelegated.secure.example. 3600 IN SOA {soa}
225 undelegated.secure.example. 3600 IN NS ns1.undelegated.secure.example.
227 node1.undelegated.secure.example. 3600 IN A 192.0.2.21
229 'undelegated.insecure.example' : """
230 undelegated.insecure.example. 3600 IN SOA {soa}
231 undelegated.insecure.example. 3600 IN NS ns1.undelegated.insecure.example.
233 node1.undelegated.insecure.example. 3600 IN A 192.0.2.22
237 # The private keys for the zones (note that DS records should go into
238 # the zonecontent in _zones
241 Private-key-format: v1.2
242 Algorithm: 13 (ECDSAP256SHA256)
243 PrivateKey: rhWuEydDz3QaIspSVj683B8Xq5q/ozzA38XUgzD4Fbo=
247 Private-key-format: v1.2
248 Algorithm: 13 (ECDSAP256SHA256)
249 PrivateKey: Lt0v0Gol3pRUFM7fDdcy0IWN0O/MnEmVPA+VylL8Y4U=
252 'secure.example' : """
253 Private-key-format: v1.2
254 Algorithm: 13 (ECDSAP256SHA256)
255 PrivateKey: 1G4WRoOFJJXk+fotDCHVORtJmIG2OUhKi8AO2jDPGZA=
259 Private-key-format: v1.2
260 Algorithm: 13 (ECDSAP256SHA256)
261 PrivateKey: f5jV7Q8kd5hDpMWObsuQ6SQda0ftf+JrO3uZwEg6nVw=
264 'optout.example' : """
265 Private-key-format: v1.2
266 Algorithm: 13 (ECDSAP256SHA256)
267 PrivateKey: efmq9G+J4Y2iPnIBRwJiy6Z/nIHSzpsCy/7XHhlS19A=
270 'secure.optout.example' : """
271 Private-key-format: v1.2
272 Algorithm: 13 (ECDSAP256SHA256)
273 PrivateKey: xcNUxt1Knj14A00lKQFDboluiJyM2f7FxpgsQaQ3AQ4=
276 'islandofsecurity.example' : """
277 Private-key-format: v1.2
278 Algorithm: 13 (ECDSAP256SHA256)
279 PrivateKey: o9F5iix8V68tnMcuOaM2Lt8XXhIIY//SgHIHEePk6cM=
282 'cname-secure.example' : """
283 Private-key-format: v1.2
284 Algorithm: 13 (ECDSAP256SHA256)
285 PrivateKey: kvoV/g4IO/tefSro+FLJ5UC7H3BUf0IUtZQSUOfQGyA=
288 'dname-secure.example' : """
289 Private-key-format: v1.2
290 Algorithm: 13 (ECDSAP256SHA256)
291 PrivateKey: Ep9uo6+wwjb4MaOmqq7LHav2FLrjotVOeZg8JT1Qk04=
295 # This dict is keyed with the suffix of the IP address and its value
296 # is a list of zones hosted on that IP. Note that delegations should
297 # go into the _zones's zonecontent
300 '9' : [ 'secure.example' , 'islandofsecurity.example' ],
303 '12' : [ 'bogus.example' , 'undelegated.secure.example' , 'undelegated.insecure.example' ],
304 '13' : [ 'insecure.example' , 'insecure.sub2.secure.example' , 'dname-secure.example' ],
305 '14' : [ 'optout.example' ],
306 '15' : [ 'insecure.optout.example' , 'secure.optout.example' , 'cname-secure.example' ]
309 _auth_cmd
= [ 'authbind' ,
315 def createConfigDir ( cls
, confdir
):
317 shutil
. rmtree ( confdir
)
319 if e
. errno
!= errno
. ENOENT
:
321 os
. mkdir ( confdir
, 0o755 )
324 def generateAuthZone ( cls
, confdir
, zonename
, zonecontent
):
325 with
open ( os
. path
. join ( confdir
, ' %s .zone' % zonename
), 'w' ) as zonefile
:
326 zonefile
. write ( zonecontent
. format ( prefix
= cls
._ PREFIX
, soa
= cls
._ SOA
))
329 def generateAuthNamedConf ( cls
, confdir
, zones
):
330 with
open ( os
. path
. join ( confdir
, 'named.conf' ), 'w' ) as namedconf
:
335 for zonename
in zones
:
336 zone
= '.' if zonename
== 'ROOT' else zonename
342 };""" % ( zone
, zonename
))
345 def generateAuthConfig ( cls
, confdir
):
346 bind_dnssec_db
= os
. path
. join ( confdir
, 'bind-dnssec.sqlite3' )
348 with
open ( os
. path
. join ( confdir
, 'pdns.conf' ), 'w' ) as pdnsconf
:
350 module-dir=../regression-tests/modules
354 bind-config= {confdir} /named.conf
355 bind-dnssec-db= {bind_dnssec_db}
364 distributor-threads=1""" . format ( confdir
= confdir
,
365 bind_dnssec_db
= bind_dnssec_db
))
367 pdnsutilCmd
= [ os
. environ
[ 'PDNSUTIL' ],
368 '--config-dir= %s ' % confdir
,
372 print ( ' ' . join ( pdnsutilCmd
))
374 subprocess
. check_output ( pdnsutilCmd
, stderr
= subprocess
. STDOUT
)
375 except subprocess
. CalledProcessError
as e
:
376 raise AssertionError ( ' %s failed ( %d ): %s ' % ( pdnsutilCmd
, e
. returncode
, e
. output
))
379 def secureZone ( cls
, confdir
, zonename
, key
= None ):
380 zone
= '.' if zonename
== 'ROOT' else zonename
382 pdnsutilCmd
= [ os
. environ
[ 'PDNSUTIL' ],
383 '--config-dir= %s ' % confdir
,
387 keyfile
= os
. path
. join ( confdir
, 'dnssec.key' )
388 with
open ( keyfile
, 'w' ) as fdKeyfile
:
391 pdnsutilCmd
= [ os
. environ
[ 'PDNSUTIL' ],
392 '--config-dir= %s ' % confdir
,
399 print ( ' ' . join ( pdnsutilCmd
))
401 subprocess
. check_output ( pdnsutilCmd
, stderr
= subprocess
. STDOUT
)
402 except subprocess
. CalledProcessError
as e
:
403 raise AssertionError ( ' %s failed ( %d ): %s ' % ( pdnsutilCmd
, e
. returncode
, e
. output
))
406 def generateAllAuthConfig ( cls
, confdir
):
408 for auth_suffix
, zones
in cls
._ auth
_ zones
. items ():
409 authconfdir
= os
. path
. join ( confdir
, 'auth- %s ' % auth_suffix
)
411 os
. mkdir ( authconfdir
)
413 cls
. generateAuthConfig ( authconfdir
)
414 cls
. generateAuthNamedConf ( authconfdir
, zones
)
417 cls
. generateAuthZone ( authconfdir
,
420 if cls
._ zone
_ keys
. get ( zone
, None ):
421 cls
. secureZone ( authconfdir
, zone
, cls
._ zone
_ keys
. get ( zone
))
424 def startAllAuth ( cls
, confdir
):
426 for auth_suffix
, _
in cls
._ auth
_ zones
. items ():
427 authconfdir
= os
. path
. join ( confdir
, 'auth- %s ' % auth_suffix
)
428 ipaddress
= cls
._ PREFIX
+ '.' + auth_suffix
429 cls
. startAuth ( authconfdir
, ipaddress
)
432 def startAuth ( cls
, confdir
, ipaddress
):
433 print ( "Launching pdns_server.." )
434 authcmd
= list ( cls
._ auth
_ cmd
)
435 authcmd
. append ( '--config-dir= %s ' % confdir
)
436 authcmd
. append ( '--local-address= %s ' % ipaddress
)
437 print ( ' ' . join ( authcmd
))
439 logFile
= os
. path
. join ( confdir
, 'pdns.log' )
440 with
open ( logFile
, 'w' ) as fdLog
:
441 cls
._ auths
[ ipaddress
] = subprocess
. Popen ( authcmd
, close_fds
= True ,
442 stdout
= fdLog
, stderr
= fdLog
,
447 if cls
._ auths
[ ipaddress
]. poll () is not None :
449 cls
._ auths
[ ipaddress
]. kill ()
451 if e
. errno
!= errno
. ESRCH
:
453 with
open ( logFile
, 'r' ) as fdLog
:
455 sys
. exit ( cls
._ auths
[ ipaddress
]. returncode
)
458 def generateRecursorConfig ( cls
, confdir
):
459 params
= tuple ([ getattr ( cls
, param
) for param
in cls
._ config
_ params
])
463 recursorconf
= os
. path
. join ( confdir
, 'recursor.conf' )
465 with
open ( recursorconf
, 'w' ) as conf
:
466 conf
. write ( "# Autogenerated by recursortests.py \n " )
467 conf
. write ( cls
._ config
_ template
_ default
)
468 conf
. write ( cls
._ config
_ template
% params
)
470 conf
. write ( "socket-dir= %s \n " % confdir
)
471 if cls
._lu a
_ config
_ file
or cls
._ root
_ DS
:
472 luaconfpath
= os
. path
. join ( confdir
, 'conffile.lua' )
473 with
open ( luaconfpath
, 'w' ) as luaconf
:
475 luaconf
. write ( "addTA('.', ' %s ') \n " % cls
._ root
_ DS
)
476 if cls
._lu a
_ config
_ file
:
477 luaconf
. write ( cls
._lu a
_ config
_ file
)
478 conf
. write ( "lua-config-file= %s \n " % luaconfpath
)
479 if cls
._lu a
_ dns
_ script
_ file
:
480 luascriptpath
= os
. path
. join ( confdir
, 'dnsscript.lua' )
481 with
open ( luascriptpath
, 'w' ) as luascript
:
482 luascript
. write ( cls
._lu a
_ dns
_ script
_ file
)
483 conf
. write ( "lua-dns-script= %s \n " % luascriptpath
)
485 roothintspath
= os
. path
. join ( confdir
, 'root.hints' )
486 with
open ( roothintspath
, 'w' ) as roothints
:
487 roothints
. write ( cls
._ roothints
)
488 conf
. write ( "hint-file= %s \n " % roothintspath
)
491 def startResponders ( cls
):
495 def startRecursor ( cls
, confdir
, port
):
496 print ( "Launching pdns_recursor.." )
497 recursorcmd
= [ os
. environ
[ 'PDNSRECURSOR' ],
498 '--config-dir= %s ' % confdir
,
499 '--local-port= %s ' % port
,
500 '--security-poll-suffix=' ]
501 print ( ' ' . join ( recursorcmd
))
503 logFile
= os
. path
. join ( confdir
, 'recursor.log' )
504 with
open ( logFile
, 'w' ) as fdLog
:
505 cls
._ recursor
= subprocess
. Popen ( recursorcmd
, close_fds
= True ,
506 stdout
= fdLog
, stderr
= fdLog
)
508 if 'PDNSRECURSOR_FAST_TESTS' in os
. environ
:
511 delay
= cls
._ recursorStartupDelay
515 if cls
._ recursor
. poll () is not None :
519 if e
. errno
!= errno
. ESRCH
:
521 with
open ( logFile
, 'r' ) as fdLog
:
523 sys
. exit ( cls
._ recursor
. returncode
)
526 def wipeRecursorCache ( cls
, confdir
):
527 rec_controlCmd
= [ os
. environ
[ 'RECCONTROL' ],
528 '--config-dir= %s ' % confdir
,
532 subprocess
. check_output ( rec_controlCmd
, stderr
= subprocess
. STDOUT
)
533 except subprocess
. CalledProcessError
as e
:
534 raise AssertionError ( ' %s failed ( %d ): %s ' % ( rec_controlCmd
, e
. returncode
, e
. output
))
537 def setUpSockets ( cls
):
538 print ( "Setting up UDP socket.." )
539 cls
._ sock
= socket
. socket ( socket
. AF_INET
, socket
. SOCK_DGRAM
)
540 cls
._ sock
. settimeout ( 2.0 )
541 cls
._ sock
. connect (( "127.0.0.1" , cls
._ recursorPort
))
547 cls
. startResponders ()
549 confdir
= os
. path
. join ( 'configs' , cls
._ confdir
)
550 cls
. createConfigDir ( confdir
)
551 cls
. generateAllAuthConfig ( confdir
)
552 cls
. startAllAuth ( confdir
)
554 cls
. generateRecursorConfig ( confdir
)
555 cls
. startRecursor ( confdir
, cls
._ recursorPort
)
557 print ( "Launching tests.." )
560 def tearDownClass ( cls
):
561 cls
. tearDownRecursor ()
563 cls
. tearDownResponders ()
566 def tearDownResponders ( cls
):
570 def tearDownAuth ( cls
):
571 if 'PDNSRECURSOR_FAST_TESTS' in os
. environ
:
576 for _
, auth
in cls
._ auths
. items ():
579 if auth
. poll () is None :
581 if auth
. poll () is None :
585 if e
. errno
!= errno
. ESRCH
:
589 def tearDownRecursor ( cls
):
590 if 'PDNSRECURSOR_FAST_TESTS' in os
. environ
:
596 cls
._ recursor
. terminate ()
597 if cls
._ recursor
. poll () is None :
599 if cls
._ recursor
. poll () is None :
603 # There is a race-condition with the poll() and
604 # kill() statements, when the process is dead on the
605 # kill(), this is fine
606 if e
. errno
!= errno
. ESRCH
:
610 def sendUDPQuery ( cls
, query
, timeout
= 2.0 , decode
= True , fwparams
= dict ()):
612 cls
._ sock
. settimeout ( timeout
)
615 cls
._ sock
. send ( query
. to_wire ())
616 data
= cls
._ sock
. recv ( 4096 )
617 except socket
. timeout
:
621 cls
._ sock
. settimeout ( None )
627 message
= dns
. message
. from_wire ( data
, ** fwparams
)
631 def sendTCPQuery ( cls
, query
, timeout
= 2.0 ):
632 sock
= socket
. socket ( socket
. AF_INET
, socket
. SOCK_STREAM
)
634 sock
. settimeout ( timeout
)
636 sock
. connect (( "127.0.0.1" , cls
._ recursorPort
))
639 wire
= query
. to_wire ()
640 sock
. send ( struct
. pack ( "!H" , len ( wire
)))
644 ( datalen
,) = struct
. unpack ( "!H" , data
)
645 data
= sock
. recv ( datalen
)
646 except socket
. timeout
as e
:
647 print ( "Timeout: %s " % ( str ( e
)))
649 except socket
. error
as e
:
650 print ( "Network error: %s " % ( str ( e
)))
657 message
= dns
. message
. from_wire ( data
)
661 # This function is called before every tests
664 ## Functions for comparisons
665 def assertMessageHasFlags ( self
, msg
, flags
, ednsflags
=[]):
666 """Asserts that msg has all the flags from flags set
668 @param msg: the dns.message.Message to check
669 @param flags: a list of strings with flag mnemonics (like ['RD', 'RA'])
670 @param ednsflags: a list of strings with edns-flag mnemonics (like ['DO'])"""
672 if not isinstance ( msg
, dns
. message
. Message
):
673 raise TypeError ( "msg is not a dns.message.Message" )
675 if isinstance ( flags
, list ):
677 if not isinstance ( elem
, str ):
678 raise TypeError ( "flags is not a list of strings" )
680 raise TypeError ( "flags is not a list of strings" )
682 if isinstance ( ednsflags
, list ):
683 for elem
in ednsflags
:
684 if not isinstance ( elem
, str ):
685 raise TypeError ( "ednsflags is not a list of strings" )
687 raise TypeError ( "ednsflags is not a list of strings" )
689 msgFlags
= dns
. flags
. to_text ( msg
. flags
). split ()
690 missingFlags
= [ flag
for flag
in flags
if flag
not in msgFlags
]
692 msgEdnsFlags
= dns
. flags
. edns_to_text ( msg
. ednsflags
). split ()
693 missingEdnsFlags
= [ ednsflag
for ednsflag
in ednsflags
if ednsflag
not in msgEdnsFlags
]
695 if len ( missingFlags
) or len ( missingEdnsFlags
) or len ( msgFlags
) > len ( flags
):
696 raise AssertionError ( "Expected flags ' %s ' (EDNS: ' %s '), found ' %s ' (EDNS: ' %s ') in query %s " %
697 ( ' ' . join ( flags
), ' ' . join ( ednsflags
),
698 ' ' . join ( msgFlags
), ' ' . join ( msgEdnsFlags
),
701 def assertMessageIsAuthenticated ( self
, msg
):
702 """Asserts that the message has the AD bit set
704 @param msg: the dns.message.Message to check"""
706 if not isinstance ( msg
, dns
. message
. Message
):
707 raise TypeError ( "msg is not a dns.message.Message" )
709 msgFlags
= dns
. flags
. to_text ( msg
. flags
)
710 self
. assertTrue ( 'AD' in msgFlags
, "No AD flag found in the message for %s " % msg
. question
[ 0 ]. name
)
712 def assertRRsetInAnswer ( self
, msg
, rrset
):
713 """Asserts the rrset (without comparing TTL) exists in the
714 answer section of msg
716 @param msg: the dns.message.Message to check
717 @param rrset: a dns.rrset.RRset object"""
720 if not isinstance ( msg
, dns
. message
. Message
):
721 raise TypeError ( "msg is not a dns.message.Message" )
723 if not isinstance ( rrset
, dns
. rrset
. RRset
):
724 raise TypeError ( "rrset is not a dns.rrset.RRset" )
727 for ans
in msg
. answer
:
728 ret
+= " %s \n " % ans
. to_text ()
729 if ans
. match ( rrset
. name
, rrset
. rdclass
, rrset
. rdtype
, 0 , None ):
730 self
. assertEqual ( ans
, rrset
, "' %s ' != ' %s '" % ( ans
. to_text (), rrset
. to_text ()))
734 raise AssertionError ( "RRset not found in answer \n\n %s " % ret
)
736 def assertMatchingRRSIGInAnswer ( self
, msg
, coveredRRset
, keys
= None ):
737 """Looks for coveredRRset in the answer section and if there is an RRSIG RRset
738 that covers that RRset. If keys is not None, this function will also try to
739 validate the RRset against the RRSIG
741 @param msg: The dns.message.Message to check
742 @param coveredRRset: The RRSet to check for
743 @param keys: a dictionary keyed by dns.name.Name with node or rdataset values to use for validation"""
745 if not isinstance ( msg
, dns
. message
. Message
):
746 raise TypeError ( "msg is not a dns.message.Message" )
748 if not isinstance ( coveredRRset
, dns
. rrset
. RRset
):
749 raise TypeError ( "coveredRRset is not a dns.rrset.RRset" )
755 for ans
in msg
. answer
:
756 ret
+= ans
. to_text () + " \n "
758 if ans
. match ( coveredRRset
. name
, coveredRRset
. rdclass
, coveredRRset
. rdtype
, 0 , None ):
760 if ans
. match ( coveredRRset
. name
, dns
. rdataclass
. IN
, dns
. rdatatype
. RRSIG
, coveredRRset
. rdtype
, None ):
762 if msgRRSet
and msgRRsigRRSet
:
766 raise AssertionError ( "RRset for ' %s ' not found in answer" % msg
. question
[ 0 ]. to_text ())
768 if not msgRRsigRRSet
:
769 raise AssertionError ( "No RRSIGs found in answer for %s : \n Full answer: \n %s " % ( msg
. question
[ 0 ]. to_text (), ret
))
773 dns
. dnssec
. validate ( msgRRSet
, msgRRsigRRSet
. to_rdataset (), keys
)
774 except dns
. dnssec
. ValidationFailure
as e
:
775 raise AssertionError ( "Signature validation failed for %s : \n %s " % ( msg
. question
[ 0 ]. to_text (), e
))
777 def assertNoRRSIGsInAnswer ( self
, msg
):
778 """Checks if there are _no_ RRSIGs in the answer section of msg"""
780 if not isinstance ( msg
, dns
. message
. Message
):
781 raise TypeError ( "msg is not a dns.message.Message" )
784 for ans
in msg
. answer
:
785 if ans
. rdtype
== dns
. rdatatype
. RRSIG
:
786 ret
+= ans
. name
. to_text () + " \n "
789 raise AssertionError ( "RRSIG found in answers for: \n %s " % ret
)
791 def assertAnswerEmpty ( self
, msg
):
792 self
. assertTrue ( len ( msg
. answer
) == 0 , "Data found in the the answer section for %s : \n %s " % ( msg
. question
[ 0 ]. to_text (), ' \n ' . join ([ i
. to_text () for i
in msg
. answer
])))
794 def assertRcodeEqual ( self
, msg
, rcode
):
795 if not isinstance ( msg
, dns
. message
. Message
):
796 raise TypeError ( "msg is not a dns.message.Message but a %s " % type ( msg
))
798 if not isinstance ( rcode
, int ):
799 if isinstance ( rcode
, str ):
800 rcode
= dns
. rcode
. from_text ( rcode
)
802 raise TypeError ( "rcode is neither a str nor int" )
804 if msg
. rcode () != rcode
:
805 msgRcode
= dns
. rcode
._ by
_ value
[ msg
. rcode ()]
806 wantedRcode
= dns
. rcode
._ by
_ value
[ rcode
]
808 raise AssertionError ( "Rcode for %s is %s , expected %s ." % ( msg
. question
[ 0 ]. to_text (), msgRcode
, wantedRcode
))
810 def assertAuthorityHasSOA ( self
, msg
):
811 if not isinstance ( msg
, dns
. message
. Message
):
812 raise TypeError ( "msg is not a dns.message.Message but a %s " % type ( msg
))
815 for rrset
in msg
. authority
:
816 if rrset
. rdtype
== dns
. rdatatype
. SOA
:
821 raise AssertionError ( "No SOA record found in the authority section: \n %s " % msg
. to_text ())
823 def assertResponseMatches ( self
, query
, expectedRRs
, response
):
824 expectedResponse
= dns
. message
. make_response ( query
)
826 if query
. flags
& dns
. flags
. RD
:
827 expectedResponse
. flags |
= dns
. flags
. RA
828 if query
. flags
& dns
. flags
. CD
:
829 expectedResponse
. flags |
= dns
. flags
. CD
831 expectedResponse
. answer
= expectedRRs
832 print ( expectedResponse
)
834 self
. assertEquals ( response
, expectedResponse
)
837 def sendQuery ( cls
, name
, rdtype
, useTCP
= False ):
838 """Helper function that creates the query"""
839 msg
= dns
. message
. make_query ( name
, rdtype
, want_dnssec
= True )
840 msg
. flags |
= dns
. flags
. AD
843 return cls
. sendTCPQuery ( msg
)
844 return cls
. sendUDPQuery ( msg
)
846 def createQuery ( self
, name
, rdtype
, flags
, ednsflags
):
847 """Helper function that creates the query with the specified flags.
848 The flags need to be strings (no checking is performed atm)"""
849 msg
= dns
. message
. make_query ( name
, rdtype
)
850 msg
. flags
= dns
. flags
. from_text ( flags
)
851 msg
. flags
+= dns
. flags
. from_text ( 'RD' )
852 msg
. use_edns ( edns
= 0 , ednsflags
= dns
. flags
. edns_from_text ( ednsflags
))