From ba26e9ebfd72824f81642c64e105032db7ed0e63 Mon Sep 17 00:00:00 2001
From: Paul Bakker
Date: Tue, 23 Oct 2012 22:18:28 +0000
Subject: [PATCH] - Cache now only allows a maximum of entries in cache for
preventing memory overrun
---
include/polarssl/ssl_cache.h | 17 +++++++++---
library/ssl_cache.c | 50 ++++++++++++++++++++++++++++--------
2 files changed, 53 insertions(+), 14 deletions(-)
diff --git a/include/polarssl/ssl_cache.h b/include/polarssl/ssl_cache.h
index e13c0875d..85e0ed112 100644
--- a/include/polarssl/ssl_cache.h
+++ b/include/polarssl/ssl_cache.h
@@ -29,7 +29,8 @@
#include "ssl.h"
-#define SSL_CACHE_DEFAULT_TIMEOUT 86400 /*!< 1 day */
+#define SSL_CACHE_DEFAULT_TIMEOUT 86400 /*!< 1 day */
+#define SSL_CACHE_DEFAULT_MAX_ENTRIES 50 /*!< Maximum entries in cache */
#ifdef __cplusplus
extern "C" {
@@ -53,8 +54,9 @@ struct _ssl_cache_entry
*/
struct _ssl_cache_context
{
- ssl_cache_entry *chain; /*!< start of the chain */
- int timeout; /*!< cache timeout */
+ ssl_cache_entry *chain; /*!< start of the chain */
+ int timeout; /*!< cache entry timeout */
+ int max_entries; /*!< maximum entries */
};
/**
@@ -91,6 +93,15 @@ int ssl_cache_set( void *data, const ssl_session *session );
*/
void ssl_cache_set_timeout( ssl_cache_context *cache, int timeout );
+/**
+ * \brief Set the cache timeout
+ * (Default: SSL_CACHE_DEFAULT_MAX_ENTRIES (50))
+ *
+ * \param cache SSL cache context
+ * \param max cache entry maximum
+ */
+void ssl_cache_set_max_entries( ssl_cache_context *cache, int max );
+
/**
* \brief Free referenced items in a cache context and clear memory
*
diff --git a/library/ssl_cache.c b/library/ssl_cache.c
index 203a4b786..ab948d6b0 100644
--- a/library/ssl_cache.c
+++ b/library/ssl_cache.c
@@ -40,6 +40,7 @@ void ssl_cache_init( ssl_cache_context *cache )
memset( cache, 0, sizeof( ssl_cache_context ) );
cache->timeout = SSL_CACHE_DEFAULT_TIMEOUT;
+ cache->max_entries = SSL_CACHE_DEFAULT_MAX_ENTRIES;
}
int ssl_cache_get( void *data, ssl_session *session )
@@ -78,15 +79,18 @@ int ssl_cache_get( void *data, ssl_session *session )
int ssl_cache_set( void *data, const ssl_session *session )
{
- time_t t = time( NULL );
+ time_t t = time( NULL ), oldest = 0;
ssl_cache_context *cache = (ssl_cache_context *) data;
- ssl_cache_entry *cur, *prv;
+ ssl_cache_entry *cur, *prv, *old = NULL;
+ int count = 0;
cur = cache->chain;
prv = NULL;
while( cur != NULL )
{
+ count++;
+
if( cache->timeout != 0 &&
(int) ( t - cur->timestamp ) > cache->timeout )
{
@@ -97,22 +101,39 @@ int ssl_cache_set( void *data, const ssl_session *session )
if( memcmp( session->id, cur->session.id, cur->session.length ) == 0 )
break; /* client reconnected, keep timestamp for session id */
+ if( oldest == 0 || cur->timestamp < oldest )
+ {
+ oldest = cur->timestamp;
+ old = cur;
+ }
+
prv = cur;
cur = cur->next;
}
if( cur == NULL )
{
- cur = (ssl_cache_entry *) malloc( sizeof( ssl_cache_entry ) );
- if( cur == NULL )
- return( 1 );
-
- memset( cur, 0, sizeof( ssl_cache_entry ) );
-
- if( prv == NULL )
- cache->chain = cur;
+ /*
+ * Reuse oldest entry if max_entries reached
+ */
+ if( old != NULL && count >= cache->max_entries )
+ {
+ cur = old;
+ memset( &cur->session, 0, sizeof( ssl_session ) );
+ }
else
- prv->next = cur;
+ {
+ cur = (ssl_cache_entry *) malloc( sizeof( ssl_cache_entry ) );
+ if( cur == NULL )
+ return( 1 );
+
+ memset( cur, 0, sizeof( ssl_cache_entry ) );
+
+ if( prv == NULL )
+ cache->chain = cur;
+ else
+ prv->next = cur;
+ }
cur->timestamp = t;
}
@@ -133,6 +154,13 @@ void ssl_cache_set_timeout( ssl_cache_context *cache, int timeout )
cache->timeout = timeout;
}
+void ssl_cache_set_max_entries( ssl_cache_context *cache, int max )
+{
+ if( max < 0 ) max = 0;
+
+ cache->max_entries = max;
+}
+
void ssl_cache_free( ssl_cache_context *cache )
{
ssl_cache_entry *cur, *prv;