1# 2# This file is a part of DNSViz, a tool suite for DNS/DNSSEC monitoring, 3# analysis, and visualization. 4# Created by Casey Deccio (casey@deccio.net) 5# 6# Copyright 2015-2016 VeriSign, Inc. 7# 8# Copyright 2016-2021 Casey Deccio 9# 10# DNSViz is free software; you can redistribute it and/or modify 11# it under the terms of the GNU General Public License as published by 12# the Free Software Foundation; either version 2 of the License, or 13# (at your option) any later version. 14# 15# DNSViz is distributed in the hope that it will be useful, 16# but WITHOUT ANY WARRANTY; without even the implied warranty of 17# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18# GNU General Public License for more details. 19# 20# You should have received a copy of the GNU General Public License along 21# with DNSViz. If not, see <http://www.gnu.org/licenses/>. 22# 23 24from __future__ import unicode_literals 25 26import datetime 27 28# minimal support for python2.6 29try: 30 from collections import OrderedDict 31except ImportError: 32 from ordereddict import OrderedDict 33 34# python3/python2 dual compatibility 35try: 36 from html import escape 37except ImportError: 38 from cgi import escape 39 40import dns.dnssec 41 42import dnsviz.format as fmt 43from dnsviz.util import tuple_to_dict 44 45class DomainNameAnalysisError(object): 46 _abstract = True 47 code = None 48 description_template = '%(code)s' 49 terse_description_template = '%(code)s' 50 references = [] 51 required_params = [] 52 use_effective_query_tag = True 53 54 def __init__(self, **kwargs): 55 if self._abstract: 56 raise TypeError('Only subclasses may be instantiated.') 57 58 self.template_kwargs = { 'code': self.code } 59 self.servers_clients = {} 60 for param in self.required_params: 61 try: 62 self.template_kwargs[param] = kwargs[param] 63 except KeyError: 64 raise TypeError('The "%s" keyword argument is required for instantiation.' % param) 65 66 def __hash__(self): 67 return id(self) 68 69 def __str__(self): 70 return self.code 71 72 def __eq__(self, other): 73 return self.__class__ == other.__class__ and self.args == other.args 74 75 def copy(self): 76 return self.__class__(**dict(list(zip(self.required_params, self.args)))) 77 78 @property 79 def args(self): 80 if not hasattr(self, '_args') or self._args is None: 81 self._args = [self.template_kwargs[p] for p in self.required_params] 82 return self._args 83 84 @property 85 def description(self): 86 return self.description_template % self.template_kwargs 87 88 @property 89 def terse_description(self): 90 return self.terse_description_template % self.template_kwargs 91 92 @property 93 def html_description(self): 94 description_template_escaped = escape(self.description_template, True) 95 template_kwargs_escaped = {} 96 for n, v in self.template_kwargs.items(): 97 if isinstance(v, int): 98 template_kwargs_escaped[n] = v 99 else: 100 if isinstance(v, str): 101 template_kwargs_escaped[n] = escape(v) 102 else: 103 template_kwargs_escaped[n] = escape(str(v)) 104 return description_template_escaped % template_kwargs_escaped 105 106 def add_server_client(self, server, client, response): 107 if (server, client) not in self.servers_clients: 108 self.servers_clients[(server, client)] = [] 109 if response not in self.servers_clients[(server, client)]: 110 self.servers_clients[(server, client)].append(response) 111 112 def remove_server_client(self, server, client, response): 113 if (server, client) in self.servers_clients: 114 try: 115 self.servers_clients[(server, client)].remove(response) 116 except ValueError: 117 pass 118 else: 119 if not self.servers_clients[(server, client)]: 120 del self.servers_clients[(server, client)] 121 122 def serialize(self, consolidate_clients=False, html_format=False): 123 d = OrderedDict() 124 125 if html_format: 126 d['description'] = self.html_description 127 else: 128 d['description'] = self.description 129 130 d['code'] = self.code 131 if self.servers_clients: 132 servers = tuple_to_dict(self.servers_clients) 133 if consolidate_clients: 134 servers = list(servers) 135 servers.sort() 136 d['servers'] = servers 137 138 tags = set() 139 for server,client in self.servers_clients: 140 for response in self.servers_clients[(server,client)]: 141 # some errors are not in conjunction with responses, per 142 # se, only servers, in which case, the response value is 143 # None. 144 if response is not None: 145 if self.use_effective_query_tag: 146 tag = response.effective_query_tag() 147 else: 148 tag = response.initial_query_tag() 149 tags.add(tag) 150 if tags: 151 d['query_options'] = list(tags) 152 d['query_options'].sort() 153 154 return d 155 156 @classmethod 157 def insert_into_list(cls, error, error_list, server, client, response): 158 try: 159 index = error_list.index(error) 160 except ValueError: 161 error_list.append(error) 162 else: 163 error = error_list[index] 164 if server is not None and client is not None: 165 error.add_server_client(server, client, response) 166 return error 167 168class RRSIGError(DomainNameAnalysisError): 169 pass 170 171class SignerNotZone(RRSIGError): 172 ''' 173 >>> e = SignerNotZone(zone_name='foo.', signer_name='bar.') 174 >>> e.args 175 ['foo.', 'bar.'] 176 >>> e.description 177 "The Signer's Name field of the RRSIG RR (bar.) does not match the name of the zone containing the RRset (foo.)." 178 ''' 179 180 _abstract = False 181 code = 'SIGNER_NOT_ZONE' 182 description_template = "The Signer's Name field of the RRSIG RR (%(signer_name)s) does not match the name of the zone containing the RRset (%(zone_name)s)." 183 references = ['RFC 4035, Sec. 5.3.1'] 184 required_params = ['zone_name', 'signer_name'] 185 186class RRsetTTLMismatch(RRSIGError): 187 ''' 188 >>> e = RRsetTTLMismatch(rrset_ttl=50, rrsig_ttl=10) 189 >>> e.args 190 [50, 10] 191 >>> e.description 192 'The TTL of the RRSIG RR (10) does not match the TTL of the RRset it covers (50).' 193 ''' 194 195 _abstract = False 196 code = 'RRSET_TTL_MISMATCH' 197 description_template = 'The TTL of the RRSIG RR (%(rrsig_ttl)d) does not match the TTL of the RRset it covers (%(rrset_ttl)d).' 198 references = ['RFC 4035, Sec. 2.2'] 199 required_params = ['rrset_ttl', 'rrsig_ttl'] 200 201class OriginalTTLExceeded(RRSIGError): 202 ''' 203 >>> e = OriginalTTLExceeded(original_ttl=10, rrset_ttl=50) 204 >>> e.args 205 [10, 50] 206 >>> e.description 207 'The TTL of the RRset (50) exceeds the value of the Original TTL field of the RRSIG RR covering it (10).' 208 ''' 209 210 _abstract = False 211 code = 'ORIGINAL_TTL_EXCEEDED' 212 description_template = 'The TTL of the RRset (%(rrset_ttl)d) exceeds the value of the Original TTL field of the RRSIG RR covering it (%(original_ttl)d).' 213 references = ['RFC 4035, Sec. 2.2'] 214 required_params = ['original_ttl', 'rrset_ttl'] 215 216class TTLBeyondExpiration(RRSIGError): 217 ''' 218 >>> e = TTLBeyondExpiration(expiration=datetime.datetime(2015,1,10), rrsig_ttl=86401, reference_time=datetime.datetime(2015,1,9)) 219 >>> e.args 220 [datetime.datetime(2015, 1, 10, 0, 0), 86401, datetime.datetime(2015, 1, 9, 0, 0)] 221 >>> e.description 222 'With a TTL of 86401 the RRSIG RR can be in the cache of a non-validating resolver until 1 second after it expires at 2015-01-10 00:00:00.' 223 ''' 224 225 _abstract = False 226 code = 'TTL_BEYOND_EXPIRATION' 227 description_template = "With a TTL of %(rrsig_ttl)d the RRSIG RR can be in the cache of a non-validating resolver until %(difference)s after it expires at %(expiration)s." 228 references = ['RFC 4035, Sec. 5.3.3'] 229 required_params = ['expiration', 'rrsig_ttl', 'reference_time'] 230 231 def __init__(self, **kwargs): 232 super(TTLBeyondExpiration, self).__init__(**kwargs) 233 diff = self.template_kwargs['reference_time'] + datetime.timedelta(seconds=self.template_kwargs['rrsig_ttl']) - self.template_kwargs['expiration'] 234 self.template_kwargs['difference'] = fmt.humanize_time(diff.seconds, diff.days) 235 236class AlgorithmNotSupported(RRSIGError): 237 ''' 238 >>> e = AlgorithmNotSupported(algorithm=5) 239 >>> e.args 240 [5] 241 >>> e.description 242 'Validation of DNSSEC algorithm 5 (RSASHA1) is not supported by this code, so the cryptographic status of this RRSIG is unknown.' 243 ''' 244 245 _abstract = False 246 code = 'ALGORITHM_NOT_SUPPORTED' 247 description_template = "Validation of DNSSEC algorithm %(algorithm)d (%(algorithm_text)s) is not supported by this code, so the cryptographic status of this RRSIG is unknown." 248 references = ['RFC 4035, Sec. 5.2'] 249 required_params = ['algorithm'] 250 251 def __init__(self, **kwargs): 252 super(AlgorithmNotSupported, self).__init__(**kwargs) 253 self.template_kwargs['algorithm_text'] = dns.dnssec.algorithm_to_text(self.template_kwargs['algorithm']) 254 255class AlgorithmValidationProhibited(RRSIGError): 256 ''' 257 >>> e = AlgorithmValidationProhibited(algorithm=5) 258 >>> e.args 259 [5] 260 >>> e.description 261 'DNSSEC specification prohibits validation of RRSIGs with DNSSEC algorithm 5 (RSASHA1).' 262 ''' 263 264 _abstract = False 265 code = 'ALGORITHM_VALIDATION_PROHIBITED' 266 description_template = "DNSSEC specification prohibits validation of RRSIGs with DNSSEC algorithm %(algorithm)d (%(algorithm_text)s)." 267 references = ['RFC 8624, Sec. 3.1'] 268 required_params = ['algorithm'] 269 270 def __init__(self, **kwargs): 271 super(AlgorithmValidationProhibited, self).__init__(**kwargs) 272 self.template_kwargs['algorithm_text'] = dns.dnssec.algorithm_to_text(self.template_kwargs['algorithm']) 273 274class AlgorithmProhibited(RRSIGError): 275 ''' 276 >>> e = AlgorithmProhibited(algorithm=5) 277 >>> e.args 278 [5] 279 >>> e.description 280 'DNSSEC specification prohibits signing with DNSSEC algorithm 5 (RSASHA1).' 281 ''' 282 283 _abstract = False 284 code = 'ALGORITHM_PROHIBITED' 285 description_template = "DNSSEC specification prohibits signing with DNSSEC algorithm %(algorithm)d (%(algorithm_text)s)." 286 references = ['RFC 8624, Sec. 3.1'] 287 required_params = ['algorithm'] 288 289 def __init__(self, **kwargs): 290 super(AlgorithmProhibited, self).__init__(**kwargs) 291 self.template_kwargs['algorithm_text'] = dns.dnssec.algorithm_to_text(self.template_kwargs['algorithm']) 292 293class AlgorithmNotRecommended(RRSIGError): 294 ''' 295 >>> e = AlgorithmNotRecommended(algorithm=5) 296 >>> e.args 297 [5] 298 >>> e.description 299 'DNSSEC specification recommends not signing with DNSSEC algorithm 5 (RSASHA1).' 300 ''' 301 302 _abstract = False 303 code = 'ALGORITHM_NOT_RECOMMENDED' 304 description_template = "DNSSEC specification recommends not signing with DNSSEC algorithm %(algorithm)d (%(algorithm_text)s)." 305 references = ['RFC 8624, Sec. 3.1'] 306 required_params = ['algorithm'] 307 308 def __init__(self, **kwargs): 309 super(AlgorithmNotRecommended, self).__init__(**kwargs) 310 self.template_kwargs['algorithm_text'] = dns.dnssec.algorithm_to_text(self.template_kwargs['algorithm']) 311 312class DNSKEYRevokedRRSIG(RRSIGError): 313 ''' 314 >>> e = DNSKEYRevokedRRSIG() 315 >>> e.description 316 'The DNSKEY RR corresponding to the RRSIG RR has the REVOKE bit set. A revoked key cannot be used to validate RRSIGs.' 317 ''' 318 319 _abstract = False 320 code = 'DNSKEY_REVOKED_RRSIG' 321 description_template = "The DNSKEY RR corresponding to the RRSIG RR has the REVOKE bit set. A revoked key cannot be used to validate RRSIGs." 322 references = ['RFC 5011, Sec. 2.1'] 323 required_params = [] 324 325class InceptionInFuture(RRSIGError): 326 ''' 327 >>> e = InceptionInFuture(inception=datetime.datetime(2015,1,10), reference_time=datetime.datetime(2015,1,9)) 328 >>> e.args 329 [datetime.datetime(2015, 1, 10, 0, 0), datetime.datetime(2015, 1, 9, 0, 0)] 330 >>> e.description 331 'The Signature Inception field of the RRSIG RR (2015-01-10 00:00:00) is 1 day in the future.' 332 ''' 333 334 _abstract = False 335 code = 'INCEPTION_IN_FUTURE' 336 description_template = "The Signature Inception field of the RRSIG RR (%(inception)s) is %(premature_time)s in the future." 337 references = ['RFC 4035, Sec. 5.3.1'] 338 required_params = ['inception', 'reference_time'] 339 340 def __init__(self, **kwargs): 341 super(InceptionInFuture, self).__init__(**kwargs) 342 diff = self.template_kwargs['inception'] - self.template_kwargs['reference_time'] 343 self.template_kwargs['premature_time'] = fmt.humanize_time(diff.seconds, diff.days) 344 345class ExpirationInPast(RRSIGError): 346 ''' 347 >>> e = ExpirationInPast(expiration=datetime.datetime(2015,1,10), reference_time=datetime.datetime(2015,1,11)) 348 >>> e.args 349 [datetime.datetime(2015, 1, 10, 0, 0), datetime.datetime(2015, 1, 11, 0, 0)] 350 >>> e.description 351 'The Signature Expiration field of the RRSIG RR (2015-01-10 00:00:00) is 1 day in the past.' 352 ''' 353 354 _abstract = False 355 code = 'EXPIRATION_IN_PAST' 356 description_template = "The Signature Expiration field of the RRSIG RR (%(expiration)s) is %(expired_time)s in the past." 357 references = ['RFC 4035, Sec. 5.3.1'] 358 required_params = ['expiration', 'reference_time'] 359 360 def __init__(self, **kwargs): 361 super(ExpirationInPast, self).__init__(**kwargs) 362 diff = self.template_kwargs['reference_time'] - self.template_kwargs['expiration'] 363 self.template_kwargs['expired_time'] = fmt.humanize_time(diff.seconds, diff.days) 364 365class InceptionWithinClockSkew(RRSIGError): 366 ''' 367 >>> e = InceptionWithinClockSkew(inception=datetime.datetime(2015,1,10,0,0,0), reference_time=datetime.datetime(2015,1,10,0,0,1)) 368 >>> e.description 369 'The value of the Signature Inception field of the RRSIG RR (2015-01-10 00:00:00) is within possible clock skew range (1 second) of the current time (2015-01-10 00:00:01).' 370 ''' 371 372 _abstract = False 373 code = 'INCEPTION_WITHIN_CLOCK_SKEW' 374 description_template = "The value of the Signature Inception field of the RRSIG RR (%(inception)s) is within possible clock skew range (%(difference)s) of the current time (%(reference_time)s)." 375 references = ['RFC 4035, Sec. 5.3.1'] 376 required_params = ['inception', 'reference_time'] 377 378 def __init__(self, **kwargs): 379 super(InceptionWithinClockSkew, self).__init__(**kwargs) 380 diff = self.template_kwargs['reference_time'] - self.template_kwargs['inception'] 381 self.template_kwargs['difference'] = fmt.humanize_time(diff.seconds, diff.days) 382 383class ExpirationWithinClockSkew(RRSIGError): 384 ''' 385 >>> e = ExpirationWithinClockSkew(expiration=datetime.datetime(2015,1,10,0,0,1), reference_time=datetime.datetime(2015,1,10,0,0,0)) 386 >>> e.description 387 'The value of the Signature Expiration field of the RRSIG RR (2015-01-10 00:00:01) is within possible clock skew range (1 second) of the current time (2015-01-10 00:00:00).' 388 ''' 389 390 _abstract = False 391 code = 'EXPIRATION_WITHIN_CLOCK_SKEW' 392 description_template = "The value of the Signature Expiration field of the RRSIG RR (%(expiration)s) is within possible clock skew range (%(difference)s) of the current time (%(reference_time)s)." 393 references = ['RFC 4035, Sec. 5.3.1'] 394 required_params = ['expiration', 'reference_time'] 395 396 def __init__(self, **kwargs): 397 super(ExpirationWithinClockSkew, self).__init__(**kwargs) 398 diff = self.template_kwargs['expiration'] - self.template_kwargs['reference_time'] 399 self.template_kwargs['difference'] = fmt.humanize_time(diff.seconds, diff.days) 400 401class SignatureInvalid(RRSIGError): 402 ''' 403 >>> e = SignatureInvalid() 404 >>> e.description 405 'The cryptographic signature of the RRSIG RR does not properly validate.' 406 ''' 407 408 _abstract = False 409 code = 'SIGNATURE_INVALID' 410 description_template = "The cryptographic signature of the RRSIG RR does not properly validate." 411 references = ['RFC 4035, Sec. 5.3.3'] 412 required_params = [] 413 414class RRSIGBadLength(RRSIGError): 415 pass 416 417class RRSIGBadLengthGOST(RRSIGBadLength): 418 ''' 419 >>> e = RRSIGBadLengthGOST(length=500) 420 >>> e.description 421 'The length of the signature is 500 bits, but a GOST signature (DNSSEC algorithm 12) must be 512 bits long.' 422 ''' 423 _abstract = False 424 description_template = 'The length of the signature is %(length)d bits, but a GOST signature (DNSSEC algorithm 12) must be 512 bits long.' 425 code = 'RRSIG_BAD_LENGTH_GOST' 426 references = ['RFC 5933, Sec. 5.2'] 427 required_params = ['length'] 428 429class RRSIGBadLengthECDSA(RRSIGBadLength): 430 curve = None 431 algorithm = None 432 correct_length = None 433 description_template = 'The length of the signature is %(length)d bits, but an ECDSA signature made with Curve %(curve)s (DNSSEC algorithm %(algorithm)d) must be %(correct_length)d bits long.' 434 references = ['RFC 6605, Sec. 4'] 435 required_params = ['length'] 436 437 def __init__(self, **kwargs): 438 super(RRSIGBadLengthECDSA, self).__init__(**kwargs) 439 self.template_kwargs['curve'] = self.curve 440 self.template_kwargs['algorithm'] = self.algorithm 441 self.template_kwargs['correct_length'] = self.correct_length 442 443class RRSIGBadLengthECDSA256(RRSIGBadLengthECDSA): 444 ''' 445 >>> e = RRSIGBadLengthECDSA256(length=500) 446 >>> e.description 447 'The length of the signature is 500 bits, but an ECDSA signature made with Curve P-256 (DNSSEC algorithm 13) must be 512 bits long.' 448 ''' 449 curve = 'P-256' 450 algorithm = 13 451 correct_length = 512 452 _abstract = False 453 code = 'RRSIG_BAD_LENGTH_ECDSA256' 454 455class RRSIGBadLengthECDSA384(RRSIGBadLengthECDSA): 456 ''' 457 >>> e = RRSIGBadLengthECDSA384(length=500) 458 >>> e.description 459 'The length of the signature is 500 bits, but an ECDSA signature made with Curve P-384 (DNSSEC algorithm 14) must be 768 bits long.' 460 ''' 461 curve = 'P-384' 462 algorithm = 14 463 correct_length = 768 464 _abstract = False 465 code = 'RRSIG_BAD_LENGTH_ECDSA384' 466 467class RRSIGBadLengthEdDSA(RRSIGBadLength): 468 curve = None 469 algorithm = None 470 correct_length = None 471 description_template = 'The length of the signature is %(length)d bits, but an %(curve)s signature (DNSSEC algorithm %(algorithm)d) must be %(correct_length)d bits long.' 472 references = ['RFC 8080, Sec. 4'] 473 required_params = ['length'] 474 475 def __init__(self, **kwargs): 476 super(RRSIGBadLengthEdDSA, self).__init__(**kwargs) 477 self.template_kwargs['curve'] = self.curve 478 self.template_kwargs['algorithm'] = self.algorithm 479 self.template_kwargs['correct_length'] = self.correct_length 480 481class RRSIGBadLengthEd25519(RRSIGBadLengthEdDSA): 482 ''' 483 >>> e = RRSIGBadLengthEd25519(length=500) 484 >>> e.description 485 'The length of the signature is 500 bits, but an Ed25519 signature (DNSSEC algorithm 15) must be 512 bits long.' 486 ''' 487 curve = 'Ed25519' 488 algorithm = 15 489 correct_length = 512 490 _abstract = False 491 code = 'RRSIG_BAD_LENGTH_ED25519' 492 493class RRSIGBadLengthEd448(RRSIGBadLengthEdDSA): 494 ''' 495 >>> e = RRSIGBadLengthEd448(length=500) 496 >>> e.description 497 'The length of the signature is 500 bits, but an Ed448 signature (DNSSEC algorithm 16) must be 912 bits long.' 498 ''' 499 curve = 'Ed448' 500 algorithm = 16 501 correct_length = 912 502 _abstract = False 503 code = 'RRSIG_BAD_LENGTH_ED448' 504 505class DSError(DomainNameAnalysisError): 506 pass 507 508class ReferralForDSQuery(DSError): 509 ''' 510 >>> e = ReferralForDSQuery(parent='baz.') 511 >>> e.description 512 'The server(s) for the parent zone (baz.) responded with a referral instead of answering authoritatively for the DS RR type.' 513 ''' 514 _abstract = False 515 code = 'REFERRAL_FOR_DS_QUERY' 516 description_template = 'The server(s) for the parent zone (%(parent)s) responded with a referral instead of answering authoritatively for the DS RR type.' 517 references = ['RFC 4034, Sec. 5'] 518 required_params = ['parent'] 519 520class DSDigestAlgorithmIgnored(DSError): 521 ''' 522 >>> e = DSDigestAlgorithmIgnored(algorithm=1, new_algorithm=2) 523 >>> e.description 524 'DS records with digest type 1 (SHA-1) are ignored when DS records with digest type 2 (SHA-256) exist in the same RRset.' 525 ''' 526 _abstract = False 527 code = 'DS_DIGEST_ALGORITHM_IGNORED' 528 description_template = "DS records with digest type %(algorithm)d (%(algorithm_text)s) are ignored when DS records with digest type %(new_algorithm)d (%(new_algorithm_text)s) exist in the same RRset." 529 references = ['RFC 4509, Sec. 3'] 530 required_params = ['algorithm', 'new_algorithm'] 531 532 def __init__(self, **kwargs): 533 super(DSDigestAlgorithmIgnored, self).__init__(**kwargs) 534 self.template_kwargs['algorithm_text'] = fmt.DS_DIGEST_TYPES.get(self.template_kwargs['algorithm'], str(self.template_kwargs['algorithm'])) 535 self.template_kwargs['new_algorithm_text'] = fmt.DS_DIGEST_TYPES.get(self.template_kwargs['new_algorithm'], str(self.template_kwargs['algorithm'])) 536 537class DSDigestAlgorithmMaybeIgnored(DSError): 538 ''' 539 >>> e = DSDigestAlgorithmMaybeIgnored(algorithm=1, new_algorithm=2) 540 >>> e.description 541 'In the spirit of RFC 4509, DS records with digest type 1 (SHA-1) might be ignored when DS records with digest type 2 (SHA-256) exist in the same RRset.' 542 ''' 543 _abstract = False 544 code = 'DS_DIGEST_ALGORITHM_MAYBE_IGNORED' 545 description_template = "In the spirit of RFC 4509, DS records with digest type %(algorithm)d (%(algorithm_text)s) might be ignored when DS records with digest type %(new_algorithm)d (%(new_algorithm_text)s) exist in the same RRset." 546 references = ['RFC 4509, Sec. 3'] 547 required_params = ['algorithm', 'new_algorithm'] 548 549 def __init__(self, **kwargs): 550 super(DSDigestAlgorithmMaybeIgnored, self).__init__(**kwargs) 551 self.template_kwargs['algorithm_text'] = fmt.DS_DIGEST_TYPES.get(self.template_kwargs['algorithm'], str(self.template_kwargs['algorithm'])) 552 self.template_kwargs['new_algorithm_text'] = fmt.DS_DIGEST_TYPES.get(self.template_kwargs['new_algorithm'], str(self.template_kwargs['algorithm'])) 553 554class DSDigestError(DSError): 555 pass 556 557class DigestAlgorithmNotSupported(DSDigestError): 558 ''' 559 >>> e = DigestAlgorithmNotSupported(algorithm=5) 560 >>> e.description 561 'Generating cryptographic hashes using algorithm 5 (5) is not supported by this code, so the cryptographic status of the DS RR is unknown.' 562 ''' 563 564 _abstract = False 565 code = 'DIGEST_ALGORITHM_NOT_SUPPORTED' 566 description_template = "Generating cryptographic hashes using algorithm %(algorithm)d (%(algorithm_text)s) is not supported by this code, so the cryptographic status of the DS RR is unknown." 567 references = ['RFC 4035, Sec. 5.2'] 568 required_params = ['algorithm'] 569 570 def __init__(self, **kwargs): 571 super(DigestAlgorithmNotSupported, self).__init__(**kwargs) 572 self.template_kwargs['algorithm_text'] = fmt.DS_DIGEST_TYPES.get(self.template_kwargs['algorithm'], self.template_kwargs['algorithm']) 573 574class DigestAlgorithmValidationProhibited(DSDigestError): 575 ''' 576 >>> e = DigestAlgorithmValidationProhibited(algorithm=5) 577 >>> e.description 578 'DNSSEC specification prohibits validation of DS records that use digest algorithm 5 (5).' 579 ''' 580 581 _abstract = False 582 code = 'DIGEST_ALGORITHM_VALIDATION_PROHIBITED' 583 description_template = "DNSSEC specification prohibits validation of DS records that use digest algorithm %(algorithm)d (%(algorithm_text)s)." 584 references = ['RFC 8624, Sec. 3.2'] 585 required_params = ['algorithm'] 586 587 def __init__(self, **kwargs): 588 super(DigestAlgorithmValidationProhibited, self).__init__(**kwargs) 589 self.template_kwargs['algorithm_text'] = fmt.DS_DIGEST_TYPES.get(self.template_kwargs['algorithm'], self.template_kwargs['algorithm']) 590 591class DigestAlgorithmProhibited(DSDigestError): 592 ''' 593 >>> e = DigestAlgorithmProhibited(algorithm=5) 594 >>> e.description 595 'DNSSEC specification prohibits signing with DS records that use digest algorithm 5 (5).' 596 ''' 597 598 _abstract = False 599 code = 'DIGEST_ALGORITHM_PROHIBITED' 600 description_template = "DNSSEC specification prohibits signing with DS records that use digest algorithm %(algorithm)d (%(algorithm_text)s)." 601 references = ['RFC 8624, Sec. 3.2'] 602 required_params = ['algorithm'] 603 604 def __init__(self, **kwargs): 605 super(DigestAlgorithmProhibited, self).__init__(**kwargs) 606 self.template_kwargs['algorithm_text'] = fmt.DS_DIGEST_TYPES.get(self.template_kwargs['algorithm'], self.template_kwargs['algorithm']) 607 608class DigestAlgorithmNotRecommended(DSDigestError): 609 ''' 610 >>> e = DigestAlgorithmNotRecommended(algorithm=5) 611 >>> e.description 612 'DNSSEC specification recommends not signing with DS records that use digest algorithm 5 (5).' 613 ''' 614 615 _abstract = False 616 code = 'DIGEST_ALGORITHM_NOT_RECOMMENDED' 617 description_template = "DNSSEC specification recommends not signing with DS records that use digest algorithm %(algorithm)d (%(algorithm_text)s)." 618 references = ['RFC 8624, Sec. 3.2'] 619 required_params = ['algorithm'] 620 621 def __init__(self, **kwargs): 622 super(DigestAlgorithmNotRecommended, self).__init__(**kwargs) 623 self.template_kwargs['algorithm_text'] = fmt.DS_DIGEST_TYPES.get(self.template_kwargs['algorithm'], self.template_kwargs['algorithm']) 624 625class DNSKEYRevokedDS(DSDigestError): 626 ''' 627 >>> e = DNSKEYRevokedDS() 628 >>> e.description 629 'The DNSKEY RR corresponding to the DS RR has the REVOKE bit set. A revoked key cannot be used with DS records.' 630 ''' 631 632 _abstract = False 633 code = 'DNSKEY_REVOKED_DS' 634 description_template = "The DNSKEY RR corresponding to the DS RR has the REVOKE bit set. A revoked key cannot be used with DS records." 635 references = ['RFC 5011, Sec. 2.1'] 636 required_params = [] 637 638class DigestInvalid(DSDigestError): 639 ''' 640 >>> e = DigestInvalid() 641 >>> e.description 642 'The cryptographic hash in the Digest field of the DS RR does not match the computed value.' 643 ''' 644 645 _abstract = False 646 code = 'DIGEST_INVALID' 647 description_template = "The cryptographic hash in the Digest field of the DS RR does not match the computed value." 648 references = ['RFC 4035, Sec. 5.2'] 649 required_params = [] 650 651class NSECError(DomainNameAnalysisError): 652 nsec_type = None 653 654 def __init__(self, *args, **kwargs): 655 super(NSECError, self).__init__(**kwargs) 656 self.template_kwargs['nsec_type'] = self.nsec_type 657 658class SnameNotCovered(NSECError): 659 code = 'SNAME_NOT_COVERED' 660 description_template = "No %(nsec_type)s RR covers the SNAME (%(sname)s)." 661 required_params = ['sname'] 662 nsec_type = 'NSEC' 663 664class SnameNotCoveredNameError(SnameNotCovered): 665 ''' 666 >>> e = SnameNotCoveredNameError(sname='foo.baz.') 667 >>> e.description 668 'No NSEC RR covers the SNAME (foo.baz.).' 669 ''' 670 671 _abstract = False 672 references = ['RFC 4035, Sec. 3.1.3.2'] 673 674class SnameNotCoveredWildcardAnswer(SnameNotCovered): 675 _abstract = False 676 references = ['RFC 4035, Sec. 3.1.3.3'] 677 678class NextClosestEncloserNotCovered(NSECError): 679 code = 'NEXT_CLOSEST_ENCLOSER_NOT_COVERED' 680 description_template = "No %(nsec_type)s RR covers the next closest encloser (%(next_closest_encloser)s)." 681 required_params = ['next_closest_encloser'] 682 nsec_type = 'NSEC3' 683 684class NextClosestEncloserNotCoveredNameError(NextClosestEncloserNotCovered): 685 ''' 686 >>> e = NextClosestEncloserNotCoveredNameError(next_closest_encloser='foo.baz.') 687 >>> e.description 688 'No NSEC3 RR covers the next closest encloser (foo.baz.).' 689 ''' 690 691 _abstract = False 692 references = ['RFC 5155, Sec. 8.4'] 693 694class NextClosestEncloserNotCoveredNODATADS(NextClosestEncloserNotCovered): 695 _abstract = False 696 references = ['RFC 5155, Sec. 8.6'] 697 698class NextClosestEncloserNotCoveredWildcardNODATA(NextClosestEncloserNotCovered): 699 _abstract = False 700 references = ['RFC 5155, Sec. 8.7'] 701 702class NextClosestEncloserNotCoveredWildcardAnswer(NextClosestEncloserNotCovered): 703 _abstract = False 704 references = ['RFC 5155, Sec. 8.8'] 705 706class WildcardNotCovered(NSECError): 707 code = 'WILDCARD_NOT_COVERED' 708 description_template = "No %(nsec_type)s RR covers the wildcard (%(wildcard)s)." 709 required_params = ['wildcard'] 710 711class WildcardNotCoveredNSEC(WildcardNotCovered): 712 ''' 713 >>> e = WildcardNotCoveredNSEC(wildcard='*.foo.baz.') 714 >>> e.description 715 'No NSEC RR covers the wildcard (*.foo.baz.).' 716 ''' 717 718 _abstract = False 719 references = ['RFC 4035, Sec. 3.1.3.2'] 720 nsec_type = 'NSEC' 721 722class WildcardNotCoveredNSEC3(WildcardNotCovered): 723 _abstract = False 724 references = ['RFC 5155, Sec. 8.4'] 725 nsec_type = 'NSEC3' 726 727class NoClosestEncloser(NSECError): 728 code = 'NO_CLOSEST_ENCLOSER' 729 description_template = "No %(nsec_type)s RR corresponds to the closest encloser of the SNAME (%(sname)s)." 730 required_params = ['sname'] 731 nsec_type = 'NSEC3' 732 733class NoClosestEncloserNameError(NoClosestEncloser): 734 ''' 735 >>> e = NoClosestEncloserNameError(sname='foo.baz.') 736 >>> e.description 737 'No NSEC3 RR corresponds to the closest encloser of the SNAME (foo.baz.).' 738 ''' 739 740 _abstract = False 741 references = ['RFC 5155, Sec. 8.4'] 742 743class NoClosestEncloserNODATADS(NoClosestEncloser): 744 _abstract = False 745 references = ['RFC 5155, Sec. 8.6'] 746 747class NoClosestEncloserWildcardNODATA(NoClosestEncloser): 748 _abstract = False 749 references = ['RFC 5155, Sec. 8.7'] 750 751class NoClosestEncloserWildcardAnswer(NoClosestEncloser): 752 _abstract = False 753 references = ['RFC 5155, Sec. 8.8'] 754 755class OptOutFlagNotSet(NSECError): 756 code = 'OPT_OUT_FLAG_NOT_SET' 757 description_template = "The opt-out flag was not set in the %(nsec_type)s RR covering the next closest encloser (%(next_closest_encloser)s) but was required for the NODATA response." 758 required_params = ['next_closest_encloser'] 759 nsec_type = 'NSEC3' 760 761class OptOutFlagNotSetNODATA(OptOutFlagNotSet): 762 ''' 763 >>> e = OptOutFlagNotSetNODATA(next_closest_encloser='foo.baz.') 764 >>> e.description 765 'The opt-out flag was not set in the NSEC3 RR covering the next closest encloser (foo.baz.) but was required for the NODATA response.' 766 ''' 767 768 _abstract = False 769 references = ['RFC 5155, Sec. 8.5', 'RFC Errata 3441'] 770 771class OptOutFlagNotSetNODATADS(OptOutFlagNotSet): 772 _abstract = False 773 references = ['RFC 5155, Sec. 8.6'] 774 775class ReferralWithSOABit(NSECError): 776 code = 'REFERRAL_WITH_SOA' 777 description_template = "The SOA bit was set in the bitmap of the %(nsec_type)s RR corresponding to the delegated name (%(sname)s)." 778 required_params = ['sname'] 779 780class ReferralWithSOABitNSEC(ReferralWithSOABit): 781 ''' 782 >>> e = ReferralWithSOABitNSEC(sname='foo.baz.') 783 >>> e.description 784 'The SOA bit was set in the bitmap of the NSEC RR corresponding to the delegated name (foo.baz.).' 785 ''' 786 787 _abstract = False 788 references = ['RFC 4034, Sec. 5.2'] 789 nsec_type = 'NSEC' 790 791class ReferralWithSOABitNSEC3(ReferralWithSOABit): 792 _abstract = False 793 references = ['RFC 5155, Sec. 8.9'] 794 nsec_type = 'NSEC3' 795 796class ReferralWithDSBit(NSECError): 797 code = 'REFERRAL_WITH_DS' 798 description_template = "The DS bit was set in the bitmap of the %(nsec_type)s RR corresponding to the delegated name (%(sname)s)." 799 required_params = ['sname'] 800 801class ReferralWithDSBitNSEC(ReferralWithDSBit): 802 ''' 803 >>> e = ReferralWithDSBitNSEC(sname='foo.baz.') 804 >>> e.description 805 'The DS bit was set in the bitmap of the NSEC RR corresponding to the delegated name (foo.baz.).' 806 ''' 807 808 _abstract = False 809 references = ['RFC 4034, Sec. 5.2'] 810 nsec_type = 'NSEC' 811 812class ReferralWithDSBitNSEC3(ReferralWithDSBit): 813 _abstract = False 814 references = ['RFC 5155, Sec. 8.9'] 815 nsec_type = 'NSEC3' 816 817class ReferralWithoutNSBit(NSECError): 818 code = 'REFERRAL_WITHOUT_NS' 819 description_template = "The NS bit was not set in the bitmap of the %(nsec_type)s RR corresponding to the delegated name (%(sname)s)." 820 required_params = ['sname'] 821 822class ReferralWithoutNSBitNSEC(ReferralWithoutNSBit): 823 ''' 824 >>> e = ReferralWithoutNSBitNSEC(sname='foo.baz.') 825 >>> e.description 826 'The NS bit was not set in the bitmap of the NSEC RR corresponding to the delegated name (foo.baz.).' 827 ''' 828 829 _abstract = False 830 references = ['RFC 6840, Sec. 4.4'] 831 nsec_type = 'NSEC' 832 833class ReferralWithoutNSBitNSEC3(ReferralWithoutNSBit): 834 _abstract = False 835 references = ['RFC 5155, Sec. 8.9'] 836 nsec_type = 'NSEC3' 837 838class StypeInBitmap(NSECError): 839 code = 'STYPE_IN_BITMAP' 840 description_template = "The %(stype)s bit was set in the bitmap of the %(nsec_type)s RR corresponding to the SNAME (%(sname)s)." 841 required_params = ['stype', 'sname'] 842 843class StypeInBitmapNODATA(StypeInBitmap): 844 pass 845 846class StypeInBitmapNODATANSEC(StypeInBitmapNODATA): 847 ''' 848 >>> e = StypeInBitmapNODATANSEC(stype='A', sname='foo.baz.') 849 >>> e.description 850 'The A bit was set in the bitmap of the NSEC RR corresponding to the SNAME (foo.baz.).' 851 ''' 852 853 _abstract = False 854 references = ['RFC 4035, Sec. 3.1.3.1'] 855 nsec_type = 'NSEC' 856 857class StypeInBitmapNODATANSEC3(StypeInBitmapNODATA): 858 _abstract = False 859 references = ['RFC 5155, Sec. 8.5'] 860 nsec_type = 'NSEC3' 861 862class StypeInBitmapNODATADSNSEC3(StypeInBitmapNODATANSEC3): 863 _abstract = False 864 references = ['RFC 5155, Sec. 8.6'] 865 866class StypeInBitmapWildcardNODATA(StypeInBitmap): 867 pass 868 869class StypeInBitmapWildcardNODATANSEC(StypeInBitmapWildcardNODATA): 870 _abstract = False 871 references = ['RFC 4035, Sec. 3.1.3.4'] 872 nsec_type = 'NSEC' 873 874class StypeInBitmapWildcardNODATANSEC3(StypeInBitmapWildcardNODATA): 875 _abstract = False 876 references = ['RFC 5155, Sec. 8.7'] 877 nsec_type = 'NSEC3' 878 879class NoNSECMatchingSname(NSECError): 880 code = 'NO_NSEC_MATCHING_SNAME' 881 description_template = "No %(nsec_type)s RR matches the SNAME (%(sname)s)." 882 required_params = ['sname'] 883 nsec_type = 'NSEC' 884 885class NoNSECMatchingSnameNODATA(NoNSECMatchingSname): 886 ''' 887 >>> e = NoNSECMatchingSnameNODATA(sname='foo.baz.') 888 >>> e.description 889 'No NSEC RR matches the SNAME (foo.baz.).' 890 ''' 891 892 _abstract = False 893 references = ['RFC 4035, Sec. 3.1.3.1'] 894 895class NoNSECMatchingSnameWildcardNODATA(NoNSECMatchingSname): 896 _abstract = False 897 references = ['RFC 4035, Sec. 3.1.3.4'] 898 899class NoNSEC3MatchingSname(NSECError): 900 code = 'NO_NSEC3_MATCHING_SNAME' 901 description_template = "No %(nsec_type)s RR matches the SNAME (%(sname)s)." 902 required_params = ['sname'] 903 nsec_type = 'NSEC3' 904 905class NoNSEC3MatchingSnameNODATA(NoNSEC3MatchingSname): 906 ''' 907 >>> e = NoNSEC3MatchingSnameNODATA(sname='foo.baz.') 908 >>> e.description 909 'No NSEC3 RR matches the SNAME (foo.baz.).' 910 ''' 911 912 _abstract = False 913 references = ['RFC 5155, Sec. 8.5'] 914 915class NoNSEC3MatchingSnameDSNODATA(NoNSEC3MatchingSname): 916 _abstract = False 917 references = ['RFC 5155, Sec. 8.6'] 918 919class WildcardExpansionInvalid(NSECError): 920 ''' 921 >>> e = WildcardExpansionInvalid(sname='a.b.c.foo.baz.', wildcard='*.foo.baz.', next_closest_encloser='b.c.foo.baz.') 922 >>> e.description 923 'The wildcard expansion of *.foo.baz. to a.b.c.foo.baz. is invalid, as the NSEC RR indicates that the next closest encloser (b.c.foo.baz.) exists.' 924 ''' 925 926 _abstract = False 927 code = 'WILDCARD_EXPANSION_INVALID' 928 description_template = "The wildcard expansion of %(wildcard)s to %(sname)s is invalid, as the %(nsec_type)s RR indicates that the next closest encloser (%(next_closest_encloser)s) exists." 929 references = ['RFC 1034, Sec. 4.4'] 930 required_params = ['sname','wildcard','next_closest_encloser'] 931 nsec_type = 'NSEC' 932 933class WildcardCovered(NSECError): 934 code = 'WILDCARD_COVERED' 935 description_template = "The %(nsec_type)s RR covers the wildcard itself (%(wildcard)s), indicating that it doesn't exist." 936 required_params = ['wildcard'] 937 938class WildcardCoveredAnswer(WildcardCovered): 939 pass 940 941class WildcardCoveredAnswerNSEC(WildcardCoveredAnswer): 942 ''' 943 >>> e = WildcardCoveredAnswerNSEC(wildcard='*.foo.baz.') 944 >>> e.description 945 "The NSEC RR covers the wildcard itself (*.foo.baz.), indicating that it doesn't exist." 946 ''' 947 948 _abstract = False 949 references = ['RFC 4035, Sec. 3.1.3.3'] 950 nsec_type = 'NSEC' 951 952class WildcardCoveredAnswerNSEC3(WildcardCoveredAnswer): 953 _abstract = False 954 references = ['RFC 5155, Sec. 8.8'] 955 nsec_type = 'NSEC3' 956 957class WildcardCoveredNODATA(WildcardCovered): 958 pass 959 960class WildcardCoveredNODATANSEC(WildcardCoveredNODATA): 961 _abstract = False 962 references = ['RFC 4035, Sec. 3.1.3.4'] 963 nsec_type = 'NSEC' 964 965class WildcardCoveredNODATANSEC3(WildcardCoveredNODATA): 966 _abstract = False 967 references = ['RFC 5155, Sec. 8.7'] 968 nsec_type = 'NSEC3' 969 970class ExistingNSECError(NSECError): 971 required_params = ['queries'] 972 973 def __init__(self, **kwargs): 974 super(ExistingNSECError, self).__init__(**kwargs) 975 queries_text = ['%s/%s' % (name, rdtype) for name, rdtype in self.template_kwargs['queries']] 976 self.template_kwargs['queries_text'] = ', '.join(queries_text) 977 978class ExistingCovered(ExistingNSECError): 979 description_template = 'The following queries resulted in an answer response, even though the %(nsec_type)s records indicate that the queried names don\'t exist: %(queries_text)s' 980 code = 'EXISTING_NAME_COVERED' 981 982class ExistingCoveredNSEC(ExistingCovered): 983 ''' 984 >>> e = ExistingCoveredNSEC(queries=[('www.foo.baz.', 'A'), ('www1.foo.baz.', 'TXT')]) 985 >>> e.description 986 "The following queries resulted in an answer response, even though the NSEC records indicate that the queried names don't exist: www.foo.baz./A, www1.foo.baz./TXT" 987 ''' 988 989 _abstract = False 990 references = ['RFC 4035, Sec. 3.1.3.2'] 991 nsec_type = 'NSEC' 992 993class ExistingCoveredNSEC3(ExistingCovered): 994 ''' 995 >>> e = ExistingCoveredNSEC3(queries=[('www.foo.baz.', 'A'), ('www1.foo.baz.', 'TXT')]) 996 >>> e.description 997 "The following queries resulted in an answer response, even though the NSEC3 records indicate that the queried names don't exist: www.foo.baz./A, www1.foo.baz./TXT" 998 ''' 999 1000 _abstract = False 1001 references = ['RFC 5155, Sec. 8.4'] 1002 nsec_type = 'NSEC3' 1003 1004class ExistingTypeNotInBitmap(ExistingNSECError): 1005 description_template = 'The following queries resulted in an answer response, even though the bitmap in the %(nsec_type)s RR indicates that the queried records don\'t exist: %(queries_text)s' 1006 code = 'EXISTING_TYPE_NOT_IN_BITMAP' 1007 1008class ExistingTypeNotInBitmapNSEC(ExistingTypeNotInBitmap): 1009 ''' 1010 >>> e = ExistingTypeNotInBitmapNSEC(queries=[('www.foo.baz.', 'A'), ('www.foo.baz.', 'TXT')]) 1011 >>> e.description 1012 "The following queries resulted in an answer response, even though the bitmap in the NSEC RR indicates that the queried records don't exist: www.foo.baz./A, www.foo.baz./TXT" 1013 ''' 1014 1015 _abstract = False 1016 references = ['RFC 4035, Sec. 3.1.3.1'] 1017 nsec_type = 'NSEC' 1018 1019class ExistingTypeNotInBitmapNSEC3(ExistingTypeNotInBitmap): 1020 ''' 1021 >>> e = ExistingTypeNotInBitmapNSEC3(queries=[('www.foo.baz.', 'A'), ('www.foo.baz.', 'TXT')]) 1022 >>> e.description 1023 "The following queries resulted in an answer response, even though the bitmap in the NSEC3 RR indicates that the queried records don't exist: www.foo.baz./A, www.foo.baz./TXT" 1024 ''' 1025 1026 _abstract = False 1027 references = ['RFC 5155, Sec. 8.5'] 1028 nsec_type = 'NSEC3' 1029 1030class SnameCoveredNODATANSEC(NSECError): 1031 ''' 1032 >>> e = SnameCoveredNODATANSEC(sname='foo.baz.') 1033 >>> e.description 1034 "The NSEC RR covers the SNAME (foo.baz.), indicating that it doesn't exist." 1035 ''' 1036 1037 _abstract = False 1038 code = 'SNAME_COVERED' 1039 description_template = "The %(nsec_type)s RR covers the SNAME (%(sname)s), indicating that it doesn't exist." 1040 references = ['RFC 4035, Sec. 3.1.3.1'] 1041 required_params = ['sname'] 1042 nsec_type = 'NSEC' 1043 1044 1045class LastNSECNextNotZone(NSECError): 1046 ''' 1047 >>> e = LastNSECNextNotZone(nsec_owner='z.foo.baz.', next_name='a.foo.baz.', zone_name='foo.baz.') 1048 >>> e.description 1049 'The value of the Next Domain Name field in the NSEC RR with owner name z.foo.baz. indicates that it is the last NSEC RR in the zone, but the value (a.foo.baz.) did not match the name of the zone apex (foo.baz.).' 1050 ''' 1051 1052 _abstract = False 1053 code = 'LAST_NSEC_NEXT_NOT_ZONE' 1054 description_template = "The value of the Next Domain Name field in the %(nsec_type)s RR with owner name %(nsec_owner)s indicates that it is the last %(nsec_type)s RR in the zone, but the value (%(next_name)s) did not match the name of the zone apex (%(zone_name)s)." 1055 references = ['RFC 4034, Sec. 4.1.1'] 1056 required_params = ['nsec_owner','next_name','zone_name'] 1057 nsec_type = 'NSEC' 1058 1059class UnsupportedNSEC3Algorithm(NSECError): 1060 ''' 1061 >>> e = UnsupportedNSEC3Algorithm(algorithm=2) 1062 >>> e.description 1063 'Generating NSEC3 hashes using algorithm 2 is not supported by this code.' 1064 ''' 1065 1066 _abstract = False 1067 code = 'UNSUPPORTED_NSEC3_ALGORITHM' 1068 description_template = "Generating %(nsec_type)s hashes using algorithm %(algorithm)d is not supported by this code." 1069 references = ['RFC 5155, Sec. 8.1'] 1070 required_params = ['algorithm'] 1071 nsec_type = 'NSEC3' 1072 1073class InvalidNSEC3OwnerName(NSECError): 1074 ''' 1075 >>> e = InvalidNSEC3OwnerName(name='foo.com.') 1076 >>> e.description 1077 'The NSEC3 owner name (foo.com.) is invalid; it does not appear to be the Base32 Hex encoding of a hashed owner name.' 1078 ''' 1079 1080 _abstract = False 1081 code = 'INVALID_NSEC3_OWNER_NAME' 1082 description_template = "The %(nsec_type)s owner name (%(name)s) is invalid; it does not appear to be the Base32 Hex encoding of a hashed owner name." 1083 references = ['RFC 5155, Sec. 3'] 1084 required_params = ['name'] 1085 nsec_type = 'NSEC3' 1086 1087class InvalidNSEC3Hash(NSECError): 1088 ''' 1089 >>> e = InvalidNSEC3Hash(name='foo', nsec3_hash='foo===') 1090 >>> e.description 1091 'The NSEC3 record for foo is invalid; the value of the Next Hashed Owner Name field (foo===) does not appear to be a valid hash.' 1092 ''' 1093 1094 _abstract = False 1095 code = 'INVALID_NSEC3_HASH' 1096 description_template = 'The NSEC3 record for %(name)s is invalid; the value of the Next Hashed Owner Name field (%(nsec3_hash)s) does not appear to be a valid hash.' 1097 references = ['RFC 5155, Sec. 3.1.7'] 1098 required_params = ['name', 'nsec3_hash'] 1099 nsec_type = 'NSEC3' 1100 1101class ResponseError(DomainNameAnalysisError): 1102 pass 1103 1104class InvalidResponseError(ResponseError): 1105 required_params = ['tcp'] 1106 1107 def __init__(self, *args, **kwargs): 1108 super(ResponseError, self).__init__(**kwargs) 1109 if self.template_kwargs['tcp']: 1110 self.template_kwargs['proto'] = 'TCP' 1111 else: 1112 self.template_kwargs['proto'] = 'UDP' 1113 1114class NetworkError(InvalidResponseError): 1115 ''' 1116 >>> e = NetworkError(tcp=False, errno='EHOSTUNREACH') 1117 >>> e.description 1118 'The server was not reachable over UDP (EHOSTUNREACH).' 1119 >>> e = NetworkError(tcp=False, errno='ECONNREFUSED') 1120 >>> e.description 1121 'The UDP connection was refused (ECONNREFUSED).' 1122 >>> e.terse_description 1123 'NETWORK_ERROR:ECONNREFUSED' 1124 ''' 1125 1126 _abstract = False 1127 code = 'NETWORK_ERROR' 1128 description_template = '%(description)s' 1129 terse_description_template = '%(code)s:%(errno)s' 1130 required_params = InvalidResponseError.required_params + ['errno'] 1131 1132 def __init__(self, *args, **kwargs): 1133 super(NetworkError, self).__init__(**kwargs) 1134 if self.template_kwargs['errno'] == 'ECONNRESET': 1135 self.template_kwargs['description'] = 'The %s connection was interrupted (%s).' % (self.template_kwargs['proto'], self.template_kwargs['errno']) 1136 elif self.template_kwargs['errno'] == 'ECONNREFUSED': 1137 self.template_kwargs['description'] = 'The %s connection was refused (%s).' % (self.template_kwargs['proto'], self.template_kwargs['errno']) 1138 elif self.template_kwargs['errno'] == 'EHOSTUNREACH': 1139 self.template_kwargs['description'] = 'The server was not reachable over %s (%s).' % (self.template_kwargs['proto'], self.template_kwargs['errno']) 1140 else: 1141 self.template_kwargs['description'] = 'There was an error communicating with the server over %s (%s).' % (self.template_kwargs['proto'], self.template_kwargs['errno']) 1142 1143class FormError(InvalidResponseError): 1144 ''' 1145 >>> e = FormError(tcp=False, msg_size=30) 1146 >>> e.description 1147 'The response (30 bytes) was malformed.' 1148 ''' 1149 1150 _abstract = False 1151 code = 'FORMERR' 1152 description_template = "The response (%(msg_size)d bytes) was malformed." 1153 required_params = InvalidResponseError.required_params + ['msg_size'] 1154 1155class Timeout(InvalidResponseError): 1156 ''' 1157 >>> e = Timeout(tcp=False, attempts=3) 1158 >>> e.description 1159 'No response was received from the server over UDP (tried 3 times).' 1160 ''' 1161 1162 _abstract = False 1163 code = 'TIMEOUT' 1164 description_template = "No response was received from the server over %(proto)s (tried %(attempts)d times)." 1165 required_params = InvalidResponseError.required_params + ['attempts'] 1166 1167class UnknownResponseError(InvalidResponseError): 1168 ''' 1169 >>> e = UnknownResponseError(tcp=False) 1170 >>> e.description 1171 'An invalid response was received from the server over UDP.' 1172 ''' 1173 1174 _abstract = False 1175 code = 'RESPONSE_ERROR' 1176 description_template = "An invalid response was received from the server over %(proto)s." 1177 1178 def __init__(self, *args, **kwargs): 1179 super(UnknownResponseError, self).__init__(**kwargs) 1180 self.template_kwargs['description'] = "An invalid response was received from the server over %s" % (self.template_kwargs['proto']) 1181 1182class InvalidRcode(InvalidResponseError): 1183 ''' 1184 >>> e = InvalidRcode(tcp=False, rcode='SERVFAIL') 1185 >>> e.description 1186 'The response had an invalid RCODE (SERVFAIL).' 1187 >>> e.terse_description 1188 'INVALID_RCODE:SERVFAIL' 1189 ''' 1190 1191 _abstract = False 1192 code = 'INVALID_RCODE' 1193 description_template = "The response had an invalid RCODE (%(rcode)s)." 1194 terse_description_template = '%(code)s:%(rcode)s' 1195 required_params = InvalidResponseError.required_params + ['rcode'] 1196 1197class NotAuthoritative(ResponseError): 1198 ''' 1199 >>> e = NotAuthoritative() 1200 >>> e.description 1201 'The Authoritative Answer (AA) flag was not set in the response.' 1202 ''' 1203 1204 _abstract = False 1205 code = 'NOT_AUTHORITATVE' 1206 description_template = "The Authoritative Answer (AA) flag was not set in the response." 1207 references = ['RFC 1035, Sec. 4.1.1'] 1208 required_params = [] 1209 1210class AuthoritativeReferral(ResponseError): 1211 ''' 1212 >>> e = AuthoritativeReferral() 1213 >>> e.description 1214 'The Authoritative Answer (AA) flag was set in the referral response.' 1215 ''' 1216 1217 _abstract = False 1218 code = 'AUTHORITATIVE_REFERRAL' 1219 description_template = "The Authoritative Answer (AA) flag was set in the referral response." 1220 references = ['RFC 1035, Sec. 4.1.1'] 1221 required_params = [] 1222 1223class RecursionNotAvailable(ResponseError): 1224 ''' 1225 >>> e = RecursionNotAvailable() 1226 >>> e.description 1227 'Recursion was desired, but the Recursion Available (RA) flag was not set in the response.' 1228 ''' 1229 1230 _abstract = False 1231 code = 'RECURSION_NOT_AVAILABLE' 1232 description_template = "Recursion was desired, but the Recursion Available (RA) flag was not set in the response." 1233 references = ['RFC 1035, Sec. 4.1.1'] 1234 required_params = [] 1235 1236class ResponseErrorWithCondition(ResponseError): 1237 description_template = "%(response_error_description)s until %(change)s%(query_specific_text)s." 1238 required_params = ['response_error', 'query_specific'] 1239 use_effective_query_tag = False 1240 1241 def __init__(self, *args, **kwargs): 1242 super(ResponseErrorWithCondition, self).__init__(**kwargs) 1243 self.template_kwargs['response_error_description'] = self.template_kwargs['response_error'].description[:-1] 1244 if self.template_kwargs['query_specific']: 1245 self.template_kwargs['query_specific_text'] = ' (however, this server appeared to respond legitimately to other queries with %s)' % (self.precondition % self.template_kwargs) 1246 else: 1247 self.template_kwargs['query_specific_text'] = '' 1248 1249class ResponseErrorWithRequestFlag(ResponseErrorWithCondition): 1250 ''' 1251 >>> e = ResponseErrorWithRequestFlag(response_error=Timeout(tcp=False, attempts=3), flag='RD', query_specific=False) 1252 >>> e.description 1253 'No response was received from the server over UDP (tried 3 times) until the RD flag was cleared.' 1254 ''' 1255 1256 _abstract = False 1257 code = 'ERROR_WITH_REQUEST_FLAG' 1258 references = ['RFC 1035, Sec. 4.1.1'] 1259 required_params = ResponseErrorWithCondition.required_params + ['flag'] 1260 1261 def __init__(self, *args, **kwargs): 1262 self.precondition = 'the %(flag)s flag set' 1263 super(ResponseErrorWithRequestFlag, self).__init__(**kwargs) 1264 self.template_kwargs['change'] = 'the %s flag was cleared' % (self.template_kwargs['flag']) 1265 1266class ResponseErrorWithoutRequestFlag(ResponseErrorWithCondition): 1267 ''' 1268 >>> e = ResponseErrorWithoutRequestFlag(response_error=Timeout(tcp=False, attempts=3), flag='RD', query_specific=False) 1269 >>> e.description 1270 'No response was received from the server over UDP (tried 3 times) until the RD flag was set.' 1271 ''' 1272 1273 _abstract = False 1274 code = 'ERROR_WITHOUT_REQUEST_FLAG' 1275 references = ['RFC 1035, Sec. 4.1.1'] 1276 required_params = ResponseErrorWithCondition.required_params + ['flag'] 1277 1278 def __init__(self, *args, **kwargs): 1279 self.precondition = 'the %(flag)s flag cleared' 1280 super(ResponseErrorWithoutRequestFlag, self).__init__(**kwargs) 1281 self.template_kwargs['change'] = 'the %s flag was set' % (self.template_kwargs['flag']) 1282 1283class ResponseErrorWithEDNS(ResponseErrorWithCondition): 1284 ''' 1285 >>> e = ResponseErrorWithEDNS(response_error=Timeout(tcp=False, attempts=3), query_specific=False) 1286 >>> e.description 1287 'No response was received from the server over UDP (tried 3 times) until EDNS was disabled.' 1288 ''' 1289 1290 _abstract = False 1291 code = 'ERROR_WITH_EDNS' 1292 references = ['RFC 6891, Sec. 6.2.6'] 1293 1294 def __init__(self, *args, **kwargs): 1295 self.precondition = 'EDNS enabled' 1296 super(ResponseErrorWithEDNS, self).__init__(**kwargs) 1297 self.template_kwargs['change'] = 'EDNS was disabled' 1298 1299class ResponseErrorWithEDNSVersion(ResponseErrorWithCondition): 1300 ''' 1301 >>> e = ResponseErrorWithEDNSVersion(response_error=Timeout(tcp=False, attempts=3), edns_old=3, edns_new=0, query_specific=False) 1302 >>> e.description 1303 'No response was received from the server over UDP (tried 3 times) until the version of EDNS was changed from 3 to 0.' 1304 ''' 1305 1306 _abstract = False 1307 code = 'ERROR_WITH_EDNS_VERSION' 1308 references = ['RFC 6891, Sec. 6.1.3'] 1309 required_params = ResponseErrorWithCondition.required_params + ['edns_old', 'edns_new'] 1310 1311 def __init__(self, *args, **kwargs): 1312 self.precondition = 'EDNS version %(edns_old)d' 1313 super(ResponseErrorWithEDNSVersion, self).__init__(**kwargs) 1314 self.template_kwargs['change'] = 'the version of EDNS was changed from %d to %d' % \ 1315 (self.template_kwargs['edns_old'], self.template_kwargs['edns_new']) 1316 1317class ResponseErrorWithEDNSFlag(ResponseErrorWithCondition): 1318 ''' 1319 >>> e = ResponseErrorWithEDNSFlag(response_error=Timeout(tcp=False, attempts=3), flag='DO', query_specific=False) 1320 >>> e.description 1321 'No response was received from the server over UDP (tried 3 times) until the DO EDNS flag was cleared.' 1322 ''' 1323 1324 _abstract = False 1325 code = 'ERROR_WITH_EDNS_FLAG' 1326 references = ['RFC 6891, Sec. 6.1.4'] 1327 required_params = ResponseErrorWithCondition.required_params + ['flag'] 1328 1329 def __init__(self, *args, **kwargs): 1330 self.precondition = 'the %(flag)s EDNS flag set' 1331 super(ResponseErrorWithEDNSFlag, self).__init__(**kwargs) 1332 self.template_kwargs['change'] = 'the %s EDNS flag was cleared' % (self.template_kwargs['flag']) 1333 1334class ResponseErrorWithoutEDNSFlag(ResponseErrorWithCondition): 1335 ''' 1336 >>> e = ResponseErrorWithoutEDNSFlag(response_error=Timeout(tcp=False, attempts=3), flag='DO', query_specific=False) 1337 >>> e.description 1338 'No response was received from the server over UDP (tried 3 times) until the DO EDNS flag was set.' 1339 ''' 1340 1341 _abstract = False 1342 code = 'ERROR_WITHOUT_EDNS_FLAG' 1343 references = ['RFC 6891, Sec. 6.1.4'] 1344 required_params = ResponseErrorWithCondition.required_params + ['flag'] 1345 1346 def __init__(self, *args, **kwargs): 1347 self.precondition = 'the %(flag)s EDNS flag cleared' 1348 super(ResponseErrorWithoutEDNSFlag, self).__init__(**kwargs) 1349 self.template_kwargs['change'] = 'the %s EDNS flag was set' % (self.template_kwargs['flag']) 1350 1351class ResponseErrorWithEDNSOption(ResponseErrorWithCondition): 1352 ''' 1353 >>> e = ResponseErrorWithEDNSOption(response_error=Timeout(tcp=False, attempts=3), option='NSID', query_specific=False) 1354 >>> e.description 1355 'No response was received from the server over UDP (tried 3 times) until the NSID EDNS option was removed.' 1356 ''' 1357 1358 _abstract = False 1359 code = 'ERROR_WITH_EDNS_OPTION' 1360 references = ['RFC 6891, Sec. 6.1.2'] 1361 required_params = ResponseErrorWithCondition.required_params + ['option'] 1362 1363 def __init__(self, *args, **kwargs): 1364 self.precondition = 'the %(option)s EDNS option present' 1365 super(ResponseErrorWithEDNSOption, self).__init__(**kwargs) 1366 self.template_kwargs['change'] = 'the %s EDNS option was removed' % (self.template_kwargs['option']) 1367 1368class ResponseErrorWithoutEDNSOption(ResponseErrorWithCondition): 1369 ''' 1370 >>> e = ResponseErrorWithoutEDNSOption(response_error=Timeout(tcp=False, attempts=3), option='NSID', query_specific=False) 1371 >>> e.description 1372 'No response was received from the server over UDP (tried 3 times) until the NSID EDNS option was added.' 1373 ''' 1374 1375 _abstract = False 1376 code = 'ERROR_WITHOUT_EDNS_OPTION' 1377 references = ['RFC 6891, Sec. 6.1.2'] 1378 required_params = ResponseErrorWithCondition.required_params + ['option'] 1379 1380 def __init__(self, *args, **kwargs): 1381 self.precondition = 'without the %(option)s EDNS option' 1382 super(ResponseErrorWithoutEDNSOption, self).__init__(**kwargs) 1383 self.template_kwargs['change'] = 'the %s EDNS option was added' % (self.template_kwargs['option']) 1384 1385class EDNSError(ResponseError): 1386 pass 1387 1388class EDNSVersionMismatch(EDNSError): 1389 ''' 1390 >>> e = EDNSVersionMismatch(request_version=1, response_version=0) 1391 >>> e.description 1392 'The server responded with EDNS version 0 when a request with EDNS version 1 was sent, instead of responding with RCODE BADVERS.' 1393 ''' 1394 1395 _abstract = False 1396 code = 'EDNS_VERSION_MISMATCH' 1397 description_template = "The server responded with EDNS version %(response_version)d when a request with EDNS version %(request_version)d was sent, instead of responding with RCODE BADVERS." 1398 references = ['RFC 6891, Sec. 6.1.3'] 1399 required_params = ['request_version', 'response_version'] 1400 1401class EDNSIgnored(EDNSError): 1402 ''' 1403 >>> e = EDNSIgnored() 1404 >>> e.description 1405 'The server responded with no OPT record, rather than with RCODE FORMERR.' 1406 ''' 1407 1408 _abstract = False 1409 code = 'EDNS_IGNORED' 1410 description_template = 'The server responded with no OPT record, rather than with RCODE FORMERR.' 1411 references = ['RFC 6891, Sec. 7'] 1412 required_params = [] 1413 1414class EDNSSupportNoOpt(EDNSError): 1415 ''' 1416 >>> e = EDNSSupportNoOpt() 1417 >>> e.description 1418 'The server appeared to understand EDNS by including RRSIG records, but its response included no OPT record.' 1419 ''' 1420 1421 _abstract = False 1422 code = 'EDNS_SUPPORT_NO_OPT' 1423 description_template = 'The server appeared to understand EDNS by including RRSIG records, but its response included no OPT record.' 1424 references = ['RFC 6891, Sec. 7'] 1425 required_params = [] 1426 1427class GratuitousOPT(EDNSError): 1428 ''' 1429 >>> e = GratuitousOPT() 1430 >>> e.description 1431 'The server responded with an OPT record, even though none was sent in the request.' 1432 ''' 1433 1434 _abstract = False 1435 code = 'GRATUITOUS_OPT' 1436 description_template = 'The server responded with an OPT record, even though none was sent in the request.' 1437 references = ['RFC 6891, Sec. 6.1.1'] 1438 required_params = [] 1439 1440class ImplementedEDNSVersionNotProvided(EDNSError): 1441 ''' 1442 >>> e = ImplementedEDNSVersionNotProvided(request_version=100, response_version=100) 1443 >>> e.description 1444 'The server responded with BADVERS to EDNS version 100 but responded with version 100 instead of providing the highest EDNS version it implements.' 1445 ''' 1446 1447 _abstract = False 1448 code = 'IMPLEMENTED_EDNS_VERSION_NOT_PROVIDED' 1449 description_template = "The server responded with BADVERS to EDNS version %(request_version)d but responded with version %(response_version)d instead of providing the highest EDNS version it implements." 1450 references = ['RFC 6891, Sec. 6.1.3'] 1451 required_params = ['request_version', 'response_version'] 1452 1453class EDNSUndefinedFlagsSet(EDNSError): 1454 ''' 1455 >>> e = EDNSUndefinedFlagsSet(flags=0x80) 1456 >>> e.description 1457 'The server set EDNS flags that are undefined: 0x80.' 1458 ''' 1459 1460 _abstract = False 1461 code = 'EDNS_UNDEFINED_FLAGS_SET' 1462 description_template = 'The server set EDNS flags that are undefined: %(flags_text)s.' 1463 references = ['RFC 6891, Sec. 6.1.4'] 1464 required_params = ['flags'] 1465 1466 def __init__(self, **kwargs): 1467 super(EDNSUndefinedFlagsSet, self).__init__(**kwargs) 1468 self.template_kwargs['flags_text'] = '0x%x' % (self.template_kwargs['flags']) 1469 1470class DNSSECDowngrade(EDNSError): 1471 description_template = "DNSSEC was effectively downgraded because %(response_error_description)s with %(precondition)s." 1472 required_params = ['response_error'] 1473 precondition = None 1474 1475 def __init__(self, *args, **kwargs): 1476 super(DNSSECDowngrade, self).__init__(**kwargs) 1477 self.template_kwargs['response_error_description'] = self.template_kwargs['response_error'].description[0].lower() + self.template_kwargs['response_error'].description[1:-1] 1478 self.template_kwargs['precondition'] = self.precondition 1479 1480class DNSSECDowngradeDOBitCleared(DNSSECDowngrade): 1481 ''' 1482 >>> e = DNSSECDowngradeDOBitCleared(response_error=Timeout(tcp=False, attempts=3)) 1483 >>> e.description 1484 'DNSSEC was effectively downgraded because no response was received from the server over UDP (tried 3 times) with the DO bit set.' 1485 ''' 1486 1487 _abstract = False 1488 code = 'DNSSEC_DOWNGRADE_DO_CLEARED' 1489 precondition = 'the DO bit set' 1490 references = ['RFC 4035, Sec. 3.2.1'] 1491 1492class DNSSECDowngradeEDNSDisabled(DNSSECDowngrade): 1493 ''' 1494 >>> e = DNSSECDowngradeEDNSDisabled(response_error=Timeout(tcp=False, attempts=3), query_specific=False) 1495 >>> e.description 1496 'DNSSEC was effectively downgraded because no response was received from the server over UDP (tried 3 times) with EDNS enabled.' 1497 ''' 1498 1499 _abstract = False 1500 code = 'DNSSEC_DOWNGRADE_EDNS_DISABLED' 1501 precondition = 'EDNS enabled' 1502 references = ['RFC 6891, Sec. 7', 'RFC 2671, Sec. 5.3'] 1503 1504class DNSCookieError(ResponseError): 1505 pass 1506 1507class GratuitousCookie(DNSCookieError): 1508 ''' 1509 >>> e = GratuitousCookie() 1510 >>> e.description 1511 'The server sent a COOKIE option when none was sent by the client.' 1512 ''' 1513 1514 _abstract = False 1515 code = 'GRATUITOUS_COOKIE' 1516 description_template = 'The server sent a COOKIE option when none was sent by the client.' 1517 references = ['RFC 7873, Sec. 5.2.1'] 1518 1519class MalformedCookieWithoutFORMERR(DNSCookieError): 1520 ''' 1521 >>> e = MalformedCookieWithoutFORMERR() 1522 >>> e.description 1523 'The server appears to support DNS cookies but did not return a FORMERR status when issued a malformed COOKIE option.' 1524 ''' 1525 1526 _abstract = False 1527 code = 'MALFORMED_COOKIE_WITHOUT_FORMERR' 1528 description_template = 'The server appears to support DNS cookies but did not return a FORMERR status when issued a malformed COOKIE option.' 1529 references = ['RFC 7873, Sec. 5.2.2'] 1530 1531class NoCookieOption(DNSCookieError): 1532 ''' 1533 >>> e = NoCookieOption() 1534 >>> e.description 1535 'The server appears to support DNS cookies but did not return a COOKIE option.' 1536 ''' 1537 1538 _abstract = False 1539 code = 'NO_COOKIE_OPTION' 1540 description_template = 'The server appears to support DNS cookies but did not return a COOKIE option.' 1541 references = ['RFC 7873, Sec. 5.2.3'] 1542 1543class NoServerCookieWithoutBADCOOKIE(DNSCookieError): 1544 ''' 1545 >>> e = NoServerCookieWithoutBADCOOKIE() 1546 >>> e.description 1547 'The server appears to support DNS cookies but did not return a BADCOOKIE status when no server cookie was sent.' 1548 ''' 1549 1550 _abstract = False 1551 code = 'NO_SERVER_COOKIE_WITHOUT_BADCOOKIE' 1552 description_template = 'The server appears to support DNS cookies but did not return a BADCOOKIE status when no server cookie was sent.' 1553 references = ['RFC 7873, Sec. 5.2.3'] 1554 1555class InvalidServerCookieWithoutBADCOOKIE(DNSCookieError): 1556 ''' 1557 >>> e = InvalidServerCookieWithoutBADCOOKIE() 1558 >>> e.description 1559 'The server appears to support DNS cookies but did not return a BADCOOKIE status when an invalid server cookie was sent.' 1560 ''' 1561 1562 _abstract = False 1563 code = 'INVALID_SERVER_COOKIE_WITHOUT_BADCOOKIE' 1564 description_template = 'The server appears to support DNS cookies but did not return a BADCOOKIE status when an invalid server cookie was sent.' 1565 references = ['RFC 7873, Sec. 5.2.4'] 1566 1567class NoServerCookie(DNSCookieError): 1568 ''' 1569 >>> e = NoServerCookie() 1570 >>> e.description 1571 'The server appears to support DNS cookies but did not return a server cookie with its COOKIE option.' 1572 ''' 1573 1574 _abstract = False 1575 code = 'NO_SERVER_COOKIE' 1576 description_template = 'The server appears to support DNS cookies but did not return a server cookie with its COOKIE option.' 1577 references = ['RFC 7873, Sec. 5.2.3'] 1578 1579class ClientCookieMismatch(DNSCookieError): 1580 ''' 1581 >>> e = ClientCookieMismatch() 1582 >>> e.description 1583 'The client cookie returned by the server did not match what was sent.' 1584 ''' 1585 1586 _abstract = False 1587 code = 'CLIENT_COOKIE_MISMATCH' 1588 description_template = 'The client cookie returned by the server did not match what was sent.' 1589 references = ['RFC 7873, Sec. 5.3'] 1590 1591class CookieInvalidLength(DNSCookieError): 1592 ''' 1593 >>> e = CookieInvalidLength(length=61) 1594 >>> e.description 1595 'The cookie returned by the server had an invalid length of 61 bytes.' 1596 ''' 1597 1598 _abstract = False 1599 code = 'COOKIE_INVALID_LENGTH' 1600 description_template = 'The cookie returned by the server had an invalid length of %(length)d bytes.' 1601 references = ['RFC 7873, Sec. 5.3'] 1602 required_params = ['length'] 1603 1604class UnableToRetrieveDNSSECRecords(ResponseError): 1605 ''' 1606 >>> e = UnableToRetrieveDNSSECRecords() 1607 >>> e.description 1608 'The DNSSEC records necessary to validate the response could not be retrieved from the server.' 1609 ''' 1610 1611 _abstract = False 1612 code = 'UNABLE_TO_RETRIEVE_DNSSEC_RECORDS' 1613 description_template = 'The DNSSEC records necessary to validate the response could not be retrieved from the server.' 1614 references = ['RFC 4035, Sec. 3.1.1', 'RFC 4035, Sec. 3.1.3'] 1615 required_params = [] 1616 use_effective_query_tag = False 1617 1618class MissingRRSIG(ResponseError): 1619 ''' 1620 >>> e = MissingRRSIG() 1621 >>> e.description 1622 'No RRSIG covering the RRset was returned in the response.' 1623 ''' 1624 1625 _abstract = False 1626 code = 'MISSING_RRSIG' 1627 description_template = 'No RRSIG covering the RRset was returned in the response.' 1628 references = ['RFC 4035, Sec. 3.1.1'] 1629 required_params = [] 1630 1631class MissingRRSIGForAlg(ResponseError): 1632 description_template = 'The %(source)s RRset for the zone included algorithm %(algorithm)s (%(algorithm_text)s), but no RRSIG with algorithm %(algorithm)d covering the RRset was returned in the response.' 1633 references = ['RFC 4035, Sec. 2.2', 'RFC 6840, Sec. 5.11'] 1634 required_params = ['algorithm'] 1635 source = None 1636 1637 def __init__(self, **kwargs): 1638 super(MissingRRSIGForAlg, self).__init__(**kwargs) 1639 self.template_kwargs['algorithm_text'] = dns.dnssec.algorithm_to_text(self.template_kwargs['algorithm']) 1640 self.template_kwargs['source'] = self.source 1641 1642class MissingRRSIGForAlgDNSKEY(MissingRRSIGForAlg): 1643 ''' 1644 >>> e = MissingRRSIGForAlgDNSKEY(algorithm=5) 1645 >>> e.description 1646 'The DNSKEY RRset for the zone included algorithm 5 (RSASHA1), but no RRSIG with algorithm 5 covering the RRset was returned in the response.' 1647 ''' 1648 1649 _abstract = False 1650 code = 'MISSING_RRSIG_FOR_ALG_DNSKEY' 1651 source = 'DNSKEY' 1652 1653class MissingRRSIGForAlgDS(MissingRRSIGForAlg): 1654 ''' 1655 >>> e = MissingRRSIGForAlgDS(algorithm=5) 1656 >>> e.description 1657 'The DS RRset for the zone included algorithm 5 (RSASHA1), but no RRSIG with algorithm 5 covering the RRset was returned in the response.' 1658 ''' 1659 1660 _abstract = False 1661 code = 'MISSING_RRSIG_FOR_ALG_DS' 1662 source = 'DS' 1663 1664class MissingRRSIGForAlgDLV(MissingRRSIGForAlg): 1665 ''' 1666 >>> e = MissingRRSIGForAlgDLV(algorithm=5) 1667 >>> e.description 1668 'The DLV RRset for the zone included algorithm 5 (RSASHA1), but no RRSIG with algorithm 5 covering the RRset was returned in the response.' 1669 ''' 1670 1671 _abstract = False 1672 code = 'MISSING_RRSIG_FOR_ALG_DLV' 1673 source = 'DLV' 1674 1675class MissingNSEC(ResponseError): 1676 description_template = 'No NSEC RR(s) were returned to validate the %(response)s response.' 1677 response = None 1678 1679 def __init__(self, **kwargs): 1680 super(MissingNSEC, self).__init__(**kwargs) 1681 self.template_kwargs['response'] = self.response 1682 1683class MissingNSECForNXDOMAIN(MissingNSEC): 1684 ''' 1685 >>> e = MissingNSECForNXDOMAIN() 1686 >>> e.description 1687 'No NSEC RR(s) were returned to validate the NXDOMAIN response.' 1688 ''' 1689 1690 _abstract = False 1691 code = 'MISSING_NSEC_FOR_NXDOMAIN' 1692 references = ['RFC 4035, Sec. 3.1.3.2', 'RFC 5155, Sec. 7.2.2'] 1693 response = 'NXDOMAIN' 1694 1695class MissingNSECForNODATA(MissingNSEC): 1696 ''' 1697 >>> e = MissingNSECForNODATA() 1698 >>> e.description 1699 'No NSEC RR(s) were returned to validate the NODATA response.' 1700 ''' 1701 1702 _abstract = False 1703 code = 'MISSING_NSEC_FOR_NODATA' 1704 references = ['RFC 4035, Sec. 3.1.3.1', 'RFC 5155, Sec. 7.2.3', 'RFC 5155, Sec. 7.2.4'] 1705 response = 'NODATA' 1706 1707class MissingNSECForWildcard(MissingNSEC): 1708 ''' 1709 >>> e = MissingNSECForWildcard() 1710 >>> e.description 1711 'No NSEC RR(s) were returned to validate the wildcard response.' 1712 ''' 1713 1714 _abstract = False 1715 code = 'MISSING_NSEC_FOR_WILDCARD' 1716 references = ['RFC 4035, Sec. 3.1.3.3', 'RFC 4035, Sec. 3.1.3.4', 'RFC 5155, Sec. 7.2.5', 'RFC 5155, Sec. 7.2.6'] 1717 response = 'wildcard' 1718 1719class MissingSOA(ResponseError): 1720 description_template = 'No SOA RR was returned with the %(response)s response.' 1721 references = ['RFC 1034, Sec. 4.3.4'] 1722 response = None 1723 1724 def __init__(self, **kwargs): 1725 super(MissingSOA, self).__init__(**kwargs) 1726 self.template_kwargs['response'] = self.response 1727 1728class MissingSOAForNXDOMAIN(MissingSOA): 1729 ''' 1730 >>> e = MissingSOAForNXDOMAIN() 1731 >>> e.description 1732 'No SOA RR was returned with the NXDOMAIN response.' 1733 ''' 1734 1735 _abstract = False 1736 code = 'MISSING_SOA_FOR_NXDOMAIN' 1737 references = MissingSOA.references + ['RFC 2308, Sec. 2.1'] 1738 response = 'NXDOMAIN' 1739 1740class MissingSOAForNODATA(MissingSOA): 1741 ''' 1742 >>> e = MissingSOAForNODATA() 1743 >>> e.description 1744 'No SOA RR was returned with the NODATA response.' 1745 ''' 1746 1747 _abstract = False 1748 code = 'MISSING_SOA_FOR_NODATA' 1749 references = MissingSOA.references + ['RFC 2308, Sec. 2.2'] 1750 response = 'NODATA' 1751 1752class UpwardReferral(ResponseError): 1753 _abstract = False 1754 code = 'UPWARD_REFERRAL' 1755 description_template = 'The response was an upward referral.' 1756 references = ['https://www.dns-oarc.net/oarc/articles/upward-referrals-considered-harmful'] 1757 1758class SOAOwnerNotZone(ResponseError): 1759 description_template = 'An SOA RR with owner name (%(soa_owner_name)s) not matching the zone name (%(zone_name)s) was returned with the %(response)s response.' 1760 references = ['RFC 1034, Sec. 4.3.4'] 1761 required_params = ['soa_owner_name', 'zone_name'] 1762 response = None 1763 1764 def __init__(self, **kwargs): 1765 super(SOAOwnerNotZone, self).__init__(**kwargs) 1766 self.template_kwargs['response'] = self.response 1767 1768class SOAOwnerNotZoneForNXDOMAIN(SOAOwnerNotZone): 1769 ''' 1770 >>> e = SOAOwnerNotZoneForNXDOMAIN(soa_owner_name='foo.baz.', zone_name='bar.') 1771 >>> e.description 1772 'An SOA RR with owner name (foo.baz.) not matching the zone name (bar.) was returned with the NXDOMAIN response.' 1773 ''' 1774 1775 _abstract = False 1776 code = 'SOA_NOT_OWNER_FOR_NXDOMAIN' 1777 references = SOAOwnerNotZone.references + ['RFC 2308, Sec. 2.1'] 1778 response = 'NXDOMAIN' 1779 1780class SOAOwnerNotZoneForNODATA(SOAOwnerNotZone): 1781 ''' 1782 >>> e = SOAOwnerNotZoneForNODATA(soa_owner_name='foo.baz.', zone_name='bar.') 1783 >>> e.description 1784 'An SOA RR with owner name (foo.baz.) not matching the zone name (bar.) was returned with the NODATA response.' 1785 ''' 1786 1787 _abstract = False 1788 code = 'SOA_NOT_OWNER_FOR_NODATA' 1789 references = SOAOwnerNotZone.references + ['RFC 2308, Sec. 2.2'] 1790 response = 'NODATA' 1791 1792class InconsistentNXDOMAIN(ResponseError): 1793 ''' 1794 >>> e = InconsistentNXDOMAIN(qname='foo.baz.', rdtype_nxdomain='NS', rdtype_noerror='A') 1795 >>> e.description 1796 'The server returned a no error (NOERROR) response when queried for foo.baz. having record data of type A, but returned a name error (NXDOMAIN) when queried for foo.baz. having record data of type NS.' 1797 ''' 1798 1799 _abstract = False 1800 code = 'INCONSISTENT_NXDOMAIN' 1801 description_template = 'The server returned a no error (NOERROR) response when queried for %(qname)s having record data of type %(rdtype_noerror)s, but returned a name error (NXDOMAIN) when queried for %(qname)s having record data of type %(rdtype_nxdomain)s.' 1802 required_params = ['qname', 'rdtype_nxdomain', 'rdtype_noerror'] 1803 references = ['RFC 1034, Sec. 4.3.2'] 1804 1805class InconsistentNXDOMAINAncestry(ResponseError): 1806 ''' 1807 >>> e = InconsistentNXDOMAINAncestry(qname='foo.baz.', ancestor_qname='baz.') 1808 >>> e.description 1809 "A query for foo.baz. results in a NOERROR response, while a query for its ancestor, baz., returns a name error (NXDOMAIN), which indicates that subdomains of baz., including foo.baz., don't exist." 1810 ''' 1811 1812 _abstract = False 1813 code = 'INCONSISTENT_NXDOMAIN_ANCESTOR' 1814 description_template = "A query for %(qname)s results in a NOERROR response, while a query for its ancestor, %(ancestor_qname)s, returns a name error (NXDOMAIN), which indicates that subdomains of %(ancestor_qname)s, including %(qname)s, don't exist." 1815 required_params = ['qname', 'ancestor_qname'] 1816 references = [] 1817 1818class PMTUExceeded(ResponseError): 1819 ''' 1820 >>> e = PMTUExceeded(pmtu_lower_bound=None, pmtu_upper_bound=None) 1821 >>> e.description 1822 'No response was received until the UDP payload size was decreased, indicating that the server might be attempting to send a payload that exceeds the path maximum transmission unit (PMTU) size.' 1823 >>> e = PMTUExceeded(pmtu_lower_bound=511, pmtu_upper_bound=513) 1824 >>> e.description 1825 'No response was received until the UDP payload size was decreased, indicating that the server might be attempting to send a payload that exceeds the path maximum transmission unit (PMTU) size. The PMTU was bounded between 511 and 513 bytes.' 1826 ''' 1827 1828 _abstract = False 1829 code = 'PMTU_EXCEEDED' 1830 description_template = '%(description)s' 1831 required_params = ['pmtu_lower_bound', 'pmtu_upper_bound'] 1832 references = ['RFC 6891, Sec. 6.2.6'] 1833 use_effective_query_tag = False 1834 1835 def __init__(self, **kwargs): 1836 super(PMTUExceeded, self).__init__(**kwargs) 1837 self.template_kwargs['description'] = 'No response was received until the UDP payload size was decreased, indicating that the server might be attempting to send a payload that exceeds the path maximum transmission unit (PMTU) size.' 1838 if self.template_kwargs['pmtu_lower_bound'] is not None and self.template_kwargs['pmtu_upper_bound'] is not None: 1839 self.template_kwargs['description'] += ' The PMTU was bounded between %(pmtu_lower_bound)d and %(pmtu_upper_bound)d bytes.' % self.template_kwargs 1840 1841class ForeignClassData(ResponseError): 1842 section = None 1843 description_template = 'Data of class %(cls)s was found in the %(section)s section of the response.' 1844 references = ['RFC 1034', 'RFC 1035'] 1845 required_params = ['cls'] 1846 1847 def __init__(self, **kwargs): 1848 super(ForeignClassData, self).__init__(**kwargs) 1849 self.template_kwargs['section'] = self.section 1850 1851class ForeignClassDataAnswer(ForeignClassData): 1852 ''' 1853 >>> e = ForeignClassDataAnswer(cls='CH') 1854 >>> e.description 1855 'Data of class CH was found in the Answer section of the response.' 1856 ''' 1857 section = 'Answer' 1858 _abstract = False 1859 code = 'FOREIGN_CLASS_DATA_ANSWER' 1860 1861class ForeignClassDataAuthority(ForeignClassData): 1862 ''' 1863 >>> e = ForeignClassDataAuthority(cls='CH') 1864 >>> e.description 1865 'Data of class CH was found in the Authority section of the response.' 1866 ''' 1867 section = 'Authority' 1868 _abstract = False 1869 code = 'FOREIGN_CLASS_DATA_AUTHORITY' 1870 1871class ForeignClassDataAdditional(ForeignClassData): 1872 ''' 1873 >>> e = ForeignClassDataAdditional(cls='CH') 1874 >>> e.description 1875 'Data of class CH was found in the Additional section of the response.' 1876 ''' 1877 section = 'Additional' 1878 _abstract = False 1879 code = 'FOREIGN_CLASS_DATA_ADDITIONAL' 1880 1881class CasePreservationError(ResponseError): 1882 ''' 1883 >>> e = CasePreservationError(qname='ExAmPlE.CoM') 1884 >>> e.description 1885 'The case of the query name (ExAmPlE.CoM) was not preserved in the Question section of the response.' 1886 ''' 1887 1888 _abstract = False 1889 code = 'CASE_NOT_PRESERVED' 1890 description_template = '%(description)s' 1891 description_template = 'The case of the query name (%(qname)s) was not preserved in the Question section of the response.' 1892 required_params = ['qname'] 1893 1894class DelegationError(DomainNameAnalysisError): 1895 pass 1896 1897class MissingSEPForAlg(DelegationError): 1898 ''' 1899 >>> e = MissingSEPForAlg(algorithm=5, source='DS') 1900 >>> e.description 1901 "The DS RRset for the zone included algorithm 5 (RSASHA1), but no DS RR matched a DNSKEY with algorithm 5 that signs the zone's DNSKEY RRset." 1902 ''' 1903 1904 _abstract = False 1905 code = 'MISSING_SEP_FOR_ALG' 1906 description_template = "The %(source)s RRset for the zone included algorithm %(algorithm)s (%(algorithm_text)s), but no %(source)s RR matched a DNSKEY with algorithm %(algorithm)d that signs the zone's DNSKEY RRset." 1907 references = ['RFC 4035, Sec. 2.2', 'RFC 6840, Sec. 5.11'] 1908 required_params = ['algorithm'] 1909 1910 def __init__(self, **kwargs): 1911 super(MissingSEPForAlg, self).__init__(**kwargs) 1912 self.template_kwargs['algorithm_text'] = dns.dnssec.algorithm_to_text(self.template_kwargs['algorithm']) 1913 try: 1914 self.template_kwargs['source'] = kwargs['source'] 1915 except KeyError: 1916 raise TypeError('The "source" keyword argument is required for instantiation.') 1917 1918class NoSEP(DelegationError): 1919 ''' 1920 >>> e = NoSEP(source='DS') 1921 >>> e.description 1922 'No valid RRSIGs made by a key corresponding to a DS RR were found covering the DNSKEY RRset, resulting in no secure entry point (SEP) into the zone.' 1923 ''' 1924 1925 _abstract = False 1926 code = 'NO_SEP' 1927 description_template = "No valid RRSIGs made by a key corresponding to a DS RR were found covering the DNSKEY RRset, resulting in no secure entry point (SEP) into the zone." 1928 references = ['RFC 4035, Sec. 2.2', 'RFC 6840, Sec. 5.11'] 1929 required_params = [] 1930 1931 def __init__(self, **kwargs): 1932 super(NoSEP, self).__init__(**kwargs) 1933 try: 1934 self.template_kwargs['source'] = kwargs['source'] 1935 except KeyError: 1936 raise TypeError('The "source" keyword argument is required for instantiation.') 1937 1938class NoNSInParent(DelegationError): 1939 ''' 1940 >>> e = NoNSInParent(parent='baz.') 1941 >>> e.description 1942 'No delegation NS records were detected in the parent zone (baz.). This results in an NXDOMAIN response to a DS query (for DNSSEC), even if the parent servers are authoritative for the child.' 1943 ''' 1944 1945 _abstract = False 1946 code = 'NO_NS_IN_PARENT' 1947 description_template = "No delegation NS records were detected in the parent zone (%(parent)s). This results in an NXDOMAIN response to a DS query (for DNSSEC), even if the parent servers are authoritative for the child." 1948 references = ['RFC 1034, Sec. 4.2.2'] 1949 required_params = ['parent'] 1950 1951class NoNSAddressesForIPVersion(DelegationError): 1952 version = None 1953 required_params = ['reference'] 1954 1955 def __init__(self, *args, **kwargs): 1956 super(NoNSAddressesForIPVersion, self).__init__(**kwargs) 1957 self.template_kwargs['version'] = self.version 1958 1959class NoNSAddressesForIPv4(NoNSAddressesForIPVersion): 1960 ''' 1961 >>> e = NoNSAddressesForIPv4(reference='parent') 1962 >>> e.description 1963 'No IPv4 addresses were found for NS records in the parent zone.' 1964 ''' 1965 1966 _abstract = False 1967 code = 'NO_NS_ADDRESSES_FOR_IPV4' 1968 description_template = "No IPv%(version)d addresses were found for NS records in the %(reference)s zone." 1969 references = [] 1970 version = 4 1971 1972class NoNSAddressesForIPv6(NoNSAddressesForIPVersion): 1973 ''' 1974 >>> e = NoNSAddressesForIPv6(reference='parent') 1975 >>> e.description 1976 'No IPv6 addresses were found for NS records in the parent zone.' 1977 ''' 1978 1979 _abstract = False 1980 code = 'NO_NS_ADDRESSES_FOR_IPV6' 1981 description_template = "No IPv%(version)d addresses were found for NS records in the %(reference)s zone." 1982 references = [] 1983 version = 6 1984 1985class NSNameError(DelegationError): 1986 required_params = ['names'] 1987 1988 def __init__(self, **kwargs): 1989 super(NSNameError, self).__init__(**kwargs) 1990 self.template_kwargs['names_text'] = ', '.join(self.template_kwargs['names']) 1991 1992class NSNameNotInChild(NSNameError): 1993 ''' 1994 >>> e = NSNameNotInChild(names=('ns1.foo.baz.',), parent='baz.') 1995 >>> e.description 1996 'The following NS name(s) were found in the delegation NS RRset (i.e., in the baz. zone), but not in the authoritative NS RRset: ns1.foo.baz.' 1997 ''' 1998 1999 _abstract = False 2000 code = 'NS_NAME_NOT_IN_CHILD' 2001 description_template = "The following NS name(s) were found in the delegation NS RRset (i.e., in the %(parent)s zone), but not in the authoritative NS RRset: %(names_text)s" 2002 required_params = NSNameError.required_params + ['parent'] 2003 2004class NSNameNotInParent(NSNameError): 2005 ''' 2006 >>> e = NSNameNotInParent(names=('ns1.foo.baz.',), parent='baz.') 2007 >>> e.description 2008 'The following NS name(s) were found in the authoritative NS RRset, but not in the delegation NS RRset (i.e., in the baz. zone): ns1.foo.baz.' 2009 ''' 2010 2011 _abstract = False 2012 code = 'NS_NAME_NOT_IN_PARENT' 2013 description_template = "The following NS name(s) were found in the authoritative NS RRset, but not in the delegation NS RRset (i.e., in the %(parent)s zone): %(names_text)s" 2014 required_params = NSNameError.required_params + ['parent'] 2015 2016class ErrorResolvingNSName(NSNameError): 2017 ''' 2018 >>> e = ErrorResolvingNSName(names=('ns1.foo.baz.',)) 2019 >>> e.description 2020 'There was an error resolving the following NS name(s) to address(es): ns1.foo.baz.' 2021 ''' 2022 2023 _abstract = False 2024 code = 'ERROR_RESOLVING_NS_NAME' 2025 description_template = 'There was an error resolving the following NS name(s) to address(es): %(names_text)s' 2026 2027class MissingGlueForNSName(NSNameError): 2028 ''' 2029 >>> e = MissingGlueForNSName(names=('ns1.foo.baz.',)) 2030 >>> e.description 2031 'The following NS name(s) required glue, but no glue was returned in the referral: ns1.foo.baz.' 2032 ''' 2033 2034 _abstract = False 2035 code = 'MISSING_GLUE_FOR_NS_NAME' 2036 description_template = "The following NS name(s) required glue, but no glue was returned in the referral: %(names_text)s" 2037 2038class NoAddressForNSName(NSNameError): 2039 ''' 2040 >>> e = NoAddressForNSName(names=('ns1.foo.baz.',)) 2041 >>> e.description 2042 'The following NS name(s) did not resolve to address(es): ns1.foo.baz.' 2043 ''' 2044 2045 _abstract = False 2046 code = 'NO_ADDRESS_FOR_NS_NAME' 2047 description_template = "The following NS name(s) did not resolve to address(es): %(names_text)s" 2048 2049class PrivateAddressNS(NSNameError): 2050 pass 2051 2052class NSNameResolvesToPrivateIP(PrivateAddressNS): 2053 ''' 2054 >>> e = NSNameResolvesToPrivateIP(names=('ns1.foo.baz.',)) 2055 >>> e.description 2056 'The following NS name(s) resolved to IP address(es) in private IP address space: ns1.foo.baz.' 2057 ''' 2058 2059 _abstract = False 2060 code = 'NS_NAME_PRIVATE_IP' 2061 description_template = "The following NS name(s) resolved to IP address(es) in private IP address space: %(names_text)s" 2062 2063class GlueReferencesPrivateIP(PrivateAddressNS): 2064 ''' 2065 >>> e = GlueReferencesPrivateIP(names=('ns1.foo.baz.',)) 2066 >>> e.description 2067 'Glue for the following NS name(s) referenced IP address(es) in private IP address space: ns1.foo.baz.' 2068 ''' 2069 2070 _abstract = False 2071 code = 'GLUE_PRIVATE_IP' 2072 description_template = "Glue for the following NS name(s) referenced IP address(es) in private IP address space: %(names_text)s" 2073 2074class GlueMismatchError(DelegationError): 2075 ''' 2076 >>> e = GlueMismatchError(name='ns1.foo.baz.', glue_addresses=('192.0.2.1',), auth_addresses=('192.0.2.2',)) 2077 >>> e.description 2078 'The glue address(es) for ns1.foo.baz. (192.0.2.1) differed from its authoritative address(es) (192.0.2.2).' 2079 ''' 2080 2081 _abstract = False 2082 code = 'GLUE_MISMATCH' 2083 description_template = 'The glue address(es) for %(name)s (%(glue_addresses_text)s) differed from its authoritative address(es) (%(auth_addresses_text)s).' 2084 required_params = ['name', 'glue_addresses', 'auth_addresses'] 2085 2086 def __init__(self, **kwargs): 2087 super(GlueMismatchError, self).__init__(**kwargs) 2088 self.template_kwargs['glue_addresses_text'] = ', '.join(self.template_kwargs['glue_addresses']) 2089 self.template_kwargs['auth_addresses_text'] = ', '.join(self.template_kwargs['auth_addresses']) 2090 2091class MissingGlueIPv4(DelegationError): 2092 ''' 2093 >>> e = MissingGlueIPv4(name='ns1.foo.baz.') 2094 >>> e.description 2095 'Authoritative A records exist for ns1.foo.baz., but there are no corresponding A glue records.' 2096 ''' 2097 2098 _abstract = False 2099 code = 'MISSING_GLUE_IPV4' 2100 description_template = "Authoritative A records exist for %(name)s, but there are no corresponding A glue records." 2101 required_params = ['name'] 2102 2103class MissingGlueIPv6(DelegationError): 2104 ''' 2105 >>> e = MissingGlueIPv6(name='ns1.foo.baz.') 2106 >>> e.description 2107 'Authoritative AAAA records exist for ns1.foo.baz., but there are no corresponding AAAA glue records.' 2108 ''' 2109 2110 _abstract = False 2111 code = 'MISSING_GLUE_IPV6' 2112 description_template = "Authoritative AAAA records exist for %(name)s, but there are no corresponding AAAA glue records." 2113 required_params = ['name'] 2114 2115class ExtraGlueIPv4(DelegationError): 2116 ''' 2117 >>> e = ExtraGlueIPv4(name='ns1.foo.baz.') 2118 >>> e.description 2119 'A glue records exist for ns1.foo.baz., but there are no corresponding authoritative A records.' 2120 ''' 2121 2122 _abstract = False 2123 code = 'EXTRA_GLUE_IPV4' 2124 description_template = "A glue records exist for %(name)s, but there are no corresponding authoritative A records." 2125 required_params = ['name'] 2126 2127class ExtraGlueIPv6(DelegationError): 2128 ''' 2129 >>> e = ExtraGlueIPv6(name='ns1.foo.baz.') 2130 >>> e.description 2131 'AAAA glue records exist for ns1.foo.baz., but there are no corresponding authoritative AAAA records.' 2132 ''' 2133 2134 _abstract = False 2135 code = 'EXTRA_GLUE_IPV6' 2136 description_template = "AAAA glue records exist for %(name)s, but there are no corresponding authoritative AAAA records." 2137 required_params = ['name'] 2138 2139class ServerUnresponsive(DelegationError): 2140 description_template = "The server(s) were not responsive to queries over %(proto)s." 2141 proto = None 2142 2143 def __init__(self, **kwargs): 2144 super(ServerUnresponsive, self).__init__(**kwargs) 2145 self.template_kwargs['proto'] = self.proto 2146 2147class ServerUnresponsiveUDP(ServerUnresponsive): 2148 ''' 2149 >>> e = ServerUnresponsiveUDP() 2150 >>> e.description 2151 'The server(s) were not responsive to queries over UDP.' 2152 ''' 2153 2154 _abstract = False 2155 code = 'SERVER_UNRESPONSIVE_UDP' 2156 proto = 'UDP' 2157 2158class ServerUnresponsiveTCP(ServerUnresponsive): 2159 ''' 2160 >>> e = ServerUnresponsiveTCP() 2161 >>> e.description 2162 'The server(s) were not responsive to queries over TCP.' 2163 ''' 2164 2165 _abstract = False 2166 code = 'SERVER_UNRESPONSIVE_TCP' 2167 proto = 'TCP' 2168 2169class ServerInvalidResponseUDP(DelegationError): 2170 ''' 2171 >>> e = ServerInvalidResponseUDP() 2172 >>> e.description 2173 'The server(s) responded over UDP with a malformed response or with an invalid RCODE.' 2174 ''' 2175 2176 _abstract = False 2177 code = 'SERVER_INVALID_RESPONSE_UDP' 2178 description_template = 'The server(s) responded over UDP with a malformed response or with an invalid RCODE.' 2179 2180class ServerInvalidResponseTCP(DelegationError): 2181 ''' 2182 >>> e = ServerInvalidResponseTCP() 2183 >>> e.description 2184 'The server(s) responded over TCP with a malformed response or with an invalid RCODE.' 2185 ''' 2186 2187 _abstract = False 2188 code = 'SERVER_INVALID_RESPONSE_TCP' 2189 description_template = 'The server(s) responded over TCP with a malformed response or with an invalid RCODE.' 2190 2191class ServerNotAuthoritative(DelegationError): 2192 ''' 2193 >>> e = ServerNotAuthoritative() 2194 >>> e.description 2195 'The server(s) did not respond authoritatively for the namespace.' 2196 ''' 2197 2198 _abstract = False 2199 code = 'SERVER_NOT_AUTHORITATIVE' 2200 description_template = "The server(s) did not respond authoritatively for the namespace." 2201 2202class DNAMEError(DomainNameAnalysisError): 2203 pass 2204 2205class DNAMENoCNAME(DNAMEError): 2206 ''' 2207 >>> e = DNAMENoCNAME() 2208 >>> e.description 2209 'No synthesized CNAME RR was found accompanying the DNAME record.' 2210 ''' 2211 _abstract = False 2212 description_template = "No synthesized CNAME RR was found accompanying the DNAME record." 2213 code = 'DNAME_NO_CNAME' 2214 2215class DNAMETargetMismatch(DNAMEError): 2216 ''' 2217 >>> e = DNAMETargetMismatch(included_target='foo.baz.', synthesized_target='bar.baz.') 2218 >>> e.description 2219 'The included CNAME RR is not a valid synthesis of the DNAME record (foo.baz. != bar.baz.).' 2220 ''' 2221 _abstract = False 2222 description_template = "The included CNAME RR is not a valid synthesis of the DNAME record (%(included_target)s != %(synthesized_target)s)." 2223 code = 'DNAME_TARGET_MISMATCH' 2224 required_params = ['included_target', 'synthesized_target'] 2225 2226class DNAMETTLZero(DNAMEError): 2227 ''' 2228 >>> e = DNAMETTLZero() 2229 >>> e.description 2230 'The TTL of the synthesized CNAME RR is 0.' 2231 ''' 2232 _abstract = False 2233 description_template = "The TTL of the synthesized CNAME RR is 0." 2234 code = 'DNAME_TTL_ZERO' 2235 2236class DNAMETTLMismatch(DNAMEError): 2237 ''' 2238 >>> e = DNAMETTLMismatch(cname_ttl=50, dname_ttl=60) 2239 >>> e.description 2240 'The TTL of the synthesized CNAME RR (50) does not match the TTL of the DNAME record (60).' 2241 ''' 2242 _abstract = False 2243 description_template = "The TTL of the synthesized CNAME RR (%(cname_ttl)d) does not match the TTL of the DNAME record (%(dname_ttl)d)." 2244 code = 'DNAME_TTL_MISMATCH' 2245 required_params = ['cname_ttl', 'dname_ttl'] 2246 2247class DNSKEYError(DomainNameAnalysisError): 2248 pass 2249 2250class DNSKEYMissingFromServers(DNSKEYError): 2251 ''' 2252 >>> e = DNSKEYMissingFromServers() 2253 >>> e.description 2254 'The DNSKEY RR was not found in the DNSKEY RRset returned by one or more servers.' 2255 ''' 2256 _abstract = False 2257 description_template = "The DNSKEY RR was not found in the DNSKEY RRset returned by one or more servers." 2258 code = 'DNSKEY_MISSING_FROM_SERVERS' 2259 2260class DNSKEYNotAtZoneApex(DNSKEYError): 2261 ''' 2262 >>> e = DNSKEYNotAtZoneApex(zone='foo.baz.', name='bar.foo.baz.') 2263 >>> e.description 2264 'The owner name of the DNSKEY RRset (bar.foo.baz.) does not match the zone apex (foo.baz.).' 2265 ''' 2266 _abstract = False 2267 description_template = "The owner name of the DNSKEY RRset (%(name)s) does not match the zone apex (%(zone)s)." 2268 code = 'DNSKEY_NOT_AT_ZONE_APEX' 2269 required_params = ['zone', 'name'] 2270 2271class DNSKEYBadLength(DNSKEYError): 2272 pass 2273 2274class DNSKEYZeroLength(DNSKEYBadLength): 2275 ''' 2276 >>> e = DNSKEYZeroLength() 2277 >>> e.description 2278 'The length of the key is 0 bits.' 2279 ''' 2280 _abstract = False 2281 description_template = 'The length of the key is 0 bits.' 2282 code = 'DNSKEY_ZERO_LENGTH' 2283 references = [] 2284 required_params = [] 2285 2286class DNSKEYBadLengthGOST(DNSKEYBadLength): 2287 ''' 2288 >>> e = DNSKEYBadLengthGOST(length=500) 2289 >>> e.description 2290 'The length of the key is 500 bits, but a GOST public key (DNSSEC algorithm 12) must be 512 bits long.' 2291 ''' 2292 _abstract = False 2293 description_template = 'The length of the key is %(length)d bits, but a GOST public key (DNSSEC algorithm 12) must be 512 bits long.' 2294 code = 'DNSKEY_BAD_LENGTH_GOST' 2295 references = ['RFC 5933, Sec. 5.1'] 2296 required_params = ['length'] 2297 2298class DNSKEYBadLengthECDSA(DNSKEYBadLength): 2299 curve = None 2300 algorithm = None 2301 correct_length = None 2302 description_template = 'The length of the key is %(length)d bits, but an ECDSA public key using Curve %(curve)s (DNSSEC algorithm %(algorithm)d) must be %(correct_length)d bits long.' 2303 references = ['RFC 6605, Sec. 4'] 2304 required_params = ['length'] 2305 2306 def __init__(self, **kwargs): 2307 super(DNSKEYBadLengthECDSA, self).__init__(**kwargs) 2308 self.template_kwargs['curve'] = self.curve 2309 self.template_kwargs['algorithm'] = self.algorithm 2310 self.template_kwargs['correct_length'] = self.correct_length 2311 2312class DNSKEYBadLengthECDSA256(DNSKEYBadLengthECDSA): 2313 ''' 2314 >>> e = DNSKEYBadLengthECDSA256(length=500) 2315 >>> e.description 2316 'The length of the key is 500 bits, but an ECDSA public key using Curve P-256 (DNSSEC algorithm 13) must be 512 bits long.' 2317 ''' 2318 curve = 'P-256' 2319 algorithm = 13 2320 correct_length = 512 2321 _abstract = False 2322 code = 'DNSKEY_BAD_LENGTH_ECDSA256' 2323 2324class DNSKEYBadLengthECDSA384(DNSKEYBadLengthECDSA): 2325 ''' 2326 >>> e = DNSKEYBadLengthECDSA384(length=500) 2327 >>> e.description 2328 'The length of the key is 500 bits, but an ECDSA public key using Curve P-384 (DNSSEC algorithm 14) must be 768 bits long.' 2329 ''' 2330 curve = 'P-384' 2331 algorithm = 14 2332 correct_length = 768 2333 _abstract = False 2334 code = 'DNSKEY_BAD_LENGTH_ECDSA384' 2335 2336class DNSKEYBadLengthEdDSA(DNSKEYBadLength): 2337 curve = None 2338 algorithm = None 2339 correct_length = None 2340 description_template = 'The length of the key is %(length)d bits, but an %(curve)s public key (DNSSEC algorithm %(algorithm)d) must be %(correct_length)d bits long.' 2341 references = ['RFC 8080, Sec. 3'] 2342 required_params = ['length'] 2343 2344 def __init__(self, **kwargs): 2345 super(DNSKEYBadLengthEdDSA, self).__init__(**kwargs) 2346 self.template_kwargs['curve'] = self.curve 2347 self.template_kwargs['algorithm'] = self.algorithm 2348 self.template_kwargs['correct_length'] = self.correct_length 2349 2350class DNSKEYBadLengthEd25519(DNSKEYBadLengthEdDSA): 2351 ''' 2352 >>> e = DNSKEYBadLengthEd25519(length=500) 2353 >>> e.description 2354 'The length of the key is 500 bits, but an Ed25519 public key (DNSSEC algorithm 15) must be 256 bits long.' 2355 ''' 2356 curve = 'Ed25519' 2357 algorithm = 15 2358 correct_length = 256 2359 _abstract = False 2360 code = 'DNSKEY_BAD_LENGTH_ED25519' 2361 2362class DNSKEYBadLengthEd448(DNSKEYBadLengthEdDSA): 2363 ''' 2364 >>> e = DNSKEYBadLengthEd448(length=500) 2365 >>> e.description 2366 'The length of the key is 500 bits, but an Ed448 public key (DNSSEC algorithm 16) must be 456 bits long.' 2367 ''' 2368 curve = 'Ed448' 2369 algorithm = 16 2370 correct_length = 456 2371 _abstract = False 2372 code = 'DNSKEY_BAD_LENGTH_ED448' 2373 2374class TrustAnchorError(DomainNameAnalysisError): 2375 pass 2376 2377class NoTrustAnchorSigning(TrustAnchorError): 2378 ''' 2379 >>> e = NoTrustAnchorSigning(zone='foo.baz.') 2380 >>> e.description 2381 'One or more keys were designated as trust anchors for foo.baz., but none were found signing the DNSKEY RRset.' 2382 ''' 2383 _abstract = False 2384 description_template = "One or more keys were designated as trust anchors for %(zone)s, but none were found signing the DNSKEY RRset." 2385 code = 'NO_TRUST_ANCHOR_SIGNING' 2386 required_params = ['zone'] 2387 2388class RevokedNotSigning(DNSKEYError): 2389 ''' 2390 >>> e = RevokedNotSigning() 2391 >>> e.description 2392 'The key was revoked but was not found signing the RRset.' 2393 ''' 2394 _abstract = False 2395 description_template = "The key was revoked but was not found signing the RRset." 2396 code = 'REVOKED_NOT_SIGNING' 2397 2398class ZoneDataError(DomainNameAnalysisError): 2399 pass 2400 2401class CNAMEWithOtherData(ZoneDataError): 2402 ''' 2403 >>> e = CNAMEWithOtherData(name='foo.') 2404 >>> e.description 2405 'The server returned CNAME for foo., but records of other types exist at that name.' 2406 ''' 2407 _abstract = False 2408 description_template = "The server returned CNAME for %(name)s, but records of other types exist at that name." 2409 code = 'CNAME_WITH_OTHER_DATA' 2410 required_params = ['name'] 2411 references = ['RFC 2181, Sec. 10.1'] 2412 2413class CNAMELoop(ZoneDataError): 2414 ''' 2415 >>> e = CNAMELoop() 2416 >>> e.description 2417 'This record results in a CNAME loop.' 2418 ''' 2419 _abstract = False 2420 description_template = "This record results in a CNAME loop." 2421 code = 'CNAME_LOOP' 2422 references = ['RFC 1034, Sec. 3.6.2'] 2423