]>
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 bogus.example. 3600 IN NS ns.bogus.example.
89 bogus.example. 3600 IN DS 65034 13 1 6df3bb50ea538e90eacdd7ae5419730783abb0ee
90 ns.bogus.example. 3600 IN A {prefix} .12
92 insecure.example. 3600 IN NS ns.insecure.example.
93 ns.insecure.example. 3600 IN A {prefix} .13
95 optout.example. 3600 IN NS ns1.optout.example.
96 optout.example. 3600 IN DS 59332 13 1 e664f886ae1b5df03d918bc1217d22afc29925b9
97 ns1.optout.example. 3600 IN A {prefix} .14
99 insecure-formerr.example. 3600 IN NS ns1.insecure-formerr.example.
100 ns1.insecure-formerr.example. 3600 IN A {prefix} .2
102 ecs-echo.example. 3600 IN NS ns1.ecs-echo.example.
103 ns1.ecs-echo.example. 3600 IN A {prefix} .21
105 islandofsecurity.example. 3600 IN NS ns1.islandofsecurity.example.
106 ns1.islandofsecurity.example. 3600 IN A {prefix} .9
108 sortcname.example. 3600 IN CNAME sort
109 sort.example. 3600 IN A 17.38.42.80
110 sort.example. 3600 IN A 192.168.0.1
111 sort.example. 3600 IN A 17.238.240.5
112 sort.example. 3600 IN MX 25 mx
114 'secure.example' : """
115 secure.example. 3600 IN SOA {soa}
116 secure.example. 3600 IN NS ns.secure.example.
117 ns.secure.example. 3600 IN A {prefix} .9
119 secure.example. 3600 IN A 192.0.2.17
121 host1.secure.example. 3600 IN A 192.0.2.2
122 cname.secure.example. 3600 IN CNAME host1.secure.example.
123 cname-to-insecure.secure.example. 3600 IN CNAME node1.insecure.example.
124 cname-to-bogus.secure.example. 3600 IN CNAME ted.bogus.example.
125 cname-to-islandofsecurity.secure.example. 3600 IN CNAME node1.islandofsecurity.example.
127 host1.sub.secure.example. 3600 IN A 192.0.2.11
130 sub2.secure.example. 3600 IN CNAME doesnotmatter.insecure.example.
131 insecure.sub2.secure.example. 3600 IN NS ns1.insecure.example.
133 *.wildcard.secure.example. 3600 IN A 192.0.2.10
135 *.cnamewildcard.secure.example. 3600 IN CNAME host1.secure.example.
137 *.cnamewildcardnxdomain.secure.example. 3600 IN CNAME doesntexist.secure.example.
139 cname-to-formerr.secure.example. 3600 IN CNAME host1.insecure-formerr.example.
141 'cname-secure.example' : """
142 cname-secure.example. 3600 IN SOA {soa}
143 cname-secure.example. 3600 IN NS ns.cname-secure.example.
144 ns.cname-secure.example. 3600 IN A {prefix} .15
145 cname-secure.example. 3600 IN CNAME secure.example.
148 bogus.example. 3600 IN SOA {soa}
149 bogus.example. 3600 IN NS ns1.bogus.example.
150 ns1.bogus.example. 3600 IN A {prefix} .12
151 ted.bogus.example. 3600 IN A 192.0.2.1
152 bill.bogus.example. 3600 IN AAAA 2001:db8:12::3
154 'insecure.sub2.secure.example' : """
155 insecure.sub2.secure.example. 3600 IN SOA {soa}
156 insecure.sub2.secure.example. 3600 IN NS ns1.insecure.example.
158 node1.insecure.sub2.secure.example. 3600 IN A 192.0.2.18
160 'insecure.example' : """
161 insecure.example. 3600 IN SOA {soa}
162 insecure.example. 3600 IN NS ns1.insecure.example.
163 ns1.insecure.example. 3600 IN A {prefix} .13
165 node1.insecure.example. 3600 IN A 192.0.2.6
167 cname-to-secure.insecure.example. 3600 IN CNAME host1.secure.example.
169 'optout.example' : """
170 optout.example. 3600 IN SOA {soa}
171 optout.example. 3600 IN NS ns1.optout.example.
172 ns1.optout.example. 3600 IN A {prefix} .14
174 insecure.optout.example. 3600 IN NS ns1.insecure.optout.example.
175 ns1.insecure.optout.example. 3600 IN A {prefix} .15
177 secure.optout.example. 3600 IN NS ns1.secure.optout.example.
178 secure.optout.example. 3600 IN DS 64215 13 1 b88284d7a8d8605c398e8942262f97b9a5a31787
179 ns1.secure.optout.example. 3600 IN A {prefix} .15
181 'insecure.optout.example' : """
182 insecure.optout.example. 3600 IN SOA {soa}
183 insecure.optout.example. 3600 IN NS ns1.insecure.optout.example.
184 ns1.insecure.optout.example. 3600 IN A {prefix} .15
186 node1.insecure.optout.example. 3600 IN A 192.0.2.7
188 'secure.optout.example' : """
189 secure.optout.example. 3600 IN SOA {soa}
190 secure.optout.example. 3600 IN NS ns1.secure.optout.example.
191 ns1.secure.optout.example. 3600 IN A {prefix} .15
193 node1.secure.optout.example. 3600 IN A 192.0.2.8
195 'islandofsecurity.example' : """
196 islandofsecurity.example. 3600 IN SOA {soa}
197 islandofsecurity.example. 3600 IN NS ns1.islandofsecurity.example.
198 ns1.islandofsecurity.example. 3600 IN A {prefix} .9
200 node1.islandofsecurity.example. 3600 IN A 192.0.2.20
202 'undelegated.secure.example' : """
203 undelegated.secure.example. 3600 IN SOA {soa}
204 undelegated.secure.example. 3600 IN NS ns1.undelegated.secure.example.
206 node1.undelegated.secure.example. 3600 IN A 192.0.2.21
208 'undelegated.insecure.example' : """
209 undelegated.insecure.example. 3600 IN SOA {soa}
210 undelegated.insecure.example. 3600 IN NS ns1.undelegated.insecure.example.
212 node1.undelegated.insecure.example. 3600 IN A 192.0.2.22
216 # The private keys for the zones (note that DS records should go into
217 # the zonecontent in _zones
220 Private-key-format: v1.2
221 Algorithm: 13 (ECDSAP256SHA256)
222 PrivateKey: rhWuEydDz3QaIspSVj683B8Xq5q/ozzA38XUgzD4Fbo=
226 Private-key-format: v1.2
227 Algorithm: 13 (ECDSAP256SHA256)
228 PrivateKey: Lt0v0Gol3pRUFM7fDdcy0IWN0O/MnEmVPA+VylL8Y4U=
231 'secure.example' : """
232 Private-key-format: v1.2
233 Algorithm: 13 (ECDSAP256SHA256)
234 PrivateKey: 1G4WRoOFJJXk+fotDCHVORtJmIG2OUhKi8AO2jDPGZA=
238 Private-key-format: v1.2
239 Algorithm: 13 (ECDSAP256SHA256)
240 PrivateKey: f5jV7Q8kd5hDpMWObsuQ6SQda0ftf+JrO3uZwEg6nVw=
243 'optout.example' : """
244 Private-key-format: v1.2
245 Algorithm: 13 (ECDSAP256SHA256)
246 PrivateKey: efmq9G+J4Y2iPnIBRwJiy6Z/nIHSzpsCy/7XHhlS19A=
249 'secure.optout.example' : """
250 Private-key-format: v1.2
251 Algorithm: 13 (ECDSAP256SHA256)
252 PrivateKey: xcNUxt1Knj14A00lKQFDboluiJyM2f7FxpgsQaQ3AQ4=
255 'islandofsecurity.example' : """
256 Private-key-format: v1.2
257 Algorithm: 13 (ECDSAP256SHA256)
258 PrivateKey: o9F5iix8V68tnMcuOaM2Lt8XXhIIY//SgHIHEePk6cM=
261 'cname-secure.example' : """
262 Private-key-format: v1.2
263 Algorithm: 13 (ECDSAP256SHA256)
264 PrivateKey: kvoV/g4IO/tefSro+FLJ5UC7H3BUf0IUtZQSUOfQGyA=
268 # This dict is keyed with the suffix of the IP address and its value
269 # is a list of zones hosted on that IP. Note that delegations should
270 # go into the _zones's zonecontent
273 '9' : [ 'secure.example' , 'islandofsecurity.example' ],
276 '12' : [ 'bogus.example' , 'undelegated.secure.example' , 'undelegated.insecure.example' ],
277 '13' : [ 'insecure.example' , 'insecure.sub2.secure.example' ],
278 '14' : [ 'optout.example' ],
279 '15' : [ 'insecure.optout.example' , 'secure.optout.example' , 'cname-secure.example' ]
282 _auth_cmd
= [ 'authbind' ,
288 def createConfigDir ( cls
, confdir
):
290 shutil
. rmtree ( confdir
)
292 if e
. errno
!= errno
. ENOENT
:
294 os
. mkdir ( confdir
, 0o755 )
297 def generateAuthZone ( cls
, confdir
, zonename
, zonecontent
):
298 with
open ( os
. path
. join ( confdir
, ' %s .zone' % zonename
), 'w' ) as zonefile
:
299 zonefile
. write ( zonecontent
. format ( prefix
= cls
._ PREFIX
, soa
= cls
._ SOA
))
302 def generateAuthNamedConf ( cls
, confdir
, zones
):
303 with
open ( os
. path
. join ( confdir
, 'named.conf' ), 'w' ) as namedconf
:
308 for zonename
in zones
:
309 zone
= '.' if zonename
== 'ROOT' else zonename
315 };""" % ( zone
, zonename
))
318 def generateAuthConfig ( cls
, confdir
):
319 bind_dnssec_db
= os
. path
. join ( confdir
, 'bind-dnssec.sqlite3' )
321 with
open ( os
. path
. join ( confdir
, 'pdns.conf' ), 'w' ) as pdnsconf
:
323 module-dir=../regression-tests/modules
327 bind-config= {confdir} /named.conf
328 bind-dnssec-db= {bind_dnssec_db}
336 distributor-threads=1""" . format ( confdir
= confdir
,
337 bind_dnssec_db
= bind_dnssec_db
))
339 pdnsutilCmd
= [ os
. environ
[ 'PDNSUTIL' ],
340 '--config-dir= %s ' % confdir
,
344 print ( ' ' . join ( pdnsutilCmd
))
346 subprocess
. check_output ( pdnsutilCmd
, stderr
= subprocess
. STDOUT
)
347 except subprocess
. CalledProcessError
as e
:
348 raise AssertionError ( ' %s failed ( %d ): %s ' % ( pdnsutilCmd
, e
. returncode
, e
. output
))
351 def secureZone ( cls
, confdir
, zonename
, key
= None ):
352 zone
= '.' if zonename
== 'ROOT' else zonename
354 pdnsutilCmd
= [ os
. environ
[ 'PDNSUTIL' ],
355 '--config-dir= %s ' % confdir
,
359 keyfile
= os
. path
. join ( confdir
, 'dnssec.key' )
360 with
open ( keyfile
, 'w' ) as fdKeyfile
:
363 pdnsutilCmd
= [ os
. environ
[ 'PDNSUTIL' ],
364 '--config-dir= %s ' % confdir
,
371 print ( ' ' . join ( pdnsutilCmd
))
373 subprocess
. check_output ( pdnsutilCmd
, stderr
= subprocess
. STDOUT
)
374 except subprocess
. CalledProcessError
as e
:
375 raise AssertionError ( ' %s failed ( %d ): %s ' % ( pdnsutilCmd
, e
. returncode
, e
. output
))
378 def generateAllAuthConfig ( cls
, confdir
):
380 for auth_suffix
, zones
in cls
._ auth
_ zones
. items ():
381 authconfdir
= os
. path
. join ( confdir
, 'auth- %s ' % auth_suffix
)
383 os
. mkdir ( authconfdir
)
385 cls
. generateAuthConfig ( authconfdir
)
386 cls
. generateAuthNamedConf ( authconfdir
, zones
)
389 cls
. generateAuthZone ( authconfdir
,
392 if cls
._ zone
_ keys
. get ( zone
, None ):
393 cls
. secureZone ( authconfdir
, zone
, cls
._ zone
_ keys
. get ( zone
))
396 def startAllAuth ( cls
, confdir
):
398 for auth_suffix
, _
in cls
._ auth
_ zones
. items ():
399 authconfdir
= os
. path
. join ( confdir
, 'auth- %s ' % auth_suffix
)
400 ipaddress
= cls
._ PREFIX
+ '.' + auth_suffix
401 cls
. startAuth ( authconfdir
, ipaddress
)
404 def startAuth ( cls
, confdir
, ipaddress
):
405 print ( "Launching pdns_server.." )
406 authcmd
= list ( cls
._ auth
_ cmd
)
407 authcmd
. append ( '--config-dir= %s ' % confdir
)
408 authcmd
. append ( '--local-address= %s ' % ipaddress
)
409 print ( ' ' . join ( authcmd
))
411 logFile
= os
. path
. join ( confdir
, 'pdns.log' )
412 with
open ( logFile
, 'w' ) as fdLog
:
413 cls
._ auths
[ ipaddress
] = subprocess
. Popen ( authcmd
, close_fds
= True ,
414 stdout
= fdLog
, stderr
= fdLog
,
419 if cls
._ auths
[ ipaddress
]. poll () is not None :
421 cls
._ auths
[ ipaddress
]. kill ()
423 if e
. errno
!= errno
. ESRCH
:
425 with
open ( logFile
, 'r' ) as fdLog
:
427 sys
. exit ( cls
._ auths
[ ipaddress
]. returncode
)
430 def generateRecursorConfig ( cls
, confdir
):
431 params
= tuple ([ getattr ( cls
, param
) for param
in cls
._ config
_ params
])
435 recursorconf
= os
. path
. join ( confdir
, 'recursor.conf' )
437 with
open ( recursorconf
, 'w' ) as conf
:
438 conf
. write ( "# Autogenerated by recursortests.py \n " )
439 conf
. write ( cls
._ config
_ template
_ default
)
440 conf
. write ( cls
._ config
_ template
% params
)
442 conf
. write ( "socket-dir= %s \n " % confdir
)
443 if cls
._lu a
_ config
_ file
or cls
._ root
_ DS
:
444 luaconfpath
= os
. path
. join ( confdir
, 'conffile.lua' )
445 with
open ( luaconfpath
, 'w' ) as luaconf
:
447 luaconf
. write ( "addTA('.', ' %s ') \n " % cls
._ root
_ DS
)
448 if cls
._lu a
_ config
_ file
:
449 luaconf
. write ( cls
._lu a
_ config
_ file
)
450 conf
. write ( "lua-config-file= %s \n " % luaconfpath
)
451 if cls
._lu a
_ dns
_ script
_ file
:
452 luascriptpath
= os
. path
. join ( confdir
, 'dnsscript.lua' )
453 with
open ( luascriptpath
, 'w' ) as luascript
:
454 luascript
. write ( cls
._lu a
_ dns
_ script
_ file
)
455 conf
. write ( "lua-dns-script= %s \n " % luascriptpath
)
457 roothintspath
= os
. path
. join ( confdir
, 'root.hints' )
458 with
open ( roothintspath
, 'w' ) as roothints
:
459 roothints
. write ( cls
._ roothints
)
460 conf
. write ( "hint-file= %s \n " % roothintspath
)
463 def startResponders ( cls
):
467 def startRecursor ( cls
, confdir
, port
):
468 print ( "Launching pdns_recursor.." )
469 recursorcmd
= [ os
. environ
[ 'PDNSRECURSOR' ],
470 '--config-dir= %s ' % confdir
,
471 '--local-port= %s ' % port
,
472 '--security-poll-suffix=' ]
473 print ( ' ' . join ( recursorcmd
))
475 logFile
= os
. path
. join ( confdir
, 'recursor.log' )
476 with
open ( logFile
, 'w' ) as fdLog
:
477 cls
._ recursor
= subprocess
. Popen ( recursorcmd
, close_fds
= True ,
478 stdout
= fdLog
, stderr
= fdLog
)
480 if 'PDNSRECURSOR_FAST_TESTS' in os
. environ
:
483 delay
= cls
._ recursorStartupDelay
487 if cls
._ recursor
. poll () is not None :
491 if e
. errno
!= errno
. ESRCH
:
493 with
open ( logFile
, 'r' ) as fdLog
:
495 sys
. exit ( cls
._ recursor
. returncode
)
498 def wipeRecursorCache ( cls
, confdir
):
499 rec_controlCmd
= [ os
. environ
[ 'RECCONTROL' ],
500 '--config-dir= %s ' % confdir
,
504 subprocess
. check_output ( rec_controlCmd
, stderr
= subprocess
. STDOUT
)
505 except subprocess
. CalledProcessError
as e
:
506 raise AssertionError ( ' %s failed ( %d ): %s ' % ( rec_controlCmd
, e
. returncode
, e
. output
))
509 def setUpSockets ( cls
):
510 print ( "Setting up UDP socket.." )
511 cls
._ sock
= socket
. socket ( socket
. AF_INET
, socket
. SOCK_DGRAM
)
512 cls
._ sock
. settimeout ( 2.0 )
513 cls
._ sock
. connect (( "127.0.0.1" , cls
._ recursorPort
))
519 cls
. startResponders ()
521 confdir
= os
. path
. join ( 'configs' , cls
._ confdir
)
522 cls
. createConfigDir ( confdir
)
523 cls
. generateAllAuthConfig ( confdir
)
524 cls
. startAllAuth ( confdir
)
526 cls
. generateRecursorConfig ( confdir
)
527 cls
. startRecursor ( confdir
, cls
._ recursorPort
)
529 print ( "Launching tests.." )
532 def tearDownClass ( cls
):
533 cls
. tearDownRecursor ()
535 cls
. tearDownResponders ()
538 def tearDownResponders ( cls
):
542 def tearDownAuth ( cls
):
543 if 'PDNSRECURSOR_FAST_TESTS' in os
. environ
:
548 for _
, auth
in cls
._ auths
. items ():
551 if auth
. poll () is None :
553 if auth
. poll () is None :
557 if e
. errno
!= errno
. ESRCH
:
561 def tearDownRecursor ( cls
):
562 if 'PDNSRECURSOR_FAST_TESTS' in os
. environ
:
568 cls
._ recursor
. terminate ()
569 if cls
._ recursor
. poll () is None :
571 if cls
._ recursor
. poll () is None :
575 # There is a race-condition with the poll() and
576 # kill() statements, when the process is dead on the
577 # kill(), this is fine
578 if e
. errno
!= errno
. ESRCH
:
582 def sendUDPQuery ( cls
, query
, timeout
= 2.0 , decode
= True , fwparams
= dict ()):
584 cls
._ sock
. settimeout ( timeout
)
587 cls
._ sock
. send ( query
. to_wire ())
588 data
= cls
._ sock
. recv ( 4096 )
589 except socket
. timeout
:
593 cls
._ sock
. settimeout ( None )
599 message
= dns
. message
. from_wire ( data
, ** fwparams
)
603 def sendTCPQuery ( cls
, query
, timeout
= 2.0 ):
604 sock
= socket
. socket ( socket
. AF_INET
, socket
. SOCK_STREAM
)
606 sock
. settimeout ( timeout
)
608 sock
. connect (( "127.0.0.1" , cls
._ recursorPort
))
611 wire
= query
. to_wire ()
612 sock
. send ( struct
. pack ( "!H" , len ( wire
)))
616 ( datalen
,) = struct
. unpack ( "!H" , data
)
617 data
= sock
. recv ( datalen
)
618 except socket
. timeout
as e
:
619 print ( "Timeout: %s " % ( str ( e
)))
621 except socket
. error
as e
:
622 print ( "Network error: %s " % ( str ( e
)))
629 message
= dns
. message
. from_wire ( data
)
633 # This function is called before every tests
636 ## Functions for comparisons
637 def assertMessageHasFlags ( self
, msg
, flags
, ednsflags
=[]):
638 """Asserts that msg has all the flags from flags set
640 @param msg: the dns.message.Message to check
641 @param flags: a list of strings with flag mnemonics (like ['RD', 'RA'])
642 @param ednsflags: a list of strings with edns-flag mnemonics (like ['DO'])"""
644 if not isinstance ( msg
, dns
. message
. Message
):
645 raise TypeError ( "msg is not a dns.message.Message" )
647 if isinstance ( flags
, list ):
649 if not isinstance ( elem
, str ):
650 raise TypeError ( "flags is not a list of strings" )
652 raise TypeError ( "flags is not a list of strings" )
654 if isinstance ( ednsflags
, list ):
655 for elem
in ednsflags
:
656 if not isinstance ( elem
, str ):
657 raise TypeError ( "ednsflags is not a list of strings" )
659 raise TypeError ( "ednsflags is not a list of strings" )
661 msgFlags
= dns
. flags
. to_text ( msg
. flags
). split ()
662 missingFlags
= [ flag
for flag
in flags
if flag
not in msgFlags
]
664 msgEdnsFlags
= dns
. flags
. edns_to_text ( msg
. ednsflags
). split ()
665 missingEdnsFlags
= [ ednsflag
for ednsflag
in ednsflags
if ednsflag
not in msgEdnsFlags
]
667 if len ( missingFlags
) or len ( missingEdnsFlags
) or len ( msgFlags
) > len ( flags
):
668 raise AssertionError ( "Expected flags ' %s ' (EDNS: ' %s '), found ' %s ' (EDNS: ' %s ') in query %s " %
669 ( ' ' . join ( flags
), ' ' . join ( ednsflags
),
670 ' ' . join ( msgFlags
), ' ' . join ( msgEdnsFlags
),
673 def assertMessageIsAuthenticated ( self
, msg
):
674 """Asserts that the message has the AD bit set
676 @param msg: the dns.message.Message to check"""
678 if not isinstance ( msg
, dns
. message
. Message
):
679 raise TypeError ( "msg is not a dns.message.Message" )
681 msgFlags
= dns
. flags
. to_text ( msg
. flags
)
682 self
. assertTrue ( 'AD' in msgFlags
, "No AD flag found in the message for %s " % msg
. question
[ 0 ]. name
)
684 def assertRRsetInAnswer ( self
, msg
, rrset
):
685 """Asserts the rrset (without comparing TTL) exists in the
686 answer section of msg
688 @param msg: the dns.message.Message to check
689 @param rrset: a dns.rrset.RRset object"""
692 if not isinstance ( msg
, dns
. message
. Message
):
693 raise TypeError ( "msg is not a dns.message.Message" )
695 if not isinstance ( rrset
, dns
. rrset
. RRset
):
696 raise TypeError ( "rrset is not a dns.rrset.RRset" )
699 for ans
in msg
. answer
:
700 ret
+= " %s \n " % ans
. to_text ()
701 if ans
. match ( rrset
. name
, rrset
. rdclass
, rrset
. rdtype
, 0 , None ):
702 self
. assertEqual ( ans
, rrset
, "' %s ' != ' %s '" % ( ans
. to_text (), rrset
. to_text ()))
706 raise AssertionError ( "RRset not found in answer \n\n %s " % ret
)
708 def assertMatchingRRSIGInAnswer ( self
, msg
, coveredRRset
, keys
= None ):
709 """Looks for coveredRRset in the answer section and if there is an RRSIG RRset
710 that covers that RRset. If keys is not None, this function will also try to
711 validate the RRset against the RRSIG
713 @param msg: The dns.message.Message to check
714 @param coveredRRset: The RRSet to check for
715 @param keys: a dictionary keyed by dns.name.Name with node or rdataset values to use for validation"""
717 if not isinstance ( msg
, dns
. message
. Message
):
718 raise TypeError ( "msg is not a dns.message.Message" )
720 if not isinstance ( coveredRRset
, dns
. rrset
. RRset
):
721 raise TypeError ( "coveredRRset is not a dns.rrset.RRset" )
727 for ans
in msg
. answer
:
728 ret
+= ans
. to_text () + " \n "
730 if ans
. match ( coveredRRset
. name
, coveredRRset
. rdclass
, coveredRRset
. rdtype
, 0 , None ):
732 if ans
. match ( coveredRRset
. name
, dns
. rdataclass
. IN
, dns
. rdatatype
. RRSIG
, coveredRRset
. rdtype
, None ):
734 if msgRRSet
and msgRRsigRRSet
:
738 raise AssertionError ( "RRset for ' %s ' not found in answer" % msg
. question
[ 0 ]. to_text ())
740 if not msgRRsigRRSet
:
741 raise AssertionError ( "No RRSIGs found in answer for %s : \n Full answer: \n %s " % ( msg
. question
[ 0 ]. to_text (), ret
))
745 dns
. dnssec
. validate ( msgRRSet
, msgRRsigRRSet
. to_rdataset (), keys
)
746 except dns
. dnssec
. ValidationFailure
as e
:
747 raise AssertionError ( "Signature validation failed for %s : \n %s " % ( msg
. question
[ 0 ]. to_text (), e
))
749 def assertNoRRSIGsInAnswer ( self
, msg
):
750 """Checks if there are _no_ RRSIGs in the answer section of msg"""
752 if not isinstance ( msg
, dns
. message
. Message
):
753 raise TypeError ( "msg is not a dns.message.Message" )
756 for ans
in msg
. answer
:
757 if ans
. rdtype
== dns
. rdatatype
. RRSIG
:
758 ret
+= ans
. name
. to_text () + " \n "
761 raise AssertionError ( "RRSIG found in answers for: \n %s " % ret
)
763 def assertAnswerEmpty ( self
, msg
):
764 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
])))
766 def assertRcodeEqual ( self
, msg
, rcode
):
767 if not isinstance ( msg
, dns
. message
. Message
):
768 raise TypeError ( "msg is not a dns.message.Message but a %s " % type ( msg
))
770 if not isinstance ( rcode
, int ):
771 if isinstance ( rcode
, str ):
772 rcode
= dns
. rcode
. from_text ( rcode
)
774 raise TypeError ( "rcode is neither a str nor int" )
776 if msg
. rcode () != rcode
:
777 msgRcode
= dns
. rcode
._ by
_ value
[ msg
. rcode ()]
778 wantedRcode
= dns
. rcode
._ by
_ value
[ rcode
]
780 raise AssertionError ( "Rcode for %s is %s , expected %s ." % ( msg
. question
[ 0 ]. to_text (), msgRcode
, wantedRcode
))
782 def assertAuthorityHasSOA ( self
, msg
):
783 if not isinstance ( msg
, dns
. message
. Message
):
784 raise TypeError ( "msg is not a dns.message.Message but a %s " % type ( msg
))
787 for rrset
in msg
. authority
:
788 if rrset
. rdtype
== dns
. rdatatype
. SOA
:
793 raise AssertionError ( "No SOA record found in the authority section: \n %s " % msg
. to_text ())
795 def assertResponseMatches ( self
, query
, expectedRRs
, response
):
796 expectedResponse
= dns
. message
. make_response ( query
)
798 if query
. flags
& dns
. flags
. RD
:
799 expectedResponse
. flags |
= dns
. flags
. RA
800 if query
. flags
& dns
. flags
. CD
:
801 expectedResponse
. flags |
= dns
. flags
. CD
803 expectedResponse
. answer
= expectedRRs
804 print ( expectedResponse
)
806 self
. assertEquals ( response
, expectedResponse
)