📄 ssl_engine_scache.c
字号:
/* _ _** _ __ ___ ___ __| | ___ ___| | mod_ssl** | '_ ` _ \ / _ \ / _` | / __/ __| | Apache Interface to OpenSSL** | | | | | | (_) | (_| | \__ \__ \ | www.modssl.org** |_| |_| |_|\___/ \__,_|___|___/___/_| ftp.modssl.org** |_____|** ssl_engine_scache.c** Session Cache*//* ==================================================================== * Copyright (c) 1998-2000 Ralf S. Engelschall. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following * disclaimer in the documentation and/or other materials * provided with the distribution. * * 3. All advertising materials mentioning features or use of this * software must display the following acknowledgment: * "This product includes software developed by * Ralf S. Engelschall <rse@engelschall.com> for use in the * mod_ssl project (http://www.modssl.org/)." * * 4. The names "mod_ssl" must not be used to endorse or promote * products derived from this software without prior written * permission. For written permission, please contact * rse@engelschall.com. * * 5. Products derived from this software may not be called "mod_ssl" * nor may "mod_ssl" appear in their names without prior * written permission of Ralf S. Engelschall. * * 6. Redistributions of any form whatsoever must retain the following * acknowledgment: * "This product includes software developed by * Ralf S. Engelschall <rse@engelschall.com> for use in the * mod_ssl project (http://www.modssl.org/)." * * THIS SOFTWARE IS PROVIDED BY RALF S. ENGELSCHALL ``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. * ==================================================================== */ /* ``Open-Source Software: generous programmers from around the world all join forces to help you shoot yourself in the foot for free.'' -- Unknown */#include "mod_ssl.h"/* _________________________________________________________________**** Session Cache Support (Common)** _________________________________________________________________*//* * FIXME: There is no define in OpenSSL, but OpenSSL uses 1024*10, * so 1024*20 should be ok. */#define MAX_SESSION_DER 1024*20void ssl_scache_init(server_rec *s, pool *p){ SSLModConfigRec *mc = myModConfig(); if (mc->nSessionCacheMode == SSL_SCMODE_DBM) ssl_scache_dbm_init(s, p); else if (mc->nSessionCacheMode == SSL_SCMODE_SHM) ssl_scache_shm_init(s, p); ssl_scache_expire(s, time(NULL));#ifdef SSL_VENDOR ap_hook_use("ap::mod_ssl::vendor::scache_init", AP_HOOK_SIG3(void,ptr,ptr), AP_HOOK_ALL, s, p);#endif return;}void ssl_scache_kill(server_rec *s){ SSLModConfigRec *mc = myModConfig(); if (mc->nSessionCacheMode == SSL_SCMODE_DBM) ssl_scache_dbm_kill(s); else if (mc->nSessionCacheMode == SSL_SCMODE_SHM) ssl_scache_shm_kill(s);#ifdef SSL_VENDOR ap_hook_use("ap::mod_ssl::vendor::scache_kill", AP_HOOK_SIG1(void), AP_HOOK_ALL);#endif return;}BOOL ssl_scache_store(server_rec *s, SSL_SESSION *pSession, int timeout){ SSLModConfigRec *mc = myModConfig(); ssl_scinfo_t SCI; UCHAR buf[MAX_SESSION_DER]; UCHAR *b; BOOL rc = FALSE; /* add the key */ SCI.ucaKey = pSession->session_id; SCI.nKey = pSession->session_id_length; /* transform the session into a data stream */ SCI.ucaData = b = buf; SCI.nData = i2d_SSL_SESSION(pSession, &b); SCI.tExpiresAt = timeout; /* and store it... */ if (mc->nSessionCacheMode == SSL_SCMODE_DBM) rc = ssl_scache_dbm_store(s, &SCI); else if (mc->nSessionCacheMode == SSL_SCMODE_SHM) rc = ssl_scache_shm_store(s, &SCI);#ifdef SSL_VENDOR ap_hook_use("ap::mod_ssl::vendor::scache_store", AP_HOOK_SIG3(void,ptr,ptr), AP_HOOK_ALL, s, &SCI);#endif /* allow the regular expiring to occur */ ssl_scache_expire(s, time(NULL)); return rc;}SSL_SESSION *ssl_scache_retrieve(server_rec *s, UCHAR *id, int idlen){ SSLModConfigRec *mc = myModConfig(); SSL_SESSION *pSession = NULL; ssl_scinfo_t SCI; time_t tNow; /* determine current time */ tNow = time(NULL); /* allow the regular expiring to occur */ ssl_scache_expire(s, tNow); /* create cache query */ SCI.ucaKey = id; SCI.nKey = idlen; SCI.ucaData = NULL; SCI.nData = 0; SCI.tExpiresAt = 0; /* perform cache query */ if (mc->nSessionCacheMode == SSL_SCMODE_DBM) ssl_scache_dbm_retrieve(s, &SCI); else if (mc->nSessionCacheMode == SSL_SCMODE_SHM) ssl_scache_shm_retrieve(s, &SCI);#ifdef SSL_VENDOR ap_hook_use("ap::mod_ssl::vendor::scache_retrieve", AP_HOOK_SIG3(void,ptr,ptr), AP_HOOK_ALL, s, &SCI);#endif /* return immediately if not found */ if (SCI.ucaData == NULL) return NULL; /* check for expire time */ if (SCI.tExpiresAt <= tNow) { if (mc->nSessionCacheMode == SSL_SCMODE_DBM) ssl_scache_dbm_remove(s, &SCI); else if (mc->nSessionCacheMode == SSL_SCMODE_SHM) ssl_scache_shm_remove(s, &SCI);#ifdef SSL_VENDOR ap_hook_use("ap::mod_ssl::vendor::scache_remove", AP_HOOK_SIG3(void,ptr,ptr), AP_HOOK_ALL, s, &SCI);#endif return NULL; } /* extract result and return it */ pSession = d2i_SSL_SESSION(NULL, &SCI.ucaData, SCI.nData); return pSession;}void ssl_scache_remove(server_rec *s, SSL_SESSION *pSession){ SSLModConfigRec *mc = myModConfig(); ssl_scinfo_t SCI; /* create cache query */ SCI.ucaKey = pSession->session_id; SCI.nKey = pSession->session_id_length; SCI.ucaData = NULL; SCI.nData = 0; SCI.tExpiresAt = 0; /* perform remove */ if (mc->nSessionCacheMode == SSL_SCMODE_DBM) ssl_scache_dbm_remove(s, &SCI); else if (mc->nSessionCacheMode == SSL_SCMODE_SHM) ssl_scache_shm_remove(s, &SCI);#ifdef SSL_VENDOR ap_hook_use("ap::mod_ssl::vendor::scache_remove", AP_HOOK_SIG3(void,ptr,ptr), AP_HOOK_ALL, s, &SCI);#endif return;}void ssl_scache_expire(server_rec *s, time_t now){ SSLModConfigRec *mc = myModConfig(); SSLSrvConfigRec *sc = mySrvConfig(s); static time_t last = 0; /* * make sure the expiration for still not-accessed session * cache entries is done only from time to time */ if (now < last+sc->nSessionCacheTimeout) return; last = now; /* * Now perform the expiration */ if (mc->nSessionCacheMode == SSL_SCMODE_DBM) ssl_scache_dbm_expire(s, now); else if (mc->nSessionCacheMode == SSL_SCMODE_SHM) ssl_scache_shm_expire(s, now); return;}void ssl_scache_status(server_rec *s, pool *p, void (*func)(char *, void *), void *arg){ SSLModConfigRec *mc = myModConfig(); /* allow the regular expiring to occur */ ssl_scache_expire(s, time(NULL)); if (mc->nSessionCacheMode == SSL_SCMODE_DBM) ssl_scache_dbm_status(s, p, func, arg); else if (mc->nSessionCacheMode == SSL_SCMODE_SHM) ssl_scache_shm_status(s, p, func, arg); else func("N.A.", arg); return;}char *ssl_scache_id2sz(UCHAR *id, int idlen){ static char str[(SSL_MAX_SSL_SESSION_ID_LENGTH+1)*2]; char *cp; int n; cp = str; for (n = 0; n < idlen && n < SSL_MAX_SSL_SESSION_ID_LENGTH; n++) { ap_snprintf(cp, sizeof(str)-(cp-str), "%02X", id[n]); cp += 2; } *cp = NUL; return str;}/* _________________________________________________________________**** Session Cache Support (DBM)** _________________________________________________________________*/void ssl_scache_dbm_init(server_rec *s, pool *p){ SSLModConfigRec *mc = myModConfig(); DBM *dbm; /* * for the DBM we need the data file */ if (mc->szSessionCacheDataFile == NULL) { ssl_log(s, SSL_LOG_ERROR, "SSLSessionCache required"); ssl_die(); } /* * Open it once to create it and to make sure it * _can_ be created. */ ssl_mutex_on(s); if ((dbm = ssl_dbm_open(mc->szSessionCacheDataFile, O_RDWR|O_CREAT, SSL_DBM_FILE_MODE)) == NULL) { ssl_log(s, SSL_LOG_ERROR|SSL_ADD_ERRNO, "Cannot create SSLSessionCache DBM file `%s'", mc->szSessionCacheDataFile); ssl_mutex_off(s); return; } ssl_dbm_close(dbm);#if !defined(OS2) && !defined(WIN32) /* * We have to make sure the Apache child processes * have access to the DBM file. But because there * are brain-dead platforms where we cannot exactly * determine the suffixes we try all possibilities. */ if (geteuid() == 0 /* is superuser */) { chown(mc->szSessionCacheDataFile, ap_user_id, -1 /* no gid change */); if (chown(ap_pstrcat(p, mc->szSessionCacheDataFile, SSL_DBM_FILE_SUFFIX_DIR, NULL), ap_user_id, -1) == -1) { if (chown(ap_pstrcat(p, mc->szSessionCacheDataFile, ".db", NULL), ap_user_id, -1) == -1) chown(ap_pstrcat(p, mc->szSessionCacheDataFile, ".dir", NULL), ap_user_id, -1); } if (chown(ap_pstrcat(p, mc->szSessionCacheDataFile, SSL_DBM_FILE_SUFFIX_PAG, NULL), ap_user_id, -1) == -1) { if (chown(ap_pstrcat(p, mc->szSessionCacheDataFile, ".db", NULL), ap_user_id, -1) == -1) chown(ap_pstrcat(p, mc->szSessionCacheDataFile, ".pag", NULL), ap_user_id, -1); } }#endif ssl_mutex_off(s); return;}void ssl_scache_dbm_kill(server_rec *s){ SSLModConfigRec *mc = myModConfig(); pool *p; if ((p = ap_make_sub_pool(NULL)) != NULL) { /* the correct way */ unlink(ap_pstrcat(p, mc->szSessionCacheDataFile, SSL_DBM_FILE_SUFFIX_DIR, NULL)); unlink(ap_pstrcat(p, mc->szSessionCacheDataFile, SSL_DBM_FILE_SUFFIX_PAG, NULL)); /* the additional ways to be sure */ unlink(ap_pstrcat(p, mc->szSessionCacheDataFile, ".dir", NULL)); unlink(ap_pstrcat(p, mc->szSessionCacheDataFile, ".pag", NULL)); unlink(ap_pstrcat(p, mc->szSessionCacheDataFile, ".db", NULL)); unlink(mc->szSessionCacheDataFile); ap_destroy_pool(p); } return;}BOOL ssl_scache_dbm_store(server_rec *s, ssl_scinfo_t *SCI){ SSLModConfigRec *mc = myModConfig(); DBM *dbm; datum dbmkey; datum dbmval; /* be careful: do not try to store too much bytes in a DBM file! */#ifdef SSL_USE_SDBM if ((SCI->nKey + SCI->nData) >= PAIRMAX) return FALSE;#else if ((SCI->nKey + SCI->nData) >= 950 /* at least less than approx. 1KB */) return FALSE;#endif /* create DBM key */ dbmkey.dptr = (char *)(SCI->ucaKey); dbmkey.dsize = SCI->nKey; /* create DBM value */ dbmval.dsize = sizeof(time_t) + SCI->nData; dbmval.dptr = (char *)malloc(dbmval.dsize); if (dbmval.dptr == NULL) return FALSE; memcpy((char *)dbmval.dptr, &SCI->tExpiresAt, sizeof(time_t)); memcpy((char *)dbmval.dptr+sizeof(time_t), SCI->ucaData, SCI->nData); /* and store it to 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 (store)", mc->szSessionCacheDataFile); ssl_mutex_off(s); free(dbmval.dptr); return FALSE; } if (ssl_dbm_store(dbm, dbmkey, dbmval, DBM_INSERT) < 0) { ssl_log(s, SSL_LOG_ERROR|SSL_ADD_ERRNO, "Cannot store SSL session to DBM file `%s'", mc->szSessionCacheDataFile); ssl_dbm_close(dbm); ssl_mutex_off(s); free(dbmval.dptr); return FALSE; } ssl_dbm_close(dbm); ssl_mutex_off(s); /* free temporary buffers */ free(dbmval.dptr); return TRUE;}void ssl_scache_dbm_retrieve(server_rec *s, ssl_scinfo_t *SCI){ SSLModConfigRec *mc = myModConfig(); DBM *dbm; datum dbmkey; datum dbmval; /* initialize result */ SCI->ucaData = NULL; SCI->nData = 0; SCI->tExpiresAt = 0; /* create DBM key and values */ dbmkey.dptr = (char *)(SCI->ucaKey); dbmkey.dsize = SCI->nKey; /* and fetch it from the DBM file */ 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 reading (fetch)", mc->szSessionCacheDataFile); ssl_mutex_off(s); return; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -