Esempio n. 1
0
ib_parsed_name_value_pair_list_wrapper_t* make_pnv_list(
    Transaction transaction,
    Iterator    begin,
    Iterator    end
)
{
    ib_parsed_name_value_pair_list_wrapper_t* ib_pnv_list;
    throw_if_error(
        ib_parsed_name_value_pair_list_wrapper_create(
            &ib_pnv_list,
            transaction.ib()
        )
    );

    BOOST_FOREACH(
        ParsedNameValue pnv,
        std::make_pair(begin, end)
    ) {
        // This will reconstruct the bytestrings but not copy the data.
        // The C API is currently asymmetric: named values are consumed as
        // structures but added to list as members.  IronBee++ hides that
        // asymmetry.
        throw_if_error(
            ib_parsed_name_value_pair_list_add(
                ib_pnv_list,
                pnv.name().const_data(),
                pnv.name().length(),
                pnv.value().const_data(),
                pnv.value().length()
            )
        );
    }
Esempio n. 2
0
/**
 * nginx post-read-request handler to feed request line and headers to Ironbee.
 *
 * @param[in]  r     The nginx request object.
 * @return     Declined (ignoreme) or error status.
 */
static ngx_int_t ironbee_post_read_request(ngx_http_request_t *r)
{
    ngx_log_t *prev_log;
    ngxib_req_ctx *ctx;
    ib_conn_t *iconn;
    ib_parsed_req_line_t *rline;
    ib_parsed_header_wrapper_t *ibhdrs;
    ib_status_t rc;

    ngx_list_part_t *part;
    ngx_table_elt_t *hdr;
    unsigned int i;

    /* Don't process internal requests */
    if (r->internal)
        return NGX_DECLINED;

    prev_log = ngxib_log(r->connection->log);
    ngx_regex_malloc_init(r->pool);

    ctx = ngx_pcalloc(r->pool, sizeof(ngxib_req_ctx));
    ctx->r = r;
    ngx_http_set_ctx(r, ctx, ngx_ironbee_module);

    iconn = ngxib_conn_get(ctx, ironbee);

    ib_tx_create(&ctx->tx, iconn, ctx);

    /* Notify Ironbee of request line and headers */
    rc = ib_parsed_req_line_create(ctx->tx, &rline,
                                   (const char*)r->request_line.data,
                                   r->request_line.len,
                                   (const char*)r->method_name.data,
                                   r->method_name.len,
                                   (const char*)r->unparsed_uri.data,
                                   r->unparsed_uri.len,
                                   (const char*)r->http_protocol.data,
                                   r->http_protocol.len);
    if (rc != IB_OK)
        cleanup_return(prev_log) NGX_ERROR;

    ib_state_notify_request_started(ironbee, ctx->tx, rline);

    rc = ib_parsed_name_value_pair_list_wrapper_create(&ibhdrs, ctx->tx);
    if (rc != IB_OK)
        cleanup_return(prev_log) NGX_ERROR;

    for (part = &r->headers_in.headers.part; part != NULL; part = part->next) {
        hdr = part->elts;
        for (i = 0; i < part->nelts; ++i) {
            ib_parsed_name_value_pair_list_add(ibhdrs,
                                               (const char*)hdr->key.data,
                                               hdr->key.len,
                                               (const char*)hdr->value.data,
                                               hdr->value.len);
            ++hdr;
        }
    }

    rc = ib_state_notify_request_header_data(ironbee, ctx->tx, ibhdrs);
    if (rc != IB_OK)
        cleanup_return(prev_log) NGX_ERROR;

    rc = ib_state_notify_request_header_finished(ironbee, ctx->tx);
    if (rc != IB_OK)
        cleanup_return(prev_log) NGX_ERROR;

    if (!ngxib_has_request_body(r, ctx)) {
        rc = ib_state_notify_request_finished(ironbee, ctx->tx);
        if (rc != IB_OK)
            cleanup_return(prev_log) NGX_ERROR;
    }
    ctx->hdrs_in = 1;
    if (STATUS_IS_ERROR(ctx->status)) {
        ctx->internal_errordoc = 1;
        cleanup_return(prev_log) ctx->status;
    }

    cleanup_return(prev_log) NGX_DECLINED;
}
Esempio n. 3
0
/**
 * A header filter to intercept response line and headers and feed to Ironbee.
 *
 * @param[in]  r     The nginx request object.
 * @return     status propagated from next filter, or Error
 */
static ngx_int_t ironbee_headers_out(ngx_http_request_t *r)
{
    ngx_log_t *prev_log;
    ngxib_req_ctx *ctx;
    ib_parsed_resp_line_t *rline;
    ib_parsed_header_wrapper_t *ibhdrs;
    ib_status_t rc;

    ngx_list_part_t *part;
    ngx_table_elt_t *hdr;
    unsigned int i;
    char proto[12];
    char *status;
    const char *reason;
    int status_len, reason_len;

    /* FIXME: needs more logic here to catch error pages */
    if (r->internal)
        return ngx_http_next_header_filter(r);

    ctx = ngx_http_get_module_ctx(r, ngx_ironbee_module);
    assert((ctx != NULL) && (ctx->tx != NULL));

    prev_log = ngxib_log(r->connection->log);
    ngx_regex_malloc_init(r->pool);

    /* Notify Ironbee of request line and headers */
    sprintf(proto, "HTTP/%d.%d", r->http_major, r->http_minor);
    if (r->headers_out.status_line.len) {
        status = (char*)r->headers_out.status_line.data;
        status_len = strcspn(status, " \t");
        for (reason = status+status_len; isspace(*reason); ++reason);
        reason_len = r->headers_out.status_line.len - (reason-status);
    }
    else if (r->headers_out.status >= 100 && r->headers_out.status < 600) {
        status = ngx_palloc(r->pool, 4);
        /* cast to int, because ngx_int_t requires different format args
         * on different platforms.  We're already limited to 3-digit numbers.
         */
        sprintf(status, "%d", (int)r->headers_out.status);
        status_len = 3;
        reason = "";
        reason_len = 0;
    }
    else {
        ib_log_error_tx(ctx->tx, "Ironbee: bogus response status %d",
                        (int)r->headers_out.status);
        cleanup_return(prev_log) NGX_ERROR;
    }
    rc = ib_parsed_resp_line_create(ctx->tx, &rline, NULL, 0,
                                    proto, strlen(proto),
                                    status, status_len,
                                    reason, reason_len);
    if (rc != IB_OK)
        cleanup_return(prev_log) NGX_ERROR;

    ib_state_notify_response_started(ironbee, ctx->tx, rline);

    rc = ib_parsed_name_value_pair_list_wrapper_create(&ibhdrs, ctx->tx);
    if (rc != IB_OK)
        cleanup_return(prev_log) NGX_ERROR;

    for (part = &r->headers_out.headers.part; part != NULL; part = part->next) {
        hdr = part->elts;
        for (i = 0; i < part->nelts; ++i) {
            ib_parsed_name_value_pair_list_add(ibhdrs,
                                               (const char*)hdr->key.data,
                                               hdr->key.len,
                                               (const char*)hdr->value.data,
                                               hdr->value.len);
            ++hdr;
        }
    }

    /* Ironbee currently crashes if called here with no headers,
     * even perfectly correctly on a 204/304 response.
     */
    if (ibhdrs->size > 0) {
        rc = ib_state_notify_response_header_data(ironbee, ctx->tx, ibhdrs);
        if (rc != IB_OK)
            cleanup_return(prev_log) NGX_ERROR;
    }

    rc = ib_state_notify_response_header_finished(ironbee, ctx->tx);
    if (rc != IB_OK)
        cleanup_return(prev_log) NGX_ERROR;

    ctx->hdrs_out = 1;

    cleanup_return(prev_log) ngx_http_next_header_filter(r);
}