📄 ssl_engine_kernel.c
字号:
/* _ _** _ __ ___ ___ __| | ___ ___| | mod_ssl** | '_ ` _ \ / _ \ / _` | / __/ __| | Apache Interface to OpenSSL** | | | | | | (_) | (_| | \__ \__ \ | www.modssl.org** |_| |_| |_|\___/ \__,_|___|___/___/_| ftp.modssl.org** |_____|** ssl_engine_kernel.c** The SSL engine kernel*//* ==================================================================== * Copyright (c) 1998-2006 Ralf S. Engelschall. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following * disclaimer in the documentation and/or other materials * provided with the distribution. * * 3. All advertising materials mentioning features or use of this * software must display the following acknowledgment: * "This product includes software developed by * Ralf S. Engelschall <rse@engelschall.com> for use in the * mod_ssl project (http://www.modssl.org/)." * * 4. The names "mod_ssl" must not be used to endorse or promote * products derived from this software without prior written * permission. For written permission, please contact * rse@engelschall.com. * * 5. Products derived from this software may not be called "mod_ssl" * nor may "mod_ssl" appear in their names without prior * written permission of Ralf S. Engelschall. * * 6. Redistributions of any form whatsoever must retain the following * acknowledgment: * "This product includes software developed by * Ralf S. Engelschall <rse@engelschall.com> for use in the * mod_ssl project (http://www.modssl.org/)." * * THIS SOFTWARE IS PROVIDED BY RALF S. ENGELSCHALL ``AS IS'' AND ANY * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RALF S. ENGELSCHALL OR * HIS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * ==================================================================== *//* ==================================================================== * Copyright (c) 1995-1999 Ben Laurie. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. All advertising materials mentioning features or use of this * software must display the following acknowledgment: * "This product includes software developed by Ben Laurie * for use in the Apache-SSL HTTP server project." * * 4. The name "Apache-SSL Server" must not be used to * endorse or promote products derived from this software without * prior written permission. * * 5. Redistributions of any form whatsoever must retain the following * acknowledgment: * "This product includes software developed by Ben Laurie * for use in the Apache-SSL HTTP server project." * * THIS SOFTWARE IS PROVIDED BY BEN LAURIE ``AS IS'' AND ANY * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BEN LAURIE OR * HIS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * ==================================================================== */ /* ``It took me fifteen years to discover I had no talent for programming, but I couldn't give it up because by that time I was too famous.'' -- Unknown */#include "mod_ssl.h"/* _________________________________________________________________**** SSL Engine Kernel** _________________________________________________________________*//* * Connect Handler: * Connect SSL to the accepted socket * * Usually we would need an Apache API hook which is triggered right after * the socket is accepted for handling a new request. But Apache 1.3 doesn't * provide such a hook, so we have to patch http_main.c and call this * function directly. */void ssl_hook_NewConnection(conn_rec *conn){ server_rec *srvr; BUFF *fb; SSLSrvConfigRec *sc; ap_ctx *apctx; SSL *ssl; char *cp; char *cpVHostID; char *cpVHostMD5; X509 *xs; int rc; /* * Get context */ srvr = conn->server; fb = conn->client; sc = mySrvConfig(srvr); /* * Create SSL context */ ap_ctx_set(fb->ctx, "ssl", NULL); /* * Immediately stop processing if SSL * is disabled for this connection */ if (sc == NULL || !sc->bEnabled) return; /* * Remember the connection information for * later access inside callback functions */ cpVHostID = ssl_util_vhostid(conn->pool, srvr); ssl_log(srvr, SSL_LOG_INFO, "Connection to child %d established " "(server %s, client %s)", conn->child_num, cpVHostID, conn->remote_ip != NULL ? conn->remote_ip : "unknown"); /* * Seed the Pseudo Random Number Generator (PRNG) */ ssl_rand_seed(srvr, conn->pool, SSL_RSCTX_CONNECT, ""); /* * Create a new SSL connection with the configured server SSL context and * attach this to the socket. Additionally we register this attachment * so we can detach later. */ if ((ssl = SSL_new(sc->pSSLCtx)) == NULL) { ssl_log(conn->server, SSL_LOG_ERROR|SSL_ADD_SSLERR, "Unable to create a new SSL connection from the SSL context"); ap_ctx_set(fb->ctx, "ssl", NULL); ap_bsetflag(fb, B_EOF|B_EOUT, 1); conn->aborted = 1; return; } SSL_clear(ssl); cpVHostMD5 = ap_md5(conn->pool, (unsigned char *)cpVHostID); if (!SSL_set_session_id_context(ssl, (unsigned char *)cpVHostMD5, strlen(cpVHostMD5))) { ssl_log(conn->server, SSL_LOG_ERROR|SSL_ADD_SSLERR, "Unable to set session id context to `%s'", cpVHostMD5); ap_ctx_set(fb->ctx, "ssl", NULL); ap_bsetflag(fb, B_EOF|B_EOUT, 1); conn->aborted = 1; return; } SSL_set_app_data(ssl, conn); apctx = ap_ctx_new(conn->pool); ap_ctx_set(apctx, "ssl::request_rec", NULL); ap_ctx_set(apctx, "ssl::verify::depth", AP_CTX_NUM2PTR(0)); SSL_set_app_data2(ssl, apctx); SSL_set_fd(ssl, fb->fd); ap_ctx_set(fb->ctx, "ssl", ssl); /* * Configure callbacks for SSL connection */ SSL_set_tmp_rsa_callback(ssl, ssl_callback_TmpRSA); SSL_set_tmp_dh_callback(ssl, ssl_callback_TmpDH); if (sc->nLogLevel >= SSL_LOG_DEBUG) { BIO_set_callback(SSL_get_rbio(ssl), ssl_io_data_cb); BIO_set_callback_arg(SSL_get_rbio(ssl), (void *)ssl); } /* * Predefine some client verification results */ ap_ctx_set(fb->ctx, "ssl::client::dn", NULL); ap_ctx_set(fb->ctx, "ssl::verify::error", NULL); ap_ctx_set(fb->ctx, "ssl::verify::info", NULL); SSL_set_verify_result(ssl, X509_V_OK); /* * We have to manage a I/O timeout ourself, because Apache * does it the first time when reading the request, but we're * working some time before this happens. */ ap_ctx_set(ap_global_ctx, "ssl::handshake::timeout", (void *)FALSE); ap_set_callback_and_alarm(ssl_hook_TimeoutConnection, srvr->timeout); /* * Now enter the SSL Handshake Phase */ while (!SSL_is_init_finished(ssl)) { if ((rc = SSL_accept(ssl)) <= 0) { if (SSL_get_error(ssl, rc) == SSL_ERROR_ZERO_RETURN) { /* * The case where the connection was closed before any data * was transferred. That's not a real error and can occur * sporadically with some clients. */ ssl_log(srvr, SSL_LOG_INFO, "SSL handshake stopped: connection was closed"); SSL_set_shutdown(ssl, SSL_RECEIVED_SHUTDOWN); SSL_smart_shutdown(ssl); SSL_free(ssl); ap_ctx_set(fb->ctx, "ssl", NULL); ap_bsetflag(fb, B_EOF|B_EOUT, 1); conn->aborted = 1; ap_set_callback_and_alarm(NULL, 0); ap_ctx_set(ap_global_ctx, "ssl::handshake::timeout", (void *)FALSE); return; } else if ((ERR_GET_REASON(ERR_peek_error()) == SSL_R_HTTP_REQUEST) && (ERR_GET_LIB(ERR_peek_error()) == ERR_LIB_SSL)) { /* * The case where OpenSSL has recognized a HTTP request: * This means the client speaks plain HTTP on our HTTPS * port. Hmmmm... At least for this error we can be more friendly * and try to provide him with a HTML error page. We have only one * problem: OpenSSL has already read some bytes from the HTTP * request. So we have to skip the request line manually and * instead provide a faked one in order to continue the internal * Apache processing. * */ char ca[2]; int rv; /* log the situation */ ssl_log(srvr, SSL_LOG_ERROR|SSL_ADD_SSLERR, "SSL handshake failed: HTTP spoken on HTTPS port; " "trying to send HTML error page"); /* first: skip the remaining bytes of the request line */ do { do { rv = read(fb->fd, ca, 1); } while (rv == -1 && errno == EINTR); } while (rv > 0 && ca[0] != '\012' /*LF*/); /* second: fake the request line */ fb->inbase = ap_palloc(fb->pool, fb->bufsiz); ap_cpystrn((char *)fb->inbase, "GET /mod_ssl:error:HTTP-request HTTP/1.0\r\n", fb->bufsiz); fb->inptr = fb->inbase; fb->incnt = strlen((char *)fb->inptr); /* third: kick away the SSL stuff */ SSL_set_shutdown(ssl, SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN); SSL_smart_shutdown(ssl); SSL_free(ssl); ap_ctx_set(fb->ctx, "ssl", NULL); ap_set_callback_and_alarm(NULL, 0); ap_ctx_set(ap_global_ctx, "ssl::handshake::timeout", (void *)FALSE); /* finally: let Apache go on with processing */ return; } else if (ap_ctx_get(ap_global_ctx, "ssl::handshake::timeout") == (void *)TRUE) { ssl_log(srvr, SSL_LOG_ERROR, "SSL handshake timed out (client %s, server %s)", conn->remote_ip != NULL ? conn->remote_ip : "unknown", cpVHostID); SSL_set_shutdown(ssl, SSL_RECEIVED_SHUTDOWN); SSL_smart_shutdown(ssl); SSL_free(ssl); ap_ctx_set(fb->ctx, "ssl", NULL); ap_bsetflag(fb, B_EOF|B_EOUT, 1); conn->aborted = 1; ap_set_callback_and_alarm(NULL, 0); ap_ctx_set(ap_global_ctx, "ssl::handshake::timeout", (void *)FALSE); return; } else if (SSL_get_error(ssl, rc) == SSL_ERROR_SYSCALL) { if (errno == EINTR) continue; if (errno > 0) ssl_log(srvr, SSL_LOG_ERROR|SSL_ADD_SSLERR|SSL_ADD_ERRNO, "SSL handshake interrupted by system " "[Hint: Stop button pressed in browser?!]"); else ssl_log(srvr, SSL_LOG_INFO|SSL_ADD_SSLERR|SSL_ADD_ERRNO, "Spurious SSL handshake interrupt" "[Hint: Usually just one of those OpenSSL confusions!?]"); SSL_set_shutdown(ssl, SSL_RECEIVED_SHUTDOWN); SSL_smart_shutdown(ssl); SSL_free(ssl); ap_ctx_set(fb->ctx, "ssl", NULL); ap_bsetflag(fb, B_EOF|B_EOUT, 1); conn->aborted = 1; ap_set_callback_and_alarm(NULL, 0); ap_ctx_set(ap_global_ctx, "ssl::handshake::timeout", (void *)FALSE); return; } else if ( (SSL_get_error(ssl, rc) == SSL_ERROR_WANT_READ && BIO_should_retry(SSL_get_rbio(ssl))) || (SSL_get_error(ssl, rc) == SSL_ERROR_WANT_WRITE && BIO_should_retry(SSL_get_wbio(ssl)))) { ssl_log(srvr, SSL_LOG_TRACE, "SSL handshake I/O retry (server %s, client %s)", cpVHostID, conn->remote_ip != NULL ? conn->remote_ip : "unknown"); continue; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -