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

# Source Code for Module dns.rdtypes.ANY.NSEC3

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