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 <levitte@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/3287)
int ccs_sent;
int save_shutdown;
int peer_auth_tested;
int ccs_sent;
int save_shutdown;
int peer_auth_tested;
- bio_dgram_sctp_save_message saved_message;
} bio_dgram_sctp_data;
# endif
} bio_dgram_sctp_data;
# endif
return 0;
data = (bio_dgram_sctp_data *) a->ptr;
return 0;
data = (bio_dgram_sctp_data *) a->ptr;
- if (data != NULL) {
- OPENSSL_free(data->saved_message.data);
struct sctp_event_subscribe event;
socklen_t eventsize;
# endif
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
/* disable sender dry event */
# ifdef SCTP_EVENT
sinfo = &handshake_sinfo;
}
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 (data->save_shutdown) {
ret = BIO_dgram_sctp_wait_for_dry(b);
- 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;