summaryrefslogtreecommitdiff
path: root/modules/ssl/ssl_engine_io.c
diff options
context:
space:
mode:
Diffstat (limited to 'modules/ssl/ssl_engine_io.c')
-rw-r--r--modules/ssl/ssl_engine_io.c55
1 files changed, 39 insertions, 16 deletions
diff --git a/modules/ssl/ssl_engine_io.c b/modules/ssl/ssl_engine_io.c
index 424f4e5e..77c48482 100644
--- a/modules/ssl/ssl_engine_io.c
+++ b/modules/ssl/ssl_engine_io.c
@@ -29,8 +29,13 @@
-- Unknown */
#include "ssl_private.h"
#include "mod_ssl.h"
+#include "mod_ssl_openssl.h"
#include "apr_date.h"
+APR_IMPLEMENT_OPTIONAL_HOOK_RUN_ALL(ssl, SSL, int, proxy_post_handshake,
+ (conn_rec *c,SSL *ssl),
+ (c,ssl),OK,DECLINED);
+
/* _________________________________________________________________
**
** I/O Hooks
@@ -217,7 +222,7 @@ static int bio_filter_out_write(BIO *bio, const char *in, int inl)
* so limit the performance impact to handshake time.
*/
#if OPENSSL_VERSION_NUMBER < 0x0009080df
- need_flush = !SSL_is_init_finished(outctx->filter_ctx->pssl)
+ need_flush = !SSL_is_init_finished(outctx->filter_ctx->pssl);
#else
need_flush = SSL_in_connect_init(outctx->filter_ctx->pssl);
#endif
@@ -489,6 +494,12 @@ static int bio_filter_in_read(BIO *bio, char *in, int inlen)
return -1;
}
+ if (block == APR_BLOCK_READ
+ && APR_STATUS_IS_TIMEUP(inctx->rc)
+ && APR_BRIGADE_EMPTY(inctx->bb)) {
+ /* don't give up, just return the timeout */
+ return -1;
+ }
if (inctx->rc != APR_SUCCESS) {
/* Unexpected errors discard the brigade */
apr_brigade_cleanup(inctx->bb);
@@ -670,6 +681,10 @@ static apr_status_t ssl_io_input_read(bio_filter_in_ctx_t *inctx,
}
continue; /* Blocking and nothing yet? Try again. */
}
+ else if (APR_STATUS_IS_TIMEUP(inctx->rc)) {
+ /* just return it, the calling layer might be fine with it,
+ and we do not want to bloat the log. */
+ }
else {
ap_log_cerror(APLOG_MARK, APLOG_INFO, inctx->rc, c, APLOGNO(01991)
"SSL input filter read failed.");
@@ -1009,6 +1024,8 @@ static void ssl_filter_io_shutdown(ssl_filter_ctx_t *filter_ctx,
/* and finally log the fact that we've closed the connection */
if (APLOG_CS_IS_LEVEL(c, mySrvFromConn(c), loglevel)) {
+ /* Intentional no APLOGNO */
+ /* logno provides APLOGNO */
ap_log_cserror(APLOG_MARK, loglevel, 0, c, mySrvFromConn(c),
"%sConnection closed to child %ld with %s shutdown "
"(server %s)",
@@ -1079,6 +1096,8 @@ static apr_status_t ssl_io_filter_handshake(ssl_filter_ctx_t *filter_ctx)
const char *hostname_note = apr_table_get(c->notes,
"proxy-request-hostname");
BOOL proxy_ssl_check_peer_ok = TRUE;
+ int post_handshake_rc = OK;
+
sc = mySrvConfig(server);
#ifdef HAVE_TLSEXT
@@ -1170,11 +1189,17 @@ static apr_status_t ssl_io_filter_handshake(ssl_filter_ctx_t *filter_ctx)
}
}
+ if (proxy_ssl_check_peer_ok == TRUE) {
+ /* another chance to fail */
+ post_handshake_rc = ssl_run_proxy_post_handshake(c, filter_ctx->pssl);
+ }
+
if (cert) {
X509_free(cert);
}
- if (proxy_ssl_check_peer_ok != TRUE) {
+ if (proxy_ssl_check_peer_ok != TRUE
+ || (post_handshake_rc != OK && post_handshake_rc != DECLINED)) {
/* ensure that the SSL structures etc are freed, etc: */
ssl_filter_io_shutdown(filter_ctx, c, 1);
apr_table_setn(c->notes, "SSL_connect_rv", "err");
@@ -1326,19 +1351,19 @@ static apr_status_t ssl_io_filter_input(ap_filter_t *f,
const char *start = inctx->buffer; /* start of block to return */
apr_size_t len = sizeof(inctx->buffer); /* length of block to return */
int is_init = (mode == AP_MODE_INIT);
+ apr_bucket *bucket;
if (f->c->aborted) {
/* XXX: Ok, if we aborted, we ARE at the EOS. We also have
* aborted. This 'double protection' is probably redundant,
* but also effective against just about anything.
*/
- apr_bucket *bucket = apr_bucket_eos_create(f->c->bucket_alloc);
+ bucket = apr_bucket_eos_create(f->c->bucket_alloc);
APR_BRIGADE_INSERT_TAIL(bb, bucket);
return APR_ECONNABORTED;
}
if (!inctx->ssl) {
- apr_bucket *bucket;
SSLConnRec *sslconn = myConnConfig(f->c);
if (sslconn->non_ssl_request == NON_SSL_SEND_REQLINE) {
bucket = HTTP_ON_HTTPS_PORT_BUCKET(f->c->bucket_alloc);
@@ -1433,7 +1458,7 @@ static apr_status_t ssl_io_filter_input(ap_filter_t *f,
/* Create a transient bucket out of the decrypted data. */
if (len > 0) {
- apr_bucket *bucket =
+ bucket =
apr_bucket_transient_create(start, len, f->c->bucket_alloc);
APR_BRIGADE_INSERT_TAIL(bb, bucket);
}
@@ -1463,7 +1488,7 @@ struct coalesce_ctx {
static apr_status_t ssl_io_filter_coalesce(ap_filter_t *f,
apr_bucket_brigade *bb)
{
- apr_bucket *e, *last = NULL;
+ apr_bucket *e, *upto;
apr_size_t bytes = 0;
struct coalesce_ctx *ctx = f->ctx;
unsigned count = 0;
@@ -1490,19 +1515,20 @@ static apr_status_t ssl_io_filter_coalesce(ap_filter_t *f,
&& (ctx == NULL
|| bytes + ctx->bytes + e->length < COALESCE_BYTES);
e = APR_BUCKET_NEXT(e)) {
- last = e;
if (e->length) count++; /* don't count zero-length buckets */
bytes += e->length;
}
+ upto = e;
/* Coalesce the prefix, if:
* a) more than one bucket is found to coalesce, or
* b) the brigade contains only a single data bucket, or
- * c)
+ * c) the data bucket is not last but we have buffered data already.
*/
if (bytes > 0
&& (count > 1
- || (count == 1 && APR_BUCKET_NEXT(last) == APR_BRIGADE_SENTINEL(bb)))) {
+ || (upto == APR_BRIGADE_SENTINEL(bb))
+ || (ctx && ctx->bytes > 0))) {
/* If coalescing some bytes, ensure a context has been
* created. */
if (!ctx) {
@@ -1519,7 +1545,7 @@ static apr_status_t ssl_io_filter_coalesce(ap_filter_t *f,
* normal path of sending the buffer + remaining buckets in
* brigade. */
e = APR_BRIGADE_FIRST(bb);
- while (e != last) {
+ while (e != upto) {
apr_size_t len;
const char *data;
apr_bucket *next;
@@ -1571,8 +1597,6 @@ static apr_status_t ssl_io_filter_coalesce(ap_filter_t *f,
* the filter stack, first prepending anything that has been
* coalesced. */
if (ctx && ctx->bytes) {
- apr_bucket *e;
-
ap_log_cerror(APLOG_MARK, APLOG_TRACE4, 0, f->c,
"coalesce: passing on %" APR_SIZE_T_FMT " bytes", ctx->bytes);
@@ -1789,6 +1813,7 @@ static apr_status_t ssl_io_filter_buffer(ap_filter_t *f,
{
struct modssl_buffer_ctx *ctx = f->ctx;
apr_status_t rv;
+ apr_bucket *e, *d;
ap_log_cerror(APLOG_MARK, APLOG_TRACE4, 0, f->c,
"read from buffered SSL brigade, mode %d, "
@@ -1813,8 +1838,6 @@ static apr_status_t ssl_io_filter_buffer(ap_filter_t *f,
}
if (mode == AP_MODE_READBYTES) {
- apr_bucket *e;
-
/* Partition the buffered brigade. */
rv = apr_brigade_partition(ctx->bb, bytes, &e);
if (rv && rv != APR_INCOMPLETE) {
@@ -1829,7 +1852,7 @@ static apr_status_t ssl_io_filter_buffer(ap_filter_t *f,
if (rv == APR_INCOMPLETE) {
APR_BRIGADE_CONCAT(bb, ctx->bb);
} else {
- apr_bucket *d = APR_BRIGADE_FIRST(ctx->bb);
+ d = APR_BRIGADE_FIRST(ctx->bb);
e = APR_BUCKET_PREV(e);
@@ -1856,7 +1879,7 @@ static apr_status_t ssl_io_filter_buffer(ap_filter_t *f,
}
if (APR_BRIGADE_EMPTY(ctx->bb)) {
- apr_bucket *e = APR_BRIGADE_LAST(bb);
+ e = APR_BRIGADE_LAST(bb);
/* Ensure that the brigade is terminated by an EOS if the
* buffered request body has been entirely consumed. */