10599 Commits

Author SHA1 Message Date
Christopher Faulet
6112391f81 BUG/MEDIUM: cache: Be sure to end the forwarding when XFER length is unknown
This bug exists in the HTX code and in the legacy one. When the body length is
unknown, the applet hangs. For the legacy code, it hangs because the end of the
cached object is not correctly handled and the applet is never recalled. For the
HTX code, only the begining of the response (the 1st buffer) is sent then the
applet hangs. To work in HTX, The fast forwarding must be correctly handled.

This patch must be backported to 1.9.

[cf: the patch adding the function channel_add_input must be backported with
this one. It does not exist in 1.8 because only responses with a C-L are cached.]
2019-01-02 20:12:49 +01:00
Christopher Faulet
5adbeeb336 MINOR: stats/htx: Call channel_add_input instead of updating channel state by hand
This way we are sure the channel state is always correctly upadated, especially
the amount of data directly forwarded. For the stats applet, it is not a bug
because the fast forwarding is never used (the response is chunked and the HTX
extra field is always set to 0).

This patch must be backported to 1.9.
2019-01-02 20:12:47 +01:00
Christopher Faulet
e64582929f MINOR: channel: Add the function channel_add_input
This function must be called when new incoming data are pushed in the channel's
buffer. It updates the channel state and take care of the fast forwarding by
consuming right amount of data and decrementing "->to_forward" accordingly when
necessary. In fact, this patch just moves a part of ci_putblk in a dedicated
function.

This patch must be backported to 1.9.
2019-01-02 20:12:44 +01:00
Willy Tarreau
b1d7b700bb BUG/MEDIUM: log: don't mark log FDs as non-blocking on terminals
With the new ability to log to a terminal, it's convenient to be able
to use "log stdout" in a config file, except that it now results in
setting the terminal to non-blocking mode, breaking every utility
relying on stdin afterwards. Since the only reason for logging to a
terminal is to debug, do not set the FD to non-blocking mode when it's
a terminal.

This fix must be backported to 1.9.
2019-01-02 20:12:02 +01:00
Alex Zorin
4afdd13842 MINOR: payload: add sample fetch for TLS ALPN
Application-Layer Protocol Negotiation (ALPN, RFC7301) is a TLS
extension which allows a client to present a preference for which
protocols it wishes to connect to, when a single port supports multiple
multiple application protocols.
It allows a transparent proxy to take a decision based on the beginning
of an SSL/TLS stream without deciphering it.

The new fetch "req.ssl_alpn" extracts the ALPN protocol names that may
be present in the ClientHello message.
2019-01-01 09:15:01 +01:00
Olivier Houchard
a2dbeb22fc MEDIUM: sessions: Keep track of which connections are idle.
Instead of keeping track of the number of connections we're responsible for,
keep track of the number of connections we're responsible for that we are
currently considering idling (ie that we are not using, they may be in use
by other sessions), that way we can actually reuse connections when we have
more connections than the max configured.
2018-12-28 19:16:03 +01:00
Olivier Houchard
c685d700fd MEDIUM: servers: Be smarter when switching connections.
When connecting to a server, and reusing a connection, always attempt to give
the owner of the previous session one of its own connections, so that one
session won't be responsible for too many connections.

This should be backported to 1.9.
2018-12-28 16:34:03 +01:00
Olivier Houchard
4f41751ad2 BUG/MEDIUM: servers: Flag the stream_interface on handshake error.
When creating a new outgoing connection, if we're using ALPN and waiting
for the handshake completion to choose the mux, and for some reason the
handshake failed, add the SI_FL_ERR flag to the stream_interface, so that
process_streams() knows the connection failed, and can attempt to retry,
instead of just hanging.

This should be backported to 1.9.
2018-12-28 16:33:22 +01:00
Olivier Houchard
351411facd BUG/MAJOR: sessions: Use an unlimited number of servers for the conn list.
When a session adds a connection to its connection list, we used to remove
connections for an another server if there were not enough room for our
server. This can't work, because those lists are now the list of connections
we're responsible for, not just the idle connections.
To fix this, allow for an unlimited number of servers, instead of using
an array, we're now using a linked list.
2018-12-28 16:33:13 +01:00
Olivier Houchard
5f7de56a08 BUG/MAJOR: servers: Correctly use LIST_ELEM().
To access the first element of the list, correctly use LIST_ELEM(), or we
end up getting the head of the list, instead of getting the first connection.

