Return-Path: Delivered-To: apmail-httpd-dev-archive@www.apache.org Received: (qmail 96120 invoked from network); 19 Aug 2008 06:17:53 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.2) by minotaur.apache.org with SMTP; 19 Aug 2008 06:17:53 -0000 Received: (qmail 2402 invoked by uid 500); 19 Aug 2008 06:17:48 -0000 Delivered-To: apmail-httpd-dev-archive@httpd.apache.org Received: (qmail 2342 invoked by uid 500); 19 Aug 2008 06:17:48 -0000 Mailing-List: contact dev-help@httpd.apache.org; run by ezmlm Precedence: bulk Reply-To: dev@httpd.apache.org list-help: list-unsubscribe: List-Post: List-Id: Delivered-To: mailing list dev@httpd.apache.org Received: (qmail 2331 invoked by uid 99); 19 Aug 2008 06:17:48 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 18 Aug 2008 23:17:47 -0700 X-ASF-Spam-Status: No, hits=-0.0 required=10.0 tests=SPF_PASS X-Spam-Check-By: apache.org Received-SPF: pass (athena.apache.org: local policy) Received: from [62.75.208.171] (HELO appendix.velox.ch) (62.75.208.171) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 19 Aug 2008 06:16:48 +0000 Received: from cortex.velox.ch (77-56-88-217.dclient.hispeed.ch [77.56.88.217]) (authenticated bits=0) by appendix.velox.ch (8.14.2/8.14.2/2.0) with ESMTP id m7J6GB6h003653 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Tue, 19 Aug 2008 08:16:13 +0200 DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=velox.ch; s=appendix-177f; t=1219126573; bh=oXPQ+lous4pz1XzE262vlo+4DzjsrvbVa CYafFf35p8=; h=Message-ID:Date:From:MIME-Version:To:Subject: Content-Type; b=VXv3+rxTe6e4OZeJL5wuBXX7vh4qK/Xbi28XTTPoj8ft6iyN4l bgavwOOJUTyHBf48+tiTSrdrXFzbAlr0F8oTwkWB4pT8Gk3flarjW+D+Hq9YPyFi0s+ DuHeH0Ueqm8CnNJaG40nNlScdCrQwVdNnvSdoPMlOeHvSu88NrmGuJKMgG0dbcfXO8F KU3lTuzkN3zlqIk9BVuVHSwSA+dKVY5vg/45XRQ3TqWbSACk6xc1fJzmWpilKo6xiwB aXPZC1S387gbJUcdQsBc+wn65vZ6Sqftdc+pmw6zyz/LCLEpRR9NgFmbtb4xI/NSWcr WMBbgWoU074Ls1Y9A0tuV63Q== Message-ID: <48AA6528.1090301@velox.ch> DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=velox.ch; s=cortex-8a58; t=1219126574; bh=oXPQ+lous4pz1XzE262vlo+4DzjsrvbVaCY afFf35p8=; h=Date:From:MIME-Version:To:Subject:Content-Type; b=ko6U +w34oFEzSdv+jhlu6ChgbrwBqiPT1WDLoQvbZoP5TAlSIqiX8n7/RBuoCbTewv8z5PS E4lh8bJWtpCypLM78dcPPOQB1B1gROL7SMyRQC+V/OKGt+6sxQ9chT0qNTyZUZKbS0w byz7NHihKpYQeYAFamMSPBKrS/wYUCzTJYCEn/VbZxAiD9FKcdQYX8ijoobOnai4Wc0 mKdw9kx6hlC4JY6uMxJ72hV6l5zE2wJGDcc+BJz9DCC3EEdo1oVvbQRovcshBRgu3DS StKvfddkVX+ZHmTuOVXLpsQyX+00k0RvemJ0iGS1M/ActsXYcMG7QCcxM5sEYrb03gf eLw== Date: Tue, 19 Aug 2008 08:16:08 +0200 From: Kaspar Brand User-Agent: Thunderbird 2.0.0.16 (Windows/20080708) MIME-Version: 1.0 To: dev@httpd.apache.org Subject: SNI in 2.2.x (Re: Time for 2.2.10?) Content-Type: multipart/mixed; boundary="------------070302090709030408050509" X-Virus-Checked: Checked by ClamAV on apache.org This is a multi-part message in MIME format. --------------070302090709030408050509 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit Ruediger Pluem wrote: > At the moment we have 9 entries in the CHANGES file for 2.2.10 and > there are 5 more proposals in the STATUS file that are missing only > one vote. I think if get these done we also have enough stuff from > pure httpd point of view that warrants a release. WDYT? May I use this occasion to ask if there's still a chance of getting a backport of SNI accepted for 2.2.x? Following suggestions from Joe, I went through all relevant SSL* config directives and posted my findings in two parts on 9th/18th June: http://mail-archives.apache.org/mod_mbox/httpd-dev/200806.mbox/%3c484CBAA6.7050702@velox.ch%3e http://mail-archives.apache.org/mod_mbox/httpd-dev/200806.mbox/%3c48592955.2090303@velox.ch%3e The patch I posted on 18 June introduced a regression, however, so I posted an updated version on 26th June: http://mail-archives.apache.org/mod_mbox/httpd-dev/200806.mbox/%3c4863C04C.2010502@velox.ch%3e That's the version I still consider suitable for check-in to trunk (attached again for convenience). A backport to 2.2.x is available at http://sni.velox.ch/httpd-2.2.x-sni.diff If, on the other hand, people think that SNI isn't important enough for 2.2.x, then I'd be glad to hear that as well (it doesn't make sense to repeatedly nag the list about that topic, I think). Thanks, Kaspar --------------070302090709030408050509 Content-Type: text/plain; name="sni_sslverifyclient-v5.diff" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="sni_sslverifyclient-v5.diff" Index: httpd-trunk/modules/ssl/ssl_engine_kernel.c =================================================================== --- httpd-trunk/modules/ssl/ssl_engine_kernel.c (revision 671932) +++ httpd-trunk/modules/ssl/ssl_engine_kernel.c (working copy) @@ -327,32 +327,35 @@ int ssl_hook_Access(request_rec *r) * because it's the servers choice to select a cipher from the ones the * client supports. So as long as the current cipher is still in the new * cipher suite we're happy. Because we can assume we would have * selected it again even when other (better) ciphers exists now in the * new cipher suite. This approach is fine because the user explicitly * has to enable this via ``SSLOptions +OptRenegotiate''. So we do no * implicit optimizations. */ - if (dc->szCipherSuite) { + if (dc->szCipherSuite || (r->server != r->connection->base_server)) { /* remember old state */ if (dc->nOptions & SSL_OPT_OPTRENEGOTIATE) { cipher = SSL_get_current_cipher(ssl); } else { cipher_list_old = (STACK_OF(SSL_CIPHER) *)SSL_get_ciphers(ssl); if (cipher_list_old) { cipher_list_old = sk_SSL_CIPHER_dup(cipher_list_old); } } /* configure new state */ - if (!modssl_set_cipher_list(ssl, dc->szCipherSuite)) { + if ((dc->szCipherSuite && + !modssl_set_cipher_list(ssl, dc->szCipherSuite)) || + (sc->server->auth.cipher_suite && + !modssl_set_cipher_list(ssl, sc->server->auth.cipher_suite))) { ap_log_rerror(APLOG_MARK, APLOG_WARNING, 0, r, "Unable to reconfigure (per-directory) " "permitted SSL ciphers"); ssl_log_ssl_error(APLOG_MARK, APLOG_ERR, r->server); if (cipher_list_old) { sk_SSL_CIPHER_free(cipher_list_old); } @@ -408,18 +411,23 @@ int ssl_hook_Access(request_rec *r) } } /* cleanup */ if (cipher_list_old) { sk_SSL_CIPHER_free(cipher_list_old); } - /* tracing */ if (renegotiate) { +#ifdef SSL_OP_CIPHER_SERVER_PREFERENCE + if (sc->cipher_server_pref == TRUE) { + SSL_set_options(ssl, SSL_OP_CIPHER_SERVER_PREFERENCE); + } +#endif + /* tracing */ ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "Reconfigured cipher suite will force renegotiation"); } } /* * override of SSLVerifyDepth * @@ -427,29 +435,26 @@ int ssl_hook_Access(request_rec *r) * function and not by OpenSSL internally (and our function is aware of * both the per-server and per-directory contexts). So we cannot ask * OpenSSL about the currently verify depth. Instead we remember it in our * ap_ctx attached to the SSL* of OpenSSL. We've to force the * renegotiation if the reconfigured/new verify depth is less than the * currently active/remembered verify depth (because this means more * restriction on the certificate chain). */ - if ((sc->server->auth.verify_depth != UNSET) && - (dc->nVerifyDepth == UNSET)) { - /* apply per-vhost setting, if per-directory config is not set */ - dc->nVerifyDepth = sc->server->auth.verify_depth; - } - if (dc->nVerifyDepth != UNSET) { + if ((dc->nVerifyDepth != UNSET) || + (sc->server->auth.verify_depth != UNSET)) { /* XXX: doesnt look like sslconn->verify_depth is actually used */ if (!(n = sslconn->verify_depth)) { sslconn->verify_depth = n = sc->server->auth.verify_depth; } /* determine whether a renegotiation has to be forced */ - if (dc->nVerifyDepth < n) { + if ((dc->nVerifyDepth < n) || + (sc->server->auth.verify_depth < n)) { renegotiate = TRUE; ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "Reduced client verification depth will force " "renegotiation"); } } /* @@ -461,33 +466,32 @@ int ssl_hook_Access(request_rec *r) * The order is: none << optional_no_ca << optional << require * * Additionally the following optimization is possible here: When the * currently active verify type is "none" but a client certificate is * already known/present, it's enough to manually force a client * verification but at least skip the I/O-intensive renegotation * handshake. */ - if ((sc->server->auth.verify_mode != SSL_CVERIFY_UNSET) && - (dc->nVerifyClient == SSL_CVERIFY_UNSET)) { - /* apply per-vhost setting, if per-directory config is not set */ - dc->nVerifyClient = sc->server->auth.verify_mode; - } - if (dc->nVerifyClient != SSL_CVERIFY_UNSET) { + if ((dc->nVerifyClient != SSL_CVERIFY_UNSET) || + (sc->server->auth.verify_mode != SSL_CVERIFY_UNSET)) { /* remember old state */ verify_old = SSL_get_verify_mode(ssl); /* configure new state */ verify = SSL_VERIFY_NONE; - if (dc->nVerifyClient == SSL_CVERIFY_REQUIRE) { + if ((dc->nVerifyClient == SSL_CVERIFY_REQUIRE) || + (sc->server->auth.verify_mode == SSL_CVERIFY_REQUIRE)) { verify |= SSL_VERIFY_PEER_STRICT; } if ((dc->nVerifyClient == SSL_CVERIFY_OPTIONAL) || - (dc->nVerifyClient == SSL_CVERIFY_OPTIONAL_NO_CA)) + (dc->nVerifyClient == SSL_CVERIFY_OPTIONAL_NO_CA) || + (sc->server->auth.verify_mode == SSL_CVERIFY_OPTIONAL) || + (sc->server->auth.verify_mode == SSL_CVERIFY_OPTIONAL_NO_CA)) { verify |= SSL_VERIFY_PEER; } modssl_set_verify(ssl, verify, ssl_callback_SSLVerify); SSL_set_verify_result(ssl, X509_V_OK); /* determine whether we've to force a renegotiation */ @@ -574,16 +578,50 @@ int ssl_hook_Access(request_rec *r) SSL_set_client_CA_list(ssl, ca_list); renegotiate = TRUE; ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, "Changed client verification locations will force " "renegotiation"); } +#else +#ifndef OPENSSL_NO_TLSEXT +#define MODSSL_CFG_CA_NE(f, sc1, sc2) \ + (sc1->server->auth.f && \ + (!sc2->server->auth.f || \ + sc2->server->auth.f && strNE(sc1->server->auth.f, sc2->server->auth.f))) + + /* If we're handling a request for a vhost other than the default one, + * then we need to make sure that client authentication is properly + * enforced. For clients supplying an SNI extension, the peer certificate + * verification has happened in the handshake already (and r->server + * has been set to r->connection->base_server). For non-SNI requests, + * an additional check is needed here. If client authentication is + * configured as mandatory, then we can only proceed if the CA list + * doesn't have to be changed (SSL_set_cert_store() would be required + * for this). + */ + if ((r->server != r->connection->base_server) && + (verify & SSL_VERIFY_FAIL_IF_NO_PEER_CERT) && + renegotiate && + !(SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name))) { + SSLSrvConfigRec *bssc = mySrvConfig(r->connection->base_server); + + if (MODSSL_CFG_CA_NE(ca_cert_file, sc, bssc) || + MODSSL_CFG_CA_NE(ca_cert_path, sc, bssc)) { + ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r, + "Non-default virtual host with SSLVerify set to 'require' " + "and VirtualHost-specific CA certificate list is only " + "supported for clients with TLS server name indication " + "(SNI) support"); + return HTTP_FORBIDDEN; + } + } +#endif /* OPENSSL_NO_TLSEXT */ #endif /* HAVE_SSL_SET_CERT_STORE */ /* If a renegotiation is now required for this location, and the * request includes a message body (and the client has not * requested a "100 Continue" response), then the client will be * streaming the request body over the wire already. In that * case, it is not possible to stop and perform a new SSL * handshake immediately; once the SSL library moves to the @@ -749,18 +787,20 @@ int ssl_hook_Access(request_rec *r) } sslconn->client_cert = cert; sslconn->client_dn = NULL; } /* * Finally check for acceptable renegotiation results */ - if (dc->nVerifyClient != SSL_CVERIFY_NONE) { - BOOL do_verify = (dc->nVerifyClient == SSL_CVERIFY_REQUIRE); + if ((dc->nVerifyClient != SSL_CVERIFY_NONE) || + (sc->server->auth.verify_mode != SSL_CVERIFY_NONE)) { + BOOL do_verify = ((dc->nVerifyClient == SSL_CVERIFY_REQUIRE) || + (sc->server->auth.verify_mode == SSL_CVERIFY_REQUIRE)); if (do_verify && (SSL_get_verify_result(ssl) != X509_V_OK)) { ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, "Re-negotiation handshake failed: " "Client verification failed"); return HTTP_FORBIDDEN; } @@ -1266,18 +1306,18 @@ DH *ssl_callback_TmpDH(SSL *ssl, int exp * does client authentication and verifies the certificate chain. */ int ssl_callback_SSLVerify(int ok, X509_STORE_CTX *ctx) { /* Get Apache context back through OpenSSL context */ SSL *ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx()); conn_rec *conn = (conn_rec *)SSL_get_app_data(ssl); - server_rec *s = conn->base_server; request_rec *r = (request_rec *)SSL_get_app_data2(ssl); + server_rec *s = r ? r->server : conn->base_server; SSLSrvConfigRec *sc = mySrvConfig(s); SSLDirConfigRec *dc = r ? myDirConfig(r) : NULL; SSLConnRec *sslconn = myConnConfig(conn); modssl_ctx_t *mctx = myCtxConfig(sslconn, sc); /* Get verify ingredients */ int errnum = X509_STORE_CTX_get_error(ctx); @@ -1397,17 +1437,20 @@ int ssl_callback_SSLVerify(int ok, X509_ /* * And finally signal OpenSSL the (perhaps changed) state */ return ok; } int ssl_callback_SSLVerify_CRL(int ok, X509_STORE_CTX *ctx, conn_rec *c) { - server_rec *s = c->base_server; + SSL *ssl = X509_STORE_CTX_get_ex_data(ctx, + SSL_get_ex_data_X509_STORE_CTX_idx()); + request_rec *r = (request_rec *)SSL_get_app_data2(ssl); + server_rec *s = r ? r->server : c->base_server; SSLSrvConfigRec *sc = mySrvConfig(s); SSLConnRec *sslconn = myConnConfig(c); modssl_ctx_t *mctx = myCtxConfig(sslconn, sc); X509_OBJECT obj; X509_NAME *subject, *issuer; X509 *cert; X509_CRL *crl; EVP_PKEY *pubkey; --------------070302090709030408050509--