On 06/08/2007 04:48 AM, [EMAIL PROTECTED] wrote:
> Author: pquerna
> Date: Thu Jun  7 19:48:04 2007
> New Revision: 545379
> 
> URL: http://svn.apache.org/viewvc?view=rev&rev=545379
> Log:
> Add support for distributed caching of SSL Sessions inside memcached, using 
> apr_memcache, which is present in APR-Util 1.3/trunk.
> 
> This was originally written at ApacheCon US 2005 (San Diego), and was sent to 
> the list:
> http://mail-archives.apache.org/mod_mbox/httpd-dev/200512.mbox/[EMAIL 
> PROTECTED]
> 
> This version is slightly cleaned up, and of course, uses the now bundled 
> apr_memcache, rather than an external dependency.
> 
> 
> Added:
>     httpd/httpd/trunk/modules/ssl/ssl_scache_memcache.c   (with props)
> Modified:
>     httpd/httpd/trunk/CHANGES
>     httpd/httpd/trunk/modules/ssl/config.m4
>     httpd/httpd/trunk/modules/ssl/ssl_engine_config.c
>     httpd/httpd/trunk/modules/ssl/ssl_private.h
>     httpd/httpd/trunk/modules/ssl/ssl_scache.c
> 

> Modified: httpd/httpd/trunk/modules/ssl/ssl_engine_config.c
> URL: 
> http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/ssl/ssl_engine_config.c?view=diff&rev=545379&r1=545378&r2=545379
> ==============================================================================
> --- httpd/httpd/trunk/modules/ssl/ssl_engine_config.c (original)
> +++ httpd/httpd/trunk/modules/ssl/ssl_engine_config.c Thu Jun  7 19:48:04 2007
> @@ -1034,6 +1034,19 @@
>          return "SSLSessionCache: distcache support disabled";
>  #endif
>      }
> +    else if ((arglen > 3) && strcEQn(arg, "memcache:", 9)) {
> +#ifdef HAVE_SSL_CACHE_MEMCACHE
> +        mc->nSessionCacheMode      = SSL_SCMODE_MC;
> +        mc->szSessionCacheDataFile = apr_pstrdup(mc->pPool, arg+9);
> +        if (!mc->szSessionCacheDataFile) {
> +            return apr_pstrcat(cmd->pool,
> +                               "SSLSessionCache: Invalid memcache config: ",
> +                               arg+9, NULL);
> +        }
> +#else
> +        return "SSLSessionCache: distcache support disabled";

Nitpicking: Should memcache instead of distcache.


> Added: httpd/httpd/trunk/modules/ssl/ssl_scache_memcache.c
> URL: 
> http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/ssl/ssl_scache_memcache.c?view=auto&rev=545379
> ==============================================================================
> --- httpd/httpd/trunk/modules/ssl/ssl_scache_memcache.c (added)
> +++ httpd/httpd/trunk/modules/ssl/ssl_scache_memcache.c Thu Jun  7 19:48:04 
> 2007
> @@ -0,0 +1,289 @@


> +
> +void ssl_scache_mc_init(server_rec *s, apr_pool_t *p)
> +{
> +    apr_status_t rv;
> +    int thread_limit = 0;
> +    int nservers = 0;
> +    char *cache_config;
> +    char *split;
> +    char *tok;
> +    SSLModConfigRec *mc = myModConfig(s);
> +
> +    ap_mpm_query(AP_MPMQ_HARD_LIMIT_THREADS, &thread_limit);
> +
> +    if (mc->szSessionCacheDataFile == NULL) {
> +        ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, "SSLSessionCache 
> required");
> +        ssl_die();
> +    }
> +
> +    /* Find all the servers in the first run to get a total count */
> +    cache_config = apr_pstrdup(p, mc->szSessionCacheDataFile);
> +    split = apr_strtok(cache_config, ",", &tok);
> +    while (split) {
> +        nservers++;
> +        split = apr_strtok(NULL,",", &tok);
> +    }
> +
> +    rv = apr_memcache_create(p, nservers, 0, &memctxt);
> +    if (rv != APR_SUCCESS) {
> +        ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s,
> +                     "SSLSessionCache: Failed to create Memcache Object of 
> '%d' size.", 
> +                     nservers);
> +        ssl_die();
> +    }
> +
> +    /* Now add each server to the memcache */
> +    cache_config = apr_pstrdup(p, mc->szSessionCacheDataFile);
> +    split = apr_strtok(cache_config, ",", &tok);
> +    while (split) {
> +        apr_memcache_server_t *st;
> +        char *host_str;
> +        char *scope_id;
> +        apr_port_t port;
> +
> +        rv = apr_parse_addr_port(&host_str, &scope_id, &port, split, p);
> +        if (rv != APR_SUCCESS) {
> +            ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s,
> +                         "SSLSessionCache: Failed to Parse Server: '%s'", 
> split);
> +            ssl_die();
> +        }
> +
> +        if (host_str == NULL) {
> +            ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s,
> +                         "SSLSessionCache: Failed to Parse Server, "
> +                         "no hostname specified: '%s'", split);
> +            ssl_die();
> +        }
> +
> +        if (port == 0) {
> +            port = 11211; /* default port */

Shouldn't we use a define for the default port and refer to it instead of using 
it directly?

> +        }
> +
> +        /* Should Max Conns be (thread_limit / nservers) ? */
> +        rv = apr_memcache_server_create(p,
> +                                        host_str, port,
> +                                        0,
> +                                        1,
> +                                        thread_limit, 
> +                                        600,
> +                                        &st);

