]>
git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/recursordist/test-syncres_cc.cc
1 #define BOOST_TEST_DYN_LINK
2 #include <boost/test/unit_test.hpp>
5 #include "lua-recursor4.hh"
6 #include "root-dnssec.hh"
7 #include "test-syncres_cc.hh"
10 GlobalStateHolder
< LuaConfigItems
> g_luaconfs
;
11 GlobalStateHolder
< SuffixMatchNode
> g_dontThrottleNames
;
12 GlobalStateHolder
< NetmaskGroup
> g_dontThrottleNetmasks
;
13 thread_local
std :: unique_ptr
< MemRecursorCache
> t_RC
{ nullptr };
14 unsigned int g_numThreads
= 1 ;
15 bool g_lowercaseOutgoing
= false ;
17 /* Fake some required functions we didn't want the trouble to
21 static ArgvMap theArg
;
30 bool RecursorLua4 :: preoutquery ( const ComboAddress
& ns
, const ComboAddress
& requestor
, const DNSName
& query
, const QType
& qtype
, bool isTcp
, vector
< DNSRecord
>& res
, int & ret
) const
35 int asyncresolve ( const ComboAddress
& ip
, const DNSName
& domain
, int type
, bool doTCP
, bool sendRDQuery
, int EDNS0Level
, struct timeval
* now
, boost :: optional
< Netmask
>& srcmask
, boost :: optional
< const ResolveContext
&> context
, const std :: shared_ptr
< std :: vector
< std :: unique_ptr
< RemoteLogger
>>>& outgoingLoggers
, const std :: shared_ptr
< std :: vector
< std :: unique_ptr
< FrameStreamLogger
>>>& fstrmLoggers
, const std :: set
< uint16_t >& exportTypes
, LWResult
* res
, bool * chained
)
40 /* primeHints() is only here for now because it
41 was way too much trouble to link with the real one.
42 We should fix this, empty functions are one thing, but this is
46 #include "root-addresses.hh"
50 vector
< DNSRecord
> nsset
;
52 t_RC
= std :: unique_ptr
< MemRecursorCache
>( new MemRecursorCache ());
54 DNSRecord arr
, aaaarr
, nsrr
;
55 nsrr
. d_name
= g_rootdnsname
;
57 aaaarr
. d_type
= QType :: AAAA
;
58 nsrr
. d_type
= QType :: NS
;
59 arr
. d_ttl
= aaaarr
. d_ttl
= nsrr
. d_ttl
= time ( nullptr )+ 3600000 ;
61 for ( char c
= 'a' ; c
<= 'm' ;++ c
) {
63 strncpy ( templ
, "a.root-servers.net." , sizeof ( templ
) - 1 );
64 templ
[ sizeof ( templ
)- 1 ] = '\0' ;
66 aaaarr
. d_name
= arr
. d_name
= DNSName ( templ
);
67 nsrr
. d_content
= std :: make_shared
< NSRecordContent
>( DNSName ( templ
));
68 arr
. d_content
= std :: make_shared
< ARecordContent
>( ComboAddress ( rootIps4
[ c
- 'a' ]));
69 vector
< DNSRecord
> aset
;
71 t_RC
-> replace ( time ( nullptr ), DNSName ( templ
), QType ( QType :: A
), aset
, vector
< std :: shared_ptr
< RRSIGRecordContent
>>(), vector
< std :: shared_ptr
< DNSRecord
>>(), true ); // auth, nuke it all
72 if ( rootIps6
[ c
- 'a' ] != NULL
) {
73 aaaarr
. d_content
= std :: make_shared
< AAAARecordContent
>( ComboAddress ( rootIps6
[ c
- 'a' ]));
75 vector
< DNSRecord
> aaaaset
;
76 aaaaset
. push_back ( aaaarr
);
77 t_RC
-> replace ( time ( nullptr ), DNSName ( templ
), QType ( QType :: AAAA
), aaaaset
, vector
< std :: shared_ptr
< RRSIGRecordContent
>>(), vector
< std :: shared_ptr
< DNSRecord
>>(), true );
80 nsset
. push_back ( nsrr
);
82 t_RC
-> replace ( time ( nullptr ), g_rootdnsname
, QType ( QType :: NS
), nsset
, vector
< std :: shared_ptr
< RRSIGRecordContent
>>(), vector
< std :: shared_ptr
< DNSRecord
>>(), false ); // and stuff in the cache
85 LuaConfigItems :: LuaConfigItems ()
87 for ( const auto & dsRecord
: rootDSs
) {
88 auto ds
= std :: dynamic_pointer_cast
< DSRecordContent
>( DSRecordContent :: make ( dsRecord
));
89 dsAnchors
[ g_rootdnsname
]. insert (* ds
);
93 /* Some helpers functions */
95 void initSR ( bool debug
)
97 g_log
. setName ( "test" );
98 g_log
. disableSyslog ( true );
101 g_log
. setLoglevel (( Logger :: Urgency
)( 6 )); // info and up
102 g_log
. toConsole ( Logger :: Info
);
105 g_log
. setLoglevel ( Logger :: None
);
106 g_log
. toConsole ( Logger :: Error
);
109 t_RC
= std :: unique_ptr
< MemRecursorCache
>( new MemRecursorCache ());
111 SyncRes :: s_maxqperq
= 50 ;
112 SyncRes :: s_maxtotusec
= 1000 * 7000 ;
113 SyncRes :: s_maxdepth
= 40 ;
114 SyncRes :: s_maxnegttl
= 3600 ;
115 SyncRes :: s_maxbogusttl
= 3600 ;
116 SyncRes :: s_maxcachettl
= 86400 ;
117 SyncRes :: s_packetcachettl
= 3600 ;
118 SyncRes :: s_packetcacheservfailttl
= 60 ;
119 SyncRes :: s_serverdownmaxfails
= 64 ;
120 SyncRes :: s_serverdownthrottletime
= 60 ;
121 SyncRes :: s_doIPv6
= true ;
122 SyncRes :: s_ecsipv4limit
= 24 ;
123 SyncRes :: s_ecsipv6limit
= 56 ;
124 SyncRes :: s_ecsipv4cachelimit
= 24 ;
125 SyncRes :: s_ecsipv6cachelimit
= 56 ;
126 SyncRes :: s_ecscachelimitttl
= 0 ;
127 SyncRes :: s_rootNXTrust
= true ;
128 SyncRes :: s_minimumTTL
= 0 ;
129 SyncRes :: s_minimumECSTTL
= 0 ;
130 SyncRes :: s_serverID
= "PowerDNS Unit Tests Server ID" ;
131 SyncRes :: clearEDNSLocalSubnets ();
132 SyncRes :: addEDNSLocalSubnet ( "0.0.0.0/0" );
133 SyncRes :: addEDNSLocalSubnet ( "::/0" );
134 SyncRes :: clearEDNSRemoteSubnets ();
135 SyncRes :: clearEDNSDomains ();
136 SyncRes :: clearDelegationOnly ();
137 SyncRes :: clearDontQuery ();
138 SyncRes :: setECSScopeZeroAddress ( Netmask ( "127.0.0.1/32" ));
140 SyncRes :: clearNSSpeeds ();
141 BOOST_CHECK_EQUAL ( SyncRes :: getNSSpeedsSize (), 0 );
142 SyncRes :: clearEDNSStatuses ();
143 BOOST_CHECK_EQUAL ( SyncRes :: getEDNSStatusesSize (), 0 );
144 SyncRes :: clearThrottle ();
145 BOOST_CHECK_EQUAL ( SyncRes :: getThrottledServersSize (), 0 );
146 SyncRes :: clearFailedServers ();
147 BOOST_CHECK_EQUAL ( SyncRes :: getFailedServersSize (), 0 );
149 SyncRes :: clearECSStats ();
151 auto luaconfsCopy
= g_luaconfs
. getCopy ();
152 luaconfsCopy
. dfe
. clear ();
153 luaconfsCopy
. dsAnchors
. clear ();
154 for ( const auto & dsRecord
: rootDSs
) {
155 auto ds
= std :: dynamic_pointer_cast
< DSRecordContent
>( DSRecordContent :: make ( dsRecord
));
156 luaconfsCopy
. dsAnchors
[ g_rootdnsname
]. insert (* ds
);
158 luaconfsCopy
. negAnchors
. clear ();
159 g_luaconfs
. setState ( luaconfsCopy
);
161 g_dnssecmode
= DNSSECMode :: Off
;
163 g_maxNSEC3Iterations
= 2500 ;
165 :: arg (). set ( "version-string" , "string reported on version.pdns or version.bind" )= "PowerDNS Unit Tests" ;
166 :: arg (). set ( "rng" )= "auto" ;
167 :: arg (). set ( "entropy-source" )= "/dev/urandom" ;
168 :: arg (). setSwitch ( "qname-minimization" , "Use Query Name Minimization" ) = "no" ;
171 void initSR ( std :: unique_ptr
< SyncRes
>& sr
, bool dnssec
, bool debug
, time_t fakeNow
)
175 now
. tv_sec
= fakeNow
;
179 Utility :: gettimeofday (& now
, 0 );
184 sr
= std :: unique_ptr
< SyncRes
>( new SyncRes ( now
));
185 sr
-> setDoEDNS0 ( true );
187 sr
-> setDoDNSSEC ( dnssec
);
190 sr
-> setLogMode ( debug
== false ? SyncRes :: LogNone
: SyncRes :: Log
);
192 SyncRes :: setDomainMap ( std :: make_shared
< SyncRes :: domainmap_t
>());
193 SyncRes :: clearNegCache ();
196 void setDNSSECValidation ( std :: unique_ptr
< SyncRes
>& sr
, const DNSSECMode
& mode
)
198 sr
-> setDNSSECValidationRequested ( true );
202 void setLWResult ( LWResult
* res
, int rcode
, bool aa
, bool tc
, bool edns
, bool validpacket
)
204 res
-> d_rcode
= rcode
;
207 res
-> d_haveEDNS
= edns
;
208 res
-> d_validpacket
= validpacket
;
211 void addRecordToLW ( LWResult
* res
, const DNSName
& name
, uint16_t type
, const std :: string
& content
, DNSResourceRecord :: Place place
, uint32_t ttl
)
213 addRecordToList ( res
-> d_records
, name
, type
, content
, place
, ttl
);
216 void addRecordToLW ( LWResult
* res
, const std :: string
& name
, uint16_t type
, const std :: string
& content
, DNSResourceRecord :: Place place
, uint32_t ttl
)
218 addRecordToLW ( res
, DNSName ( name
), type
, content
, place
, ttl
);
221 bool isRootServer ( const ComboAddress
& ip
)
224 for ( size_t idx
= 0 ; idx
< rootIps4Count
; idx
++) {
225 if ( ip
. toString () == rootIps4
[ idx
]) {
231 for ( size_t idx
= 0 ; idx
< rootIps6Count
; idx
++) {
232 if ( ip
. toString () == rootIps6
[ idx
]) {
241 void computeRRSIG ( const DNSSECPrivateKey
& dpk
, const DNSName
& signer
, const DNSName
& signQName
, uint16_t signQType
, uint32_t signTTL
, uint32_t sigValidity
, RRSIGRecordContent
& rrc
, vector
< shared_ptr
< DNSRecordContent
> >& toSign
, boost :: optional
< uint8_t > algo
, boost :: optional
< uint32_t > inception
, boost :: optional
< time_t > now
)
246 DNSKEYRecordContent drc
= dpk
. getDNSKEY ();
247 const std :: shared_ptr
< DNSCryptoKeyEngine
> rc
= dpk
. getKey ();
249 rrc
. d_type
= signQType
;
250 rrc
. d_labels
= signQName
. countLabels () - signQName
. isWildcard ();
251 rrc
. d_originalttl
= signTTL
;
252 rrc
. d_siginception
= inception
? * inception
: (* now
- 10 );
253 rrc
. d_sigexpire
= * now
+ sigValidity
;
254 rrc
. d_signer
= signer
;
256 rrc
. d_tag
= drc
. getTag ();
257 rrc
. d_algorithm
= algo
? * algo
: drc
. d_algorithm
;
259 std :: string msg
= getMessageForRRSET ( signQName
, rrc
, toSign
);
261 rrc
. d_signature
= rc
-> sign ( msg
);
264 typedef std :: unordered_map
< DNSName
, std :: pair
< DNSSECPrivateKey
, DSRecordContent
> > testkeysset_t
;
266 bool addRRSIG ( const testkeysset_t
& keys
, std :: vector
< DNSRecord
>& records
, const DNSName
& signer
, uint32_t sigValidity
, bool broken
, boost :: optional
< uint8_t > algo
, boost :: optional
< DNSName
> wildcard
, boost :: optional
< time_t > now
)
268 if ( records
. empty ()) {
272 const auto it
= keys
. find ( signer
);
273 if ( it
== keys
. cend ()) {
274 throw std :: runtime_error ( "No DNSKEY found for " + signer
. toLogString () + ", unable to compute the requested RRSIG" );
277 size_t recordsCount
= records
. size ();
278 const DNSName
& name
= records
[ recordsCount
- 1 ]. d_name
;
279 const uint16_t type
= records
[ recordsCount
- 1 ]. d_type
;
281 std :: vector
< std :: shared_ptr
< DNSRecordContent
> > recordcontents
;
282 for ( const auto record
: records
) {
283 if ( record
. d_name
== name
&& record
. d_type
== type
) {
284 recordcontents
. push_back ( record
. d_content
);
288 RRSIGRecordContent rrc
;
289 computeRRSIG ( it
-> second
. first
, signer
, wildcard
? * wildcard
: records
[ recordsCount
- 1 ]. d_name
, records
[ recordsCount
- 1 ]. d_type
, records
[ recordsCount
- 1 ]. d_ttl
, sigValidity
, rrc
, recordcontents
, algo
, boost :: none
, now
);
291 rrc
. d_signature
[ 0 ] ^= 42 ;
295 rec
. d_type
= QType :: RRSIG
;
296 rec
. d_place
= records
[ recordsCount
- 1 ]. d_place
;
297 rec
. d_name
= records
[ recordsCount
- 1 ]. d_name
;
298 rec
. d_ttl
= records
[ recordsCount
- 1 ]. d_ttl
;
300 rec
. d_content
= std :: make_shared
< RRSIGRecordContent
>( rrc
);
301 records
. push_back ( rec
);
306 void addDNSKEY ( const testkeysset_t
& keys
, const DNSName
& signer
, uint32_t ttl
, std :: vector
< DNSRecord
>& records
)
308 const auto it
= keys
. find ( signer
);
309 if ( it
== keys
. cend ()) {
310 throw std :: runtime_error ( "No DNSKEY found for " + signer
. toLogString ());
314 rec
. d_place
= DNSResourceRecord :: ANSWER
;
316 rec
. d_type
= QType :: DNSKEY
;
319 rec
. d_content
= std :: make_shared
< DNSKEYRecordContent
>( it
-> second
. first
. getDNSKEY ());
320 records
. push_back ( rec
);
323 bool addDS ( const DNSName
& domain
, uint32_t ttl
, std :: vector
< DNSRecord
>& records
, const testkeysset_t
& keys
, DNSResourceRecord :: Place place
)
325 const auto it
= keys
. find ( domain
);
326 if ( it
== keys
. cend ()) {
332 rec
. d_type
= QType :: DS
;
335 rec
. d_content
= std :: make_shared
< DSRecordContent
>( it
-> second
. second
);
337 records
. push_back ( rec
);
341 void addNSECRecordToLW ( const DNSName
& domain
, const DNSName
& next
, const std :: set
< uint16_t >& types
, uint32_t ttl
, std :: vector
< DNSRecord
>& records
)
343 NSECRecordContent nrc
;
345 for ( const auto & type
: types
) {
352 rec
. d_type
= QType :: NSEC
;
353 rec
. d_content
= std :: make_shared
< NSECRecordContent
>( std :: move ( nrc
));
354 rec
. d_place
= DNSResourceRecord :: AUTHORITY
;
356 records
. push_back ( rec
);
359 void addNSEC3RecordToLW ( const DNSName
& hashedName
, const std :: string
& hashedNext
, const std :: string
& salt
, unsigned int iterations
, const std :: set
< uint16_t >& types
, uint32_t ttl
, std :: vector
< DNSRecord
>& records
)
361 NSEC3RecordContent nrc
;
364 nrc
. d_iterations
= iterations
;
366 nrc
. d_nexthash
= hashedNext
;
367 for ( const auto & type
: types
) {
372 rec
. d_name
= hashedName
;
374 rec
. d_type
= QType :: NSEC3
;
375 rec
. d_content
= std :: make_shared
< NSEC3RecordContent
>( std :: move ( nrc
));
376 rec
. d_place
= DNSResourceRecord :: AUTHORITY
;
378 records
. push_back ( rec
);
381 void addNSEC3UnhashedRecordToLW ( const DNSName
& domain
, const DNSName
& zone
, const std :: string
& next
, const std :: set
< uint16_t >& types
, uint32_t ttl
, std :: vector
< DNSRecord
>& records
, unsigned int iterations
)
383 static const std :: string salt
= "deadbeef" ;
384 std :: string hashed
= hashQNameWithSalt ( salt
, iterations
, domain
);
386 addNSEC3RecordToLW ( DNSName ( toBase32Hex ( hashed
)) + zone
, next
, salt
, iterations
, types
, ttl
, records
);
389 void addNSEC3NarrowRecordToLW ( const DNSName
& domain
, const DNSName
& zone
, const std :: set
< uint16_t >& types
, uint32_t ttl
, std :: vector
< DNSRecord
>& records
, unsigned int iterations
)
391 static const std :: string salt
= "deadbeef" ;
392 std :: string hashed
= hashQNameWithSalt ( salt
, iterations
, domain
);
393 std :: string
hashedNext ( hashed
);
394 incrementHash ( hashedNext
);
395 decrementHash ( hashed
);
397 addNSEC3RecordToLW ( DNSName ( toBase32Hex ( hashed
)) + zone
, hashedNext
, salt
, iterations
, types
, ttl
, records
);
400 void generateKeyMaterial ( const DNSName
& name
, unsigned int algo
, uint8_t digest
, testkeysset_t
& keys
)
402 auto dcke
= std :: shared_ptr
< DNSCryptoKeyEngine
>( DNSCryptoKeyEngine :: make ( algo
));
403 dcke
-> create (( algo
<= 10 ) ? 2048 : dcke
-> getBits ());
404 DNSSECPrivateKey dpk
;
407 DSRecordContent ds
= makeDSFromDNSKey ( name
, dpk
. getDNSKEY (), digest
);
408 keys
[ name
] = std :: pair
< DNSSECPrivateKey
, DSRecordContent
>( dpk
, ds
);
411 void generateKeyMaterial ( const DNSName
& name
, unsigned int algo
, uint8_t digest
, testkeysset_t
& keys
, map
< DNSName
, dsmap_t
>& dsAnchors
)
413 generateKeyMaterial ( name
, algo
, digest
, keys
);
414 dsAnchors
[ name
]. insert ( keys
[ name
]. second
);
417 int genericDSAndDNSKEYHandler ( LWResult
* res
, const DNSName
& domain
, DNSName auth
, int type
, const testkeysset_t
& keys
, bool proveCut
)
419 if ( type
== QType :: DS
) {
422 setLWResult ( res
, 0 , true , false , true );
424 if ( addDS ( domain
, 300 , res
-> d_records
, keys
, DNSResourceRecord :: ANSWER
)) {
425 addRRSIG ( keys
, res
-> d_records
, auth
, 300 );
428 addRecordToLW ( res
, auth
, QType :: SOA
, "foo. bar. 2017032800 1800 900 604800 86400" , DNSResourceRecord :: AUTHORITY
, 86400 );
430 /* if the auth zone is signed, we need to provide a secure denial */
431 const auto it
= keys
. find ( auth
);
432 if ( it
!= keys
. cend ()) {
434 addRRSIG ( keys
, res
-> d_records
, auth
, 300 );
435 /* add a NSEC denying the DS */
436 std :: set
< uint16_t > types
= { QType :: NSEC
};
438 types
. insert ( QType :: NS
);
441 addNSECRecordToLW ( domain
, DNSName ( "z" ) + domain
, types
, 600 , res
-> d_records
);
442 addRRSIG ( keys
, res
-> d_records
, auth
, 300 );
449 if ( type
== QType :: DNSKEY
) {
450 setLWResult ( res
, 0 , true , false , true );
451 addDNSKEY ( keys
, domain
, 300 , res
-> d_records
);
452 addRRSIG ( keys
, res
-> d_records
, domain
, 300 );
459 int basicRecordsForQnameMinimization ( LWResult
* res
, const DNSName
& domain
, int type
) {
460 if ( domain
== DNSName ( "." ) && type
== QType :: A
) {
461 setLWResult ( res
, 0 , true );
462 addRecordToLW ( res
, DNSName ( "." ), QType :: SOA
, "a.root-servers.net. nstld.verisign-grs.com. 2019042400 1800 900 604800 86400" , DNSResourceRecord :: AUTHORITY
);
465 if ( domain
== DNSName ( "com" ) && type
== QType :: A
) {
466 setLWResult ( res
, 0 , true );
467 addRecordToLW ( res
, DNSName ( "com" ), QType :: NS
, "ns1.com" , DNSResourceRecord :: AUTHORITY
);
468 addRecordToLW ( res
, DNSName ( "ns1.com" ), QType :: A
, "1.2.3.4" , DNSResourceRecord :: ADDITIONAL
);
471 if ( domain
== DNSName ( "ns1.com" ) && type
== QType :: A
) {
472 setLWResult ( res
, 0 , true );
473 addRecordToLW ( res
, DNSName ( "ns1.com" ), QType :: A
, "1.2.3.4" );
476 if ( domain
== DNSName ( "powerdns.com" ) && type
== QType :: A
) {
477 setLWResult ( res
, 0 , true );
478 addRecordToLW ( res
, domain
, QType :: NS
, "ns1.powerdns.com" , DNSResourceRecord :: AUTHORITY
);
479 addRecordToLW ( res
, DNSName ( "ns1.powerdns.com" ), QType :: A
, "4.5.6.7" , DNSResourceRecord :: ADDITIONAL
);
482 if ( domain
== DNSName ( "powerdns.com" ) && type
== QType :: NS
) {
483 setLWResult ( res
, 0 , true );
484 addRecordToLW ( res
, domain
, QType :: NS
, "ns1.powerdns.com" );
485 addRecordToLW ( res
, DNSName ( "ns1.powerdns.com" ), QType :: A
, "4.5.6.7" , DNSResourceRecord :: ADDITIONAL
);