From: Matt Caswell Date: Tue, 26 Nov 2024 12:36:52 +0000 (+0000) Subject: Add the ablity to set a local address for BIO_dgram_pair X-Git-Tag: openssl-3.5.0-alpha1~317 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=16a19002d8a1937493b28ae49e506460c0569c88;p=thirdparty%2Fopenssl.git Add the ablity to set a local address for BIO_dgram_pair BIOs created from a BIO_dgram_pair don't normally have a local BIO_ADDR associated with them. This allows us to set one. Fixes openssl/project#933 Reviewed-by: Tim Hudson Reviewed-by: Tomas Mraz Reviewed-by: Saša Nedvědický (Merged from https://github.com/openssl/openssl/pull/26066) --- diff --git a/crypto/bio/bss_dgram_pair.c b/crypto/bio/bss_dgram_pair.c index 08dd802d8fd..8a42d66bcc4 100644 --- a/crypto/bio/bss_dgram_pair.c +++ b/crypto/bio/bss_dgram_pair.c @@ -256,6 +256,8 @@ struct bio_dgram_pair_st { size_t mtu; /* Capability flags. */ uint32_t cap; + /* The local address to use (if set) */ + BIO_ADDR *local_addr; /* * This lock protects updates to our rbuf. Since writes are directed to our * own rbuf, this means we use this lock for writes and our peer's lock for @@ -405,6 +407,8 @@ static int dgram_pair_ctrl_destroy_bio_pair(BIO *bio1) ring_buf_destroy(&b1->rbuf); bio1->init = 0; + BIO_ADDR_free(b1->local_addr); + /* Early return if we don't have a peer. */ if (b1->peer == NULL) return 1; @@ -634,6 +638,16 @@ static int dgram_pair_ctrl_set_mtu(BIO *bio, size_t mtu) return 1; } +/* BIO_dgram_set0_local_addr (BIO_CTRL_DGRAM_SET0_LOCAL_ADDR) */ +static int dgram_pair_ctrl_set0_local_addr(BIO *bio, BIO_ADDR *addr) +{ + struct bio_dgram_pair_st *b = bio->ptr; + + BIO_ADDR_free(b->local_addr); + b->local_addr = addr; + return 1; +} + /* Partially threadsafe (some commands) */ static long dgram_mem_ctrl(BIO *bio, int cmd, long num, void *ptr) { @@ -731,6 +745,10 @@ static long dgram_mem_ctrl(BIO *bio, int cmd, long num, void *ptr) ret = (long)dgram_pair_ctrl_set_mtu(bio, (uint32_t)num); break; + case BIO_CTRL_DGRAM_SET0_LOCAL_ADDR: + ret = (long)dgram_pair_ctrl_set0_local_addr(bio, (BIO_ADDR *)ptr); + break; + /* * BIO_eof: Returns whether this half of the BIO pair is empty of data to * read. @@ -1230,6 +1248,8 @@ static ossl_ssize_t dgram_pair_write_actual(BIO *bio, const char *buf, size_t sz hdr.len = sz; hdr.dst_addr = (peer != NULL ? *peer : zero_addr); + if (local == NULL) + local = b->local_addr; hdr.src_addr = (local != NULL ? *local : zero_addr); saved_idx = b->rbuf.idx[0]; diff --git a/include/openssl/bio.h.in b/include/openssl/bio.h.in index 7e684be5948..d0a09cfe393 100644 --- a/include/openssl/bio.h.in +++ b/include/openssl/bio.h.in @@ -194,6 +194,7 @@ extern "C" { # define BIO_CTRL_GET_RPOLL_DESCRIPTOR 91 # define BIO_CTRL_GET_WPOLL_DESCRIPTOR 92 # define BIO_CTRL_DGRAM_DETECT_PEER_ADDR 93 +# define BIO_CTRL_DGRAM_SET0_LOCAL_ADDR 94 # define BIO_DGRAM_CAP_NONE 0U # define BIO_DGRAM_CAP_HANDLES_SRC_ADDR (1U << 0) @@ -670,6 +671,8 @@ int BIO_ctrl_reset_read_request(BIO *b); (unsigned int)BIO_ctrl((b), BIO_CTRL_DGRAM_GET_MTU, 0, NULL) # define BIO_dgram_set_mtu(b, mtu) \ (int)BIO_ctrl((b), BIO_CTRL_DGRAM_SET_MTU, (mtu), NULL) +# define BIO_dgram_set0_local_addr(b, addr) \ + (int)BIO_ctrl((b), BIO_CTRL_DGRAM_SET0_LOCAL_ADDR, 0, (addr)) /* ctrl macros for BIO_f_prefix */ # define BIO_set_prefix(b,p) BIO_ctrl((b), BIO_CTRL_SET_PREFIX, 0, (void *)(p)) diff --git a/test/helpers/quictestlib.c b/test/helpers/quictestlib.c index db39d659b16..83fe29c78cf 100644 --- a/test/helpers/quictestlib.c +++ b/test/helpers/quictestlib.c @@ -193,6 +193,8 @@ int qtest_create_quic_objects(OSSL_LIB_CTX *libctx, SSL_CTX *clientctx, goto err; #endif } else { + BIO_ADDR *localaddr = NULL; + if (!TEST_true(BIO_new_bio_dgram_pair(&cbio, 0, &sbio, 0))) goto err; @@ -200,6 +202,18 @@ int qtest_create_quic_objects(OSSL_LIB_CTX *libctx, SSL_CTX *clientctx, || !TEST_true(BIO_dgram_set_caps(sbio, BIO_DGRAM_CAP_HANDLES_DST_ADDR))) goto err; + if (!TEST_ptr(localaddr = BIO_ADDR_new())) + goto err; + /* Dummy client local addresses */ + if (!TEST_true(BIO_ADDR_rawmake(localaddr, AF_INET, &ina, sizeof(ina), + htons(0)))) { + BIO_ADDR_free(localaddr); + goto err; + } + if (!TEST_int_eq(BIO_dgram_set0_local_addr(cbio, localaddr), 1)) { + BIO_ADDR_free(localaddr); + goto err; + } /* Dummy server address */ if (!TEST_true(BIO_ADDR_rawmake(peeraddr, AF_INET, &ina, sizeof(ina), htons(0))))