DA 1.712: vhost of domain A uses the SSL certificate file of domain B (same user), serving an expired cert while A's own ACME cert is valid

castris

Verified User
Joined
Apr 16, 2021
Messages
168
Location
Arcenillas
Hi,

DirectAdmin 1.712 (183b67368b137bca2765445f19ece9b2dfc53132), nginx_apache, Let's Encrypt via lego.

Setup
One user, two domains:
  • example.com — acme_enabled=yes, renews fine. Its own example.com.cert.combined holds a valid wildcard (*.example.com + example.com).
  • example.es — acme_enabled was NOT set. Its example.es.cert.combined held an old, manually installed certificate whose SAN was *.example.com + example.com (not .es). That certificate expired months ago.

What happened
After a successful ACME renewal of example.com (files rewritten, user's nginx.conf and httpd.conf regenerated in the same minute), the HTTPS vhost of example.com was still generated with:

Code:
ssl_certificate /usr/local/directadmin/data/users/USER/domains/example.es.cert.combined;
SSLCertificateFile /usr/local/directadmin/data/users/USER/domains/example.es.cert.combined

So example.com served the expired certificate stored under example.es (browser: NET::ERR_CERT_DATE_INVALID), even though example.com.cert.combined was valid. The vhost of example.es pointed to the same file.

No custom HTTPD/nginx config for either domain, no pointers, no custom templates involved for this user.

How it was resolved
Requesting an ACME certificate for example.es (letsencrypt.sh request example.es) replaced example.es.cert.combined with a real *.example.es certificate. On that rewrite, DA regenerated the vhost of example.com pointing to example.com.cert.combined. Both domains are fine now.

Questions
  1. How does DA choose which certificate file goes into a domain's vhost? It looks like it picked another domain's certificate because its SAN covered the hostname.
  2. Should a domain's own valid certificate always win over another domain's certificate that merely covers the same name?
  3. Should an expired certificate ever be selected when a valid one exists for that hostname?

Hosting users install certificates manually on the "wrong" domain more often than one would hope, and today this produces a silent outage that survives every successful renewal. Is this expected behaviour, and is there a setting to make each domain always use its own certificate?

Thanks.
 
How does DA choose which certificate file goes into a domain's vhost? It looks like it picked another domain's certificate because its SAN covered the hostname.
Any certificate owned by the user could be used in web server configuration. This means user can have "cross-domain" certificates but he can only affect the domains he own. Certificates are never shared between users.

Exact matching certificates are preferred, this means if user has cert A for www.example.com and cert B for *.example.com, the cert A will be preferred for the www.example.com host name.

If user has two certificates that cover the same names the order is undefined (usually the last one wins).

Should a domain's own valid certificate always win over another domain's certificate that merely covers the same name?
Current implementation does not take into consideration what domain certificate is associated with, only association with the user name is used. So all certificate files owned by a single user are considered equal.

If this really causes problems we could improve the certificate mapping logic. Our initial expectation was that it should not be too hard for the user to check his manually uploaded certificates and resolve problems if there are any.

In the long term I think manually managed certificates will be used very rarely. It will require a lot of effort maintaining them once the maximum certificate lifetime is reduced to 47 days. So even paid certificates will use ACME for auto-renewal.

Should an expired certificate ever be selected when a valid one exists for that hostname?
Yes. This allows the certificate selection to stay stable when certificates expire and makes the certificate selection logic simpler.
 
Back
Top