From 956ac08cab020bd988a8c40ca0c8168c361f5dcb Mon Sep 17 00:00:00 2001 From: toddouska Date: Wed, 24 Apr 2013 11:10:23 -0700 Subject: [PATCH] add persistent session cache, ssn9 --- configure.ac | 14 ++++++ cyassl/error.h | 1 + cyassl/ssl.h | 2 + src/internal.c | 4 ++ src/ssl.c | 121 +++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 142 insertions(+) diff --git a/configure.ac b/configure.ac index 4e030d5b9..64d345fd7 100644 --- a/configure.ac +++ b/configure.ac @@ -250,6 +250,19 @@ then fi +# Persistent session cache +AC_ARG_ENABLE([savesession], + [ --enable-savesession Enable persistent session cache (default: disabled)], + [ ENABLED_SAVESESSION=$enableval ], + [ ENABLED_SAVESESSION=no ] + ) + +if test "$ENABLED_SAVESESSION" = "yes" +then + AM_CFLAGS="$AM_CFLAGS -DPERSIST_SESSION_CACHE" +fi + + # SNIFFER AC_ARG_ENABLE([sniffer], [AS_HELP_STRING([--enable-sniffer],[ Enable CyaSSL sniffer support (default: disabled) ])],[ @@ -1379,6 +1392,7 @@ echo " * Old TLS Versions: $ENABLED_OLD_TLS" echo " * OCSP: $ENABLED_OCSP" echo " * CRL: $ENABLED_CRL" echo " * CRL-MONITOR: $ENABLED_CRL_MONITOR" +echo " * Persistent session cache: $ENABLED_SAVESESSION" echo " * NTRU: $ENABLED_NTRU" echo " * valgrind unit tests: $ENABLED_VALGRIND" echo " * LIBZ: $ENABLED_LIBZ" diff --git a/cyassl/error.h b/cyassl/error.h index 04bb689a8..8192b702d 100644 --- a/cyassl/error.h +++ b/cyassl/error.h @@ -111,6 +111,7 @@ enum CyaSSL_ErrorCodes { RECV_OVERFLOW_E = -276, /* RXCB returned more than rqed */ GEN_COOKIE_E = -277, /* Generate Cookie Error */ NO_PEER_VERIFY = -278, /* Need peer cert verify Error */ + FWRITE_ERROR = -279, /* fwrite problem */ /* add strings to SetErrorString !!!!! */ /* begin negotiation parameter errors */ diff --git a/cyassl/ssl.h b/cyassl/ssl.h index b50b31c09..b52b91bb5 100644 --- a/cyassl/ssl.h +++ b/cyassl/ssl.h @@ -233,6 +233,8 @@ CYASSL_API int CyaSSL_pending(CYASSL*); CYASSL_API void CyaSSL_load_error_strings(void); CYASSL_API int CyaSSL_library_init(void); CYASSL_API long CyaSSL_CTX_set_session_cache_mode(CYASSL_CTX*, long); +CYASSL_API int CyaSSL_save_session_cache(const char *fname); +CYASSL_API int CyaSSL_restore_session_cache(const char *fname); /* only supports full name from cipher_name[] delimited by : */ CYASSL_API int CyaSSL_CTX_set_cipher_list(CYASSL_CTX*, const char*); diff --git a/src/internal.c b/src/internal.c index ff5182d3a..8c0414345 100644 --- a/src/internal.c +++ b/src/internal.c @@ -5774,6 +5774,10 @@ void SetErrorString(int error, char* str) XSTRNCPY(str, "Need peer certificate verify Error", max); break; + case FWRITE_ERROR: + XSTRNCPY(str, "fwrite Error", max); + break; + default : XSTRNCPY(str, "unknown error number", max); } diff --git a/src/ssl.c b/src/ssl.c index 8f2588db6..ecf97bca2 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -1617,6 +1617,7 @@ int CyaSSL_CertManagerVerifyBuffer(CYASSL_CERT_MANAGER* cm, const byte* buff, #define XFTELL vf_tell #define XREWIND vf_rewind #define XFREAD(BUF, SZ, AMT, FD) vf_read(FD, BUF, SZ*AMT) + #define XFWRITE(BUF, SZ, AMT, FD) vf_write(FD, BUF, SZ*AMT) #define XFCLOSE vf_close #define XSEEK_END VSEEK_END #define XBADFILE -1 @@ -1628,6 +1629,7 @@ int CyaSSL_CertManagerVerifyBuffer(CYASSL_CERT_MANAGER* cm, const byte* buff, #define XFTELL(F) (F)->len #define XREWIND(F) (void)F #define XFREAD(BUF, SZ, AMT, F) fs_read(F, (char*)BUF, SZ*AMT) + #define XFWRITE(BUF, SZ, AMT, F) fs_write(F, (char*)BUF, SZ*AMT) #define XFCLOSE fs_close #define XSEEK_END 0 #define XBADFILE NULL @@ -1638,6 +1640,7 @@ int CyaSSL_CertManagerVerifyBuffer(CYASSL_CERT_MANAGER* cm, const byte* buff, #define XFTELL ftell #define XREWIND(F) fseek(F, 0, IO_SEEK_SET) #define XFREAD fread + #define XFWRITE fwrite #define XFCLOSE fclose #define XSEEK_END IO_SEEK_END #define XBADFILE NULL @@ -1649,6 +1652,7 @@ int CyaSSL_CertManagerVerifyBuffer(CYASSL_CERT_MANAGER* cm, const byte* buff, #define XFTELL fs_ftell #define XREWIND fs_rewind #define XFREAD fs_fread + #define XFWRITE fs_fwrite #define XFCLOSE fs_fclose #define XSEEK_END FS_SEEK_END #define XBADFILE NULL @@ -1660,6 +1664,7 @@ int CyaSSL_CertManagerVerifyBuffer(CYASSL_CERT_MANAGER* cm, const byte* buff, #define XFTELL ftell #define XREWIND rewind #define XFREAD fread + #define XFWRITE fwrite #define XFCLOSE fclose #define XSEEK_END SEEK_END #define XBADFILE NULL @@ -2525,6 +2530,122 @@ int CyaSSL_set_session(CYASSL* ssl, CYASSL_SESSION* session) return SSL_FAILURE; } +#if !defined(NO_FILESYSTEM) && defined(PERSIST_SESSION_CACHE) + +/* Session Cache Header information */ +typedef struct { + int rows; /* session rows */ + int columns; /* session columns */ + int sessionSz; /* sizeof CYASSL_SESSION */ +} cache_header_t; + + +/* Persist session cache to file */ +int CyaSSL_save_session_cache(const char *fname) +{ + XFILE file; + int ret; + int rc = SSL_SUCCESS; + int i; + cache_header_t cache_header; + + CYASSL_ENTER("CyaSSL_save_session_cache"); + + file = XFOPEN(fname, "rb"); + if (file == XBADFILE) { + CYASSL_MSG("Couldn't open session cache save file"); + return SSL_BAD_FILE; + } + cache_header.rows = SESSION_ROWS; + cache_header.columns = SESSIONS_PER_ROW; + cache_header.sessionSz = (int)sizeof(CYASSL_SESSION); + + ret = (int)XFWRITE(&cache_header, sizeof cache_header, 1, file); + if (ret != 1) { + CYASSL_MSG("Session cache header file write failed"); + XFCLOSE(file); + return FWRITE_ERROR; + } + + if (LockMutex(&session_mutex) != 0) { + CYASSL_MSG("Session cache mutex lock failed"); + XFCLOSE(file); + return BAD_MUTEX_ERROR; + } + + for (i = 0; i < cache_header.rows; ++i) { + ret = (int)XFWRITE(SessionCache + i, sizeof(SessionRow), 1, file); + if (ret != 1) { + CYASSL_MSG("Session cache member file write failed"); + rc = FWRITE_ERROR; + break; + } + } + + UnLockMutex(&session_mutex); + + XFCLOSE(file); + CYASSL_LEAVE("CyaSSL_save_session_cache", rc); + + return rc; +} + + +/* Restore the persistant session cache from file */ +int CyaSSL_restore_session_cache(const char *fname) +{ + XFILE file; + int rc = SSL_SUCCESS; + int ret; + int i; + cache_header_t cache_header; + + CYASSL_ENTER("CyaSSL_restore_session_cache"); + + file = XFOPEN(fname, "w+b"); + if (file == XBADFILE) { + CYASSL_MSG("Couldn't open session cache save file"); + return SSL_BAD_FILE; + } + ret = (int)XFREAD(&cache_header, sizeof cache_header, 1, file); + if (ret != 1 || + cache_header.rows != SESSION_ROWS || + cache_header.columns != SESSIONS_PER_ROW || + cache_header.sessionSz != (int)sizeof(CYASSL_SESSION)) { + + CYASSL_MSG("Session cache header file read/match failed"); + XFCLOSE(file); + return FREAD_ERROR; + } + + if (LockMutex(&session_mutex) != 0) { + CYASSL_MSG("Session cache mutex lock failed"); + XFCLOSE(file); + return BAD_MUTEX_ERROR; + } + + for (i = 0; i < cache_header.rows; ++i) { + ret = (int)XFREAD(SessionCache + i, sizeof(SessionRow), 1, file); + if (ret != 1) { + CYASSL_MSG("Session cache member file read failed"); + rc = FREAD_ERROR; + break; + } + } + + UnLockMutex(&session_mutex); + + if (rc != SSL_SUCCESS) + XMEMSET(SessionCache, 0, sizeof SessionCache); + + XFCLOSE(file); + CYASSL_LEAVE("CyaSSL_restore_session_cache", rc); + + return rc; +} + +#endif /* !NO_FILESYSTEM && PERSIST_SESSION_CACHE */ + #endif /* NO_SESSION_CACHE */