⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ssl_engine_io.c

📁 apache服务器源代码(版本号:2.2.2)
💻 C
📖 第 1 页 / 共 4 页
字号:
    if (!filter_ctx->pssl) {        /* ssl_filter_io_shutdown was called */        return ap_pass_brigade(f->next, bb);    }    inctx = (bio_filter_in_ctx_t *)filter_ctx->pbioRead->ptr;    outctx = (bio_filter_out_ctx_t *)filter_ctx->pbioWrite->ptr;    /* When we are the writer, we must initialize the inctx     * mode so that we block for any required ssl input, because     * output filtering is always nonblocking.     */    inctx->mode = AP_MODE_READBYTES;    inctx->block = APR_BLOCK_READ;    if ((status = ssl_io_filter_connect(filter_ctx)) != APR_SUCCESS) {        return ssl_io_filter_error(f, bb, status);    }    while (!APR_BRIGADE_EMPTY(bb)) {        apr_bucket *bucket = APR_BRIGADE_FIRST(bb);        /* If it is a flush or EOS, we need to pass this down.         * These types do not require translation by OpenSSL.         */        if (APR_BUCKET_IS_EOS(bucket) || APR_BUCKET_IS_FLUSH(bucket)) {            if (bio_filter_out_flush(filter_ctx->pbioWrite) < 0) {                status = outctx->rc;                break;            }            if (APR_BUCKET_IS_EOS(bucket)) {                /*                 * By definition, nothing can come after EOS.                 * which also means we can pass the rest of this brigade                 * without creating a new one since it only contains the                 * EOS bucket.                 */                if ((status = ap_pass_brigade(f->next, bb)) != APR_SUCCESS) {                    return status;                }                break;            }            else {                /* bio_filter_out_flush() already passed down a flush bucket                 * if there was any data to be flushed.                 */                apr_bucket_delete(bucket);            }        }        else if (AP_BUCKET_IS_EOC(bucket)) {            /* The special "EOC" bucket means a shutdown is needed;             * - turn off buffering in bio_filter_out_write             * - issue the SSL_shutdown             */            filter_ctx->nobuffer = 1;            status = ssl_filter_io_shutdown(filter_ctx, f->c, 0);            if (status != APR_SUCCESS) {                ap_log_cerror(APLOG_MARK, APLOG_INFO, status, f->c,                              "SSL filter error shutting down I/O");            }            if ((status = ap_pass_brigade(f->next, bb)) != APR_SUCCESS) {                return status;            }            break;        }        else {            /* filter output */            const char *data;            apr_size_t len;            status = apr_bucket_read(bucket, &data, &len, rblock);            if (APR_STATUS_IS_EAGAIN(status)) {                /* No data available: flush... */                if (bio_filter_out_flush(filter_ctx->pbioWrite) < 0) {                    status = outctx->rc;                    break;                }                rblock = APR_BLOCK_READ;                continue; /* and try again with a blocking read. */            }            rblock = APR_NONBLOCK_READ;            if (!APR_STATUS_IS_EOF(status) && (status != APR_SUCCESS)) {                break;            }            status = ssl_filter_write(f, data, len);            apr_bucket_delete(bucket);            if (status != APR_SUCCESS) {                break;            }        }    }    return status;}/* 128K maximum buffer size by default. */#ifndef SSL_MAX_IO_BUFFER#define SSL_MAX_IO_BUFFER (128 * 1024)#endifstruct modssl_buffer_ctx {    apr_bucket_brigade *bb;    apr_pool_t *pool;};int ssl_io_buffer_fill(request_rec *r){    conn_rec *c = r->connection;    struct modssl_buffer_ctx *ctx;    apr_bucket_brigade *tempb;    apr_off_t total = 0; /* total length buffered */    int eos = 0; /* non-zero once EOS is seen */    /* Create the context which will be passed to the input filter;     * containing a setaside pool and a brigade which constrain the     * lifetime of the buffered data. */    ctx = apr_palloc(r->pool, sizeof *ctx);    apr_pool_create(&ctx->pool, r->pool);    ctx->bb = apr_brigade_create(ctx->pool, c->bucket_alloc);    /* ... and a temporary brigade. */    tempb = apr_brigade_create(r->pool, c->bucket_alloc);    ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c, "filling buffer");    do {        apr_status_t rv;        apr_bucket *e, *next;        /* The request body is read from the protocol-level input         * filters; the buffering filter will reinject it from that         * level, allowing content/resource filters to run later, if         * necessary. */        rv = ap_get_brigade(r->proto_input_filters, tempb, AP_MODE_READBYTES,                            APR_BLOCK_READ, 8192);        if (rv) {            ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,                          "could not read request body for SSL buffer");            return HTTP_INTERNAL_SERVER_ERROR;        }        /* Iterate through the returned brigade: setaside each bucket         * into the context's pool and move it into the brigade. */        for (e = APR_BRIGADE_FIRST(tempb);             e != APR_BRIGADE_SENTINEL(tempb) && !eos; e = next) {            const char *data;            apr_size_t len;            next = APR_BUCKET_NEXT(e);            if (APR_BUCKET_IS_EOS(e)) {                eos = 1;            } else if (!APR_BUCKET_IS_METADATA(e)) {                rv = apr_bucket_read(e, &data, &len, APR_BLOCK_READ);                if (rv != APR_SUCCESS) {                    ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,                                  "could not read bucket for SSL buffer");                    return HTTP_INTERNAL_SERVER_ERROR;                }                total += len;            }            rv = apr_bucket_setaside(e, ctx->pool);            if (rv != APR_SUCCESS) {                ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,                              "could not setaside bucket for SSL buffer");                return HTTP_INTERNAL_SERVER_ERROR;            }            APR_BUCKET_REMOVE(e);            APR_BRIGADE_INSERT_TAIL(ctx->bb, e);        }        ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, c,                      "total of %" APR_OFF_T_FMT " bytes in buffer, eos=%d",                      total, eos);        /* Fail if this exceeds the maximum buffer size. */        if (total > SSL_MAX_IO_BUFFER) {            ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,                          "request body exceeds maximum size for SSL buffer");            return HTTP_REQUEST_ENTITY_TOO_LARGE;        }    } while (!eos);    apr_brigade_destroy(tempb);    /* Insert the filter which will supply the buffered data. */    ap_add_input_filter(ssl_io_buffer, ctx, r, c);    return 0;}/* This input filter supplies the buffered request body to the caller * from the brigade stored in f->ctx. */static apr_status_t ssl_io_filter_buffer(ap_filter_t *f,                                         apr_bucket_brigade *bb,                                         ap_input_mode_t mode,                                         apr_read_type_e block,                                         apr_off_t bytes){    struct modssl_buffer_ctx *ctx = f->ctx;    apr_status_t rv;    ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, f->c,                  "read from buffered SSL brigade, mode %d, "                  "%" APR_OFF_T_FMT " bytes",                  mode, bytes);    if (mode != AP_MODE_READBYTES && mode != AP_MODE_GETLINE) {        return APR_ENOTIMPL;    }    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) {            ap_log_cerror(APLOG_MARK, APLOG_ERR, rv, f->c,                          "could not partition buffered SSL brigade");            ap_remove_input_filter(f);            return rv;        }        /* If the buffered brigade contains less then the requested         * length, just pass it all back. */        if (rv == APR_INCOMPLETE) {            APR_BRIGADE_CONCAT(bb, ctx->bb);        } else {            apr_bucket *d = APR_BRIGADE_FIRST(ctx->bb);            e = APR_BUCKET_PREV(e);            /* Unsplice the partitioned segment and move it into the             * passed-in brigade; no convenient way to do this with             * the APR_BRIGADE_* macros. */            APR_RING_UNSPLICE(d, e, link);            APR_RING_SPLICE_HEAD(&bb->list, d, e, apr_bucket, link);            APR_BRIGADE_CHECK_CONSISTENCY(bb);            APR_BRIGADE_CHECK_CONSISTENCY(ctx->bb);        }    }    else {        /* Split a line into the passed-in brigade. */        rv = apr_brigade_split_line(bb, ctx->bb, mode, bytes);        if (rv) {            ap_log_cerror(APLOG_MARK, APLOG_ERR, rv, f->c,                          "could not split line from buffered SSL brigade");            ap_remove_input_filter(f);            return rv;        }    }    if (APR_BRIGADE_EMPTY(ctx->bb)) {        apr_bucket *e = APR_BRIGADE_LAST(bb);        /* Ensure that the brigade is terminated by an EOS if the         * buffered request body has been entirely consumed. */        if (e == APR_BRIGADE_SENTINEL(bb) || !APR_BUCKET_IS_EOS(e)) {            e = apr_bucket_eos_create(f->c->bucket_alloc);            APR_BRIGADE_INSERT_TAIL(bb, e);        }        ap_log_cerror(APLOG_MARK, APLOG_DEBUG, 0, f->c,                      "buffered SSL brigade now exhausted; removing filter");        ap_remove_input_filter(f);    }    return APR_SUCCESS;}static void ssl_io_input_add_filter(ssl_filter_ctx_t *filter_ctx, conn_rec *c,                                    SSL *ssl){    bio_filter_in_ctx_t *inctx;    inctx = apr_palloc(c->pool, sizeof(*inctx));    filter_ctx->pInputFilter = ap_add_input_filter(ssl_io_filter, inctx, NULL, c);    filter_ctx->pbioRead = BIO_new(&bio_filter_in_method);    filter_ctx->pbioRead->ptr = (void *)inctx;    inctx->ssl = ssl;    inctx->bio_out = filter_ctx->pbioWrite;    inctx->f = filter_ctx->pInputFilter;    inctx->rc = APR_SUCCESS;    inctx->mode = AP_MODE_READBYTES;    inctx->cbuf.length = 0;    inctx->bb = apr_brigade_create(c->pool, c->bucket_alloc);    inctx->block = APR_BLOCK_READ;    inctx->pool = c->pool;    inctx->filter_ctx = filter_ctx;}void ssl_io_filter_init(conn_rec *c, SSL *ssl){    ssl_filter_ctx_t *filter_ctx;    filter_ctx = apr_palloc(c->pool, sizeof(ssl_filter_ctx_t));    filter_ctx->nobuffer        = 0;    filter_ctx->pOutputFilter   = ap_add_output_filter(ssl_io_filter,                                                   filter_ctx, NULL, c);    filter_ctx->pbioWrite       = BIO_new(&bio_filter_out_method);    filter_ctx->pbioWrite->ptr  = (void *)bio_filter_out_ctx_new(filter_ctx, c);    ssl_io_input_add_filter(filter_ctx, c, ssl);    SSL_set_bio(ssl, filter_ctx->pbioRead, filter_ctx->pbioWrite);    filter_ctx->pssl            = ssl;    apr_pool_cleanup_register(c->pool, (void*)filter_ctx,                              ssl_io_filter_cleanup, apr_pool_cleanup_null);    if (c->base_server->loglevel >= APLOG_DEBUG) {        BIO_set_callback(SSL_get_rbio(ssl), ssl_io_data_cb);        BIO_set_callback_arg(SSL_get_rbio(ssl), (void *)ssl);    }    return;}void ssl_io_filter_register(apr_pool_t *p){    /* This filter MUST be after the HTTP_HEADER filter, but it also must be     * a resource-level filter so it has the request_rec.     */    ap_register_output_filter ("UPGRADE_FILTER", ssl_io_filter_Upgrade, NULL, AP_FTYPE_PROTOCOL + 5);    ap_register_input_filter  (ssl_io_filter, ssl_io_filter_input,  NULL, AP_FTYPE_CONNECTION + 5);    ap_register_output_filter (ssl_io_filter, ssl_io_filter_output, NULL, AP_FTYPE_CONNECTION + 5);    ap_register_input_filter  (ssl_io_buffer, ssl_io_filter_buffer, NULL, AP_FTYPE_PROTOCOL - 1);    return;}/*  _________________________________________________________________****  I/O Data Debugging**  _________________________________________________________________*/#define DUMP_WIDTH 16static void ssl_io_data_dump(server_rec *srvr,                             MODSSL_BIO_CB_ARG_TYPE *s,                             long len){    char buf[256];    char tmp[64];    int i, j, rows, trunc;    unsigned char ch;    trunc = 0;    for(; (len > 0) && ((s[len-1] == ' ') || (s[len-1] == '\0')); len--)        trunc++;    rows = (len / DUMP_WIDTH);    if ((rows * DUMP_WIDTH) < len)        rows++;    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, srvr,            "+-------------------------------------------------------------------------+");    for(i = 0 ; i< rows; i++) {        apr_snprintf(tmp, sizeof(tmp), "| %04x: ", i * DUMP_WIDTH);        apr_cpystrn(buf, tmp, sizeof(buf));        for (j = 0; j < DUMP_WIDTH; j++) {            if (((i * DUMP_WIDTH) + j) >= len)                apr_cpystrn(buf+strlen(buf), "   ", sizeof(buf)-strlen(buf));            else {                ch = ((unsigned char)*((char *)(s) + i * DUMP_WIDTH + j)) & 0xff;                apr_snprintf(tmp, sizeof(tmp), "%02x%c", ch , j==7 ? '-' : ' ');                apr_cpystrn(buf+strlen(buf), tmp, sizeof(buf)-strlen(buf));            }        }        apr_cpystrn(buf+strlen(buf), " ", sizeof(buf)-strlen(buf));        for (j = 0; j < DUMP_WIDTH; j++) {            if (((i * DUMP_WIDTH) + j) >= len)                apr_cpystrn(buf+strlen(buf), " ", sizeof(buf)-strlen(buf));            else {                ch = ((unsigned char)*((char *)(s) + i * DUMP_WIDTH + j)) & 0xff;                apr_snprintf(tmp, sizeof(tmp), "%c", ((ch >= ' ') && (ch <= '~')) ? ch : '.');                apr_cpystrn(buf+strlen(buf), tmp, sizeof(buf)-strlen(buf));            }        }        apr_cpystrn(buf+strlen(buf), " |", sizeof(buf)-strlen(buf));        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, srvr,                     "%s", buf);    }    if (trunc > 0)        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, srvr,                "| %04ld - <SPACES/NULS>", len + trunc);    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, srvr,            "+-------------------------------------------------------------------------+");    return;}long ssl_io_data_cb(BIO *bio, int cmd,                    MODSSL_BIO_CB_ARG_TYPE *argp,                    int argi, long argl, long rc){    SSL *ssl;    conn_rec *c;    server_rec *s;    if ((ssl = (SSL *)BIO_get_callback_arg(bio)) == NULL)        return rc;    if ((c = (conn_rec *)SSL_get_app_data(ssl)) == NULL)        return rc;    s = c->base_server;    if (   cmd == (BIO_CB_WRITE|BIO_CB_RETURN)        || cmd == (BIO_CB_READ |BIO_CB_RETURN) ) {        if (rc >= 0) {            ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,                    "%s: %s %ld/%d bytes %s BIO#%pp [mem: %pp] %s",                    SSL_LIBRARY_NAME,                    (cmd == (BIO_CB_WRITE|BIO_CB_RETURN) ? "write" : "read"),                    rc, argi, (cmd == (BIO_CB_WRITE|BIO_CB_RETURN) ? "to" : "from"),                    bio, argp,                    (argp != NULL ? "(BIO dump follows)" : "(Oops, no memory buffer?)"));            if (argp != NULL)                ssl_io_data_dump(s, argp, rc);        }        else {            ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,                    "%s: I/O error, %d bytes expected to %s on BIO#%pp [mem: %pp]",                    SSL_LIBRARY_NAME, argi,                    (cmd == (BIO_CB_WRITE|BIO_CB_RETURN) ? "write" : "read"),                    bio, argp);        }    }    return rc;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -