RHEL Engineering is moving the tracking of its product development work on RHEL 6 through RHEL 9 to Red Hat Jira (issues.redhat.com). If you're a Red Hat customer, please continue to file support cases via the Red Hat customer portal. If you're not, please head to the "RHEL project" in Red Hat Jira and file new tickets here. Individual Bugzilla bugs in the statuses "NEW", "ASSIGNED", and "POST" are being migrated throughout September 2023. Bugs of Red Hat partners with an assigned Engineering Partner Manager (EPM) are migrated in late September as per pre-agreed dates. Bugs against components "kernel", "kernel-rt", and "kpatch" are only migrated if still in "NEW" or "ASSIGNED". If you cannot log in to RH Jira, please consult article #7032570. That failing, please send an e-mail to the RH Jira admins at rh-issues@redhat.com to troubleshoot your issue as a user management inquiry. The email creates a ServiceNow ticket with Red Hat. Individual Bugzilla bugs that are migrated will be moved to status "CLOSED", resolution "MIGRATED", and set with "MigratedToJIRA" in "Keywords". The link to the successor Jira issue will be found under "Links", have a little "two-footprint" icon next to it, and direct you to the "RHEL project" in Red Hat Jira (issue links are of type "https://issues.redhat.com/browse/RHEL-XXXX", where "X" is a digit). This same link will be available in a blue banner at the top of the page informing you that that bug has been migrated.
Bug 2018488 - x509 allowed Distinguished Names should not be order sensitive
Summary: x509 allowed Distinguished Names should not be order sensitive
Keywords:
Status: CLOSED ERRATA
Alias: None
Product: Red Hat Enterprise Linux 9
Classification: Red Hat
Component: libvirt
Version: 9.0
Hardware: Unspecified
OS: Unspecified
unspecified
unspecified
Target Milestone: rc
: ---
Assignee: Martin Kletzander
QA Contact: Lili Zhu
URL:
Whiteboard:
Depends On:
Blocks:
TreeView+ depends on / blocked
 
Reported: 2021-10-29 13:36 UTC by Lili Zhu
Modified: 2022-05-17 13:05 UTC (History)
7 users (show)

Fixed In Version: libvirt-7.10.0-1.el9
Doc Type: If docs needed, set a value
Doc Text:
Clone Of:
Environment:
Last Closed: 2022-05-17 12:45:49 UTC
Type: Bug
Target Upstream Version: 7.10.0
Embargoed:


Attachments (Terms of Use)


Links
System ID Private Priority Status Summary Last Updated
Red Hat Issue Tracker RHELPLAN-101089 0 None None None 2021-10-29 13:37:57 UTC
Red Hat Product Errata RHBA-2022:2390 0 None None None 2022-05-17 12:46:14 UTC

Description Lili Zhu 2021-10-29 13:36:01 UTC
Description of problem:
x509 allowed Distinguished Names should not be order sensitive

Version-Release number of selected component (if applicable):
libvirt-7.8.0-1.el9.x86_64


How reproducible:
100%

Steps to Reproduce:
1. setup the tls env

2. connect to the libvirtd daemon via tls transport

# virsh -c qemu+tls://$hostname/system
Welcome to virsh, the virtualization interactive terminal.

Type:  'help' for help with commands
       'quit' to quit

virsh # exit


3. check the subject from clientcert.pem

certtool -i --infile clientcert.pem
....
 Subject: C=GB,ST=London,L=London,O=Red Hat,CN=$hostname
....

4. config the config file
# cat /etc/libvirt/libvirtd.conf
tls_allowed_dn_list = ["C=GB,ST=London,L=London,O=Red Hat,CN=*"]

5. connect to the libvirtd daemon via tls transport
# virsh -c qemu+tls://$hostname/system
error: failed to connect to the hypervisor
error: Unable to read TLS confirmation: Input/output error



Expected results:
Can connect to libvirtd using the dn indicated by 'certtool -i --infile clientcert.pem'