Having at least some of the values configurable would be an enhancement (Sorry 
for wanting to have
everything perfect from the start :-))
Nevertheless shouldn't we use defines for these default values (except 
thread_limit of course)
and refer to them instead of using the values directly?


> +
> +static char *mc_session_id2sz(unsigned char *id, int idlen,
> +                               char *str, int strsize)
> +{
> +    char *cp;
> +    int n;
> + 
> +    cp = apr_cpystrn(str, MC_TAG, MC_TAG_LEN);
> +    for (n = 0; n < idlen && n < (MC_KEY_LEN - MC_TAG_LEN); n++) {

Hm. It seems to me that our upper limit for n is (MC_KEY_LEN - MC_TAG_LEN)/2
and not (MC_KEY_LEN - MC_TAG_LEN) since every element of id consumes 2 bytes in 
the
target buffer. Furthermore I would think that using (strsize - MC_TAG_LEN)/2
as a precalculated value would be even bettter.

> +        apr_snprintf(cp, strsize - (cp-str), "%02X", id[n]);

Couldn't we replace

strsize - (cp-str)

just with

2

once the loop condition is fixed?

> +        cp += 2;
> +    }
> +    *cp = '\0';
> +    return str;
> +}
> +
> +BOOL ssl_scache_mc_store(server_rec *s, UCHAR *id, int idlen,
> +                           time_t timeout, SSL_SESSION *pSession)
> +{
> +    char buf[MC_KEY_LEN];
> +    char *strkey = NULL;
> +    UCHAR ucaData[SSL_SESSION_MAX_DER];
> +    UCHAR *ucp;
> +    int nData;
> +    apr_status_t rv;
> +
> +    /* streamline session data */
> +    if ((nData = i2d_SSL_SESSION(pSession, NULL)) > sizeof(ucaData)) {
> +        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
> +                     "scache_mc: streamline session data size too large: %d 
> > "
> +                     "%" APR_SIZE_T_FMT,
> +                     nData, sizeof(ucaData));
> +        return FALSE;
> +    }
> +
> +    ucp = ucaData;
> +    i2d_SSL_SESSION(pSession, &ucp);
> +
> +    strkey = mc_session_id2sz(id, idlen, buf, sizeof(buf));
> +    if(!strkey) {
> +        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "scache_mc: Key 
> generation borked.");
> +        return FALSE;
> +    }
> +
> +    timeout -= time(NULL);
> +
> +    timeout = apr_time_sec(timeout);
> +
> +    rv = apr_memcache_set(memctxt, strkey, (char*)ucp, nData, timeout, 0);
> +
> +    if (rv != APR_SUCCESS) {
> +        ap_log_error(APLOG_MARK, APLOG_CRIT, rv, s,
> +                     "scache_mc: error setting key '%s' "
> +                     "with %d bytes of data", strkey, nData);
> +        return FALSE;
> +    }
> +
> +    return TRUE;
> +}
> +
> +SSL_SESSION *ssl_scache_mc_retrieve(server_rec *s, UCHAR *id, int idlen)
> +{
> +    SSL_SESSION *pSession;
> +    MODSSL_D2I_SSL_SESSION_CONST unsigned char *pder;
> +    apr_size_t der_len;
> +    SSLModConfigRec *mc = myModConfig(s);
> +    char buf[MC_KEY_LEN];
> +    char* strkey = NULL;
> +    apr_status_t rv;
> +
> +    strkey = mc_session_id2sz(id, idlen, buf, sizeof(buf));
> +
> +    if(!strkey) {
> +        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
> +                     "scache_mc: Key generation borked.");
> +        return NULL;
> +    }
> +
> +    rv = apr_memcache_getp(memctxt,  mc->pPool, strkey,

Is this the correct pool to use? AFAICT the data stored in *pder
will only be used locally, because d2i_SSL_SESSION allocates
new memory to create the pSession object.
mc->pPool seems to be a pool with a long lifetime to me and I fear
that we introduce a memory leak here. How about a temporary subpool
if no other pool is at hand here?

> +                           (char**)&pder, &der_len, NULL);
> +
> +    if (rv == APR_NOTFOUND) {
> +        /* ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
> +                       "scache_mc: 'get_session' MISS"); */
> +        return NULL;
> +    }
> +
> +    if (rv != APR_SUCCESS) {
> +        ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
> +                     "scache_mc: 'get_session' FAIL");
> +        return NULL;
> +    }
> +
> +    if (der_len > SSL_SESSION_MAX_DER) {
> +        ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
> +                     "scache_mc: 'get_session' OVERFLOW");
> +        return NULL;
> +    }
> +
> +    pSession = d2i_SSL_SESSION(NULL, &pder, der_len);
> +
> +    if (!pSession) {
> +        ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
> +                     "scache_mc: 'get_session' CORRUPT");
> +        return NULL;
> +    }
> +
> +    /* ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
> +        "scache_mc: 'get_session' HIT"); */

Why the comments above?


Regards

RĂ¼diger

Reply via email to