The current version of PolarSSL has session caching capabilities, but unfortunately the peer SSL certificate (in case of client SSL authentication) is not included in this cache. This cause Hiawatha to lose information about the peer's SSL certificate when new connections are made within the same SSL session.
I've written a patch for PolarSSL which fixes this issue. With this patch, CGI applications will always have the right information about the current client SSL certificate that has been used for the SSL authentication proces.
This patch has of course also been sent to the PolarSSL developer. He is aware of the issue and has placed it on his todo list.
Write the patch to a file (for example cache_peer_cert.diff), go to the polarssl directory inside the Hiawatha source and apply the patch via: patch -p1 < cache_peer_cert.diff
diff -ru polar/include/polarssl/ssl_cache.h polarssl/include/polarssl/ssl_cache.h --- polar/include/polarssl/ssl_cache.h 2013-02-02 19:23:57.000000000 +0100 +++ polarssl/include/polarssl/ssl_cache.h 2013-02-24 19:03:51.337337050 +0100 @@ -46,6 +46,7 @@ { time_t timestamp; /*!< entry timestamp */ ssl_session session; /*!< entry session */ + x509_buf peer_cert; /*!< entry peer_cert */ ssl_cache_entry *next; /*!< chain pointer */ }; diff -ru polar/library/ssl_cache.c polarssl/library/ssl_cache.c --- polar/library/ssl_cache.c 2013-02-02 19:23:57.000000000 +0100 +++ polarssl/library/ssl_cache.c 2013-02-24 19:30:04.333337079 +0100 @@ -71,6 +71,27 @@ continue; memcpy( session->master, entry->session.master, 48 ); + + /* + * Restore peer certificate + */ + if( entry->peer_cert.p != NULL ) + { + session->peer_cert = ( x509_cert* )malloc( sizeof( x509_cert ) ); + if( session->peer_cert == NULL ) + return( 1 ); + + memset( session->peer_cert, 0, sizeof( x509_cert ) ); + if( x509parse_crt(session->peer_cert, entry->peer_cert.p, entry->peer_cert.len) != 0 ) + { + free( session->peer_cert ); + session->peer_cert = NULL; + return( 1 ); + } + + session->peer_cert->next = NULL; + } + return( 0 ); } @@ -120,6 +140,8 @@ { cur = old; memset( &cur->session, 0, sizeof( ssl_session ) ); + if( cur->peer_cert.p != NULL ) + free(cur->peer_cert.p); } else { @@ -135,14 +157,31 @@ prv->next = cur; } + cur->peer_cert.p = NULL; + cur->peer_cert.len = 0; + cur->timestamp = t; } memcpy( &cur->session, session, sizeof( ssl_session ) ); - - // Do not include peer_cert in cache entry - // - cur->session.peer_cert = NULL; + + /* + * Store peer certificate + */ + if( session->peer_cert != NULL ) + { + cur->peer_cert.p = ( unsigned char* )malloc( session->peer_cert->raw.len ); + if( cur->peer_cert.p == NULL ) + return( 1 ); + + memcpy( cur->peer_cert.p, session->peer_cert->raw.p, session->peer_cert->raw.len ); + cur->peer_cert.len = session->peer_cert->raw.len; + + cur->session.peer_cert = NULL; + } else { + cur->peer_cert.p = NULL; + cur->peer_cert.len = 0; + } return( 0 ); } @@ -173,6 +212,10 @@ cur = cur->next; ssl_session_free( &prv->session ); + + if( prv->peer_cert.p != NULL) + free( prv->peer_cert.p ); + free( prv ); } }
Do you think the above should be changed to reflect what is now distributed?
But there is no reason to apply this patch, because it's already applied when you use the latest Hiawatha release.