ssl_engine_ext.c revision 6d7efb8c76b56eaebd6032096771c9e44b247f3f
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari/* _ _
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari** _ __ ___ ___ __| | ___ ___| | mod_ssl
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari** | '_ ` _ \ / _ \ / _` | / __/ __| | Apache Interface to OpenSSL
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari** | | | | | | (_) | (_| | \__ \__ \ | www.modssl.org
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari** |_| |_| |_|\___/ \__,_|___|___/___/_| ftp.modssl.org
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari** |_____|
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari** ssl_engine_ext.c
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari** Extensions to other Apache parts
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari*/
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari/* ====================================================================
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari * The Apache Software License, Version 1.1
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari *
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari * reserved.
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari *
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari * Redistribution and use in source and binary forms, with or without
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari * modification, are permitted provided that the following conditions
b5c780c06889ceb5c241a6b5da7ef0663e5451caDaniel Calegari * are met:
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari *
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari * 1. Redistributions of source code must retain the above copyright
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari * notice, this list of conditions and the following disclaimer.
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari *
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari * 2. Redistributions in binary form must reproduce the above copyright
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari * notice, this list of conditions and the following disclaimer in
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari * the documentation and/or other materials provided with the
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari * distribution.
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari *
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari * 3. The end-user documentation included with the redistribution,
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari * if any, must include the following acknowledgment:
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari * "This product includes software developed by the
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari * Apache Software Foundation (http://www.apache.org/)."
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari * Alternately, this acknowledgment may appear in the software itself,
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari * if and wherever such third-party acknowledgments normally appear.
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari *
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari * 4. The names "Apache" and "Apache Software Foundation" must
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari * not be used to endorse or promote products derived from this
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari * software without prior written permission. For written
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari * permission, please contact apache@apache.org.
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari *
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari * 5. Products derived from this software may not be called "Apache",
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari * nor may "Apache" appear in their name, without prior written
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari * permission of the Apache Software Foundation.
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari *
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari * SUCH DAMAGE.
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari * ====================================================================
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari */
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari /* ``Only those who attempt the absurd
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari can achieve the impossible.''
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari -- Unknown */
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari#include "mod_ssl.h"
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari#if 0 /* XXX this is for mod_proxy hackers, which optional_fn's to create? */
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari/* _________________________________________________________________
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari**
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari** SSL Extension to mod_proxy
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari** _________________________________________________________________
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari*/
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegaristatic int ssl_ext_mp_canon(request_rec *, char *);
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegaristatic int ssl_ext_mp_handler(request_rec *, void *, char *, char *, int, char *);
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegaristatic int ssl_ext_mp_set_destport(request_rec *);
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegaristatic char *ssl_ext_mp_new_connection(request_rec *, BUFF *, char *);
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegaristatic void ssl_ext_mp_close_connection(void *);
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegaristatic int ssl_ext_mp_write_host_header(request_rec *, BUFF *, char *, int, char *);
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari#ifdef SSL_EXPERIMENTAL_PROXY
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegaristatic void ssl_ext_mp_init(server_rec *, pool *);
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegaristatic int ssl_ext_mp_verify_cb(int, X509_STORE_CTX *);
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegaristatic int ssl_ext_mp_clientcert_cb(SSL *, X509 **, EVP_PKEY **);
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari#endif
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari/*
b5c780c06889ceb5c241a6b5da7ef0663e5451caDaniel Calegari * register us ...
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari */
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegarivoid ssl_ext_proxy_register(apr_pool_t *pconf)
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari{
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari#ifdef SSL_EXPERIMENTAL_PROXY
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari ap_hook_register("ap::mod_proxy::init",
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari ssl_ext_mp_init, AP_HOOK_NOCTX);
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari#endif
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari ap_hook_register("ap::mod_proxy::canon",
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari ssl_ext_mp_canon, AP_HOOK_NOCTX);
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari ap_hook_register("ap::mod_proxy::handler",
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari ssl_ext_mp_handler, AP_HOOK_NOCTX);
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari ap_hook_register("ap::mod_proxy::http::handler::set_destport",
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari ssl_ext_mp_set_destport, AP_HOOK_NOCTX);
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari ap_hook_register("ap::mod_proxy::http::handler::new_connection",
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari ssl_ext_mp_new_connection, AP_HOOK_NOCTX);
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari ap_hook_register("ap::mod_proxy::http::handler::write_host_header",
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari ssl_ext_mp_write_host_header, AP_HOOK_NOCTX);
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari return;
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari}
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari/*
b767e7055b5ef62c990a111ac0524500592f8781Daniel Calegari * SSL proxy initialization
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari */
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari#ifdef SSL_EXPERIMENTAL_PROXY
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegaristatic void ssl_ext_mp_init(server_rec *s, pool *p)
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari{
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari SSLSrvConfigRec *sc;
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari char *cpVHostID;
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari int nVerify;
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari SSL_CTX *ctx;
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari char *cp;
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari STACK_OF(X509_INFO) *sk;
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari /*
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari * Initialize each virtual server
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari */
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari ERR_clear_error();
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari for (; s != NULL; s = s->next) {
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari sc = mySrvConfig(s);
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari cpVHostID = ssl_util_vhostid(p, s);
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari if (sc->bProxyVerify == UNSET)
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari sc->bProxyVerify = FALSE;
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari /*
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari * Create new SSL context and configure callbacks
f3a838d9e2932da421939f348a2c3d31ded88989Daniel Calegari */
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari if (sc->nProxyProtocol == SSL_PROTOCOL_NONE) {
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari ssl_log(s, SSL_LOG_ERROR,
f3a838d9e2932da421939f348a2c3d31ded88989Daniel Calegari "Init: (%s) No Proxy SSL protocols available [hint: SSLProxyProtocol]",
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari cpVHostID);
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari ssl_die();
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari }
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari cp = ap_pstrcat(p, (sc->nProxyProtocol & SSL_PROTOCOL_SSLV2 ? "SSLv2, " : ""),
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari (sc->nProxyProtocol & SSL_PROTOCOL_SSLV3 ? "SSLv3, " : ""),
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari (sc->nProxyProtocol & SSL_PROTOCOL_TLSV1 ? "TLSv1, " : ""), NULL);
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari cp[strlen(cp)-2] = NUL;
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari ssl_log(s, SSL_LOG_TRACE,
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari "Init: (%s) Creating new proxy SSL context (protocols: %s)",
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari cpVHostID, cp);
f3a838d9e2932da421939f348a2c3d31ded88989Daniel Calegari if (sc->nProxyProtocol == SSL_PROTOCOL_SSLV2)
f3a838d9e2932da421939f348a2c3d31ded88989Daniel Calegari ctx = SSL_CTX_new(SSLv2_client_method()); /* only SSLv2 is left */
f3a838d9e2932da421939f348a2c3d31ded88989Daniel Calegari else
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari ctx = SSL_CTX_new(SSLv23_client_method()); /* be more flexible */
f3a838d9e2932da421939f348a2c3d31ded88989Daniel Calegari if (ctx == NULL) {
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari ssl_log(s, SSL_LOG_ERROR|SSL_ADD_SSLERR,
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari "Init: (%s) Unable to create SSL Proxy context", cpVHostID);
b5c780c06889ceb5c241a6b5da7ef0663e5451caDaniel Calegari ssl_die();
b5c780c06889ceb5c241a6b5da7ef0663e5451caDaniel Calegari }
b5c780c06889ceb5c241a6b5da7ef0663e5451caDaniel Calegari sc->pSSLProxyCtx = ctx;
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari SSL_CTX_set_options(ctx, SSL_OP_ALL);
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari if (!(sc->nProxyProtocol & SSL_PROTOCOL_SSLV2))
b5c780c06889ceb5c241a6b5da7ef0663e5451caDaniel Calegari SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2);
b5c780c06889ceb5c241a6b5da7ef0663e5451caDaniel Calegari if (!(sc->nProxyProtocol & SSL_PROTOCOL_SSLV3))
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv3);
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari if (!(sc->nProxyProtocol & SSL_PROTOCOL_TLSV1))
b5c780c06889ceb5c241a6b5da7ef0663e5451caDaniel Calegari SSL_CTX_set_options(ctx, SSL_OP_NO_TLSv1);
b5c780c06889ceb5c241a6b5da7ef0663e5451caDaniel Calegari
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari if (sc->szProxyClientCertificateFile || sc->szProxyClientCertificatePath) {
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari sk = sk_X509_INFO_new_null();
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari if (sc->szProxyClientCertificateFile)
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari SSL_load_CrtAndKeyInfo_file(p, sk, sc->szProxyClientCertificateFile);
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari if (sc->szProxyClientCertificatePath)
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari SSL_load_CrtAndKeyInfo_path(p, sk, sc->szProxyClientCertificatePath);
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari ssl_log(s, SSL_LOG_TRACE, "Init: (%s) loaded %d client certs for SSL proxy",
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari cpVHostID, sk_X509_INFO_num(sk));
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari if (sk_X509_INFO_num(sk) > 0) {
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari SSL_CTX_set_client_cert_cb(ctx, ssl_ext_mp_clientcert_cb);
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari sc->skProxyClientCerts = sk;
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari }
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari }
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari /*
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari * Calculate OpenSSL verify type for verifying the remote server
f3a838d9e2932da421939f348a2c3d31ded88989Daniel Calegari * certificate. We either verify it against our list of CA's, or don't
f3a838d9e2932da421939f348a2c3d31ded88989Daniel Calegari * bother at all.
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari */
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari nVerify = SSL_VERIFY_NONE;
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari if (sc->bProxyVerify)
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari nVerify |= SSL_VERIFY_PEER;
b767e7055b5ef62c990a111ac0524500592f8781Daniel Calegari if ( nVerify & SSL_VERIFY_PEER
b767e7055b5ef62c990a111ac0524500592f8781Daniel Calegari && sc->szProxyCACertificateFile == NULL
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari && sc->szProxyCACertificatePath == NULL) {
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari ssl_log(s, SSL_LOG_ERROR,
b767e7055b5ef62c990a111ac0524500592f8781Daniel Calegari "Init: (%s) SSLProxyVerify set to On but no CA certificates configured",
b767e7055b5ef62c990a111ac0524500592f8781Daniel Calegari cpVHostID);
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari ssl_die();
b767e7055b5ef62c990a111ac0524500592f8781Daniel Calegari }
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari if ( nVerify & SSL_VERIFY_NONE
b767e7055b5ef62c990a111ac0524500592f8781Daniel Calegari && ( sc->szProxyCACertificateFile != NULL
b767e7055b5ef62c990a111ac0524500592f8781Daniel Calegari || sc->szProxyCACertificatePath != NULL)) {
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari ssl_log(s, SSL_LOG_WARN,
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari "init: (%s) CA certificates configured but ignored because SSLProxyVerify is Off",
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari cpVHostID);
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari }
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari SSL_CTX_set_verify(ctx, nVerify, ssl_ext_mp_verify_cb);
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari /*
f3a838d9e2932da421939f348a2c3d31ded88989Daniel Calegari * Enable session caching. We can safely use the same cache
f3a838d9e2932da421939f348a2c3d31ded88989Daniel Calegari * as used for communicating with the other clients.
b5c780c06889ceb5c241a6b5da7ef0663e5451caDaniel Calegari */
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari SSL_CTX_sess_set_new_cb(sc->pSSLProxyCtx, ssl_callback_NewSessionCacheEntry);
b5c780c06889ceb5c241a6b5da7ef0663e5451caDaniel Calegari SSL_CTX_sess_set_get_cb(sc->pSSLProxyCtx, ssl_callback_GetSessionCacheEntry);
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari SSL_CTX_sess_set_remove_cb(sc->pSSLProxyCtx, ssl_callback_DelSessionCacheEntry);
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari /*
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari * Configure SSL Cipher Suite
b767e7055b5ef62c990a111ac0524500592f8781Daniel Calegari */
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari ssl_log(s, SSL_LOG_TRACE,
b5c780c06889ceb5c241a6b5da7ef0663e5451caDaniel Calegari "Init: (%s) Configuring permitted SSL ciphers for SSL proxy", cpVHostID);
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari if (sc->szProxyCipherSuite != NULL) {
b5c780c06889ceb5c241a6b5da7ef0663e5451caDaniel Calegari if (!SSL_CTX_set_cipher_list(sc->pSSLProxyCtx, sc->szProxyCipherSuite)) {
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari ssl_log(s, SSL_LOG_ERROR|SSL_ADD_SSLERR,
b767e7055b5ef62c990a111ac0524500592f8781Daniel Calegari "Init: (%s) Unable to configure permitted SSL ciphers for SSL Proxy",
b767e7055b5ef62c990a111ac0524500592f8781Daniel Calegari cpVHostID);
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari ssl_die();
b767e7055b5ef62c990a111ac0524500592f8781Daniel Calegari }
b767e7055b5ef62c990a111ac0524500592f8781Daniel Calegari }
b767e7055b5ef62c990a111ac0524500592f8781Daniel Calegari
b767e7055b5ef62c990a111ac0524500592f8781Daniel Calegari /*
b767e7055b5ef62c990a111ac0524500592f8781Daniel Calegari * Configure Client Authentication details
b767e7055b5ef62c990a111ac0524500592f8781Daniel Calegari */
b767e7055b5ef62c990a111ac0524500592f8781Daniel Calegari if (sc->szProxyCACertificateFile != NULL || sc->szProxyCACertificatePath != NULL) {
b767e7055b5ef62c990a111ac0524500592f8781Daniel Calegari ssl_log(s, SSL_LOG_DEBUG,
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari "Init: (%s) Configuring client verification locations for SSL Proxy",
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari cpVHostID);
b767e7055b5ef62c990a111ac0524500592f8781Daniel Calegari if (!SSL_CTX_load_verify_locations(sc->pSSLProxyCtx,
b767e7055b5ef62c990a111ac0524500592f8781Daniel Calegari sc->szProxyCACertificateFile,
b767e7055b5ef62c990a111ac0524500592f8781Daniel Calegari sc->szProxyCACertificatePath)) {
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari ssl_log(s, SSL_LOG_ERROR|SSL_ADD_SSLERR,
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari "Init: (%s) Unable to configure SSL verify locations for SSL proxy",
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari cpVHostID);
b767e7055b5ef62c990a111ac0524500592f8781Daniel Calegari ssl_die();
b767e7055b5ef62c990a111ac0524500592f8781Daniel Calegari }
b767e7055b5ef62c990a111ac0524500592f8781Daniel Calegari }
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari }
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari return;
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari}
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari#endif /* SSL_EXPERIMENTAL_PROXY */
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegaristatic int ssl_ext_mp_canon(request_rec *r, char *url)
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari{
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari int rc;
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari if (strcEQn(url, "https:", 6)) {
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari rc = OK;
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari ap_hook_call("ap::mod_proxy::http::canon",
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari &rc, r, url+6, "https", DEFAULT_HTTPS_PORT);
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari return rc;
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari }
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari return DECLINED;
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari}
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegaristatic int ssl_ext_mp_handler(
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari request_rec *r, void *cr, char *url, char *proxyhost, int proxyport, char *protocol)
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari{
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari int rc;
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari
7e9757ba2f41c4ac30634a4a1f1d87a042e37c45Daniel Calegari if (strcEQ(protocol, "https")) {
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari ap_ctx_set(r->ctx, "ssl::proxy::enabled", PTRUE);
b767e7055b5ef62c990a111ac0524500592f8781Daniel Calegari ap_hook_call("ap::mod_proxy::http::handler",
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari &rc, r, cr, url, proxyhost, proxyport);
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari return rc;
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari }
7e9757ba2f41c4ac30634a4a1f1d87a042e37c45Daniel Calegari else {
7e9757ba2f41c4ac30634a4a1f1d87a042e37c45Daniel Calegari ap_ctx_set(r->ctx, "ssl::proxy::enabled", PFALSE);
7e9757ba2f41c4ac30634a4a1f1d87a042e37c45Daniel Calegari }
7e9757ba2f41c4ac30634a4a1f1d87a042e37c45Daniel Calegari return DECLINED;
7e9757ba2f41c4ac30634a4a1f1d87a042e37c45Daniel Calegari}
7e9757ba2f41c4ac30634a4a1f1d87a042e37c45Daniel Calegari
7e9757ba2f41c4ac30634a4a1f1d87a042e37c45Daniel Calegaristatic int ssl_ext_mp_set_destport(request_rec *r)
7e9757ba2f41c4ac30634a4a1f1d87a042e37c45Daniel Calegari{
7e9757ba2f41c4ac30634a4a1f1d87a042e37c45Daniel Calegari if (ap_ctx_get(r->ctx, "ssl::proxy::enabled") == PTRUE)
7e9757ba2f41c4ac30634a4a1f1d87a042e37c45Daniel Calegari return DEFAULT_HTTPS_PORT;
7e9757ba2f41c4ac30634a4a1f1d87a042e37c45Daniel Calegari else
7e9757ba2f41c4ac30634a4a1f1d87a042e37c45Daniel Calegari return DEFAULT_HTTP_PORT;
7e9757ba2f41c4ac30634a4a1f1d87a042e37c45Daniel Calegari}
7e9757ba2f41c4ac30634a4a1f1d87a042e37c45Daniel Calegari
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegaristatic char *ssl_ext_mp_new_connection(request_rec *r, BUFF *fb, char *peer)
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari{
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari#ifndef SSL_EXPERIMENTAL_PROXY
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari SSL_CTX *ssl_ctx;
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari#endif
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari SSL *ssl;
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari char *errmsg;
7e9757ba2f41c4ac30634a4a1f1d87a042e37c45Daniel Calegari int rc;
7e9757ba2f41c4ac30634a4a1f1d87a042e37c45Daniel Calegari char *cpVHostID;
7e9757ba2f41c4ac30634a4a1f1d87a042e37c45Daniel Calegari char *cpVHostMD5;
7e9757ba2f41c4ac30634a4a1f1d87a042e37c45Daniel Calegari#ifdef SSL_EXPERIMENTAL_PROXY
7e9757ba2f41c4ac30634a4a1f1d87a042e37c45Daniel Calegari SSLSrvConfigRec *sc;
7e9757ba2f41c4ac30634a4a1f1d87a042e37c45Daniel Calegari char *cp;
7e9757ba2f41c4ac30634a4a1f1d87a042e37c45Daniel Calegari#endif
7e9757ba2f41c4ac30634a4a1f1d87a042e37c45Daniel Calegari
7e9757ba2f41c4ac30634a4a1f1d87a042e37c45Daniel Calegari if (ap_ctx_get(r->ctx, "ssl::proxy::enabled") == PFALSE)
7e9757ba2f41c4ac30634a4a1f1d87a042e37c45Daniel Calegari return NULL;
7e9757ba2f41c4ac30634a4a1f1d87a042e37c45Daniel Calegari
7e9757ba2f41c4ac30634a4a1f1d87a042e37c45Daniel Calegari /*
7e9757ba2f41c4ac30634a4a1f1d87a042e37c45Daniel Calegari * Find context
7e9757ba2f41c4ac30634a4a1f1d87a042e37c45Daniel Calegari */
7e9757ba2f41c4ac30634a4a1f1d87a042e37c45Daniel Calegari#ifdef SSL_EXPERIMENTAL_PROXY
7e9757ba2f41c4ac30634a4a1f1d87a042e37c45Daniel Calegari sc = mySrvConfig(r->server);
7e9757ba2f41c4ac30634a4a1f1d87a042e37c45Daniel Calegari#endif
7e9757ba2f41c4ac30634a4a1f1d87a042e37c45Daniel Calegari cpVHostID = ssl_util_vhostid(r->pool, r->server);
7e9757ba2f41c4ac30634a4a1f1d87a042e37c45Daniel Calegari
7e9757ba2f41c4ac30634a4a1f1d87a042e37c45Daniel Calegari /*
7e9757ba2f41c4ac30634a4a1f1d87a042e37c45Daniel Calegari * Create a SSL context and handle
7e9757ba2f41c4ac30634a4a1f1d87a042e37c45Daniel Calegari */
7e9757ba2f41c4ac30634a4a1f1d87a042e37c45Daniel Calegari#ifdef SSL_EXPERIMENTAL_PROXY
7e9757ba2f41c4ac30634a4a1f1d87a042e37c45Daniel Calegari ssl = SSL_new(sc->pSSLProxyCtx);
7e9757ba2f41c4ac30634a4a1f1d87a042e37c45Daniel Calegari#else
7e9757ba2f41c4ac30634a4a1f1d87a042e37c45Daniel Calegari ssl_ctx = SSL_CTX_new(SSLv23_client_method());
7e9757ba2f41c4ac30634a4a1f1d87a042e37c45Daniel Calegari ssl = SSL_new(ssl_ctx);
7e9757ba2f41c4ac30634a4a1f1d87a042e37c45Daniel Calegari#endif
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari if (ssl == NULL) {
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari errmsg = ap_psprintf(r->pool, "SSL proxy new failed (%s): peer %s: %s",
f3a838d9e2932da421939f348a2c3d31ded88989Daniel Calegari cpVHostID, peer, ERR_reason_error_string(ERR_get_error()));
f3a838d9e2932da421939f348a2c3d31ded88989Daniel Calegari ap_ctx_set(fb->ctx, "ssl", NULL);
f3a838d9e2932da421939f348a2c3d31ded88989Daniel Calegari return errmsg;
f3a838d9e2932da421939f348a2c3d31ded88989Daniel Calegari }
f3a838d9e2932da421939f348a2c3d31ded88989Daniel Calegari
f3a838d9e2932da421939f348a2c3d31ded88989Daniel Calegari cpVHostMD5 = ap_md5(r->pool, (unsigned char *)cpVHostID);
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari if (!SSL_set_session_id_context(ssl, (unsigned char *)cpVHostMD5, strlen(cpVHostMD5))) {
f3a838d9e2932da421939f348a2c3d31ded88989Daniel Calegari errmsg = ap_psprintf(r->pool, "Unable to set session id context to `%s': peer %s: %s",
f3a838d9e2932da421939f348a2c3d31ded88989Daniel Calegari cpVHostMD5, peer, ERR_reason_error_string(ERR_get_error()));
f3a838d9e2932da421939f348a2c3d31ded88989Daniel Calegari ap_ctx_set(fb->ctx, "ssl", NULL);
f3a838d9e2932da421939f348a2c3d31ded88989Daniel Calegari return errmsg;
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari }
f3a838d9e2932da421939f348a2c3d31ded88989Daniel Calegari SSL_set_fd(ssl, fb->fd);
f3a838d9e2932da421939f348a2c3d31ded88989Daniel Calegari#ifdef SSL_EXPERIMENTAL_PROXY
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari SSL_set_app_data(ssl, fb->ctx);
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari#endif
7e9757ba2f41c4ac30634a4a1f1d87a042e37c45Daniel Calegari ap_ctx_set(fb->ctx, "ssl", ssl);
7e9757ba2f41c4ac30634a4a1f1d87a042e37c45Daniel Calegari#ifdef SSL_EXPERIMENTAL_PROXY
7e9757ba2f41c4ac30634a4a1f1d87a042e37c45Daniel Calegari ap_ctx_set(fb->ctx, "ssl::proxy::server_rec", r->server);
7e9757ba2f41c4ac30634a4a1f1d87a042e37c45Daniel Calegari ap_ctx_set(fb->ctx, "ssl::proxy::peer", peer);
7e9757ba2f41c4ac30634a4a1f1d87a042e37c45Daniel Calegari ap_ctx_set(fb->ctx, "ssl::proxy::servername", cpVHostID);
7e9757ba2f41c4ac30634a4a1f1d87a042e37c45Daniel Calegari ap_ctx_set(fb->ctx, "ssl::proxy::verifyerror", NULL);
7e9757ba2f41c4ac30634a4a1f1d87a042e37c45Daniel Calegari#endif
7e9757ba2f41c4ac30634a4a1f1d87a042e37c45Daniel Calegari
7e9757ba2f41c4ac30634a4a1f1d87a042e37c45Daniel Calegari /*
f3a838d9e2932da421939f348a2c3d31ded88989Daniel Calegari * Give us a chance to gracefully close the connection
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari */
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari ap_register_cleanup(r->pool, (void *)fb,
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari ssl_ext_mp_close_connection, ssl_ext_mp_close_connection);
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari
f3a838d9e2932da421939f348a2c3d31ded88989Daniel Calegari /*
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari * Establish the SSL connection
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari */
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari if ((rc = SSL_connect(ssl)) <= 0) {
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari#ifdef SSL_EXPERIMENTAL_PROXY
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari if ((cp = (char *)ap_ctx_get(fb->ctx, "ssl::proxy::verifyerror")) != NULL) {
cba1bca86fce751bb0dc758f4a7e43ff95640137Daniel Calegari SSL_set_shutdown(ssl, SSL_RECEIVED_SHUTDOWN);
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari SSL_smart_shutdown(ssl);
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari SSL_free(ssl);
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari ap_ctx_set(fb->ctx, "ssl", NULL);
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari ap_bsetflag(fb, B_EOF|B_EOUT, 1);
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari return NULL;
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari }
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari#endif
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari errmsg = ap_psprintf(r->pool, "SSL proxy connect failed (%s): peer %s: %s",
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari cpVHostID, peer, ERR_reason_error_string(ERR_get_error()));
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari ssl_log(r->server, SSL_LOG_ERROR, errmsg);
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari SSL_free(ssl);
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari ap_ctx_set(fb->ctx, "ssl", NULL);
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari return errmsg;
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari }
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari return NULL;
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari}
f3a838d9e2932da421939f348a2c3d31ded88989Daniel Calegari
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegaristatic void ssl_ext_mp_close_connection(void *_fb)
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari{
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari BUFF *fb = _fb;
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari SSL *ssl;
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari#ifndef SSL_EXPERIMENTAL_PROXY
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari SSL_CTX *ctx;
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari#endif
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari ssl = ap_ctx_get(fb->ctx, "ssl");
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari if (ssl != NULL) {
f3a838d9e2932da421939f348a2c3d31ded88989Daniel Calegari#ifndef SSL_EXPERIMENTAL_PROXY
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari ctx = SSL_get_SSL_CTX(ssl);
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari#endif
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari SSL_set_shutdown(ssl, SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN);
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari SSL_smart_shutdown(ssl);
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari SSL_free(ssl);
f3a838d9e2932da421939f348a2c3d31ded88989Daniel Calegari ap_ctx_set(fb->ctx, "ssl", NULL);
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari#ifndef SSL_EXPERIMENTAL_PROXY
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari if (ctx != NULL)
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari SSL_CTX_free(ctx);
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari#endif
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari }
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari return;
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari}
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegaristatic int ssl_ext_mp_write_host_header(
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari request_rec *r, BUFF *fb, char *host, int port, char *portstr)
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari{
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari if (ap_ctx_get(r->ctx, "ssl::proxy::enabled") == PFALSE)
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari return DECLINED;
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari if (portstr != NULL && port != DEFAULT_HTTPS_PORT) {
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari ap_bvputs(fb, "Host: ", host, ":", portstr, "\r\n", NULL);
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari return OK;
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari }
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari return DECLINED;
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari}
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari#ifdef SSL_EXPERIMENTAL_PROXY
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari/*
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari * Callback for client certificate stuff.
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari * If the remote site sent us a SSLv3 list of acceptable CA's then trawl the
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari * table of client certs and send the first one that matches.
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari */
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegaristatic int ssl_ext_mp_clientcert_cb(SSL *ssl, X509 **x509, EVP_PKEY **pkey)
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari{
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari SSLSrvConfigRec *sc;
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari X509_NAME *xnx;
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari X509_NAME *issuer;
b5c780c06889ceb5c241a6b5da7ef0663e5451caDaniel Calegari X509_INFO *xi;
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari char *peer;
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari char *servername;
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari server_rec *s;
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari ap_ctx *pCtx;
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari STACK_OF(X509_NAME) *sk;
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari STACK_OF(X509_INFO) *pcerts;
f3a838d9e2932da421939f348a2c3d31ded88989Daniel Calegari char *cp;
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari int i, j;
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari pCtx = (ap_ctx *)SSL_get_app_data(ssl);
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari s = ap_ctx_get(pCtx, "ssl::proxy::server_rec");
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari peer = ap_ctx_get(pCtx, "ssl::proxy::peer");
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari servername = ap_ctx_get(pCtx, "ssl::proxy::servername");
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari
f3a838d9e2932da421939f348a2c3d31ded88989Daniel Calegari sc = mySrvConfig(s);
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari pcerts = sc->skProxyClientCerts;
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari ssl_log(s, SSL_LOG_DEBUG,
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari "Proxy client certificate callback: (%s) entered", servername);
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari if ((pcerts == NULL) || (sk_X509_INFO_num(pcerts) <= 0)) {
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari ssl_log(s, SSL_LOG_TRACE,
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari "Proxy client certificate callback: (%s) "
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari "site wanted client certificate but none available",
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari servername);
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari return 0;
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari }
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari sk = SSL_get_client_CA_list(ssl);
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari if ((sk == NULL) || (sk_X509_NAME_num(sk) <= 0)) {
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari /*
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari * remote site didn't send us a list of acceptable CA certs,
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari * so lets send the first one we came across
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari */
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari xi = sk_X509_INFO_value(pcerts, 0);
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari cp = X509_NAME_oneline(X509_get_subject_name(xi->x509), NULL, 0);
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari ssl_log(s, SSL_LOG_DEBUG,
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari "SSL Proxy: (%s) no acceptable CA list, sending %s",
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari servername, cp != NULL ? cp : "-unknown-");
b5c780c06889ceb5c241a6b5da7ef0663e5451caDaniel Calegari free(cp);
b5c780c06889ceb5c241a6b5da7ef0663e5451caDaniel Calegari /* export structures to the caller */
b5c780c06889ceb5c241a6b5da7ef0663e5451caDaniel Calegari *x509 = xi->x509;
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari *pkey = xi->x_pkey->dec_pkey;
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari /* prevent OpenSSL freeing these structures */
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari CRYPTO_add(&((*x509)->references), +1, CRYPTO_LOCK_X509_PKEY);
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari CRYPTO_add(&((*pkey)->references), +1, CRYPTO_LOCK_X509_PKEY);
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari return 1;
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari }
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari for (i = 0; i < sk_X509_NAME_num(sk); i++) {
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari xnx = sk_X509_NAME_value(sk, i);
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari for (j = 0; j < sk_X509_INFO_num(pcerts); j++) {
cebd8658147937d53195664ad8b1e37de1e6f017Daniel Calegari xi = sk_X509_INFO_value(pcerts,j);
issuer = X509_get_issuer_name(xi->x509);
if (X509_NAME_cmp(issuer, xnx) == 0) {
cp = X509_NAME_oneline(X509_get_subject_name(xi->x509), NULL, 0);
ssl_log(s, SSL_LOG_DEBUG, "SSL Proxy: (%s) sending %s",
servername, cp != NULL ? cp : "-unknown-");
free(cp);
/* export structures to the caller */
*x509 = xi->x509;
*pkey = xi->x_pkey->dec_pkey;
/* prevent OpenSSL freeing these structures */
CRYPTO_add(&((*x509)->references), +1, CRYPTO_LOCK_X509_PKEY);
CRYPTO_add(&((*pkey)->references), +1, CRYPTO_LOCK_X509_PKEY);
return 1;
}
}
}
ssl_log(s, SSL_LOG_TRACE,
"Proxy client certificate callback: (%s) "
"no client certificate found!?", servername);
return 0;
}
/*
* This is the verify callback when we are connecting to a remote SSL server
* from the proxy. Information is passed in via the SSL "ctx" app_data
* mechanism. We pass in an Apache context in this field, which contains
* server_rec of the server making the proxy connection from the
* "ssl::proxy::server_rec" context.
*
* The result of the verification is passed back out to SSLERR via the return
* value. We also store the error message in the "proxyverifyfailed" context,
* so the caller of SSL_connect() can log a detailed error message.
*/
static int ssl_ext_mp_verify_cb(int ok, X509_STORE_CTX *ctx)
{
SSLSrvConfigRec *sc;
X509 *xs;
int errnum;
int errdepth;
char *cp, *cp2;
ap_ctx *pCtx;
server_rec *s;
SSL *ssl;
char *peer;
char *servername;
ssl = (SSL *)X509_STORE_CTX_get_app_data(ctx);
pCtx = (ap_ctx *)SSL_get_app_data(ssl);
s = ap_ctx_get(pCtx, "ssl::proxy::server_rec");
peer = ap_ctx_get(pCtx, "ssl::proxy::peer");
servername = ap_ctx_get(pCtx, "ssl::proxy::servername");
sc = mySrvConfig(s);
/*
* Unless stated otherwise by the configuration, we really don't
* care if the verification was okay or not, so lets return now
* before we do anything involving memory or time.
*/
if (sc->bProxyVerify == FALSE)
return ok;
/*
* Get verify ingredients
*/
xs = X509_STORE_CTX_get_current_cert(ctx);
errnum = X509_STORE_CTX_get_error(ctx);
errdepth = X509_STORE_CTX_get_error_depth(ctx);
/*
* Log verification information
*/
cp = X509_NAME_oneline(X509_get_subject_name(xs), NULL, 0);
cp2 = X509_NAME_oneline(X509_get_issuer_name(xs), NULL, 0);
ssl_log(s, SSL_LOG_DEBUG,
"SSL Proxy: (%s) Certificate Verification for remote server %s: "
"depth: %d, subject: %s, issuer: %s",
servername, peer != NULL ? peer : "-unknown-",
errdepth, cp != NULL ? cp : "-unknown-",
cp2 != NULL ? cp2 : "-unknown");
free(cp);
free(cp2);
/*
* If we already know it's not ok, log the real reason
*/
if (!ok) {
ssl_log(s, SSL_LOG_ERROR,
"SSL Proxy: (%s) Certificate Verification failed for %s: "
"Error (%d): %s", servername,
peer != NULL ? peer : "-unknown-",
errnum, X509_verify_cert_error_string(errnum));
ap_ctx_set(pCtx, "ssl::proxy::verifyerror",
(void *)X509_verify_cert_error_string(errnum));
return ok;
}
/*
* Check the depth of the certificate chain
*/
if (sc->nProxyVerifyDepth > 0) {
if (errdepth > sc->nProxyVerifyDepth) {
ssl_log(s, SSL_LOG_ERROR,
"SSL Proxy: (%s) Certificate Verification failed for %s: "
"Certificate Chain too long "
"(chain has %d certificates, but maximum allowed are only %d)",
servername, peer, errdepth, sc->nProxyVerifyDepth);
ap_ctx_set(pCtx, "ssl::proxy::verifyerror",
(void *)X509_verify_cert_error_string(X509_V_ERR_CERT_CHAIN_TOO_LONG));
ok = FALSE;
}
}
/*
* And finally signal OpenSSL the (perhaps changed) state
*/
return (ok);
}
#endif /* SSL_EXPERIMENTAL_PROXY */
#endif /* XXX */