Weblog

26 February 2013, 14:37

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 );
     }
 }
crusty
18 April 2013, 04:32
I see there are differences between the above patch and what is coded in version 9.1.
Do you think the above should be changed to reflect what is now distributed?
Hugo Leisink
18 April 2013, 11:03
The patch was submitted to the PolarSSL developer and he included it in the latest release. There are probably some small differences, like code style and some improvements or bugfixes. But the basic idea remained the same.

But there is no reason to apply this patch, because it's already applied when you use the latest Hiawatha release.