This should be backported to 1.9.
2018-12-28 16:33:06 +01:00
Olivier Houchard
c3fa638b4c BUG/MAJOR: servers: Use the list api correctly to avoid crashes.
In connect_server(), if we looked for an usable connection and failed to
find one, srv_conn won't be NULL at the end of list_for_each_entry(), but
will point to the head of a list, which is not a pointer to a struct
connection, so explicitely set it to NULL.

This should be backported to 1.9.
2018-12-28 16:33:00 +01:00
Olivier Houchard
134a2045bb BUG/MEDIUM: servers: Fail if we fail to allocate a conn_stream.
If, for some reason we failed to allocate a conn_stream when reusing an
existing connection, set srv_conn to NULL, so that we fail later, instead
of pretending all is right. This ends up giving a stream_interface with
no endpoint, and so the stream will never end.

This should be backported to 1.9.
2018-12-28 15:49:24 +01:00
Olivier Houchard
855ac25d82 BUG/MEDIUM: mux_h2: Don't add to the idle list if we're full.
In h2_detach(), don't add the connection to the idle list if nb_streams
is at the max. This can happen if we already closed that stream before, so
its slot became available and was used by another stream.

This should be backported to 1.9.
2018-12-28 15:48:52 +01:00
Jérôme Magnin
86cef23266 BUG/MINOR: htx: send the proper authenticate header when using http-request auth
When we use htx and http-request auth rules, we need to send WWW-Authenticate
with a 401 and Proxy-Authenticate with a 407. We only sent Proxy-Authenticate
regardless of status, with htx enabled.

To be backported to 1.9.
2018-12-28 15:48:12 +01:00
Olivier Houchard
bb3dac37a2 BUG/MEDIUM: servers: Don't try to reuse connection if we switched server.
In connect_server(), don't attempt to reuse the old connection if it's
targetting a different server than the one we're supposed to access, or
we will never be able to connect to a server if the first one we tried failed.

This should be backported to 1.9.
2018-12-24 13:45:43 +01:00
Willy Tarreau
48507ef558 CLEANUP: mux-h2: remove misleading comments about CONTINUATION
These ones were left-over from copy-pastes that are unrelated to
CONTINUATION frames.
2018-12-24 11:45:00 +01:00
Willy Tarreau
ea18f86364 MEDIUM: mux-h2: handle decoding of CONTINUATION frames
Now that the HEADERS frame decoding is retryable, we can safely try to
fold CONTINUATION frames into a HEADERS frame when the END_OF_HEADERS
flag is missing. In order to do this, h2c_decode_headers() moves the
frames payloads in-situ and leaves a hole that is plugged when leaving
the function. There is no limit to the number of CONTINUATION frames
handled this way provided that all of them fit into the buffer. The
error reported when meeting isolated CONTINUATION frames has now changed
from INTERNAL_ERROR to PROTOCOL_ERROR.

Now there is only one (unrelated) remaining failure in h2spec.
2018-12-24 11:45:00 +01:00
Willy Tarreau
a4428bd531 MINOR: mux-h2: make h2_peek_frame_hdr() support an offset
This function will be used to parse multiple subsequent frames so it
needs to support an offset.
2018-12-24 11:45:00 +01:00
Willy Tarreau
96a10c24cf MINOR: mux-h2: fail stream creation more cleanly using RST_STREAM
The H2 demux only checks for too many streams in h2c_frt_stream_new(),
then refuses to create a new stream and causes the connection to be
aborted by sending a GOAWAY frame. This will also happen if any error
happens during the stream creation (e.g. memory allocation).

RFC7540#5.1.2 says that attempts to create streams in excess should
instead be dealt with using an RST_STREAM frame conveying either the
PROTOCOL_ERROR or REFUSED_STREAM reason (the latter being usable only
if it is guaranteed that the stream was not processed). In theory it
should not happen for well behaving clients, though it may if we
configure a low enough h2.max_concurrent_streams limit. This error
however may definitely happen on memory shortage.

Previously it was not possible to use RST_STREAM due to the fact that
the HPACK decompressor would be desynchronized. But now we first decode
and only then try to allocate the stream, so the decompressor remains
synchronized regardless of policy or resources issues.

With this patch we enforce stream termination with RST_STREAM and
REFUSED_STREAM if this protocol violation happens, as well as if there
is a temporary condition like a memory allocation issue. It will allow
a client to recover cleanly.

This could possibly be backported to 1.9. Note that this requires that
these five previous patches are merged as well :

    MINOR: h2: add a bit-based frame type representation
    MEDIUM: mux-h2: remove padlen during headers phase
    MEDIUM: mux-h2: decode HEADERS frames before allocating the stream
    MINOR: mux-h2: make h2c_send_rst_stream() use the dummy stream's error code
    MINOR: mux-h2: add a new dummy stream for the REFUSED_STREAM error code
