Courier doesn't send trust chain

Hi,

I’m trying to get my LE certificates to work with courier. CheckTLS and mail clients keep telling me, my certificates are not trusted because they don’t know the authority. Examining the trust chain via CheckTLS, there’s only LE visible.

`[000.955]
Certificate 1 of 3 in chain:
subject= /CN=mail.[mydomain].de
issuer= /C=US/O=Let’s Encrypt/CN=Let’s Encrypt Authority X1
[000.977]
Certificate 2 of 3 in chain:
subject= /CN=mail.[mydomain].de
issuer= /C=US/O=Let’s Encrypt/CN=Let’s Encrypt Authority X1
[000.999]
Certificate 3 of 3 in chain:
subject= /CN=mail.[mydomain].de
issuer= /C=US/O=Let’s Encrypt/CN=Let’s Encrypt Authority X1

Cert NOT VALIDATED: unable to get local issuer certificate`

I’ve configured courier with TLS_TRUSTCERTS=[path to the corresponding fullchain.pem file]. Is this right or do I have to do something else?

Thanks.

I'm assuming the courier you're talking about is a server? Have you read Courier's documentation?

TLS_CERTFILE=filename
The certificate to use. TLS_CERTFILE is required for SSL/TLS servers, and is optional for SSL/TLS clients. filename must not be world-readable.

TLS_TRUSTCERTS=pathname
Load trusted root certificates from pathname. pathname can be a file or a directory. If a file, the file should contain a list of trusted certificates, in PEM format. If a directory, the directory should contain the trusted certificates, in PEM format, one per file and hashed using OpenSSL's c_rehash script. TLS_TRUSTCERTS is used by SSL/TLS clients (by specifying the -domain option) and by SSL/TLS servers (TLS_VERIFYPEER is set to PEER or REQUIREPEER).

TLS_VERIFYPEER=level
Whether to verify peer's X.509 certificate. The exact meaning of this option depends upon whether couriertls is used in the client or server mode. In server mode: NONE - do not request an X.509 certificate from the client; PEER - request an optional X.509 certificate from the client, if the client returns one, the SSL/TLS connection is shut down unless the certificate is signed by a trusted certificate authority (see TLS_TRUSTCERTS); REQUIREPEER - same as PEER, except that the SSL/TLS connects is also shut down if the client does not return the optional X.509 certificate. In client mode: NONE - ignore the server's X.509 certificate; PEER - verify the server's X.509 certificate according to the -domain option, (see above).

Do you run a Courier server? If the answer is yes: do you want to verify clients by X.509 certificates? If the answer is no: can you answer the following question after reading the above: do you need to set TLS_TRUSTCERTS or TLS_CERTFILE in your configuration? :wink:

Thanks for your reply. Yes, it’s a server. And yes, I do not want to authenticate clients.

I have concatenated the certificate and the private key into one file and point to that file via TLS_CERTFILE. Do I have to concatenate the chain also with that? Or what do I have to do to tell clients the trust chain?

For some reason every single “howto” online says you should use TLS_TRUSTCERTS for the intermediate PEM file. In my humble opinion that’s bullcr*p if you read the documentation.

I would recommend concatenate fullchain.pem and privkey.pem into one file and feed thát file to TLS_CERTFILE. And see what it does.

Why does your initial CheckTLS test give three certificates by the way? And those look like they are the same?

I am not familiar with Courier configuration, but my intuition from the documentation above would be TLS_TRUSTCERTS=/path/to/chain.pem and TLS_CERTFILE=/path/to/cert.pem (or since there’s no obvious way to specific the privkey (!), maybe TLS_CERTFILE with the concatenation of cert.pem and privkey.pem, as a variant of what @Osiris suggested).

I’ve tested both setups on a fresh Courier-IMAP install and both setups work:

  1. Put everything (cert.pem, chain.pem [= the same as fullchain.pem] ánd privkey.pem) and refer to them in the config file with TLS_CERTFILE(I tested it in that order);
  2. refer to chain.pem in TLS_TRUSTCERTS. But I don’t know why but my Courier-IMAP also sends the DST Root CA X3 certificate to the client… And that’s very odd in my opinion, because that certificate is nowhere in the PEM files to be found?

Personally, I would say: TLS_TRUSTCERTS is meant for client certificate verification, so semantically speaking the best option would be to put everything in one file. Unfortunately, you have to put the private key together with the certificate, so an chain certificate extra or not doesn’t really matter…

Sorry for the late reply. I think I found a solution.

It’s not the courier certificate which is decisive, it’s QMail. And QMail is the bottleneck in my case if you want to provide certificates for multiple domains, because it does not accept multiple certificates in its .pem-file and always returns the first one, resulting in different domain names.

For anyone who wants to setup a similar configuration, this way should be successful:

  1. Create a certificate for your domains in one certificate with the letsencrypt-auto (with “certonly” and multiple -d arguments, each followed by one domain).
  2. Concatenate the certificate/private key/chain into one file and refer to it in imapd-ssl (Courier) via “TLS_CERTFILE” (multiple certificates for multiple domains might work here). Leave “TLS_TRUSTCERTS” untouched.
  3. Concatenate the certificate/private key/full chain into your QMail servercert.pem file (in my case located at /var/qmail/control).
  4. Restart courier-imapd/qmail/xinetd services.

Thanks @Osiris and @schoen for your help.