ssl_engine_io.c revision b76a31daaa6e83bb0fd627a04f20e82bffcf1df4
842ae4bd224140319ae7feec1872b93dfd491143fielding/* Licensed to the Apache Software Foundation (ASF) under one or more
842ae4bd224140319ae7feec1872b93dfd491143fielding * contributor license agreements. See the NOTICE file distributed with
842ae4bd224140319ae7feec1872b93dfd491143fielding * this work for additional information regarding copyright ownership.
842ae4bd224140319ae7feec1872b93dfd491143fielding * The ASF licenses this file to You under the Apache License, Version 2.0
842ae4bd224140319ae7feec1872b93dfd491143fielding * (the "License"); you may not use this file except in compliance with
842ae4bd224140319ae7feec1872b93dfd491143fielding * the License. You may obtain a copy of the License at
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * Unless required by applicable law or agreed to in writing, software
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * distributed under the License is distributed on an "AS IS" BASIS,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * See the License for the specific language governing permissions and
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * limitations under the License.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * _ __ ___ ___ __| | ___ ___| | mod_ssl
e8f95a682820a599fe41b22977010636be5c2717jim * | '_ ` _ \ / _ \ / _` | / __/ __| | Apache Interface to OpenSSL
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * | | | | | | (_) | (_| | \__ \__ \ |
e8f95a682820a599fe41b22977010636be5c2717jim * |_| |_| |_|\___/ \__,_|___|___/___/_|
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * I/O Functions
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* ``MY HACK: This universe.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes Just one little problem:
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes core keeps dumping.''
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes -- Unknown */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes/* _________________________________________________________________
5c0419d51818eb02045cf923a9fe456127a44c60wrowe** I/O Hooks
5c0419d51818eb02045cf923a9fe456127a44c60wrowe** _________________________________________________________________
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes/* This file is designed to be the bridge between OpenSSL and httpd.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * However, we really don't expect anyone (let alone ourselves) to
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * remember what is in this file. So, first, a quick overview.
d266c3777146d36a4c23c17aad6f153aebea1bf4jorton * In this file, you will find:
d266c3777146d36a4c23c17aad6f153aebea1bf4jorton * - ssl_io_filter_input (Apache input filter)
22f8da8087791fcb95b836c8a81937c5a9bba202bnicholes * - ssl_io_filter_output (Apache output filter)
22f8da8087791fcb95b836c8a81937c5a9bba202bnicholes * - bio_filter_in_* (OpenSSL input filter)
22f8da8087791fcb95b836c8a81937c5a9bba202bnicholes * - bio_filter_out_* (OpenSSL output filter)
22f8da8087791fcb95b836c8a81937c5a9bba202bnicholes * The input chain is roughly:
cd3bbd6d2df78d6c75e5d159a81ef8bdd5f70df9trawick * ssl_io_filter_input->ssl_io_input_read->SSL_read->...
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * ...->bio_filter_in_read->ap_get_brigade/next-httpd-filter
0f60998368b493f90120180a93fc2e1e74490872covener * In mortal terminology, we do the following:
0f60998368b493f90120180a93fc2e1e74490872covener * - Receive a request for data to the SSL input filter
0f60998368b493f90120180a93fc2e1e74490872covener * - Call a helper function once we know we should perform a read
0f60998368b493f90120180a93fc2e1e74490872covener * - Call OpenSSL's SSL_read()
0f60998368b493f90120180a93fc2e1e74490872covener * - SSL_read() will then call bio_filter_in_read
0f60998368b493f90120180a93fc2e1e74490872covener * - bio_filter_in_read will then try to fetch data from the next httpd filter
0f60998368b493f90120180a93fc2e1e74490872covener * - bio_filter_in_read will flatten that data and return it to SSL_read
87587593f1a53030e840acc0dec6cc881022ea40covener * - SSL_read will then decrypt the data
87587593f1a53030e840acc0dec6cc881022ea40covener * - ssl_io_input_read will then receive decrypted data as a char* and
87587593f1a53030e840acc0dec6cc881022ea40covener * ensure that there were no read errors
87587593f1a53030e840acc0dec6cc881022ea40covener * - The char* is placed in a brigade and returned
43997561b2302d13dee973998e77743a3ddd2374trawick * Since connection-level input filters in httpd need to be able to
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * handle AP_MODE_GETLINE calls (namely identifying LF-terminated strings),
0568280364eb026393be492ebc732795c4934643jorton * ssl_io_input_getline which will handle this special case.
0568280364eb026393be492ebc732795c4934643jorton * Due to AP_MODE_GETLINE and AP_MODE_SPECULATIVE, we may sometimes have
0568280364eb026393be492ebc732795c4934643jorton * 'leftover' decoded data which must be setaside for the next read. That
0568280364eb026393be492ebc732795c4934643jorton * is currently handled by the char_buffer_{read|write} functions. So,
0568280364eb026393be492ebc732795c4934643jorton * ssl_io_input_read may be able to fulfill reads without invoking
0568280364eb026393be492ebc732795c4934643jorton * SSL_read().
0568280364eb026393be492ebc732795c4934643jorton * Note that the filter context of ssl_io_filter_input and bio_filter_in_*
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * are shared as bio_filter_in_ctx_t.
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener * Note that the filter is by choice limited to reading at most
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * AP_IOBUFSIZE (8192 bytes) per call.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes/* this custom BIO allows us to hook SSL_write directly into
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * an apr_bucket_brigade and use transient buckets with the SSL
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * malloc-ed buffer, rather than copying into a mem BIO.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * also allows us to pass the brigade as data is being written
796e4a7141265d8ed7036e4628161c6eafb2a789jorton * rather than buffering up the entire response in the mem BIO.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * when SSL needs to flush (e.g. SSL_accept()), it will call BIO_flush()
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * which will trigger a call to bio_filter_out_ctrl() -> bio_filter_out_flush().
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * so we only need to flush the output ourselves if we receive an
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * EOS or FLUSH bucket. this was not possible with the mem BIO where we
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * had to flush all over the place not really knowing when it was required
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholestypedef struct {
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowetypedef struct {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes apr_bucket_brigade *bb; /* Brigade used as a buffer. */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes apr_size_t length; /* Number of bytes stored in ->bb brigade. */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes char buffer[AP_IOBUFSIZE]; /* Fixed-size buffer */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes apr_size_t blen; /* Number of bytes of ->buffer used. */
a1790fb35c4b352dab721370985c623a9f8f5062rpluemstatic bio_filter_out_ctx_t *bio_filter_out_ctx_new(ssl_filter_ctx_t *filter_ctx,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes bio_filter_out_ctx_t *outctx = apr_palloc(c->pool, sizeof(*outctx));
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe outctx->bb = apr_brigade_create(c->pool, c->bucket_alloc);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes bio_filter_out_ctx_t *outctx = (bio_filter_out_ctx_t *)(bio->ptr);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes e = apr_bucket_transient_create(outctx->buffer, outctx->blen,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* we filled this buffer first so add it to the
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * head of the brigade
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes e = apr_bucket_flush_create(outctx->bb->bucket_alloc);
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener outctx->rc = ap_pass_brigade(outctx->filter_ctx->pOutputFilter->next,
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener /* Fail if the connection was reset: */
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener if (outctx->rc == APR_SUCCESS && outctx->c->aborted) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* nothing to free here.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * apache will destroy the bucket brigade for us
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstatic int bio_filter_out_read(BIO *bio, char *out, int outl)
1f299703465bd9975d94e9f229f76af807442de2covener /* this is never called */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstatic int bio_filter_out_write(BIO *bio, const char *in, int inl)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes bio_filter_out_ctx_t *outctx = (bio_filter_out_ctx_t *)(bio->ptr);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* Abort early if the client has initiated a renegotiation. */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (outctx->filter_ctx->config->reneg_state == RENEG_ABORT) {
f43b67c5a9d29b572eac916f8335cedc80c908bebnicholes /* when handshaking we'll have a small number of bytes.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * max size SSL will pass us here is about 16k.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * (16413 bytes to be exact)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (!outctx->length && (inl + outctx->blen < sizeof(outctx->buffer)) &&
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* the first two SSL_writes (of 1024 and 261 bytes)
3e6d7277b90d3011db832139afc20efb5f17e203rederpj * need to be in the same packet (vec[0].iov_base)
3e6d7277b90d3011db832139afc20efb5f17e203rederpj /* XXX: could use apr_brigade_write() to make code look cleaner
3e6d7277b90d3011db832139afc20efb5f17e203rederpj * but this way we avoid the malloc(APR_BUCKET_BUFF_SIZE)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * and free() of it later
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener /* pass along the encrypted data
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener * need to flush since we're using SSL's malloc-ed buffer
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener * which will be overwritten once we leave here
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener apr_bucket *bucket = apr_bucket_transient_create(in, inl,
6683642c1e0032eeeed5f99e8c14880692ef84c5sf return -1;
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovenerstatic long bio_filter_out_ctrl(BIO *bio, int cmd, long num, void *ptr)
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener bio_filter_out_ctx_t *outctx = (bio_filter_out_ctx_t *)(bio->ptr);
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener /* _PENDING is interpreted as "pending to read" - since this
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener * is a *write* buffer, return zero. */
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener /* _WPENDING is interpreted as "pending to write" - return the
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener * number of bytes in ->bb plus buffer. */
465bb68501690d7a47bfd2a6129580047d76d8f1rederpj /* we don't care */
ebe5305f8b22507374358f32b74d12fb50c05a25covenerstatic int bio_filter_out_gets(BIO *bio, char *buf, int size)
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes /* this is never called */
513b324e774c559b579896df131fd7c8471ed529rederpjstatic int bio_filter_out_puts(BIO *bio, const char *str)
513b324e774c559b579896df131fd7c8471ed529rederpj /* this is never called */
513b324e774c559b579896df131fd7c8471ed529rederpj "APR output filter",
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes NULL /* sslc does not have the callback_ctrl field */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholestypedef struct {
9ad7b260be233be7d7b5576979825cac72e15498rederpjtypedef struct {
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes * this char_buffer api might seem silly, but we don't need to copy
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes * any of this data and we need to remember the length.
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes/* Copy up to INL bytes from the char_buffer BUFFER into IN. Note
54d22ed1c429b903b029bbd62621f11a9e286137minfrin * that due to the strange way this API is designed/used, the
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes * char_buffer object is used to cache a segment of inctx->buffer, and
54d22ed1c429b903b029bbd62621f11a9e286137minfrin * then this function called to copy (part of) that segment to the
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes * beginning of inctx->buffer. So the segments to copy cannot be
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes * presumed to be non-overlapping, and memmove must be used. */
ebe5305f8b22507374358f32b74d12fb50c05a25covenerstatic int char_buffer_read(char_buffer_t *buffer, char *in, int inl)
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes /* we have have enough to fill the caller's buffer */
9ad7b260be233be7d7b5576979825cac72e15498rederpj /* swallow remainder of the buffer */
9ad7b260be233be7d7b5576979825cac72e15498rederpjstatic int char_buffer_write(char_buffer_t *buffer, char *in, int inl)
9ad7b260be233be7d7b5576979825cac72e15498rederpj/* This function will read from a brigade and discard the read buckets as it
9ad7b260be233be7d7b5576979825cac72e15498rederpj * proceeds. It will read at most *len bytes.
87587593f1a53030e840acc0dec6cc881022ea40covenerstatic apr_status_t brigade_consume(apr_bucket_brigade *bb,
9ad7b260be233be7d7b5576979825cac72e15498rederpj const char *str;
9ad7b260be233be7d7b5576979825cac72e15498rederpj /* Justin points out this is an http-ism that might
9ad7b260be233be7d7b5576979825cac72e15498rederpj * not fit if brigade_consume is added to APR. Perhaps
9ab21648975dff7e1b680daf8aea627227ba28f7trawick * apr_bucket_read(eos_bucket) should return APR_EOF?
9ad7b260be233be7d7b5576979825cac72e15498rederpj * Then this becomes mainline instead of a one-off.
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem /* The reason I'm not offering brigade_consume yet
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem * across to apr-util is that the following call
7add8f7fb048534390571801b7794f71cd9e127abnicholes * illustrates how borked that API really is. For
7add8f7fb048534390571801b7794f71cd9e127abnicholes * this sort of case (caller provided buffer) it
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes * would be much more trivial for apr_bucket_consume
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes * to do all the work that follows, based on the
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes * particular characteristics of the bucket we are
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes * consuming here.
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes status = apr_bucket_read(b, &str, &str_len, block);
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes /* This stream bucket was consumed */
7add8f7fb048534390571801b7794f71cd9e127abnicholes /* Do not block once some data has been consumed */
3dfeb02cfb853d8717ca0cc259b59fea610173f5bnicholes /* Assure we don't overflow. */
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes consume = (str_len + actual > *len) ? *len - actual : str_len;
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes /* This physical bucket was consumed */
3dfeb02cfb853d8717ca0cc259b59fea610173f5bnicholes /* Only part of this physical bucket was consumed */
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf else if (b->length == 0) {
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf /* This could probably be actual == *len, but be safe from stray
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf * photons. */
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes * this is the function called by SSL_read()
e8f95a682820a599fe41b22977010636be5c2717jimstatic int bio_filter_in_read(BIO *bio, char *in, int inlen)
7dbf29be626018bc389ef94c1846aeac4b72633bsf bio_filter_in_ctx_t *inctx = (bio_filter_in_ctx_t *)(bio->ptr);
7dbf29be626018bc389ef94c1846aeac4b72633bsf /* OpenSSL catches this case, so should we. */
7dbf29be626018bc389ef94c1846aeac4b72633bsf /* Abort early if the client has initiated a renegotiation. */
7dbf29be626018bc389ef94c1846aeac4b72633bsf if (inctx->filter_ctx->config->reneg_state == RENEG_ABORT) {
7dbf29be626018bc389ef94c1846aeac4b72633bsf return -1;
7dbf29be626018bc389ef94c1846aeac4b72633bsf /* In theory, OpenSSL should flush as necessary, but it is known
7dbf29be626018bc389ef94c1846aeac4b72633bsf * not to do so correctly in some cases; see PR 46952.
7dbf29be626018bc389ef94c1846aeac4b72633bsf * Historically, this flush call was performed only for an SSLv2
7dbf29be626018bc389ef94c1846aeac4b72633bsf * connection or for a proxy connection. Calling _out_flush
7dbf29be626018bc389ef94c1846aeac4b72633bsf * should be very cheap in cases where it is unnecessary (and no
7dbf29be626018bc389ef94c1846aeac4b72633bsf * output is buffered) so the performance impact of doing it
7dbf29be626018bc389ef94c1846aeac4b72633bsf * unconditionally should be minimal.
7dbf29be626018bc389ef94c1846aeac4b72633bsf return -1;
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes inctx->rc = ap_get_brigade(inctx->f->next, inctx->bb,
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf /* If the read returns EAGAIN or success with an empty
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf * brigade, return an error after setting the retry flag;
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes * SSL_read() will then return -1, and SSL_get_error() will
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes * indicate SSL_ERROR_WANT_READ. */
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes if (APR_STATUS_IS_EAGAIN(inctx->rc) || APR_STATUS_IS_EINTR(inctx->rc)
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes || (inctx->rc == APR_SUCCESS && APR_BRIGADE_EMPTY(inctx->bb))) {
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes /* Unexpected errors discard the brigade */
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes inctx->rc = brigade_consume(inctx->bb, block, in, &inl);
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes return (int)inl;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return (int)inl;
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf /* Unexpected errors and APR_EOF clean out the brigade.
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf * Subsequent calls will return APR_EOF.
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf /* Provide the results of this read pass,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * without resetting the BIO retry_read flag
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes return (int)inl;
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf return -1;
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf "APR input filter",
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes NULL /* sslc does not have the callback_ctrl field */
4be9c459920a7c1cfe62d654327dae5c4bb6b284sfstatic apr_status_t ssl_io_input_read(bio_filter_in_ctx_t *inctx,
d330a801b1e5d63a4b8b4fd431542ad0903fd71bbnicholes /* If we have something leftover from last time, try that first. */
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf if ((bytes = char_buffer_read(&inctx->cbuf, buf, wanted))) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* We want to rollback this read. */
54d22ed1c429b903b029bbd62621f11a9e286137minfrin /* This could probably be *len == wanted, but be safe from stray
54d22ed1c429b903b029bbd62621f11a9e286137minfrin /* Down to a nonblock pattern as we have some data already
54d22ed1c429b903b029bbd62621f11a9e286137minfrin while (1) {
54d22ed1c429b903b029bbd62621f11a9e286137minfrin /* Ensure a non-zero error code is returned */
6999a76d8eb5ef6b4b295e51df0b2fb6064bd373covener /* SSL_read may not read because we haven't taken enough data
6999a76d8eb5ef6b4b295e51df0b2fb6064bd373covener * from the stack. This is where we want to consider all of
54d22ed1c429b903b029bbd62621f11a9e286137minfrin * the blocking and SPECULATIVE semantics
54d22ed1c429b903b029bbd62621f11a9e286137minfrin rc = SSL_read(inctx->filter_ctx->pssl, buf + bytes, wanted - bytes);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* We want to rollback this read. */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes else if (rc == 0) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* If EAGAIN, we will loop given a blocking read,
e8f95a682820a599fe41b22977010636be5c2717jim * otherwise consider ourselves at EOF.
e8f95a682820a599fe41b22977010636be5c2717jim /* Already read something, return APR_SUCCESS instead.
8113dac419143273351446c3ad653f3fe5ba5cfdwrowe * On win32 in particular, but perhaps on other kernels,
8113dac419143273351446c3ad653f3fe5ba5cfdwrowe * a blocking call isn't 'always' blocking.
f0f6f1b90ab582896f8a7d56d85bd62a55e57d90covener if (*len > 0) {
9ad7b260be233be7d7b5576979825cac72e15498rederpj if (*len > 0) {
560fd0658902ab57754616c172d8953e69fc4722bnicholes else /* (rc < 0) */ {
560fd0658902ab57754616c172d8953e69fc4722bnicholes int ssl_err = SSL_get_error(inctx->filter_ctx->pssl, rc);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes conn_rec *c = (conn_rec*)SSL_get_app_data(inctx->filter_ctx->pssl);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * If OpenSSL wants to read more, and we were nonblocking,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * report as an EAGAIN. Otherwise loop, pulling more
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * data from network filter.
e8f95a682820a599fe41b22977010636be5c2717jim * (This is usually the case when the client forces an SSL
e8f95a682820a599fe41b22977010636be5c2717jim * renegotiation which is handled implicitly by OpenSSL.)
ae1981fc94adf2b231e2d0e15d2f895b2138c969covener if (*len > 0) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes continue; /* Blocking and nothing yet? Try again. */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* Already read something, return APR_SUCCESS instead. */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (*len > 0) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes continue; /* Blocking and nothing yet? Try again. */
560fd0658902ab57754616c172d8953e69fc4722bnicholes "SSL input filter read failed.");
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes else /* if (ssl_err == SSL_ERROR_SSL) */ {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * Log SSL errors and any unexpected conditions.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_log_cerror(APLOG_MARK, APLOG_INFO, inctx->rc, c,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ssl_log_ssl_error(SSLLOG_MARK, APLOG_INFO, mySrvFromConn(c));
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes/* Read a line of input from the SSL input layer into buffer BUF of
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * length *LEN; updating *len to reflect the length of the line
0e05808dc59a321566303084c84b9826a4353cefrederpj * including the LF character. */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstatic apr_status_t ssl_io_input_getline(bio_filter_in_ctx_t *inctx,
ebe5305f8b22507374358f32b74d12fb50c05a25covener apr_size_t tmplen = *len, buflen = *len, offset = 0;
ebe5305f8b22507374358f32b74d12fb50c05a25covener * in most cases we get all the headers on the first SSL_read.
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener * however, in certain cases SSL_read will only get a partial
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener * chunk of the headers, so we try to read until LF is seen.
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener while (tmplen > 0) {
4e9c24785b525d2956e6e381015c0f2bd0a72f4bcovener status = ssl_io_input_read(inctx, buf + offset, &tmplen);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstatic apr_status_t ssl_filter_write(ap_filter_t *f,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes const char *data,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* write SSL */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes outctx = (bio_filter_out_ctx_t *)filter_ctx->pbioWrite->ptr;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes res = SSL_write(filter_ctx->pssl, (unsigned char *)data, len);
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe if (res < 0) {
e8f95a682820a599fe41b22977010636be5c2717jim conn_rec *c = (conn_rec*)SSL_get_app_data(outctx->filter_ctx->pssl);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * If OpenSSL wants to write more, and we were nonblocking,
e8f95a682820a599fe41b22977010636be5c2717jim * report as an EAGAIN. Otherwise loop, pushing more
e8f95a682820a599fe41b22977010636be5c2717jim * data at the network filter.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * (This is usually the case when the client forces an SSL
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * renegotiation which is handled implicitly by OpenSSL.)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_log_cerror(APLOG_MARK, APLOG_INFO, outctx->rc, c,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "SSL output filter write failed.");
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes else /* if (ssl_err == SSL_ERROR_SSL) */ {
e8f95a682820a599fe41b22977010636be5c2717jim * Log SSL errors
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_log_cerror(APLOG_MARK, APLOG_INFO, outctx->rc, c,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ssl_log_ssl_error(SSLLOG_MARK, APLOG_INFO, mySrvFromConn(c));
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* XXX: probably a better way to determine this */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_log_cerror(APLOG_MARK, APLOG_INFO, outctx->rc, c,
e8f95a682820a599fe41b22977010636be5c2717jim/* Just use a simple request. Any request will work for this, because
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * we use a flag in the conn_rec->conn_vector now. The fake request just
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * gets the request back to the Apache core so that a response can be sent.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * To avoid calling back for more data from the socket, use an HTTP/0.9
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * request, and tack on an EOS bucket.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes/* Custom apr_status_t error code, used when a plain HTTP request is
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * recevied on an SSL port. */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes#define MODSSL_ERROR_HTTP_ON_HTTPS (APR_OS_START_USERERR + 0)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes/* Custom apr_status_t error code, used when the proxy cannot
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * establish an outgoing SSL connection. */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes#define MODSSL_ERROR_BAD_GATEWAY (APR_OS_START_USERERR + 1)
f43b67c5a9d29b572eac916f8335cedc80c908bebnicholesstatic void ssl_io_filter_disable(SSLConnRec *sslconn, ap_filter_t *f)
37af4b0cf648275b68ff41c866c665b4ccf4667dcovenerstatic apr_status_t ssl_io_filter_error(ap_filter_t *f,
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf switch (status) {
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf /* log the situation */
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf "SSL handshake failed: HTTP spoken on HTTPS port; "
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf "trying to send HTML error page");
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf ssl_log_ssl_error(SSLLOG_MARK, APLOG_INFO, sslconn->server);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* fake the request line */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes bucket = HTTP_ON_HTTPS_PORT_BUCKET(f->c->bucket_alloc);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes bucket = ap_bucket_error_create(HTTP_BAD_REQUEST, NULL,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "SSL handshake failed: sending 502");
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes bucket = apr_bucket_eos_create(f->c->bucket_alloc);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * Close the SSL part of the socket connection
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * (called immediately _before_ the socket is closed)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * or called with
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstatic void ssl_filter_io_shutdown(ssl_filter_ctx_t *filter_ctx,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * Now close the SSL layer of the connection. We've to take
8113dac419143273351446c3ad653f3fe5ba5cfdwrowe * the TLSv1 standard into account here:
8113dac419143273351446c3ad653f3fe5ba5cfdwrowe * | 7.2.1. Closure alerts
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * | The client and the server must share knowledge that the connection is
e8f95a682820a599fe41b22977010636be5c2717jim * | ending in order to avoid a truncation attack. Either party may
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * | initiate the exchange of closing messages.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * | close_notify
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * | This message notifies the recipient that the sender will not send
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * | any more messages on this connection. The session becomes
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * | unresumable if any connection is terminated without proper
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe * | close_notify messages with level equal to warning.
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe * | Either party may initiate a close by sending a close_notify alert.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * | Any data received after a closure alert is ignored.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * | Each party is required to send a close_notify alert before closing
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * | the write side of the connection. It is required that the other party
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * | respond with a close_notify alert of its own and close down the
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * | connection immediately, discarding any pending writes. It is not
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * | required for the initiator of the close to wait for the responding
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * | close_notify alert before closing the read side of the connection.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * This means we've to send a close notify message, but haven't to wait
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * for the close notify of the client. Actually we cannot wait for the
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * close notify of the client because some clients (including Netscape
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * 4.x) don't send one, so we would hang.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * exchange close notify messages, but allow the user
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * to force the type of handshake via SetEnvIf directive
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj shutdown_type = SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* perform no close notify handshake at all
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes (violates the SSL/TLS standard!) */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes shutdown_type = SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* send close notify and wait for clients close notify
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes (standard compliant, but usually causes connection hangs) */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * case SSL_SHUTDOWN_TYPE_UNSET:
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * case SSL_SHUTDOWN_TYPE_STANDARD:
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* send close notify, but don't wait for clients close notify
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes (standard compliant and safe, so it's the DEFAULT!) */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* and finally log the fact that we've closed the connection */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (APLOG_CS_IS_LEVEL(c, mySrvFromConn(c), loglevel)) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ap_log_cserror(APLOG_MARK, loglevel, 0, c, mySrvFromConn(c),
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "Connection closed to child %ld with %s shutdown "
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "(server %s)",
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* deallocate the SSL connection */
37af4b0cf648275b68ff41c866c665b4ccf4667dcovener filter_ctx->pssl = NULL; /* so filters know we've been shutdown */
37af4b0cf648275b68ff41c866c665b4ccf4667dcovener /* prevent any further I/O */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstatic apr_status_t ssl_io_filter_cleanup(void *data)
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf conn_rec *c = (conn_rec *)SSL_get_app_data(filter_ctx->pssl);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * The hook is NOT registered with ap_hook_process_connection. Instead, it is
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * called manually from the churn () before it tries to read any data.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * There is some problem if I accept conn_rec *. Still investigating..
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * Adv. if conn_rec * can be accepted is we can hook this function using the
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * ap_hook_process_connection hook.
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes/* Perform the SSL handshake (whether in client or server mode), if
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe * necessary, for the given connection. */
e8f95a682820a599fe41b22977010636be5c2717jimstatic apr_status_t ssl_io_filter_handshake(ssl_filter_ctx_t *filter_ctx)
e8f95a682820a599fe41b22977010636be5c2717jim conn_rec *c = (conn_rec *)SSL_get_app_data(filter_ctx->pssl);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "SSL Proxy connect failed");
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes ssl_log_ssl_error(SSLLOG_MARK, APLOG_INFO, server);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* ensure that the SSL structures etc are freed, etc: */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (sc->proxy_ssl_check_peer_expire != SSL_ENABLED_FALSE) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes cert = SSL_get_peer_certificate(filter_ctx->pssl);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "SSL Proxy: Peer certificate is expired");
8869662bb1a4078297020e94ae5e928626d877c6rederpj /* ensure that the SSL structures etc are freed, etc: */
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem if ((sc->proxy_ssl_check_peer_cn != SSL_ENABLED_FALSE)
8869662bb1a4078297020e94ae5e928626d877c6rederpj apr_table_get(c->notes, "proxy-request-hostname")) != NULL)) {
8869662bb1a4078297020e94ae5e928626d877c6rederpj const char *hostname;
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem "SSL_CLIENT_S_DN_CN");
8869662bb1a4078297020e94ae5e928626d877c6rederpj apr_table_unset(c->notes, "proxy-request-hostname");
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem "SSL Proxy: Peer certificate CN mismatch:"
8869662bb1a4078297020e94ae5e928626d877c6rederpj " Certificate CN: %s Requested hostname: %s",
8869662bb1a4078297020e94ae5e928626d877c6rederpj /* ensure that the SSL structures etc are freed, etc: */
8869662bb1a4078297020e94ae5e928626d877c6rederpj bio_filter_in_ctx_t *inctx = (bio_filter_in_ctx_t *)
8869662bb1a4078297020e94ae5e928626d877c6rederpj bio_filter_out_ctx_t *outctx = (bio_filter_out_ctx_t *)
8869662bb1a4078297020e94ae5e928626d877c6rederpj apr_status_t rc = inctx->rc ? inctx->rc : outctx->rc ;
8869662bb1a4078297020e94ae5e928626d877c6rederpj * The case where the connection was closed before any data
6733d943c9e8d0f27dd077a04037e8c49eb090ffcovener * was transferred. That's not a real error and can occur
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem * sporadically with some clients.
8869662bb1a4078297020e94ae5e928626d877c6rederpj "SSL handshake stopped: connection was closed");
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf * This is in addition to what was present earlier. It is
4be9c459920a7c1cfe62d654327dae5c4bb6b284sf * borrowed from openssl_state_machine.c [mod_tls].
8869662bb1a4078297020e94ae5e928626d877c6rederpj else if (ERR_GET_LIB(ERR_peek_error()) == ERR_LIB_SSL &&
8869662bb1a4078297020e94ae5e928626d877c6rederpj ERR_GET_REASON(ERR_peek_error()) == SSL_R_HTTP_REQUEST) {
8869662bb1a4078297020e94ae5e928626d877c6rederpj * The case where OpenSSL has recognized a HTTP request:
8869662bb1a4078297020e94ae5e928626d877c6rederpj * This means the client speaks plain HTTP on our HTTPS port.
8869662bb1a4078297020e94ae5e928626d877c6rederpj * ssl_io_filter_error will disable the ssl filters when it
8869662bb1a4078297020e94ae5e928626d877c6rederpj * sees this status code.
8869662bb1a4078297020e94ae5e928626d877c6rederpj "SSL handshake interrupted by system "
8869662bb1a4078297020e94ae5e928626d877c6rederpj "[Hint: Stop button pressed in browser?!]");
8869662bb1a4078297020e94ae5e928626d877c6rederpj else /* if (ssl_err == SSL_ERROR_SSL) */ {
8869662bb1a4078297020e94ae5e928626d877c6rederpj * Log SSL errors and any unexpected conditions.
8869662bb1a4078297020e94ae5e928626d877c6rederpj "SSL library error %d in handshake "
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem * Check for failed client authentication
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem verify_result = SSL_get_verify_result(filter_ctx->pssl);
8869662bb1a4078297020e94ae5e928626d877c6rederpj (sc->server->auth.verify_mode == SSL_CVERIFY_OPTIONAL_NO_CA))
8869662bb1a4078297020e94ae5e928626d877c6rederpj /* leaving this log message as an error for the moment,
8869662bb1a4078297020e94ae5e928626d877c6rederpj * according to the mod_ssl docs:
8869662bb1a4078297020e94ae5e928626d877c6rederpj * "level optional_no_ca is actually against the idea
8869662bb1a4078297020e94ae5e928626d877c6rederpj * of authentication (but can be used to establish
8869662bb1a4078297020e94ae5e928626d877c6rederpj * SSL test pages, etc.)"
8869662bb1a4078297020e94ae5e928626d877c6rederpj * optional_no_ca doesn't appear to work as advertised
8869662bb1a4078297020e94ae5e928626d877c6rederpj "SSL client authentication failed, "
8869662bb1a4078297020e94ae5e928626d877c6rederpj "accepting certificate based on "
8869662bb1a4078297020e94ae5e928626d877c6rederpj "\"SSLVerifyClient optional_no_ca\" "
8869662bb1a4078297020e94ae5e928626d877c6rederpj "configuration");
8869662bb1a4078297020e94ae5e928626d877c6rederpj "SSL client authentication failed: %s",
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj * Remember the peer certificate's DN
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem if ((cert = SSL_get_peer_certificate(filter_ctx->pssl))) {
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem * Make really sure that when a peer certificate
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem * is required we really got one... (be paranoid)
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem if ((sc->server->auth.verify_mode == SSL_CVERIFY_REQUIRE) &&
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem "No acceptable peer certificate available");
8445dae5cc606ba8ba04efc341cc1e081d95920drpluemstatic apr_status_t ssl_io_filter_input(ap_filter_t *f,
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem const char *start = inctx->buffer; /* start of block to return */
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem apr_size_t len = sizeof(inctx->buffer); /* length of block to return */
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj if (f->c->aborted) {
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem /* XXX: Ok, if we aborted, we ARE at the EOS. We also have
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem * aborted. This 'double protection' is probably redundant,
11ca38a20ab9b2d00258f745620e2724838e7e21rederpj * but also effective against just about anything.
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem apr_bucket *bucket = apr_bucket_eos_create(f->c->bucket_alloc);
11ca38a20ab9b2d00258f745620e2724838e7e21rederpj return ap_get_brigade(f->next, bb, mode, block, readbytes);
11ca38a20ab9b2d00258f745620e2724838e7e21rederpj /* XXX: we don't currently support anything other than these modes. */
11ca38a20ab9b2d00258f745620e2724838e7e21rederpj if (mode != AP_MODE_READBYTES && mode != AP_MODE_GETLINE &&
0e05808dc59a321566303084c84b9826a4353cefrederpj mode != AP_MODE_SPECULATIVE && mode != AP_MODE_INIT) {
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem /* XXX: we could actually move ssl_io_filter_handshake to an
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem * ap_hook_process_connection but would still need to call it for
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem * AP_MODE_INIT for protocols that may upgrade the connection
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem * rather than have SSLEngine On configured.
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem if ((status = ssl_io_filter_handshake(inctx->filter_ctx)) != APR_SUCCESS) {
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj /* protocol module needs to handshake before sending
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj * data to client (e.g. NNTP or FTP)
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem /* Protected from truncation, readbytes < MAX_SIZE_T
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem * FIXME: No, it's *not* protected. -- jre */
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj status = ssl_io_input_read(inctx, inctx->buffer, &len);
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj const char *pos;
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj /* Satisfy the read directly out of the buffer if possible;
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj * invoking ssl_io_input_getline will mean the entire buffer
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj * is copied once (unnecessarily) for each GETLINE call. */
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj /* Buffer contents now consumed. */
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj /* Otherwise fall back to the hard way. */
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj status = ssl_io_input_getline(inctx, inctx->buffer, &len);
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj /* We have no idea what you are talking about, so return an error. */
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem /* It is possible for mod_ssl's BIO to be used outside of the
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem * direct control of mod_ssl's input or output filter -- notably,
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj * when mod_ssl initiates a renegotiation. Switching the BIO mode
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj * back to "blocking" here ensures such operations don't fail with
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem * SSL_ERROR_WANT_READ. */
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem /* Handle custom errors. */
0e05808dc59a321566303084c84b9826a4353cefrederpj /* Create a transient bucket out of the decrypted data. */
0e05808dc59a321566303084c84b9826a4353cefrederpj apr_bucket_transient_create(start, len, f->c->bucket_alloc);
0e05808dc59a321566303084c84b9826a4353cefrederpjstatic apr_status_t ssl_io_filter_output(ap_filter_t *f,
0e05808dc59a321566303084c84b9826a4353cefrederpj if (f->c->aborted) {
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj /* ssl_filter_io_shutdown was called */
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem inctx = (bio_filter_in_ctx_t *)filter_ctx->pbioRead->ptr;
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem outctx = (bio_filter_out_ctx_t *)filter_ctx->pbioWrite->ptr;
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem /* When we are the writer, we must initialize the inctx
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj * mode so that we block for any required ssl input, because
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj * output filtering is always nonblocking.
0e05808dc59a321566303084c84b9826a4353cefrederpj if ((status = ssl_io_filter_handshake(filter_ctx)) != APR_SUCCESS) {
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj /* If it is a flush or EOS, we need to pass this down.
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj * These types do not require translation by OpenSSL.
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj if (APR_BUCKET_IS_EOS(bucket) || APR_BUCKET_IS_FLUSH(bucket)) {
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj if (bio_filter_out_flush(filter_ctx->pbioWrite) < 0) {
0e05808dc59a321566303084c84b9826a4353cefrederpj * By definition, nothing can come after EOS.
0e05808dc59a321566303084c84b9826a4353cefrederpj * which also means we can pass the rest of this brigade
0e05808dc59a321566303084c84b9826a4353cefrederpj * without creating a new one since it only contains the
0e05808dc59a321566303084c84b9826a4353cefrederpj * EOS bucket.
0e05808dc59a321566303084c84b9826a4353cefrederpj if ((status = ap_pass_brigade(f->next, bb)) != APR_SUCCESS) {
0e05808dc59a321566303084c84b9826a4353cefrederpj /* bio_filter_out_flush() already passed down a flush bucket
0e05808dc59a321566303084c84b9826a4353cefrederpj * if there was any data to be flushed.
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj /* The special "EOC" bucket means a shutdown is needed;
0e05808dc59a321566303084c84b9826a4353cefrederpj * - turn off buffering in bio_filter_out_write
40a1aee60a66f7c8dbd0835fdd4f09334e12fc15rpluem * - issue the SSL_shutdown
0e05808dc59a321566303084c84b9826a4353cefrederpj if ((status = ap_pass_brigade(f->next, bb)) != APR_SUCCESS) {
0e05808dc59a321566303084c84b9826a4353cefrederpj /* filter output */
0e05808dc59a321566303084c84b9826a4353cefrederpj const char *data;
0e05808dc59a321566303084c84b9826a4353cefrederpj status = apr_bucket_read(bucket, &data, &len, rblock);
0e05808dc59a321566303084c84b9826a4353cefrederpj /* No data available: flush... */
0e05808dc59a321566303084c84b9826a4353cefrederpj if (bio_filter_out_flush(filter_ctx->pbioWrite) < 0) {
0e05808dc59a321566303084c84b9826a4353cefrederpj continue; /* and try again with a blocking read. */
0e05808dc59a321566303084c84b9826a4353cefrederpj if (!APR_STATUS_IS_EOF(status) && (status != APR_SUCCESS)) {
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpjint ssl_io_buffer_fill(request_rec *r, apr_size_t maxlen)
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem /* Create the context which will be passed to the input filter;
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem * containing a setaside pool and a brigade which constrain the
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem * lifetime of the buffered data. */
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem ctx->bb = apr_brigade_create(r->pool, c->bucket_alloc);
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem /* ... and a temporary brigade. */
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj tempb = apr_brigade_create(r->pool, c->bucket_alloc);
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem ap_log_cerror(APLOG_MARK, APLOG_TRACE4, 0, c, "filling buffer, max size "
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem /* The request body is read from the protocol-level input
85da6b76d07b7af570cbbec208a87697ba9c44f5rederpj * filters; the buffering filter will reinject it from that
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem * level, allowing content/resource filters to run later, if
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem * necessary. */
8445dae5cc606ba8ba04efc341cc1e081d95920drpluem rv = ap_get_brigade(r->proto_input_filters, tempb, AP_MODE_READBYTES,
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj "could not read request body for SSL buffer");
3f5585f7f4a7d74f2f94ec729ea8c1879d419e35rederpj /* Iterate through the returned brigade: setaside each bucket
8113dac419143273351446c3ad653f3fe5ba5cfdwrowe * into the context's pool and move it into the brigade. */
e8f95a682820a599fe41b22977010636be5c2717jim const char *data;
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes } else if (!APR_BUCKET_IS_METADATA(e)) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes rv = apr_bucket_read(e, &data, &len, APR_BLOCK_READ);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "could not read bucket for SSL buffer");
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "could not setaside bucket for SSL buffer");
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "total of %" APR_OFF_T_FMT " bytes in buffer, eos=%d",
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* Fail if this exceeds the maximum buffer size. */
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes "request body exceeds maximum size (%" APR_SIZE_T_FMT
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes } while (!eos);
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe /* After consuming all protocol-level input, remove all protocol-level
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * filters. It should strictly only be necessary to remove filters
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * at exactly ftype == AP_FTYPE_PROTOCOL, since this filter will
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * precede all > AP_FTYPE_PROTOCOL anyway. */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes while (r->proto_input_filters->frec->ftype < AP_FTYPE_CONNECTION) {
e8f95a682820a599fe41b22977010636be5c2717jim /* Insert the filter which will supply the buffered content. */
d64dd2fd4516c2b1b664c5e59c0628d9aff26984covener/* This input filter supplies the buffered request body to the caller
d64dd2fd4516c2b1b664c5e59c0628d9aff26984covener * from the brigade stored in f->ctx. Note that the placement of this
d64dd2fd4516c2b1b664c5e59c0628d9aff26984covener * filter in the filter stack is important; it must be the first
c4f16f709c79bb7e2ddffb532bc7708eab9a9691covener * r->proto_input_filter; lower-typed filters will not be preserved
c4f16f709c79bb7e2ddffb532bc7708eab9a9691covener * across internal redirects (see PR 43738). */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstatic apr_status_t ssl_io_filter_buffer(ap_filter_t *f,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "read from buffered SSL brigade, mode %d, "
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe if (mode != AP_MODE_READBYTES && mode != AP_MODE_GETLINE) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* Suprisingly (and perhaps, wrongly), the request body can be
f43b67c5a9d29b572eac916f8335cedc80c908bebnicholes * pulled from the input filter stack more than once; a
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * handler may read it, and ap_discard_request_body() will
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * attempt to do so again after *every* request. So input
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * filters must be prepared to give up an EOS if invoked after
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * initially reading the request. The HTTP_IN filter does this
37af4b0cf648275b68ff41c866c665b4ccf4667dcovener * with its ->eos_sent flag. */
37af4b0cf648275b68ff41c866c665b4ccf4667dcovener APR_BRIGADE_INSERT_TAIL(bb, apr_bucket_eos_create(f->c->bucket_alloc));
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* Partition the buffered brigade. */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "could not partition buffered SSL brigade");
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* If the buffered brigade contains less then the requested
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * length, just pass it all back. */
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe /* Unsplice the partitioned segment and move it into the
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe * passed-in brigade; no convenient way to do this with
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * the APR_BRIGADE_* macros. */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes APR_RING_SPLICE_HEAD(&bb->list, d, e, apr_bucket, link);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* Split a line into the passed-in brigade. */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes rv = apr_brigade_split_line(bb, ctx->bb, block, bytes);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes "could not split line from buffered SSL brigade");
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* Ensure that the brigade is terminated by an EOS if the
e8f95a682820a599fe41b22977010636be5c2717jim * buffered request body has been entirely consumed. */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (e == APR_BRIGADE_SENTINEL(bb) || !APR_BUCKET_IS_EOS(e)) {
7dbf29be626018bc389ef94c1846aeac4b72633bsf "buffered SSL brigade exhausted");
7dbf29be626018bc389ef94c1846aeac4b72633bsf /* Note that the filter must *not* be removed here; it may be
7dbf29be626018bc389ef94c1846aeac4b72633bsf * invoked again, see comment above. */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes/* The request_rec pointer is passed in here only to ensure that the
f43b67c5a9d29b572eac916f8335cedc80c908bebnicholes * filter chain is modified correctly when doing a TLS upgrade. It
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * must *not* be used otherwise. */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholesstatic void ssl_io_input_add_filter(ssl_filter_ctx_t *filter_ctx, conn_rec *c,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes filter_ctx->pInputFilter = ap_add_input_filter(ssl_io_filter, inctx, r, c);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes filter_ctx->pbioRead = BIO_new(&bio_filter_in_method);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes inctx->bb = apr_brigade_create(c->pool, c->bucket_alloc);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes/* The request_rec pointer is passed in here only to ensure that the
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * filter chain is modified correctly when doing a TLS upgrade. It
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes * must *not* be used otherwise. */
8bdea88407c848c1c2693655e2f8b23abde12307bnicholesvoid ssl_io_filter_init(conn_rec *c, request_rec *r, SSL *ssl)
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes filter_ctx = apr_palloc(c->pool, sizeof(ssl_filter_ctx_t));
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe filter_ctx->pOutputFilter = ap_add_output_filter(ssl_io_filter,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes filter_ctx->pbioWrite = BIO_new(&bio_filter_out_method);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes filter_ctx->pbioWrite->ptr = (void *)bio_filter_out_ctx_new(filter_ctx, c);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes /* We insert a clogging input filter. Let the core know. */
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes SSL_set_bio(ssl, filter_ctx->pbioRead, filter_ctx->pbioWrite);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes apr_pool_cleanup_register(c->pool, (void*)filter_ctx,
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes if (APLOG_CS_IS_LEVEL(c, mySrvFromConn(c), APLOG_TRACE4)) {
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes BIO_set_callback(SSL_get_rbio(ssl), ssl_io_data_cb);
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes BIO_set_callback_arg(SSL_get_rbio(ssl), (void *)ssl);
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe ap_register_input_filter (ssl_io_filter, ssl_io_filter_input, NULL, AP_FTYPE_CONNECTION + 5);
e8f95a682820a599fe41b22977010636be5c2717jim ap_register_output_filter (ssl_io_filter, ssl_io_filter_output, NULL, AP_FTYPE_CONNECTION + 5);
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes ap_register_input_filter (ssl_io_buffer, ssl_io_filter_buffer, NULL, AP_FTYPE_PROTOCOL);
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes/* _________________________________________________________________
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes** I/O Data Debugging
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes** _________________________________________________________________
d5b12fe8ae917e654a33247fd4e59dc9e75170aebnicholes unsigned char ch;
8113dac419143273351446c3ad653f3fe5ba5cfdwrowe for(; (len > 0) && ((s[len-1] == ' ') || (s[len-1] == '\0')); len--)
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes "+-------------------------------------------------------------------------+");
8113dac419143273351446c3ad653f3fe5ba5cfdwrowe for(i = 0 ; i< rows; i++) {
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes memcpy(ebcdic_text,(char *)(s) + i * DUMP_WIDTH, j);
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes#endif /* APR_CHARSET_EBCDIC */
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes apr_snprintf(tmp, sizeof(tmp), "| %04x: ", i * DUMP_WIDTH);
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes for (j = 0; j < DUMP_WIDTH; j++) {
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes apr_cpystrn(buf+strlen(buf), " ", sizeof(buf)-strlen(buf));
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes ch = ((unsigned char)*((char *)(s) + i * DUMP_WIDTH + j)) & 0xff;
e8f95a682820a599fe41b22977010636be5c2717jim apr_snprintf(tmp, sizeof(tmp), "%02x%c", ch , j==7 ? '-' : ' ');
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes apr_cpystrn(buf+strlen(buf), tmp, sizeof(buf)-strlen(buf));
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes apr_cpystrn(buf+strlen(buf), " ", sizeof(buf)-strlen(buf));
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes for (j = 0; j < DUMP_WIDTH; j++) {
e8f95a682820a599fe41b22977010636be5c2717jim apr_cpystrn(buf+strlen(buf), " ", sizeof(buf)-strlen(buf));
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes ch = ((unsigned char)*((char *)(s) + i * DUMP_WIDTH + j)) & 0xff;
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes apr_snprintf(tmp, sizeof(tmp), "%c", (ch >= 0x20 && ch <= 0x7F) ? ebcdic_text[j] : '.');
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes#else /* APR_CHARSET_EBCDIC */
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes apr_snprintf(tmp, sizeof(tmp), "%c", ((ch >= ' ') && (ch <= '~')) ? ch : '.');
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes#endif /* APR_CHARSET_EBCDIC */
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes apr_cpystrn(buf+strlen(buf), tmp, sizeof(buf)-strlen(buf));
482f676c6c19b1c5bb5cca04dad11509c1da3a4cwrowe apr_cpystrn(buf+strlen(buf), " |", sizeof(buf)-strlen(buf));
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes "+-------------------------------------------------------------------------+");
d64dd2fd4516c2b1b664c5e59c0628d9aff26984covener if ((ssl = (SSL *)BIO_get_callback_arg(bio)) == NULL)
c4f16f709c79bb7e2ddffb532bc7708eab9a9691covener if ((c = (conn_rec *)SSL_get_app_data(ssl)) == NULL)
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes if (rc >= 0) {
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes "%s: %s %ld/%d bytes %s BIO#%pp [mem: %pp] %s",
e8f95a682820a599fe41b22977010636be5c2717jim (cmd == (BIO_CB_WRITE|BIO_CB_RETURN) ? "write" : "read"),
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes rc, argi, (cmd == (BIO_CB_WRITE|BIO_CB_RETURN) ? "to" : "from"),
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes (argp != NULL ? "(BIO dump follows)" : "(Oops, no memory buffer?)"));
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes if ((argp != NULL) && APLOG_CS_IS_LEVEL(c, s, APLOG_TRACE7))
03f4448f864e31ade79856ac8c264a5e6dce3b10bnicholes "%s: I/O error, %d bytes expected to %s on BIO#%pp [mem: %pp]",
f43b67c5a9d29b572eac916f8335cedc80c908bebnicholes (cmd == (BIO_CB_WRITE|BIO_CB_RETURN) ? "write" : "read"),