📄 ssl_scache_shmcb.c
字号:
} 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))); } ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "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; ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "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) { ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "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); ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "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) { ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, "shmcb_insert_encoded_session internal error"); return FALSE; } if (shmcb_get_safe_uint(queue->pos_count) == header->index_num) { ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, "shmcb_insert_encoded_session internal error"); return FALSE; } ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "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)); ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "storing in index %u, at offset %u", new_pos, new_offset); idx = shmcb_get_index(queue, new_pos); if (idx == NULL) { ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, "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]; ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "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 ... */ ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "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)); ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "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, unsigned int idlen){ unsigned char tempasn[SSL_SESSION_MAX_DER]; SHMCBIndex *idx; SHMCBHeader *header; SSL_SESSION *pSession = NULL; unsigned int curr_pos, loop, count; MODSSL_D2I_SSL_SESSION_CONST unsigned char *ptr; time_t now; ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "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++) { ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "loop=%u, count=%u, curr_pos=%u", loop, count, curr_pos); idx = shmcb_get_index(queue, curr_pos); ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "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)) { unsigned int session_id_length; unsigned char *session_id; ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "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; pSession = d2i_SSL_SESSION(NULL, &ptr, SSL_SESSION_MAX_DER); session_id_length = SSL_SESSION_get_session_id_length(pSession); session_id = SSL_SESSION_get_session_id(pSession); if (pSession == NULL) { ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, "scach2_lookup_session_id internal error"); return NULL; } if ((session_id_length == idlen) && (memcmp(session_id, id, idlen) == 0)) { ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "a match!"); return pSession; } ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "not a match"); SSL_SESSION_free(pSession); pSession = NULL; } curr_pos = shmcb_cyclic_increment(header->index_num, curr_pos, 1); } ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "no matching sessions were found"); return NULL;}static BOOL shmcb_remove_session_id( server_rec *s, SHMCBQueue *queue, SHMCBCache *cache, UCHAR *id, unsigned int idlen){ unsigned char tempasn[SSL_SESSION_MAX_DER]; SSL_SESSION *pSession = NULL; SHMCBIndex *idx; SHMCBHeader *header; unsigned int curr_pos, loop, count; MODSSL_D2I_SSL_SESSION_CONST unsigned char *ptr; BOOL to_return = FALSE; ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "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++) { ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "loop=%u, count=%u, curr_pos=%u", loop, count, curr_pos); idx = shmcb_get_index(queue, curr_pos); ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "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]) { unsigned int session_id_length; unsigned char *session_id; ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "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; pSession = d2i_SSL_SESSION(NULL, &ptr, SSL_SESSION_MAX_DER); if (pSession == NULL) { ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, "shmcb_remove_session_id, internal error"); goto end; } session_id_length = SSL_SESSION_get_session_id_length(pSession); session_id = SSL_SESSION_get_session_id(pSession); if ((session_id_length == idlen) && (memcmp(id, session_id, idlen) == 0)) { ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "a match!"); /* Scrub out this session "quietly" */ idx->removed = (unsigned char) 1; SSL_SESSION_free(pSession); to_return = TRUE; goto end; } ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "not a match"); SSL_SESSION_free(pSession); pSession = NULL; } curr_pos = shmcb_cyclic_increment(header->index_num, curr_pos, 1); } ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "no matching sessions were found"); /* If there's entries to expire, ditch them now. */ shmcb_expire_division(s, queue, cache);end: ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "leaving shmcb_remove_session_id"); return to_return;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -