From b651a05d261530923c4d1f8f464a91c50602d3ea Mon Sep 17 00:00:00 2001 From: Matt Caswell Date: Fri, 21 Apr 2017 16:56:06 +0100 Subject: [PATCH] Fix problem with SCTP close_notify alerts In SCTP the code was only allowing a send of a close_notify alert if the socket is dry. If the socket isn't dry then it was attempting to save away the close_notify alert to resend later when it is dry and then it returned success. However because the application then thinks that the close_notify alert has been successfully sent it never re-enters the DTLS code to actually resend the alert. A much simpler solution is to just fail with a retryable error in the event that the socket isn't dry. That way the application knows to retry sending the close_notify alert. Reviewed-by: Richard Levitte (Merged from https://github.com/openssl/openssl/pull/3287) --- crypto/bio/bss_dgram.c | 43 ++++++------------------------------------ 1 file changed, 6 insertions(+), 37 deletions(-) diff --git a/crypto/bio/bss_dgram.c b/crypto/bio/bss_dgram.c index 6dfcc9ba7b..81730abe44 100644 --- a/crypto/bio/bss_dgram.c +++ b/crypto/bio/bss_dgram.c @@ -130,7 +130,6 @@ typedef struct bio_dgram_sctp_data_st { int ccs_sent; int save_shutdown; int peer_auth_tested; - bio_dgram_sctp_save_message saved_message; } bio_dgram_sctp_data; # endif @@ -962,10 +961,8 @@ static int dgram_sctp_free(BIO *a) return 0; data = (bio_dgram_sctp_data *) a->ptr; - if (data != NULL) { - OPENSSL_free(data->saved_message.data); + if (data != NULL) OPENSSL_free(data); - } return (1); } @@ -1067,22 +1064,6 @@ static int dgram_sctp_read(BIO *b, char *out, int outl) struct sctp_event_subscribe event; socklen_t eventsize; # endif - /* - * If a message has been delayed until the socket is dry, - * it can be sent now. - */ - if (data->saved_message.length > 0) { - i = dgram_sctp_write(data->saved_message.bio, - data->saved_message.data, - data->saved_message.length); - if (i < 0) { - ret = i; - break; - } - OPENSSL_free(data->saved_message.data); - data->saved_message.data = NULL; - data->saved_message.length = 0; - } /* disable sender dry event */ # ifdef SCTP_EVENT @@ -1265,27 +1246,15 @@ static int dgram_sctp_write(BIO *b, const char *in, int inl) sinfo = &handshake_sinfo; } - /* - * If we have to send a shutdown alert message and the socket is not dry - * yet, we have to save it and send it as soon as the socket gets dry. - */ + /* We can only send a shutdown alert if the socket is dry */ if (data->save_shutdown) { ret = BIO_dgram_sctp_wait_for_dry(b); - if (ret < 0) { + if (ret < 0) return -1; - } if (ret == 0) { - char *tmp; - data->saved_message.bio = b; - if ((tmp = OPENSSL_malloc(inl)) == NULL) { - BIOerr(BIO_F_DGRAM_SCTP_WRITE, ERR_R_MALLOC_FAILURE); - return -1; - } - OPENSSL_free(data->saved_message.data); - data->saved_message.data = tmp; - memcpy(data->saved_message.data, in, inl); - data->saved_message.length = inl; - return inl; + BIO_clear_retry_flags(b); + BIO_set_retry_write(b); + return -1; } } -- 2.25.1