⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ssl_engine_kernel.c

📁 最新apache的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
     * override of SSLVerifyClient     *     * We force a renegotiation if the reconfigured/new verify type is     * stronger than the currently active verify type.      *     * The order is: none << optional_no_ca << optional << require     *     * Additionally the following optimization is possible here: When the     * currently active verify type is "none" but a client certificate is     * already known/present, it's enough to manually force a client     * verification but at least skip the I/O-intensive renegotation     * handshake.     */    if (dc->nVerifyClient != SSL_CVERIFY_UNSET) {        /* remember old state */        verify_old = SSL_get_verify_mode(ssl);        /* configure new state */        verify = SSL_VERIFY_NONE;        if (dc->nVerifyClient == SSL_CVERIFY_REQUIRE) {            verify |= SSL_VERIFY_PEER_STRICT;        }        if ((dc->nVerifyClient == SSL_CVERIFY_OPTIONAL) ||            (dc->nVerifyClient == SSL_CVERIFY_OPTIONAL_NO_CA))        {            verify |= SSL_VERIFY_PEER;        }        modssl_set_verify(ssl, verify, ssl_callback_SSLVerify);        SSL_set_verify_result(ssl, X509_V_OK);        /* determine whether we've to force a renegotiation */        if (!renegotiate && verify != verify_old) {            if (((verify_old == SSL_VERIFY_NONE) &&                 (verify     != SSL_VERIFY_NONE)) ||                (!(verify_old & SSL_VERIFY_PEER) &&                  (verify     & SSL_VERIFY_PEER)) ||                (!(verify_old & SSL_VERIFY_FAIL_IF_NO_PEER_CERT) &&                  (verify     & SSL_VERIFY_FAIL_IF_NO_PEER_CERT)))            {                renegotiate = TRUE;                /* optimization */                if ((dc->nOptions & SSL_OPT_OPTRENEGOTIATE) &&                    (verify_old == SSL_VERIFY_NONE) &&                    ((peercert = SSL_get_peer_certificate(ssl)) != NULL))                {                    renegotiate_quick = TRUE;                    X509_free(peercert);                }                ap_log_error(APLOG_MARK, APLOG_DEBUG, 0,                             r->server,                             "Changed client verification type will force "                             "%srenegotiation",                             renegotiate_quick ? "quick " : "");             }        }    }    /*     * override SSLCACertificateFile & SSLCACertificatePath     * This is only enabled if the SSL_set_cert_store() function     * is available in the ssl library.  the 1.x based mod_ssl     * used SSL_CTX_set_cert_store which is not thread safe.     */#ifdef HAVE_SSL_SET_CERT_STORE    /*     * check if per-dir and per-server config field are not the same.     * if f is defined in per-dir and not defined in per-server     * or f is defined in both but not the equal ...     */#define MODSSL_CFG_NE(f) \     (dc->f && (!sc->f || (sc->f && strNE(dc->f, sc->f))))#define MODSSL_CFG_CA(f) \     (dc->f ? dc->f : sc->f)    if (MODSSL_CFG_NE(szCACertificateFile) ||        MODSSL_CFG_NE(szCACertificatePath))    {        STACK_OF(X509_NAME) *ca_list;        const char *ca_file = MODSSL_CFG_CA(szCACertificateFile);        const char *ca_path = MODSSL_CFG_CA(szCACertificatePath);        cert_store = X509_STORE_new();        if (!X509_STORE_load_locations(cert_store, ca_file, ca_path)) {            ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,                         "Unable to reconfigure verify locations "                         "for client authentication");            ssl_log_ssl_error(APLOG_MARK, APLOG_ERR, r->server);            X509_STORE_free(cert_store);            return HTTP_FORBIDDEN;        }        /* SSL_free will free cert_store */        SSL_set_cert_store(ssl, cert_store);        if (!(ca_list = ssl_init_FindCAList(r->server, r->pool,                                            ca_file, ca_path)))        {            ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,                         "Unable to determine list of available "                         "CA certificates for client authentication");            return HTTP_FORBIDDEN;        }        SSL_set_client_CA_list(ssl, ca_list);        renegotiate = TRUE;        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,                     "Changed client verification locations will force "                     "renegotiation");    }#endif /* HAVE_SSL_SET_CERT_STORE */    /*      * SSL renegotiations in conjunction with HTTP     * requests using the POST method are not supported.     *     * Background:     *     * 1. When the client sends a HTTP/HTTPS request, Apache's core code     * reads only the request line ("METHOD /path HTTP/x.y") and the     * attached MIME headers ("Foo: bar") up to the terminating line ("CR     * LF"). An attached request body (for instance the data of a POST     * method) is _NOT_ read. Instead it is read by mod_cgi's content     * handler and directly passed to the CGI script.     *     * 2. mod_ssl supports per-directory re-configuration of SSL parameters.     * This is implemented by performing an SSL renegotiation of the     * re-configured parameters after the request is read, but before the     * response is sent. In more detail: the renegotiation happens after the     * request line and MIME headers were read, but _before_ the attached     * request body is read. The reason simply is that in the HTTP protocol     * usually there is no acknowledgment step between the headers and the     * body (there is the 100-continue feature and the chunking facility     * only), so Apache has no API hook for this step.     *     * 3. the problem now occurs when the client sends a POST request for     * URL /foo via HTTPS the server and the server has SSL parameters     * re-configured on a per-URL basis for /foo. Then mod_ssl has to     * perform an SSL renegotiation after the request was read and before     * the response is sent. But the problem is the pending POST body data     * in the receive buffer of SSL (which Apache still has not read - it's     * pending until mod_cgi sucks it in). When mod_ssl now tries to perform     * the renegotiation the pending data leads to an I/O error.     *     * Solution Idea:     *     * There are only two solutions: Either to simply state that POST     * requests to URLs with SSL re-configurations are not allowed, or to     * renegotiate really after the _complete_ request (i.e. including     * the POST body) was read. Obviously the latter would be preferred,     * but it cannot be done easily inside Apache, because as already     * mentioned, there is no API step between the body reading and the body     * processing. And even when we mod_ssl would hook directly into the     * loop of mod_cgi, we wouldn't solve the problem for other handlers, of     * course. So the only general solution is to suck in the pending data     * of the request body from the OpenSSL BIO into the Apache BUFF. Then     * the renegotiation can be done and after this step Apache can proceed     * processing the request as before.     *     * Solution Implementation:     *     * We cannot simply suck in the data via an SSL_read-based loop because of     * HTTP chunking. Instead we _have_ to use the Apache API for this step which     * is aware of HTTP chunking. So the trick is to suck in the pending request     * data via the Apache API (which uses Apache's BUFF code and in the     * background mod_ssl's I/O glue code) and re-inject it later into the Apache     * BUFF code again. This way the data flows twice through the Apache BUFF, of     * course. But this way the solution doesn't depend on any Apache specifics     * and is fully transparent to Apache modules.     *     * !! BUT ALL THIS IS STILL NOT RE-IMPLEMENTED FOR APACHE 2.0 !!     */    if (renegotiate && !renegotiate_quick && (r->method_number == M_POST)) {        ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,                     "SSL Re-negotiation in conjunction "                     "with POST method not supported! "                     "hint: try SSLOptions +OptRenegotiate");        return HTTP_METHOD_NOT_ALLOWED;    }    /*     * now do the renegotiation if anything was actually reconfigured     */    if (renegotiate) {        /*         * Now we force the SSL renegotation by sending the Hello Request         * message to the client. Here we have to do a workaround: Actually         * OpenSSL returns immediately after sending the Hello Request (the         * intent AFAIK is because the SSL/TLS protocol says it's not a must         * that the client replies to a Hello Request). But because we insist         * on a reply (anything else is an error for us) we have to go to the         * ACCEPT state manually. Using SSL_set_accept_state() doesn't work         * here because it resets too much of the connection.  So we set the         * state explicitly and continue the handshake manually.         */        ap_log_error(APLOG_MARK, APLOG_INFO, 0, r->server,                     "Requesting connection re-negotiation");        if (renegotiate_quick) {            STACK_OF(X509) *cert_stack;            /* perform just a manual re-verification of the peer */            ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,                         "Performing quick renegotiation: "                         "just re-verifying the peer");            cert_stack = (STACK_OF(X509) *)SSL_get_peer_cert_chain(ssl);            cert = SSL_get_peer_certificate(ssl);            if (!cert_stack && cert) {                /* client cert is in the session cache, but there is                 * no chain, since ssl3_get_client_certificate()                 * sk_X509_shift-ed the peer cert out of the chain.                 * we put it back here for the purpose of quick_renegotiation.                 */                cert_stack = sk_new_null();                sk_X509_push(cert_stack, MODSSL_PCHAR_CAST cert);            }            if (!cert_stack || (sk_X509_num(cert_stack) == 0)) {                ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,                             "Cannot find peer certificate chain");                return HTTP_FORBIDDEN;            }            if (!(cert_store ||                  (cert_store = SSL_CTX_get_cert_store(ctx))))            {                ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,                             "Cannot find certificate storage");                return HTTP_FORBIDDEN;            }            if (!cert) {                cert = sk_X509_value(cert_stack, 0);            }            X509_STORE_CTX_init(&cert_store_ctx, cert_store, cert, cert_stack);            depth = SSL_get_verify_depth(ssl);            if (depth >= 0) {                X509_STORE_CTX_set_depth(&cert_store_ctx, depth);            }            X509_STORE_CTX_set_ex_data(&cert_store_ctx,                                       SSL_get_ex_data_X509_STORE_CTX_idx(),                                       (char *)ssl);            if (!modssl_X509_verify_cert(&cert_store_ctx)) {                ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,                             "Re-negotiation verification step failed");                ssl_log_ssl_error(APLOG_MARK, APLOG_ERR, r->server);            }            SSL_set_verify_result(ssl, cert_store_ctx.error);            X509_STORE_CTX_cleanup(&cert_store_ctx);            if (cert_stack != SSL_get_peer_cert_chain(ssl)) {                /* we created this ourselves, so free it */                sk_X509_pop_free(cert_stack, X509_free);            }        }        else {            request_rec *id = r->main ? r->main : r;            /* do a full renegotiation */            ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server,                         "Performing full renegotiation: "                         "complete handshake protocol");            SSL_set_session_id_context(ssl,                                       (unsigned char *)&id,                                       sizeof(id));            SSL_renegotiate(ssl);            SSL_do_handshake(ssl);            if (SSL_get_state(ssl) != SSL_ST_OK) {                ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,                             "Re-negotiation request failed");                r->connection->aborted = 1;                return HTTP_FORBIDDEN;            }            ap_log_error(APLOG_MARK, APLOG_INFO, 0, r->server,                         "Awaiting re-negotiation handshake");            SSL_set_state(ssl, SSL_ST_ACCEPT);            SSL_do_handshake(ssl);            if (SSL_get_state(ssl) != SSL_ST_OK) {                ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,                             "Re-negotiation handshake failed: "                        "Not accepted by client!?");                r->connection->aborted = 1;                return HTTP_FORBIDDEN;            }        }        /*         * Remember the peer certificate's DN         */        if ((cert = SSL_get_peer_certificate(ssl))) {            if (sslconn->client_cert) {                X509_free(sslconn->client_cert);            }            sslconn->client_cert = cert;            sslconn->client_dn = NULL;        }        /*         * Finally check for acceptable renegotiation results         */        if (dc->nVerifyClient != SSL_CVERIFY_NONE) {            BOOL do_verify = (dc->nVerifyClient == SSL_CVERIFY_REQUIRE);            if (do_verify && (SSL_get_verify_result(ssl) != X509_V_OK)) {                ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,                             "Re-negotiation handshake failed: "                             "Client verification failed");                return HTTP_FORBIDDEN;            }            if (do_verify) {                if ((peercert = SSL_get_peer_certificate(ssl)) == NULL) {                    ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,                                 "Re-negotiation handshake failed: "                                 "Client certificate missing");                    return HTTP_FORBIDDEN;                }                X509_free(peercert);            }        }                /*         * Also check that SSLCipherSuite has been enforced as expected.         */        if (cipher_list) {            cipher = SSL_get_current_cipher(ssl);            if (sk_SSL_CIPHER_find(cipher_list, cipher) < 0) {                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,                             "SSL cipher suite not renegotiated: "                             "access to %s denied using cipher %s",                              r->filename,                              SSL_CIPHER_get_name(cipher));                return HTTP_FORBIDDEN;            }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -