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