dnspython  1.16.0
About: dnspython is a DNS toolkit (for Python 2.x) that supports almost all record types.
  Fossies Dox: dnspython-1.16.0.tar.gz  ("inofficial" and yet experimental doxygen-generated source code documentation)  

NSEC3.py
Go to the documentation of this file.
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 
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)
dns.exception.FormError
Definition: exception.py:109
dns.exception.SyntaxError
Definition: exception.py:113
dns.rdtypes.ANY.NSEC3.NSEC3.flags
flags
Definition: NSEC3.py:71
dns.rdtypes.ANY.NSEC3.NSEC3
Definition: NSEC3.py:49
dns.rdtypes.ANY.NSEC3.NSEC3.__init__
def __init__(self, rdclass, rdtype, algorithm, flags, iterations, salt, next, windows)
Definition: NSEC3.py:68
dns.rdtypes.ANY.NSEC3.NSEC3.from_text
def from_text(cls, rdclass, rdtype, tok, origin=None, relativize=True)
Definition: NSEC3.py:102
dns.rdtypes.ANY.NSEC3.NSEC3.windows
windows
Definition: NSEC3.py:78
dns.rdtypes.ANY.NSEC3.NSEC3.to_wire
def to_wire(self, file, compress=None, origin=None)
Definition: NSEC3.py:151
dns.rdtypes.ANY.NSEC3.NSEC3.next
next
Definition: NSEC3.py:77
dns.rdtypes.ANY.NSEC3.NSEC3.from_wire
def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin=None)
Definition: NSEC3.py:164
dns.rdata
Definition: rdata.py:1
dns.rdatatype
Definition: rdatatype.py:1
dns.rdtypes.ANY.NSEC3.NSEC3.to_text
def to_text(self, origin=None, relativize=True, **kw)
Definition: NSEC3.py:81
dns.rdatatype.to_text
def to_text(value)
Definition: rdatatype.py:219
dns.rdatatype.from_text
def from_text(text)
Definition: rdatatype.py:193
dns.rdtypes.ANY.NSEC3.NSEC3.iterations
iterations
Definition: NSEC3.py:72
dns._compat
Definition: _compat.py:1
dns._compat.xrange
xrange
Definition: _compat.py:11
dns.rdtypes.ANY.NSEC3.NSEC3.algorithm
algorithm
Definition: NSEC3.py:70
dns.exception
Definition: exception.py:1
dns.rdtypes.ANY.NSEC3.NSEC3.salt
salt
Definition: NSEC3.py:74
dns.rdata.Rdata
Definition: rdata.py:95