int SSL_callback_SSL_verify()

in native/src/sslutils.c [295:386]


int SSL_callback_SSL_verify(int ok, X509_STORE_CTX *ctx)
{
   /* Get Apache context back through OpenSSL context */
    SSL *ssl = X509_STORE_CTX_get_ex_data(ctx,
                                          SSL_get_ex_data_X509_STORE_CTX_idx());
    tcn_ssl_conn_t *con = (tcn_ssl_conn_t *)SSL_get_app_data(ssl);
    /* Get verify ingredients */
    int errnum   = X509_STORE_CTX_get_error(ctx);
    int errdepth = X509_STORE_CTX_get_error_depth(ctx);
    int verify   = con->ctx->verify_mode;
    int depth    = con->ctx->verify_depth;
    int ocsp_check_type = con->ctx->no_ocsp_check;

#if defined(SSL_OP_NO_TLSv1_3)
    con->pha_state = PHA_COMPLETE;
#endif

    if (verify == SSL_CVERIFY_UNSET ||
        verify == SSL_CVERIFY_NONE) {
        return 1;
    }

    if (SSL_VERIFY_ERROR_IS_OPTIONAL(errnum) &&
        (verify == SSL_CVERIFY_OPTIONAL_NO_CA)) {
        ok = 1;
        SSL_set_verify_result(ssl, X509_V_OK);
    }

    /*
     * Expired certificates vs. "expired" CRLs: by default, OpenSSL
     * turns X509_V_ERR_CRL_HAS_EXPIRED into a "certificate_expired(45)"
     * SSL alert, but that's not really the message we should convey to the
     * peer (at the very least, it's confusing, and in many cases, it's also
     * inaccurate, as the certificate itself may very well not have expired
     * yet). We set the X509_STORE_CTX error to something which OpenSSL's
     * s3_both.c:ssl_verify_alarm_type() maps to SSL_AD_CERTIFICATE_UNKNOWN,
     * i.e. the peer will receive a "certificate_unknown(46)" alert.
     * We do not touch errnum, though, so that later on we will still log
     * the "real" error, as returned by OpenSSL.
     */
    if (!ok && errnum == X509_V_ERR_CRL_HAS_EXPIRED) {
        X509_STORE_CTX_set_error(ctx, -1);
    }

#ifdef HAVE_OCSP
    /* First perform OCSP validation if possible */
    if (ocsp_check_type == 0) {
       if (ok) {
            /* If there was an optional verification error, it's not
             * possible to perform OCSP validation since the issuer may be
             * missing/untrusted.  Fail in that case.
             */
            if (SSL_VERIFY_ERROR_IS_OPTIONAL(errnum)) {
                X509_STORE_CTX_set_error(ctx, X509_V_ERR_APPLICATION_VERIFICATION);
                errnum = X509_V_ERR_APPLICATION_VERIFICATION;
                ok = 0;
            }
            else {
                int ocsp_response = ssl_verify_OCSP(ctx);
                if (ocsp_response == OCSP_STATUS_REVOKED) {
                    ok = 0 ;
                    errnum = X509_STORE_CTX_get_error(ctx);
                }
                else if (ocsp_response == OCSP_STATUS_UNKNOWN) {
                    errnum = X509_STORE_CTX_get_error(ctx);
                    if (errnum)
                        ok = 0 ;
                }
            }
        }
    }
#endif
    /*
     * If we already know it's not ok, log the real reason
     */
    if (!ok) {
        /* TODO: Some logging
         * Certificate Verification: Error
         */
        if (con->peer) {
            X509_free(con->peer);
            con->peer = NULL;
        }
    }
    if (errdepth > depth) {
        /* TODO: Some logging
         * Certificate Verification: Certificate Chain too long
         */
        ok = 0;
    }
    return ok;
}