]> git.ipfire.org Git - thirdparty/openssl.git/blob - doc/man7/ossl-guide-quic-client-block.pod
437c57b68a29a84d736da9b8971b92b4fc4f7275
[thirdparty/openssl.git] / doc / man7 / ossl-guide-quic-client-block.pod
1 =pod
2
3 =begin comment
4
5 NB: Changes to the source code samples in this file should also be reflected in
6 demos/guide/quic-client-block.c
7
8 =end comment
9
10 =head1 NAME
11
12 ossl-guide-quic-client-block
13 - OpenSSL Guide: Writing a simple blocking QUIC client
14
15 =head1 SIMPLE BLOCKING QUIC CLIENT EXAMPLE
16
17 This page will present various source code samples demonstrating how to write
18 a simple blocking QUIC client application which connects to a server, sends an
19 HTTP/1.0 request to it, and reads back the response. Note that HTTP/1.0 over
20 QUIC is non-standard and will not typically be supported by real world servers.
21 This is for demonstration purposes only.
22
23 We assume that you already have OpenSSL installed on your system; that you
24 already have some fundamental understanding of OpenSSL concepts, TLS and QUIC
25 (see L<crypto(7)>, L<ossl-guide-tls-introduction(7)> and
26 L<ossl-guide-quic-introduction(7)>); and that you know how to
27 write and build C code and link it against the libcrypto and libssl libraries
28 that are provided by OpenSSL. It also assumes that you have a basic
29 understanding of UDP/IP and sockets. The example code that we build in this
30 tutorial will amend the blocking TLS client example that is covered in
31 L<ossl-guide-tls-client-block(7)>. Only the differences between that client and
32 this one will be discussed so we also assume that you have run through and
33 understand that tutorial.
34
35 For this tutorial our client will be using a single QUIC stream. A subsequent
36 tutorial will discuss how to write a multi-stream client.
37
38 The complete source code for this example blocking QUIC client is available in
39 the C<demos/guide> directory of the OpenSSL source distribution in the file
40 C<quic-client-block.c>. It is also available online at
41 L<https://github.com/openssl/openssl/blob/master/demos/guide/quic-client-block.c>.
42
43 =head2 Creating the SSL_CTX and SSL objects
44
45 In the TLS tutorial (L<ossl-guide-tls-client-block(7)>) we created an B<SSL_CTX>
46 object for our client and used it to create an B<SSL> object to represent the
47 TLS connection. A QUIC connection works in exactly the same way. We first create
48 an B<SSL_CTX> object and then use it to create an B<SSL> object to represent the
49 QUIC connection.
50
51 As in the TLS example the first step is to create an B<SSL_CTX> object for our
52 client. This is done in the same way as before except that we use a different
53 "method". OpenSSL offers two different QUIC client methods, i.e.
54 L<OSSL_QUIC_client_method(3)> and L<OSSL_QUIC_client_thread_method(3)>.
55
56 The first one is the equivalent of L<TLS_client_method(3)> but for the QUIC
57 protocol. The second one is the same, but it will additionally create a
58 background thread for handling time based events (known as "thread assisted
59 mode", see L<ossl-guide-quic-introduction(7)>). For this tutorial we will be
60 using L<OSSL_QUIC_client_method(3)> because we will not be leaving the QUIC
61 connection idle in our application and so thread assisted mode is not needed.
62
63 /*
64 * Create an SSL_CTX which we can use to create SSL objects from. We
65 * want an SSL_CTX for creating clients so we use OSSL_QUIC_client_method()
66 * here.
67 */
68 ctx = SSL_CTX_new(OSSL_QUIC_client_method());
69 if (ctx == NULL) {
70 printf("Failed to create the SSL_CTX\n");
71 goto end;
72 }
73
74 The other setup steps that we applied to the B<SSL_CTX> for TLS also apply to
75 QUIC except for restricting the TLS versions that we are willing to accept. The
76 QUIC protocol implementation in OpenSSL currently only supports TLSv1.3. There
77 is no need to call L<SSL_CTX_set_min_proto_version(3)> or
78 L<SSL_CTX_set_max_proto_version(3)> in an OpenSSL QUIC application, and any such
79 call will be ignored.
80
81 Once the B<SSL_CTX> is created, the B<SSL> object is constructed in exactly the
82 same way as for the TLS application.
83
84 =head2 Creating the socket and BIO
85
86 A major difference between TLS and QUIC is the underlying transport protocol.
87 TLS uses TCP while QUIC uses UDP. The way that the QUIC socket is created in our
88 example code is much the same as for TLS. We use the L<BIO_lookup_ex(3)> and
89 L<BIO_socket(3)> helper functions as we did in the previous tutorial except that
90 we pass B<SOCK_DGRAM> as an argument to indicate UDP (instead of B<SOCK_STREAM>
91 for TCP).
92
93 /*
94 * Lookup IP address info for the server.
95 */
96 if (!BIO_lookup_ex(hostname, port, BIO_LOOKUP_CLIENT, 0, SOCK_DGRAM, 0,
97 &res))
98 return NULL;
99
100 /*
101 * Loop through all the possible addresses for the server and find one
102 * we can connect to.
103 */
104 for (ai = res; ai != NULL; ai = BIO_ADDRINFO_next(ai)) {
105 /*
106 * Create a TCP socket. We could equally use non-OpenSSL calls such
107 * as "socket" here for this and the subsequent connect and close
108 * functions. But for portability reasons and also so that we get
109 * errors on the OpenSSL stack in the event of a failure we use
110 * OpenSSL's versions of these functions.
111 */
112 sock = BIO_socket(BIO_ADDRINFO_family(ai), SOCK_DGRAM, 0, 0);
113 if (sock == -1)
114 continue;
115
116 /* Connect the socket to the server's address */
117 if (!BIO_connect(sock, BIO_ADDRINFO_address(ai), 0)) {
118 BIO_closesocket(sock);
119 sock = -1;
120 continue;
121 }
122
123 /* Set to nonblocking mode */
124 if (!BIO_socket_nbio(sock, 1)) {
125 sock = -1;
126 continue;
127 }
128
129 break;
130 }
131
132 if (sock != -1) {
133 *peer_addr = BIO_ADDR_dup(BIO_ADDRINFO_address(ai));
134 if (*peer_addr == NULL) {
135 BIO_closesocket(sock);
136 return NULL;
137 }
138 }
139
140 /* Free the address information resources we allocated earlier */
141 BIO_ADDRINFO_free(res);
142
143 You may notice a couple of other differences between this code and the version
144 that we used for TLS.
145
146 Firstly, we set the socket into nonblocking mode. This must always be done for
147 an OpenSSL QUIC application. This may be surprising considering that we are
148 trying to write a blocking client. Despite this the B<SSL> object will still
149 have blocking behaviour. See L<ossl-guide-quic-introduction(7)> for further
150 information on this.
151
152 Secondly, we take note of the IP address of the peer that we are connecting to.
153 We store that information away. We will need it later.
154
155 See L<BIO_lookup_ex(3)>, L<BIO_socket(3)>, L<BIO_connect(3)>,
156 L<BIO_closesocket(3)>, L<BIO_ADDRINFO_next(3)>, L<BIO_ADDRINFO_address(3)>,
157 L<BIO_ADDRINFO_free(3)> and L<BIO_ADDR_dup(3)> for further information on the
158 functions used here. In the above example code the B<hostname> and B<port>
159 variables are strings, e.g. "www.example.com" and "443".
160
161 As for our TLS client, once the socket has been created and connected we need to
162 associate it with a BIO object:
163
164 BIO *bio;
165
166 /* Create a BIO to wrap the socket*/
167 bio = BIO_new(BIO_s_datagram());
168 if (bio == NULL)
169 BIO_closesocket(sock);
170
171 /*
172 * Associate the newly created BIO with the underlying socket. By
173 * passing BIO_CLOSE here the socket will be automatically closed when
174 * the BIO is freed. Alternatively you can use BIO_NOCLOSE, in which
175 * case you must close the socket explicitly when it is no longer
176 * needed.
177 */
178 BIO_set_fd(bio, sock, BIO_CLOSE);
179
180 Note the use of L<BIO_s_datagram(3)> here as opposed to L<BIO_s_socket(3)> that
181 we used for our TLS client. This is again due to the fact that QUIC uses UDP
182 instead of TCP for its transport layer. See L<BIO_new(3)>, L<BIO_s_datagram(3)>
183 and L<BIO_set_fd(3)> for further information on these functions.
184
185 =head2 Setting the server's hostname
186
187 As in the TLS tutorial we need to set the server's hostname both for SNI (Server
188 Name Indication) and for certificate validation purposes. The steps for this are
189 identical to the TLS tutorial and won't be repeated here.
190
191 =head2 Setting the ALPN
192
193 ALPN (Application-Layer Protocol Negotiation) is a feature of TLS that enables
194 the application to negotiate which protocol will be used over the connection.
195 For example, if you intend to use HTTP/3 over the connection then the ALPN value
196 for that is "h3" (see
197 L<https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xml#alpn-protocol-ids>).
198 OpenSSL provides the ability for a client to specify the ALPN to use via the
199 L<SSL_set_alpn_protos(3)> function. This is optional for a TLS client and so our
200 simple client that we developed in L<ossl-guide-tls-client-block(7)> did not use
201 it. However QUIC mandates that the TLS handshake used in establishing a QUIC
202 connection must use ALPN.
203
204 unsigned char alpn[] = { 8, 'h', 't', 't', 'p', '/', '1', '.', '0' };
205
206 /* SSL_set_alpn_protos returns 0 for success! */
207 if (SSL_set_alpn_protos(ssl, alpn, sizeof(alpn)) != 0) {
208 printf("Failed to set the ALPN for the connection\n");
209 goto end;
210 }
211
212 The ALPN is specified using a length prefixed array of unsigned chars (it is not
213 a NUL terminated string). Our original TLS blocking client demo was using
214 HTTP/1.0. We will use the same for this example. Unlike most OpenSSL functions
215 L<SSL_set_alpn_protos(3)> returns zero for success and nonzero for failure.
216
217 =head2 Setting the peer address
218
219 An OpenSSL QUIC application must specify the target address of the server that
220 is being connected to. In L</Creating the socket and BIO> above we saved that
221 address away for future use. Now we need to use it via the
222 L<SSL_set_initial_peer_addr(3)> function.
223
224 if (!SSL_set_initial_peer_addr(ssl, peer_addr)) {
225 printf("Failed to set the initial peer address\n");
226 goto end;
227 }
228
229 Note that we will need to free the B<peer_addr> value that we allocated via
230 L<BIO_ADDR_dup(3)> earlier:
231
232 BIO_ADDR_free(peer_addr);
233
234 =head2 The handshake and application data transfer
235
236 Once initial setup of the B<SSL> object is complete then we perform the
237 handshake via L<SSL_connect(3)> in exactly the same way as we did for the TLS
238 client, so we won't repeat it here.
239
240 We can also perform data transfer using a default QUIC stream that is
241 automatically associated with the B<SSL> object for us. We can transmit data
242 using L<SSL_write_ex(3)>, and receive data using L<SSL_read_ex(3)> in exactly
243 the same way as for TLS. Again, we won't repeat it here.
244
245 =head2 Shutting down the connection
246
247 As in the TLS tutorial, once we have finished reading data from the server then
248 we are ready to close the connection down. As before we do this via the
249 L<SSL_shutdown(3)> function. This example for QUIC is very similar to the TLS
250 version. However the L<SSL_shutdown(3)> function may need to be called more than
251 once:
252
253 /*
254 * Repeatedly call SSL_shutdown() until the connection is fully
255 * closed.
256 */
257 do {
258 ret = SSL_shutdown(ssl);
259 if (ret < 0) {
260 printf("Error shutting down: %d\n", ret);
261 goto end;
262 }
263 } while (ret != 1);
264
265 The shutdown process is in two stages. First we gracefully shutdown the
266 connection for sending and secondly we shutdown the connection for receiving.
267 L<SSL_shutdown(3)> returns 0 once the first stage has been completed, and 1 once
268 the second stage is finished. This two stage process applies to TLS as well.
269 However in our blocking TLS client example code we knew that the peer had
270 already partially closed down due to the B<SSL_ERROR_ZERO_RETURN> that we had
271 obtained via L<SSL_get_error(3)> after the final L<SSL_read_ex(3)> call. Due to
272 that return value we knew that the connection was already closed down for
273 receiving data and hence L<SSL_shutdown(3)> should only need to be called once.
274
275 However, with QUIC, the B<SSL_ERROR_ZERO_RETURN> value only tells us that the
276 stream (not the connection) is partially closed down. Therefore we need to call
277 L<SSL_shutdown(3)> more than once to ensure that we progress through both stages
278 of the shutdown process.
279
280 =head1 SEE ALSO
281
282 L<crypto(7)>, L<ossl-guide-tls-introduction(7)>,
283 L<ossl-guide-tls-client-block(7)>, L<ossl-guide-quic-introduction(7)>
284
285 =head1 COPYRIGHT
286
287 Copyright 2023 The OpenSSL Project Authors. All Rights Reserved.
288
289 Licensed under the Apache License 2.0 (the "License"). You may not use
290 this file except in compliance with the License. You can obtain a copy
291 in the file LICENSE in the source distribution or at
292 L<https://www.openssl.org/source/license.html>.
293
294 =cut