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

PR: 1829

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

DTLS Timer Bug fix.
parent 1319aad9
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -159,6 +159,7 @@ extern "C" {

#define BIO_CTRL_DGRAM_SET_PEER           44 /* Destination for the data */

#define BIO_CTRL_DGRAM_SET_TIMEOUT        45

/* modifiers */
#define BIO_FP_READ		0x02
+50 −0
Original line number Diff line number Diff line
@@ -104,6 +104,8 @@ typedef struct bio_dgram_data_st
	unsigned int connected;
	unsigned int _errno;
	unsigned int mtu;
	struct timeval hstimeoutdiff;
	struct timeval hstimeout;
	} bio_dgram_data;

BIO_METHOD *BIO_s_datagram(void)
@@ -196,6 +198,29 @@ static int dgram_read(BIO *b, char *out, int outl)
				BIO_set_retry_read(b);
				data->_errno = get_last_socket_error();
				}
			memset(&(data->hstimeout), 0, sizeof(struct timeval));
			}
		else
			{
			if (data->hstimeout.tv_sec > 0 || data->hstimeout.tv_usec > 0)
				{
#ifdef OPENSSL_SYS_WIN32
				struct timeb tb;
				ftime(&tb);
				curtime.tv_sec = tb.time;
				curtime.tv_usec = tb.millitm * 1000;
#else
				gettimeofday(&curtime, NULL);
#endif

				if (curtime.tv_sec >= data->hstimeout.tv_sec &&
					curtime.tv_usec >= data->hstimeout.tv_usec)
					{
					data->_errno = EAGAIN;
					ret = -1;
					memset(&(data->hstimeout), 0, sizeof(struct timeval));
					}
				}
			}
		}
	return(ret);
@@ -345,6 +370,30 @@ static long dgram_ctrl(BIO *b, int cmd, long num, void *ptr)

        memcpy(&(data->peer), to, sizeof(struct sockaddr));
        break;
	case BIO_CTRL_DGRAM_SET_TIMEOUT:
		if (num > 0)
			{
#ifdef OPENSSL_SYS_WIN32
			struct timeb tb;
			ftime(&tb);
			data->hstimeout.tv_sec = tb.time;
			data->hstimeout.tv_usec = tb.millitm * 1000;
#else
			gettimeofday(&(data->hstimeout), NULL);
#endif
			data->hstimeout.tv_sec += data->hstimeoutdiff.tv_sec;
			data->hstimeout.tv_usec += data->hstimeoutdiff.tv_usec;
			if (data->hstimeout.tv_usec >= 1000000)
				{
				data->hstimeout.tv_sec++;
				data->hstimeout.tv_usec -= 1000000;
				}
			}
		else
			{
			memset(&(data->hstimeout), 0, sizeof(struct timeval));
			}
		break;
#if defined(SO_RCVTIMEO)
	case BIO_CTRL_DGRAM_SET_RECV_TIMEOUT:
#ifdef OPENSSL_SYS_WINDOWS
@@ -360,6 +409,7 @@ static long dgram_ctrl(BIO *b, int cmd, long num, void *ptr)
			sizeof(struct timeval)) < 0)
			{ perror("setsockopt");	ret = -1; }
#endif
		memcpy(&(data->hstimeoutdiff), ptr, sizeof(struct timeval));
		break;
	case BIO_CTRL_DGRAM_GET_RECV_TIMEOUT:
#ifdef OPENSSL_SYS_WINDOWS
+9 −0
Original line number Diff line number Diff line
@@ -229,6 +229,7 @@ int dtls1_connect(SSL *s)
			/* every DTLS ClientHello resets Finished MAC */
			ssl3_init_finished_mac(s);

			BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_TIMEOUT, 1, NULL);
			ret=dtls1_client_hello(s);
			if (ret <= 0) goto end;

