📄 ssl_engine_scache.c
字号:
dbmval = ssl_dbm_fetch(dbm, dbmkey); ssl_dbm_close(dbm); ssl_mutex_off(s); /* immediately return if not found */ if (dbmval.dptr == NULL || dbmval.dsize <= sizeof(time_t)) return; /* copy over the information to the SCI */ SCI->nData = dbmval.dsize-sizeof(time_t); SCI->ucaData = (UCHAR *)malloc(SCI->nData); if (SCI->ucaData == NULL) { SCI->nData = 0; return; } memcpy(SCI->ucaData, (char *)dbmval.dptr+sizeof(time_t), SCI->nData); memcpy(&SCI->tExpiresAt, dbmval.dptr, sizeof(time_t)); return;}void ssl_scache_dbm_remove(server_rec *s, ssl_scinfo_t *SCI){ SSLModConfigRec *mc = myModConfig(); DBM *dbm; datum dbmkey; /* create DBM key and values */ dbmkey.dptr = (char *)(SCI->ucaKey); dbmkey.dsize = SCI->nKey; /* and delete it from the DBM file */ ssl_mutex_on(s); if ((dbm = ssl_dbm_open(mc->szSessionCacheDataFile, O_RDWR, SSL_DBM_FILE_MODE)) == NULL) { ssl_log(s, SSL_LOG_ERROR|SSL_ADD_ERRNO, "Cannot open SSLSessionCache DBM file `%s' for writing (delete)", mc->szSessionCacheDataFile); ssl_mutex_off(s); return; } ssl_dbm_delete(dbm, dbmkey); ssl_dbm_close(dbm); ssl_mutex_off(s); return;}void ssl_scache_dbm_expire(server_rec *s, time_t tNow){ SSLModConfigRec *mc = myModConfig(); DBM *dbm; datum dbmkey; datum dbmval; pool *p; time_t tExpiresAt; int nElements = 0; int nDeleted = 0; int bDelete; datum *keylist; int keyidx; int i; /* * Here we have to be very carefully: Not all DBM libraries are * smart enough to allow one to iterate over the elements and at the * same time delete expired ones. Some of them get totally crazy * while others have no problems. So we have to do it the slower but * more safe way: we first iterate over all elements and remember * those which have to be expired. Then in a second pass we delete * all those expired elements. Additionally we reopen the DBM file * to be really safe in state. */#define KEYMAX 1024 ssl_mutex_on(s); for (;;) { /* allocate the key array in a memory sub pool */ if ((p = ap_make_sub_pool(NULL)) == NULL) break; if ((keylist = ap_palloc(p, sizeof(dbmkey)*KEYMAX)) == NULL) { ap_destroy_pool(p); break; } /* pass 1: scan DBM database */ keyidx = 0; if ((dbm = ssl_dbm_open(mc->szSessionCacheDataFile, O_RDWR, SSL_DBM_FILE_MODE)) == NULL) { ssl_log(s, SSL_LOG_ERROR|SSL_ADD_ERRNO, "Cannot open SSLSessionCache DBM file `%s' for scanning", mc->szSessionCacheDataFile); ap_destroy_pool(p); break; } dbmkey = ssl_dbm_firstkey(dbm); while (dbmkey.dptr != NULL) { nElements++; bDelete = FALSE; dbmval = ssl_dbm_fetch(dbm, dbmkey); if (dbmval.dsize <= sizeof(time_t) || dbmval.dptr == NULL) bDelete = TRUE; else { memcpy(&tExpiresAt, dbmval.dptr, sizeof(time_t)); if (tExpiresAt <= tNow) bDelete = TRUE; } if (bDelete) { if ((keylist[keyidx].dptr = ap_palloc(p, dbmkey.dsize)) != NULL) { memcpy(keylist[keyidx].dptr, dbmkey.dptr, dbmkey.dsize); keylist[keyidx].dsize = dbmkey.dsize; keyidx++; if (keyidx == KEYMAX) break; } } dbmkey = ssl_dbm_nextkey(dbm); } ssl_dbm_close(dbm); /* pass 2: delete expired elements */ if ((dbm = ssl_dbm_open(mc->szSessionCacheDataFile, O_RDWR, SSL_DBM_FILE_MODE)) == NULL) { ssl_log(s, SSL_LOG_ERROR|SSL_ADD_ERRNO, "Cannot re-open SSLSessionCache DBM file `%s' for expiring", mc->szSessionCacheDataFile); ap_destroy_pool(p); break; } for (i = 0; i < keyidx; i++) { ssl_dbm_delete(dbm, keylist[i]); nDeleted++; } ssl_dbm_close(dbm); /* destroy temporary pool */ ap_destroy_pool(p); if (keyidx < KEYMAX) break; } ssl_mutex_off(s); ssl_log(s, SSL_LOG_TRACE, "Inter-Process Session Cache (DBM) Expiry: " "old: %d, new: %d, removed: %d", nElements, nElements-nDeleted, nDeleted); return;}void ssl_scache_dbm_status(server_rec *s, pool *p, void (*func)(char *, void *), void *arg){ SSLModConfigRec *mc = myModConfig(); DBM *dbm; datum dbmkey; datum dbmval; int nElem; int nSize; int nAverage; nElem = 0; nSize = 0; ssl_mutex_on(s); if ((dbm = ssl_dbm_open(mc->szSessionCacheDataFile, O_RDONLY, SSL_DBM_FILE_MODE)) == NULL) { ssl_log(s, SSL_LOG_ERROR|SSL_ADD_ERRNO, "Cannot open SSLSessionCache DBM file `%s' for status retrival", mc->szSessionCacheDataFile); ssl_mutex_off(s); return; } dbmkey = ssl_dbm_firstkey(dbm); for ( ; dbmkey.dptr != NULL; dbmkey = ssl_dbm_nextkey(dbm)) { dbmval = ssl_dbm_fetch(dbm, dbmkey); if (dbmval.dptr == NULL) continue; nElem += 1; nSize += dbmval.dsize; } ssl_dbm_close(dbm); ssl_mutex_off(s); if (nSize > 0 && nElem > 0) nAverage = nSize / nElem; else nAverage = 0; func(ap_psprintf(p, "cache type: <b>DBM</b>, maximum size: <b>unlimited</b><br>"), arg); func(ap_psprintf(p, "current sessions: <b>%d</b>, current size: <b>%d</b> bytes<br>", nElem, nSize), arg); func(ap_psprintf(p, "average session size: <b>%d</b> bytes<br>", nAverage), arg); return;}/* _________________________________________________________________**** Session Cache Support (SHM)** _________________________________________________________________*//* * Wrapper functions for table library which resemble malloc(3) & Co * but use the variants from the MM shared memory library. */static void *ssl_scache_shm_malloc(size_t size){ SSLModConfigRec *mc = myModConfig(); return ap_mm_malloc(mc->pSessionCacheDataMM, size);}static void *ssl_scache_shm_calloc(size_t number, size_t size){ SSLModConfigRec *mc = myModConfig(); return ap_mm_calloc(mc->pSessionCacheDataMM, number, size);}static void *ssl_scache_shm_realloc(void *ptr, size_t size){ SSLModConfigRec *mc = myModConfig(); return ap_mm_realloc(mc->pSessionCacheDataMM, ptr, size);}static void ssl_scache_shm_free(void *ptr){ SSLModConfigRec *mc = myModConfig(); ap_mm_free(mc->pSessionCacheDataMM, ptr); return;}/* * Now the actual session cache implementation * based on a hash table inside a shared memory segment. */void ssl_scache_shm_init(server_rec *s, pool *p){ SSLModConfigRec *mc = myModConfig(); AP_MM *mm; table_t *ta; int ta_errno; int avail; int n; /* * Create shared memory segment */ if (mc->szSessionCacheDataFile == NULL) { ssl_log(s, SSL_LOG_ERROR, "SSLSessionCache required"); ssl_die(); } if ((mm = ap_mm_create(mc->nSessionCacheDataSize, mc->szSessionCacheDataFile)) == NULL) { ssl_log(s, SSL_LOG_ERROR, "Cannot allocate shared memory: %s", ap_mm_error()); ssl_die(); } mc->pSessionCacheDataMM = mm; /* * Make sure the childs have access to the underlaying files */ ap_mm_permission(mm, SSL_MM_FILE_MODE, ap_user_id, -1); /* * Create hash table in shared memory segment */ avail = ap_mm_available(mm); n = (avail/2) / 1024; n = n < 10 ? 10 : n; if ((ta = table_alloc(n, &ta_errno, ssl_scache_shm_malloc, ssl_scache_shm_calloc, ssl_scache_shm_realloc, ssl_scache_shm_free )) == NULL) { ssl_log(s, SSL_LOG_ERROR, "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 */ ssl_log(s, SSL_LOG_INFO, "Init: Created hash-table (%d buckets) " "in shared memory (%d bytes) for SSL session cache", n, avail); return;}void ssl_scache_shm_kill(server_rec *s){ SSLModConfigRec *mc = myModConfig(); if (mc->pSessionCacheDataMM != NULL) { ap_mm_destroy(mc->pSessionCacheDataMM); mc->pSessionCacheDataMM = NULL; } return;}BOOL ssl_scache_shm_store(server_rec *s, ssl_scinfo_t *SCI){ SSLModConfigRec *mc = myModConfig(); void *vp; ssl_mutex_on(s); if (table_insert_kd(mc->tSessionCacheDataTable, SCI->ucaKey, SCI->nKey, NULL, sizeof(time_t)+SCI->nData, NULL, &vp, 1) != TABLE_ERROR_NONE) { ssl_mutex_off(s); return FALSE; } memcpy(vp, &SCI->tExpiresAt, sizeof(time_t)); memcpy((char *)vp+sizeof(time_t), SCI->ucaData, SCI->nData); ssl_mutex_off(s); return TRUE;}void ssl_scache_shm_retrieve(server_rec *s, ssl_scinfo_t *SCI){ SSLModConfigRec *mc = myModConfig(); void *vp; int n; /* initialize result */ SCI->ucaData = NULL; SCI->nData = 0; SCI->tExpiresAt = 0; /* lookup key in table */ ssl_mutex_on(s); if (table_retrieve(mc->tSessionCacheDataTable, SCI->ucaKey, SCI->nKey, &vp, &n) != TABLE_ERROR_NONE) { ssl_mutex_off(s); return; } /* copy over the information to the SCI */ SCI->nData = n-sizeof(time_t); SCI->ucaData = (UCHAR *)malloc(SCI->nData); if (SCI->ucaData == NULL) { SCI->nData = 0; ssl_mutex_off(s); return; } memcpy(&SCI->tExpiresAt, vp, sizeof(time_t)); memcpy(SCI->ucaData, (char *)vp+sizeof(time_t), SCI->nData); ssl_mutex_off(s); return;}void ssl_scache_shm_remove(server_rec *s, ssl_scinfo_t *SCI){ SSLModConfigRec *mc = myModConfig(); /* remove value under key in table */ ssl_mutex_on(s); table_delete(mc->tSessionCacheDataTable, SCI->ucaKey, SCI->nKey, NULL, NULL); ssl_mutex_off(s); return;}void ssl_scache_shm_expire(server_rec *s, time_t tNow){ SSLModConfigRec *mc = myModConfig(); 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; 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)); 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); } ssl_mutex_off(s); ssl_log(s, SSL_LOG_TRACE, "Inter-Process Session Cache (SHM) Expiry: " "old: %d, new: %d, removed: %d", nElements, nElements-nDeleted, nDeleted); return;}void ssl_scache_shm_status(server_rec *s, pool *p, void (*func)(char *, void *), void *arg){ SSLModConfigRec *mc = myModConfig(); 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(ap_psprintf(p, "cache type: <b>SHM</b>, maximum size: <b>%d</b> bytes<br>", mc->nSessionCacheDataSize), arg); func(ap_psprintf(p, "current sessions: <b>%d</b>, current size: <b>%d</b> bytes<br>", nElem, nSize), arg); func(ap_psprintf(p, "average session size: <b>%d</b> bytes<br>", nAverage), arg); return;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -