X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=ssl%2Fd1_lib.c;h=183717624c3a403e186cfb00d3ea2b6045210a9c;hb=c21a427a149774c0e14600062d04646da0c7a3f0;hp=ae067f6eed6329afce330e15584bfc108fb0ca9c;hpb=6252f3bc7c2dfd79ebd673dcffababc2f37752f1;p=oweals%2Fopenssl.git diff --git a/ssl/d1_lib.c b/ssl/d1_lib.c index ae067f6eed..183717624c 100644 --- a/ssl/d1_lib.c +++ b/ssl/d1_lib.c @@ -58,9 +58,15 @@ */ #include +#define USE_SOCKETS #include #include "ssl_locl.h" +#if defined(OPENSSL_SYS_WIN32) || defined(OPENSSL_SYS_VMS) +#include +#endif + +static void get_current_time(struct timeval *t); const char dtls1_version_str[]="DTLSv1" OPENSSL_VERSION_PTEXT; SSL3_ENC_METHOD DTLSv1_enc_data={ @@ -198,7 +204,33 @@ void dtls1_free(SSL *s) void dtls1_clear(SSL *s) { ssl3_clear(s); - s->version=DTLS1_VERSION; + if (s->options & SSL_OP_CISCO_ANYCONNECT) + s->version=DTLS1_BAD_VER; + else + 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); } /* @@ -220,3 +252,137 @@ SSL_CIPHER *dtls1_get_cipher(unsigned int u) return ciph; } + +void dtls1_start_timer(SSL *s) + { + /* If timer is not set, initialize duration with 1 second */ + if (s->d1->next_timeout.tv_sec == 0 && s->d1->next_timeout.tv_usec == 0) + { + s->d1->timeout_duration = 1; + } + + /* Set timeout to current time */ + get_current_time(&(s->d1->next_timeout)); + + /* Add duration to current time */ + s->d1->next_timeout.tv_sec += s->d1->timeout_duration; + BIO_ctrl(SSL_get_rbio(s), BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT, 0, &(s->d1->next_timeout)); + } + +struct timeval* dtls1_get_timeout(SSL *s, struct timeval* timeleft) + { + struct timeval timenow; + + /* If no timeout is set, just return NULL */ + if (s->d1->next_timeout.tv_sec == 0 && s->d1->next_timeout.tv_usec == 0) + { + return NULL; + } + + /* Get current time */ + get_current_time(&timenow); + + /* If timer already expired, set remaining time to 0 */ + if (s->d1->next_timeout.tv_sec < timenow.tv_sec || + (s->d1->next_timeout.tv_sec == timenow.tv_sec && + s->d1->next_timeout.tv_usec <= timenow.tv_usec)) + { + memset(timeleft, 0, sizeof(struct timeval)); + return timeleft; + } + + /* Calculate time left until timer expires */ + memcpy(timeleft, &(s->d1->next_timeout), sizeof(struct timeval)); + timeleft->tv_sec -= timenow.tv_sec; + timeleft->tv_usec -= timenow.tv_usec; + if (timeleft->tv_usec < 0) + { + timeleft->tv_sec--; + timeleft->tv_usec += 1000000; + } + + return timeleft; + } + +int dtls1_is_timer_expired(SSL *s) + { + struct timeval timeleft; + + /* Get time left until timeout, return false if no timer running */ + if (dtls1_get_timeout(s, &timeleft) == NULL) + { + return 0; + } + + /* Return false if timer is not expired yet */ + if (timeleft.tv_sec > 0 || timeleft.tv_usec > 0) + { + return 0; + } + + /* Timer expired, so return true */ + return 1; + } + +void dtls1_double_timeout(SSL *s) + { + s->d1->timeout_duration *= 2; + if (s->d1->timeout_duration > 60) + s->d1->timeout_duration = 60; + dtls1_start_timer(s); + } + +void dtls1_stop_timer(SSL *s) + { + /* Reset everything */ + memset(&(s->d1->next_timeout), 0, sizeof(struct timeval)); + s->d1->timeout_duration = 1; + 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_HANDLE_TIMEOUT,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 + struct _timeb tb; + _ftime(&tb); + t->tv_sec = (long)tb.time; + t->tv_usec = (long)tb.millitm * 1000; +#elif defined(OPENSSL_SYS_VMS) + struct timeb tb; + ftime(&tb); + t->tv_sec = (long)tb.time; + t->tv_usec = (long)tb.millitm * 1000; +#else + gettimeofday(t, NULL); +#endif +}