[PATCH] allow setting explicit SSL server certificate chain
To explain why this is needed, consider this comment from the
Apache mod_ssl ssl_engine_init.c source file:
/* * Optionally configure extra server certificate chain certificates. * This is usually done by OpenSSL automatically when one of the * server cert issuers are found under SSLCACertificatePath or in * SSLCACertificateFile. But because these are intended for client * authentication it can conflict. For instance when you use a * Global ID server certificate you've to send out the intermediate * CA certificate, too. When you would just configure this with * SSLCACertificateFile and also use client authentication mod_ssl * would accept all clients also issued by this CA. Obviously this * isn't what we want in this situation. So this feature here exists * to allow one to explicity configure CA certificates which are * used only for the server certificate chain. */
Note that SSLCACertificateFile corresponds to lighttpd's ssl.ca-file
However, lighttpd does not have an explicit directive to set the server's
sertificate chain. It sets only the server's certificate (excluding any
necessary intermediate certificates) using the SSL_CTX_use_certificate
function. The server's certificate chain, if it were to be configured
explicitly, would be set using the SSL_CTX_add_extra_chain_cert function.
However, lighttpd never calls the SSL_CTX_add_extra_chain_cert function.
But consider this information from the man page documentation about the
SSL_CTX_use_certificate() loads the certificate x into ctx, SSL_use_certificate() loads x into ssl. The rest of the certificates needed to form the complete certificate chain can be specified using the SSL_CTX_add_extra_chain_cert(3) function. SSL_CTX_use_certificate_file() loads the first certificate stored in file into ctx. The formatting type of the certificate must be specified from the known types SSL_FILETYPE_PEM, SSL_FILETYPE_ASN1. SSL_use_certificate_file() loads the certificate from file into ssl. See the NOTES section on why SSL_CTX_use_certificate_chain_file() should be preferred. SSL_CTX_use_certificate_chain_file() loads a certificate chain from file into ctx. The certificates must be in PEM format and must be sorted starting with the subject's certificate (actual client or server certificate), followed by intermediate CA certificates if applicable, and ending at the highest level (root) CA. There is no corresponding function working on a single SSL object. SSL_CTX_use_certificate_chain_file() is only applicable to PEM formatting. Files of type SSL_FILETYPE_PEM can contain more than one item. 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_add_extra_chain_cert(3). There exists only one extra chain store, so that the same chain is appended to both types of certificates, RSA and DSA! If it is not intended to use both type of certificate at the same time, it is recommended to use the SSL_CTX_use_certificate_chain_file() instead of the SSL_CTX_use_certificate_file() function in order to allow the use of complete certificate chains even when no trusted CA storage is used or when the CA issuing the certificate shall not be added to the trusted CA storage.
We could switch from using the SSL_CTX_use_certificate function to the
SSL_CTX_use_certificate_chain_file function instead so that an optional
server certificate chain can simply be concatenated onto the end of the
file specified using the ssl.pemfile directive.
This requires only the very simplest change.
The problem with such a change is that the file may not be read until
after lighttpd has dropped privileges. If the file has restricted
privileges because it contains the server certificate's key it may not
be readable at that time.
However, the solution is simple. Just set a separate server certificate
key file with restricted permissions and relax the permissions on the
pemfile that then contains only non-sensitive certificates but no key.
Of course lighttpd has no ssl.keyfile directive making this impossible.
The alternative is to load the entire chain at the time the ssl.pemfile
is originally read and then call SSL_CTX_add_extra_chain_cert for each
extra certificate in the chain.
The final solution requires a bit more code than just using
SSL_CTX_use_certificate_chain_file would, but it's more compatible.
Also, while we we're mucking around with the SSL function calls, we take
the opportunity to correct the error return checking. Most SSL function
calls are documented as returning 1 on success. If it's not 1 then it
cannot be assumed to be successful, so checking for '< 0' for failure
or '!0' for success is simply incorrect. We correct all these checks.
Patch file attached.
Updated to reflect deprecation of svn repository:
mackyle: thanks for rebasing your patches to master. I'd like to try to review them and related tickets in the next couple weeks.
There are a fair number of tickets that I recently categorized into 'TLS', including yours.
I could use some help evaluating all the TLS-related requests/issues so that they can all be addressed coherently.
Also available in: Atom