dnl ## SUCH DAMAGE.
dnl ## ====================================================================
+AC_DEFUN([CHECK_DISTCACHE], [
+ AC_MSG_CHECKING(whether Distcache is required)
+ ap_ssltk_dc="no"
+ tmp_nomessage=""
+ tmp_forced="no"
+ AC_ARG_ENABLE(distcache,
+ APACHE_HELP_STRING(--enable-distcache,Select distcache support in mod_ssl),
+ ap_ssltk_dc="$enableval"
+ tmp_nomessage=""
+ tmp_forced="yes"
+ if test "x$ap_ssltk_dc" = "x"; then
+ ap_ssltk_dc="yes"
+ dnl our "error"s become "tests revealed that..."
+ tmp_forced="no"
+ fi
+ if test "$ap_ssltk_dc" != "yes" -a "$ap_ssltk_dc" != "no"; then
+ tmp_nomessage="--enable-distcache had illegal syntax - disabling"
+ ap_ssltk_dc="no"
+ fi)
+ if test "$tmp_forced" = "no"; then
+ AC_MSG_RESULT($ap_ssltk_dc (default))
+ else
+ AC_MSG_RESULT($ap_ssltk_dc (specified))
+ fi
+ if test "$tmp_forced" = "yes" -a "x$ap_ssltk_dc" = "xno" -a "x$tmp_nomessage" != "x"; then
+ AC_MSG_ERROR(distcache support failed: $tmp_nomessage)
+ fi
+ if test "$ap_ssltk_dc" = "yes"; then
+ AC_CHECK_HEADER(
+ [distcache/dc_client.h],
+ [],
+ [tmp_nomessage="can't include distcache headers"
+ ap_ssltk_dc="no"])
+ if test "$tmp_forced" = "yes" -a "x$ap_ssltk_dc" = "xno"; then
+ AC_MSG_ERROR(distcache support failed: $tmp_nomessage)
+ fi
+ fi
+ if test "$ap_ssltk_dc" = "yes"; then
+ AC_MSG_CHECKING(for Distcache version)
+ AC_TRY_COMPILE(
+[#include <distcache/dc_client.h>],
+[#if DISTCACHE_CLIENT_API != 0x0001
+#error "distcache API version is unrecognised"
+#endif],
+[],
+[tmp_nomessage="distcache has an unsupported API version"
+ap_ssltk_dc="no"])
+ AC_MSG_RESULT($ap_ssltk_dc)
+ if test "$tmp_forced" = "yes" -a "x$ap_ssltk_dc" = "xno"; then
+ AC_MSG_ERROR(distcache support failed: $tmp_nomessage)
+ fi
+ fi
+ if test "$ap_ssltk_dc" = "yes"; then
+ AC_MSG_CHECKING(for Distcache libraries)
+ save_libs=$LIBS
+ LIBS="$LIBS -ldistcache -lnal"
+ AC_TRY_LINK(
+ [#include <distcache/dc_client.h>],
+ [DC_CTX *foo = DC_CTX_new((const char *)0,0);],
+ [],
+ [tmp_no_message="failed to link with distcache libraries"
+ ap_ssltk_dc="no"])
+ LIBS=$save_libs
+ AC_MSG_RESULT($ap_ssltk_dc)
+ if test "$tmp_forced" = "yes" -a "x$ap_ssltk_dc" = "xno"; then
+ AC_MSG_ERROR(distcache support failed: $tmp_nomessage)
+ else
+ APR_ADDTO(LIBS,[-ldistcache -lnal])
+ AC_DEFINE(HAVE_DISTCACHE, 1, [Define if distcache support is enabled])
+ fi
+ fi
+])
+
dnl # start of module specific part
APACHE_MODPATH_INIT(ssl)
ssl_scache.lo dnl
ssl_scache_dbm.lo dnl
ssl_scache_shmcb.lo dnl
+ssl_scache_dc.lo dnl
ssl_util.lo dnl
ssl_util_ssl.lo dnl
"
dnl # hook module into the Autoconf mechanism (--enable-ssl option)
APACHE_MODULE(ssl, [SSL/TLS support (mod_ssl)], $ssl_objs, , no, [
APACHE_CHECK_SSL_TOOLKIT
+ CHECK_DISTCACHE
])
dnl # end of module specific part
if (mc->nSessionCacheMode == SSL_SCMODE_DBM)
ssl_scache_dbm_init(s, p);
+#ifdef HAVE_DISTCACHE
+ else if (mc->nSessionCacheMode == SSL_SCMODE_DC)
+ ssl_scache_dc_init(s, p);
+#endif
else if (mc->nSessionCacheMode == SSL_SCMODE_SHMCB) {
void *data;
const char *userdata_key = "ssl_scache_init";
ssl_scache_dbm_kill(s);
else if (mc->nSessionCacheMode == SSL_SCMODE_SHMCB)
ssl_scache_shmcb_kill(s);
+#ifdef HAVE_DISTCACHE
+ else if (mc->nSessionCacheMode == SSL_SCMODE_DC)
+ ssl_scache_dc_kill(s);
+#endif
return;
}
rv = ssl_scache_dbm_store(s, id, idlen, expiry, sess);
else if (mc->nSessionCacheMode == SSL_SCMODE_SHMCB)
rv = ssl_scache_shmcb_store(s, id, idlen, expiry, sess);
+#ifdef HAVE_DISTCACHE
+ else if (mc->nSessionCacheMode == SSL_SCMODE_DC)
+ rv = ssl_scache_dc_store(s, id, idlen, expiry, sess);
+#endif
return rv;
}
sess = ssl_scache_dbm_retrieve(s, id, idlen);
else if (mc->nSessionCacheMode == SSL_SCMODE_SHMCB)
sess = ssl_scache_shmcb_retrieve(s, id, idlen);
+#ifdef HAVE_DISTCACHE
+ else if (mc->nSessionCacheMode == SSL_SCMODE_DC)
+ sess = ssl_scache_dc_retrieve(s, id, idlen);
+#endif
return sess;
}
ssl_scache_dbm_remove(s, id, idlen);
else if (mc->nSessionCacheMode == SSL_SCMODE_SHMCB)
ssl_scache_shmcb_remove(s, id, idlen);
+#ifdef HAVE_DISTCACHE
+ else if (mc->nSessionCacheMode == SSL_SCMODE_DC)
+ ssl_scache_dc_remove(s, id, idlen);
+#endif
return;
}
ssl_scache_dbm_status(r, flags, r->pool);
else if (sc->mc->nSessionCacheMode == SSL_SCMODE_SHMCB)
ssl_scache_shmcb_status(r, flags, r->pool);
+#ifdef HAVE_DISTCACHE
+ else if (sc->mc->nSessionCacheMode == SSL_SCMODE_DC)
+ ssl_scache_dc_status(r, flags, r->pool);
+#endif
ap_rputs("</td></tr>\n", r);
ap_rputs("</table>\n", r);
--- /dev/null
+/* _ _
+** _ __ ___ ___ __| | ___ ___| | mod_ssl
+** | '_ ` _ \ / _ \ / _` | / __/ __| | Apache Interface to OpenSSL
+** | | | | | | (_) | (_| | \__ \__ \ | www.modssl.org
+** |_| |_| |_|\___/ \__,_|___|___/___/_| ftp.modssl.org
+** |_____|
+** ssl_scache_dc.c
+** Distributed Session Cache (client support)
+*/
+
+/* ====================================================================
+ * THIS SOFTWARE IS PROVIDED BY GEOFF THORPE ``AS IS'' AND ANY
+ * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RALF S. ENGELSCHALL OR
+ * HIS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ * ====================================================================
+ */
+
+#include "mod_ssl.h"
+
+/* Only build this code if it's enabled at configure-time. */
+#ifdef HAVE_DISTCACHE
+
+#include "distcache/dc_client.h"
+
+#if !defined(DISTCACHE_CLIENT_API) || (DISTCACHE_CLIENT_API < 0x0001)
+#error "You must compile with a more recent version of the distcache-base package"
+#endif
+
+/*
+ * This cache implementation allows modssl to access 'distcache' servers (or
+ * proxies) to facilitate distributed session caching. It is based on code
+ * released as open source by Cryptographic Appliances Inc, and was developed by
+ * Geoff Thorpe, Steve Robb, and Chris Zimmerman.
+ */
+
+/*
+**
+** High-Level "handlers" as per ssl_scache.c
+**
+*/
+
+void ssl_scache_dc_init(server_rec *s, apr_pool_t *p)
+{
+ DC_CTX *ctx;
+ SSLModConfigRec *mc = myModConfig(s);
+ /*
+ * Create a session context
+ */
+ if (mc->szSessionCacheDataFile == NULL) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, "SSLSessionCache required");
+ ssl_die();
+ }
+#if 0
+ /* If a "persistent connection" mode of operation is preferred, you *must*
+ * also use the PIDCHECK flag to ensure fork()'d processes don't interlace
+ * comms on the same connection as each other. */
+#define SESSION_CTX_FLAGS SESSION_CTX_FLAG_PERSISTENT | \
+ SESSION_CTX_FLAG_PERSISTENT_PIDCHECK | \
+ SESSION_CTX_FLAG_PERSISTENT_RETRY | \
+ SESSION_CTX_FLAG_PERSISTENT_LATE
+#else
+ /* This mode of operation will open a temporary connection to the 'target'
+ * for each cache operation - this makes it safe against fork()
+ * automatically. This mode is preferred when running a local proxy (over
+ * unix domain sockets) because overhead is negligable and it reduces the
+ * performance/stability danger of file-descriptor bloatage. */
+#define SESSION_CTX_FLAGS 0
+#endif
+ ctx = DC_CTX_new(mc->szSessionCacheDataFile, SESSION_CTX_FLAGS);
+ if (!ctx) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, "distributed scache failed to obtain context");
+ ssl_die();
+ }
+ ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, "distributed scache context initialised");
+ /*
+ * Success ...
+ */
+ mc->tSessionCacheDataTable = ctx;
+ return;
+}
+
+void ssl_scache_dc_kill(server_rec *s)
+{
+ SSLModConfigRec *mc = myModConfig(s);
+
+ if (mc->tSessionCacheDataTable)
+ DC_CTX_free(mc->tSessionCacheDataTable);
+ mc->tSessionCacheDataTable = NULL;
+}
+
+BOOL ssl_scache_dc_store(server_rec *s, UCHAR *id, int idlen,
+ time_t timeout, SSL_SESSION * pSession)
+{
+ unsigned char der[SSL_SESSION_MAX_DER];
+ int der_len;
+ unsigned char *pder = der;
+ SSLModConfigRec *mc = myModConfig(s);
+ DC_CTX *ctx = mc->tSessionCacheDataTable;
+
+ /* Serialise the SSL_SESSION object */
+ if ((der_len = i2d_SSL_SESSION(pSession, NULL)) > SSL_SESSION_MAX_DER)
+ return FALSE;
+ i2d_SSL_SESSION(pSession, &pder);
+ /* !@#$%^ - why do we deal with *absolute* time anyway??? */
+ timeout -= time(NULL);
+ /* Send the serialised session to the distributed cache context */
+ if (!DC_CTX_add_session(ctx, id, idlen, der, der_len,
+ (unsigned long)timeout * 1000)) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, "distributed scache 'add_session' failed");
+ return FALSE;
+ }
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "distributed scache 'add_session' successful");
+ return TRUE;
+}
+
+SSL_SESSION *ssl_scache_dc_retrieve(server_rec *s, UCHAR *id, int idlen)
+{
+ unsigned char der[SSL_SESSION_MAX_DER];
+ unsigned int der_len;
+ SSL_SESSION *pSession;
+ unsigned char *pder = der;
+ SSLModConfigRec *mc = myModConfig(s);
+ DC_CTX *ctx = mc->tSessionCacheDataTable;
+
+ /* Retrieve any corresponding session from the distributed cache context */
+ if (!DC_CTX_get_session(ctx, id, idlen, der, SSL_SESSION_MAX_DER,
+ &der_len)) {
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "distributed scache 'get_session' MISS");
+ return NULL;
+ }
+ if (der_len > SSL_SESSION_MAX_DER) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, "distributed scache 'get_session' OVERFLOW");
+ return NULL;
+ }
+ pSession = d2i_SSL_SESSION(NULL, &pder, der_len);
+ if (!pSession) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, "distributed scache 'get_session' CORRUPT");
+ return NULL;
+ }
+ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "distributed scache 'get_session' HIT");
+ return pSession;
+}
+
+void ssl_scache_dc_remove(server_rec *s, UCHAR *id, int idlen)
+{
+ SSLModConfigRec *mc = myModConfig(s);
+ DC_CTX *ctx = mc->tSessionCacheDataTable;
+
+ /* Remove any corresponding session from the distributed cache context */
+ if (!DC_CTX_remove_session(ctx, id, idlen)) {
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, "distributed scache 'remove_session' MISS");
+ } else {
+ ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, "distributed scache 'remove_session' HIT");
+ }
+}
+
+void ssl_scache_dc_expire(server_rec *s)
+{
+ /* NOP */
+ return;
+}
+
+void ssl_scache_dc_status(request_rec *r, int flags, apr_pool_t *pool)
+{
+ SSLModConfigRec *mc = myModConfig(r->server);
+
+ ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
+ "distributed scache 'ssl_scache_dc_status'");
+ ap_rprintf(r, "cache type: <b>DC (Distributed Cache)</b>, "
+ " target: <b>%s</b><br>", mc->szSessionCacheDataFile);
+}
+
+#endif
+