Improve handling of IDNA/Unicode domains (#436)

* Prepare IDNA/Unicode conversion code. Use to normalize input.

* Use IDNA library first (IDNA2008) and Python's IDNA2003 implementation as a fallback.

* Make sure idna is installed.

* Add changelog fragment.

* 'punycode' → 'idna'.

* Add name_encoding options and tests.

* Avoid invalid character for IDNA2008.

* Linting.

* Forgot to upate value.

* Work around cryptography bug. Fix port handling for URIs.

* Forgot other place sensitive to cryptography bug.

* Forgot one. (Will likely still fail.)

* Decode IDNA in _compress_entry() to avoid comparison screw-ups.

* Work around Python 3.5 problem in Ansible 2.9's default test container.

* Update changelog fragment.

* Fix error, add tests.

* Python 2 compatibility.

* Update requirements.
This commit is contained in:
Felix Fontein
2022-05-09 19:57:14 +02:00
committed by GitHub
parent 90efcc1ca7
commit 4cf951596f
20 changed files with 479 additions and 31 deletions

View File

@@ -20,6 +20,7 @@ from ansible_collections.community.crypto.plugins.module_utils.crypto.basic impo
from ansible_collections.community.crypto.plugins.module_utils.crypto.cryptography_support import (
cryptography_get_name,
_adjust_idn,
_parse_dn_component,
_parse_dn,
)
@@ -27,6 +28,67 @@ from ansible_collections.community.crypto.plugins.module_utils.crypto.cryptograp
from ansible_collections.community.crypto.plugins.module_utils.version import LooseVersion
@pytest.mark.parametrize('unicode, idna, cycled_unicode', [
(u'..', u'..', None),
(u'foo.com', u'foo.com', None),
(u'.foo.com.', u'.foo.com.', None),
(u'*.foo.com', u'*.foo.com', None),
(u'straße', u'xn--strae-oqa', None),
(u'ffóò.ḃâŗ.çøṁ', u'xn--ff-3jad.xn--2ca8uh37e.xn--7ca8a981n', u'ffóò.ḃâŗ.çøṁ'),
(u'*.☺.', u'*.xn--74h.', None),
])
def test_adjust_idn(unicode, idna, cycled_unicode):
if cycled_unicode is None:
cycled_unicode = unicode
result = _adjust_idn(unicode, 'ignore')
print(result, unicode)
assert result == unicode
result = _adjust_idn(idna, 'ignore')
print(result, idna)
assert result == idna
result = _adjust_idn(unicode, 'unicode')
print(result, unicode)
assert result == unicode
result = _adjust_idn(idna, 'unicode')
print(result, cycled_unicode)
assert result == cycled_unicode
result = _adjust_idn(unicode, 'idna')
print(result, idna)
assert result == idna
result = _adjust_idn(idna, 'idna')
print(result, idna)
assert result == idna
@pytest.mark.parametrize('value, idn_rewrite, message', [
(u'bar', 'foo', re.escape(u'Invalid value for idn_rewrite: "foo"')),
])
def test_adjust_idn_fail_valueerror(value, idn_rewrite, message):
with pytest.raises(ValueError, match=message):
result = _adjust_idn(value, idn_rewrite)
@pytest.mark.parametrize('value, idn_rewrite, message', [
(
u'xn--a',
'unicode',
u'''^Error while transforming part u?"xn\\-\\-a" of IDNA DNS name u?"xn\\-\\-a" to Unicode\\.'''
u''' IDNA2008 transformation resulted in "Codepoint U\\+0080 at position 1 of u?'\\\\x80' not allowed",'''
u''' IDNA2003 transformation resulted in "(decoding with 'idna' codec failed'''
u''' \\(UnicodeError: )?Invalid character u?'\\\\x80'\\)?"\\.$'''
),
])
def test_adjust_idn_fail_user_error(value, idn_rewrite, message):
with pytest.raises(OpenSSLObjectError, match=message):
result = _adjust_idn(value, idn_rewrite)
def test_cryptography_get_name_invalid_prefix():
with pytest.raises(OpenSSLObjectError, match="^Cannot parse Subject Alternative Name"):
cryptography_get_name('fake:value')