Commit 41b3c9ce authored by Matt Caswell's avatar Matt Caswell
Browse files

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: default avatarRichard Levitte <levitte@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/3286)
parent aefb9256
Loading
Loading
Loading
Loading
+6 −37
Original line number Diff line number Diff line
@@ -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,28 +1262,16 @@ 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);
            BIO_clear_retry_flags(b);
            BIO_set_retry_write(b);
            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;
        }
    }

    iov[0].iov_base = (char *)in;