480 Commits

Author SHA1 Message Date
Azat Khuzhin
8feed7f165
http: forbid chunks size with 0X prefix
Co-authored-by: Ben Kallus <49924171+kenballus@users.noreply.github.com>
2024-02-18 19:26:47 +01:00
Azat Khuzhin
87cdcc1868 http: change error for corrupted requests to 400 Bad Request
Previously it was 413 Request Entity Too Large, which was odd.
2024-02-18 17:02:45 +01:00
Azat Khuzhin
f1632e5909 http: check first byte of the chunk for 0x as well 2024-02-18 17:02:45 +01:00
Ben Kallus
92ea8476b4
Forbid 0x/+/-/whitespace prefixes on HTTP chunk sizes (#1542)
Currently, libevent's HTTP parser accepts and ignores 0x, +, and whitespace prefixes on chunk sizes. It also ignores - prefixes on chunk sizes of 0. This patch fixes that.

There is a potential danger in the current behavior, which is that there exist HTTP implementations that interpret chunk sizes as their longest valid prefix. For those implementations, 0xa (for example) is equivalent to 0, and this may present a request smuggling risk when those implementations are used in conjunction with libevent. However, as far I'm aware, there is no HTTP proxy that both interprets 0xa as 0 and forwards it verbatim, so I think this is a low-risk bug that is acceptable to report in public.
2024-02-18 14:56:46 +01:00
Ben Kallus
665d79f176
Fix integer overflow in HTTP version (#1541)
Currently, when libevent parses requests with version `HTTP/4294967295.255`, you end up with `req->major == req->minor == (char)-1`. (At least on linux-gnu-x86_64, where `char` is signed.)

This is sort of weird.

This patch changes the version parser to match the grammar in RFCs 7230 and 9112. (i.e. `HTTP/[0-9].[0-9]`)

EDIT: Technically, a little stronger than the RFC requires, since this patch continues to block major versions greater than 1, which was already what libevent was doing.
2024-01-19 00:42:52 +03:00
Andy Pan
7658b78853
Implement full support of TCP Keep-Alives across most Unix-like OS's (#1532)
Default settings of TCP keep-alive are not always feasible,
take Linux for example, the duration a connection needs to be
idle before sending out the first keep-alive probe is two hours,
which makes detecting dead connections extremely deferred. Thus,
enabling TCP keep-alive will be to little avail.

This sets TCP_KEEPIDLE, TCP_KEEPINTVL, and TCP_KEEPCNT when enabling TCP
keep-alive mechanism to make it practicable.
2024-01-05 19:52:43 +03:00
Sam James
4c38de8cb3
Fix -Walloc-size (#1526)
Co-authored-by: Azat Khuzhin <azat@libevent.org>
2023-11-26 21:52:32 +01:00
Liao Tonglang
9203d98ff8
http: style fix: use space between arguments list (#1435) 2023-03-26 22:35:00 +02:00
Liao Tonglang
6bfa580559
http: Reduce times of checking if response has body (#1395)
Use a variable 'need_body' to store the result of
evhttp_response_needs_body(), then use the variable instead of call the function again.
2023-03-05 16:59:21 +01:00
Cœur
3bcc92cf59 Fix the value is never actually read from 'argument' in evhttp_parse_query_impl()
Although the value stored to 'argument' is used in the enclosing
expression, the value is never actually read from 'argument'
2023-03-02 07:32:17 +01:00
Leon George
3ec3b469b8
ws: fix compile error on centos 7 - very old compiler (#1359)
* http: fix typo

* ws: fix comile error

On CentOS:

  CC       ws.lo
ws.c: In function 'get_ws_frame':
ws.c:244:3: error: 'for' loop initial declarations are only allowed in C99 mode
   for (int i = 0; i < payload_len; i++) {
   ^
ws.c:244:3: note: use option -std=c99 or -std=gnu99 to compile your code
2022-10-23 14:47:23 +03:00
Dmitry Ilyin
e8313084f9
Add minimal WebSocket server implementation for evhttp (#1322)
This adds few functions to use evhttp-based webserver to handle incoming
WebSockets connections. We've tried to use both libevent and libwebsockets in
our application, but found that we need to have different ports at the same
time to handle standard HTTP and WebSockets traffic. This change can help to
stick only with libevent library.

Implementation was inspired by modified Libevent source code in ipush project
[1].

  [1]: https://github.com/sqfasd/ipush/tree/master/deps/libevent-2.0.21-stable

Also, WebSocket-based chat server was added as a sample.
2022-09-12 22:16:56 +03:00
mareksm
b19af675c7
Fix non-std printf %p arguments (#1327)
* Fix non-std printf %p arguments when running with -Werror -pedantic-errors

Co-authored-by: Mareks Malnacs <mareks.malnacs>
2022-08-28 15:27:04 +03:00
Leon M. George
1bdc91350e http: allow setting bevcb per socket
Co-authored-by: Azat Khuzhin <azat@libevent.org>
v2: remove handling of HTTP_BIND_IPV6
2022-08-13 20:12:18 +02:00
Azat Khuzhin
c8501afc0c http: suppress "flags may be used uninitialized in this function" error
Some GCC reports [1]:

    /home/runner/work/libevent/libevent/http.c: In function ‘evhttp_make_header’:
    /home/runner/work/libevent/libevent/http.c:503:14: error: ‘flags’ may be used uninitialized in this function [-Werror=maybe-uninitialized]
      ev_uint16_t flags;
                  ^~~~~
    /home/runner/work/libevent/libevent/http.c: In function ‘evhttp_get_body’:
    /home/runner/work/libevent/libevent/http.c:2354:14: error: ‘flags’ may be used uninitialized in this function [-Werror=maybe-uninitialized]
      ev_uint16_t flags;
                  ^~~~~
  [1]: https://github.com/libevent/libevent/runs/7263518338?check_suite_focus=true#logs
2022-07-09 17:36:13 +03:00
Azat Khuzhin
2b92b830a7 http: fix building under windows (guard with _WIN32 for unixsocket free)
Reported-by: @kaend
2021-08-12 01:40:46 +03:00
Sean Young
f446229b22 http: support unix domain sockets
There are no standard for encoding a unix socket in an url. nginx uses:

    http://unix:/path/to/unix/socket:/httppath

The second colon is needed to delimit where the unix path ends and where
the rest of the url continues.

Signed-off-by: Sean Young <sean@mess.org>
2021-08-10 23:22:10 +03:00
Azat Khuzhin
2385638edf http: fix fd leak on fd reset (by using bufferevent_replacefd())
Fixes: afa66ea4 ("http: eliminate redundant bev fd manipulating and caching [WIP]")
2021-03-23 09:06:58 +03:00
ihsinme
d13b7bbfcf http: fix invalid unsigned arithmetic 2021-02-11 21:14:42 +03:00
Azat Khuzhin
afa66ea420 http: eliminate redundant bev fd manipulating and caching [WIP]
At the very beginning we reset the bufferevent fd (if bev has it), which
is not a good idea, since if user passes bufferevent with existing fd he
has some intention.

So we need to:
- use BEV_OPT_CLOSE_ON_FREE for default bufferevent_socket_new() (to
  avoid manual shutdown/closee)
- drop getsockopt(SOL_SOCKET, SO_ERROR), since bufferevent already has
  evutil_socket_finished_connecting_()
- drop supperior bufferevent_setfd(bev, -1) in
  evhttp_connection_connect_()

Closes: #795
Refs: #875
2020-10-31 21:34:02 +03:00
Azat Khuzhin
e91c436388 http: add EVHTTP_URI_HOST_STRIP_BRACKETS
Refs: #1115
2020-10-27 02:13:21 +03:00
Leon M. George
a18301a2bb http: const out address param to evcon_get_peer 2020-09-09 00:37:17 +03:00
Azat Khuzhin
4528d8e987 Check error code of evhttp_add_header_internal() in evhttp_parse_query_impl() 2020-06-25 09:41:54 +03:00
Azat Khuzhin
7426a568d0 http: Merge branch 'http-max_connections-pr-592'
@jcoffland:

  "When the max connection limit is enabled and the limit is reached, the
   server will respond immediately with 503 Service Unavailable. This can
   be used to prevent servers from running out of file descriptors. This is
   better than request limiting because clients may make more than one
   request over a single connection. Blocking a request does not
   necessarily close the connection and free up a socket."

* http-max_connections-pr-592:
  test: cover evhttp max connections
  Added evhttp max simultaneous connection limiting
2020-05-25 11:25:18 +03:00
Azat Khuzhin
eee26deed3 http: fix EVHTTP_CON_AUTOFREE in case of timeout (and some else)
Refs: #182
2020-05-19 11:46:21 +03:00
Azat Khuzhin
083c6d54d5 http: fix EVHTTP_CON_AUTOFREE in case of connection error
Refs: #182
2020-05-19 01:06:12 +03:00
nntrab
02905413fd Add callback support for error pages
The existing error pages are very basic and don't allow for
multi-lingual support or for conformity with other pages in a web site.
The aim of the callback functionality is to allow custom error pages to
be supported for calls to evhttp_send_error() by both calling
applications and Libevent itself.

A backward-incompatible change has been made to the title of error pages
sent by evhttp_send_error(). The original version of the function used
the reason argument as part of the title. That might have unforeseen
side-effects if it contains HTML tags. Therefore the title has been
changed to always use the standard status text.

An example of the error callback can be found in this
[version](https://github.com/libevent/libevent/files/123607/http-server.zip)
of the 'http-server' sample. It will output error pages with very bright
backgrounds, the error code using a very large font size and the reason.

Closes: #323 (cherr-picked from PR)
2020-01-13 00:50:14 +03:00
Azat Khuzhin
12ad0c8fcd http: do not close connection for CONNECT 2020-01-12 15:34:01 +03:00
Azat Khuzhin
998e68340e http: do not assume body for CONNECT 2020-01-12 15:33:59 +03:00
yuangongji
0cd536b0b3
http: rename bind_socket_ai() to create_bind_socket_nonblock() 2019-09-18 23:13:34 +03:00
yuangongji
1c78451f0d
http: make sure the other fields in ext_method are not changed by the callback 2019-09-18 23:12:56 +03:00
Azat Khuzhin
1c573ab3a9
http: do not name variable "sun" since this breaks solaris builds
-bash-3.2$ /opt/csw/bin/gcc -xc /dev/null -dM -E | grep '#define sun'
  #define sun 1
2019-05-25 23:41:38 +03:00
Azat Khuzhin
ad51a3c1ba
http: avoid use of uninitialized value for AF_UNIX/AF_LOCAL sockaddr
unixsock peer does not have sun_path initialized.
2019-05-12 18:21:21 +03:00
Thomas Bernard
8dcb94a4ca
Added http method extending
User can define his own response method by calling
evhttp_set_ext_method_cmp() on the struct http, or
evhttp_connection_set_ext_method_cmp() on the connection.

We expose a new stucture `evhttp_ext_method` which is passed to the
callback if it's set. So any field can be modified, with some exceptions
(in evhttp_method_):

If the cmp function is set, it has the ability to modify method, and
flags. Other fields will be ignored. Flags returned are OR'd with the
current flags.

Based on changes to the #282 from: Mark Ellzey <socket@gmail.com>
2019-04-11 22:48:01 +03:00
Thomas Bernard
96e56beb94
http: Update allowed_methods field from 16 to 32bits. 2019-04-11 22:47:55 +03:00
Azat Khuzhin
799053db8a
http: replace EVHTTP_REQ_UNKNOWN_ with 0
From the server perspective the evhttp_response_phrase_internal() should
not be called with 0 before this patch, it will be called with
EVHTTP_REQ_UNKNOWN_ hence this patch should not change behavior.

Fixes: 68eb526d7b ("http: add WebDAV methods support")
Fixes: #789
Fixes: #796
Reported-by: Thomas Bernard <miniupnp@free.fr>
2019-04-10 00:51:27 +03:00
Alexander Drozdov
68eb526d7b http: add WebDAV methods support
WebDAV introduced new HTTP methods (RFC4918):
PROPFIND, PROPPATCH, MKCOL, LOCK, UNLOCK, COPY, MOVE.

Add support of the methods.
2019-03-14 11:12:46 +03:00
Azat Khuzhin
bf19462a55
http: suppress -Wwrite-string in evhttp_parse_query_impl() 2019-03-13 00:21:38 +03:00
Azat Khuzhin
5ee507c889
http: implement separate timeouts for read/write/connect phase
This patch allows to change timeout for next events read/write/connect
separatelly, using new API:

- client:
  evhttp_connection_set_connect_timeout_tv() -- for connect
  evhttp_connection_set_read_timeout_tv()    -- for read
  evhttp_connection_set_write_timeout_tv()   -- for write

- server:
  evhttp_set_read_timeout_tv()  -- for read
  evhttp_set_write_timeout_tv() -- for write

It also changes a logic a little, before there was next fallbacks which
does not handled in new API:
- HTTP_CONNECT_TIMEOUT
- HTTP_WRITE_TIMEOUT
- HTTP_READ_TIMEOUT

And introduce another internal flag (EVHTTP_CON_TIMEOUT_ADJUSTED) that
will be used in evrpc, which adjust evhttp_connection timeout only if it
is not default.

Fixes: #692
Fixes: #715
2019-03-05 00:33:46 +03:00
Azat Khuzhin
30791eccce
http: try to read existing data in buffer under EVHTTP_CON_READ_ON_WRITE_ERROR
There are two possible ways of getting response from the server:
- processing existing bufferevent buffer
- reading from the socket (even after write() errored with -1, it is
still possible)

But we did not tried the first option, only the second one.

Fixes: http/read_on_write_error (on freebsd/osx)
2019-01-29 01:16:48 +03:00
Azat Khuzhin
d3dcb5aca9
http: do not call deferred readcb if readcb is not set
Otherwise evhttp_read_cb can be called with invalid connection state:
    http/read_on_write_error: [forking] [msg] libevent using: kqueue
      FAIL ../test/regress_http.c:4079: assert(req)
      FAIL ../test/regress_http.c:4087: assert(req)[err] evhttp_read_cb: illegal connection state 0
2019-01-28 22:20:47 +03:00
Luke Dashjr
28d7221b85
http: Preserve socket error from listen across closesocket cleanup
Closes: #738 (cherry-picked)
2019-01-07 15:22:39 +03:00
Azat Khuzhin
f3f7aa5aff
http: fix connection retries when there more then one request for connection
We should not attemp to establishe the connection if there is retry
timer active, since otherwise there will be a bug.

Imagine next situation:
  con = evhttp_connection_base_new()
  evhttp_connection_set_retries(con, 2)
  req = evhttp_request_new()
  evhttp_make_request(con, req, ...)
  # failed during connecting, and timer for 2 second scheduler (retry_ev)

Then another request scheduled for this evcon:
  evhttp_make_request(con, req, ...)
  # got request from server,
  # and now it tries to read the response from the server
  # (req.kind == EVHTTP_RESPONSE)
  #
  # but at this point retry_ev scheduled,
  # and it schedules the connect again,
  # and after the connect will succeeed, it will pick request with
  # EVHTTP_RESPONSE for sending and this is completelly wrong and will
  # fail in evhttp_make_header_response() since there is no
  # "http_server" for this evcon

This was a long standing issue, that I came across few years ago
firstly, bad only now I had time to dig into it (but right now it was
pretty simple, by limiting amount of CPU for the process and using rr
for debug to go back and forth).
2018-12-12 21:46:27 +03:00
Azat Khuzhin
b98d32d0c9
http: improve error path for bufferevent_{setfd,enable,disable}()
We have calls to the next functions but do not check return values,
though they can be invalid and it is better to show this somehow.

Also do bufferevent_setfd() first and only after it
bufferevent_enable()/bufferevent_disable() since:
a) it is more natural
b) it will avoid extra operations
c) it will not fail first bufferevent_enable() (this is the case for
   buffbufferevent_async at least)

In this case we could add more information for issues like #709
2018-11-20 06:22:31 +03:00
Azat Khuzhin
5dc88b387f
Fix conceivable UAF of the bufferevent in evhttp_connection_free()
Although this is not a problem, since bufferevent uses finalizers and
will free itself only from the loop (well this is not a problem if you
do not play games with various event_base in different threads) it
generates questions, so rewrite it in more reliable way.

Fixes: #712
2018-11-13 22:26:12 +03:00
Azat Khuzhin
26ef859aa7
Add evhttp_parse_query_str_flags()
And a set of flags:
- EVHTTP_URI_QUERY_LAST
- EVHTTP_URI_QUERY_NONCONFORMANT

Fixes: #15
2018-10-27 17:59:11 +03:00
Azat Khuzhin
b94d913d90
http: allow non RFC3986 conformant during parsing request-line (http server)
Reported-by: lsdyst@163.com
2018-10-23 00:12:03 +03:00
Azat Khuzhin
64ead341a0
http: do not try to parse request-line if we do not have enough bytes 2018-10-22 23:56:50 +03:00
Azat Khuzhin
254fbc81b4
http: allow trailing spaces (and only them) in request-line (like nginx) 2018-10-22 23:56:31 +03:00
Azat Khuzhin
6cf659b0bd
http: cleanup of the request-line parsing 2018-10-22 23:55:35 +03:00