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

📄 ssl_engine_io.c

📁 linux网络服务器工具
💻 C
📖 第 1 页 / 共 5 页
字号:
        }        offset += tmplen;        tmplen = buflen - offset;    }    if (pos) {        char *value;        int length;        apr_size_t bytes = pos - buf;        bytes += 1;        value = buf + bytes;        length = *len - bytes;        char_buffer_write(&inctx->cbuf, value, length);        *len = bytes;    }    return APR_SUCCESS;}static apr_status_t ssl_filter_write(ap_filter_t *f,                                     const char *data,                                     apr_size_t len){    ssl_filter_ctx_t *filter_ctx = f->ctx;    bio_filter_out_ctx_t *outctx;    int res;    /* write SSL */    if (filter_ctx->pssl == NULL) {        return APR_EGENERAL;    }    outctx = (bio_filter_out_ctx_t *)filter_ctx->pbioWrite->ptr;    res = SSL_write(filter_ctx->pssl, (unsigned char *)data, len);    if (res < 0) {        int ssl_err = SSL_get_error(filter_ctx->pssl, res);        conn_rec *c = (conn_rec*)SSL_get_app_data(outctx->filter_ctx->pssl);        if (ssl_err == SSL_ERROR_WANT_WRITE) {            /*             * If OpenSSL wants to write more, and we were nonblocking,             * report as an EAGAIN.  Otherwise loop, pushing more             * data at the network filter.             *             * (This is usually the case when the client forces an SSL             * renegotation which is handled implicitly by OpenSSL.)             */            outctx->rc = APR_EAGAIN;        }        else if (ssl_err == SSL_ERROR_SYSCALL) {            ap_log_cerror(APLOG_MARK, APLOG_INFO, outctx->rc, c,                          "SSL output filter write failed.");        }        else /* if (ssl_err == SSL_ERROR_SSL) */ {            /*             * Log SSL errors             */            ap_log_cerror(APLOG_MARK, APLOG_INFO, outctx->rc, c,                          "SSL library error %d writing data", ssl_err);            ssl_log_ssl_error(APLOG_MARK, APLOG_INFO, c->base_server);        }        if (outctx->rc == APR_SUCCESS) {            outctx->rc = APR_EGENERAL;        }    }    else if ((apr_size_t)res != len) {        conn_rec *c = f->c;        char *reason = "reason unknown";        /* XXX: probably a better way to determine this */        if (SSL_total_renegotiations(filter_ctx->pssl)) {            reason = "likely due to failed renegotiation";        }        ap_log_cerror(APLOG_MARK, APLOG_INFO, outctx->rc, c,                      "failed to write %" APR_SSIZE_T_FMT                      " of %" APR_SIZE_T_FMT " bytes (%s)",                      len - (apr_size_t)res, len, reason);        outctx->rc = APR_EGENERAL;    }    return outctx->rc;}/* Just use a simple request.  Any request will work for this, because * we use a flag in the conn_rec->conn_vector now.  The fake request just * gets the request back to the Apache core so that a response can be sent. * * To avoid calling back for more data from the socket, use an HTTP/0.9 * request, and tack on an EOS bucket. */#define HTTP_ON_HTTPS_PORT \    "GET /" CRLF#define HTTP_ON_HTTPS_PORT_BUCKET(alloc) \    apr_bucket_immortal_create(HTTP_ON_HTTPS_PORT, \                               sizeof(HTTP_ON_HTTPS_PORT) - 1, \                               alloc)static void ssl_io_filter_disable(SSLConnRec *sslconn, ap_filter_t *f){    bio_filter_in_ctx_t *inctx = f->ctx;    SSL_free(inctx->ssl);    sslconn->ssl = NULL;    inctx->ssl = NULL;    inctx->filter_ctx->pssl = NULL;}static apr_status_t ssl_io_filter_error(ap_filter_t *f,                                        apr_bucket_brigade *bb,                                        apr_status_t status){    SSLConnRec *sslconn = myConnConfig(f->c);    apr_bucket *bucket;    switch (status) {      case HTTP_BAD_REQUEST:            /* log the situation */            ap_log_cerror(APLOG_MARK, APLOG_INFO, 0, f->c,                         "SSL handshake failed: HTTP spoken on HTTPS port; "                         "trying to send HTML error page");            ssl_log_ssl_error(APLOG_MARK, APLOG_INFO, f->c->base_server);            sslconn->non_ssl_request = 1;            ssl_io_filter_disable(sslconn, f);            /* fake the request line */            bucket = HTTP_ON_HTTPS_PORT_BUCKET(f->c->bucket_alloc);            break;      default:        return status;    }    APR_BRIGADE_INSERT_TAIL(bb, bucket);    bucket = apr_bucket_eos_create(f->c->bucket_alloc);    APR_BRIGADE_INSERT_TAIL(bb, bucket);    return APR_SUCCESS;}static const char ssl_io_filter[] = "SSL/TLS Filter";static const char ssl_io_buffer[] = "SSL/TLS Buffer";/* *  Close the SSL part of the socket connection *  (called immediately _before_ the socket is closed) *  or called with */static apr_status_t ssl_filter_io_shutdown(ssl_filter_ctx_t *filter_ctx,                                           conn_rec *c,                                           int abortive){    SSL *ssl = filter_ctx->pssl;    const char *type = "";    SSLConnRec *sslconn = myConnConfig(c);    int shutdown_type;    if (!ssl) {        return APR_SUCCESS;    }    /*     * Now close the SSL layer of the connection. We've to take     * the TLSv1 standard into account here:     *     * | 7.2.1. Closure alerts     * |     * | The client and the server must share knowledge that the connection is     * | ending in order to avoid a truncation attack. Either party may     * | initiate the exchange of closing messages.     * |     * | close_notify     * |     This message notifies the recipient that the sender will not send     * |     any more messages on this connection. The session becomes     * |     unresumable if any connection is terminated without proper     * |     close_notify messages with level equal to warning.     * |     * | Either party may initiate a close by sending a close_notify alert.     * | Any data received after a closure alert is ignored.     * |     * | Each party is required to send a close_notify alert before closing     * | the write side of the connection. It is required that the other party     * | respond with a close_notify alert of its own and close down the     * | connection immediately, discarding any pending writes. It is not     * | required for the initiator of the close to wait for the responding     * | close_notify alert before closing the read side of the connection.     *     * This means we've to send a close notify message, but haven't to wait     * for the close notify of the client. Actually we cannot wait for the     * close notify of the client because some clients (including Netscape     * 4.x) don't send one, so we would hang.     */    /*     * exchange close notify messages, but allow the user     * to force the type of handshake via SetEnvIf directive     */    if (abortive) {        shutdown_type = SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN;        type = "abortive";    }    else switch (sslconn->shutdown_type) {      case SSL_SHUTDOWN_TYPE_UNCLEAN:        /* perform no close notify handshake at all           (violates the SSL/TLS standard!) */        shutdown_type = SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN;        type = "unclean";        break;      case SSL_SHUTDOWN_TYPE_ACCURATE:        /* send close notify and wait for clients close notify           (standard compliant, but usually causes connection hangs) */        shutdown_type = 0;        type = "accurate";        break;      default:        /*         * case SSL_SHUTDOWN_TYPE_UNSET:         * case SSL_SHUTDOWN_TYPE_STANDARD:         */        /* send close notify, but don't wait for clients close notify           (standard compliant and safe, so it's the DEFAULT!) */        shutdown_type = SSL_RECEIVED_SHUTDOWN;        type = "standard";        break;    }    SSL_set_shutdown(ssl, shutdown_type);    SSL_smart_shutdown(ssl);    /* and finally log the fact that we've closed the connection */    if (c->base_server->loglevel >= APLOG_INFO) {        ap_log_cerror(APLOG_MARK, APLOG_INFO, 0, c,                      "Connection closed to child %ld with %s shutdown "                      "(server %s)",                      c->id, type, ssl_util_vhostid(c->pool, c->base_server));    }    /* deallocate the SSL connection */    if (sslconn->client_cert) {        X509_free(sslconn->client_cert);        sslconn->client_cert = NULL;    }    SSL_free(ssl);    sslconn->ssl = NULL;    filter_ctx->pssl = NULL; /* so filters know we've been shutdown */    if (abortive) {        /* prevent any further I/O */        c->aborted = 1;    }    return APR_SUCCESS;}static apr_status_t ssl_io_filter_cleanup(void *data){    ssl_filter_ctx_t *filter_ctx = data;    if (filter_ctx->pssl) {        conn_rec *c = (conn_rec *)SSL_get_app_data(filter_ctx->pssl);        SSLConnRec *sslconn = myConnConfig(c);        SSL_free(filter_ctx->pssl);        sslconn->ssl = filter_ctx->pssl = NULL;    }    return APR_SUCCESS;}/* * The hook is NOT registered with ap_hook_process_connection. Instead, it is * called manually from the churn () before it tries to read any data. * There is some problem if I accept conn_rec *. Still investigating.. * Adv. if conn_rec * can be accepted is we can hook this function using the * ap_hook_process_connection hook. */static int ssl_io_filter_connect(ssl_filter_ctx_t *filter_ctx){    conn_rec *c         = (conn_rec *)SSL_get_app_data(filter_ctx->pssl);    SSLConnRec *sslconn = myConnConfig(c);    SSLSrvConfigRec *sc = mySrvConfig(c->base_server);    X509 *cert;    int n;    int ssl_err;    long verify_result;    if (SSL_is_init_finished(filter_ctx->pssl)) {        return APR_SUCCESS;    }    if (sslconn->is_proxy) {        if ((n = SSL_connect(filter_ctx->pssl)) <= 0) {            ap_log_cerror(APLOG_MARK, APLOG_INFO, 0, c,                          "SSL Proxy connect failed");            ssl_log_ssl_error(APLOG_MARK, APLOG_INFO, c->base_server);            /* ensure that the SSL structures etc are freed, etc: */            ssl_filter_io_shutdown(filter_ctx, c, 1);            return HTTP_BAD_GATEWAY;        }        return APR_SUCCESS;    }    if ((n = SSL_accept(filter_ctx->pssl)) <= 0) {        bio_filter_in_ctx_t *inctx = (bio_filter_in_ctx_t *)                                     (filter_ctx->pbioRead->ptr);        bio_filter_out_ctx_t *outctx = (bio_filter_out_ctx_t *)                                       (filter_ctx->pbioWrite->ptr);        apr_status_t rc = inctx->rc ? inctx->rc : outctx->rc ;        ssl_err = SSL_get_error(filter_ctx->pssl, n);        if (ssl_err == SSL_ERROR_ZERO_RETURN) {            /*             * The case where the connection was closed before any data             * was transferred. That's not a real error and can occur             * sporadically with some clients.             */            ap_log_cerror(APLOG_MARK, APLOG_INFO, rc, c,                         "SSL handshake stopped: connection was closed");        }        else if (ssl_err == SSL_ERROR_WANT_READ) {            /*             * This is in addition to what was present earlier. It is             * borrowed from openssl_state_machine.c [mod_tls].             * TBD.             */            outctx->rc = APR_EAGAIN;            return SSL_ERROR_WANT_READ;        }        else if (ERR_GET_LIB(ERR_peek_error()) == ERR_LIB_SSL &&                 ERR_GET_REASON(ERR_peek_error()) == SSL_R_HTTP_REQUEST) {            /*             * The case where OpenSSL has recognized a HTTP request:             * This means the client speaks plain HTTP on our HTTPS port.             * ssl_io_filter_error will disable the ssl filters when it             * sees this status code.             */            return HTTP_BAD_REQUEST;        }        else if (ssl_err == SSL_ERROR_SYSCALL) {            ap_log_cerror(APLOG_MARK, APLOG_INFO, rc, c,                          "SSL handshake interrupted by system "                          "[Hint: Stop button pressed in browser?!]");        }        else /* if (ssl_err == SSL_ERROR_SSL) */ {            /*             * Log SSL errors and any unexpected conditions.             */            ap_log_cerror(APLOG_MARK, APLOG_INFO, rc, c,                          "SSL library error %d in handshake "                          "(server %s)", ssl_err,                          ssl_util_vhostid(c->pool, c->base_server));            ssl_log_ssl_error(APLOG_MARK, APLOG_INFO, c->base_server);        }        if (inctx->rc == APR_SUCCESS) {            inctx->rc = APR_EGENERAL;        }        return ssl_filter_io_shutdown(filter_ctx, c, 1);    }

⌨️ 快捷键说明

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