Yellow-Camper / libevhtp

Create extremely-fast and secure embedded HTTP servers with ease.
https://criticalstack.com/
BSD 3-Clause "New" or "Revised" License
426 stars 162 forks source link

Invalid content length value results in empty response #161

Open jk-valentine opened 3 years ago

jk-valentine commented 3 years ago

Details

I've been unable to elicit an http response from evhtp when the parser hits an error on invalid content length value and exits prematurely without consuming all input. I'm not sure if this indicates a bug or if I simply haven't found the correct way to achieve what I'd like.

Steps or code to reproduce the problem.

$ examples/test_basic $ curl -H "Content-Length:x" http://127.0.0.1:8081/simple/ curl: (52) Empty reply from server

It looks like the parser exits early when str_to_uint64 fails (parser.c:1789):

                            case eval_hdr_val_content_length:
                                p->content_len      = str_to_uint64(p->buf, p->buf_idx, &err);
                                p->orig_content_len = p->content_len;

                                log_debug("[%p] s_hdrline_hdr_val content-lenth = %zu", p, p->content_len);

                                if (err == 1)
                                {
                                    p->error = htparse_error_too_big;
                                    return i + 1;
                                }

and htp__connectionreadcb bails out:

    } else if (htparser_get_error(c->parser) != htparse_error_none) {
        log_debug("error %d, freeing connection",
            htparser_get_error(c->parser));

        evhtp_safe_free(c, evhtp_connection_free);

I've tried working around this by hooking evhtp_connection_free via htp__hook_connectionfini:

    if ( htparser_get_error(conn->parser) == htparse_error_too_big ) {
        if ( conn->request->conn ) {
            MDSV_Log((reinterpret_cast<CMAE_HTTP_Server *>(arg))->Adapter(), MDSV_LOG_WARNING, "%s", "htparse error");
            // TODO: determine why this response is not being sent
            //evhtp_send_reply(conn->request, EVHTP_RES_400);
            struct evbuffer * buf = evbuffer_new();
            const char response[] = "HTTP/1.1 411 Length Required\r\n";
            evhtp_header_t *h1 = evhtp_header_new("Content-Type", "text/plain", 0, 1);
            evhtp_header_t *h2 = evhtp_header_new("Content-Length", 0, 0, 1);
            evhtp_headers_add_header(conn->request->headers_out, h1);
            evhtp_headers_add_header(conn->request->headers_out, h2);
            evbuffer_add( buf, (void *)response, sizeof(response) );
            evbuffer_add( conn->request->buffer_out, (void *)response, sizeof(response) );
            evhtp_send_reply_body( conn->request, buf );
            evhtp_send_reply_end( conn->request );
        }

but no dice. I see my log message but still get no http response.

Version

1.2.18