Additional info:
6. check the log file
# cat /var/log/libvirt/libvirtd.log
....
2021-09-20 07:07:13.182+0000: 22001: debug : virNetTLSContextValidCertificate:1060 : Peer DN is CN=$hostname,O=Red Hat,L=London,ST=London,C=GB
2021-09-20 07:07:13.182+0000: 22001: debug : virNetTLSContextCheckCertDNACL:368 : Failed ACL check for client DN 'CN=$hostname,O=Red Hat,L=London,ST=London,C=GB'
2021-09-20 07:07:13.182+0000: 22001: error : virNetTLSContextCheckCertDNACL:371 : Client's Distinguished Name is not on the list of allowed clients (tls_allowed_dn_list).  Use 'certtool -i --infile clientcert.pem' to view the Distinguished Name field in the client certificate, or run this daemon with --verbose option.
2021-09-20 07:07:13.182+0000: 22001: info : virNetTLSContextValidCertificate:1100 : RPC_TLS_CONTEXT_SESSION_DENY: ctxt=0x555f027f3010 sess=0x7f80e8010e10 dname=CN=$hostname,O=Red Hat,L=London,ST=London,C=GB
2021-09-20 07:07:13.182+0000: 22001: warning : virNetTLSContextCheckCertificate:1122 : Certificate check failed Client's Distinguished Name is not on the list of allowed clients (tls_allowed_dn_list).  Use 'certtool -i --infile clientcert.pem' to view the Distinguished Name field in the client certificate, or run this daemon with --verbose option.
2021-09-20 07:07:13.182+0000: 22001: error : virNetTLSContextCheckCertificate:1124 : authentication failed: Failed to verify peer's certificate

7. If config the config file as following:
# cat /etc/libvirt/libvirtd.conf
tls_allowed_dn_list = ["CN=*,O=Red Hat,L=London,ST=London,C=GB"]

Then connection is successful.

Comment 1 Martin Kletzander 2021-11-08 16:29:50 UTC
I tried reproducing your issue and even though I managed to do that, I am getting a different output.

When asking certtool about the subject, I get this:

  CN=rhel9,O=Libvirt Project,L=London,ST=London,C=GB

And when libvirt complains about the DN being wrong, I get this:

  C=GB,ST=London,L=London,O=Libvirt Project,CN=rhel9

Which is switched around compared to your report.

I have not dug much more deep, but gnutls_x509_crt_get_dn(3), which we are using, is saying:

  The name will be in the form "C=xxxx,O=yyyy,CN=zzzz" as described in RFC4514.

And we will have to rely on that, unless we want to do some extra matching, which could be potentially dangerous.

My guess is that gnutls maybe have switched the output at some point.  What version of gnutls are you using?  Mine are:

  # rpm -qa 'gnutls*'
  gnutls-3.7.2-4.el9.x86_64
  gnutls-dane-3.7.2-4.el9.x86_64
  gnutls-utils-3.7.2-4.el9.x86_64

I have a documentation fix for this issue (explaining a bit more in the configuration file), but I guess this might be worth asking them, or even creating a bug there (unless you have a version with a bug which is fixed in mine).  Anyway I do not see why certtool would output that information with the fields in different order anyway.

Comment 2 Martin Kletzander 2021-11-09 13:26:44 UTC
Few more things:

I can confirm certtool changed how it prints the Subject.  In RHEL8 (gnutls*-3.6.14-7.el8_3) it used to print this:

  C=GB,ST=London,L=London,O=Libvirt Project,CN=rhel9

which works with what libvirt expects because it is what gnutls_x509_crt_get_dn(3) returns.

Unfortunately RFC4514 does explicitly say that the order of the fields can be in any order.  So it is not an error in certtool, just an issue with libvirt depending on the consistency of its output.

This cannot be fixed correctly with the current way of configuring this and in my humble opinion this configuration knob did not ever make sense.  I will raise the question upstream and update this bug.

Comment 3 Daniel Berrangé 2021-11-09 18:54:58 UTC
From my testing it is more complicated, because it depends both on which version of certtool created the cert and which version is querying the cert.

I created 3 certs on rhel7, rhel8 and rhel9 using certool, then queried them using gnutls_x509_crt_get_dn

  created-rhel7:  CN=acme-client1,O=ACME,L=London,ST=London,C=GB
  created-rhel8:  CN=acme-client1,O=ACME,L=London,ST=London,C=GB
  created-rhel9:  C=GB,ST=London,L=London,O=ACME,CN=acme-client1

