Skip to content

Commit

Permalink
Make pyOpenSSL skip DNS names which can't be idna-encoded (urllib3#1406)
Browse files Browse the repository at this point in the history
  • Loading branch information
SethMichaelLarson committed Jun 30, 2018
1 parent 8087324 commit bdd0998
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 8 deletions.
2 changes: 2 additions & 0 deletions CHANGES.rst
Expand Up @@ -4,6 +4,8 @@ Changes
dev (master)
------------

* Skip DNS names that can't be idna-decoded when using pyOpenSSL (Issue #1405).

* ... [Short description of non-trivial change.] (Issue #)


Expand Down
25 changes: 17 additions & 8 deletions urllib3/contrib/pyopenssl.py
Expand Up @@ -163,6 +163,9 @@ def _dnsname_to_stdlib(name):
from ASCII bytes. We need to idna-encode that string to get it back, and
then on Python 3 we also need to convert to unicode via UTF-8 (the stdlib
uses PyUnicode_FromStringAndSize on it, which decodes via UTF-8).
If the name cannot be idna-encoded then we return None signalling that
the name given should be skipped.
"""
def idna_encode(name):
"""
Expand All @@ -172,14 +175,19 @@ def idna_encode(name):
"""
import idna

for prefix in [u'*.', u'.']:
if name.startswith(prefix):
name = name[len(prefix):]
return prefix.encode('ascii') + idna.encode(name)
return idna.encode(name)
try:
for prefix in [u'*.', u'.']:
if name.startswith(prefix):
name = name[len(prefix):]
return prefix.encode('ascii') + idna.encode(name)
return idna.encode(name)
except idna.core.IDNAError:
return None

name = idna_encode(name)
if sys.version_info >= (3, 0):
if name is None:
return None
elif sys.version_info >= (3, 0):
name = name.decode('utf-8')
return name

Expand Down Expand Up @@ -223,9 +231,10 @@ def get_subj_alt_name(peer_cert):
# Sadly the DNS names need to be idna encoded and then, on Python 3, UTF-8
# decoded. This is pretty frustrating, but that's what the standard library
# does with certificates, and so we need to attempt to do the same.
# We also want to skip over names which cannot be idna encoded.
names = [
('DNS', _dnsname_to_stdlib(name))
for name in ext.get_values_for_type(x509.DNSName)
('DNS', name) for name in map(_dnsname_to_stdlib, ext.get_values_for_type(x509.DNSName))
if name is not None
]
names.extend(
('IP Address', str(name))
Expand Down

0 comments on commit bdd0998

Please sign in to comment.