BIO_s_dgram: add documentation and hazard warnings

Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: Paul Dale <pauli@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/19795)
This commit is contained in:
Hugo Landau 2022-11-30 19:24:15 +00:00
parent a167e048a4
commit 408622b73a
6 changed files with 285 additions and 9 deletions

View File

@ -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 \

255
doc/man3/BIO_s_datagram.pod Normal file
View File

@ -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 <openssl/bio.h>
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<BIO_s_dgram_pair(3)>.
This BIO supports the L<BIO_sendmmsg(3)> and L<BIO_recvmmsg(3)> 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<BIO_connect(3)> 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<BIO_sendmmsg(3)> and L<BIO_recvmmsg(3)> methods
only and forego use of L<BIO_read(3)> and L<BIO_write(3)>. An exception is where
L<DTLSv1_listen(3)> must be used; see L<DTLSv1_listen(3)> for further
discussion.
=item
Unlike L<BIO_read(3)> and L<BIO_write(3)>, the L<BIO_sendmmsg(3)> and
L<BIO_recvmmsg(3)> 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<BIO_ctrl(3)>:
=over 4
=item BIO_ctrl_dgram_connect (BIO_CTRL_DGRAM_CONNECT)
This is equivalent to calling L<BIO_dgram_set_peer(3)>.
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<peer> 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<peer> argument should specify the peer address to which the socket
is connected.
If the I<peer> 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<BIO_sendmmsg(3)> or
L<BIO_recvmmsg(3)>.
=item BIO_dgram_get_peer (BIO_CTRL_DGRAM_GET_PEER)
This outputs a B<BIO_ADDR> 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<BIO_read(3)>, making use of BIO_s_datagram()
hazardous when used with unconnected network sockets; see above.
This does not affect the operation of L<BIO_sendmmsg(3)>.
L<BIO_recvmmsg(3)> 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<BIO_read(3)>) 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<BIO_write(3)>) 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<num> 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<num> 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<struct timeval>. 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<BIO_read(3)>
calls.
=item BIO_CTRL_DGRAM_SET_PEEK_MODE
If B<num> is nonzero, enables peek mode; otherwise, disables peek mode. Where
peek mode is enabled, calls to L<BIO_read(3)> read datagrams from the underlying
network socket in peek mode, meaning that a future call to L<BIO_read(3)> will
yield the same datagram until peek mode is disabled.
L<BIO_recvmmsg(3)> 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<fd> 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<BIO_sendmmsg(3)>, L<BIO_s_dgram_pair(3)>, L<DTLSv1_listen(3)>, L<bio(7)>
=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<https://www.openssl.org/source/license.html>.
=cut

View File

@ -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<BIO_s_datagram(3)> 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<BIO_s_datagram(3)>; see L<BIO_s_datagram(3)> for details on this issue.
Once a socket has been connected, L<BIO_ctrl_set_connected(3)> 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<SSL_CTX_set_cookie_generate_cb(3)> and L<SSL_CTX_set_cookie_verify_cb(3)>

View File

@ -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)

View File

@ -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)

View File

@ -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