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