#3916: Mutt 1.8: TOFU approach bails out on first fail or reject, not offering higher links of the cert' chain --------------------------+---------------------- Reporter: kratem32 | Owner: mutt-dev Type: enhancement | Status: new Priority: minor | Milestone: 1.8 Component: crypto | Version: Resolution: | Keywords: tofu --------------------------+----------------------
Comment (by m-a): Replying to [comment:48 kevin8t8's comment:48] (and after having read kratem32's comment:49): > Matthias, > > I feel as if some confusion is occurring about how the option/patch is intended to be used. Or it may be that I am too ignorant and am missing an important point. TL;DR: {{{X509_V_FLAG_PARTIAL_CHAIN}}} appears to be the flag we need to get this going right. The gist of prototypical code I have given below. Details: The important point is providing a sound user interface that lives up to the users' expectations, makes the options do what they promise, and we can stop the quadoption abuse and go for a binary option instead. If "let them tinker" is the excuse to waive that requirement, we can forgo the UI altogether and make them stuff the certificates manually into their mutt_certificates file, but even then we need to permit OpenSSL to accept partial chains. So, preliminary results with a piece of code such as the one below (not ready to be sewn onto the code yet) mutt_ssl.c makes "=ask-yes" exactly what we set out to reinstate, barring the "presents root certificate twice". With this code and Ubuntu 16.04's OpenSSL 1.0.2blah, **any** certificate from the chain (including root, either single one of both intermediate CAs, or the server's certificate) that is in our cache makes OpenSSL accept the host certificate without further ado. This is incremental to the other two patches. We may then even be able to reduce the complexity of the ticket-3916-verify-partial-quadoption.patch quite a bit, I hope that we can omit the entire "skip" logic. TODOS: * add error handling * make $ssl_verify_partial_chains a binary option (instead of the quadoption), and make the new "yes" of the new option behave the same as the old ask-yes/ask-no of the current quadoption * mask the entire rig with partial chain support under the "yes"/true path of $ssl_verify_partial_chains * test on OpenSSL 1.0.2b+ with {{{OPENSSL_NO_SSL_INTERN}}} (no longer supported as of 1.1.0) and * see if this whole lot is needed at all with OpenSSL 1.1.0+ because it sets {{{X509_V_FLAG_TRUSTED_FIRST}}} * test on OpenSSL 1.1.0blah with {{{OPENSSL_NO_DEPRECATED}}} * test on OpenSSL master with {{{OPENSSL_NO_DEPRECATED}}} * consider if we need to support older OpenSSL versions. Upstream doesn't, so I won't contribute here. If anyone wants to run mutt 1.8.1 on OpenSSL 1.0.1 they can seek paid support. * figure out why the root cert is presented twice, and avoid that. {{{ ... +#include <openssl/x509_vfy.h> ... @@ -459,6 +460,16 @@ SSL_CTX_set_cipher_list (data->ctx, SslCiphers); } + X509_VERIFY_PARAM *param; + param = X509_VERIFY_PARAM_new(); + if (param) { + X509_VERIFY_PARAM_set_flags(param, X509_V_FLAG_PARTIAL_CHAIN); + SSL_CTX_set1_param(data->ctx, param); + X509_VERIFY_PARAM_free(param); + } else { + /* XXX Handle error */ + } + }}} > > Saving the cert of the intermediate that is closer to the root (2/4), however, mutt > > will ask for the root again next time. > No. The **next** time you connect, ssl_verify_partial_chains should be set to "=yes". The patch will ignore (1/4), find (2/4) in the certificate file and return true, and so (3/4) and (4/4) should then be marked preverify_ok=1. Unacceptable. This needs to become a binary option, as laid out above. > The ssl_verify_partial_chains=ask-yes setting is **only** for the **first** time you connect to a host. The (s)kip option is only to help you save one of the certificates in the chain to your certificate file. Once you do this, you set it back to "=yes". This option flipping is not needed for the function, isn't process-safe (i. e. will generate a lot of frustration and user support, and require a lot of documentation to get right), and should not be made. > > Or we implement an even more complex concept that uses the > > earlier callbacks to just build a global view of the chain, > > always pretending success and caching the preverify results as > > well as the cache state, until we get to the final > > callback (which is the one concerning the host certificate), when > > we present the user with the necessary questions. This would, > > however, amount to doing most of the verification in loops > > ourselves again. But before we go into code, we need to > > understand how OpenSSL itself deals with "alternative trust > > This is certainly the *best* way to go about it. But I am trying to avoid this option > if at all possible. I feel the quadoption patch allows the tinkerers to tinker > without too much effort from mutt development side, while the "=no" option > preserves the safe/correct behavior for 99% of the users. > > With the above explanation, does the patch make more sense? MichaĆ does it > make sense to you? The current patch is inferior to a solution that is based on your patch, simplified, and flips a few OpenSSL levers in the right way. A patch that causes confusing behaviour cannot be rectified or justified with documentation, let's get it right, and we can. I can't promise any more refined version before 2017-03-06 though. -- Ticket URL: <https://dev.mutt.org/trac/ticket/3916#comment:50> Mutt <http://www.mutt.org/> The Mutt mail user agent