aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPaul Kehrer <paul.l.kehrer@gmail.com>2017-08-01 19:27:06 -0500
committerAlex Gaynor <alex.gaynor@gmail.com>2017-08-01 20:27:06 -0400
commit6c29d74cfb60ba9480f2fcef18459cc532b2f33b (patch)
treea3ae324d93b584b67171a265fa2bc74ccb3372fd /src
parent7f40239ea2a8ac276f8dbf07fd51d1ff5e98c565 (diff)
downloadcryptography-6c29d74cfb60ba9480f2fcef18459cc532b2f33b.tar.gz
cryptography-6c29d74cfb60ba9480f2fcef18459cc532b2f33b.tar.bz2
cryptography-6c29d74cfb60ba9480f2fcef18459cc532b2f33b.zip
deprecate auto-idna on UniformResourceIdentifier (#3832)
* deprecate auto-idna on UniformResourceIdentifier * fix repr test * docs * some updated language
Diffstat (limited to 'src')
-rw-r--r--src/cryptography/hazmat/backends/openssl/encode_asn1.py2
-rw-r--r--src/cryptography/x509/general_name.py73
2 files changed, 64 insertions, 11 deletions
diff --git a/src/cryptography/hazmat/backends/openssl/encode_asn1.py b/src/cryptography/hazmat/backends/openssl/encode_asn1.py
index 77d22127..78ae21a2 100644
--- a/src/cryptography/hazmat/backends/openssl/encode_asn1.py
+++ b/src/cryptography/hazmat/backends/openssl/encode_asn1.py
@@ -449,7 +449,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_URI
gn.d.uniformResourceIdentifier = asn1_str
diff --git a/src/cryptography/x509/general_name.py b/src/cryptography/x509/general_name.py
index 9ea1cff6..40525a01 100644
--- a/src/cryptography/x509/general_name.py
+++ b/src/cryptography/x509/general_name.py
@@ -173,13 +173,36 @@ class DNSName(object):
@utils.register_interface(GeneralName)
class UniformResourceIdentifier(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(
+ "UniformResourceIdentifier values should be passed as "
+ "bytes with the hostname idna encoded, not strings. "
+ "Support for passing unicode strings will be removed in a "
+ "future version.",
+ utils.DeprecatedIn21,
+ stacklevel=2,
+ )
+ else:
+ warnings.warn(
+ "UniformResourceIdentifier values should be passed as "
+ "bytes with the hostname idna encoded, 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")
+
+ self._bytes_value = value
+ def _idna_encode(self, value):
parsed = urllib_parse.urlparse(value)
- if not parsed.hostname:
- netloc = ""
- elif parsed.port:
+ if parsed.port:
netloc = (
idna.encode(parsed.hostname) +
":{0}".format(parsed.port).encode("ascii")
@@ -190,7 +213,7 @@ class UniformResourceIdentifier(object):
# Note that building a URL in this fashion means it should be
# semantically indistinguishable from the original but is not
# guaranteed to be exactly the same.
- uri = urllib_parse.urlunparse((
+ return urllib_parse.urlunparse((
parsed.scheme,
netloc,
parsed.path,
@@ -199,13 +222,43 @@ class UniformResourceIdentifier(object):
parsed.fragment
)).encode("ascii")
- self._value = value
- self._encoded = uri
+ @property
+ def value(self):
+ warnings.warn(
+ "UniformResourceIdentifier.bytes_value should be used instead of "
+ "UniformResourceIdentifier.value; it contains the name as raw "
+ "bytes, instead of as an idna-decoded unicode string. "
+ "UniformResourceIdentifier.value will be removed in a future "
+ "version.",
+ utils.DeprecatedIn21,
+ stacklevel=2
+ )
+ parsed = urllib_parse.urlparse(self.bytes_value)
+ if not parsed.hostname:
+ netloc = ""
+ elif parsed.port:
+ netloc = idna.decode(parsed.hostname) + ":{0}".format(parsed.port)
+ else:
+ netloc = idna.decode(parsed.hostname)
- value = utils.read_only_property("_value")
+ # Note that building a URL in this fashion means it should be
+ # semantically indistinguishable from the original but is not
+ # guaranteed to be exactly the same.
+ return urllib_parse.urlunparse((
+ parsed.scheme.decode('utf8'),
+ netloc,
+ parsed.path.decode('utf8'),
+ parsed.params.decode('utf8'),
+ parsed.query.decode('utf8'),
+ parsed.fragment.decode('utf8')
+ ))
+
+ bytes_value = utils.read_only_property("_bytes_value")
def __repr__(self):
- return "<UniformResourceIdentifier(value={0})>".format(self.value)
+ return "<UniformResourceIdentifier(bytes_value={0!r})>".format(
+ self.bytes_value
+ )
def __eq__(self, other):
if not isinstance(other, UniformResourceIdentifier):