From 7d28e12612ec08e80cf1351ea523bf4a9adfc255 Mon Sep 17 00:00:00 2001 From: Felipe Volpone Date: Thu, 11 May 2017 10:20:02 -0300 Subject: [PATCH] Fixing the cert-request comparing whole email address case-sensitively. Now, the cert-request command compares the domain part of the email case-insensitively. https://pagure.io/freeipa/issue/5919 Reviewed-By: Fraser Tweedale Reviewed-By: Alexander Bokovoy --- ipaserver/plugins/cert.py | 27 ++++++++++++++++++++++++--- ipatests/test_xmlrpc/test_cert_plugin.py | 23 +++++++++++++++++++++++ 2 files changed, 47 insertions(+), 3 deletions(-) diff --git a/ipaserver/plugins/cert.py b/ipaserver/plugins/cert.py index c1d389217265f44e646ac27d9adc8d5524c74ce7..501fc9015468c864215cfb604de37cdf6d805e52 100644 --- a/ipaserver/plugins/cert.py +++ b/ipaserver/plugins/cert.py @@ -710,7 +710,9 @@ class cert_request(Create, BaseCertMethod, VirtualCommand): # fail if any email addr from DN does not appear in ldap entry email_addrs = csr_obj.subject.get_attributes_for_oid( cryptography.x509.oid.NameOID.EMAIL_ADDRESS) - if len(set(email_addrs) - set(principal_obj.get('mail', []))) > 0: + csr_emails = [attr.value for attr in email_addrs] + if not _emails_are_valid(csr_emails, + principal_obj.get('mail', [])): raise errors.ValidationError( name='csr', error=_( @@ -796,8 +798,8 @@ class cert_request(Create, BaseCertMethod, VirtualCommand): "match requested principal") % gn.name) elif isinstance(gn, cryptography.x509.general_name.RFC822Name): if principal_type == USER: - if principal_obj and gn.value not in principal_obj.get( - 'mail', []): + if not _emails_are_valid([gn.value], + principal_obj.get('mail', [])): raise errors.ValidationError( name='csr', error=_( @@ -865,6 +867,25 @@ class cert_request(Create, BaseCertMethod, VirtualCommand): ) +def _emails_are_valid(csr_emails, principal_emails): + """ + Checks if any email address from certificate request does not + appear in ldap entry, comparing the domain part case-insensitively. + """ + + def lower_domain(email): + email_splitted = email.split('@', 1) + if len(email_splitted) > 1: + email_splitted[1] = email_splitted[1].lower() + + return '@'.join(email_splitted) + + principal_emails_lower = set(map(lower_domain, principal_emails)) + csr_emails_lower = set(map(lower_domain, csr_emails)) + + return csr_emails_lower.issubset(principal_emails_lower) + + def principal_to_principal_type(principal): if principal.is_user: return USER diff --git a/ipatests/test_xmlrpc/test_cert_plugin.py b/ipatests/test_xmlrpc/test_cert_plugin.py index 0b8277b8a6d67777db2eb328116ed0a761914663..dc9e8cba7b40e7b655ea7c0e3bed7706ac78ed1a 100644 --- a/ipatests/test_xmlrpc/test_cert_plugin.py +++ b/ipatests/test_xmlrpc/test_cert_plugin.py @@ -253,6 +253,29 @@ class test_cert(BaseCert): res = api.Command['service_find'](self.service_princ) assert res['count'] == 0 + def test_00011_emails_are_valid(self): + """ + Verify the different scenarios when checking if any email addr + from DN or SAN extension does not appear in ldap entry. + """ + + from ipaserver.plugins.cert import _emails_are_valid + email_addrs = [u'any@EmAiL.CoM'] + result = _emails_are_valid(email_addrs, [u'any@email.com']) + assert True == result, result + + email_addrs = [u'any@EmAiL.CoM'] + result = _emails_are_valid(email_addrs, [u'any@email.com', + u'another@email.com']) + assert True == result, result + + result = _emails_are_valid([], [u'any@email.com']) + assert True == result, result + + email_addrs = [u'invalidEmailAddress'] + result = _emails_are_valid(email_addrs, []) + assert False == result, result + @pytest.mark.tier1 class test_cert_find(XMLRPC_test): -- 2.13.6