Return-Path: Delivered-To: apmail-httpd-cvs-archive@www.apache.org Received: (qmail 81337 invoked from network); 22 Feb 2008 19:59:12 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.2) by minotaur.apache.org with SMTP; 22 Feb 2008 19:59:12 -0000 Received: (qmail 28051 invoked by uid 500); 22 Feb 2008 19:59:06 -0000 Delivered-To: apmail-httpd-cvs-archive@httpd.apache.org Received: (qmail 27996 invoked by uid 500); 22 Feb 2008 19:59:06 -0000 Mailing-List: contact cvs-help@httpd.apache.org; run by ezmlm Precedence: bulk Reply-To: dev@httpd.apache.org list-help: list-unsubscribe: List-Post: List-Id: Delivered-To: mailing list cvs@httpd.apache.org Received: (qmail 27985 invoked by uid 99); 22 Feb 2008 19:59:06 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 22 Feb 2008 11:59:06 -0800 X-ASF-Spam-Status: No, hits=-2000.0 required=10.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.3] (HELO eris.apache.org) (140.211.11.3) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 22 Feb 2008 19:58:26 +0000 Received: by eris.apache.org (Postfix, from userid 65534) id B995D1A983A; Fri, 22 Feb 2008 11:58:45 -0800 (PST) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r630307 - in /httpd/httpd/trunk/modules/ssl: ssl_private.h ssl_scache.c ssl_scache_dbm.c ssl_scache_dc.c ssl_scache_memcache.c ssl_scache_shmcb.c Date: Fri, 22 Feb 2008 19:58:43 -0000 To: cvs@httpd.apache.org From: jorton@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20080222195845.B995D1A983A@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: jorton Date: Fri Feb 22 11:58:39 2008 New Revision: 630307 URL: http://svn.apache.org/viewvc?rev=630307&view=rev Log: Move SSL session data deserialization up out of the session cache storage providers; includes a significant change to the shmcb storage structure: * modules/ssl/ssl_private.h (modssl_sesscache_provider): Change retrieve function to take dest/destlen output buffer, to take a constant id paramater, and to return a BOOL. * modules/ssl/ssl_scache.c (ssl_scache_retrieve): Update accordingly, perform SSL deserialization here. * modules/ssl/ssl_scache_dc.c (ssl_scache_dc_retrieve), modules/ssl/ssl_scache_dbm.c (ssl_scache_dbm_retrieve), modules/ssl/ssl_scache_memcache.c (ssl_scache_mc_retrieve): Update accordingly. * modules/ssl/ssl_scache_shmcb.c: Store the whole ID in the cache before the data, so that each index can be compared against the requested ID without deserializing the data. This requires approx 20% extra storage per session in the common case, though should reduce CPU overhead in some retrieval paths. (SHMCBIndex): Replace s_id2 field with id_len. (shmcb_cyclic_memcmp): New function. (ssl_scache_shmcb_init): Change the heuristics to allow for increase in per-session storage requirement. (ssl_scache_shmcb_retrieve): Drop requirement on ID length. (shmcb_subcache_store): Store the ID in the cyclic buffer. (shmcb_subcache_retrieve, shmcb_subcache_remove): Compare against the stored ID rather than deserializing the data. (ssl_scache_shmcb_retrieve, ssl_scache_shmcb_store): Update accordingly. Modified: httpd/httpd/trunk/modules/ssl/ssl_private.h httpd/httpd/trunk/modules/ssl/ssl_scache.c httpd/httpd/trunk/modules/ssl/ssl_scache_dbm.c httpd/httpd/trunk/modules/ssl/ssl_scache_dc.c httpd/httpd/trunk/modules/ssl/ssl_scache_memcache.c httpd/httpd/trunk/modules/ssl/ssl_scache_shmcb.c Modified: httpd/httpd/trunk/modules/ssl/ssl_private.h URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/ssl/ssl_private.h?rev=630307&r1=630306&r2=630307&view=diff ============================================================================== --- httpd/httpd/trunk/modules/ssl/ssl_private.h (original) +++ httpd/httpd/trunk/modules/ssl/ssl_private.h Fri Feb 22 11:58:39 2008 @@ -371,8 +371,14 @@ BOOL (*store)(server_rec *s, UCHAR *id, int idlen, time_t expiry, unsigned char *data, unsigned int datalen); - SSL_SESSION *(*retrieve)(server_rec *s, UCHAR *id, int idlen, - apr_pool_t *pool); + /* Retrieve cached data with key ID of length IDLEN, + * returning TRUE on success or FALSE otherwise. If + * TRUE, the data must be placed in DEST, which has length + * on entry of *DESTLEN. *DESTLEN must be updated to + * equal the length of data written on exit. */ + BOOL (*retrieve)(server_rec *s, const UCHAR *id, int idlen, + unsigned char *dest, unsigned int *destlen, + apr_pool_t *pool); void (*delete)(server_rec *s, UCHAR *id, int idlen, apr_pool_t *pool); void (*status)(request_rec *r, int flags, apr_pool_t *pool); } modssl_sesscache_provider; Modified: httpd/httpd/trunk/modules/ssl/ssl_scache.c URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/ssl/ssl_scache.c?rev=630307&r1=630306&r2=630307&view=diff ============================================================================== --- httpd/httpd/trunk/modules/ssl/ssl_scache.c (original) +++ httpd/httpd/trunk/modules/ssl/ssl_scache.c Fri Feb 22 11:58:39 2008 @@ -88,8 +88,17 @@ apr_pool_t *p) { SSLModConfigRec *mc = myModConfig(s); + 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(s, id, idlen, dest, &destlen, p) == FALSE) { + return NULL; + } - return mc->sesscache->retrieve(s, id, idlen, p); + ptr = dest; + + return d2i_SSL_SESSION(NULL, &ptr, destlen); } void ssl_scache_remove(server_rec *s, UCHAR *id, int idlen, Modified: httpd/httpd/trunk/modules/ssl/ssl_scache_dbm.c URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/ssl/ssl_scache_dbm.c?rev=630307&r1=630306&r2=630307&view=diff ============================================================================== --- httpd/httpd/trunk/modules/ssl/ssl_scache_dbm.c (original) +++ httpd/httpd/trunk/modules/ssl/ssl_scache_dbm.c Fri Feb 22 11:58:39 2008 @@ -188,16 +188,15 @@ return TRUE; } -static SSL_SESSION *ssl_scache_dbm_retrieve(server_rec *s, UCHAR *id, int idlen, - apr_pool_t *p) +static BOOL ssl_scache_dbm_retrieve(server_rec *s, const UCHAR *id, int idlen, + unsigned char *dest, unsigned int *destlen, + apr_pool_t *p) { SSLModConfigRec *mc = myModConfig(s); apr_dbm_t *dbm; apr_datum_t dbmkey; apr_datum_t dbmval; - SSL_SESSION *sess = NULL; - MODSSL_D2I_SSL_SESSION_CONST unsigned char *ucpData; - int nData; + unsigned int nData; time_t expiry; time_t now; apr_status_t rc; @@ -221,32 +220,30 @@ "(fetch)", mc->szSessionCacheDataFile); ssl_mutex_off(s); - return NULL; + return FALSE; } rc = apr_dbm_fetch(dbm, dbmkey, &dbmval); if (rc != APR_SUCCESS) { apr_dbm_close(dbm); ssl_mutex_off(s); - return NULL; + return FALSE; } if (dbmval.dptr == NULL || dbmval.dsize <= sizeof(time_t)) { apr_dbm_close(dbm); ssl_mutex_off(s); - return NULL; + return FALSE; } /* parse resulting data */ nData = dbmval.dsize-sizeof(time_t); - ucpData = malloc(nData); - if (ucpData == NULL) { + if (nData > *destlen) { apr_dbm_close(dbm); ssl_mutex_off(s); - return NULL; - } - /* Cast needed, ucpData may be const */ - memcpy((unsigned char *)ucpData, - (char *)dbmval.dptr + sizeof(time_t), nData); + return FALSE; + } + memcpy(&expiry, dbmval.dptr, sizeof(time_t)); + memcpy(dest, (char *)dbmval.dptr + sizeof(time_t), nData); apr_dbm_close(dbm); ssl_mutex_off(s); @@ -254,14 +251,11 @@ /* make sure the stuff is still not expired */ now = time(NULL); if (expiry <= now) { - ssl_scache_dbm_remove(s, id, idlen, p); - return NULL; + ssl_scache_dbm_remove(s, (UCHAR *)id, idlen, p); + return FALSE; } - /* unstreamed SSL_SESSION */ - sess = d2i_SSL_SESSION(NULL, &ucpData, nData); - - return sess; + return TRUE; } static void ssl_scache_dbm_remove(server_rec *s, UCHAR *id, int idlen, Modified: httpd/httpd/trunk/modules/ssl/ssl_scache_dc.c URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/ssl/ssl_scache_dc.c?rev=630307&r1=630306&r2=630307&view=diff ============================================================================== --- httpd/httpd/trunk/modules/ssl/ssl_scache_dc.c (original) +++ httpd/httpd/trunk/modules/ssl/ssl_scache_dc.c Fri Feb 22 11:58:39 2008 @@ -116,32 +116,25 @@ return TRUE; } -static SSL_SESSION *ssl_scache_dc_retrieve(server_rec *s, UCHAR *id, int idlen, apr_pool_t *p) +static BOOL ssl_scache_dc_retrieve(server_rec *s, const UCHAR *id, int idlen, + unsigned char *dest, unsigned int *destlen, + apr_pool_t *p) { - unsigned char der[SSL_SESSION_MAX_DER]; - unsigned int der_len; - SSL_SESSION *pSession; - MODSSL_D2I_SSL_SESSION_CONST unsigned char *pder = der; + unsigned int data_len; SSLModConfigRec *mc = myModConfig(s); DC_CTX *ctx = mc->tSessionCacheDataTable; /* Retrieve any corresponding session from the distributed cache context */ - if (!DC_CTX_get_session(ctx, id, idlen, der, SSL_SESSION_MAX_DER, - &der_len)) { + if (!DC_CTX_get_session(ctx, id, idlen, dest, *destlen, &data_len)) { ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "distributed scache 'get_session' MISS"); - return NULL; + return FALSE; } - if (der_len > SSL_SESSION_MAX_DER) { + if (data_len > *destlen) { ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, "distributed scache 'get_session' OVERFLOW"); - return NULL; - } - pSession = d2i_SSL_SESSION(NULL, &pder, der_len); - if (!pSession) { - ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, "distributed scache 'get_session' CORRUPT"); - return NULL; + return FALSE; } ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "distributed scache 'get_session' HIT"); - return pSession; + return TRUE; } static void ssl_scache_dc_remove(server_rec *s, UCHAR *id, int idlen, apr_pool_t *p) Modified: httpd/httpd/trunk/modules/ssl/ssl_scache_memcache.c URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/ssl/ssl_scache_memcache.c?rev=630307&r1=630306&r2=630307&view=diff ============================================================================== --- httpd/httpd/trunk/modules/ssl/ssl_scache_memcache.c (original) +++ httpd/httpd/trunk/modules/ssl/ssl_scache_memcache.c Fri Feb 22 11:58:39 2008 @@ -163,8 +163,8 @@ } -static char *mc_session_id2sz(unsigned char *id, int idlen, - char *str, int strsize) +static char *mc_session_id2sz(const unsigned char *id, int idlen, + char *str, int strsize) { char *cp; int n; @@ -207,57 +207,45 @@ return TRUE; } -static SSL_SESSION *ssl_scache_mc_retrieve(server_rec *s, UCHAR *id, int idlen, - apr_pool_t *p) +static BOOL ssl_scache_mc_retrieve(server_rec *s, const UCHAR *id, int idlen, + unsigned char *dest, unsigned int *destlen, + apr_pool_t *p) { - SSL_SESSION *pSession; - MODSSL_D2I_SSL_SESSION_CONST unsigned char *pder; apr_size_t der_len; - char buf[MC_KEY_LEN]; + char buf[MC_KEY_LEN], *der; char* strkey = NULL; apr_status_t rv; strkey = mc_session_id2sz(id, idlen, buf, sizeof(buf)); - if(!strkey) { + if (!strkey) { ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "scache_mc: Key generation borked."); - return NULL; + return FALSE; } - rv = apr_memcache_getp(memctxt, p, strkey, - (char**)&pder, &der_len, NULL); + /* ### this could do with a subpool, but _getp looks like it will + * eat memory like it's going out of fashion anyway. */ - if (rv == APR_NOTFOUND) { - /* ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, - "scache_mc: 'get_session' MISS"); */ - return NULL; - } - - if (rv != APR_SUCCESS) { - ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, - "scache_mc: 'get_session' FAIL"); - return NULL; + rv = apr_memcache_getp(memctxt, p, strkey, + &der, &der_len, NULL); + if (rv) { + if (rv != APR_NOTFOUND) { + ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, + "scache_mc: 'get_session' FAIL"); + } + return FALSE; } - - if (der_len > SSL_SESSION_MAX_DER) { - ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, + else if (der_len > *destlen) { + ap_log_error(APLOG_MARK, APLOG_ERR, rv, s, "scache_mc: 'get_session' OVERFLOW"); - return NULL; - } - - pSession = d2i_SSL_SESSION(NULL, &pder, der_len); - - if (!pSession) { - ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, - "scache_mc: 'get_session' CORRUPT"); - return NULL; - } + return FALSE; + } - /* ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, - "scache_mc: 'get_session' HIT"); */ + memcpy(dest, der, der_len); + *destlen = der_len; - return pSession; + return TRUE; } static void ssl_scache_mc_remove(server_rec *s, UCHAR *id, int idlen, apr_pool_t *p) Modified: httpd/httpd/trunk/modules/ssl/ssl_scache_shmcb.c URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/ssl/ssl_scache_shmcb.c?rev=630307&r1=630306&r2=630307&view=diff ============================================================================== --- httpd/httpd/trunk/modules/ssl/ssl_scache_shmcb.c (original) +++ httpd/httpd/trunk/modules/ssl/ssl_scache_shmcb.c Fri Feb 22 11:58:39 2008 @@ -80,8 +80,8 @@ unsigned int data_pos; /* size (most logic ignores this, we keep it only to minimise memcpy) */ unsigned int data_used; - /* Optimisation to prevent ASN decoding unless a match is likely */ - unsigned char s_id2; + /* length of the used data which contains the id */ + unsigned int id_len; /* Used to mark explicitly-removed sessions */ unsigned char removed; } SHMCBIndex; @@ -115,6 +115,18 @@ * use. Both ->idx_* values have a range of [0, header->index_num) * * Each in-use SHMCBIndex structure represents a single SSL session. + * The ID and data segment are stored consecutively in the subcache's + * cyclic data buffer. The "Data" segment can thus be seen to + * look like this, for example + * + * offset: [ 0 1 2 3 4 5 6 ... + * contents:[ ID1 Data1 ID2 Data2 ID3 ... + * + * where the corresponding indices would look like: + * + * idx1 = { data_pos = 0, data_used = 3, id_len = 1, ...} + * idx2 = { data_pos = 3, data_used = 3, id_len = 1, ...} + * ... */ /* This macro takes a pointer to the header and a zero-based index and returns @@ -190,12 +202,42 @@ } } +/* A memcmp against a cyclic data buffer. Compares SRC of length + * SRC_LEN data which begins at offset DEST_OFFSET in cyclic buffer + * DATA which is of size BUF_SIZE. Got that? Good. */ +static int shmcb_cyclic_memcmp(unsigned int buf_size, unsigned char *data, + unsigned int dest_offset, + const unsigned char *src, + unsigned int src_len) +{ + if (dest_offset + src_len < buf_size) + /* It be compared all in one go */ + return memcmp(data + dest_offset, src, src_len); + else { + /* Compare the two splits */ + int diff; + + diff = memcmp(data + dest_offset, src, buf_size - dest_offset); + if (diff) { + return diff; + } + return memcmp(data, src + buf_size - dest_offset, + src_len + dest_offset - buf_size); + } +} + + /* Prototypes for low-level subcache operations */ static void shmcb_subcache_expire(server_rec *, SHMCBHeader *, SHMCBSubcache *); -static BOOL shmcb_subcache_store(server_rec *, SHMCBHeader *, SHMCBSubcache *, - UCHAR *, unsigned int, UCHAR *, time_t); -static SSL_SESSION *shmcb_subcache_retrieve(server_rec *, SHMCBHeader *, SHMCBSubcache *, - UCHAR *, unsigned int); +static BOOL shmcb_subcache_store(server_rec *s, SHMCBHeader *header, + SHMCBSubcache *subcache, + UCHAR *data, unsigned int data_len, + UCHAR *id, unsigned int id_len, + time_t expiry); +static BOOL shmcb_subcache_retrieve(server_rec *, SHMCBHeader *, SHMCBSubcache *, + const UCHAR *id, unsigned int idlen, + UCHAR *data, unsigned int *datalen); + static BOOL shmcb_subcache_remove(server_rec *, SHMCBHeader *, SHMCBSubcache *, UCHAR *, unsigned int); @@ -271,12 +313,13 @@ /* Select the number of subcaches to create and how many indexes each * should contain based on the size of the memory (the header has already * been subtracted). Typical non-client-auth sslv3/tlsv1 sessions are - * around 150 bytes, so erring to division by 120 helps ensure we would - * exhaust data storage before index storage (except sslv2, where it's - * *slightly* the other way). From there, we select the number of subcaches - * to be a power of two, such that the number of indexes per subcache at - * least twice the number of subcaches. */ - num_idx = (shm_segsize) / 120; + * around 180 bytes (148 bytes data and 32 bytes for the id), so + * erring to division by 150 helps ensure we would exhaust data + * storage before index storage (except sslv2, where it's + * *slightly* the other way). From there, we select the number of + * subcaches to be a power of two, such that the number of indexes + * per subcache at least twice the number of subcaches. */ + num_idx = (shm_segsize) / 150; num_subcache = 256; while ((num_idx / num_subcache) < (2 * num_subcache)) num_subcache /= 2; @@ -370,7 +413,7 @@ goto done; } if (!shmcb_subcache_store(s, header, subcache, encoded, - len_encoded, id, timeout)) { + len_encoded, id, idlen, timeout)) { ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, "can't store a session!"); goto done; @@ -384,35 +427,34 @@ return to_return; } -static SSL_SESSION *ssl_scache_shmcb_retrieve(server_rec *s, UCHAR *id, int idlen, - apr_pool_t *p) +static BOOL ssl_scache_shmcb_retrieve(server_rec *s, + const UCHAR *id, int idlen, + unsigned char *dest, unsigned int *destlen, + apr_pool_t *p) { SSLModConfigRec *mc = myModConfig(s); - SSL_SESSION *pSession = NULL; SHMCBHeader *header = mc->tSessionCacheDataTable; 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)); - if (idlen < 4) { - ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, "unusably short session_id provided " - "(%u bytes)", idlen); - goto done; - } + /* Get the session corresponding to the session_id or NULL if it doesn't * exist (or is flagged as "removed"). */ - pSession = shmcb_subcache_retrieve(s, header, subcache, id, idlen); - if (pSession) + rv = shmcb_subcache_retrieve(s, header, subcache, id, idlen, + dest, destlen); + if (rv) header->stat_retrieves_hit++; else header->stat_retrieves_miss++; ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "leaving ssl_scache_shmcb_retrieve successfully"); -done: + ssl_mutex_off(s); - return pSession; + return rv; } static void ssl_scache_shmcb_remove(server_rec *s, UCHAR *id, int idlen, apr_pool_t *p) @@ -564,16 +606,18 @@ static BOOL shmcb_subcache_store(server_rec *s, SHMCBHeader *header, SHMCBSubcache *subcache, UCHAR *data, unsigned int data_len, - UCHAR *id, time_t expiry) + UCHAR *id, unsigned int id_len, + time_t expiry) { - unsigned int new_offset, new_idx; + unsigned int data_offset, new_idx, id_offset; SHMCBIndex *idx; + unsigned int total_len = id_len + data_len; /* Sanity check the input */ - if ((data_len > header->subcache_data_size) || (data_len > SSL_SESSION_MAX_DER)) { + if (total_len > header->subcache_data_size) { ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, "inserting session larger (%d) than subcache data area (%d)", - data_len, header->subcache_data_size); + total_len, header->subcache_data_size); return FALSE; } @@ -581,7 +625,7 @@ shmcb_subcache_expire(s, header, subcache); /* Loop until there is enough space to insert */ - if (header->subcache_data_size - subcache->data_used < data_len + if (header->subcache_data_size - subcache->data_used < total_len || subcache->idx_used == header->index_num) { unsigned int loop = 0; @@ -611,7 +655,7 @@ /* Loop admin */ idx = idx2; loop++; - } while (header->subcache_data_size - subcache->data_used < data_len); + } while (header->subcache_data_size - subcache->data_used < total_len); ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "finished force-expire, subcache: idx_used=%d, " @@ -628,11 +672,18 @@ * would make this stuff *MUCH* more efficient. Mind you, it's very * efficient right now because I'm ignoring this problem!!! */ + /* Insert the id */ + id_offset = SHMCB_CYCLIC_INCREMENT(subcache->data_pos, subcache->data_used, + header->subcache_data_size); + shmcb_cyclic_ntoc_memcpy(header->subcache_data_size, + SHMCB_DATA(header, subcache), id_offset, + id, id_len); + subcache->data_used += id_len; /* Insert the data */ - new_offset = SHMCB_CYCLIC_INCREMENT(subcache->data_pos, subcache->data_used, - header->subcache_data_size); + data_offset = SHMCB_CYCLIC_INCREMENT(subcache->data_pos, subcache->data_used, + header->subcache_data_size); shmcb_cyclic_ntoc_memcpy(header->subcache_data_size, - SHMCB_DATA(header, subcache), new_offset, + SHMCB_DATA(header, subcache), data_offset, data, data_len); subcache->data_used += data_len; /* Insert the index */ @@ -640,13 +691,14 @@ header->index_num); idx = SHMCB_INDEX(subcache, new_idx); idx->expires = expiry; - idx->data_pos = new_offset; - idx->data_used = data_len; - idx->s_id2 = id[1]; + idx->data_pos = id_offset; + idx->data_used = total_len; + idx->id_len = id_len; idx->removed = 0; subcache->idx_used++; ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, - "insert happened at idx=%d, data=%d", new_idx, new_offset); + "insert happened at idx=%d, data=(%u:%u)", new_idx, + id_offset, data_offset); ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "finished insert, subcache: idx_pos/idx_used=%d/%d, " "data_pos/data_used=%d/%d", @@ -655,9 +707,10 @@ return TRUE; } -static SSL_SESSION *shmcb_subcache_retrieve(server_rec *s, SHMCBHeader *header, - SHMCBSubcache *subcache, UCHAR *id, - unsigned int idlen) +static BOOL shmcb_subcache_retrieve(server_rec *s, SHMCBHeader *header, + SHMCBSubcache *subcache, + const UCHAR *id, unsigned int idlen, + UCHAR *dest, unsigned int *destlen) { unsigned int pos; unsigned int loop = 0; @@ -669,39 +722,31 @@ while (loop < subcache->idx_used) { SHMCBIndex *idx = SHMCB_INDEX(subcache, pos); - /* Only consider 'idx' if; - * (a) the s_id2 byte matches - * (b) the "removed" flag isn't set. - */ - if ((idx->s_id2 == id[1]) && !idx->removed) { - SSL_SESSION *pSession; - unsigned char *s_id; - unsigned int s_idlen; - unsigned char tempasn[SSL_SESSION_MAX_DER]; - MODSSL_D2I_SSL_SESSION_CONST unsigned char *ptr = tempasn; - + /* Only consider 'idx' if the id matches, and the "removed" + * flag isn't set; check the data length too to avoid a buffer + * overflow in case of corruption, which should be impossible, + * but it's cheap to be safe. */ + if (idx->id_len == idlen && (idx->data_used - idx->id_len) < *destlen + && shmcb_cyclic_memcmp(header->subcache_data_size, + SHMCB_DATA(header, subcache), + idx->data_pos, id, idx->id_len) == 0) { ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, - "possible match at idx=%d, data=%d", pos, idx->data_pos); - /* Copy the data */ + "match at idx=%d, data=%d", pos, idx->data_pos); + unsigned int data_offset; + + /* Find the offset of the data segment, after the id */ + data_offset = SHMCB_CYCLIC_INCREMENT(idx->data_pos, + idx->id_len, + header->subcache_data_size); + + *destlen = idx->data_used - idx->id_len; + + /* Copy out the data */ shmcb_cyclic_cton_memcpy(header->subcache_data_size, - tempasn, SHMCB_DATA(header, subcache), - idx->data_pos, idx->data_used); - /* Decode the session */ - pSession = d2i_SSL_SESSION(NULL, &ptr, idx->data_used); - if (!pSession) { - ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, - "shmcb_subcache_retrieve internal error"); - return NULL; - } - s_id = SSL_SESSION_get_session_id(pSession); - s_idlen = SSL_SESSION_get_session_id_length(pSession); - if (s_idlen == idlen && memcmp(s_id, id, idlen) == 0) { - /* Found the matching session */ - ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, - "shmcb_subcache_retrieve returning matching session"); - return pSession; - } - SSL_SESSION_free(pSession); + dest, SHMCB_DATA(header, subcache), + data_offset, *destlen); + + return TRUE; } /* Increment */ loop++; @@ -710,7 +755,7 @@ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "shmcb_subcache_retrieve found no match"); - return NULL; + return FALSE; } static BOOL shmcb_subcache_remove(server_rec *s, SHMCBHeader *header, @@ -730,38 +775,20 @@ pos = subcache->idx_pos; while (!to_return && (loop < subcache->idx_used)) { SHMCBIndex *idx = SHMCB_INDEX(subcache, pos); - /* Only consider 'idx' if the s_id2 byte matches and it's not already - * removed - easiest way to avoid costly ASN decodings. */ - if ((idx->s_id2 == id[1]) && !idx->removed) { - SSL_SESSION *pSession; - unsigned char *s_id; - unsigned int s_idlen; - unsigned char tempasn[SSL_SESSION_MAX_DER]; - MODSSL_D2I_SSL_SESSION_CONST unsigned char *ptr = tempasn; + /* Only consider 'idx' if the id matches, and the "removed" + * flag isn't set. */ + if (idx->id_len == idlen + && shmcb_cyclic_memcmp(header->subcache_data_size, + SHMCB_DATA(header, subcache), + idx->data_pos, id, idx->id_len) == 0) { ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "possible match at idx=%d, data=%d", pos, idx->data_pos); - /* Copy the data */ - shmcb_cyclic_cton_memcpy(header->subcache_data_size, - tempasn, SHMCB_DATA(header, subcache), - idx->data_pos, idx->data_used); - /* Decode the session */ - pSession = d2i_SSL_SESSION(NULL, &ptr, idx->data_used); - if (!pSession) { - ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, - "shmcb_subcache_remove internal error"); - return FALSE; - } - s_id = SSL_SESSION_get_session_id(pSession); - s_idlen = SSL_SESSION_get_session_id_length(pSession); - if (s_idlen == idlen && memcmp(s_id, id, idlen) == 0) { - /* Found the matching session, remove it quietly. */ - idx->removed = 1; - to_return = TRUE; - ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, + /* Found the matching session, remove it quietly. */ + idx->removed = 1; + to_return = TRUE; + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "shmcb_subcache_remove removing matching session"); - } - SSL_SESSION_free(pSession); } /* Increment */ loop++;