From: Matt Caswell Date: Fri, 21 Apr 2017 15:56:06 +0000 (+0100) Subject: Fix problem with SCTP close_notify alerts X-Git-Tag: OpenSSL_1_1_1-pre1~1697 X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=41b3c9ce2a02195aa7cf74c90b80468354ac708d;p=oweals%2Fopenssl.git 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/3286) --- diff --git a/crypto/bio/bss_dgram.c b/crypto/bio/bss_dgram.c index d3a7b03fba..7ef4281597 100644 --- a/crypto/bio/bss_dgram.c +++ b/crypto/bio/bss_dgram.c @@ -135,7 +135,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 @@ -978,10 +977,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); } @@ -1083,22 +1080,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 @@ -1281,27 +1262,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; } }