Index: modules/ssl/ssl_engine_io.c =================================================================== --- modules/ssl/ssl_engine_io.c (revision 1878367) +++ modules/ssl/ssl_engine_io.c (working copy) @@ -606,6 +606,13 @@ void free_bio_methods(void) } #endif +/* Forward declare */ +static apr_status_t ssl_io_filter_handshake(ssl_filter_ctx_t *filter_ctx); +static apr_status_t ssl_io_filter_error(bio_filter_in_ctx_t *inctx, + apr_bucket_brigade *bb, + apr_status_t status, + int is_init); + static apr_status_t ssl_io_input_read(bio_filter_in_ctx_t *inctx, char *buf, apr_size_t *len) @@ -612,6 +619,7 @@ static apr_status_t ssl_io_input_read(bio_filter_i { apr_size_t wanted = *len; apr_size_t bytes = 0; + apr_status_t status; int rc; *len = 0; @@ -635,18 +643,17 @@ static apr_status_t ssl_io_input_read(bio_filter_i if (*len >= wanted) { return APR_SUCCESS; } - if (inctx->mode == AP_MODE_GETLINE) { - if (memchr(buf, APR_ASCII_LF, *len)) { - return APR_SUCCESS; - } - } - else { - /* Down to a nonblock pattern as we have some data already - */ - inctx->block = APR_NONBLOCK_READ; - } } + if ((status = ssl_io_filter_handshake(inctx->filter_ctx))) { + return status; + } + + if (bytes && inctx->mode != AP_MODE_GETLINE) { + /* Down to a nonblock pattern as we have some data already */ + inctx->block = APR_NONBLOCK_READ; + } + while (1) { if (!inctx->filter_ctx->pssl) { @@ -779,7 +786,7 @@ static apr_status_t ssl_io_input_read(bio_filter_i * length *LEN; updating *len to reflect the length of the line * including the LF character. */ static apr_status_t ssl_io_input_getline(bio_filter_in_ctx_t *inctx, - char *buf, + char **buf, apr_size_t *len) { const char *pos = NULL; @@ -786,6 +793,18 @@ static apr_status_t ssl_io_input_getline(bio_filte apr_status_t status; apr_size_t tmplen = *len, buflen = *len, offset = 0; + /* Satisfy the read directly out of the buffer if possible */ + if (inctx->cbuf.length + && (pos = memchr(inctx->cbuf.value, APR_ASCII_LF, + inctx->cbuf.length)) != NULL) { + *buf = inctx->cbuf.value; + *len = pos - inctx->cbuf.value + 1; /* +1 to include LF */ + /* Buffer contents now consumed. */ + inctx->cbuf.value += *len; + inctx->cbuf.length -= *len; + return APR_SUCCESS; + } + *len = 0; /* @@ -795,12 +814,12 @@ static apr_status_t ssl_io_input_getline(bio_filte */ while (tmplen > 0) { - status = ssl_io_input_read(inctx, buf + offset, &tmplen); + status = ssl_io_input_read(inctx, *buf + offset, &tmplen); if (status != APR_SUCCESS) { if (APR_STATUS_IS_EAGAIN(status) && (*len > 0)) { /* Save the part of the line we already got */ - char_buffer_write(&inctx->cbuf, buf, *len); + char_buffer_write(&inctx->cbuf, *buf, *len); } return status; } @@ -807,7 +826,7 @@ static apr_status_t ssl_io_input_getline(bio_filte *len += tmplen; - if ((pos = memchr(buf, APR_ASCII_LF, *len))) { + if ((pos = memchr(*buf, APR_ASCII_LF, *len))) { break; } @@ -818,10 +837,10 @@ static apr_status_t ssl_io_input_getline(bio_filte if (pos) { char *value; int length; - apr_size_t bytes = pos - buf; + apr_size_t bytes = pos - *buf; bytes += 1; - value = buf + bytes; + value = *buf + bytes; length = *len - bytes; char_buffer_write(&inctx->cbuf, value, length); @@ -1157,7 +1176,10 @@ static apr_status_t ssl_io_filter_handshake(ssl_fi long verify_result; server_rec *server; - if (SSL_is_init_finished(filter_ctx->pssl)) { + if (SSL_is_init_finished(filter_ctx->pssl) + || (sslconn->is_proxy + /* let SSL_read/write handle proxy renegotiations */ + && SSL_total_renegotiations(filter_ctx->pssl)) != 0) { return APR_SUCCESS; } @@ -1466,7 +1488,7 @@ static apr_status_t ssl_io_filter_input(ap_filter_ { apr_status_t status; bio_filter_in_ctx_t *inctx = f->ctx; - const char *start = inctx->buffer; /* start of block to return */ + 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; @@ -1511,20 +1533,19 @@ static apr_status_t ssl_io_filter_input(ap_filter_ inctx->mode = mode; inctx->block = block; - /* XXX: we could actually move ssl_io_filter_handshake to an - * ap_hook_process_connection but would still need to call it for - * AP_MODE_INIT for protocols that may upgrade the connection - * rather than have SSLEngine On configured. - */ - if ((status = ssl_io_filter_handshake(inctx->filter_ctx)) != APR_SUCCESS) { - return ssl_io_filter_error(inctx, bb, status, is_init); - } - if (is_init) { /* protocol module needs to handshake before sending * data to client (e.g. NNTP or FTP) */ - return APR_SUCCESS; + /* XXX: we could actually move ssl_io_filter_handshake to an + * ap_hook_process_connection but would still need to call it for + * AP_MODE_INIT for protocols that may upgrade the connection + * rather than have SSLEngine On configured. + */ + if ((status = ssl_io_filter_handshake(inctx->filter_ctx))) { + status = ssl_io_filter_error(inctx, bb, status, 1); + } + return status; } if (inctx->mode == AP_MODE_READBYTES || @@ -1537,25 +1558,7 @@ static apr_status_t ssl_io_filter_input(ap_filter_ status = ssl_io_input_read(inctx, inctx->buffer, &len); } else if (inctx->mode == AP_MODE_GETLINE) { - const char *pos; - - /* Satisfy the read directly out of the buffer if possible; - * invoking ssl_io_input_getline will mean the entire buffer - * is copied once (unnecessarily) for each GETLINE call. */ - if (inctx->cbuf.length - && (pos = memchr(inctx->cbuf.value, APR_ASCII_LF, - inctx->cbuf.length)) != NULL) { - start = inctx->cbuf.value; - len = 1 + pos - start; /* +1 to include LF */ - /* Buffer contents now consumed. */ - inctx->cbuf.value += len; - inctx->cbuf.length -= len; - status = APR_SUCCESS; - } - else { - /* Otherwise fall back to the hard way. */ - status = ssl_io_input_getline(inctx, inctx->buffer, &len); - } + status = ssl_io_input_getline(inctx, &start, &len); } else { /* We have no idea what you are talking about, so return an error. */ Index: modules/ssl/ssl_engine_kernel.c =================================================================== --- modules/ssl/ssl_engine_kernel.c (revision 1878367) +++ modules/ssl/ssl_engine_kernel.c (working copy) @@ -2175,37 +2175,38 @@ void ssl_callback_DelSessionCacheEntry(SSL_CTX *ct static void log_tracing_state(const SSL *ssl, conn_rec *c, server_rec *s, int where, int rc) { + const char *prefix; + if (where & SSL_ST_ACCEPT) { + prefix = MODSSL_LIBRARY_NAME ": Server"; + } + else if (where & SSL_ST_CONNECT) { + prefix = MODSSL_LIBRARY_NAME ": Client"; + } + else { + prefix = MODSSL_LIBRARY_NAME; + } + /* * create the various trace messages */ if (where & SSL_CB_HANDSHAKE_START) { ap_log_cerror(APLOG_MARK, APLOG_TRACE3, 0, c, - "%s: Handshake: start", MODSSL_LIBRARY_NAME); + "%s: Handshake: start", prefix); } else if (where & SSL_CB_HANDSHAKE_DONE) { ap_log_cerror(APLOG_MARK, APLOG_TRACE3, 0, c, - "%s: Handshake: done", MODSSL_LIBRARY_NAME); + "%s: Handshake: done", prefix); } else if (where & SSL_CB_LOOP) { ap_log_cerror(APLOG_MARK, APLOG_TRACE3, 0, c, "%s: Loop: %s", - MODSSL_LIBRARY_NAME, SSL_state_string_long(ssl)); + prefix, SSL_state_string_long(ssl)); } - else if (where & SSL_CB_READ) { - ap_log_cerror(APLOG_MARK, APLOG_TRACE3, 0, c, - "%s: Read: %s", - MODSSL_LIBRARY_NAME, SSL_state_string_long(ssl)); - } - else if (where & SSL_CB_WRITE) { - ap_log_cerror(APLOG_MARK, APLOG_TRACE3, 0, c, - "%s: Write: %s", - MODSSL_LIBRARY_NAME, SSL_state_string_long(ssl)); - } else if (where & SSL_CB_ALERT) { char *str = (where & SSL_CB_READ) ? "read" : "write"; ap_log_cerror(APLOG_MARK, APLOG_TRACE3, 0, c, "%s: Alert: %s:%s:%s", - MODSSL_LIBRARY_NAME, str, + prefix, str, SSL_alert_type_string_long(rc), SSL_alert_desc_string_long(rc)); } @@ -2213,12 +2214,12 @@ static void log_tracing_state(const SSL *ssl, conn if (rc == 0) { ap_log_cerror(APLOG_MARK, APLOG_TRACE3, 0, c, "%s: Exit: failed in %s", - MODSSL_LIBRARY_NAME, SSL_state_string_long(ssl)); + prefix, SSL_state_string_long(ssl)); } else if (rc < 0) { ap_log_cerror(APLOG_MARK, APLOG_TRACE3, 0, c, "%s: Exit: error in %s", - MODSSL_LIBRARY_NAME, SSL_state_string_long(ssl)); + prefix, SSL_state_string_long(ssl)); } } @@ -2279,10 +2280,16 @@ void ssl_callback_Info(const SSL *ssl, int where, "rejecting client initiated renegotiation"); } /* If the first handshake is complete, change state to reject any - * subsequent client-initiated renegotiation. */ + * subsequent client-initiated renegotiation, but allow potential + * backend-initiated proxy renegotiations still. */ else if ((where & SSL_CB_HANDSHAKE_DONE) && sslconn->reneg_state == RENEG_INIT) { - sslconn->reneg_state = RENEG_REJECT; + if (sslconn->is_proxy) { + sslconn->reneg_state = RENEG_ALLOW; + } + else { + sslconn->reneg_state = RENEG_REJECT; + } } }