@@ -254,6 +255,7 @@ int dtls1_connect(SSL *s)
			if (ret <= 0) goto end;
			else
				{
				BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_TIMEOUT, 0, NULL);
				if (s->hit)
					s->state=SSL3_ST_CR_FINISHED_A;
				else
@@ -268,6 +270,7 @@ int dtls1_connect(SSL *s)
			ret = dtls1_get_hello_verify(s);
			if ( ret <= 0)
				goto end;
			BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_TIMEOUT, 0, NULL);
			if ( s->d1->send_cookie) /* start again, with a cookie */
				s->state=SSL3_ST_CW_CLNT_HELLO_A;
			else
@@ -329,6 +332,7 @@ int dtls1_connect(SSL *s)
		case SSL3_ST_CW_CERT_B:
		case SSL3_ST_CW_CERT_C:
		case SSL3_ST_CW_CERT_D:
			BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_TIMEOUT, 1, NULL);
			ret=dtls1_send_client_certificate(s);
			if (ret <= 0) goto end;
			s->state=SSL3_ST_CW_KEY_EXCH_A;
@@ -337,6 +341,7 @@ int dtls1_connect(SSL *s)

		case SSL3_ST_CW_KEY_EXCH_A:
		case SSL3_ST_CW_KEY_EXCH_B:
			BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_TIMEOUT, 1, NULL);
			ret=dtls1_send_client_key_exchange(s);
			if (ret <= 0) goto end;
			/* EAY EAY EAY need to check for DH fix cert
@@ -358,6 +363,7 @@ int dtls1_connect(SSL *s)

		case SSL3_ST_CW_CERT_VRFY_A:
		case SSL3_ST_CW_CERT_VRFY_B:
			BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_TIMEOUT, 1, NULL);
			ret=dtls1_send_client_verify(s);
			if (ret <= 0) goto end;
			s->state=SSL3_ST_CW_CHANGE_A;
@@ -367,6 +373,7 @@ int dtls1_connect(SSL *s)

		case SSL3_ST_CW_CHANGE_A:
		case SSL3_ST_CW_CHANGE_B:
			BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_TIMEOUT, 1, NULL);
			ret=dtls1_send_change_cipher_spec(s,
				SSL3_ST_CW_CHANGE_A,SSL3_ST_CW_CHANGE_B);
			if (ret <= 0) goto end;
@@ -401,6 +408,7 @@ int dtls1_connect(SSL *s)

		case SSL3_ST_CW_FINISHED_A:
		case SSL3_ST_CW_FINISHED_B:
			BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_TIMEOUT, 1, NULL);
			ret=dtls1_send_finished(s,
				SSL3_ST_CW_FINISHED_A,SSL3_ST_CW_FINISHED_B,
				s->method->ssl3_enc->client_finished_label,
@@ -433,6 +441,7 @@ int dtls1_connect(SSL *s)
			ret=ssl3_get_finished(s,SSL3_ST_CR_FINISHED_A,
				SSL3_ST_CR_FINISHED_B);
			if (ret <= 0) goto end;
			BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_TIMEOUT, 0, NULL);

			if (s->hit)
				s->state=SSL3_ST_CW_CHANGE_A;
+13 −0
Original line number Diff line number Diff line
@@ -249,6 +249,7 @@ int dtls1_accept(SSL *s)
		case SSL3_ST_SW_HELLO_REQ_B:

			s->shutdown=0;
			BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_TIMEOUT, 1, NULL);
			ret=dtls1_send_hello_request(s);
			if (ret <= 0) goto end;
			s->s3->tmp.next_state=SSL3_ST_SW_HELLO_REQ_C;
@@ -269,6 +270,7 @@ int dtls1_accept(SSL *s)
			s->shutdown=0;
			ret=ssl3_get_client_hello(s);
			if (ret <= 0) goto end;
			BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_TIMEOUT, 0, NULL);
			s->new_session = 2;

			if (s->d1->send_cookie)
@@ -282,6 +284,7 @@ int dtls1_accept(SSL *s)
		case DTLS1_ST_SW_HELLO_VERIFY_REQUEST_A:
		case DTLS1_ST_SW_HELLO_VERIFY_REQUEST_B:

			BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_TIMEOUT, 1, NULL);
			ret = dtls1_send_hello_verify_request(s);
			if ( ret <= 0) goto end;
			s->d1->send_cookie = 0;
@@ -294,6 +297,7 @@ int dtls1_accept(SSL *s)
			
		case SSL3_ST_SW_SRVR_HELLO_A:
		case SSL3_ST_SW_SRVR_HELLO_B:
			BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_TIMEOUT, 1, NULL);
			ret=dtls1_send_server_hello(s);
			if (ret <= 0) goto end;

@@ -309,6 +313,7 @@ int dtls1_accept(SSL *s)
			/* Check if it is anon DH */
			if (!(s->s3->tmp.new_cipher->algorithm_auth & SSL_aNULL))
				{
				BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_TIMEOUT, 1, NULL);
				ret=dtls1_send_server_certificate(s);
				if (ret <= 0) goto end;
				}