2018-12-24 11:45:00 +01:00
Willy Tarreau
8d0d58bf6a MINOR: mux-h2: add a new dummy stream for the REFUSED_STREAM error code
This patch introduces a new dummy stream, h2_refused_stream, in CLOSED
status with the aforementioned error code. It will be usable to reject
unexpected extraneous streams.
2018-12-24 11:45:00 +01:00
Willy Tarreau
e6888fff75 MINOR: mux-h2: make h2c_send_rst_stream() use the dummy stream's error code
We currently have 2 dummy streams allowing us to send an RST_STREAM
message with an error code matching this one. However h2c_send_rst_stream()
still enforces the STREAM_CLOSED error code for these dummy streams,
ignoring their respective errcode fields which however are properly
set.

Let's make the function always use the stream's error code. This will
allow to create other dummy streams for different codes.
2018-12-24 11:45:00 +01:00
Willy Tarreau
5c8cafae39 MEDIUM: mux-h2: decode HEADERS frames before allocating the stream
It's hard to recover from a HEADERS frame decoding error after having
already created the stream, and it's not possible to recover from a
stream allocation error without dropping the connection since we can't
maintain the HPACK context, so let's decode it before allocating the
stream, into a temporary buffer that will then be offered to the newly
created stream.
2018-12-24 11:45:00 +01:00
Willy Tarreau
6fa380dbba MINOR: mux-h2: remove useless check for empty frame length in h2s_decode_headers()
This test for an empty frame was already performed in the callers, there
is no need for checking it again.
2018-12-24 11:45:00 +01:00
Willy Tarreau
3bf6918cb2 MEDIUM: mux-h2: remove padlen during headers phase
Three types of frames may be padded : DATA, HEADERS and PUSH_PROMISE.
Currently, each of these independently deals with padding and needs to
wait for and skip the initial padlen byte. Not only this complicates
frame processing, but it makes it very hard to process CONTINUATION
frames after a padded HEADERS frame, and makes it complicated to perform
atomic calls to h2s_decode_headers(), which are needed if we want to be
able to maintain the HPACK decompressor's context even when dropping
streams.

