diff options
author | Hugo Landau <hlandau@openssl.org> | 2023-08-09 17:46:33 +0100 |
---|---|---|
committer | Hugo Landau <hlandau@openssl.org> | 2023-09-01 10:45:34 +0100 |
commit | 62665fc2430cb3d3c9e59a133e67ab9941222017 (patch) | |
tree | c30c574d669cabf36d04d159562ea6d3e85b3ab0 | |
parent | c20b78d59960c523c4de02e7bd62fcd4c0a5a4f7 (diff) |
QUIC APL: Introduce addressed v. non-addressed mode handling
Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/21715)
-rw-r--r-- | ssl/quic/quic_impl.c | 84 | ||||
-rw-r--r-- | ssl/quic/quic_local.h | 6 |
2 files changed, 83 insertions, 7 deletions
diff --git a/ssl/quic/quic_impl.c b/ssl/quic/quic_impl.c index d56c64f97f..49133f0ca7 100644 --- a/ssl/quic/quic_impl.c +++ b/ssl/quic/quic_impl.c @@ -816,7 +816,7 @@ uint64_t ossl_quic_get_options(const SSL *ssl) */ static int csm_analyse_init_peer_addr(BIO *net_wbio, BIO_ADDR *peer) { - if (BIO_dgram_get_peer(net_wbio, peer) <= 0) + if (BIO_dgram_detect_peer_addr(net_wbio, peer) <= 0) return 0; return 1; @@ -1518,12 +1518,6 @@ static int quic_do_handshake(QCTX *ctx) if (!quic_mutation_allowed(qc, /*req_active=*/0)) return QUIC_RAISE_NON_NORMAL_ERROR(ctx, SSL_R_PROTOCOL_IS_SHUTDOWN, NULL); - if (BIO_ADDR_family(&qc->init_peer_addr) == AF_UNSPEC) { - /* Peer address must have been set. */ - QUIC_RAISE_NON_NORMAL_ERROR(ctx, SSL_R_REMOTE_PEER_ADDRESS_NOT_SET, NULL); - return -1; /* Non-protocol error */ - } - if (qc->as_server != qc->as_server_state) { QUIC_RAISE_NON_NORMAL_ERROR(ctx, ERR_R_PASSED_INVALID_ARGUMENT, NULL); return -1; /* Non-protocol error */ @@ -1536,6 +1530,82 @@ static int quic_do_handshake(QCTX *ctx) } /* + * We need to determine our addressing mode. There are basically two + * ways we can use L4 addresses: + * + * - Addressed mode, in which our BIO_sendmmsg calls have destination + * addresses attached to them which we expect the underlying network BIO + * to handle; + * + * - Unaddressed mode, in which the BIO provided to us on the + * network side neither provides us with L4 addresses nor is capable of + * honouring ones we provide. We don't know where the QUIC traffic we + * send ends up exactly and trust the application to know what it is + * doing. + * + * Addressed mode is preferred because it enables support for connection + * migration, multipath, etc. in the future. Addressed mode is automatically + * enabled if we are using e.g. BIO_s_datagram, with or without + * BIO_s_connect. + * + * If we are passed a BIO_s_dgram_pair (or some custom BIO) we may have to + * use unaddressed mode unless that BIO supports capability flags indicating + * it can provide and honour L4 addresses. + * + * Our strategy for determining address mode is simple: we probe the + * underlying network BIOs for their capabilities. If the network BIOs + * support what we need, we use addressed mode. Otherwise, we use + * unaddressed mode. + * + * If addressed mode is chosen, we require an initial peer address to be + * set. If this is not set, we fail. If unaddressed mode is used, we do not + * require this, as such an address is superfluous, though it can be set if + * desired. + */ + if (!qc->started && !qc->addressing_probe_done) { + long rcaps = BIO_dgram_get_effective_caps(qc->net_rbio); + long wcaps = BIO_dgram_get_effective_caps(qc->net_wbio); + int can_use_addressed = + (wcaps & BIO_DGRAM_CAP_HANDLES_DST_ADDR) != 0 + && (rcaps & BIO_DGRAM_CAP_PROVIDES_SRC_ADDR) != 0; + + qc->addressed_mode = can_use_addressed; + qc->addressing_probe_done = 1; + } + + if (!qc->started && qc->addressed_mode + && BIO_ADDR_family(&qc->init_peer_addr) == AF_UNSPEC) { + /* + * We are trying to connect and are using addressed mode, which means we + * need an initial peer address; if we do not have a peer address yet, + * we should try to autodetect one. + * + * We do this as late as possible because some BIOs (e.g. BIO_s_connect) + * may not be able to provide us with a peer address until they have + * finished their own processing. They may not be able to perform this + * processing until an application has figured configuring that BIO + * (e.g. with setter calls), which might happen after SSL_set_bio is + * called. + */ + if (!csm_analyse_init_peer_addr(qc->net_wbio, &qc->init_peer_addr)) + /* best effort */ + BIO_ADDR_clear(&qc->init_peer_addr); + else + ossl_quic_channel_set_peer_addr(qc->ch, &qc->init_peer_addr); + } + + if (!qc->started + && qc->addressed_mode + && BIO_ADDR_family(&qc->init_peer_addr) == AF_UNSPEC) { + /* + * If we still don't have a peer address in addressed mode, we can't do + * anything. + */ + QUIC_RAISE_NON_NORMAL_ERROR(ctx, SSL_R_REMOTE_PEER_ADDRESS_NOT_SET, NULL); + return -1; /* Non-protocol error */ + } + + /* * Start connection process. Note we may come here multiple times in * non-blocking mode, which is fine. */ diff --git a/ssl/quic/quic_local.h b/ssl/quic/quic_local.h index d194563c23..aaaab128aa 100644 --- a/ssl/quic/quic_local.h +++ b/ssl/quic/quic_local.h @@ -195,6 +195,12 @@ struct quic_conn_st { */ unsigned int shutting_down : 1; + /* Have we probed the BIOs for addressing support? */ + unsigned int addressing_probe_done : 1; + + /* Are we using addressed mode (BIO_sendmmsg with non-NULL peer)? */ + unsigned int addressed_mode : 1; + /* Default stream type. Defaults to SSL_DEFAULT_STREAM_MODE_AUTO_BIDI. */ uint32_t default_stream_mode; |