Package dns :: Package rdtypes :: Package ANY :: Module NSEC3
[hide private]
[frames] | no frames]

Source Code for Module dns.rdtypes.ANY.NSEC3

  1  # Copyright (C) Dnspython Contributors, see LICENSE for text of ISC license 
  2   
  3  # Copyright (C) 2004-2017 Nominum, Inc. 
  4  # 
  5  # Permission to use, copy, modify, and distribute this software and its 
  6  # documentation for any purpose with or without fee is hereby granted, 
  7  # provided that the above copyright notice and this permission notice 
  8  # appear in all copies. 
  9  # 
 10  # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES 
 11  # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 
 12  # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR 
 13  # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 
 14  # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 
 15  # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 
 16  # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 
 17   
 18  import base64 
 19  import binascii 
 20  import string 
 21  import struct 
 22   
 23  import dns.exception 
 24  import dns.rdata 
 25  import dns.rdatatype 
 26  from dns._compat import xrange, text_type, PY3 
 27   
 28  # pylint: disable=deprecated-string-function 
 29  if PY3: 
 30      b32_hex_to_normal = bytes.maketrans(b'0123456789ABCDEFGHIJKLMNOPQRSTUV', 
 31                                          b'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567') 
 32      b32_normal_to_hex = bytes.maketrans(b'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567', 
 33                                          b'0123456789ABCDEFGHIJKLMNOPQRSTUV') 
 34  else: 
 35      b32_hex_to_normal = string.maketrans('0123456789ABCDEFGHIJKLMNOPQRSTUV', 
 36                                           'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567') 
 37      b32_normal_to_hex = string.maketrans('ABCDEFGHIJKLMNOPQRSTUVWXYZ234567', 
 38                                           '0123456789ABCDEFGHIJKLMNOPQRSTUV') 
 39  # pylint: enable=deprecated-string-function 
 40   
 41   
 42  # hash algorithm constants 
 43  SHA1 = 1 
 44   
 45  # flag constants 
 46  OPTOUT = 1 
47 48 49 -class NSEC3(dns.rdata.Rdata):
50 51 """NSEC3 record 52 53 @ivar algorithm: the hash algorithm number 54 @type algorithm: int 55 @ivar flags: the flags 56 @type flags: int 57 @ivar iterations: the number of iterations 58 @type iterations: int 59 @ivar salt: the salt 60 @type salt: string 61 @ivar next: the next name hash 62 @type next: string 63 @ivar windows: the windowed bitmap list 64 @type windows: list of (window number, string) tuples""" 65 66 __slots__ = ['algorithm', 'flags', 'iterations', 'salt', 'next', 'windows'] 67
68 - def __init__(self, rdclass, rdtype, algorithm, flags, iterations, salt, 69 next, windows):
70 super(NSEC3, self).__init__(rdclass, rdtype) 71 self.algorithm = algorithm 72 self.flags = flags 73 self.iterations = iterations 74 if isinstance(salt, text_type): 75 self.salt = salt.encode() 76 else: 77 self.salt = salt 78 self.next = next 79 self.windows = windows
80
81 - def to_text(self, origin=None, relativize=True, **kw):
82 next = base64.b32encode(self.next).translate( 83 b32_normal_to_hex).lower().decode() 84 if self.salt == b'': 85 salt = '-' 86 else: 87 salt = binascii.hexlify(self.salt).decode() 88 text = u'' 89 for (window, bitmap) in self.windows: 90 bits = [] 91 for i in xrange(0, len(bitmap)): 92 byte = bitmap[i] 93 for j in xrange(0, 8): 94 if byte & (0x80 >> j): 95 bits.append(dns.rdatatype.to_text(window * 256 + 96 i * 8 + j)) 97 text += (u' ' + u' '.join(bits)) 98 return u'%u %u %u %s %s%s' % (self.algorithm, self.flags, 99 self.iterations, salt, next, text)
100 101 @classmethod
102 - def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True):
103 algorithm = tok.get_uint8() 104 flags = tok.get_uint8() 105 iterations = tok.get_uint16() 106 salt = tok.get_string() 107 if salt == u'-': 108 salt = b'' 109 else: 110 salt = binascii.unhexlify(salt.encode('ascii')) 111 next = tok.get_string().encode( 112 'ascii').upper().translate(b32_hex_to_normal) 113 next = base64.b32decode(next) 114 rdtypes = [] 115 while 1: 116 token = tok.get().unescape() 117 if token.is_eol_or_eof(): 118 break 119 nrdtype = dns.rdatatype.from_text(token.value) 120 if nrdtype == 0: 121 raise dns.exception.SyntaxError("NSEC3 with bit 0") 122 if nrdtype > 65535: 123 raise dns.exception.SyntaxError("NSEC3 with bit > 65535") 124 rdtypes.append(nrdtype) 125 rdtypes.sort() 126 window = 0 127 octets = 0 128 prior_rdtype = 0 129 bitmap = bytearray(b'\0' * 32) 130 windows = [] 131 for nrdtype in rdtypes: 132 if nrdtype == prior_rdtype: 133 continue 134 prior_rdtype = nrdtype 135 new_window = nrdtype // 256 136 if new_window != window: 137 if octets != 0: 138 windows.append((window, bitmap[0:octets])) 139 bitmap = bytearray(b'\0' * 32) 140 window = new_window 141 offset = nrdtype % 256 142 byte = offset // 8 143 bit = offset % 8 144 octets = byte + 1 145 bitmap[byte] = bitmap[byte] | (0x80 >> bit) 146 if octets != 0: 147 windows.append((window, bitmap[0:octets])) 148 return cls(rdclass, rdtype, algorithm, flags, iterations, salt, next, 149 windows)
150
151 - def to_wire(self, file, compress=None, origin=None):
152 l = len(self.salt) 153 file.write(struct.pack("!BBHB", self.algorithm, self.flags, 154 self.iterations, l)) 155 file.write(self.salt) 156 l = len(self.next) 157 file.write(struct.pack("!B", l)) 158 file.write(self.next) 159 for (window, bitmap) in self.windows: 160 file.write(struct.pack("!BB", window, len(bitmap))) 161 file.write(bitmap)
162 163 @classmethod
164 - def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin=None):
165 (algorithm, flags, iterations, slen) = \ 166 struct.unpack('!BBHB', wire[current: current + 5]) 167 168 current += 5 169 rdlen -= 5 170 salt = wire[current: current + slen].unwrap() 171 current += slen 172 rdlen -= slen 173 nlen = wire[current] 174 current += 1 175 rdlen -= 1 176 next = wire[current: current + nlen].unwrap() 177 current += nlen 178 rdlen -= nlen 179 windows = [] 180 while rdlen > 0: 181 if rdlen < 3: 182 raise dns.exception.FormError("NSEC3 too short") 183 window = wire[current] 184 octets = wire[current + 1] 185 if octets == 0 or octets > 32: 186 raise dns.exception.FormError("bad NSEC3 octets") 187 current += 2 188 rdlen -= 2 189 if rdlen < octets: 190 raise dns.exception.FormError("bad NSEC3 bitmap length") 191 bitmap = bytearray(wire[current: current + octets].unwrap()) 192 current += octets 193 rdlen -= octets 194 windows.append((window, bitmap)) 195 return cls(rdclass, rdtype, algorithm, flags, iterations, salt, next, 196 windows)
197