Commit b972fbaa authored by Dr. Stephen Henson's avatar Dr. Stephen Henson
Browse files

PR: 1997

Submitted by: Robin Seggelmann <seggelmann@fh-muenster.de>
Approved by: steve@openssl.org

DTLS timeout handling fix.
parent 77c7f17a
Loading
Loading
Loading
Loading
+16 −5
Original line number Diff line number Diff line
@@ -411,6 +411,7 @@ int MAIN(int argc, char **argv)
	BIO *sbio;
	char *inrand=NULL;
	int mbuf_len=0;
	struct timeval timeout, *timeoutp;
#ifndef OPENSSL_NO_ENGINE
	char *engine_id=NULL;
	char *ssl_client_engine_id=NULL;
@@ -979,7 +980,6 @@ re_start:

	if ( SSL_version(con) == DTLS1_VERSION)
		{
		struct timeval timeout;

		sbio=BIO_new_dgram(s,BIO_NOCLOSE);
		if (getsockname(s, &peer, (void *)&peerlen) < 0)
@@ -1196,6 +1196,12 @@ SSL_set_tlsext_status_ids(con, ids);
		FD_ZERO(&readfds);
		FD_ZERO(&writefds);

		if ((SSL_version(con) == DTLS1_VERSION) &&
			DTLSv1_get_timeout(con, &timeout))
			timeoutp = &timeout;
		else
			timeoutp = NULL;

		if (SSL_in_init(con) && !SSL_total_renegotiations(con))
			{
			in_init=1;
@@ -1300,7 +1306,7 @@ SSL_set_tlsext_status_ids(con, ids);
					if(!i && (!((_kbhit()) || (WAIT_OBJECT_0 == WaitForSingleObject(GetStdHandle(STD_INPUT_HANDLE), 0))) || !read_tty) ) continue;
#endif
				} else 	i=select(width,(void *)&readfds,(void *)&writefds,
					 NULL,NULL);
					 NULL,timeoutp);
			}
#elif defined(OPENSSL_SYS_NETWARE)
			if(!write_tty) {
@@ -1310,7 +1316,7 @@ SSL_set_tlsext_status_ids(con, ids);
					i=select(width,(void *)&readfds,(void *)&writefds,
						NULL,&tv);
				} else 	i=select(width,(void *)&readfds,(void *)&writefds,
					NULL,NULL);
					NULL,timeoutp);
			}
#elif defined(OPENSSL_SYS_BEOS_R5)
			/* Under BeOS-R5 the situation is similar to DOS */
@@ -1328,12 +1334,12 @@ SSL_set_tlsext_status_ids(con, ids);
					if (!i && (stdin_set != 1 || !read_tty))
						continue;
				} else 	i=select(width,(void *)&readfds,(void *)&writefds,
					 NULL,NULL);
					 NULL,timeoutp);
			}
			(void)fcntl(fileno(stdin), F_SETFL, 0);
#else
			i=select(width,(void *)&readfds,(void *)&writefds,
				 NULL,NULL);
				 NULL,timeoutp);
