aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/cryptography/hazmat/backends/openssl/encode_asn1.py2
-rw-r--r--src/cryptography/x509/general_name.py64
2 files changed, 51 insertions, 15 deletions
diff --git a/src/cryptography/hazmat/backends/openssl/encode_asn1.py b/src/cryptography/hazmat/backends/openssl/encode_asn1.py
index 78ae21a2..6d9f9567 100644
--- a/src/cryptography/hazmat/backends/openssl/encode_asn1.py
+++ b/src/cryptography/hazmat/backends/openssl/encode_asn1.py
@@ -441,7 +441,7 @@ def _encode_general_name(backend, name):
gn = backend._lib.GENERAL_NAME_new()
backend.openssl_assert(gn != backend._ffi.NULL)
asn1_str = _encode_asn1_str(
- backend, name._encoded, len(name._encoded)
+ backend, name.bytes_value, len(name.bytes_value)
)
gn.type = backend._lib.GEN_EMAIL
gn.d.rfc822Name = asn1_str
diff --git a/src/cryptography/x509/general_name.py b/src/cryptography/x509/general_name.py
index 40525a01..114b43ae 100644
--- a/src/cryptography/x509/general_name.py
+++ b/src/cryptography/x509/general_name.py
@@ -51,31 +51,67 @@ class GeneralName(object):
@utils.register_interface(GeneralName)
class RFC822Name(object):
def __init__(self, value):
- if not isinstance(value, six.text_type):
- raise TypeError("value must be a unicode string")
+ if isinstance(value, six.text_type):
+ try:
+ value = value.encode("ascii")
+ except UnicodeEncodeError:
+ value = self._idna_encode(value)
+ warnings.warn(
+ "RFC822Name values should be passed as bytes, not strings."
+ " Support for passing unicode strings will be removed in a"
+ " future version.",
+ utils.DeprecatedIn21,
+ stacklevel=2,
+ )
+ else:
+ warnings.warn(
+ "RFC822Name values should be passed as bytes, not strings."
+ " Support for passing unicode strings will be removed in a"
+ " future version.",
+ utils.DeprecatedIn21,
+ stacklevel=2,
+ )
+ elif not isinstance(value, bytes):
+ raise TypeError("value must be bytes")
- name, address = parseaddr(value)
- parts = address.split(u"@")
+ name, address = parseaddr(value.decode("ascii"))
if name or not address:
# parseaddr has found a name (e.g. Name <email>) or the entire
# value is an empty string.
raise ValueError("Invalid rfc822name value")
- elif len(parts) == 1:
+
+ self._bytes_value = value
+
+ bytes_value = utils.read_only_property("_bytes_value")
+
+ def _idna_encode(self, value):
+ _, address = parseaddr(value)
+ parts = address.split(u"@")
+ return parts[0].encode("ascii") + b"@" + idna.encode(parts[1])
+
+ @property
+ def value(self):
+ warnings.warn(
+ "RFC822Name.bytes_value should be used instead of RFC822Name.value"
+ "; it contains the name as raw bytes, instead of as an idna-"
+ "decoded unicode string. RFC822Name.value will be removed in a "
+ "future version.",
+ utils.DeprecatedIn21,
+ stacklevel=2
+ )
+ _, address = parseaddr(self.bytes_value.decode("ascii"))
+ parts = address.split(u"@")
+ if len(parts) == 1:
# Single label email name. This is valid for local delivery.
- # No IDNA encoding needed since there is no domain component.
- encoded = address.encode("ascii")
+ # No IDNA decoding needed since there is no domain component.
+ return address
else:
# A normal email of the form user@domain.com. Let's attempt to
# encode the domain component and reconstruct the address.
- encoded = parts[0].encode("ascii") + b"@" + idna.encode(parts[1])
-
- self._value = value
- self._encoded = encoded
-
- value = utils.read_only_property("_value")
+ return parts[0] + u"@" + idna.decode(parts[1])
def __repr__(self):
- return "<RFC822Name(value={0})>".format(self.value)
+ return "<RFC822Name(bytes_value={0!r})>".format(self.bytes_value)
def __eq__(self, other):
if not isinstance(other, RFC822Name):