From 5f0e13ce9c3d1ead02de61a148de973fc6787b96 Mon Sep 17 00:00:00 2001 From: Fraser Tweedale Date: Jun 01 2017 07:28:36 +0000 Subject: ca-add: validate Subject DN name attributes If the Subject DN is syntactically valid but contains unrecognised name attributes, FreeIPA accepts it but Dogtag rejects it, returning status 400 and causing the framework to raise RemoteRetrieveError. Update the ca-add command to perform some additional validation on the user-supplied Subject DN, making sure that we recognise all the attributes. Fixes: https://pagure.io/freeipa/issue/6987 Reviewed-By: Stanislav Laznicka Reviewed-By: Felipe Volpone --- diff --git a/ipapython/dn.py b/ipapython/dn.py index a54629e..9499096 100644 --- a/ipapython/dn.py +++ b/ipapython/dn.py @@ -1131,7 +1131,7 @@ class DN(object): elif isinstance(value, cryptography.x509.name.Name): rdns = list(reversed([ [get_ava( - _ATTR_NAME_BY_OID.get(ava.oid, ava.oid.dotted_string), + ATTR_NAME_BY_OID.get(ava.oid, ava.oid.dotted_string), ava.value)] for ava in value ])) @@ -1426,7 +1426,7 @@ class DN(object): return i -_ATTR_NAME_BY_OID = { +ATTR_NAME_BY_OID = { cryptography.x509.oid.NameOID.COMMON_NAME: 'CN', cryptography.x509.oid.NameOID.COUNTRY_NAME: 'C', cryptography.x509.oid.NameOID.LOCALITY_NAME: 'L', diff --git a/ipaserver/plugins/ca.py b/ipaserver/plugins/ca.py index 9bb163d..8db6ec5 100644 --- a/ipaserver/plugins/ca.py +++ b/ipaserver/plugins/ca.py @@ -4,9 +4,12 @@ import base64 +import six + from ipalib import api, errors, output, Bytes, DNParam, Flag, Str from ipalib.constants import IPA_CA_CN from ipalib.plugable import Registry +from ipapython.dn import ATTR_NAME_BY_OID from ipaserver.plugins.baseldap import ( LDAPObject, LDAPSearch, LDAPCreate, LDAPDelete, LDAPUpdate, LDAPRetrieve, LDAPQuery, pkey_to_value) @@ -236,6 +239,24 @@ class ca_add(LDAPCreate): raise errors.ACIError( info=_("Insufficient 'add' privilege for entry '%s'.") % dn) + # check that DN only includes standard naming attributes + dn_attrs = { + ava.attr.lower() + for rdn in options['ipacasubjectdn'] + for ava in rdn + } + x509_attrs = { + attr.lower() + for attr in six.viewvalues(ATTR_NAME_BY_OID) + } + unknown_attrs = dn_attrs - x509_attrs + if len(unknown_attrs) > 0: + raise errors.ValidationError( + name=_("Subject DN"), + error=_("Unrecognized attributes: %(attrs)s") + % dict(attrs=", ".join(unknown_attrs)) + ) + # check for name collision before creating CA in Dogtag try: api.Object.ca.get_dn_if_exists(keys[-1]) diff --git a/ipatests/test_xmlrpc/test_ca_plugin.py b/ipatests/test_xmlrpc/test_ca_plugin.py index 1e0e52f..28cd94a 100644 --- a/ipatests/test_xmlrpc/test_ca_plugin.py +++ b/ipatests/test_xmlrpc/test_ca_plugin.py @@ -63,6 +63,16 @@ def subject_conflict_subca(request): return tracker +@pytest.fixture(scope='class') +def unrecognised_subject_dn_attrs_subca(request): + name = u'crud-subca-3' + subject = u'CN=crud subca test,DN=example.com,O=crud testing inc' + tracker = CATracker(name, subject) + + # Should not get created, no need to delete + return tracker + + @pytest.mark.tier0 class TestDefaultCA(XMLRPC_test): def test_default_ca_present(self, default_ca): @@ -173,3 +183,8 @@ class TestCAbasicCRUD(XMLRPC_test): with pytest.raises(errors.DuplicateEntry): subject_conflict_subca.create() + + def test_create_subca_with_unrecognised_subject_dn_attrs( + self, unrecognised_subject_dn_attrs_subca): + with pytest.raises(errors.ValidationError): + unrecognised_subject_dn_attrs_subca.create()