]> git.ipfire.org Git - thirdparty/openssl.git/blob - doc/man7/ossl-guide-quic-client-block.pod
fc8912086dae6419dd10f53aa14bc0d2218bf197
[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 be supported by real world servers. This is
21 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<ossl-guide-libraries-introduction(7)>, L<ossl-guide-tls-introduction(7)>
26 and 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 (see
37 L<ossl-guide-quic-multi-stream(7)>).
38
39 The complete source code for this example blocking QUIC client is available in
40 the C<demos/guide> directory of the OpenSSL source distribution in the file
41 C<quic-client-block.c>. It is also available online at
42 L<https://github.com/openssl/openssl/blob/master/demos/guide/quic-client-block.c>.
43
44 =head2 Creating the SSL_CTX and SSL objects
45
46 In the TLS tutorial (L<ossl-guide-tls-client-block(7)>) we created an B<SSL_CTX>
47 object for our client and used it to create an B<SSL> object to represent the
48 TLS connection. A QUIC connection works in exactly the same way. We first create
49 an B<SSL_CTX> object and then use it to create an B<SSL> object to represent the
50 QUIC connection.
51
52 As in the TLS example the first step is to create an B<SSL_CTX> object for our
53 client. This is done in the same way as before except that we use a different
54 "method". OpenSSL offers two different QUIC client methods, i.e.
55 L<OSSL_QUIC_client_method(3)> and L<OSSL_QUIC_client_thread_method(3)>.
56
57 The first one is the equivalent of L<TLS_client_method(3)> but for the QUIC
58 protocol. The second one is the same, but it will additionally create a
59 background thread for handling time based events (known as "thread assisted
60 mode", see L<ossl-guide-quic-introduction(7)>). For this tutorial we will be
61 using L<OSSL_QUIC_client_method(3)> because we will not be leaving the QUIC
62 connection idle in our application and so thread assisted mode is not needed.
63
64 /*
65 * Create an SSL_CTX which we can use to create SSL objects from. We
66 * want an SSL_CTX for creating clients so we use OSSL_QUIC_client_method()
67 * here.
68 */
69 ctx = SSL_CTX_new(OSSL_QUIC_client_method());
70 if (ctx == NULL) {
71 printf("Failed to create the SSL_CTX\n");
72 goto end;
73 }
74
75 The other setup steps that we applied to the B<SSL_CTX> for TLS also apply to
76 QUIC except for restricting the TLS versions that we are willing to accept. The
77 QUIC protocol implementation in OpenSSL currently only supports TLSv1.3. There
78 is no need to call L<SSL_CTX_set_min_proto_version(3)> or
79 L<SSL_CTX_set_max_proto_version(3)> in an OpenSSL QUIC application, and any such
80 call will be ignored.
81
82 Once the B<SSL_CTX> is created, the B<SSL> object is constructed in exactly the
83 same way as for the TLS application.
84
85 =head2 Creating the socket and BIO
86
87 A major difference between TLS and QUIC is the underlying transport protocol.
88 TLS uses TCP while QUIC uses UDP. The way that the QUIC socket is created in our
89 example code is much the same as for TLS. We use the L<BIO_lookup_ex(3)> and
90 L<BIO_socket(3)> helper functions as we did in the previous tutorial except that
91 we pass B<SOCK_DGRAM> as an argument to indicate UDP (instead of B<SOCK_STREAM>
92 for TCP).
93
94 /*
95 * Lookup IP address info for the server.
96 */
97 if (!BIO_lookup_ex(hostname, port, BIO_LOOKUP_CLIENT, 0, SOCK_DGRAM, 0,
98 &res))
99 return NULL;
100
101 /*
102 * Loop through all the possible addresses for the server and find one
103 * we can connect to.
104 */
105 for (ai = res; ai != NULL; ai = BIO_ADDRINFO_next(ai)) {
106 /*
107 * Create a TCP socket. We could equally use non-OpenSSL calls such
108 * as "socket" here for this and the subsequent connect and close
109 * functions. But for portability reasons and also so that we get
110 * errors on the OpenSSL stack in the event of a failure we use
111 * OpenSSL's versions of these functions.
112 */
113 sock = BIO_socket(BIO_ADDRINFO_family(ai), SOCK_DGRAM, 0, 0);
114 if (sock == -1)
115 continue;
116
117 /* Connect the socket to the server's address */
118 if (!BIO_connect(sock, BIO_ADDRINFO_address(ai), 0)) {
119 BIO_closesocket(sock);
120 sock = -1;
121 continue;
122 }
123
124 /* Set to nonblocking mode */
125 if (!BIO_socket_nbio(sock, 1)) {
126 BIO_closesocket(sock);
127 sock = -1;
128 continue;
129 }
130
131 break;
132 }
133
134 if (sock != -1) {
135 *peer_addr = BIO_ADDR_dup(BIO_ADDRINFO_address(ai));
136 if (*peer_addr == NULL) {
137 BIO_closesocket(sock);
138 return NULL;
139 }
140 }
141
142 /* Free the address information resources we allocated earlier */
143 BIO_ADDRINFO_free(res);
144
145 You may notice a couple of other differences between this code and the version
146 that we used for TLS.
147
148 Firstly, we set the socket into nonblocking mode. This must always be done for
149 an OpenSSL QUIC application. This may be surprising considering that we are
150 trying to write a blocking client. Despite this the B<SSL> object will still
151 have blocking behaviour. See L<ossl-guide-quic-introduction(7)> for further
152 information on this.
153
154 Secondly, we take note of the IP address of the peer that we are connecting to.
155 We store that information away. We will need it later.
156
157 See L<BIO_lookup_ex(3)>, L<BIO_socket(3)>, L<BIO_connect(3)>,
158 L<BIO_closesocket(3)>, L<BIO_ADDRINFO_next(3)>, L<BIO_ADDRINFO_address(3)>,
159 L<BIO_ADDRINFO_free(3)> and L<BIO_ADDR_dup(3)> for further information on the
160 functions used here. In the above example code the B<hostname> and B<port>
161 variables are strings, e.g. "www.example.com" and "443".
162
163 As for our TLS client, once the socket has been created and connected we need to
164 associate it with a BIO object:
165
166 BIO *bio;
167
168 /* Create a BIO to wrap the socket */
169 bio = BIO_new(BIO_s_datagram());
170 if (bio == NULL) {
171 BIO_closesocket(sock);
172 return NULL;
173 }
174
175 /*
176 * Associate the newly created BIO with the underlying socket. By
177 * passing BIO_CLOSE here the socket will be automatically closed when
178 * the BIO is freed. Alternatively you can use BIO_NOCLOSE, in which
179 * case you must close the socket explicitly when it is no longer
180 * needed.
181 */
182 BIO_set_fd(bio, sock, BIO_CLOSE);
183
184 Note the use of L<BIO_s_datagram(3)> here as opposed to L<BIO_s_socket(3)> that
185 we used for our TLS client. This is again due to the fact that QUIC uses UDP
186 instead of TCP for its transport layer. See L<BIO_new(3)>, L<BIO_s_datagram(3)>
187 and L<BIO_set_fd(3)> for further information on these functions.
188
189 =head2 Setting the server's hostname
190
191 As in the TLS tutorial we need to set the server's hostname both for SNI (Server
192 Name Indication) and for certificate validation purposes. The steps for this are
193 identical to the TLS tutorial and won't be repeated here.
194
195 =head2 Setting the ALPN
196
197 ALPN (Application-Layer Protocol Negotiation) is a feature of TLS that enables
198 the application to negotiate which protocol will be used over the connection.
199 For example, if you intend to use HTTP/3 over the connection then the ALPN value
200 for that is "h3" (see
201 L<https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xml#alpn-protocol-ids>).
202 OpenSSL provides the ability for a client to specify the ALPN to use via the
203 L<SSL_set_alpn_protos(3)> function. This is optional for a TLS client and so our
204 simple client that we developed in L<ossl-guide-tls-client-block(7)> did not use
205 it. However QUIC mandates that the TLS handshake used in establishing a QUIC
206 connection must use ALPN.
207
208 unsigned char alpn[] = { 8, 'h', 't', 't', 'p', '/', '1', '.', '0' };
209
210 /* SSL_set_alpn_protos returns 0 for success! */
211 if (SSL_set_alpn_protos(ssl, alpn, sizeof(alpn)) != 0) {
212 printf("Failed to set the ALPN for the connection\n");
213 goto end;
214 }
215
216 The ALPN is specified using a length prefixed array of unsigned chars (it is not
217 a NUL terminated string). Our original TLS blocking client demo was using
218 HTTP/1.0. We will use the same for this example. Unlike most OpenSSL functions
219 L<SSL_set_alpn_protos(3)> returns zero for success and nonzero for failure.
220
221 =head2 Setting the peer address
222
223 An OpenSSL QUIC application must specify the target address of the server that
224 is being connected to. In L</Creating the socket and BIO> above we saved that
225 address away for future use. Now we need to use it via the
226 L<SSL_set1_initial_peer_addr(3)> function.
227
228 /* Set the IP address of the remote peer */
229 if (!SSL_set1_initial_peer_addr(ssl, peer_addr)) {
230 printf("Failed to set the initial peer address\n");
231 goto end;
232 }
233
234 Note that we will need to free the B<peer_addr> value that we allocated via
235 L<BIO_ADDR_dup(3)> earlier:
236
237 BIO_ADDR_free(peer_addr);
238
239 =head2 The handshake and application data transfer
240
241 Once initial setup of the B<SSL> object is complete then we perform the
242 handshake via L<SSL_connect(3)> in exactly the same way as we did for the TLS
243 client, so we won't repeat it here.
244
245 We can also perform data transfer using a default QUIC stream that is
246 automatically associated with the B<SSL> object for us. We can transmit data
247 using L<SSL_write_ex(3)>, and receive data using L<SSL_read_ex(3)> in the same
248 way as for TLS. The main difference is that we have to account for failures
249 slightly differently. With QUIC the stream can be reset by the peer (which is
250 fatal for that stream), but the underlying connection itself may still be
251 healthy.
252
253 /*
254 * Get up to sizeof(buf) bytes of the response. We keep reading until the
255 * server closes the connection.
256 */
257 while (SSL_read_ex(ssl, buf, sizeof(buf), &readbytes)) {
258 /*
259 * OpenSSL does not guarantee that the returned data is a string or
260 * that it is NUL terminated so we use fwrite() to write the exact
261 * number of bytes that we read. The data could be non-printable or
262 * have NUL characters in the middle of it. For this simple example
263 * we're going to print it to stdout anyway.
264 */
265 fwrite(buf, 1, readbytes, stdout);
266 }
267 /* In case the response didn't finish with a newline we add one now */
268 printf("\n");
269
270 /*
271 * Check whether we finished the while loop above normally or as the
272 * result of an error. The 0 argument to SSL_get_error() is the return
273 * code we received from the SSL_read_ex() call. It must be 0 in order
274 * to get here. Normal completion is indicated by SSL_ERROR_ZERO_RETURN. In
275 * QUIC terms this means that the peer has sent FIN on the stream to
276 * indicate that no further data will be sent.
277 */
278 switch (SSL_get_error(ssl, 0)) {
279 case SSL_ERROR_ZERO_RETURN:
280 /* Normal completion of the stream */
281 break;
282
283 case SSL_ERROR_SSL:
284 /*
285 * Some stream fatal error occurred. This could be because of a stream
286 * reset - or some failure occurred on the underlying connection.
287 */
288 switch (SSL_get_stream_read_state(ssl)) {
289 case SSL_STREAM_STATE_RESET_REMOTE:
290 printf("Stream reset occurred\n");
291 /* The stream has been reset but the connection is still healthy. */
292 break;
293
294 case SSL_STREAM_STATE_CONN_CLOSED:
295 printf("Connection closed\n");
296 /* Connection is already closed. Skip SSL_shutdown() */
297 goto end;
298
299 default:
300 printf("Unknown stream failure\n");
301 break;
302 }
303 break;
304
305 default:
306 /* Some other unexpected error occurred */
307 printf ("Failed reading remaining data\n");
308 break;
309 }
310
311 In the above code example you can see that B<SSL_ERROR_SSL> indicates a stream
312 fatal error. We can use L<SSL_get_stream_read_state(3)> to determine whether the
313 stream has been reset, or if some other fatal error has occurred.
314
315 =head2 Shutting down the connection
316
317 In the TLS tutorial we knew that the server had finished sending data because
318 L<SSL_read_ex(3)> returned 0, and L<SSL_get_error(3)> returned
319 B<SSL_ERROR_ZERO_RETURN>. The same is true with QUIC except that
320 B<SSL_ERROR_ZERO_RETURN> should be interpreted slightly differently. With TLS
321 we knew that this meant that the server had sent a "close_notify" alert. No
322 more data will be sent from the server on that connection.
323
324 With QUIC it means that the server has indicated "FIN" on the stream, meaning
325 that it will no longer send any more data on that stream. However this only
326 gives us information about the stream itself and does not tell us anything about
327 the underlying connection. More data could still be sent from the server on some
328 other stream. Additionally, although the server will not send any more data to
329 the client, it does not prevent the client from sending more data to the server.
330
331 In this tutorial, once we have finished reading data from the server on the one
332 stream that we are using, we will close the connection down. As before we do
333 this via the L<SSL_shutdown(3)> function. This example for QUIC is very similar
334 to the TLS version. However the L<SSL_shutdown(3)> function will need to be
335 called more than once:
336
337 /*
338 * Repeatedly call SSL_shutdown() until the connection is fully
339 * closed.
340 */
341 do {
342 ret = SSL_shutdown(ssl);
343 if (ret < 0) {
344 printf("Error shutting down: %d\n", ret);
345 goto end;
346 }
347 } while (ret != 1);
348
349 The shutdown process is in two stages. In the first stage we wait until all the
350 data we have buffered for sending on any stream has been successfully sent and
351 acknowledged by the peer, and then we send a CONNECTION_CLOSE to the peer to
352 indicate that the connection is no longer usable. This immediately closes the
353 connection and no more data can be sent or received. L<SSL_shutdown(3)> returns
354 0 once the first stage has been completed.
355
356 In the second stage the connection enters a "closing" state. Application data
357 cannot be sent or received in this state, but late arriving packets coming from
358 the peer will be handled appropriately. Once this stage has completed
359 successfully L<SSL_shutdown(3)> will return 1 to indicate success.
360
361 =head1 FURTHER READING
362
363 See L<ossl-guide-quic-multi-stream(7)> to read a tutorial on how to modify the
364 client developed on this page to support multiple streams.
365
366 =head1 SEE ALSO
367
368 L<ossl-guide-introduction(7)>, L<ossl-guide-libraries-introduction(7)>,
369 L<ossl-guide-libssl-introduction(7)>, L<ossl-guide-tls-introduction(7)>,
370 L<ossl-guide-tls-client-block(7)>, L<ossl-guide-quic-introduction(7)>
371
372 =head1 COPYRIGHT
373
374 Copyright 2023 The OpenSSL Project Authors. All Rights Reserved.
375
376 Licensed under the Apache License 2.0 (the "License"). You may not use
377 this file except in compliance with the License. You can obtain a copy
378 in the file LICENSE in the source distribution or at
379 L<https://www.openssl.org/source/license.html>.
380
381 =cut