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/tls-client-block.c
|
---|
7 |
|
---|
8 | =end comment
|
---|
9 |
|
---|
10 | =head1 NAME
|
---|
11 |
|
---|
12 | ossl-guide-tls-client-block
|
---|
13 | - OpenSSL Guide: Writing a simple blocking TLS client
|
---|
14 |
|
---|
15 | =head1 SIMPLE BLOCKING TLS CLIENT EXAMPLE
|
---|
16 |
|
---|
17 | This page will present various source code samples demonstrating how to write
|
---|
18 | a simple TLS client application which connects to a server, sends an HTTP/1.0
|
---|
19 | request to it, and reads back the response.
|
---|
20 |
|
---|
21 | We use a blocking socket for the purposes of this example. This means that
|
---|
22 | attempting to read data from a socket that has no data available on it to read
|
---|
23 | will block (and the function will not return), until data becomes available.
|
---|
24 | For example, this can happen if we have sent our request, but we are still
|
---|
25 | waiting for the server's response. Similarly any attempts to write to a socket
|
---|
26 | that is not able to write at the moment will block until writing is possible.
|
---|
27 |
|
---|
28 | This blocking behaviour simplifies the implementation of a client because you do
|
---|
29 | not have to worry about what happens if data is not yet available. The
|
---|
30 | application will simply wait until it is available.
|
---|
31 |
|
---|
32 | The complete source code for this example blocking TLS client is available in
|
---|
33 | the B<demos/guide> directory of the OpenSSL source distribution in the file
|
---|
34 | B<tls-client-block.c>. It is also available online at
|
---|
35 | L<https://github.com/openssl/openssl/blob/master/demos/guide/tls-client-block.c>.
|
---|
36 |
|
---|
37 | We assume that you already have OpenSSL installed on your system; that you
|
---|
38 | already have some fundamental understanding of OpenSSL concepts and TLS (see
|
---|
39 | L<ossl-guide-libraries-introduction(7)> and L<ossl-guide-tls-introduction(7)>);
|
---|
40 | and that you know how to write and build C code and link it against the
|
---|
41 | libcrypto and libssl libraries that are provided by OpenSSL. It also assumes
|
---|
42 | that you have a basic understanding of TCP/IP and sockets.
|
---|
43 |
|
---|
44 | =head2 Creating the SSL_CTX and SSL objects
|
---|
45 |
|
---|
46 | The first step is to create an B<SSL_CTX> object for our client. We use the
|
---|
47 | L<SSL_CTX_new(3)> function for this purpose. We could alternatively use
|
---|
48 | L<SSL_CTX_new_ex(3)> if we want to associate the B<SSL_CTX> with a particular
|
---|
49 | B<OSSL_LIB_CTX> (see L<ossl-guide-libraries-introduction(7)> to learn about
|
---|
50 | B<OSSL_LIB_CTX>). We pass as an argument the return value of the function
|
---|
51 | L<TLS_client_method(3)>. You should use this method whenever you are writing a
|
---|
52 | TLS client. This method will automatically use TLS version negotiation to select
|
---|
53 | the highest version of the protocol that is mutually supported by both the
|
---|
54 | client and the server.
|
---|
55 |
|
---|
56 | /*
|
---|
57 | * Create an SSL_CTX which we can use to create SSL objects from. We
|
---|
58 | * want an SSL_CTX for creating clients so we use TLS_client_method()
|
---|
59 | * here.
|
---|
60 | */
|
---|
61 | ctx = SSL_CTX_new(TLS_client_method());
|
---|
62 | if (ctx == NULL) {
|
---|
63 | printf("Failed to create the SSL_CTX\n");
|
---|
64 | goto end;
|
---|
65 | }
|
---|
66 |
|
---|
67 | Since we are writing a client we must ensure that we verify the server's
|
---|
68 | certificate. We do this by calling the L<SSL_CTX_set_verify(3)> function and
|
---|
69 | pass the B<SSL_VERIFY_PEER> value to it. The final argument to this function
|
---|
70 | is a callback that you can optionally supply to override the default handling
|
---|
71 | for certificate verification. Most applications do not need to do this so this
|
---|
72 | can safely be set to NULL to get the default handling.
|
---|
73 |
|
---|
74 | /*
|
---|
75 | * Configure the client to abort the handshake if certificate
|
---|
76 | * verification fails. Virtually all clients should do this unless you
|
---|
77 | * really know what you are doing.
|
---|
78 | */
|
---|
79 | SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);
|
---|
80 |
|
---|
81 | In order for certificate verification to be successful you must have configured
|
---|
82 | where the trusted certificate store to be used is located (see
|
---|
83 | L<ossl-guide-tls-introduction(7)>). In most cases you just want to use the
|
---|
84 | default store so we call L<SSL_CTX_set_default_verify_paths(3)>.
|
---|
85 |
|
---|
86 | /* Use the default trusted certificate store */
|
---|
87 | if (!SSL_CTX_set_default_verify_paths(ctx)) {
|
---|
88 | printf("Failed to set the default trusted certificate store\n");
|
---|
89 | goto end;
|
---|
90 | }
|
---|
91 |
|
---|
92 | We would also like to restrict the TLS versions that we are willing to accept to
|
---|
93 | TLSv1.2 or above. TLS protocol versions earlier than that are generally to be
|
---|
94 | avoided where possible. We can do that using
|
---|
95 | L<SSL_CTX_set_min_proto_version(3)>:
|
---|
96 |
|
---|
97 | /*
|
---|
98 | * TLSv1.1 or earlier are deprecated by IETF and are generally to be
|
---|
99 | * avoided if possible. We require a minimum TLS version of TLSv1.2.
|
---|
100 | */
|
---|
101 | if (!SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION)) {
|
---|
102 | printf("Failed to set the minimum TLS protocol version\n");
|
---|
103 | goto end;
|
---|
104 | }
|
---|
105 |
|
---|
106 | That is all the setup that we need to do for the B<SSL_CTX>, so next we need to
|
---|
107 | create an B<SSL> object to represent the TLS connection. In a real application
|
---|
108 | we might expect to be creating more than one TLS connection over time. In that
|
---|
109 | case we would expect to reuse the B<SSL_CTX> that we already created each time.
|
---|
110 | There is no need to repeat those steps. In fact it is best not to since certain
|
---|
111 | internal resources are cached in the B<SSL_CTX>. You will get better performance
|
---|
112 | by reusing an existing B<SSL_CTX> instead of creating a new one each time.
|
---|
113 |
|
---|
114 | Creating the B<SSL> object is a simple matter of calling the B<SSL_new(3)>
|
---|
115 | function and passing the B<SSL_CTX> we created as an argument.
|
---|
116 |
|
---|
117 | /* Create an SSL object to represent the TLS connection */
|
---|
118 | ssl = SSL_new(ctx);
|
---|
119 | if (ssl == NULL) {
|
---|
120 | printf("Failed to create the SSL object\n");
|
---|
121 | goto end;
|
---|
122 | }
|
---|
123 |
|
---|
124 | =head2 Creating the socket and BIO
|
---|
125 |
|
---|
126 | TLS data is transmitted over an underlying transport layer. Normally a TCP
|
---|
127 | socket. It is the application's responsibility for ensuring that the socket is
|
---|
128 | created and associated with an SSL object (via a BIO).
|
---|
129 |
|
---|
130 | Socket creation for use by a client is typically a 2 step process, i.e.
|
---|
131 | constructing the socket; and connecting the socket.
|
---|
132 |
|
---|
133 | How to construct a socket is platform specific - but most platforms (including
|
---|
134 | Windows) provide a POSIX compatible interface via the I<socket> function, e.g.
|
---|
135 | to create an IPv4 TCP socket:
|
---|
136 |
|
---|
137 | int sock;
|
---|
138 |
|
---|
139 | sock = socket(AF_INET, SOCK_STREAM, 0);
|
---|
140 | if (sock == -1)
|
---|
141 | return NULL;
|
---|
142 |
|
---|
143 | Once the socket is constructed it must be connected to the remote server. Again
|
---|
144 | the details are platform specific but most platforms (including Windows)
|
---|
145 | provide the POSIX compatible I<connect> function. For example:
|
---|
146 |
|
---|
147 | struct sockaddr_in serveraddr;
|
---|
148 | struct hostent *server;
|
---|
149 |
|
---|
150 | server = gethostbyname("www.openssl.org");
|
---|
151 | if (server == NULL) {
|
---|
152 | close(sock);
|
---|
153 | return NULL;
|
---|
154 | }
|
---|
155 |
|
---|
156 | memset(&serveraddr, 0, sizeof(serveraddr));
|
---|
157 | serveraddr.sin_family = server->h_addrtype;
|
---|
158 | serveraddr.sin_port = htons(443);
|
---|
159 | memcpy(&serveraddr.sin_addr.s_addr, server->h_addr, server->h_length);
|
---|
160 |
|
---|
161 | if (connect(sock, (struct sockaddr *)&serveraddr,
|
---|
162 | sizeof(serveraddr)) == -1) {
|
---|
163 | close(sock);
|
---|
164 | return NULL;
|
---|
165 | }
|
---|
166 |
|
---|
167 | OpenSSL provides portable helper functions to do these tasks which also
|
---|
168 | integrate into the OpenSSL error system to log error data, e.g.
|
---|
169 |
|
---|
170 | int sock = -1;
|
---|
171 | BIO_ADDRINFO *res;
|
---|
172 | const BIO_ADDRINFO *ai = NULL;
|
---|
173 |
|
---|
174 | /*
|
---|
175 | * Lookup IP address info for the server.
|
---|
176 | */
|
---|
177 | if (!BIO_lookup_ex(hostname, port, BIO_LOOKUP_CLIENT, family, SOCK_STREAM, 0,
|
---|
178 | &res))
|
---|
179 | return NULL;
|
---|
180 |
|
---|
181 | /*
|
---|
182 | * Loop through all the possible addresses for the server and find one
|
---|
183 | * we can connect to.
|
---|
184 | */
|
---|
185 | for (ai = res; ai != NULL; ai = BIO_ADDRINFO_next(ai)) {
|
---|
186 | /*
|
---|
187 | * Create a TCP socket. We could equally use non-OpenSSL calls such
|
---|
188 | * as "socket" here for this and the subsequent connect and close
|
---|
189 | * functions. But for portability reasons and also so that we get
|
---|
190 | * errors on the OpenSSL stack in the event of a failure we use
|
---|
191 | * OpenSSL's versions of these functions.
|
---|
192 | */
|
---|
193 | sock = BIO_socket(BIO_ADDRINFO_family(ai), SOCK_STREAM, 0, 0);
|
---|
194 | if (sock == -1)
|
---|
195 | continue;
|
---|
196 |
|
---|
197 | /* Connect the socket to the server's address */
|
---|
198 | if (!BIO_connect(sock, BIO_ADDRINFO_address(ai), BIO_SOCK_NODELAY)) {
|
---|
199 | BIO_closesocket(sock);
|
---|
200 | sock = -1;
|
---|
201 | continue;
|
---|
202 | }
|
---|
203 |
|
---|
204 | /* We have a connected socket so break out of the loop */
|
---|
205 | break;
|
---|
206 | }
|
---|
207 |
|
---|
208 | /* Free the address information resources we allocated earlier */
|
---|
209 | BIO_ADDRINFO_free(res);
|
---|
210 |
|
---|
211 | See L<BIO_lookup_ex(3)>, L<BIO_socket(3)>, L<BIO_connect(3)>,
|
---|
212 | L<BIO_closesocket(3)>, L<BIO_ADDRINFO_next(3)>, L<BIO_ADDRINFO_address(3)> and
|
---|
213 | L<BIO_ADDRINFO_free(3)> for further information on the functions used here. In
|
---|
214 | the above example code the B<hostname> and B<port> variables are strings, e.g.
|
---|
215 | "www.example.com" and "443". Note also the use of the family variable, which
|
---|
216 | can take the values of AF_INET or AF_INET6 based on the command line -6 option,
|
---|
217 | to allow specific connections to an ipv4 or ipv6 enabled host.
|
---|
218 |
|
---|
219 | Sockets created using the methods described above will automatically be blocking
|
---|
220 | sockets - which is exactly what we want for this example.
|
---|
221 |
|
---|
222 | Once the socket has been created and connected we need to associate it with a
|
---|
223 | BIO object:
|
---|
224 |
|
---|
225 | BIO *bio;
|
---|
226 |
|
---|
227 | /* Create a BIO to wrap the socket */
|
---|
228 | bio = BIO_new(BIO_s_socket());
|
---|
229 | if (bio == NULL) {
|
---|
230 | BIO_closesocket(sock);
|
---|
231 | return NULL;
|
---|
232 | }
|
---|
233 |
|
---|
234 | /*
|
---|
235 | * Associate the newly created BIO with the underlying socket. By
|
---|
236 | * passing BIO_CLOSE here the socket will be automatically closed when
|
---|
237 | * the BIO is freed. Alternatively you can use BIO_NOCLOSE, in which
|
---|
238 | * case you must close the socket explicitly when it is no longer
|
---|
239 | * needed.
|
---|
240 | */
|
---|
241 | BIO_set_fd(bio, sock, BIO_CLOSE);
|
---|
242 |
|
---|
243 | See L<BIO_new(3)>, L<BIO_s_socket(3)> and L<BIO_set_fd(3)> for further
|
---|
244 | information on these functions.
|
---|
245 |
|
---|
246 | Finally we associate the B<SSL> object we created earlier with the B<BIO> using
|
---|
247 | the L<SSL_set_bio(3)> function. Note that this passes ownership of the B<BIO>
|
---|
248 | object to the B<SSL> object. Once ownership is passed the SSL object is
|
---|
249 | responsible for its management and will free it automatically when the B<SSL> is
|
---|
250 | freed. So, once L<SSL_set_bio(3)> has been been called, you should not call
|
---|
251 | L<BIO_free(3)> on the B<BIO>.
|
---|
252 |
|
---|
253 | SSL_set_bio(ssl, bio, bio);
|
---|
254 |
|
---|
255 | =head2 Setting the server's hostname
|
---|
256 |
|
---|
257 | We have already connected our underlying socket to the server, but the client
|
---|
258 | still needs to know the server's hostname. It uses this information for 2 key
|
---|
259 | purposes and we need to set the hostname for each one.
|
---|
260 |
|
---|
261 | Firstly, the server's hostname is included in the initial ClientHello message
|
---|
262 | sent by the client. This is known as the Server Name Indication (SNI). This is
|
---|
263 | important because it is common for multiple hostnames to be fronted by a single
|
---|
264 | server that handles requests for all of them. In other words a single server may
|
---|
265 | have multiple hostnames associated with it and it is important to indicate which
|
---|
266 | one we want to connect to. Without this information we may get a handshake
|
---|
267 | failure, or we may get connected to the "default" server which may not be the
|
---|
268 | one we were expecting.
|
---|
269 |
|
---|
270 | To set the SNI hostname data we call the L<SSL_set_tlsext_host_name(3)> function
|
---|
271 | like this:
|
---|
272 |
|
---|
273 | /*
|
---|
274 | * Tell the server during the handshake which hostname we are attempting
|
---|
275 | * to connect to in case the server supports multiple hosts.
|
---|
276 | */
|
---|
277 | if (!SSL_set_tlsext_host_name(ssl, hostname)) {
|
---|
278 | printf("Failed to set the SNI hostname\n");
|
---|
279 | goto end;
|
---|
280 | }
|
---|
281 |
|
---|
282 | Here the C<hostname> argument is a string representing the hostname of the
|
---|
283 | server, e.g. "www.example.com".
|
---|
284 |
|
---|
285 | Secondly, we need to tell OpenSSL what hostname we expect to see in the
|
---|
286 | certificate coming back from the server. This is almost always the same one that
|
---|
287 | we asked for in the original request. This is important because, without this,
|
---|
288 | we do not verify that the hostname in the certificate is what we expect it to be
|
---|
289 | and any certificate is acceptable unless your application explicitly checks this
|
---|
290 | itself. We do this via the L<SSL_set1_host(3)> function:
|
---|
291 |
|
---|
292 | /*
|
---|
293 | * Ensure we check during certificate verification that the server has
|
---|
294 | * supplied a certificate for the hostname that we were expecting.
|
---|
295 | * Virtually all clients should do this unless you really know what you
|
---|
296 | * are doing.
|
---|
297 | */
|
---|
298 | if (!SSL_set1_host(ssl, hostname)) {
|
---|
299 | printf("Failed to set the certificate verification hostname");
|
---|
300 | goto end;
|
---|
301 | }
|
---|
302 |
|
---|
303 | All of the above steps must happen before we attempt to perform the handshake
|
---|
304 | otherwise they will have no effect.
|
---|
305 |
|
---|
306 | =head2 Performing the handshake
|
---|
307 |
|
---|
308 | Before we can start sending or receiving application data over a TLS connection
|
---|
309 | the TLS handshake must be performed. We can do this explicitly via the
|
---|
310 | L<SSL_connect(3)> function.
|
---|
311 |
|
---|
312 | /* Do the handshake with the server */
|
---|
313 | if (SSL_connect(ssl) < 1) {
|
---|
314 | printf("Failed to connect to the server\n");
|
---|
315 | /*
|
---|
316 | * If the failure is due to a verification error we can get more
|
---|
317 | * information about it from SSL_get_verify_result().
|
---|
318 | */
|
---|
319 | if (SSL_get_verify_result(ssl) != X509_V_OK)
|
---|
320 | printf("Verify error: %s\n",
|
---|
321 | X509_verify_cert_error_string(SSL_get_verify_result(ssl)));
|
---|
322 | goto end;
|
---|
323 | }
|
---|
324 |
|
---|
325 | The L<SSL_connect(3)> function can return 1, 0 or less than 0. Only a return
|
---|
326 | value of 1 is considered a success. For a simple blocking client we only need
|
---|
327 | to concern ourselves with whether the call was successful or not. Anything else
|
---|
328 | indicates that we have failed to connect to the server.
|
---|
329 |
|
---|
330 | A common cause of failures at this stage is due to a problem verifying the
|
---|
331 | server's certificate. For example if the certificate has expired, or it is not
|
---|
332 | signed by a CA in our trusted certificate store. We can use the
|
---|
333 | L<SSL_get_verify_result(3)> function to find out more information about the
|
---|
334 | verification failure. A return value of B<X509_V_OK> indicates that the
|
---|
335 | verification was successful (so the connection error must be due to some other
|
---|
336 | cause). Otherwise we use the L<X509_verify_cert_error_string(3)> function to get
|
---|
337 | a human readable error message.
|
---|
338 |
|
---|
339 | =head2 Sending and receiving data
|
---|
340 |
|
---|
341 | Once the handshake is complete we are able to send and receive application data.
|
---|
342 | Exactly what data is sent and in what order is usually controlled by some
|
---|
343 | application level protocol. In this example we are using HTTP 1.0 which is a
|
---|
344 | very simple request and response protocol. The client sends a request to the
|
---|
345 | server. The server sends the response data and then immediately closes down the
|
---|
346 | connection.
|
---|
347 |
|
---|
348 | To send data to the server we use the L<SSL_write_ex(3)> function and to receive
|
---|
349 | data from the server we use the L<SSL_read_ex(3)> function. In HTTP 1.0 the
|
---|
350 | client always writes data first. Our HTTP request will include the hostname that
|
---|
351 | we are connecting to. For simplicity, we write the HTTP request in three
|
---|
352 | chunks. First we write the start of the request. Secondly we write the hostname
|
---|
353 | we are sending the request to. Finally we send the end of the request.
|
---|
354 |
|
---|
355 | size_t written;
|
---|
356 | const char *request_start = "GET / HTTP/1.0\r\nConnection: close\r\nHost: ";
|
---|
357 | const char *request_end = "\r\n\r\n";
|
---|
358 |
|
---|
359 | /* Write an HTTP GET request to the peer */
|
---|
360 | if (!SSL_write_ex(ssl, request_start, strlen(request_start), &written)) {
|
---|
361 | printf("Failed to write start of HTTP request\n");
|
---|
362 | goto end;
|
---|
363 | }
|
---|
364 | if (!SSL_write_ex(ssl, hostname, strlen(hostname), &written)) {
|
---|
365 | printf("Failed to write hostname in HTTP request\n");
|
---|
366 | goto end;
|
---|
367 | }
|
---|
368 | if (!SSL_write_ex(ssl, request_end, strlen(request_end), &written)) {
|
---|
369 | printf("Failed to write end of HTTP request\n");
|
---|
370 | goto end;
|
---|
371 | }
|
---|
372 |
|
---|
373 | The L<SSL_write_ex(3)> function returns 0 if it fails and 1 if it is successful.
|
---|
374 | If it is successful then we can proceed to waiting for a response from the
|
---|
375 | server.
|
---|
376 |
|
---|
377 | size_t readbytes;
|
---|
378 | char buf[160];
|
---|
379 |
|
---|
380 | /*
|
---|
381 | * Get up to sizeof(buf) bytes of the response. We keep reading until the
|
---|
382 | * server closes the connection.
|
---|
383 | */
|
---|
384 | while (SSL_read_ex(ssl, buf, sizeof(buf), &readbytes)) {
|
---|
385 | /*
|
---|
386 | * OpenSSL does not guarantee that the returned data is a string or
|
---|
387 | * that it is NUL terminated so we use fwrite() to write the exact
|
---|
388 | * number of bytes that we read. The data could be non-printable or
|
---|
389 | * have NUL characters in the middle of it. For this simple example
|
---|
390 | * we're going to print it to stdout anyway.
|
---|
391 | */
|
---|
392 | fwrite(buf, 1, readbytes, stdout);
|
---|
393 | }
|
---|
394 | /* In case the response didn't finish with a newline we add one now */
|
---|
395 | printf("\n");
|
---|
396 |
|
---|
397 |
|
---|
398 | We use the L<SSL_read_ex(3)> function to read the response. We don't know
|
---|
399 | exactly how much data we are going to receive back so we enter a loop reading
|
---|
400 | blocks of data from the server and printing each block that we receive to the
|
---|
401 | screen. The loop ends as soon as L<SSL_read_ex(3)> returns 0 - meaning that it
|
---|
402 | failed to read any data.
|
---|
403 |
|
---|
404 | A failure to read data could mean that there has been some error, or it could
|
---|
405 | simply mean that server has sent all the data that it wants to send and has
|
---|
406 | indicated that it has finished by sending a "close_notify" alert. This alert is
|
---|
407 | a TLS protocol level message indicating that the endpoint has finished sending
|
---|
408 | all of its data and it will not send any more. Both of these conditions result
|
---|
409 | in a 0 return value from L<SSL_read_ex(3)> and we need to use the function
|
---|
410 | L<SSL_get_error(3)> to determine the cause of the 0 return value.
|
---|
411 |
|
---|
412 | /*
|
---|
413 | * Check whether we finished the while loop above normally or as the
|
---|
414 | * result of an error. The 0 argument to SSL_get_error() is the return
|
---|
415 | * code we received from the SSL_read_ex() call. It must be 0 in order
|
---|
416 | * to get here. Normal completion is indicated by SSL_ERROR_ZERO_RETURN.
|
---|
417 | */
|
---|
418 | if (SSL_get_error(ssl, 0) != SSL_ERROR_ZERO_RETURN) {
|
---|
419 | /*
|
---|
420 | * Some error occurred other than a graceful close down by the
|
---|
421 | * peer
|
---|
422 | */
|
---|
423 | printf ("Failed reading remaining data\n");
|
---|
424 | goto end;
|
---|
425 | }
|
---|
426 |
|
---|
427 | If L<SSL_get_error(3)> returns B<SSL_ERROR_ZERO_RETURN> then we know that the
|
---|
428 | server has finished sending its data. Otherwise an error has occurred.
|
---|
429 |
|
---|
430 | =head2 Shutting down the connection
|
---|
431 |
|
---|
432 | Once we have finished reading data from the server then we are ready to close
|
---|
433 | the connection down. We do this via the L<SSL_shutdown(3)> function which has
|
---|
434 | the effect of sending a TLS protocol level message (a "close_notify" alert) to
|
---|
435 | the server saying that we have finished writing data:
|
---|
436 |
|
---|
437 | /*
|
---|
438 | * The peer already shutdown gracefully (we know this because of the
|
---|
439 | * SSL_ERROR_ZERO_RETURN above). We should do the same back.
|
---|
440 | */
|
---|
441 | ret = SSL_shutdown(ssl);
|
---|
442 | if (ret < 1) {
|
---|
443 | /*
|
---|
444 | * ret < 0 indicates an error. ret == 0 would be unexpected here
|
---|
445 | * because that means "we've sent a close_notify and we're waiting
|
---|
446 | * for one back". But we already know we got one from the peer
|
---|
447 | * because of the SSL_ERROR_ZERO_RETURN above.
|
---|
448 | */
|
---|
449 | printf("Error shutting down\n");
|
---|
450 | goto end;
|
---|
451 | }
|
---|
452 |
|
---|
453 | The L<SSL_shutdown(3)> function will either return 1, 0, or less than 0. A
|
---|
454 | return value of 1 is a success, and a return value less than 0 is an error. More
|
---|
455 | precisely a return value of 1 means that we have sent a "close_notify" alert to
|
---|
456 | the server, and that we have also received one back. A return value of 0 means
|
---|
457 | that we have sent a "close_notify" alert to the server, but we have not yet
|
---|
458 | received one back. Usually in this scenario you would call L<SSL_shutdown(3)>
|
---|
459 | again which (with a blocking socket) would block until the "close_notify" is
|
---|
460 | received. However in this case we already know that the server has sent us a
|
---|
461 | "close_notify" because of the SSL_ERROR_ZERO_RETURN that we received from the
|
---|
462 | call to L<SSL_read_ex(3)>. So this scenario should never happen in practice. We
|
---|
463 | just treat it as an error in this example.
|
---|
464 |
|
---|
465 | =head2 Final clean up
|
---|
466 |
|
---|
467 | Before the application exits we have to clean up some memory that we allocated.
|
---|
468 | If we are exiting due to an error we might also want to display further
|
---|
469 | information about that error if it is available to the user:
|
---|
470 |
|
---|
471 | /* Success! */
|
---|
472 | res = EXIT_SUCCESS;
|
---|
473 | end:
|
---|
474 | /*
|
---|
475 | * If something bad happened then we will dump the contents of the
|
---|
476 | * OpenSSL error stack to stderr. There might be some useful diagnostic
|
---|
477 | * information there.
|
---|
478 | */
|
---|
479 | if (res == EXIT_FAILURE)
|
---|
480 | ERR_print_errors_fp(stderr);
|
---|
481 |
|
---|
482 | /*
|
---|
483 | * Free the resources we allocated. We do not free the BIO object here
|
---|
484 | * because ownership of it was immediately transferred to the SSL object
|
---|
485 | * via SSL_set_bio(). The BIO will be freed when we free the SSL object.
|
---|
486 | */
|
---|
487 | SSL_free(ssl);
|
---|
488 | SSL_CTX_free(ctx);
|
---|
489 | return res;
|
---|
490 |
|
---|
491 | To display errors we make use of the L<ERR_print_errors_fp(3)> function which
|
---|
492 | simply dumps out the contents of any errors on the OpenSSL error stack to the
|
---|
493 | specified location (in this case I<stderr>).
|
---|
494 |
|
---|
495 | We need to free up the B<SSL> object that we created for the connection via the
|
---|
496 | L<SSL_free(3)> function. Also, since we are not going to be creating any more
|
---|
497 | TLS connections we must also free up the B<SSL_CTX> via a call to
|
---|
498 | L<SSL_CTX_free(3)>.
|
---|
499 |
|
---|
500 | =head1 TROUBLESHOOTING
|
---|
501 |
|
---|
502 | There are a number of things that might go wrong when running the demo
|
---|
503 | application. This section describes some common things you might encounter.
|
---|
504 |
|
---|
505 | =head2 Failure to connect the underlying socket
|
---|
506 |
|
---|
507 | This could occur for numerous reasons. For example if there is a problem in the
|
---|
508 | network route between the client and the server; or a firewall is blocking the
|
---|
509 | communication; or the server is not in DNS. Check the network configuration.
|
---|
510 |
|
---|
511 | =head2 Verification failure of the server certificate
|
---|
512 |
|
---|
513 | A verification failure of the server certificate would result in a failure when
|
---|
514 | running the L<SSL_connect(3)> function. L<ERR_print_errors_fp(3)> would display
|
---|
515 | an error which would look something like this:
|
---|
516 |
|
---|
517 | Verify error: unable to get local issuer certificate
|
---|
518 | 40E74AF1F47F0000:error:0A000086:SSL routines:tls_post_process_server_certificate:certificate verify failed:ssl/statem/statem_clnt.c:2069:
|
---|
519 |
|
---|
520 | A server certificate verification failure could be caused for a number of
|
---|
521 | reasons. For example
|
---|
522 |
|
---|
523 | =over 4
|
---|
524 |
|
---|
525 | =item Failure to correctly setup the trusted certificate store
|
---|
526 |
|
---|
527 | See the page L<ossl-guide-tls-introduction(7)> and check that your trusted
|
---|
528 | certificate store is correctly configured
|
---|
529 |
|
---|
530 | =item Unrecognised CA
|
---|
531 |
|
---|
532 | If the CA used by the server's certificate is not in the trusted certificate
|
---|
533 | store for the client then this will cause a verification failure during
|
---|
534 | connection. Often this can occur if the server is using a self-signed
|
---|
535 | certificate (i.e. a test certificate that has not been signed by a CA at all).
|
---|
536 |
|
---|
537 | =item Missing intermediate CAs
|
---|
538 |
|
---|
539 | This is a server misconfiguration where the client has the relevant root CA in
|
---|
540 | its trust store, but the server has not supplied all of the intermediate CA
|
---|
541 | certificates between that root CA and the server's own certificate. Therefore
|
---|
542 | a trust chain cannot be established.
|
---|
543 |
|
---|
544 | =item Mismatched hostname
|
---|
545 |
|
---|
546 | If for some reason the hostname of the server that the client is expecting does
|
---|
547 | not match the hostname in the certificate then this will cause verification to
|
---|
548 | fail.
|
---|
549 |
|
---|
550 | =item Expired certificate
|
---|
551 |
|
---|
552 | The date that the server's certificate is valid to has passed.
|
---|
553 |
|
---|
554 | =back
|
---|
555 |
|
---|
556 | The "unable to get local issuer certificate" we saw in the example above means
|
---|
557 | that we have been unable to find the issuer of the server's certificate (or one
|
---|
558 | of its intermediate CA certificates) in our trusted certificate store (e.g.
|
---|
559 | because the trusted certificate store is misconfigured, or there are missing
|
---|
560 | intermediate CAs, or the issuer is simply unrecognised).
|
---|
561 |
|
---|
562 | =head1 FURTHER READING
|
---|
563 |
|
---|
564 | See L<ossl-guide-tls-client-non-block(7)> to read a tutorial on how to modify
|
---|
565 | the client developed on this page to support a nonblocking socket.
|
---|
566 |
|
---|
567 | See L<ossl-guide-tls-server-block(7)> for a tutorial on how to implement a
|
---|
568 | simple TLS server handling one client at a time over a blocking socket.
|
---|
569 |
|
---|
570 | See L<ossl-guide-quic-client-block(7)> to read a tutorial on how to modify the
|
---|
571 | client developed on this page to support QUIC instead of TLS.
|
---|
572 |
|
---|
573 | =head1 SEE ALSO
|
---|
574 |
|
---|
575 | L<ossl-guide-introduction(7)>, L<ossl-guide-libraries-introduction(7)>,
|
---|
576 | L<ossl-guide-libssl-introduction(7)>, L<ossl-guide-tls-introduction(7)>,
|
---|
577 | L<ossl-guide-tls-client-non-block(7)>, L<ossl-guide-quic-client-block(7)>
|
---|
578 |
|
---|
579 | =head1 COPYRIGHT
|
---|
580 |
|
---|
581 | Copyright 2023-2024 The OpenSSL Project Authors. All Rights Reserved.
|
---|
582 |
|
---|
583 | Licensed under the Apache License 2.0 (the "License"). You may not use
|
---|
584 | this file except in compliance with the License. You can obtain a copy
|
---|
585 | in the file LICENSE in the source distribution or at
|
---|
586 | L<https://www.openssl.org/source/license.html>.
|
---|
587 |
|
---|
588 | =cut
|
---|