Bug 1565341

Summary: Use SSL_CTX_use_certificate_chain_file() rather SSL_CTX_use_certificate_file()
Product: [Fedora] Fedora Reporter: Robert Scheck <redhat-bugzilla>
Component: sendmailAssignee: Jaroslav Škarvada <jskarvad>
Status: CLOSED ERRATA QA Contact: Fedora Extras Quality Assurance <extras-qa>
Severity: medium Docs Contact:
Priority: unspecified    
Version: 28CC: jskarvad, olysonek, redhat-bugzilla
Target Milestone: ---   
Target Release: ---   
Hardware: All   
OS: Linux   
Whiteboard:
Fixed In Version: sendmail-8.15.2-27.fc28 Doc Type: If docs needed, set a value
Doc Text:
Story Points: ---
Clone Of:
: 1596724 (view as bug list) Environment:
Last Closed: 2018-07-05 16:13:55 UTC Type: Bug
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:
Bug Depends On:    
Bug Blocks: 1596724, 1596725    
Attachments:
Description Flags
Patch for sendmail.spec
none
Rebased patch for sendmail.spec jskarvad: review+

Description Robert Scheck 2018-04-09 21:02:10 UTC
Description of problem:
In a common scenario, a sendmail admin would like to provide STARTTLS
for inbound e-mails but also perform certificate verification for outbound
e-mails, while the latter is maybe not enforced for all destination hosts;
the sendmail default is just to log e.g. "verify=FAIL" or "verify=OK" for
outbound e-mails if the remote host offered STARTTLS.

For above, /etc/mail/sendmail.mc looks usually more or less like this:

