⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ssl_scache_shmcb.c

📁 mod_ssl-2.8.31-1.3.41.tar.gz 好用的ssl工具
💻 C
📖 第 1 页 / 共 4 页
字号:
/*                      _             _**  _ __ ___   ___   __| |    ___ ___| |  mod_ssl** | '_ ` _ \ / _ \ / _` |   / __/ __| |  Apache Interface to OpenSSL** | | | | | | (_) | (_| |   \__ \__ \ |  www.modssl.org** |_| |_| |_|\___/ \__,_|___|___/___/_|  ftp.modssl.org**                      |_____|**  ssl_scache_shmcb.c**  Session Cache via Shared Memory (Cyclic Buffer Variant)*//* ==================================================================== * Copyright (c) 2000-2004 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. * ==================================================================== */#include "mod_ssl.h"/*  * This shared memory based SSL session cache implementation was * originally written by Geoff Thorpe <geoff@geoffthorpe.net> for C2Net  * Europe and as a contribution to Ralf Engelschall's mod_ssl project. *//* * The shared-memory segment header can be cast to and from the * SHMCBHeader type, all other structures need to be initialised by * utility functions. * * The "header" looks like this; * * data applying to the overall structure: * - division_offset (unsigned int): *   how far into the shared memory segment the first division is. * - division_size (unsigned int): *   how many bytes each division occupies. *   (NB: This includes the queue and the cache) * - division_mask (unsigned char): *   the "mask" in the next line. Add one to this, *   and that's the number of divisions. * * data applying to within each division: * - queue_size (unsigned int): *   how big each "queue" is. NB: The queue is the first block in each *   division and is followed immediately by the cache itself so so *   there's no cache_offset value. * * data applying to within each queue: * - index_num (unsigned char): *   how many indexes in each cache's queue * - index_offset (unsigned char): *   how far into the queue the first index is. * - index_size: *   how big each index is. * * data applying to within each cache: * - cache_data_offset (unsigned int): *   how far into the cache the session-data array is stored. * - cache_data_size (unsigned int): *   how big each cache's data block is. * * statistics data (this will eventually be per-division but right now * there's only one mutex): * - stores (unsigned long): *   how many stores have been performed in the cache. * - expiries (unsigned long): *   how many session have been expired from the cache. * - scrolled (unsigned long): *   how many sessions have been scrolled out of full cache during a *   "store" operation. This is different to the "removes" stats as *   they are requested by mod_ssl/Apache, these are done because of *   cache logistics. (NB: Also, this value should be deducible from *   the others if my code has no bugs, but I count it anyway - plus *   it helps debugging :-). * - retrieves_hit (unsigned long): *   how many session-retrieves have succeeded. * - retrieves_miss (unsigned long): *   how many session-retrieves have failed. * - removes_hit (unsigned long): * - removes_miss (unsigned long): *  * Following immediately after the header is an array of "divisions". * Each division is simply a "queue" immediately followed by its * corresponding "cache". Each division handles some pre-defined band * of sessions by using the "division_mask" in the header. Eg. if * division_mask=0x1f then there are 32 divisions, the first of which * will store sessions whose least-significant 5 bits are 0, the second * stores session whose LS 5 bits equal 1, etc. A queue is an indexing * structure referring to its corresponding cache. * * A "queue" looks like this; * * - first_pos (unsigned int): *   the location within the array of indexes where the virtual *   "left-hand-edge" of the cyclic buffer is. * - pos_count (unsigned int): *   the number of indexes occupied from first_pos onwards. * * ...followed by an array of indexes, each of which can be * memcpy'd to and from an SHMCBIndex, and look like this; * * - expires (time_t): *   the time() value at which this session expires. * - offset (unsigned int): *   the offset within the cache data block where the corresponding *   session is stored. * - s_id2 (unsigned char): *   the second byte of the session_id, stored as an optimisation to *   reduce the number of d2i_SSL_SESSION calls that are made when doing *   a lookup. * - removed (unsigned char): *   a byte used to indicate whether a session has been "passively" *   removed. Ie. it is still in the cache but is to be disregarded by *   any "retrieve" operation. * * A "cache" looks like this; * * - first_pos (unsigned int): *   the location within the data block where the virtual *   "left-hand-edge" of the cyclic buffer is. * - pos_count (unsigned int): *   the number of bytes used in the data block from first_pos onwards. * * ...followed by the data block in which actual DER-encoded SSL * sessions are stored. *//*  * Header - can be memcpy'd to and from the front of the shared * memory segment. NB: The first copy (commented out) has the * elements in a meaningful order, but due to data-alignment * braindeadness, the second (uncommented) copy has the types grouped * so as to decrease "struct-bloat". sigh. */typedef struct {#if 0    unsigned char division_mask;    unsigned int division_offset;    unsigned int division_size;    unsigned int queue_size;    unsigned int index_num;    unsigned int index_offset;    unsigned int index_size;    unsigned int cache_data_offset;    unsigned int cache_data_size;    unsigned long num_stores;    unsigned long num_expiries;    unsigned long num_scrolled;    unsigned long num_retrieves_hit;    unsigned long num_retrieves_miss;    unsigned long num_removes_hit;    unsigned long num_removes_miss;#else    unsigned long num_stores;    unsigned long num_expiries;    unsigned long num_scrolled;    unsigned long num_retrieves_hit;    unsigned long num_retrieves_miss;    unsigned long num_removes_hit;    unsigned long num_removes_miss;    unsigned int division_offset;    unsigned int division_size;    unsigned int queue_size;    unsigned int cache_data_offset;    unsigned int cache_data_size;    unsigned char division_mask;    unsigned int index_num;    unsigned int index_offset;    unsigned int index_size;#endif} SHMCBHeader;/*  * Index - can be memcpy'd to and from an index inside each * queue's index array. */typedef struct {    time_t expires;    unsigned int offset;    unsigned char s_id2;    unsigned char removed;} SHMCBIndex;/*  * Queue - must be populated by a call to shmcb_get_division * and the structure's pointers are used for updating (ie. * the structure doesn't need any "set" to update values). */typedef struct {    SHMCBHeader *header;    unsigned int *first_pos;    unsigned int *pos_count;    SHMCBIndex *indexes;} SHMCBQueue;/*  * Cache - same comment as for Queue. 'Queue's are in a 1-1 * correspondance with 'Cache's and are usually carried round * in a pair, they are only seperated for clarity. */typedef struct {    SHMCBHeader *header;    unsigned int *first_pos;    unsigned int *pos_count;    unsigned char *data;} SHMCBCache;/* * Forward function prototypes. *//* Functions for working around data-alignment-picky systems (sparcs,   Irix, etc). These use "memcpy" as a way of foxing these systems into   treating the composite types as byte-arrays rather than higher-level   primitives that it prefers to have 4-(or 8-)byte aligned. I don't   envisage this being a performance issue as a couple of 2 or 4 byte   memcpys can hardly make a dent on the massive memmove operations this   cache technique avoids, nor the overheads of ASN en/decoding. */static unsigned int shmcb_get_safe_uint(unsigned int *);static void shmcb_set_safe_uint_ex(unsigned char *, const unsigned char *);#define shmcb_set_safe_uint(pdest, src) \	do { \		unsigned int tmp_uint = src; \		shmcb_set_safe_uint_ex((unsigned char *)pdest, \			(const unsigned char *)(&tmp_uint)); \	} while(0)#if 0 /* Unused so far */static unsigned long shmcb_get_safe_ulong(unsigned long *);static void shmcb_set_safe_ulong_ex(unsigned char *, const unsigned char *);#define shmcb_set_safe_ulong(pdest, src) \	do { \		unsigned long tmp_ulong = src; \		shmcb_set_safe_ulong_ex((unsigned char *)pdest, \			(const unsigned char *)(&tmp_ulong)); \	} while(0)#endifstatic time_t shmcb_get_safe_time(time_t *);static void shmcb_set_safe_time_ex(unsigned char *, const unsigned char *);#define shmcb_set_safe_time(pdest, src) \	do { \		time_t tmp_time = src; \		shmcb_set_safe_time_ex((unsigned char *)pdest, \			(const unsigned char *)(&tmp_time)); \	} while(0)/* This is necessary simply so that the size passed to memset() is not a * compile-time constant, preventing the compiler from optimising it. */static void shmcb_safe_clear(void *ptr, size_t size){	memset(ptr, 0, size);}/* Underlying functions for session-caching */static BOOL shmcb_init_memory(server_rec *, void *, unsigned int);static BOOL shmcb_store_session(server_rec *, void *, UCHAR *, int, SSL_SESSION *, time_t);static SSL_SESSION *shmcb_retrieve_session(server_rec *, void *, UCHAR *, int);static BOOL shmcb_remove_session(server_rec *, void *, UCHAR *, int);/* Utility functions for manipulating the structures */static void shmcb_get_header(void *, SHMCBHeader **);static BOOL shmcb_get_division(SHMCBHeader *, SHMCBQueue *, SHMCBCache *, unsigned int);static SHMCBIndex *shmcb_get_index(const SHMCBQueue *, unsigned int);static unsigned int shmcb_expire_division(server_rec *, SHMCBQueue *, SHMCBCache *);static BOOL shmcb_insert_encoded_session(server_rec *, SHMCBQueue *, SHMCBCache *, unsigned char *, unsigned int, unsigned char *, time_t);static SSL_SESSION *shmcb_lookup_session_id(server_rec *, SHMCBQueue *, SHMCBCache *, UCHAR *, int);static BOOL shmcb_remove_session_id(server_rec *, SHMCBQueue *, SHMCBCache *, UCHAR *, int);/* * Data-alignment functions (a.k.a. avoidance tactics) * * NB: On HPUX (and possibly others) there is a *very* mischievous little * "optimisation" in the compilers where it will convert the following; *      memcpy(dest_ptr, &source, sizeof(unsigned int)); * (where dest_ptr is of type (unsigned int *) and source is (unsigned int)) * into; *      *dest_ptr = source; (or *dest_ptr = *(&source), not sure). * Either way, it completely destroys the whole point of these _safe_ * functions, because the assignment operation will fall victim to the * architecture's byte-alignment dictations, whereas the memcpy (as a * byte-by-byte copy) should not. sigh. So, if you're wondering about the * apparently unnecessary conversions to (unsigned char *) in these * functions, you now have an explanation. Don't just revert them back and * say "ooh look, it still works" - if you try it on HPUX (well, 32-bit * HPUX 11.00 at least) you may find it fails with a SIGBUS. :-( */static unsigned int shmcb_get_safe_uint(unsigned int *ptr){    unsigned int ret;    shmcb_set_safe_uint_ex((unsigned char *)(&ret),		    (const unsigned char *)ptr);    return ret;}static void shmcb_set_safe_uint_ex(unsigned char *dest,				const unsigned char *src){    memcpy(dest, src, sizeof(unsigned int));

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -