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, 2010 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                  windows.append((window, ''.join(bitmap[0:octets])))
    118                  bitmap = ['\0'] * 32
    119                  window = new_window
    120              offset = nrdtype % 256
    121              byte = offset / 8
    122              bit = offset % 8
    123              octets = byte + 1
    124              bitmap[byte] = chr(ord(bitmap[byte]) | (0x80 >> bit))
    125          windows.append((window, ''.join(bitmap[0:octets])))
    126          return cls(rdclass, rdtype, algorithm, flags, iterations, salt, next, windows)
    127
    128      from_text = classmethod(from_text)
    129
    130 -    def to_wire(self, file, compress = None, origin = None):
    131          l = len(self.salt)
    132          file.write(struct.pack("!BBHB", self.algorithm, self.flags,
    133                                 self.iterations, l))
    134          file.write(self.salt)
    135          l = len(self.next)
    136          file.write(struct.pack("!B", l))
    137          file.write(self.next)
    138          for (window, bitmap) in self.windows:
    139              file.write(chr(window))
    140              file.write(chr(len(bitmap)))
    141              file.write(bitmap)
    142
    143 -    def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None):
    144          (algorithm, flags, iterations, slen) = struct.unpack('!BBHB',
    145                                                               wire[current : current + 5])
    146          current += 5
    147          rdlen -= 5
    148          salt = wire[current : current + slen]
    149          current += slen
    150          rdlen -= slen
    151          (nlen, ) = struct.unpack('!B', wire[current])
    152          current += 1
    153          rdlen -= 1
    154          next = wire[current : current + nlen]
    155          current += nlen
    156          rdlen -= nlen
    157          windows = []
    158          while rdlen > 0:
    159              if rdlen < 3:
    160                  raise dns.exception.FormError("NSEC3 too short")
    161              window = ord(wire[current])
    162              octets = ord(wire[current + 1])
    163              if octets == 0 or octets > 32:
    164                  raise dns.exception.FormError("bad NSEC3 octets")
    165              current += 2
    166              rdlen -= 2
    167              if rdlen < octets:
    168                  raise dns.exception.FormError("bad NSEC3 bitmap length")
    169              bitmap = wire[current : current + octets]
    170              current += octets
    171              rdlen -= octets
    172              windows.append((window, bitmap))
    173          return cls(rdclass, rdtype, algorithm, flags, iterations, salt, next, windows)
    174
    175      from_wire = classmethod(from_wire)
    176
    177 -    def _cmp(self, other):
    178          b1 = cStringIO.StringIO()
    179          self.to_wire(b1)
    180          b2 = cStringIO.StringIO()
    181          other.to_wire(b2)
    182          return cmp(b1.getvalue(), b2.getvalue())
    183