c102521a149e72c1d540a695ee33f7ac6b089434
[samba.git] / lib / dnspython / dns / rdtypes / ANY / CERT.py
1 # Copyright (C) 2003-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 cStringIO
17 import struct
18
19 import dns.exception
20 import dns.dnssec
21 import dns.rdata
22 import dns.tokenizer
23
24 _ctype_by_value = {
25     1 : 'PKIX',
26     2 : 'SPKI',
27     3 : 'PGP',
28     253 : 'URI',
29     254 : 'OID',
30     }
31
32 _ctype_by_name = {
33     'PKIX' : 1,
34     'SPKI' : 2,
35     'PGP' : 3,
36     'URI' : 253,
37     'OID' : 254,
38     }
39
40 def _ctype_from_text(what):
41     v = _ctype_by_name.get(what)
42     if not v is None:
43         return v
44     return int(what)
45
46 def _ctype_to_text(what):
47     v = _ctype_by_value.get(what)
48     if not v is None:
49         return v
50     return str(what)
51
52 class CERT(dns.rdata.Rdata):
53     """CERT record
54
55     @ivar certificate_type: certificate type
56     @type certificate_type: int
57     @ivar key_tag: key tag
58     @type key_tag: int
59     @ivar algorithm: algorithm
60     @type algorithm: int
61     @ivar certificate: the certificate or CRL
62     @type certificate: string
63     @see: RFC 2538"""
64
65     __slots__ = ['certificate_type', 'key_tag', 'algorithm', 'certificate']
66
67     def __init__(self, rdclass, rdtype, certificate_type, key_tag, algorithm,
68                  certificate):
69         super(CERT, self).__init__(rdclass, rdtype)
70         self.certificate_type = certificate_type
71         self.key_tag = key_tag
72         self.algorithm = algorithm
73         self.certificate = certificate
74
75     def to_text(self, origin=None, relativize=True, **kw):
76         certificate_type = _ctype_to_text(self.certificate_type)
77         return "%s %d %s %s" % (certificate_type, self.key_tag,
78                                 dns.dnssec.algorithm_to_text(self.algorithm),
79                                 dns.rdata._base64ify(self.certificate))
80
81     def from_text(cls, rdclass, rdtype, tok, origin = None, relativize = True):
82         certificate_type = _ctype_from_text(tok.get_string())
83         key_tag = tok.get_uint16()
84         algorithm = dns.dnssec.algorithm_from_text(tok.get_string())
85         if algorithm < 0 or algorithm > 255:
86             raise dns.exception.SyntaxError("bad algorithm type")
87         chunks = []
88         while 1:
89             t = tok.get().unescape()
90             if t.is_eol_or_eof():
91                 break
92             if not t.is_identifier():
93                 raise dns.exception.SyntaxError
94             chunks.append(t.value)
95         b64 = ''.join(chunks)
96         certificate = b64.decode('base64_codec')
97         return cls(rdclass, rdtype, certificate_type, key_tag,
98                    algorithm, certificate)
99
100     from_text = classmethod(from_text)
101
102     def to_wire(self, file, compress = None, origin = None):
103         prefix = struct.pack("!HHB", self.certificate_type, self.key_tag,
104                              self.algorithm)
105         file.write(prefix)
106         file.write(self.certificate)
107
108     def from_wire(cls, rdclass, rdtype, wire, current, rdlen, origin = None):
109         prefix = wire[current : current + 5].unwrap()
110         current += 5
111         rdlen -= 5
112         if rdlen < 0:
113             raise dns.exception.FormError
114         (certificate_type, key_tag, algorithm) = struct.unpack("!HHB", prefix)
115         certificate = wire[current : current + rdlen].unwrap()
116         return cls(rdclass, rdtype, certificate_type, key_tag, algorithm,
117                    certificate)
118
119     from_wire = classmethod(from_wire)
120
121     def _cmp(self, other):
122         f = cStringIO.StringIO()
123         self.to_wire(f)
124         wire1 = f.getvalue()
125         f.seek(0)
126         f.truncate()
127         other.to_wire(f)
128         wire2 = f.getvalue()
129         f.close()
130
131         return cmp(wire1, wire2)