I also queried using $ openssl x509 -in usercert.pem -noout -subject | sed 's/subject= //'

  created-rhel7:  subject=CN = acme-client1, O = ACME, L = London, ST = London, C = GB
  created-rhel8:  subject=CN = acme-client1, O = ACME, L = London, ST = London, C = GB
  created-rhel9:  subject=C = GB, ST = London, L = London, O = ACME, CN = acme-client1


I then also queried them using 'certtool -i --infile PEMFILE | grep Subject:', on each RHEL version

gnutls certtool rhel7

  created-rhel7:  Subject: CN=acme-client1,O=ACME,L=London,ST=London,C=GB
  created-rhel8:  Subject: CN=acme-client1,O=ACME,L=London,ST=London,C=GB
  created-rhel9:  Subject: C=GB,ST=London,L=London,O=ACME,CN=acme-client1

gnutls certtool rhel8

  created-rhel7:  Subject: C=GB,ST=London,L=London,O=ACME,CN=acme-client1
  created-rhel8:  Subject: C=GB,ST=London,L=London,O=ACME,CN=acme-client1
  created-rhel9:  Subject: CN=acme-client1,O=ACME,L=London,ST=London,C=GB

gnutls certtool rhel9

  created-rhel7:  Subject: C=GB,ST=London,L=London,O=ACME,CN=acme-client1
  created-rhel8:  Subject: C=GB,ST=London,L=London,O=ACME,CN=acme-client1
  created-rhel9:  Subject: CN=acme-client1,O=ACME,L=London,ST=London,C=GB


