]> granicus.if.org Git - apache/commitdiff
Add support to mod_ssl for a distributed session cache using
authorJoe Orton <jorton@apache.org>
Thu, 8 Jan 2004 16:26:53 +0000 (16:26 +0000)
committerJoe Orton <jorton@apache.org>
Thu, 8 Jan 2004 16:26:53 +0000 (16:26 +0000)
distcache.

* LAYOUT: Update for removal of scache_shmht and addition of scache_dc.

* modules/ssl/config.m4: Check for libdistcache; build ssl_scache_dc.lo.

* modules/ssl/mod_ssl.dsp: Build ssl_scache_dc (with luck).

* modules/ssl/mod_ssl.h: Add SSL_SCMODE_DC and scache_dc_* prototypes.

* modules/ssl/ssl_engine_config.c (ssl_cmd_SSLSessionCache): Allow
use of dc: argument.

* modules/ssl/ssl_scache_dc.c: New file.

* modules/ssl/ssl_scache.c (ssl_scache_init, ssl_scache_kill,
ssl_scache_store, ssl_scache_retrieve, ssl_scache_remove,
ssl_ext_status_hook): Hook into scache_dc.

Submitted by: Geoff Thorpe <geoff@geoffthorpe.net>

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@102227 13f79535-47bb-0310-9956-ffa450edef68

CHANGES
LAYOUT
modules/ssl/config.m4
modules/ssl/mod_ssl.dsp
modules/ssl/mod_ssl.h
modules/ssl/ssl_engine_config.c
modules/ssl/ssl_scache.c
modules/ssl/ssl_scache_dc.c [new file with mode: 0644]

diff --git a/CHANGES b/CHANGES
index cda3dad2232957f8359c1eb974e977bcce76ca24..f168fea94585ff1d7f71ed4e4bf4753335960fd2 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -2,6 +2,9 @@ Changes with Apache 2.1.0-dev
 
   [Remove entries to the current 2.0 section below, when backported]
 
+  *) mod_ssl: Add support for distributed session cache using 'distcache'.
+     [Geoff Thorpe <geoff geoffthorpe.net>]
+
   *) mod_dav: Disallow requests with an unescaped hash character in
      the Request-URI.  PR 21779.  [Amit Athavale <amit_athavale lycos.com>]
 
diff --git a/LAYOUT b/LAYOUT
index c5525d76ea41c3b6015bae7883c29d5d513820aa..8385e67f0f45245af70b0bd5f7ecb37c2e5a528f 100644 (file)
--- a/LAYOUT
+++ b/LAYOUT
@@ -128,7 +128,7 @@ modules/ ................ Manditory and Add-In Apache stock modules
     ssl_scache.c ............ session cache abstraction layer
     ssl_scache_dbm.c ........ session cache via DBM file
     ssl_scache_shmcb.c ...... session cache via shared memory cyclic buffer
-    ssl_scache_shmht.c ...... session cache via shared memory hash table
+    ssl_scache_dc.c ......... session cache offloading via 'distcache'
     ssl_util.c .............. utility functions
     ssl_util_ssl.c .......... the OpenSSL companion source
     ssl_util_ssl.h .......... the OpenSSL companion header
index 956320204c40ef65b62f4588b80ea62ab5a3b2fa..35f92bcf0e5449e19c40ed6f3976444c79938fcf 100644 (file)
@@ -46,6 +46,79 @@ dnl ## OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 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)
 
@@ -69,12 +142,14 @@ ssl_expr_scan.lo dnl
 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
index 43a106dffafee373e3900a1da8bc94f5fa070692..091539ead1da09b42ee6edf3398253ae2b27f548 100644 (file)
@@ -164,6 +164,10 @@ SOURCE=.\ssl_scache_shmcb.c
 # End Source File
 # Begin Source File
 
+SOURCE=.\ssl_scache_dc.c
+# End Source File
+# Begin Source File
+
 SOURCE=.\ssl_util.c
 # End Source File
 # Begin Source File
