summaryrefslogtreecommitdiffstats
path: root/upstream/debian-unstable/man7/ossl-guide-quic-client-block.7ssl
diff options
context:
space:
mode:
Diffstat (limited to 'upstream/debian-unstable/man7/ossl-guide-quic-client-block.7ssl')
-rw-r--r--upstream/debian-unstable/man7/ossl-guide-quic-client-block.7ssl436
1 files changed, 436 insertions, 0 deletions
diff --git a/upstream/debian-unstable/man7/ossl-guide-quic-client-block.7ssl b/upstream/debian-unstable/man7/ossl-guide-quic-client-block.7ssl
new file mode 100644
index 00000000..73ef8d9b
--- /dev/null
+++ b/upstream/debian-unstable/man7/ossl-guide-quic-client-block.7ssl
@@ -0,0 +1,436 @@
+.\" -*- mode: troff; coding: utf-8 -*-
+.\" Automatically generated by Pod::Man 5.01 (Pod::Simple 3.43)
+.\"
+.\" Standard preamble:
+.\" ========================================================================
+.de Sp \" Vertical space (when we can't use .PP)
+.if t .sp .5v
+.if n .sp
+..
+.de Vb \" Begin verbatim text
+.ft CW
+.nf
+.ne \\$1
+..
+.de Ve \" End verbatim text
+.ft R
+.fi
+..
+.\" \*(C` and \*(C' are quotes in nroff, nothing in troff, for use with C<>.
+.ie n \{\
+. ds C` ""
+. ds C' ""
+'br\}
+.el\{\
+. ds C`
+. ds C'
+'br\}
+.\"
+.\" Escape single quotes in literal strings from groff's Unicode transform.
+.ie \n(.g .ds Aq \(aq
+.el .ds Aq '
+.\"
+.\" If the F register is >0, we'll generate index entries on stderr for
+.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index
+.\" entries marked with X<> in POD. Of course, you'll have to process the
+.\" output yourself in some meaningful fashion.
+.\"
+.\" Avoid warning from groff about undefined register 'F'.
+.de IX
+..
+.nr rF 0
+.if \n(.g .if rF .nr rF 1
+.if (\n(rF:(\n(.g==0)) \{\
+. if \nF \{\
+. de IX
+. tm Index:\\$1\t\\n%\t"\\$2"
+..
+. if !\nF==2 \{\
+. nr % 0
+. nr F 2
+. \}
+. \}
+.\}
+.rr rF
+.\" ========================================================================
+.\"
+.IX Title "OSSL-GUIDE-QUIC-CLIENT-BLOCK 7SSL"
+.TH OSSL-GUIDE-QUIC-CLIENT-BLOCK 7SSL 2024-04-04 3.2.2-dev OpenSSL
+.\" For nroff, turn off justification. Always turn off hyphenation; it makes
+.\" way too many mistakes in technical documents.
+.if n .ad l
+.nh
+.SH NAME
+ossl\-guide\-quic\-client\-block
+\&\- OpenSSL Guide: Writing a simple blocking QUIC client
+.SH "SIMPLE BLOCKING QUIC CLIENT EXAMPLE"
+.IX Header "SIMPLE BLOCKING QUIC CLIENT EXAMPLE"
+This page will present various source code samples demonstrating how to write
+a simple blocking QUIC client application which connects to a server, sends an
+HTTP/1.0 request to it, and reads back the response. Note that HTTP/1.0 over
+QUIC is non-standard and will not be supported by real world servers. This is
+for demonstration purposes only.
+.PP
+We assume that you already have OpenSSL installed on your system; that you
+already have some fundamental understanding of OpenSSL concepts, TLS and QUIC
+(see \fBossl\-guide\-libraries\-introduction\fR\|(7), \fBossl\-guide\-tls\-introduction\fR\|(7)
+and \fBossl\-guide\-quic\-introduction\fR\|(7)); and that you know how to
+write and build C code and link it against the libcrypto and libssl libraries
+that are provided by OpenSSL. It also assumes that you have a basic
+understanding of UDP/IP and sockets. The example code that we build in this
+tutorial will amend the blocking TLS client example that is covered in
+\&\fBossl\-guide\-tls\-client\-block\fR\|(7). Only the differences between that client and
+this one will be discussed so we also assume that you have run through and
+understand that tutorial.
+.PP
+For this tutorial our client will be using a single QUIC stream. A subsequent
+tutorial will discuss how to write a multi-stream client (see
+\&\fBossl\-guide\-quic\-multi\-stream\fR\|(7)).
+.PP
+The complete source code for this example blocking QUIC client is available in
+the \f(CW\*(C`demos/guide\*(C'\fR directory of the OpenSSL source distribution in the file
+\&\f(CW\*(C`quic\-client\-block.c\*(C'\fR. It is also available online at
+<https://github.com/openssl/openssl/blob/master/demos/guide/quic\-client\-block.c>.
+.SS "Creating the SSL_CTX and SSL objects"
+.IX Subsection "Creating the SSL_CTX and SSL objects"
+In the TLS tutorial (\fBossl\-guide\-tls\-client\-block\fR\|(7)) we created an \fBSSL_CTX\fR
+object for our client and used it to create an \fBSSL\fR object to represent the
+TLS connection. A QUIC connection works in exactly the same way. We first create
+an \fBSSL_CTX\fR object and then use it to create an \fBSSL\fR object to represent the
+QUIC connection.
+.PP
+As in the TLS example the first step is to create an \fBSSL_CTX\fR object for our
+client. This is done in the same way as before except that we use a different
+"method". OpenSSL offers two different QUIC client methods, i.e.
+\&\fBOSSL_QUIC_client_method\fR\|(3) and \fBOSSL_QUIC_client_thread_method\fR\|(3).
+.PP
+The first one is the equivalent of \fBTLS_client_method\fR\|(3) but for the QUIC
+protocol. The second one is the same, but it will additionally create a
+background thread for handling time based events (known as "thread assisted
+mode", see \fBossl\-guide\-quic\-introduction\fR\|(7)). For this tutorial we will be
+using \fBOSSL_QUIC_client_method\fR\|(3) because we will not be leaving the QUIC
+connection idle in our application and so thread assisted mode is not needed.
+.PP
+.Vb 10
+\& /*
+\& * Create an SSL_CTX which we can use to create SSL objects from. We
+\& * want an SSL_CTX for creating clients so we use OSSL_QUIC_client_method()
+\& * here.
+\& */
+\& ctx = SSL_CTX_new(OSSL_QUIC_client_method());
+\& if (ctx == NULL) {
+\& printf("Failed to create the SSL_CTX\en");
+\& goto end;
+\& }
+.Ve
+.PP
+The other setup steps that we applied to the \fBSSL_CTX\fR for TLS also apply to
+QUIC except for restricting the TLS versions that we are willing to accept. The
+QUIC protocol implementation in OpenSSL currently only supports TLSv1.3. There
+is no need to call \fBSSL_CTX_set_min_proto_version\fR\|(3) or
+\&\fBSSL_CTX_set_max_proto_version\fR\|(3) in an OpenSSL QUIC application, and any such
+call will be ignored.
+.PP
+Once the \fBSSL_CTX\fR is created, the \fBSSL\fR object is constructed in exactly the
+same way as for the TLS application.
+.SS "Creating the socket and BIO"
+.IX Subsection "Creating the socket and BIO"
+A major difference between TLS and QUIC is the underlying transport protocol.
+TLS uses TCP while QUIC uses UDP. The way that the QUIC socket is created in our
+example code is much the same as for TLS. We use the \fBBIO_lookup_ex\fR\|(3) and
+\&\fBBIO_socket\fR\|(3) helper functions as we did in the previous tutorial except that
+we pass \fBSOCK_DGRAM\fR as an argument to indicate UDP (instead of \fBSOCK_STREAM\fR
+for TCP).
+.PP
+.Vb 6
+\& /*
+\& * Lookup IP address info for the server.
+\& */
+\& if (!BIO_lookup_ex(hostname, port, BIO_LOOKUP_CLIENT, family, SOCK_DGRAM, 0,
+\& &res))
+\& return NULL;
+\&
+\& /*
+\& * Loop through all the possible addresses for the server and find one
+\& * we can connect to.
+\& */
+\& for (ai = res; ai != NULL; ai = BIO_ADDRINFO_next(ai)) {
+\& /*
+\& * Create a TCP socket. We could equally use non\-OpenSSL calls such
+\& * as "socket" here for this and the subsequent connect and close
+\& * functions. But for portability reasons and also so that we get
+\& * errors on the OpenSSL stack in the event of a failure we use
+\& * OpenSSL\*(Aqs versions of these functions.
+\& */
+\& sock = BIO_socket(BIO_ADDRINFO_family(ai), SOCK_DGRAM, 0, 0);
+\& if (sock == \-1)
+\& continue;
+\&
+\& /* Connect the socket to the server\*(Aqs address */
+\& if (!BIO_connect(sock, BIO_ADDRINFO_address(ai), 0)) {
+\& BIO_closesocket(sock);
+\& sock = \-1;
+\& continue;
+\& }
+\&
+\& /* Set to nonblocking mode */
+\& if (!BIO_socket_nbio(sock, 1)) {
+\& BIO_closesocket(sock);
+\& sock = \-1;
+\& continue;
+\& }
+\&
+\& break;
+\& }
+\&
+\& if (sock != \-1) {
+\& *peer_addr = BIO_ADDR_dup(BIO_ADDRINFO_address(ai));
+\& if (*peer_addr == NULL) {
+\& BIO_closesocket(sock);
+\& return NULL;
+\& }
+\& }
+\&
+\& /* Free the address information resources we allocated earlier */
+\& BIO_ADDRINFO_free(res);
+.Ve
+.PP
+You may notice a couple of other differences between this code and the version
+that we used for TLS.
+.PP
+Firstly, we set the socket into nonblocking mode. This must always be done for
+an OpenSSL QUIC application. This may be surprising considering that we are
+trying to write a blocking client. Despite this the \fBSSL\fR object will still
+have blocking behaviour. See \fBossl\-guide\-quic\-introduction\fR\|(7) for further
+information on this.
+.PP
+Secondly, we take note of the IP address of the peer that we are connecting to.
+We store that information away. We will need it later.
+.PP
+See \fBBIO_lookup_ex\fR\|(3), \fBBIO_socket\fR\|(3), \fBBIO_connect\fR\|(3),
+\&\fBBIO_closesocket\fR\|(3), \fBBIO_ADDRINFO_next\fR\|(3), \fBBIO_ADDRINFO_address\fR\|(3),
+\&\fBBIO_ADDRINFO_free\fR\|(3) and \fBBIO_ADDR_dup\fR\|(3) for further information on the
+functions used here. In the above example code the \fBhostname\fR and \fBport\fR
+variables are strings, e.g. "www.example.com" and "443".
+.PP
+As for our TLS client, once the socket has been created and connected we need to
+associate it with a BIO object:
+.PP
+.Vb 1
+\& BIO *bio;
+\&
+\& /* Create a BIO to wrap the socket */
+\& bio = BIO_new(BIO_s_datagram());
+\& if (bio == NULL) {
+\& BIO_closesocket(sock);
+\& return NULL;
+\& }
+\&
+\& /*
+\& * Associate the newly created BIO with the underlying socket. By
+\& * passing BIO_CLOSE here the socket will be automatically closed when
+\& * the BIO is freed. Alternatively you can use BIO_NOCLOSE, in which
+\& * case you must close the socket explicitly when it is no longer
+\& * needed.
+\& */
+\& BIO_set_fd(bio, sock, BIO_CLOSE);
+.Ve
+.PP
+Note the use of \fBBIO_s_datagram\fR\|(3) here as opposed to \fBBIO_s_socket\fR\|(3) that
+we used for our TLS client. This is again due to the fact that QUIC uses UDP
+instead of TCP for its transport layer. See \fBBIO_new\fR\|(3), \fBBIO_s_datagram\fR\|(3)
+and \fBBIO_set_fd\fR\|(3) for further information on these functions.
+.SS "Setting the server's hostname"
+.IX Subsection "Setting the server's hostname"
+As in the TLS tutorial we need to set the server's hostname both for SNI (Server
+Name Indication) and for certificate validation purposes. The steps for this are
+identical to the TLS tutorial and won't be repeated here.
+.SS "Setting the ALPN"
+.IX Subsection "Setting the ALPN"
+ALPN (Application-Layer Protocol Negotiation) is a feature of TLS that enables
+the application to negotiate which protocol will be used over the connection.
+For example, if you intend to use HTTP/3 over the connection then the ALPN value
+for that is "h3" (see
+<https://www.iana.org/assignments/tls\-extensiontype\-values/tls\-extensiontype\-values.xml#alpn\-protocol\-ids>).
+OpenSSL provides the ability for a client to specify the ALPN to use via the
+\&\fBSSL_set_alpn_protos\fR\|(3) function. This is optional for a TLS client and so our
+simple client that we developed in \fBossl\-guide\-tls\-client\-block\fR\|(7) did not use
+it. However QUIC mandates that the TLS handshake used in establishing a QUIC
+connection must use ALPN.
+.PP
+.Vb 1
+\& unsigned char alpn[] = { 8, \*(Aqh\*(Aq, \*(Aqt\*(Aq, \*(Aqt\*(Aq, \*(Aqp\*(Aq, \*(Aq/\*(Aq, \*(Aq1\*(Aq, \*(Aq.\*(Aq, \*(Aq0\*(Aq };
+\&
+\& /* SSL_set_alpn_protos returns 0 for success! */
+\& if (SSL_set_alpn_protos(ssl, alpn, sizeof(alpn)) != 0) {
+\& printf("Failed to set the ALPN for the connection\en");
+\& goto end;
+\& }
+.Ve
+.PP
+The ALPN is specified using a length prefixed array of unsigned chars (it is not
+a NUL terminated string). Our original TLS blocking client demo was using
+HTTP/1.0. We will use the same for this example. Unlike most OpenSSL functions
+\&\fBSSL_set_alpn_protos\fR\|(3) returns zero for success and nonzero for failure.
+.SS "Setting the peer address"
+.IX Subsection "Setting the peer address"
+An OpenSSL QUIC application must specify the target address of the server that
+is being connected to. In "Creating the socket and BIO" above we saved that
+address away for future use. Now we need to use it via the
+\&\fBSSL_set1_initial_peer_addr\fR\|(3) function.
+.PP
+.Vb 5
+\& /* Set the IP address of the remote peer */
+\& if (!SSL_set1_initial_peer_addr(ssl, peer_addr)) {
+\& printf("Failed to set the initial peer address\en");
+\& goto end;
+\& }
+.Ve
+.PP
+Note that we will need to free the \fBpeer_addr\fR value that we allocated via
+\&\fBBIO_ADDR_dup\fR\|(3) earlier:
+.PP
+.Vb 1
+\& BIO_ADDR_free(peer_addr);
+.Ve
+.SS "The handshake and application data transfer"
+.IX Subsection "The handshake and application data transfer"
+Once initial setup of the \fBSSL\fR object is complete then we perform the
+handshake via \fBSSL_connect\fR\|(3) in exactly the same way as we did for the TLS
+client, so we won't repeat it here.
+.PP
+We can also perform data transfer using a default QUIC stream that is
+automatically associated with the \fBSSL\fR object for us. We can transmit data
+using \fBSSL_write_ex\fR\|(3), and receive data using \fBSSL_read_ex\fR\|(3) in the same
+way as for TLS. The main difference is that we have to account for failures
+slightly differently. With QUIC the stream can be reset by the peer (which is
+fatal for that stream), but the underlying connection itself may still be
+healthy.
+.PP
+.Vb 10
+\& /*
+\& * Get up to sizeof(buf) bytes of the response. We keep reading until the
+\& * server closes the connection.
+\& */
+\& while (SSL_read_ex(ssl, buf, sizeof(buf), &readbytes)) {
+\& /*
+\& * OpenSSL does not guarantee that the returned data is a string or
+\& * that it is NUL terminated so we use fwrite() to write the exact
+\& * number of bytes that we read. The data could be non\-printable or
+\& * have NUL characters in the middle of it. For this simple example
+\& * we\*(Aqre going to print it to stdout anyway.
+\& */
+\& fwrite(buf, 1, readbytes, stdout);
+\& }
+\& /* In case the response didn\*(Aqt finish with a newline we add one now */
+\& printf("\en");
+\&
+\& /*
+\& * Check whether we finished the while loop above normally or as the
+\& * result of an error. The 0 argument to SSL_get_error() is the return
+\& * code we received from the SSL_read_ex() call. It must be 0 in order
+\& * to get here. Normal completion is indicated by SSL_ERROR_ZERO_RETURN. In
+\& * QUIC terms this means that the peer has sent FIN on the stream to
+\& * indicate that no further data will be sent.
+\& */
+\& switch (SSL_get_error(ssl, 0)) {
+\& case SSL_ERROR_ZERO_RETURN:
+\& /* Normal completion of the stream */
+\& break;
+\&
+\& case SSL_ERROR_SSL:
+\& /*
+\& * Some stream fatal error occurred. This could be because of a stream
+\& * reset \- or some failure occurred on the underlying connection.
+\& */
+\& switch (SSL_get_stream_read_state(ssl)) {
+\& case SSL_STREAM_STATE_RESET_REMOTE:
+\& printf("Stream reset occurred\en");
+\& /* The stream has been reset but the connection is still healthy. */
+\& break;
+\&
+\& case SSL_STREAM_STATE_CONN_CLOSED:
+\& printf("Connection closed\en");
+\& /* Connection is already closed. Skip SSL_shutdown() */
+\& goto end;
+\&
+\& default:
+\& printf("Unknown stream failure\en");
+\& break;
+\& }
+\& break;
+\&
+\& default:
+\& /* Some other unexpected error occurred */
+\& printf ("Failed reading remaining data\en");
+\& break;
+\& }
+.Ve
+.PP
+In the above code example you can see that \fBSSL_ERROR_SSL\fR indicates a stream
+fatal error. We can use \fBSSL_get_stream_read_state\fR\|(3) to determine whether the
+stream has been reset, or if some other fatal error has occurred.
+.SS "Shutting down the connection"
+.IX Subsection "Shutting down the connection"
+In the TLS tutorial we knew that the server had finished sending data because
+\&\fBSSL_read_ex\fR\|(3) returned 0, and \fBSSL_get_error\fR\|(3) returned
+\&\fBSSL_ERROR_ZERO_RETURN\fR. The same is true with QUIC except that
+\&\fBSSL_ERROR_ZERO_RETURN\fR should be interpreted slightly differently. With TLS
+we knew that this meant that the server had sent a "close_notify" alert. No
+more data will be sent from the server on that connection.
+.PP
+With QUIC it means that the server has indicated "FIN" on the stream, meaning
+that it will no longer send any more data on that stream. However this only
+gives us information about the stream itself and does not tell us anything about
+the underlying connection. More data could still be sent from the server on some
+other stream. Additionally, although the server will not send any more data to
+the client, it does not prevent the client from sending more data to the server.
+.PP
+In this tutorial, once we have finished reading data from the server on the one
+stream that we are using, we will close the connection down. As before we do
+this via the \fBSSL_shutdown\fR\|(3) function. This example for QUIC is very similar
+to the TLS version. However the \fBSSL_shutdown\fR\|(3) function will need to be
+called more than once:
+.PP
+.Vb 11
+\& /*
+\& * Repeatedly call SSL_shutdown() until the connection is fully
+\& * closed.
+\& */
+\& do {
+\& ret = SSL_shutdown(ssl);
+\& if (ret < 0) {
+\& printf("Error shutting down: %d\en", ret);
+\& goto end;
+\& }
+\& } while (ret != 1);
+.Ve
+.PP
+The shutdown process is in two stages. In the first stage we wait until all the
+data we have buffered for sending on any stream has been successfully sent and
+acknowledged by the peer, and then we send a CONNECTION_CLOSE to the peer to
+indicate that the connection is no longer usable. This immediately closes the
+connection and no more data can be sent or received. \fBSSL_shutdown\fR\|(3) returns
+0 once the first stage has been completed.
+.PP
+In the second stage the connection enters a "closing" state. Application data
+cannot be sent or received in this state, but late arriving packets coming from
+the peer will be handled appropriately. Once this stage has completed
+successfully \fBSSL_shutdown\fR\|(3) will return 1 to indicate success.
+.SH "FURTHER READING"
+.IX Header "FURTHER READING"
+See \fBossl\-guide\-quic\-multi\-stream\fR\|(7) to read a tutorial on how to modify the
+client developed on this page to support multiple streams.
+.SH "SEE ALSO"
+.IX Header "SEE ALSO"
+\&\fBossl\-guide\-introduction\fR\|(7), \fBossl\-guide\-libraries\-introduction\fR\|(7),
+\&\fBossl\-guide\-libssl\-introduction\fR\|(7), \fBossl\-guide\-tls\-introduction\fR\|(7),
+\&\fBossl\-guide\-tls\-client\-block\fR\|(7), \fBossl\-guide\-quic\-introduction\fR\|(7)
+.SH COPYRIGHT
+.IX Header "COPYRIGHT"
+Copyright 2023 The OpenSSL Project Authors. All Rights Reserved.
+.PP
+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
+<https://www.openssl.org/source/license.html>.