summaryrefslogtreecommitdiffstats
path: root/modules/ssl/ssl_engine_io.c
diff options
context:
space:
mode:
authorRainer Jung <rjung@apache.org>2018-10-15 23:14:21 +0200
committerRainer Jung <rjung@apache.org>2018-10-15 23:14:21 +0200
commit5bfbbcf9a23c01f2a6219d00121bcf89cfba1252 (patch)
treea7ffebb2ed3fd86cdce3ec2510c938a2afb8a687 /modules/ssl/ssl_engine_io.c
parent* Ensure that aborted connections are logged as such. (diff)
downloadapache2-5bfbbcf9a23c01f2a6219d00121bcf89cfba1252.tar.xz
apache2-5bfbbcf9a23c01f2a6219d00121bcf89cfba1252.zip
SSL_read() doesn't distinguish between return value 0 and <0,
at least not for OpenSSL 1.1.1. This is documented in the man page for SSL_read and let to h2 failures when using OpenSSL 1.1.1. When no data could be read, our code returned EAGAIN up until OpenSSL 1.1.0, but APR_EOF for OpenSSL 1.1.1. Now instead check SSL_get_error() also when SSL_read() returns 0. To keep changes small, this change should not influence behavior, when (rc=SSL_read()): - rc < 0 - rc == 0 && *len > 0 - rc == 0 && (APR_STATUS_IS_EAGAIN(inctx->rc) || APR_STATUS_IS_EINTR(inctx->rc) && inctx->block == APR_NONBLOCK_READ Behavior changes if - rc == 0 && !(APR_STATUS_IS_EAGAIN(inctx->rc) || APR_STATUS_IS_EINTR(inctx->rc) && !*len > 0 Instead of APR_EOF: - same behavior as rc < 0 for SSL_ERROR_WANT_READ - same behavior as rc < 0 for SSL_ERROR_SYSCALL && APR_STATUS_IS_EAGAIN(inctx->rc) Another change is that rc == 0 && ssl_err == SSL_ERROR_ZERO_RETURN also results in APR_EOF. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1843954 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to '')
-rw-r--r--modules/ssl/ssl_engine_io.c59
1 files changed, 33 insertions, 26 deletions
diff --git a/modules/ssl/ssl_engine_io.c b/modules/ssl/ssl_engine_io.c
index 204b7f5481..5f7d10457a 100644
--- a/modules/ssl/ssl_engine_io.c
+++ b/modules/ssl/ssl_engine_io.c
@@ -715,37 +715,36 @@ static apr_status_t ssl_io_input_read(bio_filter_in_ctx_t *inctx,
}
return inctx->rc;
}
- else if (rc == 0) {
- /* If EAGAIN, we will loop given a blocking read,
- * otherwise consider ourselves at EOF.
- */
- if (APR_STATUS_IS_EAGAIN(inctx->rc)
- || APR_STATUS_IS_EINTR(inctx->rc)) {
- /* Already read something, return APR_SUCCESS instead.
- * On win32 in particular, but perhaps on other kernels,
- * a blocking call isn't 'always' blocking.
+ else /* (rc <= 0) */ {
+ int ssl_err;
+ conn_rec *c;
+ if (rc == 0) {
+ /* If EAGAIN, we will loop given a blocking read,
+ * otherwise consider ourselves at EOF.
*/
- if (*len > 0) {
- inctx->rc = APR_SUCCESS;
- break;
- }
- if (inctx->block == APR_NONBLOCK_READ) {
- break;
- }
- }
- else {
- if (*len > 0) {
- inctx->rc = APR_SUCCESS;
+ if (APR_STATUS_IS_EAGAIN(inctx->rc)
+ || APR_STATUS_IS_EINTR(inctx->rc)) {
+ /* Already read something, return APR_SUCCESS instead.
+ * On win32 in particular, but perhaps on other kernels,
+ * a blocking call isn't 'always' blocking.
+ */
+ if (*len > 0) {
+ inctx->rc = APR_SUCCESS;
+ break;
+ }
+ if (inctx->block == APR_NONBLOCK_READ) {
+ break;
+ }
}
else {
- inctx->rc = APR_EOF;
+ if (*len > 0) {
+ inctx->rc = APR_SUCCESS;
+ break;
+ }
}
- break;
}
- }
- else /* (rc < 0) */ {
- int ssl_err = SSL_get_error(inctx->filter_ctx->pssl, rc);
- conn_rec *c = (conn_rec*)SSL_get_app_data(inctx->filter_ctx->pssl);
+ ssl_err = SSL_get_error(inctx->filter_ctx->pssl, rc);
+ c = (conn_rec*)SSL_get_app_data(inctx->filter_ctx->pssl);
if (ssl_err == SSL_ERROR_WANT_READ) {
/*
@@ -789,6 +788,10 @@ static apr_status_t ssl_io_input_read(bio_filter_in_ctx_t *inctx,
"SSL input filter read failed.");
}
}
+ else if (rc == 0 && ssl_err == SSL_ERROR_ZERO_RETURN) {
+ inctx->rc = APR_EOF;
+ break;
+ }
else /* if (ssl_err == SSL_ERROR_SSL) */ {
/*
* Log SSL errors and any unexpected conditions.
@@ -798,6 +801,10 @@ static apr_status_t ssl_io_input_read(bio_filter_in_ctx_t *inctx,
ssl_log_ssl_error(SSLLOG_MARK, APLOG_INFO, mySrvFromConn(c));
}
+ if (rc == 0) {
+ inctx->rc = APR_EOF;
+ break;
+ }
if (inctx->rc == APR_SUCCESS) {
inctx->rc = APR_EGENERAL;
}