index a49ac6f1a984e38de474583c84129fba82489fdb..e93520c6e26c30029523ba7452b8dc335a376950 100644 (file)
@@ -306,7 +306,8 @@ typedef enum {
     SSL_SCMODE_UNSET = UNSET,
     SSL_SCMODE_NONE  = 0,
     SSL_SCMODE_DBM   = 1,
-    SSL_SCMODE_SHMCB = 3
+    SSL_SCMODE_SHMCB = 3,
+    SSL_SCMODE_DC    = 4
 } ssl_scmode_t;
 
 /*
@@ -602,7 +603,15 @@ void         ssl_scache_shmcb_remove(server_rec *, UCHAR *, int);
 void         ssl_scache_shmcb_expire(server_rec *);
 void         ssl_scache_shmcb_status(request_rec *r, int flags, apr_pool_t *pool);
 
-/*  Pass Phrase Support  */
+void         ssl_scache_dc_init(server_rec *, apr_pool_t *);
+void         ssl_scache_dc_kill(server_rec *);
+BOOL         ssl_scache_dc_store(server_rec *, UCHAR *, int, time_t, SSL_SESSION *);
+SSL_SESSION *ssl_scache_dc_retrieve(server_rec *, UCHAR *, int);
+void         ssl_scache_dc_remove(server_rec *, UCHAR *, int);
+void         ssl_scache_dc_expire(server_rec *);
+void         ssl_scache_dc_status(request_rec *r, int flags, apr_pool_t *pool);
+
+/*  PASS Phrase Support  */
 void         ssl_pphrase_Handle(server_rec *, apr_pool_t *);
 
 /*  Diffie-Hellman Parameter Support  */
index 455fbafb716d8b5c022b254dec324ab6515516bd..53130d1e436c21025917c7e1cf9136c7863a1099 100644 (file)
@@ -1051,6 +1051,19 @@ const char *ssl_cmd_SSLSessionCache(cmd_parms *cmd,
             }
         }
     }
+    else if ((arglen > 3) && strcEQn(arg, "dc:", 3)) {
+#ifdef HAVE_DISTCACHE
+        mc->nSessionCacheMode      = SSL_SCMODE_DC;
+        mc->szSessionCacheDataFile = apr_pstrdup(mc->pPool, arg+3);
+        if (!mc->szSessionCacheDataFile) {
+            return apr_pstrcat(cmd->pool, 
+                               "SSLSessionCache: Invalid cache file path: ",
+                               arg+3, NULL);
+        }
+#else
+        return "SSLSessionCache: distcache support disabled";
+#endif
+    }
     else {
         return "SSLSessionCache: Invalid argument";
     }
index 67199f7b21530e618eb2333674e1a6ac3cd1ce86..7180c21266663ccdacfb021a103f1f9bb19e4f57 100644 (file)
@@ -88,6 +88,10 @@ void ssl_scache_init(server_rec *s, apr_pool_t *p)
 
     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";
@@ -110,6 +114,10 @@ void ssl_scache_kill(server_rec *s)
         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;
 }
 
@@ -122,6 +130,10 @@ BOOL ssl_scache_store(server_rec *s, UCHAR *id, int idlen, time_t expiry, SSL_SE
         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;
 }
 
@@ -134,6 +146,10 @@ SSL_SESSION *ssl_scache_retrieve(server_rec *s, UCHAR *id, int idlen)
         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;
 }
 
@@ -145,6 +161,10 @@ void ssl_scache_remove(server_rec *s, UCHAR *id, int idlen)
         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;
 }
 
@@ -182,6 +202,10 @@ static int ssl_ext_status_hook(request_rec *r, int flags)
         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);
diff --git a/modules/ssl/ssl_scache_dc.c b/modules/ssl/ssl_scache_dc.c
new file mode 100644 (file)
index 0000000..5866568
--- /dev/null
@@ -0,0 +1,183 @@
+/*                      _             _
+**  _ __ ___   ___   __| |    ___ ___| |  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
+