Hi all,

I use openssl library in a daemon (as ssl client), and there are a lot
of crashes around ssl session management. A crash happens when ssl
sessions are flushed via SSL_CTX_flush_sessions(), because they
could have bad session id.

> openssl version on FreeBSD
OpenSSL 1.0.1m 19 Mar 2015

The client cache is enable with:

SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_CLIENT)

Moreover, I also use:

SSL_CTX_sess_set_new_cb(ctx, new_ssl_session_cb);
SSL_CTX_sess_set_remove_cb(ctx, remove_ssl_session_cb);

So, when server requests new session ticket (SSL3_ST_CR_SESSION_TICKET_[AB]),
the session can have more references than once. But in function
ssl3_get_new_session_ticket(), session_id is changed without checks on
session->references. If session_id is changed then cache access is wrong!

To solve this problem, I used a new ssl session, created with i2d/d2i (and
release one reference from old ssl session).

What do you think?

Olivier

-- 
Olivier Szika
R&D System Engineer

Stormshield - Stormshield Network Security


--- crypto/openssl/ssl/s3_clnt.c.orig	2015-04-16 11:24:32.860740414 +0200
+++ crypto/openssl/ssl/s3_clnt.c	2015-04-17 09:49:38.646822826 +0200
@@ -2115,6 +2115,59 @@
      * elsewhere in OpenSSL. The session ID is set to the SHA256 (or SHA1 is
      * SHA256 is disabled) hash of the ticket.
      */
+
+	/*
+	 * If references > 1, ssl session id must not be changed, mainly with cache sessions.
+	 * To solve this problem, a new ssl session is created from original.
+	 */
+	if (s->session->references > 1)
+	{
+		int len;
+		unsigned char *buffer, *p;
+		const unsigned char *cp;
+		SSL_SESSION *sess;
+
+		/* Create new ssl session from current */
+		len = i2d_SSL_SESSION(s->session, NULL);
+		if (len > 0xFF00)
+		{
+			SSLerr(SSL_F_SSL3_GET_NEW_SESSION_TICKET, SSL_R_BAD_LENGTH);
+			goto err;
+		}
+
+		buffer = OPENSSL_malloc(len);
+		if (buffer == NULL)
+		{
+			SSLerr(SSL_F_SSL3_GET_NEW_SESSION_TICKET, ERR_R_MALLOC_FAILURE);
+			goto err;
+		}
+		p = buffer;
+		cp = buffer;
+
+		if (!i2d_SSL_SESSION(s->session, &p))
+		{
+			OPENSSL_free(buffer);
+			SSLerr(SSL_F_SSL3_GET_NEW_SESSION_TICKET, SSL_F_I2D_SSL_SESSION);
+			goto err;
+		}
+
+		sess = d2i_SSL_SESSION(NULL, &cp, len);
+		if (sess == NULL)
+		{
+			OPENSSL_free(buffer);
+			SSLerr(SSL_F_SSL3_GET_NEW_SESSION_TICKET, SSL_F_D2I_SSL_SESSION);
+			goto err;
+		}
+
+		/* Release 1 reference for current session */
+		SSL_SESSION_free(s->session);
+
+		/* use new session */
+		s->session = sess;
+
+		OPENSSL_free(buffer);
+	}
+
     EVP_Digest(p, ticklen,
                s->session->session_id, &s->session->session_id_length,
 # ifndef OPENSSL_NO_SHA256
_______________________________________________
openssl-dev mailing list
To unsubscribe: https://mta.openssl.org/mailman/listinfo/openssl-dev

Reply via email to