📄 ssl_scache_shmcb.c
字号:
{ SHMCBIndex *idx; time_t now; unsigned int loop, index_num, pos_count, new_pos; SHMCBHeader *header; ssl_log(s, SSL_LOG_TRACE, "entering shmcb_expire_division"); /* We must calculate num and space ourselves based on expiry times. */ now = time(NULL); loop = 0; new_pos = shmcb_get_safe_uint(queue->first_pos); /* Cache useful values */ header = queue->header; index_num = header->index_num; pos_count = shmcb_get_safe_uint(queue->pos_count); while (loop < pos_count) { idx = shmcb_get_index(queue, new_pos); if (shmcb_get_safe_time(&(idx->expires)) > now) /* it hasn't expired yet, we're done iterating */ break; /* This one should be expired too. Shift to the next entry. */ loop++; new_pos = shmcb_cyclic_increment(index_num, new_pos, 1); } /* Find the new_offset and make the expiries happen. */ if (loop > 0) { ssl_log(s, SSL_LOG_TRACE, "will be expiring %u sessions", loop); /* We calculate the new_offset by "peeking" (or in the * case it's the last entry, "sneaking" ;-). */ if (loop == pos_count) { /* We are expiring everything! This is easy to do... */ shmcb_set_safe_uint(queue->pos_count, 0); shmcb_set_safe_uint(cache->pos_count, 0); } else { /* The Queue is easy to adjust */ shmcb_set_safe_uint(queue->pos_count, shmcb_get_safe_uint(queue->pos_count) - loop); shmcb_set_safe_uint(queue->first_pos, new_pos); /* peek to the start of the next session */ idx = shmcb_get_index(queue, new_pos); /* We can use shmcb_cyclic_space because we've guaranteed * we don't fit the ambiguous full/empty case. */ shmcb_set_safe_uint(cache->pos_count, shmcb_get_safe_uint(cache->pos_count) - shmcb_cyclic_space(header->cache_data_size, shmcb_get_safe_uint(cache->first_pos), shmcb_get_safe_uint(&(idx->offset)))); shmcb_set_safe_uint(cache->first_pos, shmcb_get_safe_uint(&(idx->offset))); } ssl_log(s, SSL_LOG_TRACE, "we now have %u sessions", shmcb_get_safe_uint(queue->pos_count)); } header->num_expiries += loop; return loop;}/* Inserts a new encoded session into a queue/cache pair - expiring * (early or otherwise) any leading sessions as necessary to ensure * there is room. An error return (FALSE) should only happen in the * event of surreal values being passed on, or ridiculously small * cache sizes. NB: For tracing purposes, this function is also given * the server_rec to allow "ssl_log()". */static BOOL shmcb_insert_encoded_session( server_rec *s, SHMCBQueue * queue, SHMCBCache * cache, unsigned char *encoded, unsigned int encoded_len, unsigned char *session_id, time_t expiry_time){ SHMCBHeader *header; SHMCBIndex *idx = NULL; unsigned int gap, new_pos, loop, new_offset; int need; ssl_log(s, SSL_LOG_TRACE, "entering shmcb_insert_encoded_session, " "*queue->pos_count = %u", shmcb_get_safe_uint(queue->pos_count)); /* If there's entries to expire, ditch them first thing. */ shmcb_expire_division(s, queue, cache); header = cache->header; gap = header->cache_data_size - shmcb_get_safe_uint(cache->pos_count); if (gap < encoded_len) { new_pos = shmcb_get_safe_uint(queue->first_pos); loop = 0; need = (int) encoded_len - (int) gap; while ((need > 0) && (loop + 1 < shmcb_get_safe_uint(queue->pos_count))) { new_pos = shmcb_cyclic_increment(header->index_num, new_pos, 1); loop += 1; idx = shmcb_get_index(queue, new_pos); need = (int) encoded_len - (int) gap - shmcb_cyclic_space(header->cache_data_size, shmcb_get_safe_uint(cache->first_pos), shmcb_get_safe_uint(&(idx->offset))); } if (loop > 0) { ssl_log(s, SSL_LOG_TRACE, "about to scroll %u sessions from %u", loop, shmcb_get_safe_uint(queue->pos_count)); /* We are removing "loop" items from the cache. */ shmcb_set_safe_uint(cache->pos_count, shmcb_get_safe_uint(cache->pos_count) - shmcb_cyclic_space(header->cache_data_size, shmcb_get_safe_uint(cache->first_pos), shmcb_get_safe_uint(&(idx->offset)))); shmcb_set_safe_uint(cache->first_pos, shmcb_get_safe_uint(&(idx->offset))); shmcb_set_safe_uint(queue->pos_count, shmcb_get_safe_uint(queue->pos_count) - loop); shmcb_set_safe_uint(queue->first_pos, new_pos); ssl_log(s, SSL_LOG_TRACE, "now only have %u sessions", shmcb_get_safe_uint(queue->pos_count)); /* Update the stats!!! */ header->num_scrolled += loop; } } /* probably unecessary checks, but I'll leave them until this code * is verified. */ if (shmcb_get_safe_uint(cache->pos_count) + encoded_len > header->cache_data_size) { ssl_log(s, SSL_LOG_ERROR, "shmcb_insert_encoded_session, " "internal error"); return FALSE; } if (shmcb_get_safe_uint(queue->pos_count) == header->index_num) { ssl_log(s, SSL_LOG_ERROR, "shmcb_insert_encoded_session, " "internal error"); return FALSE; } ssl_log(s, SSL_LOG_TRACE, "we have %u bytes and %u indexes free - " "enough", header->cache_data_size - shmcb_get_safe_uint(cache->pos_count), header->index_num - shmcb_get_safe_uint(queue->pos_count)); /* HERE WE ASSUME THAT THE NEW SESSION SHOULD GO ON THE END! I'M NOT * CHECKING WHETHER IT SHOULD BE GENUINELY "INSERTED" SOMEWHERE. * * We either fix that, or find out at a "higher" (read "mod_ssl") * level whether it is possible to have distinct session caches for * any attempted tomfoolery to do with different session timeouts. * Knowing in advance that we can have a cache-wide constant timeout * would make this stuff *MUCH* more efficient. Mind you, it's very * efficient right now because I'm ignoring this problem!!! */ /* Increment to the first unused byte */ new_offset = shmcb_cyclic_increment(header->cache_data_size, shmcb_get_safe_uint(cache->first_pos), shmcb_get_safe_uint(cache->pos_count)); /* Copy the DER-encoded session into place */ shmcb_cyclic_ntoc_memcpy(header->cache_data_size, cache->data, new_offset, encoded, encoded_len); /* Get the new index that this session is stored in. */ new_pos = shmcb_cyclic_increment(header->index_num, shmcb_get_safe_uint(queue->first_pos), shmcb_get_safe_uint(queue->pos_count)); ssl_log(s, SSL_LOG_TRACE, "storing in index %u, at offset %u", new_pos, new_offset); idx = shmcb_get_index(queue, new_pos); if (idx == NULL) { ssl_log(s, SSL_LOG_ERROR, "shmcb_insert_encoded_session, " "internal error"); return FALSE; } shmcb_safe_clear(idx, sizeof(SHMCBIndex)); shmcb_set_safe_time(&(idx->expires), expiry_time); shmcb_set_safe_uint(&(idx->offset), new_offset); /* idx->removed = (unsigned char)0; */ /* Not needed given the memset above. */ idx->s_id2 = session_id[1]; ssl_log(s, SSL_LOG_TRACE, "session_id[0]=%u, idx->s_id2=%u", session_id[0], session_id[1]); /* All that remains is to adjust the cache's and queue's "pos_count"s. */ shmcb_set_safe_uint(cache->pos_count, shmcb_get_safe_uint(cache->pos_count) + encoded_len); shmcb_set_safe_uint(queue->pos_count, shmcb_get_safe_uint(queue->pos_count) + 1); /* And just for good debugging measure ... */ ssl_log(s, SSL_LOG_TRACE, "leaving now with %u bytes in the cache and " "%u indexes", shmcb_get_safe_uint(cache->pos_count), shmcb_get_safe_uint(queue->pos_count)); ssl_log(s, SSL_LOG_TRACE, "leaving shmcb_insert_encoded_session"); return TRUE;}/* Performs a lookup into a queue/cache pair for a * session_id. If found, the session is deserialised * and returned, otherwise NULL. */static SSL_SESSION *shmcb_lookup_session_id( server_rec *s, SHMCBQueue *queue, SHMCBCache *cache, UCHAR *id, int idlen){ unsigned char tempasn[SSL_SESSION_MAX_DER]; SHMCBIndex *idx; SHMCBHeader *header; SSL_SESSION *pSession = NULL; unsigned int curr_pos, loop, count; unsigned char *ptr; time_t now; ssl_log(s, SSL_LOG_TRACE, "entering shmcb_lookup_session_id"); /* If there are entries to expire, ditch them first thing. */ shmcb_expire_division(s, queue, cache); now = time(NULL); curr_pos = shmcb_get_safe_uint(queue->first_pos); count = shmcb_get_safe_uint(queue->pos_count); header = queue->header; for (loop = 0; loop < count; loop++) { ssl_log(s, SSL_LOG_TRACE, "loop=%u, count=%u, curr_pos=%u", loop, count, curr_pos); idx = shmcb_get_index(queue, curr_pos); ssl_log(s, SSL_LOG_TRACE, "idx->s_id2=%u, id[1]=%u, offset=%u", idx->s_id2, id[1], shmcb_get_safe_uint(&(idx->offset))); /* Only look into the session further if; * (a) the second byte of the session_id matches, * (b) the "removed" flag isn't set, * (c) the session hasn't expired yet. * We do (c) like this so that it saves us having to * do natural expiries ... naturally expired sessions * scroll off the front anyway when the cache is full and * "rotating", the only real issue that remains is the * removal or disabling of forcibly killed sessions. */ if ((idx->s_id2 == id[1]) && !idx->removed && (shmcb_get_safe_time(&(idx->expires)) > now)) { ssl_log(s, SSL_LOG_TRACE, "at index %u, found possible " "session match", curr_pos); shmcb_cyclic_cton_memcpy(header->cache_data_size, tempasn, cache->data, shmcb_get_safe_uint(&(idx->offset)), SSL_SESSION_MAX_DER); ptr = tempasn;#if SSL_LIBRARY_VERSION >= 0x00908000 pSession = d2i_SSL_SESSION(NULL, (const unsigned char **)&ptr, SSL_SESSION_MAX_DER);#else pSession = d2i_SSL_SESSION(NULL, &ptr, SSL_SESSION_MAX_DER);#endif if (pSession == NULL) { ssl_log(s, SSL_LOG_ERROR, "scach2_lookup_" "session_id, internal error"); return NULL; } if ((pSession->session_id_length == idlen) && (memcmp(pSession->session_id, id, idlen) == 0)) { ssl_log(s, SSL_LOG_TRACE, "a match!"); return pSession; } ssl_log(s, SSL_LOG_TRACE, "not a match"); SSL_SESSION_free(pSession); pSession = NULL; } curr_pos = shmcb_cyclic_increment(header->index_num, curr_pos, 1); } ssl_log(s, SSL_LOG_TRACE, "no matching sessions were found"); return NULL;}static BOOL shmcb_remove_session_id( server_rec *s, SHMCBQueue *queue, SHMCBCache *cache, UCHAR *id, int idlen){ unsigned char tempasn[SSL_SESSION_MAX_DER]; SSL_SESSION *pSession = NULL; SHMCBIndex *idx; SHMCBHeader *header; unsigned int curr_pos, loop, count; unsigned char *ptr; BOOL to_return = FALSE; ssl_log(s, SSL_LOG_TRACE, "entering shmcb_remove_session_id"); /* If there's entries to expire, ditch them first thing. */ /* shmcb_expire_division(s, queue, cache); */ /* Regarding the above ... hmmm ... I know my expiry code is slightly * "faster" than all this remove stuff ... but if the higher level * code calls a "remove" operation (and this *only* seems to happen * when it has spotted an expired session before we had a chance to) * then it should get credit for a remove (stats-wise). Also, in the * off-chance that the server *requests* a renegotiate and wants to * wipe the session clean we should give that priority over our own * routine expiry handling. So I've moved the expiry check to *after* * this general remove stuff. */ curr_pos = shmcb_get_safe_uint(queue->first_pos); count = shmcb_get_safe_uint(queue->pos_count); header = cache->header; for (loop = 0; loop < count; loop++) { ssl_log(s, SSL_LOG_TRACE, "loop=%u, count=%u, curr_pos=%u", loop, count, curr_pos); idx = shmcb_get_index(queue, curr_pos); ssl_log(s, SSL_LOG_TRACE, "idx->s_id2=%u, id[1]=%u", idx->s_id2, id[1]); /* Only look into the session further if the second byte of the * session_id matches. */ if (idx->s_id2 == id[1]) { ssl_log(s, SSL_LOG_TRACE, "at index %u, found possible " "session match", curr_pos); shmcb_cyclic_cton_memcpy(header->cache_data_size, tempasn, cache->data, shmcb_get_safe_uint(&(idx->offset)), SSL_SESSION_MAX_DER); ptr = tempasn;#if SSL_LIBRARY_VERSION >= 0x00908000 pSession = d2i_SSL_SESSION(NULL, (const unsigned char **)&ptr, SSL_SESSION_MAX_DER);#else pSession = d2i_SSL_SESSION(NULL, &ptr, SSL_SESSION_MAX_DER);#endif if (pSession == NULL) { ssl_log(s, SSL_LOG_ERROR, "shmcb_remove_session_id, " "internal error"); goto end; } if ((pSession->session_id_length == idlen) && (memcmp(id, pSession->session_id, idlen) == 0)) { ssl_log(s, SSL_LOG_TRACE, "a match!"); /* Scrub out this session "quietly" */ idx->removed = (unsigned char) 1; SSL_SESSION_free(pSession); to_return = TRUE; goto end; } ssl_log(s, SSL_LOG_TRACE, "not a match"); SSL_SESSION_free(pSession); pSession = NULL; } curr_pos = shmcb_cyclic_increment(header->index_num, curr_pos, 1); } ssl_log(s, SSL_LOG_TRACE, "no matching sessions were found"); /* If there's entries to expire, ditch them now. */ shmcb_expire_division(s, queue, cache);end: ssl_log(s, SSL_LOG_TRACE, "leaving shmcb_remove_session_id"); return to_return;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -