• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# This file is dual licensed under the terms of the Apache License, Version
2# 2.0, and the BSD License. See the LICENSE file in the root of this repository
3# for complete details.
4
5from __future__ import absolute_import, division, print_function
6
7import abc
8import ipaddress
9from email.utils import parseaddr
10
11import six
12
13from cryptography import utils
14from cryptography.x509.name import Name
15from cryptography.x509.oid import ObjectIdentifier
16
17
18_GENERAL_NAMES = {
19    0: "otherName",
20    1: "rfc822Name",
21    2: "dNSName",
22    3: "x400Address",
23    4: "directoryName",
24    5: "ediPartyName",
25    6: "uniformResourceIdentifier",
26    7: "iPAddress",
27    8: "registeredID",
28}
29
30
31class UnsupportedGeneralNameType(Exception):
32    def __init__(self, msg, type):
33        super(UnsupportedGeneralNameType, self).__init__(msg)
34        self.type = type
35
36
37@six.add_metaclass(abc.ABCMeta)
38class GeneralName(object):
39    @abc.abstractproperty
40    def value(self):
41        """
42        Return the value of the object
43        """
44
45
46@utils.register_interface(GeneralName)
47class RFC822Name(object):
48    def __init__(self, value):
49        if isinstance(value, six.text_type):
50            try:
51                value.encode("ascii")
52            except UnicodeEncodeError:
53                raise ValueError(
54                    "RFC822Name values should be passed as an A-label string. "
55                    "This means unicode characters should be encoded via "
56                    "a library like idna."
57                )
58        else:
59            raise TypeError("value must be string")
60
61        name, address = parseaddr(value)
62        if name or not address:
63            # parseaddr has found a name (e.g. Name <email>) or the entire
64            # value is an empty string.
65            raise ValueError("Invalid rfc822name value")
66
67        self._value = value
68
69    value = utils.read_only_property("_value")
70
71    @classmethod
72    def _init_without_validation(cls, value):
73        instance = cls.__new__(cls)
74        instance._value = value
75        return instance
76
77    def __repr__(self):
78        return "<RFC822Name(value={0!r})>".format(self.value)
79
80    def __eq__(self, other):
81        if not isinstance(other, RFC822Name):
82            return NotImplemented
83
84        return self.value == other.value
85
86    def __ne__(self, other):
87        return not self == other
88
89    def __hash__(self):
90        return hash(self.value)
91
92
93@utils.register_interface(GeneralName)
94class DNSName(object):
95    def __init__(self, value):
96        if isinstance(value, six.text_type):
97            try:
98                value.encode("ascii")
99            except UnicodeEncodeError:
100                raise ValueError(
101                    "DNSName values should be passed as an A-label string. "
102                    "This means unicode characters should be encoded via "
103                    "a library like idna."
104                )
105        else:
106            raise TypeError("value must be string")
107
108        self._value = value
109
110    value = utils.read_only_property("_value")
111
112    @classmethod
113    def _init_without_validation(cls, value):
114        instance = cls.__new__(cls)
115        instance._value = value
116        return instance
117
118    def __repr__(self):
119        return "<DNSName(value={0!r})>".format(self.value)
120
121    def __eq__(self, other):
122        if not isinstance(other, DNSName):
123            return NotImplemented
124
125        return self.value == other.value
126
127    def __ne__(self, other):
128        return not self == other
129
130    def __hash__(self):
131        return hash(self.value)
132
133
134@utils.register_interface(GeneralName)
135class UniformResourceIdentifier(object):
136    def __init__(self, value):
137        if isinstance(value, six.text_type):
138            try:
139                value.encode("ascii")
140            except UnicodeEncodeError:
141                raise ValueError(
142                    "URI values should be passed as an A-label string. "
143                    "This means unicode characters should be encoded via "
144                    "a library like idna."
145                )
146        else:
147            raise TypeError("value must be string")
148
149        self._value = value
150
151    value = utils.read_only_property("_value")
152
153    @classmethod
154    def _init_without_validation(cls, value):
155        instance = cls.__new__(cls)
156        instance._value = value
157        return instance
158
159    def __repr__(self):
160        return "<UniformResourceIdentifier(value={0!r})>".format(self.value)
161
162    def __eq__(self, other):
163        if not isinstance(other, UniformResourceIdentifier):
164            return NotImplemented
165
166        return self.value == other.value
167
168    def __ne__(self, other):
169        return not self == other
170
171    def __hash__(self):
172        return hash(self.value)
173
174
175@utils.register_interface(GeneralName)
176class DirectoryName(object):
177    def __init__(self, value):
178        if not isinstance(value, Name):
179            raise TypeError("value must be a Name")
180
181        self._value = value
182
183    value = utils.read_only_property("_value")
184
185    def __repr__(self):
186        return "<DirectoryName(value={})>".format(self.value)
187
188    def __eq__(self, other):
189        if not isinstance(other, DirectoryName):
190            return NotImplemented
191
192        return self.value == other.value
193
194    def __ne__(self, other):
195        return not self == other
196
197    def __hash__(self):
198        return hash(self.value)
199
200
201@utils.register_interface(GeneralName)
202class RegisteredID(object):
203    def __init__(self, value):
204        if not isinstance(value, ObjectIdentifier):
205            raise TypeError("value must be an ObjectIdentifier")
206
207        self._value = value
208
209    value = utils.read_only_property("_value")
210
211    def __repr__(self):
212        return "<RegisteredID(value={})>".format(self.value)
213
214    def __eq__(self, other):
215        if not isinstance(other, RegisteredID):
216            return NotImplemented
217
218        return self.value == other.value
219
220    def __ne__(self, other):
221        return not self == other
222
223    def __hash__(self):
224        return hash(self.value)
225
226
227@utils.register_interface(GeneralName)
228class IPAddress(object):
229    def __init__(self, value):
230        if not isinstance(
231            value,
232            (
233                ipaddress.IPv4Address,
234                ipaddress.IPv6Address,
235                ipaddress.IPv4Network,
236                ipaddress.IPv6Network,
237            ),
238        ):
239            raise TypeError(
240                "value must be an instance of ipaddress.IPv4Address, "
241                "ipaddress.IPv6Address, ipaddress.IPv4Network, or "
242                "ipaddress.IPv6Network"
243            )
244
245        self._value = value
246
247    value = utils.read_only_property("_value")
248
249    def __repr__(self):
250        return "<IPAddress(value={})>".format(self.value)
251
252    def __eq__(self, other):
253        if not isinstance(other, IPAddress):
254            return NotImplemented
255
256        return self.value == other.value
257
258    def __ne__(self, other):
259        return not self == other
260
261    def __hash__(self):
262        return hash(self.value)
263
264
265@utils.register_interface(GeneralName)
266class OtherName(object):
267    def __init__(self, type_id, value):
268        if not isinstance(type_id, ObjectIdentifier):
269            raise TypeError("type_id must be an ObjectIdentifier")
270        if not isinstance(value, bytes):
271            raise TypeError("value must be a binary string")
272
273        self._type_id = type_id
274        self._value = value
275
276    type_id = utils.read_only_property("_type_id")
277    value = utils.read_only_property("_value")
278
279    def __repr__(self):
280        return "<OtherName(type_id={}, value={!r})>".format(
281            self.type_id, self.value
282        )
283
284    def __eq__(self, other):
285        if not isinstance(other, OtherName):
286            return NotImplemented
287
288        return self.type_id == other.type_id and self.value == other.value
289
290    def __ne__(self, other):
291        return not self == other
292
293    def __hash__(self):
294        return hash((self.type_id, self.value))
295