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

📄 ssl_engine_io.c

📁 Apache HTTP Server 是一个功能强大的灵活的与HTTP/1.1相兼容的web服务器.这里给出的是Apache HTTP服务器的源码。
💻 C
📖 第 1 页 / 共 4 页
字号:
    /*     * Remember the peer certificate's DN     */    if ((cert = SSL_get_peer_certificate(filter_ctx->pssl))) {        if (sslconn->client_cert) {            X509_free(sslconn->client_cert);        }        sslconn->client_cert = cert;        sslconn->client_dn = NULL;    }    /*     * Make really sure that when a peer certificate     * is required we really got one... (be paranoid)     */    if ((sc->server->auth.verify_mode == SSL_CVERIFY_REQUIRE) &&        !sslconn->client_cert)    {        ap_log_error(APLOG_MARK, APLOG_INFO, 0, c->base_server,                     "No acceptable peer certificate available");        return ssl_filter_io_shutdown(filter_ctx, c, 1);    }    return APR_SUCCESS;}static apr_status_t ssl_io_filter_input(ap_filter_t *f,                                        apr_bucket_brigade *bb,                                        ap_input_mode_t mode,                                        apr_read_type_e block,                                        apr_off_t readbytes){    apr_status_t status;    bio_filter_in_ctx_t *inctx = f->ctx;    apr_size_t len = sizeof(inctx->buffer);    int is_init = (mode == AP_MODE_INIT);    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);        APR_BRIGADE_INSERT_TAIL(bb, bucket);        return APR_ECONNABORTED;    }    if (!inctx->ssl) {        return ap_get_brigade(f->next, bb, mode, block, readbytes);    }    /* XXX: we don't currently support anything other than these modes. */    if (mode != AP_MODE_READBYTES && mode != AP_MODE_GETLINE &&         mode != AP_MODE_SPECULATIVE && mode != AP_MODE_INIT) {        return APR_ENOTIMPL;    }    inctx->mode = mode;    inctx->block = block;    /* XXX: we could actually move ssl_io_filter_connect 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_connect(inctx->filter_ctx)) != APR_SUCCESS) {        return ssl_io_filter_error(f, bb, status);    }    if (is_init) {        /* protocol module needs to handshake before sending         * data to client (e.g. NNTP or FTP)         */        return APR_SUCCESS;    }    if (inctx->mode == AP_MODE_READBYTES ||         inctx->mode == AP_MODE_SPECULATIVE) {        /* Protected from truncation, readbytes < MAX_SIZE_T          * FIXME: No, it's *not* protected.  -- jre */        if (readbytes < len) {            len = (apr_size_t)readbytes;        }        status = ssl_io_input_read(inctx, inctx->buffer, &len);    }    else if (inctx->mode == AP_MODE_GETLINE) {        status = ssl_io_input_getline(inctx, inctx->buffer, &len);    }    else {        /* We have no idea what you are talking about, so return an error. */        return APR_ENOTIMPL;    }    if (status != APR_SUCCESS) {        return ssl_io_filter_error(f, bb, status);    }    /* Create a transient bucket out of the decrypted data. */    if (len > 0) {        apr_bucket *bucket =            apr_bucket_transient_create(inctx->buffer, len, f->c->bucket_alloc);        APR_BRIGADE_INSERT_TAIL(bb, bucket);    }    return APR_SUCCESS;}static apr_status_t ssl_io_filter_output(ap_filter_t *f,                                         apr_bucket_brigade *bb){    apr_status_t status = APR_SUCCESS;    ssl_filter_ctx_t *filter_ctx = f->ctx;    bio_filter_in_ctx_t *inctx;    bio_filter_out_ctx_t *outctx;    apr_read_type_e rblock = APR_NONBLOCK_READ;    if (f->c->aborted) {        apr_brigade_cleanup(bb);        return APR_ECONNABORTED;    }    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_error(APLOG_MARK, APLOG_INFO, status, NULL,                             "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;}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->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){    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);    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 + -