This patch takes a different approach : the padding is checked when
parsing the frame header, the padlen byte is waited for and parsed,
and the dpl value is updated with this padlen value. This will allow
the frame parsers to decide to overwrite the padding if needed when
merging adjacent frames.
2018-12-24 11:45:00 +01:00
Willy Tarreau
a875466243 BUG/MEDIUM: mux-h2: mark that we have too many CS once we have more than the max
Since commit f210191 ("BUG/MEDIUM: h2: don't accept new streams if
conn_streams are still in excess") we're refraining from reading input
frames if we've reached the limit of number of CS. The problem is that
it prevents such situations from working fine. The initial purpose was
in fact to prevent from reading new HEADERS frames when this happens,
and causes some occasional transfer hiccups and pauses with large
concurrencies.

Given that we now properly reject extraneous streams before checking
this value, we can be sure never to have too many streams, and that
any higher value is only caused by a scheduling reason and will go
down after the scheduler calls the code.

This fix must be backported to 1.9 and possibly to 1.8. It may be
tested using h2spec this way with an h2spec config :

  while :; do
    h2spec -o 5 -v -t -S -k -h 127.0.0.1 -p 4443 http2/5.1.2
  done
2018-12-24 08:13:16 +01:00
Willy Tarreau
c4ea04c2b6 BUG/MINOR: mux-h2: make empty HEADERS frame return a connection error
We were returning a stream error of type PROTOCOL_ERROR on empty HEADERS
frames, but RFC7540#4.2 stipulates that we should instead return a
connection error of type FRAME_SIZE_ERROR.

This may be backported to 1.9 and 1.8 though it's unlikely to have any
real life effect.
2018-12-23 10:02:38 +01:00
Willy Tarreau
97aaa67658 MINOR: mux-h2: only increase the connection window with the first update
Commit dc57236 ("BUG/MINOR: mux-h2: advertise a larger connection window
size") caused a WINDOW_UPDATE message to be sent early with the connection
to increase the connection's window size. It turns out that it causes some
minor trouble that need to be worked around :
  - varnishtest cannot transparently cope with the WU frames during the
    handshake, forcing all tests to explicitly declare the handshake
    sequence ;
  - some vtc scripts randomly fail if the WU frame is sent after another
    expected response frame, adding uncertainty to some tests ;
  - h2spec doesn't correctly identify these WU at the connection level
    that it believes are the responses to some purposely erroneous frames
    it sends, resulting in some errors being reported

None of these are a problem with real clients but they add some confusion
during troubleshooting.

Since the fix above was intended to increase the upload bandwidth, we
have another option which is to increase the window size with the first
WU frame sent for the connection. This way, no WU frame is sent until
one is really needed, and this first frame will adjust the window to
the maximum value. It will make the window increase slightly later, so
the client will experience the first round trip when uploading data,
but this should not be perceptible, and is not worth the extra hassle
needed to maintain our debugging abilities. As an extra bonus, a few
extra bytes are saved for each connection until the first attempt to
upload data.

This should possibly be backported to 1.9 and 1.8.
2018-12-23 09:49:04 +01:00
Olivier Houchard
921501443b MEDIUM: checks: Add check-alpn.
Add a way to configure the ALPN used by check, with a new "check-alpn"
keyword. By default, the checks will use the server ALPN, but it may not
be convenient, for instance because the server may use HTTP/2, while checks
are unable to do HTTP/2 yet.
2018-12-21 19:54:16 +01:00
Olivier Houchard
ab28a320aa MINOR: ssl: Add ssl_sock_set_alpn().
Add a new function, ssl_sock_set_alpn(), to be able to change the ALPN
for a connection, instead of relying of the one defined in the SSL_CTX.
2018-12-21 19:53:30 +01:00
Olivier Houchard
21944019ca BUG/MEDIUM: server: Also copy "check-sni" for server templates.
When using server templates, if "check-sni" is used, make sure it shows up
in all the created servers.

This should be backported to 1.8 and 1.9.
2018-12-21 19:53:28 +01:00
Willy Tarreau
47b515a462 BUG/MEDIUM: mux-h2: don't needlessly wake up the demux on short frames
In some situations, if too short a frame header is received, we may leave
h2_process_demux() waking up the task again without checking that we were
already subscribed.

In order to avoid this once for all, let's introduce an h2_restart_reading()
function which performs the control and calls the task up. This way we won't
needlessly wake the task up if it's already waiting for I/O.

Must be backported to 1.9.
2018-12-21 16:12:33 +01:00
Olivier Houchard
a8f6b43b07 MEDIUM: mux_h1: Implement h1_show_fd.
In the mux_h1, implement h1_show_fd, to give a bit more information about
each H1 stream, when using "show fd".
2018-12-21 15:33:26 +01:00
Christopher Faulet
d238ae3a9b BUG/MINOR: compression/htx: Don't add the last block of data if it is empty
In HTX, when the compression filter analyze the EOM, it flushes the compression
context and add the last block of compressed data. But, this block can be
empty. In this case, we must ignore it.
2018-12-21 15:33:26 +01:00
Christopher Faulet
c963eb2a1d BUG/MINOR: compression/htx: Don't compress responses with unknown body length
In HTX, if the body length of a response cannot be determined, we must not try
to compress it.
2018-12-21 15:33:16 +01:00
Nikhil Agrawal
2fa66c3b93 BUG/MEDIUM: dns: overflowed dns name start position causing invalid dns error
In dns_read_name() when dns name is used with compression and start position of
name is greater than 255 name read is incorrect and causes invalid dns error.
eg: 0xc11b c specifies name compression being used. 11b represent the start
position of name but currently we are using only 1b for start position.

This should be backported as far as 1.7.
2018-12-21 11:36:44 +01:00
Jérôme Magnin
8d4e7dc880 BUG/MEDIUM: dns: Don't prevent reading the last byte of the payload in dns_validate_response()
A regression was introduced with efbbdf72 BUG: dns: Prevent out-of-bounds
read in dns_validate_dns_response() as it prevented from taking into account
the last byte of the payload.  this patch aims at fixing it.

this must be backported in 1.8.
2018-12-20 17:13:02 +01:00
Willy Tarreau
645b33d233 BUG/MEDIUM: mux-h2: Don't forget to quit the send list on error reports
Similar to last fix, we need to quit the send list when reporting an
error via the send side.

This should be backported to 1.9.
2018-12-20 15:35:57 +01:00
Olivier Houchard
f29cd5c8a8 BUG/MEDIUM: h2: Don't forget to quit the sending_list if SUB_CALL_UNSUBSCRIBE.
In mux_h2_unsubscribe, don't forget to leave the sending_list if
SUB_CALL_UNSUBSCRIBE was set. SUB_CALL_UNSUBSCRIBE means we were about
to be woken up for writing, unless the mux was too full to get more data.
If there's an unsubscribe call in the meanwhile, we should leave the list,
or we may be put back in the send_list.

This should be backported to 1.9.
2018-12-20 12:24:43 +01:00
Willy Tarreau
d22d69bd58 CLEANUP: remove my name and address from the copyright banner
First, it's a pain to always have to think about updating this date,
second for a long time I've not been the only developer there, and third,
some users contact me hoping to get help that I can't deliver. It's about
time to redirect them to the main site where all the useful links should
be.
2018-12-19 19:07:04 +01:00
Willy Tarreau
e9ca80711d MINOR: cli/show_fd: report that a connection is back or not
It simply adds a "back={0,1}" depending on the connection's side, it's
useful to debug.
2018-12-19 18:40:58 +01:00
Olivier Houchard
6dea2ee939 BUG/MEDIUM: h2: Don't wait for flow control if the connection had a shutr.
In h2_snd_buf(), if we couldn't send the data because of flow control, and
the connection got a shutr, then add CS_FL_ERROR (or CS_FL_ERR_PENDING). We
will never get any window update, so we will never be unlocked, anyway.

No backport is needed.
2018-12-19 18:35:40 +01:00
Willy Tarreau
fde287cc76 BUG/MINOR: mux-h2: make sure we check the conn_stream in early data
When dealing with early data we scan the list of stream to notify them.
We're not supposed to have h2s->cs == NULL here but it doesn't cost much
to make the scan more robust and verify it before notifying.

No backport is needed.
2018-12-19 18:33:16 +01:00
Willy Tarreau
ec988c7a0f CLEANUP: mux-h2: make use of cs_set_error()
It's cleaner than open-coding the conditions and error bits.
2018-12-19 18:13:52 +01:00
Willy Tarreau
f830f018cf BUG/MEDIUM: mux-h2: make use of h2s_alert() to report aborts
If we had no pending read, it could be complicated to report an
RST_STREAM to a sender since we used to only report it via the
rx side if subscribed. Similarly in h2_wake_some_streams() we
now try all methods, hoping to catch all possible events.

No backport is needed.
2018-12-19 18:13:52 +01:00
Willy Tarreau
8b2757c339 MINOR: mux-h2: add a new function h2s_alert() to call the data layer
In order to report an error to the data layer, we have different ways
depending on the situation. At a lot of places it's open-coded and not
always correct. Let's create a new function h2s_alert() to handle this
task. It tries to wake on recv() first, then on send(), then using
wake().
2018-12-19 18:13:48 +01:00
Willy Tarreau
7e094451d0 CLEANUP: mux-h2: implement h2s_notify_{send,recv} to report events to subscribers
Till now we had to open-code all the manipulation of the wait_event,
let's use standarized functions for this and reduce the risk of bugs.
2018-12-19 18:11:35 +01:00
Olivier Houchard
251064b02d BUG/MEDIUM: h2: Make sure we don't set CS_FL_ERROR if there's still data.
In the mux h2, make sure we set CS_FL_ERR_PENDING and wake the recv task,
instead of setting CS_FL_ERROR, if CS_FL_EOS is not set, so if there's
potentially still some data to be sent.
2018-12-19 17:28:54 +01:00
Willy Tarreau
bddf7fc417 MEDIUM: stream-int: always consider all CS errors on the send side
We still have an issue with asynchronous errors, which is that while
they don't truncate reads anymore, they might be missed during a
send() attempt. This can happen for example when processing a request
followed by undesired data for which the stream doesn't try to receive,
while the send side experiences an error (transfer aborted by the client).
In this case we definitely want all send() attempts to fail as soon as
the error was reported, even if it's only pending. This way we leave an
opportunity to the stream interface to try to receive the last data
pending in the buffer but it cannot send anymore and knows that there
is an error when trying to do so.
2018-12-19 17:23:26 +01:00
Olivier Houchard
9117780bfd BUG/MEDIUM: mux-h2: pass CS_FL_ERR_PENDING to h2_wake_some_streams()
Commiy 8519357c ("BUG/MEDIUM: mux-h2: report asynchronous errors in
h2_wake_some_streams()") addressed an issue with synchronous errors
but forgot to fix the call places to also pass CS_FL_ERR_PENDING
instead of CS_FL_ERROR.

No backport is needed.
2018-12-19 17:06:49 +01:00
Olivier Houchard
2f30883793 BUG/MEDIUM: H2: Make sure htx is set even on empty frames.
When transfering data, make sure htx is set even on empty frames, or we
will never add a HTX_BLK_EOM block.
2018-12-19 17:00:14 +01:00