define(`confCACERT_PATH', `/etc/pki/tls/certs')dnl
define(`confCACERT', `/etc/pki/tls/certs/ca-bundle.crt')dnl
define(`confSERVER_CERT', `/etc/pki/tls/certs/mail.example.net.pem')dnl
define(`confSERVER_KEY', `/etc/pki/tls/private/mail.example.net.key')dnl
define(`confTLS_SRV_OPTIONS', `V')dnl

It provides the /etc/pki/tls/certs/ca-bundle.crt root CA bundle to allow
verification of outbound SSL/TLS connections, also adds /etc/pki/tls/certs
directory in case of company-internal CAs that shall be handled as well,
but are not publically trusted (put *.pem in that dir, then c_rehash(1)).

Put the public SSL certificate into /etc/pki/tls/certs/mail.example.net.pem
and the private key into /etc/pki/tls/private/mail.example.net.key. The 'V'
is used to not ask the client for a SSL certificate, given we do not want a
certificate based authentication (e.g. for relaying), most scenarios still
use username/password (via SASL).

Running "openssl s_client -connect mail.example.net:25 -starttls smtp" when
the SSL certificate is from a publically trusted root CA will lead now to an
incomplete certificate chain.

Why? The root CA bundle does not contain intermediate certificates, which is
correct. The lazy way is now to put the intermediate certificate simply into
/etc/pki/tls/certs/whatever-ca-intermediate.pem and run 'c_rehash'.

But running "openssl s_client -connect mail.example.net:25 -starttls smtp"
now again will show a certificate chain from the SSL certificate via the
intermediate certificate including the root CA - which isn't really perfect
either.

RFC 5246, § 7.4.2 [1] says "This is a sequence (chain) of certificates.  The
sender's certificate MUST come first in the list.  Each following
certificate MUST directly certify the one preceding it.  Because certificate 
validation requires that root keys be distributed independently, the self-
signed certificate that specifies the root certificate authority MAY be
omitted from the chain, under the assumption that the remote end must already
possess it in order to validate it in any case.". This is also how e.g.
Qualys SSL Labs handle their tests (delivering root CA in a chain leads to
a warning) and what e.g. the CA/B Forum meeting minutes 2014-06-17 [2] are
also discussing (avoid root CA in chains to keep them short).

So, various websites suggest to just feed the intermediate certificate into
confCACERT (+ /etc/pki/tls/certs/whatever-ca-intermediate.pem). While this
indeed works at the first glance (proper certificate chain for inbound SMTP
with STARTTLS), it breaks all outbound SSL certificate verifications, given
/etc/pki/tls/certs/ca-bundle.crt file is no longer referenced; verify=FAIL"
is now what is logged for each outbound SSL/TLS connection that is not using
the same parent CA like confCACERT contains.

Building an own bundle for confCACERT? Possible, but not really upgrade-safe
and/or requires manual (or scripted) handling afterwards.

Under the hood, sendmail uses SSL_CTX_use_certificate_file() from OpenSSL.
OpenSSL recommends that SSL_CTX_use_certificate_chain_file() is used instead
of SSL_CTX_use_certificate_file() [3]: "SSL_CTX_use_certificate_chain_file()
adds the first certificate found in the file to the certificate store. The
other certificates are added to the store of chain certificates using 
SSL_CTX_add1_chain_cert.".

This means, the above sendmail configuration snippet works as expected when
confSERVER_CERT contains both, the SSL certificate and the intermediate cert.
This is also how Apache's SSLCertificateFile works since >= 2.4.8 and this is
also what e.g. Let's Encrypt reference ACME client (certbot) but also other
ACME clients (e.g. dehydrated) are delivering by default.

How to enable SSL_CTX_use_certificate_chain_file() in sendmail? According to
sendmail/tls.c it's preprocessor option _FFR_TLS_USE_CERTIFICATE_CHAIN_FILE.

[1] https://tools.ietf.org/html/rfc5246#section-7.4.2
[2] https://cabforum.org/2014/06/17/2014-06-16-17-18-minutes/
[3] https://www.openssl.org/docs/man1.0.2/ssl/SSL_CTX_use_certificate_chain_file.html

Version-Release number of selected component (if applicable):
sendmail-8.15.2-25.fc28

How reproducible:
See above.

Actual results:
Intermediate certificate passed via confSERVER_CERT is ignored.

Expected results:
Intermediate certificate passed via confSERVER_CERT is handled properly.

Additional info:
Could you please clone this bug report for RHEL 8? I'm unfortunately not
allowed to do so (lack of bugzilla permissions).

Comment 1 Robert Scheck 2018-04-09 21:08:12 UTC
Created attachment 1419567 [details]
Patch for sendmail.spec

Aside of adding -D_FFR_TLS_USE_CERTIFICATE_CHAIN_FILE, the patch
also moves -D_FFR_TLS_1 and -D_FFR_TLS_EC from unconditional part
into the %{with_tls} part.

Comment 2 Robert Scheck 2018-06-24 18:54:31 UTC
Cross-filed ticket 02127283 to get the clone for RHEL 8 hopefully addressed.

Comment 3 Jaroslav Škarvada 2018-06-26 17:08:45 UTC
Thanks, it looks good.

Comment 4 Jaroslav Škarvada 2018-06-26 17:18:16 UTC
Could you please rebase the patch for the rawhide (to have a credit in the changelog)?

Comment 5 Robert Scheck 2018-06-26 21:21:11 UTC
Created attachment 1454796 [details]
Rebased patch for sendmail.spec

Of course, Jaroslav.

Comment 6 Jaroslav Škarvada 2018-06-27 08:11:45 UTC
Thanks, applied.

Comment 7 Fedora Update System 2018-06-27 08:49:29 UTC
sendmail-8.15.2-27.fc28 has been submitted as an update to Fedora 28. https://bodhi.fedoraproject.org/updates/FEDORA-2018-0b760ba7f8

Comment 8 Fedora Update System 2018-06-28 15:04:16 UTC
sendmail-8.15.2-27.fc28 has been pushed to the Fedora 28 testing repository. If problems still persist, please make note of it in this bug report.
See https://fedoraproject.org/wiki/QA:Updates_Testing for
instructions on how to install test updates.
You can provide feedback for this update here: https://bodhi.fedoraproject.org/updates/FEDORA-2018-0b760ba7f8

Comment 9 Fedora Update System 2018-07-05 16:13:55 UTC
sendmail-8.15.2-27.fc28 has been pushed to the Fedora 28 stable repository. If problems still persist, please make note of it in this bug report.

Comment 10 Fedora Update System 2018-07-05 18:37:58 UTC
sendmail-8.15.2-27.fc28 has been pushed to the Fedora 28 stable repository. If problems still persist, please make note of it in this bug report.