What we can see from this:

 - In RHEL-8 gnutls certtool reversed the order in which it reports distinguished name fields (see https://bugzilla.redhat.com/show_bug.cgi?id=1394318)
 - In RHEL-9 gnutls certtool reversed the order in which it encoded distinguished name fields in the certificate


The gnutls_x509_crt_get_dn() API libvirt uses always matches the order of the fields in the certificate

This is good because it means from a functional POV, libvirt behaviour has not changed in RHEL-9, we are still honouring the order in the certificate when doing wildcard matches.


In terms of certificates people use in production deployments, there has never been any guarantee about what order fields will appear in. That is entirely dependant on what tools people use to create certificates for use with libvirt. They might be using certtool, or openssl, or FreeIPA, or something else again.

What matters is that the "tls_allowed_dn_list" setting applies to the actual order in the certificate and that is still working correctly and has not changed in behaviour.

The main bugs here are

 - Our documentation tells people to look at the 'certtool' output to determine the string they need to use for the match.

   This is wrong. We need to tell people to use the *reverse* of what certtool reports. 

 - QE was creating a certificate on RHEL-9 with certtool, and then using the tls_allowed_dn_list setting their test plan had used in RHEL-8. 

   This doesn't take into account the fact that certtool has created the cert in a different way. The test plan needs updating for this. A certificate created on RHEL-8 and used on RHEL-9 would still have worked, but a cert created on RHEL-9 needs a reversed setting

Comment 4 Martin Kletzander 2021-11-12 12:06:00 UTC
Fixed upstream by not recommending certtool, but rather our own helper virt-pki-query-dn.

Comment 5 Martin Kletzander 2021-11-12 12:08:12 UTC
Fixed upstream with v7.9.0-124-g971504354405, v7.9.0-125-g5d972ad910c1, v7.9.0-126-g831f5415826b:
commit 971504354405de286a3bb1967763ae3fc02b8dc6
Author: Martin Kletzander <mkletzan>
Date:   Thu Nov 11 15:35:38 2021 +0100

    tools: Add virt-pki-query-dn binary
    
commit 5d972ad910c1ffdf11fec7482db805329e8a01fd
Author: Martin Kletzander <mkletzan>
Date:   Thu Nov 11 15:56:05 2021 +0100

    Add suggestions for virt-pki-query-dn usage
    
commit 831f5415826bb0792c28d50544e6970df4443d66
Author: Martin Kletzander <mkletzan>
Date:   Thu Nov 11 15:59:48 2021 +0100

    news: Mention the addition of virt-pki-query-dn binary

Comment 7 Lili Zhu 2021-12-10 13:33:36 UTC
Test with libvirt-7.10.0-1.el9.x86_64:

Steps to Reproduce:
1. setup the tls env

2. connect to the libvirtd daemon via tls transport

# virsh -c qemu+tls://$hostname/system
Welcome to virsh, the virtualization interactive terminal.

Type:  'help' for help with commands
       'quit' to quit

virsh # exit


3. check the subject from clientcert.pem
# virt-pki-query-dn clientcert.pem 
CN=$client_hostname,O=Red Hat,L=London,ST=London,C=GB

4. config the config file
# cat /etc/libvirt/libvirtd.conf
tls_allowed_dn_list = ["CN=$client_hostname,O=Red Hat,L=London,ST=London,C=GB"]

5. connect to the libvirtd daemon via tls transport
# virsh -c qemu+tls://$hostname/system
Welcome to virsh, the virtualization interactive terminal.

Type:  'help' for help with commands
       'quit' to quit

virsh #

Comment 10 Lili Zhu 2021-12-26 09:50:42 UTC
Verify this bug with:
libvirt-7.10.0-1.el9.x86_64

1. setup the tls env

2. connect to the libvirtd daemon via tls transport

# virsh -c qemu+tls://$hostname/system
Welcome to virsh, the virtualization interactive terminal.

Type:  'help' for help with commands
       'quit' to quit

virsh # exit


3. check the subject from clientcert.pem
# virt-pki-query-dn clientcert.pem
C=GB,ST=London,L=London,O=Red Hat,CN=$client_hostname

4. config the config file
# cat /etc/libvirt/libvirtd.conf
tls_allowed_dn_list = ["C=GB,ST=London,L=London,O=Red Hat,CN=$client_hostname"]

5. connect to the libvirtd daemon via tls transport
# virsh -c qemu+tls://$server_hostname/system
Welcome to virsh, the virtualization interactive terminal.

Type:  'help' for help with commands
       'quit' to quit

virsh #

6. change the config file
# cat /etc/libvirt/libvirtd.conf
tls_allowed_dn_list = ["C=GB,ST=London,L=London,O=Red Hat,CN=$wrong_client_hostname"]

7. # virsh -c qemu+tls://$server_hostname/system
error: failed to connect to the hypervisor
error: Unable to read TLS confirmation: Input/output error

8. check the log
2021-12-26 09:39:26.803+0000: 2773553: debug : virNetTLSContextValidCertificate:1064 : Peer DN is C=GB,ST=London,L=London,O=Red Hat,CN=$client_hostname
2021-12-26 09:39:26.803+0000: 2773553: debug : virNetTLSContextCheckCertDNACL:368 : Failed ACL check for client DN 'C=GB,ST=London,L=London,O=Red Hat,CN=$client_hostname'
2021-12-26 09:39:26.803+0000: 2773553: error : virNetTLSContextCheckCertDNACL:371 : Client's Distinguished Name is not on the list of allowed clients (tls_allowed_dn_list).  Use 'virt-pki-query-dn clientcert.pem' to view the Distinguished Name field in the client certificate, or run this daemon with --verbose option.
2021-12-26 09:39:26.803+0000: 2773553: info : virNetTLSContextValidCertificate:1104 : RPC_TLS_CONTEXT_SESSION_DENY: ctxt=0x5563e42a2830 sess=0x7f6438010db0 dname=C=GB,ST=London,L=London,O=Red Hat,CN=$client_hostname
2021-12-26 09:39:26.803+0000: 2773553: warning : virNetTLSContextCheckCertificate:1126 : Certificate check failed Client's Distinguished Name is not on the list of allowed clients (tls_allowed_dn_list).  Use 'virt-pki-query-dn clientcert.pem' to view the Distinguished Name field in the client certificate, or run this daemon with --verbose option.

The method of how to get the correct DN is also reported.

As the test result matches with the expected one, mark the bug as verified.

Comment 12 errata-xmlrpc 2022-05-17 12:45:49 UTC
Since the problem described in this bug report should be
resolved in a recent advisory, it has been closed with a
resolution of ERRATA.

For information on the advisory (new packages: libvirt), and where to find the updated
files, follow the link below.

If the solution does not work for you, open a new bug report.

https://access.redhat.com/errata/RHBA-2022:2390


Note You need to log in before you can comment on or make changes to this bug.