diff options
Diffstat (limited to 'rubbos/app/httpd-2.0.64/modules/ssl/ssl_scache_shmht.c')
-rw-r--r-- | rubbos/app/httpd-2.0.64/modules/ssl/ssl_scache_shmht.c | 351 |
1 files changed, 351 insertions, 0 deletions
diff --git a/rubbos/app/httpd-2.0.64/modules/ssl/ssl_scache_shmht.c b/rubbos/app/httpd-2.0.64/modules/ssl/ssl_scache_shmht.c new file mode 100644 index 00000000..28def647 --- /dev/null +++ b/rubbos/app/httpd-2.0.64/modules/ssl/ssl_scache_shmht.c @@ -0,0 +1,351 @@ +/* Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* _ _ + * _ __ ___ ___ __| | ___ ___| | mod_ssl + * | '_ ` _ \ / _ \ / _` | / __/ __| | Apache Interface to OpenSSL + * | | | | | | (_) | (_| | \__ \__ \ | + * |_| |_| |_|\___/ \__,_|___|___/___/_| + * |_____| + * ssl_scache_shmht.c + * Session Cache via Shared Memory (Hash Table Variant) + */ + +#include "mod_ssl.h" + +/* + * Wrapper functions for table library which resemble malloc(3) & Co + * but use the variants from the MM shared memory library. + */ + +static void *ssl_scache_shmht_malloc(void *opt_param, size_t size) +{ + SSLModConfigRec *mc = myModConfig((server_rec *)opt_param); + + apr_rmm_off_t off = apr_rmm_calloc(mc->pSessionCacheDataRMM, size); + return apr_rmm_addr_get(mc->pSessionCacheDataRMM, off); +} + +static void *ssl_scache_shmht_calloc(void *opt_param, + size_t number, size_t size) +{ + SSLModConfigRec *mc = myModConfig((server_rec *)opt_param); + + apr_rmm_off_t off = apr_rmm_calloc(mc->pSessionCacheDataRMM, (number*size)); + + return apr_rmm_addr_get(mc->pSessionCacheDataRMM, off); +} + +static void *ssl_scache_shmht_realloc(void *opt_param, void *ptr, size_t size) +{ + SSLModConfigRec *mc = myModConfig((server_rec *)opt_param); + + apr_rmm_off_t off = apr_rmm_realloc(mc->pSessionCacheDataRMM, ptr, size); + return apr_rmm_addr_get(mc->pSessionCacheDataRMM, off); +} + +static void ssl_scache_shmht_free(void *opt_param, void *ptr) +{ + SSLModConfigRec *mc = myModConfig((server_rec *)opt_param); + + apr_rmm_off_t off = apr_rmm_offset_get(mc->pSessionCacheDataRMM, ptr); + apr_rmm_free(mc->pSessionCacheDataRMM, off); + return; +} + +/* + * Now the actual session cache implementation + * based on a hash table inside a shared memory segment. + */ + +void ssl_scache_shmht_init(server_rec *s, apr_pool_t *p) +{ + SSLModConfigRec *mc = myModConfig(s); + table_t *ta; + int ta_errno; + apr_size_t avail; + int n; + apr_status_t rv; + + /* + * Create shared memory segment + */ + if (mc->szSessionCacheDataFile == NULL) { + ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, + "SSLSessionCache required"); + ssl_die(); + } + + if ((rv = apr_shm_create(&(mc->pSessionCacheDataMM), + mc->nSessionCacheDataSize, + mc->szSessionCacheDataFile, mc->pPool)) != APR_SUCCESS) { + ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, + "Cannot allocate shared memory"); + ssl_die(); + } + + if ((rv = apr_rmm_init(&(mc->pSessionCacheDataRMM), NULL, + apr_shm_baseaddr_get(mc->pSessionCacheDataMM), + mc->nSessionCacheDataSize, mc->pPool)) != APR_SUCCESS) { + ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, + "Cannot initialize rmm"); + ssl_die(); + } + ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, + "initialize MM %pp RMM %pp", + mc->pSessionCacheDataMM, mc->pSessionCacheDataRMM); + + /* + * Create hash table in shared memory segment + */ + avail = mc->nSessionCacheDataSize; + n = (avail/2) / 1024; + n = n < 10 ? 10 : n; + + /* + * Passing server_rec as opt_param to table_alloc so that we can do + * logging if required ssl_util_table. Otherwise, mc is sufficient. + */ + if ((ta = table_alloc(n, &ta_errno, + ssl_scache_shmht_malloc, + ssl_scache_shmht_calloc, + ssl_scache_shmht_realloc, + ssl_scache_shmht_free, s )) == NULL) { + ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, + "Cannot allocate hash table in shared memory: %s", + table_strerror(ta_errno)); + ssl_die(); + } + + table_attr(ta, TABLE_FLAG_AUTO_ADJUST|TABLE_FLAG_ADJUST_DOWN); + table_set_data_alignment(ta, sizeof(char *)); + table_clear(ta); + mc->tSessionCacheDataTable = ta; + + /* + * Log the done work + */ + ap_log_error(APLOG_MARK, APLOG_INFO, 0, s, + "Init: Created hash-table (%d buckets) " + "in shared memory (%" APR_SIZE_T_FMT + " bytes) for SSL session cache", + n, avail); + return; +} + +void ssl_scache_shmht_kill(server_rec *s) +{ + SSLModConfigRec *mc = myModConfig(s); + + if (mc->pSessionCacheDataRMM != NULL) { + apr_rmm_destroy(mc->pSessionCacheDataRMM); + mc->pSessionCacheDataRMM = NULL; + } + + if (mc->pSessionCacheDataMM != NULL) { + apr_shm_destroy(mc->pSessionCacheDataMM); + mc->pSessionCacheDataMM = NULL; + } + return; +} + +BOOL ssl_scache_shmht_store(server_rec *s, UCHAR *id, int idlen, time_t expiry, SSL_SESSION *sess) +{ + SSLModConfigRec *mc = myModConfig(s); + void *vp; + UCHAR ucaData[SSL_SESSION_MAX_DER]; + int nData; + UCHAR *ucp; + + /* streamline session data */ + if ((nData = i2d_SSL_SESSION(sess, NULL)) > sizeof(ucaData)) + return FALSE; + ucp = ucaData; + i2d_SSL_SESSION(sess, &ucp); + + ssl_mutex_on(s); + if (table_insert_kd(mc->tSessionCacheDataTable, + id, idlen, NULL, sizeof(time_t)+nData, + NULL, &vp, 1) != TABLE_ERROR_NONE) { + ssl_mutex_off(s); + return FALSE; + } + memcpy(vp, &expiry, sizeof(time_t)); + memcpy((char *)vp+sizeof(time_t), ucaData, nData); + ssl_mutex_off(s); + + /* allow the regular expiring to occur */ + ssl_scache_shmht_expire(s); + + return TRUE; +} + +SSL_SESSION *ssl_scache_shmht_retrieve(server_rec *s, UCHAR *id, int idlen) +{ + SSLModConfigRec *mc = myModConfig(s); + void *vp; + SSL_SESSION *sess = NULL; + MODSSL_D2I_SSL_SESSION_CONST UCHAR *ucpData; + int nData; + time_t expiry; + time_t now; + int n; + + /* allow the regular expiring to occur */ + ssl_scache_shmht_expire(s); + + /* lookup key in table */ + ssl_mutex_on(s); + if (table_retrieve(mc->tSessionCacheDataTable, + id, idlen, &vp, &n) != TABLE_ERROR_NONE) { + ssl_mutex_off(s); + return NULL; + } + + /* copy over the information to the SCI */ + nData = n-sizeof(time_t); + ucpData = (UCHAR *)malloc(nData); + if (ucpData == NULL) { + ssl_mutex_off(s); + return NULL; + } + memcpy(&expiry, vp, sizeof(time_t)); + memcpy((void *)ucpData, (char *)vp+sizeof(time_t), nData); + ssl_mutex_off(s); + + /* make sure the stuff is still not expired */ + now = time(NULL); + if (expiry <= now) { + ssl_scache_shmht_remove(s, id, idlen); + return NULL; + } + + /* unstreamed SSL_SESSION */ + sess = d2i_SSL_SESSION(NULL, &ucpData, nData); + + return sess; +} + +void ssl_scache_shmht_remove(server_rec *s, UCHAR *id, int idlen) +{ + SSLModConfigRec *mc = myModConfig(s); + + /* remove value under key in table */ + ssl_mutex_on(s); + table_delete(mc->tSessionCacheDataTable, id, idlen, NULL, NULL); + ssl_mutex_off(s); + return; +} + +void ssl_scache_shmht_expire(server_rec *s) +{ + SSLModConfigRec *mc = myModConfig(s); + SSLSrvConfigRec *sc = mySrvConfig(s); + static time_t tLast = 0; + table_linear_t iterator; + time_t tExpiresAt; + void *vpKey; + void *vpKeyThis; + void *vpData; + int nKey; + int nKeyThis; + int nData; + int nElements = 0; + int nDeleted = 0; + int bDelete; + int rc; + time_t tNow; + + /* + * make sure the expiration for still not-accessed session + * cache entries is done only from time to time + */ + tNow = time(NULL); + if (tNow < tLast+sc->session_cache_timeout) + return; + tLast = tNow; + + ssl_mutex_on(s); + if (table_first_r(mc->tSessionCacheDataTable, &iterator, + &vpKey, &nKey, &vpData, &nData) == TABLE_ERROR_NONE) { + do { + bDelete = FALSE; + nElements++; + if (nData < sizeof(time_t) || vpData == NULL) + bDelete = TRUE; + else { + memcpy(&tExpiresAt, vpData, sizeof(time_t)); + /* + * XXX : Force the record to be cleaned up. TBD (Madhu) + * tExpiresAt = tNow; + */ + if (tExpiresAt <= tNow) + bDelete = TRUE; + } + vpKeyThis = vpKey; + nKeyThis = nKey; + rc = table_next_r(mc->tSessionCacheDataTable, &iterator, + &vpKey, &nKey, &vpData, &nData); + if (bDelete) { + table_delete(mc->tSessionCacheDataTable, + vpKeyThis, nKeyThis, NULL, NULL); + nDeleted++; + } + } while (rc == TABLE_ERROR_NONE); + /* (vpKeyThis != vpKey) && (nKeyThis != nKey) */ + } + ssl_mutex_off(s); + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, + "Inter-Process Session Cache (SHMHT) Expiry: " + "old: %d, new: %d, removed: %d", + nElements, nElements-nDeleted, nDeleted); + return; +} + +void ssl_scache_shmht_status(server_rec *s, apr_pool_t *p, void (*func)(char *, void *), void *arg) +{ + SSLModConfigRec *mc = myModConfig(s); + void *vpKey; + void *vpData; + int nKey; + int nData; + int nElem; + int nSize; + int nAverage; + + nElem = 0; + nSize = 0; + ssl_mutex_on(s); + if (table_first(mc->tSessionCacheDataTable, + &vpKey, &nKey, &vpData, &nData) == TABLE_ERROR_NONE) { + do { + if (vpKey == NULL || vpData == NULL) + continue; + nElem += 1; + nSize += nData; + } while (table_next(mc->tSessionCacheDataTable, + &vpKey, &nKey, &vpData, &nData) == TABLE_ERROR_NONE); + } + ssl_mutex_off(s); + if (nSize > 0 && nElem > 0) + nAverage = nSize / nElem; + else + nAverage = 0; + func(apr_psprintf(p, "cache type: <b>SHMHT</b>, maximum size: <b>%d</b> bytes<br>", mc->nSessionCacheDataSize), arg); + func(apr_psprintf(p, "current sessions: <b>%d</b>, current size: <b>%d</b> bytes<br>", nElem, nSize), arg); + func(apr_psprintf(p, "average session size: <b>%d</b> bytes<br>", nAverage), arg); + return; +} |