mirror of
https://github.com/apache/httpd.git
synced 2025-08-07 04:02:58 +03:00
remove #if 0-ed ssl_hook_NewConnection code; was only left for reference,
no longer needed remove #if 0-ed ssl_hook_TimeoutConnection code; ssl no longer talks directly to the socket PR: Obtained from: Submitted by: madhu Reviewed by: dougm git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@90511 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
@@ -63,318 +63,6 @@
|
||||
-- Unknown */
|
||||
#include "mod_ssl.h"
|
||||
|
||||
#if 0 /* XXX */
|
||||
|
||||
/* _________________________________________________________________
|
||||
**
|
||||
** 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), 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;
|
||||
return;
|
||||
}
|
||||
else if (ERR_GET_REASON(ERR_peek_error()) == SSL_R_HTTP_REQUEST) {
|
||||
/*
|
||||
* 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);
|
||||
|
||||
/* 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;
|
||||
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;
|
||||
return;
|
||||
}
|
||||
else {
|
||||
/*
|
||||
* Ok, anything else is a fatal error
|
||||
*/
|
||||
ssl_log(srvr, SSL_LOG_ERROR|SSL_ADD_SSLERR|SSL_ADD_ERRNO,
|
||||
"SSL handshake failed (server %s, client %s)", cpVHostID,
|
||||
conn->remote_ip != NULL ? conn->remote_ip : "unknown");
|
||||
|
||||
/*
|
||||
* try to gracefully shutdown the connection:
|
||||
* - send an own shutdown message (be gracefully)
|
||||
* - don't wait for peer's shutdown message (deadloop)
|
||||
* - kick away the SSL stuff immediately
|
||||
* - block the socket, so Apache cannot operate any more
|
||||
*/
|
||||
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;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Check for failed client authentication
|
||||
*/
|
||||
if ( SSL_get_verify_result(ssl) != X509_V_OK
|
||||
|| ap_ctx_get(fb->ctx, "ssl::verify::error") != NULL) {
|
||||
cp = (char *)ap_ctx_get(fb->ctx, "ssl::verify::error");
|
||||
ssl_log(srvr, SSL_LOG_ERROR|SSL_ADD_SSLERR,
|
||||
"SSL client authentication failed: %s",
|
||||
cp != NULL ? cp : "unknown reason");
|
||||
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;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Remember the peer certificate's DN
|
||||
*/
|
||||
if ((xs = SSL_get_peer_certificate(ssl)) != NULL) {
|
||||
cp = X509_NAME_oneline(X509_get_subject_name(xs), NULL, 0);
|
||||
ap_ctx_set(fb->ctx, "ssl::client::dn", ap_pstrdup(conn->pool, cp));
|
||||
free(cp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Make really sure that when a peer certificate
|
||||
* is required we really got one... (be paranoid)
|
||||
*/
|
||||
if ( sc->nVerifyClient == SSL_CVERIFY_REQUIRE
|
||||
&& ap_ctx_get(fb->ctx, "ssl::client::dn") == NULL) {
|
||||
ssl_log(srvr, SSL_LOG_ERROR,
|
||||
"No acceptable peer certificate available");
|
||||
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;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove the timeout handling
|
||||
*/
|
||||
ap_set_callback_and_alarm(NULL, 0);
|
||||
ap_ctx_set(ap_global_ctx, "ssl::handshake::timeout", (void *)FALSE);
|
||||
|
||||
/*
|
||||
* Improve I/O throughput by using
|
||||
* OpenSSL's read-ahead functionality
|
||||
*/
|
||||
SSL_set_read_ahead(ssl, TRUE);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Signal handler function for the SSL handshake phase
|
||||
*/
|
||||
void ssl_hook_TimeoutConnection(int sig)
|
||||
{
|
||||
/* we just set a flag for the handshake processing loop */
|
||||
ap_ctx_set(ap_global_ctx, "ssl::handshake::timeout", (void *)TRUE);
|
||||
return;
|
||||
}
|
||||
#endif /* XXX */
|
||||
|
||||
/*
|
||||
* Close the SSL part of the socket connection
|
||||
* (called immediately _before_ the socket is closed)
|
||||
|
Reference in New Issue
Block a user