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 cStringIO
     18  import string
     19  import struct
     20
     21  import dns.exception
     22  import dns.rdata
     23  import dns.rdatatype
     24
     25  b32_hex_to_normal = string.maketrans('0123456789ABCDEFGHIJKLMNOPQRSTUV',
     26                                       'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567')
     27  b32_normal_to_hex = string.maketrans('ABCDEFGHIJKLMNOPQRSTUVWXYZ234567',
     28                                       '0123456789ABCDEFGHIJKLMNOPQRSTUV')
     29
     30  # hash algorithm constants
     31  SHA1 = 1
     32
     33  # flag constants
     34  OPTOUT = 1
     35
     36 -class NSEC3(dns.rdata.Rdata):
     37      """NSEC3 record
     38
     39      @ivar algorithm: the hash algorithm number
     40      @type algorithm: int
     41      @ivar flags: the flags
     42      @type flags: int
     43      @ivar iterations: the number of iterations
     44      @type iterations: int
     45      @ivar salt: the salt
     46      @type salt: string
     47      @ivar next: the next name hash
     48      @type next: string
     49      @ivar windows: the windowed bitmap list
     50      @type windows: list of (window number, string) tuples"""
     51
     52      __slots__ = ['algorithm', 'flags', 'iterations', 'salt', 'next', 'windows']
     53
     54 -    def __init__(self, rdclass, rdtype, algorithm, flags, iterations, salt,
     55                   next, windows):
     56          super(NSEC3, self).__init__(rdclass, rdtype)
     57          self.algorithm = algorithm
     58          self.flags = flags
     59          self.iterations = iterations
     60          self.salt = salt
     61          self.next = next
     62          self.windows = windows
     63
     64 -    def to_text(self, origin=None, relativize=True, **kw):
     65          next = base64.b32encode(self.next).translate(b32_normal_to_hex).lower()
     66          if self.salt == '':
     67              salt = '-'
     68          else:
     69              salt = self.salt.encode('hex-codec')
     70          text = ''
     71          for (window, bitmap) in self.windows:
     72              bits = []
     73              for i in xrange(0, len(bitmap)):
     74                  byte = ord(bitmap[i])
     75                  for j in xrange(0, 8):
     76                      if byte & (0x80 >> j):
     77                          bits.append(dns.rdatatype.to_text(window * 256 + \
     78                                                            i * 8 + j))
     79              text += (' ' + ' '.join(bits))
     80          return '%u %u %u %s %s%s' % (self.algorithm, self.flags, self.iterations,
     81                                       salt, next, text)
     82
     83 -    def from_text(cls, rdclass, rdtype, tok, origin = None, relativize = True):
     84          algorithm = tok.get_uint8()
     85          flags = tok.get_uint8()
     86          iterations = tok.get_uint16()
     87          salt = tok.get_string()
     88          if salt == '-':
     89              salt = ''
     90          else:
     91              salt = salt.decode('hex-codec')
     92          next = tok.get_string().upper().translate(b32_hex_to_normal)
     93          next = base64.b32decode(next)
     94          rdtypes = []
     95          while 1:
     96              token = tok.get().unescape()
     97              if token.is_eol_or_eof():
     98                  break
     99              nrdtype = dns.rdatatype.from_text(token.value)
    100              if nrdtype == 0:
    101                  raise dns.exception.SyntaxError("NSEC3 with bit 0")
    102              if nrdtype > 65535:
    103                  raise dns.exception.SyntaxError("NSEC3 with bit > 65535")
    104              rdtypes.append(nrdtype)
    105          rdtypes.sort()
    106          window = 0
    107          octets = 0
    108          prior_rdtype = 0
    109          bitmap = ['\0'] * 32
    110          windows = []
    111          for nrdtype in rdtypes:
    112              if nrdtype == prior_rdtype:
    113                  continue
    114              prior_rdtype = nrdtype
    115              new_window = nrdtype // 256
    116              if new_window != window:
    117                  if octets != 0:
    118                      windows.append((window, ''.join(bitmap[0:octets])))
    119                  bitmap = ['\0'] * 32
    120                  window = new_window
    121              offset = nrdtype % 256
    122              byte = offset // 8
    123              bit = offset % 8
    124              octets = byte + 1
    125              bitmap[byte] = chr(ord(bitmap[byte]) | (0x80 >> bit))
    126          if octets != 0:
    127              windows.append((window, ''.join(bitmap[0:octets])))
    128          return cls(rdclass, rdtype, algorithm, flags, iterations, salt, next, windows)
    129
    130      from_text = classmethod(from_text)
    131
    132 -    def to_wire(self, file, compress = None, origin = None):
    133          l = len(self.salt)
    134          file.write(struct.pack("!BBHB", self.algorithm, self.flags,
    135                                 self.iterations, l))
    136          file.write(self.salt)
    137          l = len(self.next)
    138          file.write(struct.pack("!B", l))
    139          file.write(self.next)
    140          for (window, bitmap) in self.windows:
    141              file.write(chr(window))
    142              file.write(chr(len(bitmap)))
    143              file.write(bitmap)
    144
    145 -    def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None):
    146          (algorithm, flags, iterations, slen) = struct.unpack('!BBHB',
    147                                                               wire[current : current + 5])
    148          current += 5
    149          rdlen -= 5
    150          salt = wire[current : current + slen].unwrap()
    151          current += slen
    152          rdlen -= slen
    153          (nlen, ) = struct.unpack('!B', wire[current])
    154          current += 1
    155          rdlen -= 1
    156          next = wire[current : current + nlen].unwrap()
    157          current += nlen
    158          rdlen -= nlen
    159          windows = []
    160          while rdlen > 0:
    161              if rdlen < 3:
    162                  raise dns.exception.FormError("NSEC3 too short")
    163              window = ord(wire[current])
    164              octets = ord(wire[current + 1])
    165              if octets == 0 or octets > 32:
    166                  raise dns.exception.FormError("bad NSEC3 octets")
    167              current += 2
    168              rdlen -= 2
    169              if rdlen < octets:
    170                  raise dns.exception.FormError("bad NSEC3 bitmap length")
    171              bitmap = wire[current : current + octets].unwrap()
    172              current += octets
    173              rdlen -= octets
    174              windows.append((window, bitmap))
    175          return cls(rdclass, rdtype, algorithm, flags, iterations, salt, next, windows)
    176
    177      from_wire = classmethod(from_wire)
    178
    179 -    def _cmp(self, other):
    180          b1 = cStringIO.StringIO()
    181          self.to_wire(b1)
    182          b2 = cStringIO.StringIO()
    183          other.to_wire(b2)
    184          return cmp(b1.getvalue(), b2.getvalue())
    185