#endif
			if ( i < 0)
				{
@@ -1344,6 +1350,11 @@ SSL_set_tlsext_status_ids(con, ids);
				}
			}

		if ((SSL_version(con) == DTLS1_VERSION) && DTLSv1_handle_timeout(con) > 0)
			{
			BIO_printf(bio_err,"TIMEOUT occured\n");
			}

		if (!ssl_pending && FD_ISSET(SSL_get_fd(con),&writefds))
			{
			k=SSL_write(con,&(cbuf[cbuf_off]),
+14 −2
Original line number Diff line number Diff line
@@ -1750,6 +1750,7 @@ static int sv_body(char *hostname, int s, unsigned char *context)
	unsigned long l;
	SSL *con=NULL;
	BIO *sbio;
	struct timeval timeout, *timeoutp;
#if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_MSDOS) || defined(OPENSSL_SYS_NETWARE) || defined(OPENSSL_SYS_BEOS_R5)
	struct timeval tv;
#endif
@@ -1808,7 +1809,6 @@ static int sv_body(char *hostname, int s, unsigned char *context)

	if (SSL_version(con) == DTLS1_VERSION)
		{
		struct timeval timeout;

		sbio=BIO_new_dgram(s,BIO_NOCLOSE);

@@ -1919,7 +1919,19 @@ static int sv_body(char *hostname, int s, unsigned char *context)
				read_from_terminal = 1;
			(void)fcntl(fileno(stdin), F_SETFL, 0);
#else
			i=select(width,(void *)&readfds,NULL,NULL,NULL);
			if ((SSL_version(con) == DTLS1_VERSION) &&
				DTLSv1_get_timeout(con, &timeout))
				timeoutp = &timeout;
			else
				timeoutp = NULL;

			i=select(width,(void *)&readfds,NULL,NULL,timeoutp);

			if ((SSL_version(con) == DTLS1_VERSION) && DTLSv1_handle_timeout(con) > 0)
				{
				BIO_printf(bio_err,"TIMEOUT occured\n");
				}

			if (i <= 0) continue;
			if (FD_ISSET(fileno(stdin),&readfds))
				read_from_terminal = 1;
+4 −25
Original line number Diff line number Diff line
@@ -890,9 +890,6 @@ unsigned long dtls1_output_cert_chain(SSL *s, X509 *x)

int dtls1_read_failed(SSL *s, int code)
	{
	DTLS1_STATE *state;
	int send_alert = 0;

	if ( code > 0)
		{
		fprintf( stderr, "invalid state reached %s:%d", __FILE__, __LINE__);
@@ -912,24 +909,6 @@ int dtls1_read_failed(SSL *s, int code)
		return code;
		}

	dtls1_double_timeout(s);
	state = s->d1;
	state->timeout.num_alerts++;
	if ( state->timeout.num_alerts > DTLS1_TMO_ALERT_COUNT)
		{
		/* fail the connection, enough alerts have been sent */
		SSLerr(SSL_F_DTLS1_READ_FAILED,SSL_R_READ_TIMEOUT_EXPIRED);
		return 0;
		}

	state->timeout.read_timeouts++;
	if ( state->timeout.read_timeouts > DTLS1_TMO_READ_COUNT)
		{
		send_alert = 1;
		state->timeout.read_timeouts = 1;
		}


#if 0 /* for now, each alert contains only one record number */
	item = pqueue_peek(state->rcvd_records);
	if ( item )
@@ -940,12 +919,12 @@ int dtls1_read_failed(SSL *s, int code)
#endif

#if 0  /* no more alert sending, just retransmit the last set of messages */
		if ( send_alert)
	if ( state->timeout.read_timeouts >= DTLS1_TMO_READ_COUNT)
		ssl3_send_alert(s,SSL3_AL_WARNING,
			DTLS1_AD_MISSING_HANDSHAKE_MESSAGE);
#endif

	return dtls1_retransmit_buffered_messages(s) ;
	return dtls1_handle_timeout(s);
	}

int
+53 −0
Original line number Diff line number Diff line
@@ -188,6 +188,29 @@ void dtls1_clear(SSL *s)
		s->version=DTLS1_VERSION;
	}

long dtls1_ctrl(SSL *s, int cmd, long larg, void *parg)
	{
	int ret=0;

	switch (cmd)
		{
	case DTLS_CTRL_GET_TIMEOUT:
		if (dtls1_get_timeout(s, (struct timeval*) parg) != NULL)
			{
			ret = 1;
			}
		break;
	case DTLS_CTRL_HANDLE_TIMEOUT:
		ret = dtls1_handle_timeout(s);
		break;

	default:
		ret = ssl3_ctrl(s, cmd, larg, parg);
		break;
		}
	return(ret);
	}

/*
 * As it's impossible to use stream ciphers in "datagram" mode, this
 * simple filter is designed to disengage them in DTLS. Unfortunately
@@ -295,6 +318,36 @@ void dtls1_stop_timer(SSL *s)
	BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT, 0, &(s->d1->next_timeout));
	}

int dtls1_handle_timeout(SSL *s)
	{
	DTLS1_STATE *state;

	/* if no timer is expired, don't do anything */
	if (!dtls1_is_timer_expired(s))
		{
		return 0;
		}

	dtls1_double_timeout(s);
	state = s->d1;
	state->timeout.num_alerts++;
	if ( state->timeout.num_alerts > DTLS1_TMO_ALERT_COUNT)
		{
		/* fail the connection, enough alerts have been sent */
		SSLerr(SSL_F_DTLS1_READ_FAILED,SSL_R_READ_TIMEOUT_EXPIRED);
		return 0;
		}

	state->timeout.read_timeouts++;
	if ( state->timeout.read_timeouts > DTLS1_TMO_READ_COUNT)
		{
		state->timeout.read_timeouts = 1;
		}

	dtls1_start_timer(s);
	return dtls1_retransmit_buffered_messages(s);
	}

static void get_current_time(struct timeval *t)
{
#ifdef OPENSSL_SYS_WIN32
+2 −5
Original line number Diff line number Diff line
@@ -773,11 +773,8 @@ start:
		}

	/* Check for timeout */
	if (dtls1_is_timer_expired(s))
		{
		if (dtls1_read_failed(s, -1) > 0)
	if (dtls1_handle_timeout(s) > 0)
		goto start;
		}

	/* get new packet if necessary */
	if ((rr->length == 0) || (s->rstate == SSL_ST_READ_BODY))
Loading