diff options
-rw-r--r-- | modules/ssl/ssl_engine_mutex.c | 18 | ||||
-rw-r--r-- | modules/ssl/ssl_private.h | 12 | ||||
-rw-r--r-- | modules/ssl/ssl_scache.c | 48 | ||||
-rw-r--r-- | modules/ssl/ssl_scache_dbm.c | 25 | ||||
-rw-r--r-- | modules/ssl/ssl_scache_dc.c | 2 | ||||
-rw-r--r-- | modules/ssl/ssl_scache_memcache.c | 2 | ||||
-rw-r--r-- | modules/ssl/ssl_scache_shmcb.c | 22 |
7 files changed, 79 insertions, 50 deletions
diff --git a/modules/ssl/ssl_engine_mutex.c b/modules/ssl/ssl_engine_mutex.c index bbcd92ad64..7c6145cbcd 100644 --- a/modules/ssl/ssl_engine_mutex.c +++ b/modules/ssl/ssl_engine_mutex.c @@ -39,12 +39,24 @@ int ssl_mutex_init(server_rec *s, apr_pool_t *p) SSLModConfigRec *mc = myModConfig(s); apr_status_t rv; - if (mc->nMutexMode == SSL_MUTEXMODE_NONE) + /* A mutex is only needed if a session cache is configured, and + * the provider used is not internally multi-process/thread + * safe. */ + if (!mc->sesscache + || (mc->sesscache->flags & MODSSL_SESSCACHE_FLAG_NOTMPSAFE) == 0) { return TRUE; + } if (mc->pMutex) { return TRUE; } + else if (mc->nMutexMode == SSL_MUTEXMODE_NONE) { + ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, + "An SSLMutex is required for the '%s' session cache", + mc->sesscache->name); + return FALSE; + } + if ((rv = apr_global_mutex_create(&mc->pMutex, mc->szMutexFile, mc->nMutexMech, s->process->pool)) != APR_SUCCESS) { @@ -97,8 +109,6 @@ int ssl_mutex_on(server_rec *s) SSLModConfigRec *mc = myModConfig(s); apr_status_t rv; - if (mc->nMutexMode == SSL_MUTEXMODE_NONE) - return TRUE; if ((rv = apr_global_mutex_lock(mc->pMutex)) != APR_SUCCESS) { ap_log_error(APLOG_MARK, APLOG_WARNING, rv, s, "Failed to acquire SSL session cache lock"); @@ -112,8 +122,6 @@ int ssl_mutex_off(server_rec *s) SSLModConfigRec *mc = myModConfig(s); apr_status_t rv; - if (mc->nMutexMode == SSL_MUTEXMODE_NONE) - return TRUE; if ((rv = apr_global_mutex_unlock(mc->pMutex)) != APR_SUCCESS) { ap_log_error(APLOG_MARK, APLOG_WARNING, rv, s, "Failed to release SSL session cache lock"); diff --git a/modules/ssl/ssl_private.h b/modules/ssl/ssl_private.h index 0f20b535a2..76f08c61d3 100644 --- a/modules/ssl/ssl_private.h +++ b/modules/ssl/ssl_private.h @@ -354,8 +354,20 @@ typedef struct { #define MODSSL_SESSCACHE_PROVIDER_GROUP "mod_ssl-sesscache" #define MODSSL_SESSCACHE_PROVIDER_VERSION "0" +/* If this flag is set, the store/retrieve/delete/status interfaces of + * the provider are NOT safe to be called concurrently from multiple + * processes or threads, and an external global mutex must be used to + * serialize access to the provider. */ +#define MODSSL_SESSCACHE_FLAG_NOTMPSAFE (0x0001) + /* Session cache provider vtable. */ typedef struct { + /* Canonical provider name: */ + const char *name; + + /* Bitmask of MODSSL_SESSCACHE_FLAG_* flags: */ + unsigned int flags; + /* Create a session cache based on the given configuration string * ARG. Returns NULL on success, or an error string on failure. * Pool TMP should be used for any temporary allocations, pool P diff --git a/modules/ssl/ssl_scache.c b/modules/ssl/ssl_scache.c index 3d97ee8d16..db4dad12e8 100644 --- a/modules/ssl/ssl_scache.c +++ b/modules/ssl/ssl_scache.c @@ -90,6 +90,7 @@ BOOL ssl_scache_store(server_rec *s, UCHAR *id, int idlen, SSLModConfigRec *mc = myModConfig(s); unsigned char encoded[SSL_SESSION_MAX_DER], *ptr; unsigned int len; + BOOL rv; /* Serialise the session. */ len = i2d_SSL_SESSION(sess, NULL); @@ -102,8 +103,18 @@ BOOL ssl_scache_store(server_rec *s, UCHAR *id, int idlen, ptr = encoded; len = i2d_SSL_SESSION(sess, &ptr); - return mc->sesscache->store(mc->sesscache_context, s, id, idlen, - expiry, encoded, len); + if (mc->sesscache->flags & MODSSL_SESSCACHE_FLAG_NOTMPSAFE) { + ssl_mutex_on(s); + } + + rv = mc->sesscache->store(mc->sesscache_context, s, id, idlen, + expiry, encoded, len); + + if (mc->sesscache->flags & MODSSL_SESSCACHE_FLAG_NOTMPSAFE) { + ssl_mutex_off(s); + } + + return rv; } SSL_SESSION *ssl_scache_retrieve(server_rec *s, UCHAR *id, int idlen, @@ -113,9 +124,20 @@ SSL_SESSION *ssl_scache_retrieve(server_rec *s, UCHAR *id, int idlen, unsigned char dest[SSL_SESSION_MAX_DER]; unsigned int destlen = SSL_SESSION_MAX_DER; MODSSL_D2I_SSL_SESSION_CONST unsigned char *ptr; - - if (mc->sesscache->retrieve(mc->sesscache_context, s, id, idlen, - dest, &destlen, p) == FALSE) { + BOOL rv; + + if (mc->sesscache->flags & MODSSL_SESSCACHE_FLAG_NOTMPSAFE) { + ssl_mutex_on(s); + } + + rv = mc->sesscache->retrieve(mc->sesscache_context, s, id, idlen, + dest, &destlen, p); + + if (mc->sesscache->flags & MODSSL_SESSCACHE_FLAG_NOTMPSAFE) { + ssl_mutex_off(s); + } + + if (rv == FALSE) { return NULL; } @@ -129,9 +151,15 @@ void ssl_scache_remove(server_rec *s, UCHAR *id, int idlen, { SSLModConfigRec *mc = myModConfig(s); + if (mc->sesscache->flags & MODSSL_SESSCACHE_FLAG_NOTMPSAFE) { + ssl_mutex_on(s); + } + mc->sesscache->delete(mc->sesscache_context, s, id, idlen, p); - return; + if (mc->sesscache->flags & MODSSL_SESSCACHE_FLAG_NOTMPSAFE) { + ssl_mutex_off(s); + } } /* _________________________________________________________________ @@ -153,8 +181,16 @@ static int ssl_ext_status_hook(request_rec *r, int flags) ap_rputs("</td></tr>\n", r); ap_rputs("<tr><td bgcolor=\"#ffffff\">\n", r); + if (mc->sesscache->flags & MODSSL_SESSCACHE_FLAG_NOTMPSAFE) { + ssl_mutex_on(r->server); + } + mc->sesscache->status(mc->sesscache_context, r, flags, r->pool); + if (mc->sesscache->flags & MODSSL_SESSCACHE_FLAG_NOTMPSAFE) { + ssl_mutex_off(r->server); + } + ap_rputs("</td></tr>\n", r); ap_rputs("</table>\n", r); return OK; diff --git a/modules/ssl/ssl_scache_dbm.c b/modules/ssl/ssl_scache_dbm.c index acd2487222..5959d5ee81 100644 --- a/modules/ssl/ssl_scache_dbm.c +++ b/modules/ssl/ssl_scache_dbm.c @@ -71,7 +71,6 @@ static apr_status_t ssl_scache_dbm_init(void *context, server_rec *s, apr_pool_t } /* open it once to create it and to make sure it _can_ be created */ - ssl_mutex_on(s); apr_pool_clear(ctx->pool); if ((rv = apr_dbm_open(&dbm, ctx->data_file, @@ -79,7 +78,6 @@ static apr_status_t ssl_scache_dbm_init(void *context, server_rec *s, apr_pool_t ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, "Cannot create SSLSessionCache DBM file `%s'", ctx->data_file); - ssl_mutex_off(s); return rv; } apr_dbm_close(dbm); @@ -108,7 +106,6 @@ static apr_status_t ssl_scache_dbm_init(void *context, server_rec *s, apr_pool_t } } #endif - ssl_mutex_off(s); ssl_scache_dbm_expire(ctx, s); return APR_SUCCESS; @@ -173,7 +170,6 @@ static BOOL ssl_scache_dbm_store(void *context, server_rec *s, UCHAR *id, int id memcpy((char *)dbmval.dptr+sizeof(time_t), ucaData, nData); /* and store it to the DBM file */ - ssl_mutex_on(s); apr_pool_clear(ctx->pool); if ((rv = apr_dbm_open(&dbm, ctx->data_file, @@ -182,7 +178,6 @@ static BOOL ssl_scache_dbm_store(void *context, server_rec *s, UCHAR *id, int id "Cannot open SSLSessionCache DBM file `%s' for writing " "(store)", ctx->data_file); - ssl_mutex_off(s); free(dbmval.dptr); return FALSE; } @@ -191,12 +186,10 @@ static BOOL ssl_scache_dbm_store(void *context, server_rec *s, UCHAR *id, int id "Cannot store SSL session to DBM file `%s'", ctx->data_file); apr_dbm_close(dbm); - ssl_mutex_off(s); free(dbmval.dptr); return FALSE; } apr_dbm_close(dbm); - ssl_mutex_off(s); /* free temporary buffers */ free(dbmval.dptr); @@ -231,7 +224,6 @@ static BOOL ssl_scache_dbm_retrieve(void *context, server_rec *s, const UCHAR *i * XXX: Should we open the dbm against r->pool so the cleanup will * do the apr_dbm_close? This would make the code a bit cleaner. */ - ssl_mutex_on(s); apr_pool_clear(ctx->pool); if ((rc = apr_dbm_open(&dbm, ctx->data_file, APR_DBM_RWCREATE, SSL_DBM_FILE_MODE, ctx->pool)) != APR_SUCCESS) { @@ -239,18 +231,15 @@ static BOOL ssl_scache_dbm_retrieve(void *context, server_rec *s, const UCHAR *i "Cannot open SSLSessionCache DBM file `%s' for reading " "(fetch)", ctx->data_file); - ssl_mutex_off(s); return FALSE; } rc = apr_dbm_fetch(dbm, dbmkey, &dbmval); if (rc != APR_SUCCESS) { apr_dbm_close(dbm); - ssl_mutex_off(s); return FALSE; } if (dbmval.dptr == NULL || dbmval.dsize <= sizeof(time_t)) { apr_dbm_close(dbm); - ssl_mutex_off(s); return FALSE; } @@ -258,7 +247,6 @@ static BOOL ssl_scache_dbm_retrieve(void *context, server_rec *s, const UCHAR *i nData = dbmval.dsize-sizeof(time_t); if (nData > *destlen) { apr_dbm_close(dbm); - ssl_mutex_off(s); return FALSE; } @@ -267,7 +255,6 @@ static BOOL ssl_scache_dbm_retrieve(void *context, server_rec *s, const UCHAR *i memcpy(dest, (char *)dbmval.dptr + sizeof(time_t), nData); apr_dbm_close(dbm); - ssl_mutex_off(s); /* make sure the stuff is still not expired */ now = time(NULL); @@ -292,7 +279,6 @@ static void ssl_scache_dbm_remove(void *context, server_rec *s, UCHAR *id, int i dbmkey.dsize = idlen; /* and delete it from the DBM file */ - ssl_mutex_on(s); apr_pool_clear(ctx->pool); if ((rv = apr_dbm_open(&dbm, ctx->data_file, APR_DBM_RWCREATE, @@ -301,12 +287,10 @@ static void ssl_scache_dbm_remove(void *context, server_rec *s, UCHAR *id, int i "Cannot open SSLSessionCache DBM file `%s' for writing " "(delete)", ctx->data_file); - ssl_mutex_off(s); return; } apr_dbm_delete(dbm, dbmkey); apr_dbm_close(dbm); - ssl_mutex_off(s); return; } @@ -333,10 +317,7 @@ static void ssl_scache_dbm_expire(struct context *ctx, server_rec *s) */ tNow = time(NULL); - ssl_mutex_on(s); - if (tNow < ctx->last_expiry + sc->session_cache_timeout) { - ssl_mutex_off(s); return; } @@ -415,7 +396,6 @@ static void ssl_scache_dbm_expire(struct context *ctx, server_rec *s) if (keyidx < KEYMAX) break; } - ssl_mutex_off(s); ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "Inter-Process Session Cache (DBM) Expiry: " @@ -437,7 +417,6 @@ static void ssl_scache_dbm_status(void *context, request_rec *r, nElem = 0; nSize = 0; - ssl_mutex_on(r->server); apr_pool_clear(ctx->pool); if ((rv = apr_dbm_open(&dbm, ctx->data_file, APR_DBM_RWCREATE, @@ -446,7 +425,6 @@ static void ssl_scache_dbm_status(void *context, request_rec *r, "Cannot open SSLSessionCache DBM file `%s' for status " "retrival", ctx->data_file); - ssl_mutex_off(r->server); return; } /* @@ -461,7 +439,6 @@ static void ssl_scache_dbm_status(void *context, request_rec *r, nSize += dbmval.dsize; } apr_dbm_close(dbm); - ssl_mutex_off(r->server); if (nSize > 0 && nElem > 0) nAverage = nSize / nElem; else @@ -473,6 +450,8 @@ static void ssl_scache_dbm_status(void *context, request_rec *r, } const modssl_sesscache_provider modssl_sesscache_dbm = { + "dbm", + MODSSL_SESSCACHE_FLAG_NOTMPSAFE, ssl_scache_dbm_create, ssl_scache_dbm_init, ssl_scache_dbm_kill, diff --git a/modules/ssl/ssl_scache_dc.c b/modules/ssl/ssl_scache_dc.c index fa0ff5393c..9067db9165 100644 --- a/modules/ssl/ssl_scache_dc.c +++ b/modules/ssl/ssl_scache_dc.c @@ -171,6 +171,8 @@ static void ssl_scache_dc_status(void *context, request_rec *r, int flags, apr_p } const modssl_sesscache_provider modssl_sesscache_dc = { + "distcache", + 0, ssl_scache_dc_create, ssl_scache_dc_init, ssl_scache_dc_kill, diff --git a/modules/ssl/ssl_scache_memcache.c b/modules/ssl/ssl_scache_memcache.c index 52917e29ca..4622c223f3 100644 --- a/modules/ssl/ssl_scache_memcache.c +++ b/modules/ssl/ssl_scache_memcache.c @@ -292,6 +292,8 @@ static void ssl_scache_mc_status(void *context, request_rec *r, } const modssl_sesscache_provider modssl_sesscache_mc = { + "memcache", + 0, ssl_scache_mc_create, ssl_scache_mc_init, ssl_scache_mc_kill, diff --git a/modules/ssl/ssl_scache_shmcb.c b/modules/ssl/ssl_scache_shmcb.c index 6c9b114e8c..0eddf23549 100644 --- a/modules/ssl/ssl_scache_shmcb.c +++ b/modules/ssl/ssl_scache_shmcb.c @@ -429,33 +429,28 @@ static BOOL ssl_scache_shmcb_store(void *context, server_rec *s, unsigned char *encoded, unsigned int len_encoded) { - BOOL to_return = FALSE; struct context *ctx = context; SHMCBHeader *header = ctx->header; SHMCBSubcache *subcache = SHMCB_MASK(header, id); - ssl_mutex_on(s); ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "ssl_scache_shmcb_store (0x%02x -> subcache %d)", SHMCB_MASK_DBG(header, id)); if (idlen < 4) { ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, "unusably short session_id provided " "(%u bytes)", idlen); - goto done; + return FALSE; } if (!shmcb_subcache_store(s, header, subcache, encoded, len_encoded, id, idlen, timeout)) { ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, "can't store a session!"); - goto done; + return FALSE; } header->stat_stores++; - to_return = TRUE; ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "leaving ssl_scache_shmcb_store successfully"); -done: - ssl_mutex_off(s); - return to_return; + return TRUE; } static BOOL ssl_scache_shmcb_retrieve(void *context, server_rec *s, @@ -468,7 +463,6 @@ static BOOL ssl_scache_shmcb_retrieve(void *context, server_rec *s, SHMCBSubcache *subcache = SHMCB_MASK(header, id); BOOL rv; - ssl_mutex_on(s); ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "ssl_scache_shmcb_retrieve (0x%02x -> subcache %d)", SHMCB_MASK_DBG(header, id)); @@ -484,7 +478,6 @@ static BOOL ssl_scache_shmcb_retrieve(void *context, server_rec *s, ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "leaving ssl_scache_shmcb_retrieve successfully"); - ssl_mutex_off(s); return rv; } @@ -495,14 +488,13 @@ static void ssl_scache_shmcb_remove(void *context, server_rec *s, SHMCBHeader *header = ctx->header; SHMCBSubcache *subcache = SHMCB_MASK(header, id); - ssl_mutex_on(s); ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "ssl_scache_shmcb_remove (0x%02x -> subcache %d)", SHMCB_MASK_DBG(header, id)); if (idlen < 4) { ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, "unusably short session_id provided " "(%u bytes)", idlen); - goto done; + return; } if (shmcb_subcache_remove(s, header, subcache, id, idlen)) header->stat_removes_hit++; @@ -510,8 +502,6 @@ static void ssl_scache_shmcb_remove(void *context, server_rec *s, header->stat_removes_miss++; ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "leaving ssl_scache_shmcb_remove successfully"); -done: - ssl_mutex_off(s); } static void ssl_scache_shmcb_status(void *context, request_rec *r, @@ -530,7 +520,6 @@ static void ssl_scache_shmcb_status(void *context, request_rec *r, /* Perform the iteration inside the mutex to avoid corruption or invalid * pointer arithmetic. The rest of our logic uses read-only header data so * doesn't need the lock. */ - ssl_mutex_on(s); /* Iterate over the subcaches */ for (loop = 0; loop < header->subcache_num; loop++) { SHMCBSubcache *subcache = SHMCB_SUBCACHE(header, loop); @@ -549,7 +538,6 @@ static void ssl_scache_shmcb_status(void *context, request_rec *r, min_expiry = ((idx_expiry < min_expiry) ? idx_expiry : min_expiry); } } - ssl_mutex_off(s); index_pct = (100 * total) / (header->index_num * header->subcache_num); cache_pct = (100 * cache_total) / (header->subcache_data_size * @@ -832,6 +820,8 @@ static BOOL shmcb_subcache_remove(server_rec *s, SHMCBHeader *header, } const modssl_sesscache_provider modssl_sesscache_shmcb = { + "shmcb", + MODSSL_SESSCACHE_FLAG_NOTMPSAFE, ssl_scache_shmcb_create, ssl_scache_shmcb_init, ssl_scache_shmcb_kill, |