Joe Orton wrote: > A lot of the mod_ssl code will need to be > very carefully reviewed since some core assumptions are being broken by > supporting SNI. I would go through each of the config directive which > supports vhost context in turn.
So, as promised, I've looked further into it, based on the list of directives we collected earlier. Here is part one of my findings, i.e. those covering case 1(b) (I suggest to do it step by step, so I would follow up on 2(b) afterwards): > (1) SNI client connecting to > (b) one of the other, also access-restricted vhosts (two or above) In this case, the matching modssl_ctx_t structure (referred to as "mctx" henceforth) gets assigned to a conn_rec very early in the handshake, in ssl_callback_ServerNameIndication(). This is the server's first step in the TLS handshake (parsing the ClientHello), i.e. it happens before any certificate, cipher, verification mode etc. has been set/sent to the peer - which also means that virtually all parameters set at that time in the corresponding OpenSSL structure (SSL *) are applied later on in the handshake. Specifically, we have to care about the following parameters: mod_ssl directive Configured in mod_ssl as Applied in OpenSSL (modssl_ctx_t*)mctx->... based on (SSL*)ssl->... ------------------------------------------------------------------------ SSLCipherSuite auth.cipher_suite ctx->cipher_list SSLVerifyDepth auth.verify_depth [1] SSLVerifyClient auth.verify_mode verify_mode SSLCACertificateFile auth.ca_cert_file ctx->client_CA [2] SSLCACertificatePath auth.ca_cert_path ctx->client_CA [2] SSLCARevocationFile crl_file [3] SSLCARevocationPath crl_path [3] SSLOCSDefaultResponder ocsp_responder [1] SSLOCSPEnable ocsp_enabled [1] SSLOCSPOverrideResponder ocsp_force_default [1] SSLCertificateChainFile cert_chain ctx->cert_store SSLCADNRequestFile pks->ca_name_file ctx->client_CA [2] SSLCADNRequestPath pks->ca_name_path ctx->client_CA [2] SSLHonorCipherOrder sc->cipher_server_pref options SSLProtocol protocol method [4] [1] Enforced by mod_ssl's ssl_callback_SSLVerify(), which gets the parameter's value either through dc->nVerifyDepth or through mctx->auth.verify_depth (the latter as a fallback). To make sure it's the correct mctx, we adjust c->base_server before we leave ssl_find_vhost(). [2] If set, pks->ca_name_file and pks->ca_name_path have preference over auth.ca_cert_file and auth.ca_cert_path - see ssl_engine_init.c:ssl_init_ctx_verify(), where the SSL_CTX is set up. [3] Enforced by mod_ssl's ssl_callback_SSLVerify_CRL, which retrieves this information through the mctx assigned to the connection (analogous to [1]). [4] The first vhost *must* include TLSv1 as a permitted protocol, otherwise vhosts two and above are not reachable through ssl_callback_ServerNameIndication (and need to be addressed under case 2(b), i.e. as if SNI is basically disabled - even if we originally received a TLSv1 ClientHello with an SNI extension). Now, the consequence of this in reply to your observation > So *all* vhost-specific config settings which affect the handshake are > going to have to be set up manually in the SSL_CTX, otherwise the > configuration is not going to be applied correctly. is that we need to do this in ssl_callback_ServerNameIndication()/ ssl_find_vhost() only for those directives from the table above where the third column either has no "ctx->..." or no footnote. Or put another way, it amounts to those members of the SSL structure which are copied by SSL_new (as documented by openssl/ssl.h) from the SSL_CTX. We can ignore those which can't be tuned through one of the listed mod_ssl configuration directives (ctx->read_ahead e.g.), which leaves us with these two: SSLVerifyClient auth.verify_mode verify_mode SSLHonorCipherOrder sc->cipher_server_pref options "Luckily" enough, though, that's already the case for the current ssl_find_vhost() code, which includes these two calls: for SSLHonorCipherOrder (SSL_OP_CIPHER_SERVER_PREFERENCE): > SSL_set_options(ssl, SSL_CTX_get_options(ssl->ctx)); for SSLVerifyClient: > SSL_set_verify(ssl, SSL_CTX_get_verify_mode(ssl->ctx), > SSL_CTX_get_verify_callback(ssl->ctx)); To sum up, I still maintain that the implementation currently available in trunk is correct for SNI clients (i.e. supports all relevant SSL* directives for name-based SSL virtual hosts, and properly enforces access control). Joe, do you agree/disagree with this analysis? If the latter, then let me know what additional issues you see. If the former, I would continue my analysis for case 2(b) then. It definitely needs some additional fine-tuning compared to my latest patch posted on 5 June, but I think we'll be able to find an acceptable solution (read: compromise). Thanks for your help! Kaspar