Commit 905943af authored by Matt Caswell's avatar Matt Caswell
Browse files

Fix error when server does not send CertificateStatus message



If a server sends the status_request extension then it may choose
to send the CertificateStatus message. However this is optional.
We were treating it as mandatory and the connection was failing.

Thanks to BoringSSL for reporting this issue.

RT#4120

Reviewed-by: default avatarViktor Dukhovni <viktor@openssl.org>
parent 155a1623
Loading
Loading
Loading
Loading
+34 −27
Original line number Diff line number Diff line
@@ -2350,10 +2350,18 @@ int ssl3_get_cert_status(SSL *s)
    n = s->method->ssl_get_message(s,
                                   SSL3_ST_CR_CERT_STATUS_A,
                                   SSL3_ST_CR_CERT_STATUS_B,
                                   SSL3_MT_CERTIFICATE_STATUS, 16384, &ok);
                                   -1, 16384, &ok);

    if (!ok)
        return ((int)n);

    if (s->s3->tmp.message_type != SSL3_MT_CERTIFICATE_STATUS) {
        /*
         * The CertificateStatus message is optional even if
         * tlsext_status_expected is set
         */
        s->s3->tmp.reuse_message = 1;
    } else {
        if (n < 4) {
            /* need at least status type + length */
            al = SSL_AD_DECODE_ERROR;
@@ -2372,15 +2380,14 @@ int ssl3_get_cert_status(SSL *s)
            SSLerr(SSL_F_SSL3_GET_CERT_STATUS, SSL_R_LENGTH_MISMATCH);
            goto f_err;
        }
    if (s->tlsext_ocsp_resp)
        OPENSSL_free(s->tlsext_ocsp_resp);
        s->tlsext_ocsp_resp = BUF_memdup(p, resplen);
    if (!s->tlsext_ocsp_resp) {
        if (s->tlsext_ocsp_resp == NULL) {
            al = SSL_AD_INTERNAL_ERROR;
            SSLerr(SSL_F_SSL3_GET_CERT_STATUS, ERR_R_MALLOC_FAILURE);
            goto f_err;
        }
        s->tlsext_ocsp_resplen = resplen;
    }
    if (s->ctx->tlsext_status_cb) {
        int ret;
        ret = s->ctx->tlsext_status_cb(s, s->ctx->tlsext_status_arg);
+5 −7
Original line number Diff line number Diff line
@@ -3157,6 +3157,9 @@ int ssl_check_serverhello_tlsext(SSL *s)
    }
# endif

    OPENSSL_free(s->tlsext_ocsp_resp);
    s->tlsext_ocsp_resp = NULL;
    s->tlsext_ocsp_resplen = -1;
    /*
     * If we've requested certificate status and we wont get one tell the
     * callback
@@ -3165,14 +3168,9 @@ int ssl_check_serverhello_tlsext(SSL *s)
        && s->ctx && s->ctx->tlsext_status_cb) {
        int r;
        /*
         * Set resp to NULL, resplen to -1 so callback knows there is no
         * response.
         * Call callback with resp == NULL and resplen == -1 so callback
         * knows there is no response
         */
        if (s->tlsext_ocsp_resp) {
            OPENSSL_free(s->tlsext_ocsp_resp);
            s->tlsext_ocsp_resp = NULL;
        }
        s->tlsext_ocsp_resplen = -1;
        r = s->ctx->tlsext_status_cb(s, s->ctx->tlsext_status_arg);
        if (r == 0) {
            al = SSL_AD_BAD_CERTIFICATE_STATUS_RESPONSE;