Release 2.10.4

- [BUGFIX] Send HANDSHAKE_DONE only after Finished is received.
- [BUGFIX] Don't treat garbage UDP padding as library error; ignore
  it instead.
- [BUGFIX] Fix compilation on FreeBSD (missing header).
This commit is contained in:
Dmitri Tikhonov 2020-02-11 08:53:24 -05:00
parent 45aae370f6
commit e68b045258
9 changed files with 170 additions and 9 deletions

View file

@ -1,3 +1,11 @@
2020-02-11
- 2.10.4
- [BUGFIX] Send HANDSHAKE_DONE only after Finished is received.
- [BUGFIX] Don't treat garbage UDP padding as library error; ignore
it instead.
- [BUGFIX] Fix compilation on FreeBSD (missing header).
- Code cleanup: remove unnecessary #includes.
2020-01-31
- 2.10.3
- [BUGFIX] Cancel path responses and challenges on old path when

View file

@ -25,7 +25,7 @@ extern "C" {
#define LSQUIC_MAJOR_VERSION 2
#define LSQUIC_MINOR_VERSION 10
#define LSQUIC_PATCH_VERSION 3
#define LSQUIC_PATCH_VERSION 4
/**
* Engine flags:

View file

@ -296,6 +296,13 @@ struct enc_session_funcs_iquic
void
(*esfi_handshake_confirmed)(enc_session_t *);
int
(*esfi_in_init)(enc_session_t *);
int
(*esfi_data_in)(enc_session_t *, enum enc_level,
const unsigned char *, size_t);
};
extern

View file

@ -2238,6 +2238,55 @@ iquic_esfi_handshake_confirmed (enc_session_t *sess)
}
static int
iquic_esfi_in_init (enc_session_t *sess)
{
struct enc_sess_iquic *enc_sess = (struct enc_sess_iquic *) sess;
int in_init;
if (enc_sess->esi_ssl)
{
in_init = SSL_in_init(enc_sess->esi_ssl);
LSQ_DEBUG("in_init: %d", in_init);
return in_init;
}
else
{
LSQ_DEBUG("no SSL object, in_init: 0");
return 0;
}
}
int
iquic_esfi_data_in (enc_session_t *sess, enum enc_level enc_level,
const unsigned char *buf, size_t len)
{
struct enc_sess_iquic *enc_sess = (struct enc_sess_iquic *) sess;
int s;
size_t str_sz;
char str[MAX(1500 * 5, ERR_ERROR_STRING_BUF_LEN)];
if (!enc_sess->esi_ssl)
return -1;
s = SSL_provide_quic_data(enc_sess->esi_ssl,
(enum ssl_encryption_level_t) enc_level, buf, len);
if (!s)
{
LSQ_WARN("SSL_provide_quic_data returned false: %s",
ERR_error_string(ERR_get_error(), str));
return -1;
}
LSQ_DEBUG("provided %zu bytes of %u-level data to SSL", len, enc_level);
str_sz = lsquic_hexdump(buf, len, str, sizeof(str));
LSQ_DEBUG("\n%.*s", (int) str_sz, str);
s = SSL_do_handshake(enc_sess->esi_ssl);
LSQ_DEBUG("do_handshake returns %d", s);
return 0;
}
static void iquic_esfi_shake_stream (enc_session_t *sess,
struct lsquic_stream *stream, const char *what);
@ -2255,6 +2304,8 @@ const struct enc_session_funcs_iquic lsquic_enc_session_iquic_ietf_v1 =
.esfi_shake_stream = iquic_esfi_shake_stream,
.esfi_handshake_confirmed
= iquic_esfi_handshake_confirmed,
.esfi_in_init = iquic_esfi_in_init,
.esfi_data_in = iquic_esfi_data_in,
};

View file

@ -2657,8 +2657,8 @@ lsquic_engine_packet_in (lsquic_engine_t *engine,
{
LSQ_DEBUG("Cannot parse incoming packet's header");
lsquic_mm_put_packet_in(&engine->pub.enp_mm, packet_in);
errno = EINVAL;
return -1;
s = 1;
break;
}
packet_in_data += packet_in->pi_data_sz;

View file

@ -160,6 +160,7 @@ enum send
SEND_MAX_STREAMS_BIDI = SEND_MAX_STREAMS + SD_BIDI,
SEND_MAX_STREAMS_UNI = SEND_MAX_STREAMS + SD_UNI,
SEND_STOP_SENDING,
SEND_HANDSHAKE_DONE,
N_SEND
};
@ -183,6 +184,7 @@ enum send_flags
SF_SEND_MAX_STREAMS_BIDI = 1 << SEND_MAX_STREAMS_BIDI,
SF_SEND_MAX_STREAMS_UNI = 1 << SEND_MAX_STREAMS_UNI,
SF_SEND_STOP_SENDING = 1 << SEND_STOP_SENDING,
SF_SEND_HANDSHAKE_DONE = 1 << SEND_HANDSHAKE_DONE,
};
#define SF_SEND_PATH_CHAL_ALL \
@ -1321,6 +1323,12 @@ lsquic_ietf_full_conn_server_new (struct lsquic_engine_public *enpub,
assert(mini_conn->cn_flags & LSCONN_HANDSHAKE_DONE);
conn->ifc_conn.cn_flags |= LSCONN_HANDSHAKE_DONE;
if (mini_conn->cn_version > LSQVER_ID24
&& !(imc->imc_flags & IMC_HSK_DONE_SENT))
{
LSQ_DEBUG("HANDSHAKE_DONE not yet sent, will process CRYPTO frames");
conn->ifc_flags |= IFC_PROC_CRYPTO;
}
conn->ifc_conn.cn_enc_session = mini_conn->cn_enc_session;
mini_conn->cn_enc_session = NULL;
@ -2530,7 +2538,7 @@ drop_crypto_streams (struct ietf_full_conn *conn)
struct lsquic_stream **streamp;
unsigned count;
if (!(conn->ifc_flags & IFC_PROC_CRYPTO))
if ((conn->ifc_flags & (IFC_SERVER|IFC_PROC_CRYPTO)) != IFC_PROC_CRYPTO)
return;
conn->ifc_flags &= ~IFC_PROC_CRYPTO;
@ -3809,6 +3817,34 @@ generate_ping_frame (struct ietf_full_conn *conn, lsquic_time_t unused)
}
static void
generate_handshake_done_frame (struct ietf_full_conn *conn,
lsquic_time_t unused)
{
struct lsquic_packet_out *packet_out;
unsigned need;
int sz;
need = conn->ifc_conn.cn_pf->pf_handshake_done_frame_size();
packet_out = get_writeable_packet(conn, need);
if (!packet_out)
return;
sz = conn->ifc_conn.cn_pf->pf_gen_handshake_done_frame(
packet_out->po_data + packet_out->po_data_sz,
lsquic_packet_out_avail(packet_out));
if (sz < 0)
{
ABORT_ERROR("generate_handshake_done_frame failed");
return;
}
lsquic_send_ctl_incr_pack_sz(&conn->ifc_send_ctl, packet_out, sz);
packet_out->po_frame_types |= QUIC_FTBIT_HANDSHAKE_DONE;
LSQ_DEBUG("generated HANDSHAKE_DONE frame");
conn->ifc_send_flags &= ~SF_SEND_HANDSHAKE_DONE;
}
static void
generate_path_chal_frame (struct ietf_full_conn *conn, lsquic_time_t now,
unsigned path_id)
@ -4518,8 +4554,48 @@ discard_crypto_frame (struct ietf_full_conn *conn,
}
/* In the server, we only wait for Finished frame */
static unsigned
process_crypto_frame (struct ietf_full_conn *conn,
process_crypto_frame_server (struct ietf_full_conn *conn,
struct lsquic_packet_in *packet_in, const unsigned char *p, size_t len)
{
struct stream_frame stream_frame;
int parsed_len;
parsed_len = conn->ifc_conn.cn_pf->pf_parse_crypto_frame(p, len,
&stream_frame);
if (parsed_len < 0)
return 0;
if (!(conn->ifc_flags & IFC_PROC_CRYPTO))
{
LSQ_DEBUG("discard %d-byte CRYPTO frame", parsed_len);
return (unsigned) parsed_len;
}
if (0 != conn->ifc_conn.cn_esf.i->esfi_data_in(
conn->ifc_conn.cn_enc_session,
lsquic_packet_in_enc_level(packet_in),
stream_frame.data_frame.df_data,
stream_frame.data_frame.df_size))
{
LSQ_DEBUG("feeding CRYPTO frame to enc session failed");
return 0;
}
if (!conn->ifc_conn.cn_esf.i->esfi_in_init(conn->ifc_conn.cn_enc_session))
{
LSQ_DEBUG("handshake confirmed: send HANDSHAKE_DONE");
conn->ifc_flags &= ~IFC_PROC_CRYPTO;
conn->ifc_send_flags |= SF_SEND_HANDSHAKE_DONE;
}
return (unsigned) parsed_len;
}
static unsigned
process_crypto_frame_client (struct ietf_full_conn *conn,
struct lsquic_packet_in *packet_in, const unsigned char *p, size_t len)
{
struct stream_frame *stream_frame;
@ -4607,6 +4683,17 @@ process_crypto_frame (struct ietf_full_conn *conn,
}
static unsigned
process_crypto_frame (struct ietf_full_conn *conn,
struct lsquic_packet_in *packet_in, const unsigned char *p, size_t len)
{
if (conn->ifc_flags & IFC_SERVER)
return process_crypto_frame_server(conn, packet_in, p, len);
else
return process_crypto_frame_client(conn, packet_in, p, len);
}
static unsigned
process_stream_frame (struct ietf_full_conn *conn,
struct lsquic_packet_in *packet_in, const unsigned char *p, size_t len)
@ -6283,6 +6370,7 @@ static void (*const send_funcs[N_SEND])(
[SEND_PATH_RESP_PATH_0] = generate_path_resp_0,
[SEND_PATH_RESP_PATH_1] = generate_path_resp_1,
[SEND_PING] = generate_ping_frame,
[SEND_HANDSHAKE_DONE] = generate_handshake_done_frame,
};
@ -6292,7 +6380,7 @@ static void (*const send_funcs[N_SEND])(
|SF_SEND_MAX_STREAMS_UNI|SF_SEND_MAX_STREAMS_BIDI\
|SF_SEND_PATH_CHAL_PATH_0|SF_SEND_PATH_CHAL_PATH_1\
|SF_SEND_PATH_RESP_PATH_0|SF_SEND_PATH_RESP_PATH_1\
|SF_SEND_PING\
|SF_SEND_PING|SF_SEND_HANDSHAKE_DONE\
|SF_SEND_STOP_SENDING)
static enum tick_st

View file

@ -1645,6 +1645,7 @@ imico_generate_handshake_done (struct ietf_mini_conn *conn)
packet_out->po_frame_types |= 1 << QUIC_FRAME_HANDSHAKE_DONE;
packet_out->po_data_sz += sz;
LSQ_DEBUG("generated HANDSHAKE_DONE frame");
conn->imc_flags |= IMC_HSK_DONE_SENT;
return 0;
}
@ -1685,9 +1686,13 @@ ietf_mini_conn_ci_tick (struct lsquic_conn *lconn, lsquic_time_t now)
}
else if (conn->imc_flags & IMC_HSK_OK)
{
if (conn->imc_conn.cn_version > LSQVER_ID24
&& 0 != imico_generate_handshake_done(conn))
goto close_on_error;
if (conn->imc_conn.cn_version > LSQVER_ID24)
{
if (lconn->cn_esf.i->esfi_in_init(lconn->cn_enc_session))
LSQ_DEBUG("still in init, defer HANDSHAKE_DONE");
else if (0 != imico_generate_handshake_done(conn))
goto close_on_error;
}
tick |= TICK_PROMOTE;
}

View file

@ -57,6 +57,7 @@ struct ietf_mini_conn
IMC_CLOSE_RECVD = 1 << 19,
IMC_PARSE_FAILED = 1 << 20,
IMC_PATH_CHANGED = 1 << 21,
IMC_HSK_DONE_SENT = 1 << 22,
} imc_flags;
struct mini_crypto_stream imc_streams[N_ENC_LEVS];
void *imc_stream_ps[N_ENC_LEVS];

View file

@ -16,6 +16,7 @@
#endif
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#if !(defined(_POSIX_TIMERS) && _POSIX_TIMERS > 0) && defined(__APPLE__)
#include <mach/mach_time.h>