PR: 1833
Submitted By: Robin Seggelmann <seggelmann@fh-muenster.de>

Support for abbreviated handshakes when renegotiating.
diff --git a/ssl/d1_clnt.c b/ssl/d1_clnt.c
index 5bc9eb6..255c19d 100644
--- a/ssl/d1_clnt.c
+++ b/ssl/d1_clnt.c
@@ -171,7 +171,7 @@
 		switch(s->state)
 			{
 		case SSL_ST_RENEGOTIATE:
-			s->new_session=1;
+			s->renegotiate=1;
 			s->state=SSL_ST_CONNECT;
 			s->ctx->stats.sess_connect_renegotiate++;
 			/* break */
@@ -539,6 +539,7 @@
 			/* else do it later in ssl3_write */
 
 			s->init_num=0;
+			s->renegotiate=0;
 			s->new_session=0;
 
 			ssl_update_cache(s,SSL_SESS_CACHE_CLIENT);
diff --git a/ssl/d1_pkt.c b/ssl/d1_pkt.c
index 1fd58bf..ee67561 100644
--- a/ssl/d1_pkt.c
+++ b/ssl/d1_pkt.c
@@ -957,6 +957,7 @@
 			!(s->s3->flags & SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS) &&
 			!s->s3->renegotiate)
 			{
+			s->new_session = 1;
 			ssl3_renegotiate(s);
 			if (ssl3_renegotiate_check(s))
 				{
@@ -1163,6 +1164,7 @@
 #else
 			s->state = s->server ? SSL_ST_ACCEPT : SSL_ST_CONNECT;
 #endif
+			s->renegotiate=1;
 			s->new_session=1;
 			}
 		i=s->handshake_func(s);
diff --git a/ssl/d1_srvr.c b/ssl/d1_srvr.c
index 301ceda..ac4fbda 100644
--- a/ssl/d1_srvr.c
+++ b/ssl/d1_srvr.c
@@ -177,7 +177,7 @@
 		switch (s->state)
 			{
 		case SSL_ST_RENEGOTIATE:
-			s->new_session=1;
+			s->renegotiate=1;
 			/* s->state=SSL_ST_ACCEPT; */
 
 		case SSL_ST_BEFORE:
@@ -299,7 +299,7 @@
 			
 		case SSL3_ST_SW_SRVR_HELLO_A:
 		case SSL3_ST_SW_SRVR_HELLO_B:
-			s->new_session = 2;
+			s->renegotiate = 2;
 			dtls1_start_timer(s);
 			ret=dtls1_send_server_hello(s);
 			if (ret <= 0) goto end;
@@ -620,11 +620,12 @@
 
 			s->init_num=0;
 
-			if (s->new_session == 2) /* skipped if we just sent a HelloRequest */
+			if (s->renegotiate == 2) /* skipped if we just sent a HelloRequest */
 				{
 				/* actually not necessarily a 'new' session unless
 				 * SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION is set */
 				
+				s->renegotiate=0;
 				s->new_session=0;
 				
 				ssl_update_cache(s,SSL_SESS_CACHE_SERVER);
diff --git a/ssl/s3_clnt.c b/ssl/s3_clnt.c
index aa5604c..601c2b1 100644
--- a/ssl/s3_clnt.c
+++ b/ssl/s3_clnt.c
@@ -207,7 +207,7 @@
 		switch(s->state)
 			{
 		case SSL_ST_RENEGOTIATE:
-			s->new_session=1;
+			s->renegotiate=1;
 			s->state=SSL_ST_CONNECT;
 			s->ctx->stats.sess_connect_renegotiate++;
 			/* break */
@@ -563,6 +563,7 @@
 			/* else do it later in ssl3_write */
 
 			s->init_num=0;
+			s->renegotiate=0;
 			s->new_session=0;
 
 			ssl_update_cache(s,SSL_SESS_CACHE_CLIENT);
diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c
index 497f64f..c6d4ac1 100644
--- a/ssl/s3_lib.c
+++ b/ssl/s3_lib.c
@@ -2226,6 +2226,7 @@
 
 	s->packet_length=0;
 	s->s3->renegotiate=0;
+	s->s3->new_session=0;
 	s->s3->total_renegotiations=0;
 	s->s3->num_renegotiations=0;
 	s->s3->in_read_app_data=0;
diff --git a/ssl/s3_pkt.c b/ssl/s3_pkt.c
index 08a7233..94ccfa0 100644
--- a/ssl/s3_pkt.c
+++ b/ssl/s3_pkt.c
@@ -1280,6 +1280,7 @@
 #else
 			s->state = s->server ? SSL_ST_ACCEPT : SSL_ST_CONNECT;
 #endif
+			s->renegotiate=1;
 			s->new_session=1;
 			}
 		i=s->handshake_func(s);
diff --git a/ssl/s3_srvr.c b/ssl/s3_srvr.c
index 57e516f..c2874e7 100644
--- a/ssl/s3_srvr.c
+++ b/ssl/s3_srvr.c
@@ -218,7 +218,7 @@
 		switch (s->state)
 			{
 		case SSL_ST_RENEGOTIATE:
-			s->new_session=1;
+			s->renegotiate=1;
 			/* s->state=SSL_ST_ACCEPT; */
 
 		case SSL_ST_BEFORE:
@@ -316,7 +316,7 @@
 			ret=ssl3_get_client_hello(s);
 			if (ret <= 0) goto end;
 			
-			s->new_session = 2;
+			s->renegotiate = 2;
 			s->state=SSL3_ST_SW_SRVR_HELLO_A;
 			s->init_num=0;
 			break;
@@ -706,11 +706,12 @@
 
 			s->init_num=0;
 
-			if (s->new_session == 2) /* skipped if we just sent a HelloRequest */
+			if (s->renegotiate == 2) /* skipped if we just sent a HelloRequest */
 				{
 				/* actually not necessarily a 'new' session unless
 				 * SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION is set */
 				
+				s->renegotiate=0;
 				s->new_session=0;
 				
 				ssl_update_cache(s,SSL_SESS_CACHE_SERVER);
diff --git a/ssl/ssl.h b/ssl/ssl.h
index 971208b..5a35c67 100644
--- a/ssl/ssl.h
+++ b/ssl/ssl.h
@@ -1050,12 +1050,14 @@
 
 	int server;	/* are we the server side? - mostly used by SSL_clear*/
 
-	int new_session;/* 1 if we are to use a new session.
-	                 * 2 if we are a server and are inside a handshake
-	                 *   (i.e. not just sending a HelloRequest)
-	                 * NB: For servers, the 'new' session may actually be a previously
-	                 * cached session or even the previous session unless
-	                 * SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION is set */
+	int new_session;/* Generate a new session or reuse an old one.
+					 * NB: For servers, the 'new' session may actually be a previously
+					 * cached session or even the previous session unless
+					 * SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION is set */
+	int renegotiate;/* 1 if we are renegotiating.
+					 * 2 if we are a server and are inside a handshake
+					 *   (i.e. not just sending a HelloRequest) */
+
 	int quiet_shutdown;/* don't send shutdown packets */
 	int shutdown;	/* we have shut things down, 0x01 sent, 0x02
 			 * for received */
@@ -1717,6 +1719,7 @@
 
 int SSL_do_handshake(SSL *s);
 int SSL_renegotiate(SSL *s);
+int SSL_renegotiate_abbreviated(SSL *s);
 int SSL_renegotiate_pending(SSL *s);
 int SSL_shutdown(SSL *s);
 
diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
index f59a454..ff71004 100644
--- a/ssl/ssl_lib.c
+++ b/ssl/ssl_lib.c
@@ -202,9 +202,9 @@
        * needed because SSL_clear is not called when doing renegotiation) */
 	/* This is set if we are doing dynamic renegotiation so keep
 	 * the old cipher.  It is sort of a SSL_clear_lite :-) */
-	if (s->new_session) return(1);
+	if (s->renegotiate) return(1);
 #else
-	if (s->new_session)
+	if (s->renegotiate)
 		{
 		SSLerr(SSL_F_SSL_CLEAR,ERR_R_INTERNAL_ERROR);
 		return 0;
@@ -1016,18 +1016,29 @@
 
 int SSL_renegotiate(SSL *s)
 	{
-	if (s->new_session == 0)
-		{
-		s->new_session=1;
-		}
+	if (s->renegotiate == 0)
+		s->renegotiate=1;
+
+	s->new_session=1;
+
 	return(s->method->ssl_renegotiate(s));
 	}
 
+int SSL_renegotiate_abbreviated(SSL *s)
+{
+	if (s->renegotiate == 0)
+		s->renegotiate=1;
+	
+	s->new_session=0;
+	
+	return(s->method->ssl_renegotiate(s));
+}
+
 int SSL_renegotiate_pending(SSL *s)
 	{
 	/* becomes true when negotiation is requested;
 	 * false again once a handshake has finished */
-	return (s->new_session != 0);
+	return (s->renegotiate != 0);
 	}
 
 long SSL_ctrl(SSL *s,int cmd,long larg,void *parg)
@@ -2649,6 +2660,7 @@
 	ret->in_handshake = s->in_handshake;
 	ret->handshake_func = s->handshake_func;
 	ret->server = s->server;
+	ret->renegotiate = s->renegotiate;
 	ret->new_session = s->new_session;
 	ret->quiet_shutdown = s->quiet_shutdown;
 	ret->shutdown=s->shutdown;