Merge branch 'master' of ctdb into 'master' of samba
[samba.git] / lib / dnspython / dns / rdtypes / ANY / RRSIG.py
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 calendar
17 import struct
18 import time
19
20 import dns.dnssec
21 import dns.exception
22 import dns.rdata
23 import dns.rdatatype
24
25 class BadSigTime(dns.exception.DNSException):
26     """Raised when a SIG or RRSIG RR's time cannot be parsed."""
27     pass
28
29 def sigtime_to_posixtime(what):
30     if len(what) != 14:
31         raise BadSigTime
32     year = int(what[0:4])
33     month = int(what[4:6])
34     day = int(what[6:8])
35     hour = int(what[8:10])
36     minute = int(what[10:12])
37     second = int(what[12:14])
38     return calendar.timegm((year, month, day, hour, minute, second,
39                             0, 0, 0))
40
41 def posixtime_to_sigtime(what):
42     return time.strftime('%Y%m%d%H%M%S', time.gmtime(what))
43
44 class RRSIG(dns.rdata.Rdata):
45     """RRSIG record
46
47     @ivar type_covered: the rdata type this signature covers
48     @type type_covered: int
49     @ivar algorithm: the algorithm used for the sig
50     @type algorithm: int
51     @ivar labels: number of labels
52     @type labels: int
53     @ivar original_ttl: the original TTL
54     @type original_ttl: long
55     @ivar expiration: signature expiration time
56     @type expiration: long
57     @ivar inception: signature inception time
58     @type inception: long
59     @ivar key_tag: the key tag
60     @type key_tag: int
61     @ivar signer: the signer
62     @type signer: dns.name.Name object
63     @ivar signature: the signature
64     @type signature: string"""
65
66     __slots__ = ['type_covered', 'algorithm', 'labels', 'original_ttl',
67                  'expiration', 'inception', 'key_tag', 'signer',
68                  'signature']
69
70     def __init__(self, rdclass, rdtype, type_covered, algorithm, labels,
71                  original_ttl, expiration, inception, key_tag, signer,
72                  signature):
73         super(RRSIG, self).__init__(rdclass, rdtype)
74         self.type_covered = type_covered
75         self.algorithm = algorithm
76         self.labels = labels
77         self.original_ttl = original_ttl
78         self.expiration = expiration
79         self.inception = inception
80         self.key_tag = key_tag
81         self.signer = signer
82         self.signature = signature
83
84     def covers(self):
85         return self.type_covered
86
87     def to_text(self, origin=None, relativize=True, **kw):
88         return '%s %d %d %d %s %s %d %s %s' % (
89             dns.rdatatype.to_text(self.type_covered),
90             self.algorithm,
91             self.labels,
92             self.original_ttl,
93             posixtime_to_sigtime(self.expiration),
94             posixtime_to_sigtime(self.inception),
95             self.key_tag,
96             self.signer,
97             dns.rdata._base64ify(self.signature)
98             )
99
100     def from_text(cls, rdclass, rdtype, tok, origin = None, relativize = True):
101         type_covered = dns.rdatatype.from_text(tok.get_string())
102         algorithm = dns.dnssec.algorithm_from_text(tok.get_string())
103         labels = tok.get_int()
104         original_ttl = tok.get_ttl()
105         expiration = sigtime_to_posixtime(tok.get_string())
106         inception = sigtime_to_posixtime(tok.get_string())
107         key_tag = tok.get_int()
108         signer = tok.get_name()
109         signer = signer.choose_relativity(origin, relativize)
110         chunks = []
111         while 1:
112             t = tok.get().unescape()
113             if t.is_eol_or_eof():
114                 break
115             if not t.is_identifier():
116                 raise dns.exception.SyntaxError
117             chunks.append(t.value)
118         b64 = ''.join(chunks)
119         signature = b64.decode('base64_codec')
120         return cls(rdclass, rdtype, type_covered, algorithm, labels,
121                    original_ttl, expiration, inception, key_tag, signer,
122                    signature)
123
124     from_text = classmethod(from_text)
125
126     def to_wire(self, file, compress = None, origin = None):
127         header = struct.pack('!HBBIIIH', self.type_covered,
128                              self.algorithm, self.labels,
129                              self.original_ttl, self.expiration,
130                              self.inception, self.key_tag)
131         file.write(header)
132         self.signer.to_wire(file, None, origin)
133         file.write(self.signature)
134
135     def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None):
136         header = struct.unpack('!HBBIIIH', wire[current : current + 18])
137         current += 18
138         rdlen -= 18
139         (signer, cused) = dns.name.from_wire(wire[: current + rdlen], current)
140         current += cused
141         rdlen -= cused
142         if not origin is None:
143             signer = signer.relativize(origin)
144         signature = wire[current : current + rdlen].unwrap()
145         return cls(rdclass, rdtype, header[0], header[1], header[2],
146                    header[3], header[4], header[5], header[6], signer,
147                    signature)
148
149     from_wire = classmethod(from_wire)
150
151     def choose_relativity(self, origin = None, relativize = True):
152         self.signer = self.signer.choose_relativity(origin, relativize)
153
154     def _cmp(self, other):
155         return self._wire_cmp(other)