On Tue, Nov 09, 2021 at 07:02:54PM +0000, Daniel P. Berrangé wrote:
On Tue, Nov 09, 2021 at 05:30:33PM +0100, Martin Kletzander wrote:
> This setting was unsafe for a number of reasons, so bear with me here.
>
> In the Distinguished Name (or rather the string representation of ASN.1
> RelativeDistinguishedName if you will) the individial fields (or rather each
> AttributeTypeAndValue) can be in any order as defined in RFC4514, section 2.2.
> The function we use to get the DN is gnutls_x509_crt_get_dn(3) which claims to
> return the DN as described in the aforementioned RFC.
>
> The help we are providing to the user when no DN from the list of allowed DNs
> matches an incoming TLS connection says to check the output of certtool,
> particularly `certtool -i --infile clientcert.pem`. However in the output of
> that command the order of the fields changed in some previous version exposing
> the inconsistency (see bugzilla link below for more details).
>
> This is one reason why we should not depend on the order of the fields being
> stable as the same change can happen (and maybe already happened) with the
> gnutls_x509_crt_get_dn(3) function.
gnutls_x509_crt_get_dn() hasn't changed behaviour recently.
Back in 2016 it was accidentally changed, but they quickly
fixed that mistake, and introduced a newer
gnutls_x509_crt_get_dn3() which is what certtool -i uses
and reports in the opposite order.
What changed recently is the order in which fields are
written into the created certificate by certtool.
This is fine, libvirt's tls_allowed_dn_list setting
has to be configured to match the order of the fields
in the certificates you're actually using.
The primary bug here from libvirt's POV, is that we're
incorrectly telling people to use the order reported by
"certtool -i". We need to tell them to use the *reverse*
of what certtool -i reports.
Or we could possibly add a 'tls_allowed_dn_list_revere = bool'
setting to make ordering configurable.
One other option, if the output of gnutls_x509_crt_get_dn() is
guaranteed, would be to introduce a tiny helper binary that takes a
certificate on input and outputs the DN in the format libvirt will be
checking it.