From 408622b73a18dd1d8eeb6629bdd91b06715823cc Mon Sep 17 00:00:00 2001 From: Hugo Landau Date: Wed, 30 Nov 2022 19:24:15 +0000 Subject: [PATCH] BIO_s_dgram: add documentation and hazard warnings Reviewed-by: Tomas Mraz Reviewed-by: Paul Dale (Merged from https://github.com/openssl/openssl/pull/19795) --- doc/build.info | 6 + doc/man3/BIO_s_datagram.pod | 255 ++++++++++++++++++++++++++++++++++++ doc/man3/DTLSv1_listen.pod | 17 +++ util/missingcrypto.txt | 2 - util/missingmacro.txt | 7 - util/other.syms | 7 + 6 files changed, 285 insertions(+), 9 deletions(-) create mode 100644 doc/man3/BIO_s_datagram.pod diff --git a/doc/build.info b/doc/build.info index a2db40e21870a..4ffbcb843db65 100644 --- a/doc/build.info +++ b/doc/build.info @@ -651,6 +651,10 @@ DEPEND[html/man3/BIO_s_core.html]=man3/BIO_s_core.pod GENERATE[html/man3/BIO_s_core.html]=man3/BIO_s_core.pod DEPEND[man/man3/BIO_s_core.3]=man3/BIO_s_core.pod GENERATE[man/man3/BIO_s_core.3]=man3/BIO_s_core.pod +DEPEND[html/man3/BIO_s_datagram.html]=man3/BIO_s_datagram.pod +GENERATE[html/man3/BIO_s_datagram.html]=man3/BIO_s_datagram.pod +DEPEND[man/man3/BIO_s_datagram.3]=man3/BIO_s_datagram.pod +GENERATE[man/man3/BIO_s_datagram.3]=man3/BIO_s_datagram.pod DEPEND[html/man3/BIO_s_dgram_pair.html]=man3/BIO_s_dgram_pair.pod GENERATE[html/man3/BIO_s_dgram_pair.html]=man3/BIO_s_dgram_pair.pod DEPEND[man/man3/BIO_s_dgram_pair.3]=man3/BIO_s_dgram_pair.pod @@ -2958,6 +2962,7 @@ html/man3/BIO_s_accept.html \ html/man3/BIO_s_bio.html \ html/man3/BIO_s_connect.html \ html/man3/BIO_s_core.html \ +html/man3/BIO_s_datagram.html \ html/man3/BIO_s_dgram_pair.html \ html/man3/BIO_s_fd.html \ html/man3/BIO_s_file.html \ @@ -3569,6 +3574,7 @@ man/man3/BIO_s_accept.3 \ man/man3/BIO_s_bio.3 \ man/man3/BIO_s_connect.3 \ man/man3/BIO_s_core.3 \ +man/man3/BIO_s_datagram.3 \ man/man3/BIO_s_dgram_pair.3 \ man/man3/BIO_s_fd.3 \ man/man3/BIO_s_file.3 \ diff --git a/doc/man3/BIO_s_datagram.pod b/doc/man3/BIO_s_datagram.pod new file mode 100644 index 0000000000000..3ff24cc55127c --- /dev/null +++ b/doc/man3/BIO_s_datagram.pod @@ -0,0 +1,255 @@ +=pod + +=head1 NAME + +BIO_s_datagram, BIO_new_dgram, +BIO_ctrl_dgram_connect, +BIO_ctrl_set_connected, +BIO_dgram_recv_timedout, +BIO_dgram_send_timedout, +BIO_dgram_get_peer, +BIO_dgram_set_peer, +BIO_dgram_get_mtu_overhead - Network BIO with datagram semantics + +=head1 SYNOPSIS + + #include + + BIO_METHOD *BIO_s_datagram(void); + BIO *BIO_new_dgram(int fd, int close_flag); + + int BIO_ctrl_dgram_connect(BIO *bio, const BIO_ADDR *peer); + int BIO_ctrl_set_connected(BIO *bio, const BIO_ADDR *peer); + int BIO_dgram_recv_timedout(BIO *bio); + int BIO_dgram_send_timedout(BIO *bio); + int BIO_dgram_get_peer(BIO *bio, BIO_ADDR *peer); + int BIO_dgram_set_peer(BIO *bio, const BIO_ADDR *peer); + int BIO_dgram_get_mtu_overhead(BIO *bio); + +=head1 DESCRIPTION + +BIO_s_datagram() is a BIO implementation designed for use with network sockets +which provide datagram semantics, such as UDP sockets. It is suitable for use +with DTLSv1 or QUIC. + +Because BIO_s_datagram() has datagram semantics, a single BIO_write() call sends +a single datagram and a single BIO_read() call receives a single datagram. If +the size of the buffer passed to BIO_read() is inadequate, the datagram is +silently truncated. + +For a memory-based BIO which provides datagram semantics identical to those of +BIO_s_datagram(), see L. + +This BIO supports the L and L functions. + +When using BIO_s_datagram(), it is important to note that: + +=over 4 + +=item + +This BIO can be used with either a connected or unconnected network socket. A +connected socket is a network socket which has had L or a +similar OS-specific function called on it. Such a socket can only receive +datagrams from the specified peer. Any other socket is an unconnected socket and +can receive datagrams from any host. + +=item + +Despite their naming, +neither BIO_ctrl_dgram_connect() nor BIO_ctrl_set_connected() cause a socket +to become connected. These controls are provided to indicate to the BIO how +the underlying socket is configured and how it is to be used; see below. + +=item + +Use of BIO_s_datagram() with an unconnected network socket is hazardous hecause +any successful call to BIO_read() results in the peer address used for any +subsequent call to BIO_write() being set to the source address of the datagram +received by that call to BIO_read(). Thus, unless the caller calls +BIO_dgram_set_peer() immediately prior to every call to BIO_write(), or never +calls BIO_read(), any host on the network may cause future datagrams written to +be redirected to that host. Therefore, it is recommended that users either use +BIO_s_dgram() only with a connected socket, or, if using BIO_s_dgram() with an +unconnected socket, to use the L and L methods +only and forego use of L and L. An exception is where +L must be used; see L for further +discussion. + +=item + +Unlike L and L, the L and +L methods are stateless and do not cause the internal state of +the BIO_s_datagram() to change. + +=back + +Various controls are available for configuring the BIO_s_datagram() using +L: + +=over 4 + +=item BIO_ctrl_dgram_connect (BIO_CTRL_DGRAM_CONNECT) + +This is equivalent to calling L. + +Despite its name, this function does not cause the underlying socket to become +connected. + +=item BIO_ctrl_set_connected (BIO_CTRL_SET_CONNECTED) + +This informs the BIO_s_datagram() whether the underlying socket has been +connected, and therefore how the BIO_s_datagram() should attempt to use the +socket. + +If the I argument is non-NULL, BIO_s_datagram() assumes that the +underlying socket has been connected and will attempt to use the socket using OS +APIs which do not specify peer addresses (for example, send(3) and recv(3) or +similar). The I argument should specify the peer address to which the socket +is connected. + +If the I argument is NULL, BIO_s_datagram() assumes that the underlying +socket is not connected and will attempt to use the socket using an OS APIs +which specify peer addresses (for example, sendto(3) and recvfrom(3)). + +This control does not affect the operation of L or +L. + +=item BIO_dgram_get_peer (BIO_CTRL_DGRAM_GET_PEER) + +This outputs a B which specifies one of the following values, +whichever happened most recently: + +=over 4 + +=item + +The peer address last passed to BIO_dgram_set_peer(), BIO_ctrl_dgram_connect() +or BIO_ctrl_set_connected(). + +=item + +The peer address of the datagram last received by a call to BIO_read(). + +=back + +=item BIO_dgram_set_peer (BIO_CTRL_DGRAM_SET_PEER) + +Sets the peer address to be used for subsequent writes to this BIO. + +Warning: When used with an unconnected network socket, the value set may be +modified by future calls to L, making use of BIO_s_datagram() +hazardous when used with unconnected network sockets; see above. + +This does not affect the operation of L. +L does not affect the value set by BIO_dgram_set_peer(). + +=item BIO_dgram_recv_timeout (BIO_CTRL_DGRAM_GET_RECV_TIMER_EXP) + +Returns 1 if the last I/O operation performed on the BIO (for example, via a +call to L) may have been caused by a receive timeout. + +=item BIO_dgram_send_timedout (BIO_CTRL_DGRAM_GET_SEND_TIMER_EXP) + +Returns 1 if the last I/O operation performed on the BIO (for example, via a +call to L) may have been caused by a send timeout. + +=item BIO_dgram_get_mtu_overhead (BIO_CTRL_DGRAM_GET_MTU_OVERHEAD) + +Returns a quantity in bytes which is a rough estimate of the number of bytes of +overhead which should typically be added to a datagram payload size in order to +estimate the final size of the Layer 3 (e.g. IP) packet which will contain the +datagram. In most cases, the maximum datagram payload size which can be +transmitted can be determined by determining the link MTU in bytes and +subtracting the value returned by this call. + +The value returned by this call depends on the network layer protocol being +used. + +The value returned is not fully reliable because datagram overheads can be +higher in atypical network configurations, for example where IPv6 extension +headers or IPv4 options are used. + +=item BIO_CTRL_DGRAM_SET_DONT_FRAG + +If I is nonzero, configures the underlying network socket to enable Don't +Fragment mode, in which datagrams will be set with the IP Don't Fragment (DF) +bit set. If I is zero, Don't Fragment mode is disabled. + +=item BIO_CTRL_DGRAM_QUERY_MTU + +Queries the OS for its assessment of the Path MTU for the destination to which +the underlying network socket, and returns that Path MTU in bytes. This control +can only be used with a connected socket. + +This is not supported on all platforms and depends on OS support being +available. Returns 0 on failure. + +=item BIO_CTRL_DGRAM_MTU_DISCOVER + +This control requests that Path MTU discovery be enabled on the underlying +network socket. + +=item BIO_CTRL_DGRAM_GET_FALLBACK_MTU + +Returns the estimated minimum size of datagram payload which should always be +supported on the BIO. This size is determined by the minimum MTU required to be +supported by the applicable underlying network layer. Use of datagrams of this +size may lead to suboptimal performance, but should be routable in all +circumstances. The value returned is the datagram payload size in bytes and does +not include the size of layer 3 or layer 4 protocol headers. + +=item BIO_CTRL_DGRAM_MTU_EXCEEDED + +Returns 1 if the last attempted write to the BIO failed due to the size of the +attempted write exceeding the applicable MTU. + +=item BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT + +Accepts a pointer to a B. If the time specified is zero, +disables receive timeouts. Otherwise, configures the specified time interval as +the receive timeout for the socket for the purposes of future L +calls. + +=item BIO_CTRL_DGRAM_SET_PEEK_MODE + +If B is nonzero, enables peek mode; otherwise, disables peek mode. Where +peek mode is enabled, calls to L read datagrams from the underlying +network socket in peek mode, meaning that a future call to L will +yield the same datagram until peek mode is disabled. + +L is not affected by this control. + +=back + +BIO_new_dgram() is a helper function which instantiates a BIO_s_datagram() and +sets the BIO to use the socket given in I by calling BIO_set_fd(). + +=head1 RETURN VALUES + +BIO_s_datagram() returns a BIO method. + +BIO_new_dgram() returns a BIO on success and NULL on failure. + +BIO_ctrl_dgram_connect(), BIO_ctrl_set_connected(), +BIO_dgram_get_peer(), BIO_dgram_set_peer() return 1 on success and 0 on failure. + +BIO_dgram_recv_timedout() and BIO_dgram_send_timedout() return 0 or 1 depending +on the circumstance; see discussion above. + +BIO_dgram_get_mtu_overhead() returns a value in bytes. + +=head1 SEE ALSO + +L, L, L, L + +=head1 COPYRIGHT + +Copyright 2022 The OpenSSL Project Authors. All Rights Reserved. + +Licensed under the Apache License 2.0 (the "License"). You may not use +this file except in compliance with the License. You can obtain a copy +in the file LICENSE in the source distribution or at +L. + +=cut diff --git a/doc/man3/DTLSv1_listen.pod b/doc/man3/DTLSv1_listen.pod index 13f6f1ff14575..b16a82de9a8e9 100644 --- a/doc/man3/DTLSv1_listen.pod +++ b/doc/man3/DTLSv1_listen.pod @@ -64,6 +64,23 @@ does not support this), then B<*peer> will be cleared and the family set to AF_UNSPEC. Typically user code is expected to "connect" the underlying socket to the peer and continue the handshake in a connected state. +Warning: It is essential that the calling code connects the underlying socket to +the peer after making use of DTLSv1_listen(). In the typical case where +L is used, the peer address is updated when receiving a +datagram on an unconnected socket. If the socket is not connected, it can +receive datagrams from any host on the network, which will cause subsequent +outgoing datagrams transmitted by DTLS to be transmitted to that host. In other +words, failing to call BIO_connect() or a similar OS-specific function on a +socket means that any host on the network can cause outgoing DTLS traffic to be +redirected to it by sending a datagram to the socket in question. This does not +break the cryptographic protections of DTLS but may facilitate a +denial-of-service attack or allow unencrypted information in the DTLS handshake +to be learned by an attacker. This is due to the historical design of +L; see L for details on this issue. + +Once a socket has been connected, L should be used to +inform the BIO that the socket is to be used in connected mode. + Prior to calling DTLSv1_listen() user code must ensure that cookie generation and verification callbacks have been set up using L and L diff --git a/util/missingcrypto.txt b/util/missingcrypto.txt index a70861fb1f1ca..a603ff7545e69 100644 --- a/util/missingcrypto.txt +++ b/util/missingcrypto.txt @@ -201,7 +201,6 @@ BIO_indent(3) BIO_method_name(3) BIO_new_NDEF(3) BIO_new_PKCS7(3) -BIO_new_dgram(3) BIO_new_dgram_sctp(3) BIO_nread(3) BIO_nread0(3) @@ -209,7 +208,6 @@ BIO_number_read(3) BIO_number_written(3) BIO_nwrite(3) BIO_nwrite0(3) -BIO_s_datagram(3) BIO_s_datagram_sctp(3) BIO_s_log(3) BIO_set_flags(3) diff --git a/util/missingmacro.txt b/util/missingmacro.txt index ad03758ba3f56..50b4b17b15c99 100644 --- a/util/missingmacro.txt +++ b/util/missingmacro.txt @@ -12,13 +12,6 @@ BIO_cb_post(3) BIO_dup_state(3) BIO_buffer_get_num_lines(3) BIO_buffer_peek(3) -BIO_ctrl_dgram_connect(3) -BIO_ctrl_set_connected(3) -BIO_dgram_recv_timedout(3) -BIO_dgram_send_timedout(3) -BIO_dgram_get_peer(3) -BIO_dgram_set_peer(3) -BIO_dgram_get_mtu_overhead(3) BIO_sock_cleanup(3) ossl_bio__attr__(3) BN_prime_checks_for_size(3) diff --git a/util/other.syms b/util/other.syms index 94bc79e9eec99..267c0ff39c17e 100644 --- a/util/other.syms +++ b/util/other.syms @@ -161,6 +161,13 @@ BIO_dgram_set_caps define BIO_dgram_get_effective_caps define BIO_dgram_get_mtu define BIO_dgram_set_mtu define +BIO_ctrl_dgram_connect define +BIO_ctrl_set_connected define +BIO_dgram_get_mtu_overhead define +BIO_dgram_get_peer define +BIO_dgram_set_peer define +BIO_dgram_recv_timedout define +BIO_dgram_send_timedout define BIO_do_accept define BIO_do_connect define BIO_do_handshake define