From: Hugo Landau Date: Wed, 9 Aug 2023 16:46:33 +0000 (+0100) Subject: QUIC APL: Introduce addressed v. non-addressed mode handling X-Git-Tag: openssl-3.2.0-alpha1~81 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=62665fc2430cb3d3c9e59a133e67ab9941222017;p=thirdparty%2Fopenssl.git QUIC APL: Introduce addressed v. non-addressed mode handling Reviewed-by: Tomas Mraz Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/21715) --- diff --git a/ssl/quic/quic_impl.c b/ssl/quic/quic_impl.c index d56c64f97f9..49133f0ca7e 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 */ @@ -1535,6 +1529,82 @@ static int quic_do_handshake(QCTX *ctx) return -1; /* Non-protocol error */ } + /* + * 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 d194563c237..aaaab128aa2 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;