@@ -350,6 +355,7 @@ int dtls1_accept(SSL *s)
				)
			    )
				{
				BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_TIMEOUT, 1, NULL);
				ret=dtls1_send_server_key_exchange(s);
				if (ret <= 0) goto end;
				}
@@ -386,6 +392,7 @@ int dtls1_accept(SSL *s)
			else
				{
				s->s3->tmp.cert_request=1;
				BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_TIMEOUT, 1, NULL);
				ret=dtls1_send_certificate_request(s);
				if (ret <= 0) goto end;
#ifndef NETSCAPE_HANG_BUG
@@ -400,6 +407,7 @@ int dtls1_accept(SSL *s)

		case SSL3_ST_SW_SRVR_DONE_A:
		case SSL3_ST_SW_SRVR_DONE_B:
			BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_TIMEOUT, 1, NULL);
			ret=dtls1_send_server_done(s);
			if (ret <= 0) goto end;
			s->s3->tmp.next_state=SSL3_ST_SR_CERT_A;
@@ -427,6 +435,7 @@ int dtls1_accept(SSL *s)
			ret = ssl3_check_client_hello(s);
			if (ret <= 0)
				goto end;
			BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_TIMEOUT, 0, NULL);
			if (ret == 2)
				s->state = SSL3_ST_SR_CLNT_HELLO_C;
			else {
@@ -434,6 +443,7 @@ int dtls1_accept(SSL *s)
				 * have not asked for it :-) */
				ret=ssl3_get_client_certificate(s);
				if (ret <= 0) goto end;
				BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_TIMEOUT, 0, NULL);
				s->init_num=0;
				s->state=SSL3_ST_SR_KEY_EXCH_A;
			}
@@ -443,6 +453,7 @@ int dtls1_accept(SSL *s)
		case SSL3_ST_SR_KEY_EXCH_B:
			ret=ssl3_get_client_key_exchange(s);
			if (ret <= 0) goto end;
			BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_TIMEOUT, 0, NULL);
			s->state=SSL3_ST_SR_CERT_VRFY_A;
			s->init_num=0;

@@ -463,6 +474,7 @@ int dtls1_accept(SSL *s)
			/* we should decide if we expected this one */
			ret=ssl3_get_cert_verify(s);
			if (ret <= 0) goto end;
			BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_TIMEOUT, 0, NULL);

			s->state=SSL3_ST_SR_FINISHED_A;
			s->init_num=0;
@@ -473,6 +485,7 @@ int dtls1_accept(SSL *s)
			ret=ssl3_get_finished(s,SSL3_ST_SR_FINISHED_A,
				SSL3_ST_SR_FINISHED_B);
			if (ret <= 0) goto end;
			BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_TIMEOUT, 0, NULL);
			if (s->hit)
				s->state=SSL_ST_OK;
			else