ssl_engine_ext.c revision d86ef5503dcbc38e87c0e03cd3e1f16458cb6323
e8eb2b9d68adc3024eb1aa9899b902ed5a3fb460Christian Maeder/* _ _
e8eb2b9d68adc3024eb1aa9899b902ed5a3fb460Christian Maeder** _ __ ___ ___ __| | ___ ___| | mod_ssl
adea2e45fa61f1097aadc490a0aeaf4831b729ccChristian Maeder** | '_ ` _ \ / _ \ / _` | / __/ __| | Apache Interface to OpenSSL
df11e5eab86d8247f58e301d8f0a2c6ecf4c9541Till Mossakowski** | | | | | | (_) | (_| | \__ \__ \ | www.modssl.org
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder** |_| |_| |_|\___/ \__,_|___|___/___/_| ftp.modssl.org
df11e5eab86d8247f58e301d8f0a2c6ecf4c9541Till Mossakowski** |_____|
97018cf5fa25b494adffd7e9b4e87320dae6bf47Christian Maeder** ssl_engine_ext.c
2eeec5240b424984e3ee26296da1eeab6c6d739eChristian Maeder** Extensions to other Apache parts
df11e5eab86d8247f58e301d8f0a2c6ecf4c9541Till Mossakowski*/
df11e5eab86d8247f58e301d8f0a2c6ecf4c9541Till Mossakowski
f3a94a197960e548ecd6520bb768cb0d547457bbChristian Maeder/* ====================================================================
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder * The Apache Software License, Version 1.1
0095c7efbddd0ffeed6aaf8ec015346be161d819Till Mossakowski *
adea2e45fa61f1097aadc490a0aeaf4831b729ccChristian Maeder * Copyright (c) 2000-2001 The Apache Software Foundation. All rights
df11e5eab86d8247f58e301d8f0a2c6ecf4c9541Till Mossakowski * reserved.
df11e5eab86d8247f58e301d8f0a2c6ecf4c9541Till Mossakowski *
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder * Redistribution and use in source and binary forms, with or without
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder * modification, are permitted provided that the following conditions
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder * are met:
df11e5eab86d8247f58e301d8f0a2c6ecf4c9541Till Mossakowski *
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder * 1. Redistributions of source code must retain the above copyright
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder * notice, this list of conditions and the following disclaimer.
df11e5eab86d8247f58e301d8f0a2c6ecf4c9541Till Mossakowski *
df11e5eab86d8247f58e301d8f0a2c6ecf4c9541Till Mossakowski * 2. Redistributions in binary form must reproduce the above copyright
df11e5eab86d8247f58e301d8f0a2c6ecf4c9541Till Mossakowski * notice, this list of conditions and the following disclaimer in
df11e5eab86d8247f58e301d8f0a2c6ecf4c9541Till Mossakowski * the documentation and/or other materials provided with the
df11e5eab86d8247f58e301d8f0a2c6ecf4c9541Till Mossakowski * distribution.
df11e5eab86d8247f58e301d8f0a2c6ecf4c9541Till Mossakowski *
ad270004874ce1d0697fb30d7309f180553bb315Christian Maeder * 3. The end-user documentation included with the redistribution,
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder * if any, must include the following acknowledgment:
cf31aaf25d0fe96b0578755e7ee18b732e337343Christian Maeder * "This product includes software developed by the
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder * Apache Software Foundation (http://www.apache.org/)."
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder * Alternately, this acknowledgment may appear in the software itself,
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder * if and wherever such third-party acknowledgments normally appear.
df11e5eab86d8247f58e301d8f0a2c6ecf4c9541Till Mossakowski *
df11e5eab86d8247f58e301d8f0a2c6ecf4c9541Till Mossakowski * 4. The names "Apache" and "Apache Software Foundation" must
df11e5eab86d8247f58e301d8f0a2c6ecf4c9541Till Mossakowski * not be used to endorse or promote products derived from this
df11e5eab86d8247f58e301d8f0a2c6ecf4c9541Till Mossakowski * software without prior written permission. For written
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder * permission, please contact apache@apache.org.
df11e5eab86d8247f58e301d8f0a2c6ecf4c9541Till Mossakowski *
adea2e45fa61f1097aadc490a0aeaf4831b729ccChristian Maeder * 5. Products derived from this software may not be called "Apache",
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder * nor may "Apache" appear in their name, without prior written
df11e5eab86d8247f58e301d8f0a2c6ecf4c9541Till Mossakowski * permission of the Apache Software Foundation.
df11e5eab86d8247f58e301d8f0a2c6ecf4c9541Till Mossakowski *
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
df11e5eab86d8247f58e301d8f0a2c6ecf4c9541Till Mossakowski * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
df11e5eab86d8247f58e301d8f0a2c6ecf4c9541Till Mossakowski * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
df476f3bf7038997303a1760a9c1ce09be40a05eChristian Maeder * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
df11e5eab86d8247f58e301d8f0a2c6ecf4c9541Till Mossakowski * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
df11e5eab86d8247f58e301d8f0a2c6ecf4c9541Till Mossakowski * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
df11e5eab86d8247f58e301d8f0a2c6ecf4c9541Till Mossakowski * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
df11e5eab86d8247f58e301d8f0a2c6ecf4c9541Till Mossakowski * SUCH DAMAGE.
df11e5eab86d8247f58e301d8f0a2c6ecf4c9541Till Mossakowski * ====================================================================
df11e5eab86d8247f58e301d8f0a2c6ecf4c9541Till Mossakowski */
df11e5eab86d8247f58e301d8f0a2c6ecf4c9541Till Mossakowski /* ``Only those who attempt the absurd
df11e5eab86d8247f58e301d8f0a2c6ecf4c9541Till Mossakowski can achieve the impossible.''
df11e5eab86d8247f58e301d8f0a2c6ecf4c9541Till Mossakowski -- Unknown */
df11e5eab86d8247f58e301d8f0a2c6ecf4c9541Till Mossakowski#include "mod_ssl.h"
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder/* _________________________________________________________________
adea2e45fa61f1097aadc490a0aeaf4831b729ccChristian Maeder**
df11e5eab86d8247f58e301d8f0a2c6ecf4c9541Till Mossakowski** SSL Extensions
df11e5eab86d8247f58e301d8f0a2c6ecf4c9541Till Mossakowski** _________________________________________________________________
adea2e45fa61f1097aadc490a0aeaf4831b729ccChristian Maeder*/
df11e5eab86d8247f58e301d8f0a2c6ecf4c9541Till Mossakowski
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maederstatic void ssl_ext_mlc_register(void);
df11e5eab86d8247f58e301d8f0a2c6ecf4c9541Till Mossakowskistatic void ssl_ext_mlc_unregister(void);
df11e5eab86d8247f58e301d8f0a2c6ecf4c9541Till Mossakowskistatic void ssl_ext_mr_register(void);
df11e5eab86d8247f58e301d8f0a2c6ecf4c9541Till Mossakowskistatic void ssl_ext_mr_unregister(void);
df11e5eab86d8247f58e301d8f0a2c6ecf4c9541Till Mossakowskistatic void ssl_ext_mp_register(void);
df11e5eab86d8247f58e301d8f0a2c6ecf4c9541Till Mossakowskistatic void ssl_ext_mp_unregister(void);
df11e5eab86d8247f58e301d8f0a2c6ecf4c9541Till Mossakowskistatic void ssl_ext_ms_register(void);
df11e5eab86d8247f58e301d8f0a2c6ecf4c9541Till Mossakowskistatic void ssl_ext_ms_unregister(void);
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder
df11e5eab86d8247f58e301d8f0a2c6ecf4c9541Till Mossakowskivoid ssl_ext_register(void)
df11e5eab86d8247f58e301d8f0a2c6ecf4c9541Till Mossakowski{
df11e5eab86d8247f58e301d8f0a2c6ecf4c9541Till Mossakowski ssl_ext_mlc_register();
adea2e45fa61f1097aadc490a0aeaf4831b729ccChristian Maeder ssl_ext_mr_register();
df11e5eab86d8247f58e301d8f0a2c6ecf4c9541Till Mossakowski ssl_ext_mp_register();
adea2e45fa61f1097aadc490a0aeaf4831b729ccChristian Maeder ssl_ext_ms_register();
c683dfeebc4a9307ca64adda2114205bb681d62aChristian Maeder return;
df11e5eab86d8247f58e301d8f0a2c6ecf4c9541Till Mossakowski}
df11e5eab86d8247f58e301d8f0a2c6ecf4c9541Till Mossakowski
df11e5eab86d8247f58e301d8f0a2c6ecf4c9541Till Mossakowskivoid ssl_ext_unregister(void)
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder{
df11e5eab86d8247f58e301d8f0a2c6ecf4c9541Till Mossakowski ssl_ext_mlc_unregister();
adea2e45fa61f1097aadc490a0aeaf4831b729ccChristian Maeder ssl_ext_mr_unregister();
b1f59a4ea7c96f4c03a4d7cfcb9c5e66871cfbbbChristian Maeder ssl_ext_mp_unregister();
df11e5eab86d8247f58e301d8f0a2c6ecf4c9541Till Mossakowski ssl_ext_ms_unregister();
df11e5eab86d8247f58e301d8f0a2c6ecf4c9541Till Mossakowski return;
df11e5eab86d8247f58e301d8f0a2c6ecf4c9541Till Mossakowski}
df11e5eab86d8247f58e301d8f0a2c6ecf4c9541Till Mossakowski
df11e5eab86d8247f58e301d8f0a2c6ecf4c9541Till Mossakowski/* _________________________________________________________________
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder**
df11e5eab86d8247f58e301d8f0a2c6ecf4c9541Till Mossakowski** SSL Extension to mod_log_config
df11e5eab86d8247f58e301d8f0a2c6ecf4c9541Till Mossakowski** _________________________________________________________________
df11e5eab86d8247f58e301d8f0a2c6ecf4c9541Till Mossakowski*/
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder
df11e5eab86d8247f58e301d8f0a2c6ecf4c9541Till Mossakowskistatic char *ssl_ext_mlc_log_c(request_rec *r, char *a);
df11e5eab86d8247f58e301d8f0a2c6ecf4c9541Till Mossakowskistatic char *ssl_ext_mlc_log_x(request_rec *r, char *a);
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder
df11e5eab86d8247f58e301d8f0a2c6ecf4c9541Till Mossakowski/*
df11e5eab86d8247f58e301d8f0a2c6ecf4c9541Till Mossakowski * register us for the mod_log_config function registering phase
df11e5eab86d8247f58e301d8f0a2c6ecf4c9541Till Mossakowski * to establish %{...}c and to be able to expand %{...}x variables.
df11e5eab86d8247f58e301d8f0a2c6ecf4c9541Till Mossakowski */
df11e5eab86d8247f58e301d8f0a2c6ecf4c9541Till Mossakowskistatic void ssl_ext_mlc_register(void)
a98fd29a06e80e447af26d898044c23497adbc73Mihai Codescu{
a98fd29a06e80e447af26d898044c23497adbc73Mihai Codescu ap_hook_register("ap::mod_log_config::log_c",
a98fd29a06e80e447af26d898044c23497adbc73Mihai Codescu ssl_ext_mlc_log_c, AP_HOOK_NOCTX);
df11e5eab86d8247f58e301d8f0a2c6ecf4c9541Till Mossakowski ap_hook_register("ap::mod_log_config::log_x",
df11e5eab86d8247f58e301d8f0a2c6ecf4c9541Till Mossakowski ssl_ext_mlc_log_x, AP_HOOK_NOCTX);
df11e5eab86d8247f58e301d8f0a2c6ecf4c9541Till Mossakowski return;
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder}
df11e5eab86d8247f58e301d8f0a2c6ecf4c9541Till Mossakowski
df11e5eab86d8247f58e301d8f0a2c6ecf4c9541Till Mossakowskistatic void ssl_ext_mlc_unregister(void)
df11e5eab86d8247f58e301d8f0a2c6ecf4c9541Till Mossakowski{
df11e5eab86d8247f58e301d8f0a2c6ecf4c9541Till Mossakowski ap_hook_unregister("ap::mod_log_config::log_c",
df11e5eab86d8247f58e301d8f0a2c6ecf4c9541Till Mossakowski ssl_ext_mlc_log_c);
df11e5eab86d8247f58e301d8f0a2c6ecf4c9541Till Mossakowski ap_hook_unregister("ap::mod_log_config::log_x",
df11e5eab86d8247f58e301d8f0a2c6ecf4c9541Till Mossakowski ssl_ext_mlc_log_x);
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder return;
df11e5eab86d8247f58e301d8f0a2c6ecf4c9541Till Mossakowski}
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder
df11e5eab86d8247f58e301d8f0a2c6ecf4c9541Till Mossakowski/*
df11e5eab86d8247f58e301d8f0a2c6ecf4c9541Till Mossakowski * implement the %{..}c log function
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder * (we are the only function)
df11e5eab86d8247f58e301d8f0a2c6ecf4c9541Till Mossakowski */
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maederstatic char *ssl_ext_mlc_log_c(request_rec *r, char *a)
df11e5eab86d8247f58e301d8f0a2c6ecf4c9541Till Mossakowski{
df11e5eab86d8247f58e301d8f0a2c6ecf4c9541Till Mossakowski char *result;
df11e5eab86d8247f58e301d8f0a2c6ecf4c9541Till Mossakowski
df11e5eab86d8247f58e301d8f0a2c6ecf4c9541Till Mossakowski if (ap_ctx_get(r->connection->client->ctx, "ssl") == NULL)
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder return NULL;
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder result = NULL;
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder if (strEQ(a, "version"))
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder result = ssl_var_lookup(r->pool, r->server, r->connection, r, "SSL_PROTOCOL");
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder else if (strEQ(a, "cipher"))
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder result = ssl_var_lookup(r->pool, r->server, r->connection, r, "SSL_CIPHER");
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder else if (strEQ(a, "subjectdn") || strEQ(a, "clientcert"))
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder result = ssl_var_lookup(r->pool, r->server, r->connection, r, "SSL_CLIENT_S_DN");
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder else if (strEQ(a, "issuerdn") || strEQ(a, "cacert"))
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder result = ssl_var_lookup(r->pool, r->server, r->connection, r, "SSL_CLIENT_I_DN");
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder else if (strEQ(a, "errcode"))
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder result = "-";
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder else if (strEQ(a, "errstr"))
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder result = ap_ctx_get(r->connection->client->ctx, "ssl::verify::error");
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder if (result != NULL && result[0] == NUL)
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder result = NULL;
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder return result;
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder}
a98fd29a06e80e447af26d898044c23497adbc73Mihai Codescu
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder/*
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder * extend the implementation of the %{..}x log function
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder * (there can be more functions)
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder */
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maederstatic char *ssl_ext_mlc_log_x(request_rec *r, char *a)
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder{
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder char *result;
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder result = NULL;
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder if (ap_ctx_get(r->connection->client->ctx, "ssl") != NULL)
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder result = ssl_var_lookup(r->pool, r->server, r->connection, r, a);
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder if (result != NULL && result[0] == NUL)
23e0b003dd27c804487db4d3a9fc8ff2f452cb77Christian Maeder result = NULL;
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder return result;
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder}
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder/* _________________________________________________________________
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder**
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder** SSL Extension to mod_rewrite
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder** _________________________________________________________________
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder*/
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maederstatic char *ssl_ext_mr_lookup_variable(request_rec *r, char *var);
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder/*
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder * register us for the mod_rewrite lookup_variable() function
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder */
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maederstatic void ssl_ext_mr_register(void)
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder{
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder ap_hook_register("ap::mod_rewrite::lookup_variable",
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder ssl_ext_mr_lookup_variable, AP_HOOK_NOCTX);
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder return;
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder}
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maederstatic void ssl_ext_mr_unregister(void)
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder{
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder ap_hook_unregister("ap::mod_rewrite::lookup_variable",
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder ssl_ext_mr_lookup_variable);
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder return;
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder}
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maederstatic char *ssl_ext_mr_lookup_variable(request_rec *r, char *var)
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder{
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder char *val;
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder val = ssl_var_lookup(r->pool, r->server, r->connection, r, var);
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder if (val[0] == NUL)
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder val = NULL;
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder return val;
e8eb2b9d68adc3024eb1aa9899b902ed5a3fb460Christian Maeder}
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder
a98fd29a06e80e447af26d898044c23497adbc73Mihai Codescu/* _________________________________________________________________
a98fd29a06e80e447af26d898044c23497adbc73Mihai Codescu**
a98fd29a06e80e447af26d898044c23497adbc73Mihai Codescu** SSL Extension to mod_proxy
c18a07fe36512679e66faa59274bb273e735738aMihai Codescu** _________________________________________________________________
da955132262baab309a50fdffe228c9efe68251dCui Jian*/
c18a07fe36512679e66faa59274bb273e735738aMihai Codescu
c18a07fe36512679e66faa59274bb273e735738aMihai Codescustatic int ssl_ext_mp_canon(request_rec *, char *);
da955132262baab309a50fdffe228c9efe68251dCui Jianstatic int ssl_ext_mp_handler(request_rec *, void *, char *, char *, int, char *);
c18a07fe36512679e66faa59274bb273e735738aMihai Codescustatic int ssl_ext_mp_set_destport(request_rec *);
da955132262baab309a50fdffe228c9efe68251dCui Jianstatic char *ssl_ext_mp_new_connection(request_rec *, BUFF *, char *);
c18a07fe36512679e66faa59274bb273e735738aMihai Codescustatic void ssl_ext_mp_close_connection(void *);
c18a07fe36512679e66faa59274bb273e735738aMihai Codescustatic int ssl_ext_mp_write_host_header(request_rec *, BUFF *, char *, int, char *);
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder#ifdef SSL_EXPERIMENTAL_PROXY
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maederstatic void ssl_ext_mp_init(server_rec *, pool *);
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maederstatic int ssl_ext_mp_verify_cb(int, X509_STORE_CTX *);
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maederstatic int ssl_ext_mp_clientcert_cb(SSL *, X509 **, EVP_PKEY **);
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder#endif
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder
cd6e5706893519bfcf24539afa252fcbed5097ddKlaus Luettich/*
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder * register us ...
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder */
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maederstatic void ssl_ext_mp_register(void)
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder{
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder#ifdef SSL_EXPERIMENTAL_PROXY
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder ap_hook_register("ap::mod_proxy::init",
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder ssl_ext_mp_init, AP_HOOK_NOCTX);
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder#endif
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder ap_hook_register("ap::mod_proxy::canon",
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder ssl_ext_mp_canon, AP_HOOK_NOCTX);
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder ap_hook_register("ap::mod_proxy::handler",
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder ssl_ext_mp_handler, AP_HOOK_NOCTX);
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder ap_hook_register("ap::mod_proxy::http::handler::set_destport",
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder ssl_ext_mp_set_destport, AP_HOOK_NOCTX);
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder ap_hook_register("ap::mod_proxy::http::handler::new_connection",
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder ssl_ext_mp_new_connection, AP_HOOK_NOCTX);
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder ap_hook_register("ap::mod_proxy::http::handler::write_host_header",
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder ssl_ext_mp_write_host_header, AP_HOOK_NOCTX);
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder return;
e8eb2b9d68adc3024eb1aa9899b902ed5a3fb460Christian Maeder}
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maederstatic void ssl_ext_mp_unregister(void)
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder{
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder#ifdef SSL_EXPERIMENTAL_PROXY
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder ap_hook_unregister("ap::mod_proxy::init", ssl_ext_mp_init);
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder#endif
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder ap_hook_unregister("ap::mod_proxy::canon", ssl_ext_mp_canon);
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder ap_hook_unregister("ap::mod_proxy::handler", ssl_ext_mp_handler);
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder ap_hook_unregister("ap::mod_proxy::http::handler::set_destport",
cd6e5706893519bfcf24539afa252fcbed5097ddKlaus Luettich ssl_ext_mp_set_destport);
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder ap_hook_unregister("ap::mod_proxy::http::handler::new_connection",
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder ssl_ext_mp_new_connection);
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder ap_hook_unregister("ap::mod_proxy::http::handler::write_host_header",
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder ssl_ext_mp_write_host_header);
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder return;
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder}
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder/*
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder * SSL proxy initialization
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder */
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder#ifdef SSL_EXPERIMENTAL_PROXY
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maederstatic void ssl_ext_mp_init(server_rec *s, pool *p)
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder{
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder SSLSrvConfigRec *sc;
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder char *cpVHostID;
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder int nVerify;
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder SSL_CTX *ctx;
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder char *cp;
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder STACK_OF(X509_INFO) *sk;
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder /*
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder * Initialize each virtual server
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder */
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder ERR_clear_error();
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder for (; s != NULL; s = s->next) {
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder sc = mySrvConfig(s);
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder cpVHostID = ssl_util_vhostid(p, s);
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder if (sc->bProxyVerify == UNSET)
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder sc->bProxyVerify = FALSE;
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder /*
a98fd29a06e80e447af26d898044c23497adbc73Mihai Codescu * Create new SSL context and configure callbacks
a98fd29a06e80e447af26d898044c23497adbc73Mihai Codescu */
a98fd29a06e80e447af26d898044c23497adbc73Mihai Codescu if (sc->nProxyProtocol == SSL_PROTOCOL_NONE) {
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder ssl_log(s, SSL_LOG_ERROR,
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder "Init: (%s) No Proxy SSL protocols available [hint: SSLProxyProtocol]",
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder cpVHostID);
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder ssl_die();
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder }
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder cp = ap_pstrcat(p, (sc->nProxyProtocol & SSL_PROTOCOL_SSLV2 ? "SSLv2, " : ""),
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder (sc->nProxyProtocol & SSL_PROTOCOL_SSLV3 ? "SSLv3, " : ""),
a98fd29a06e80e447af26d898044c23497adbc73Mihai Codescu (sc->nProxyProtocol & SSL_PROTOCOL_TLSV1 ? "TLSv1, " : ""), NULL);
a98fd29a06e80e447af26d898044c23497adbc73Mihai Codescu cp[strlen(cp)-2] = NUL;
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder ssl_log(s, SSL_LOG_TRACE,
a98fd29a06e80e447af26d898044c23497adbc73Mihai Codescu "Init: (%s) Creating new proxy SSL context (protocols: %s)",
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder cpVHostID, cp);
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder if (sc->nProxyProtocol == SSL_PROTOCOL_SSLV2)
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder ctx = SSL_CTX_new(SSLv2_client_method()); /* only SSLv2 is left */
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder else
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder ctx = SSL_CTX_new(SSLv23_client_method()); /* be more flexible */
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder if (ctx == NULL) {
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder ssl_log(s, SSL_LOG_ERROR|SSL_ADD_SSLERR,
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder "Init: (%s) Unable to create SSL Proxy context", cpVHostID);
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder ssl_die();
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder }
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder sc->pSSLProxyCtx = ctx;
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder SSL_CTX_set_options(ctx, SSL_OP_ALL);
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder if (!(sc->nProxyProtocol & SSL_PROTOCOL_SSLV2))
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2);
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder if (!(sc->nProxyProtocol & SSL_PROTOCOL_SSLV3))
da955132262baab309a50fdffe228c9efe68251dCui Jian SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv3);
c18a07fe36512679e66faa59274bb273e735738aMihai Codescu if (!(sc->nProxyProtocol & SSL_PROTOCOL_TLSV1))
da955132262baab309a50fdffe228c9efe68251dCui Jian SSL_CTX_set_options(ctx, SSL_OP_NO_TLSv1);
da955132262baab309a50fdffe228c9efe68251dCui Jian
da955132262baab309a50fdffe228c9efe68251dCui Jian if (sc->szProxyClientCertificateFile || sc->szProxyClientCertificatePath) {
c18a07fe36512679e66faa59274bb273e735738aMihai Codescu sk = sk_X509_INFO_new_null();
c18a07fe36512679e66faa59274bb273e735738aMihai Codescu if (sc->szProxyClientCertificateFile)
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder SSL_load_CrtAndKeyInfo_file(p, sk, sc->szProxyClientCertificateFile);
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder if (sc->szProxyClientCertificatePath)
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder SSL_load_CrtAndKeyInfo_path(p, sk, sc->szProxyClientCertificatePath);
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder ssl_log(s, SSL_LOG_TRACE, "Init: (%s) loaded %d client certs for SSL proxy",
a98fd29a06e80e447af26d898044c23497adbc73Mihai Codescu cpVHostID, sk_X509_INFO_num(sk));
a98fd29a06e80e447af26d898044c23497adbc73Mihai Codescu if (sk_X509_INFO_num(sk) > 0) {
a98fd29a06e80e447af26d898044c23497adbc73Mihai Codescu SSL_CTX_set_client_cert_cb(ctx, ssl_ext_mp_clientcert_cb);
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder sc->skProxyClientCerts = sk;
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder }
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder }
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder /*
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder * Calculate OpenSSL verify type for verifying the remote server
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder * certificate. We either verify it against our list of CA's, or don't
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder * bother at all.
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder */
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder nVerify = SSL_VERIFY_NONE;
e8eb2b9d68adc3024eb1aa9899b902ed5a3fb460Christian Maeder if (sc->bProxyVerify)
e8eb2b9d68adc3024eb1aa9899b902ed5a3fb460Christian Maeder nVerify |= SSL_VERIFY_PEER;
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder if ( nVerify & SSL_VERIFY_PEER
e8eb2b9d68adc3024eb1aa9899b902ed5a3fb460Christian Maeder && sc->szProxyCACertificateFile == NULL
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder && sc->szProxyCACertificatePath == NULL) {
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder ssl_log(s, SSL_LOG_ERROR,
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder "Init: (%s) SSLProxyVerify set to On but no CA certificates configured",
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder cpVHostID);
09b431a868c79a92ae7c9bd141565f43f9034144Christian Maeder ssl_die();
cd6e5706893519bfcf24539afa252fcbed5097ddKlaus Luettich }
cd6e5706893519bfcf24539afa252fcbed5097ddKlaus Luettich if ( nVerify & SSL_VERIFY_NONE
cd6e5706893519bfcf24539afa252fcbed5097ddKlaus Luettich && ( sc->szProxyCACertificateFile != NULL
cd6e5706893519bfcf24539afa252fcbed5097ddKlaus Luettich || sc->szProxyCACertificatePath != NULL)) {
ssl_log(s, SSL_LOG_WARN,
"init: (%s) CA certificates configured but ignored because SSLProxyVerify is Off",
cpVHostID);
}
SSL_CTX_set_verify(ctx, nVerify, ssl_ext_mp_verify_cb);
/*
* Enable session caching. We can safely use the same cache
* as used for communicating with the other clients.
*/
SSL_CTX_sess_set_new_cb(sc->pSSLProxyCtx, ssl_callback_NewSessionCacheEntry);
SSL_CTX_sess_set_get_cb(sc->pSSLProxyCtx, ssl_callback_GetSessionCacheEntry);
SSL_CTX_sess_set_remove_cb(sc->pSSLProxyCtx, ssl_callback_DelSessionCacheEntry);
/*
* Configure SSL Cipher Suite
*/
ssl_log(s, SSL_LOG_TRACE,
"Init: (%s) Configuring permitted SSL ciphers for SSL proxy", cpVHostID);
if (sc->szProxyCipherSuite != NULL) {
if (!SSL_CTX_set_cipher_list(sc->pSSLProxyCtx, sc->szProxyCipherSuite)) {
ssl_log(s, SSL_LOG_ERROR|SSL_ADD_SSLERR,
"Init: (%s) Unable to configure permitted SSL ciphers for SSL Proxy",
cpVHostID);
ssl_die();
}
}
/*
* Configure Client Authentication details
*/
if (sc->szProxyCACertificateFile != NULL || sc->szProxyCACertificatePath != NULL) {
ssl_log(s, SSL_LOG_DEBUG,
"Init: (%s) Configuring client verification locations for SSL Proxy",
cpVHostID);
if (!SSL_CTX_load_verify_locations(sc->pSSLProxyCtx,
sc->szProxyCACertificateFile,
sc->szProxyCACertificatePath)) {
ssl_log(s, SSL_LOG_ERROR|SSL_ADD_SSLERR,
"Init: (%s) Unable to configure SSL verify locations for SSL proxy",
cpVHostID);
ssl_die();
}
}
}
return;
}
#endif /* SSL_EXPERIMENTAL_PROXY */
static int ssl_ext_mp_canon(request_rec *r, char *url)
{
int rc;
if (strcEQn(url, "https:", 6)) {
rc = OK;
ap_hook_call("ap::mod_proxy::http::canon",
&rc, r, url+6, "https", DEFAULT_HTTPS_PORT);
return rc;
}
return DECLINED;
}
static int ssl_ext_mp_handler(
request_rec *r, void *cr, char *url, char *proxyhost, int proxyport, char *protocol)
{
int rc;
if (strcEQ(protocol, "https")) {
ap_ctx_set(r->ctx, "ssl::proxy::enabled", PTRUE);
ap_hook_call("ap::mod_proxy::http::handler",
&rc, r, cr, url, proxyhost, proxyport);
return rc;
}
else {
ap_ctx_set(r->ctx, "ssl::proxy::enabled", PFALSE);
}
return DECLINED;
}
static int ssl_ext_mp_set_destport(request_rec *r)
{
if (ap_ctx_get(r->ctx, "ssl::proxy::enabled") == PTRUE)
return DEFAULT_HTTPS_PORT;
else
return DEFAULT_HTTP_PORT;
}
static char *ssl_ext_mp_new_connection(request_rec *r, BUFF *fb, char *peer)
{
#ifndef SSL_EXPERIMENTAL_PROXY
SSL_CTX *ssl_ctx;
#endif
SSL *ssl;
char *errmsg;
int rc;
char *cpVHostID;
char *cpVHostMD5;
#ifdef SSL_EXPERIMENTAL_PROXY
SSLSrvConfigRec *sc;
char *cp;
#endif
if (ap_ctx_get(r->ctx, "ssl::proxy::enabled") == PFALSE)
return NULL;
/*
* Find context
*/
#ifdef SSL_EXPERIMENTAL_PROXY
sc = mySrvConfig(r->server);
#endif
cpVHostID = ssl_util_vhostid(r->pool, r->server);
/*
* Create a SSL context and handle
*/
#ifdef SSL_EXPERIMENTAL_PROXY
ssl = SSL_new(sc->pSSLProxyCtx);
#else
ssl_ctx = SSL_CTX_new(SSLv23_client_method());
ssl = SSL_new(ssl_ctx);
#endif
if (ssl == NULL) {
errmsg = ap_psprintf(r->pool, "SSL proxy new failed (%s): peer %s: %s",
cpVHostID, peer, ERR_reason_error_string(ERR_get_error()));
ap_ctx_set(fb->ctx, "ssl", NULL);
return errmsg;
}
SSL_clear(ssl);
cpVHostMD5 = ap_md5(r->pool, (unsigned char *)cpVHostID);
if (!SSL_set_session_id_context(ssl, (unsigned char *)cpVHostMD5, strlen(cpVHostMD5))) {
errmsg = ap_psprintf(r->pool, "Unable to set session id context to `%s': peer %s: %s",
cpVHostMD5, peer, ERR_reason_error_string(ERR_get_error()));
ap_ctx_set(fb->ctx, "ssl", NULL);
return errmsg;
}
SSL_set_fd(ssl, fb->fd);
#ifdef SSL_EXPERIMENTAL_PROXY
SSL_set_app_data(ssl, fb->ctx);
#endif
ap_ctx_set(fb->ctx, "ssl", ssl);
#ifdef SSL_EXPERIMENTAL_PROXY
ap_ctx_set(fb->ctx, "ssl::proxy::server_rec", r->server);
ap_ctx_set(fb->ctx, "ssl::proxy::peer", peer);
ap_ctx_set(fb->ctx, "ssl::proxy::servername", cpVHostID);
ap_ctx_set(fb->ctx, "ssl::proxy::verifyerror", NULL);
#endif
/*
* Give us a chance to gracefully close the connection
*/
ap_register_cleanup(r->pool, (void *)fb,
ssl_ext_mp_close_connection, ssl_ext_mp_close_connection);
/*
* Establish the SSL connection
*/
if ((rc = SSL_connect(ssl)) <= 0) {
#ifdef SSL_EXPERIMENTAL_PROXY
if ((cp = (char *)ap_ctx_get(fb->ctx, "ssl::proxy::verifyerror")) != NULL) {
SSL_set_shutdown(ssl, SSL_RECEIVED_SHUTDOWN);
SSL_smart_shutdown(ssl);
SSL_free(ssl);
ap_ctx_set(fb->ctx, "ssl", NULL);
ap_bsetflag(fb, B_EOF|B_EOUT, 1);
return NULL;
}
#endif
errmsg = ap_psprintf(r->pool, "SSL proxy connect failed (%s): peer %s: %s",
cpVHostID, peer, ERR_reason_error_string(ERR_get_error()));
ssl_log(r->server, SSL_LOG_ERROR, errmsg);
SSL_free(ssl);
ap_ctx_set(fb->ctx, "ssl", NULL);
return errmsg;
}
return NULL;
}
static void ssl_ext_mp_close_connection(void *_fb)
{
BUFF *fb = _fb;
SSL *ssl;
#ifndef SSL_EXPERIMENTAL_PROXY
SSL_CTX *ctx;
#endif
ssl = ap_ctx_get(fb->ctx, "ssl");
if (ssl != NULL) {
#ifndef SSL_EXPERIMENTAL_PROXY
ctx = SSL_get_SSL_CTX(ssl);
#endif
SSL_set_shutdown(ssl, SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN);
SSL_smart_shutdown(ssl);
SSL_free(ssl);
ap_ctx_set(fb->ctx, "ssl", NULL);
#ifndef SSL_EXPERIMENTAL_PROXY
if (ctx != NULL)
SSL_CTX_free(ctx);
#endif
}
return;
}
static int ssl_ext_mp_write_host_header(
request_rec *r, BUFF *fb, char *host, int port, char *portstr)
{
if (ap_ctx_get(r->ctx, "ssl::proxy::enabled") == PFALSE)
return DECLINED;
if (portstr != NULL && port != DEFAULT_HTTPS_PORT) {
ap_bvputs(fb, "Host: ", host, ":", portstr, "\r\n", NULL);
return OK;
}
return DECLINED;
}
#ifdef SSL_EXPERIMENTAL_PROXY
/*
* Callback for client certificate stuff.
* If the remote site sent us a SSLv3 list of acceptable CA's then trawl the
* table of client certs and send the first one that matches.
*/
static int ssl_ext_mp_clientcert_cb(SSL *ssl, X509 **x509, EVP_PKEY **pkey)
{
SSLSrvConfigRec *sc;
X509_NAME *xnx;
X509_NAME *issuer;
X509_INFO *xi;
char *peer;
char *servername;
server_rec *s;
ap_ctx *pCtx;
STACK_OF(X509_NAME) *sk;
STACK_OF(X509_INFO) *pcerts;
char *cp;
int i, j;
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);
pcerts = sc->skProxyClientCerts;
ssl_log(s, SSL_LOG_DEBUG,
"Proxy client certificate callback: (%s) entered", servername);
if ((pcerts == NULL) || (sk_X509_INFO_num(pcerts) <= 0)) {
ssl_log(s, SSL_LOG_TRACE,
"Proxy client certificate callback: (%s) "
"site wanted client certificate but none available",
servername);
return 0;
}
sk = SSL_get_client_CA_list(ssl);
if ((sk == NULL) || (sk_X509_NAME_num(sk) <= 0)) {
/*
* remote site didn't send us a list of acceptable CA certs,
* so lets send the first one we came across
*/
xi = sk_X509_INFO_value(pcerts, 0);
cp = X509_NAME_oneline(X509_get_subject_name(xi->x509), NULL, 0);
ssl_log(s, SSL_LOG_DEBUG,
"SSL Proxy: (%s) no acceptable CA list, 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;
}
for (i = 0; i < sk_X509_NAME_num(sk); i++) {
xnx = sk_X509_NAME_value(sk, i);
for (j = 0; j < sk_X509_INFO_num(pcerts); j++) {
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 */
/* _________________________________________________________________
**
** SSL Extension to mod_status
** _________________________________________________________________
*/
static void ssl_ext_ms_display(request_rec *, int, int);
static void ssl_ext_ms_register(void)
{
ap_hook_register("ap::mod_status::display", ssl_ext_ms_display, AP_HOOK_NOCTX);
return;
}
static void ssl_ext_ms_unregister(void)
{
ap_hook_unregister("ap::mod_status::display", ssl_ext_ms_display);
return;
}
static void ssl_ext_ms_display_cb(char *str, void *_r)
{
request_rec *r = (request_rec *)_r;
if (str != NULL)
ap_rputs(str, r);
return;
}
static void ssl_ext_ms_display(request_rec *r, int no_table_report, int short_report)
{
SSLSrvConfigRec *sc = mySrvConfig(r->server);
if (sc == NULL)
return;
if (short_report)
return;
ap_rputs("<hr>\n", r);
ap_rputs("<table cellspacing=0 cellpadding=0>\n", r);
ap_rputs("<tr><td bgcolor=\"#000000\">\n", r);
ap_rputs("<b><font color=\"#ffffff\" face=\"Arial,Helvetica\">SSL/TLS Session Cache Status:</font></b>\r", r);
ap_rputs("</td></tr>\n", r);
ap_rputs("<tr><td bgcolor=\"#ffffff\">\n", r);
ssl_scache_status(r->server, r->pool, ssl_ext_ms_display_cb, r);
ap_rputs("</td></tr>\n", r);
ap_rputs("</table>\n", r);
return;
}