summaryrefslogtreecommitdiffstats
path: root/upstream/archlinux/man7/ossl-guide-tls-client-block.7ssl
diff options
context:
space:
mode:
Diffstat (limited to 'upstream/archlinux/man7/ossl-guide-tls-client-block.7ssl')
-rw-r--r--upstream/archlinux/man7/ossl-guide-tls-client-block.7ssl649
1 files changed, 649 insertions, 0 deletions
diff --git a/upstream/archlinux/man7/ossl-guide-tls-client-block.7ssl b/upstream/archlinux/man7/ossl-guide-tls-client-block.7ssl
new file mode 100644
index 00000000..f6ef5f27
--- /dev/null
+++ b/upstream/archlinux/man7/ossl-guide-tls-client-block.7ssl
@@ -0,0 +1,649 @@
+.\" -*- 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-TLS-CLIENT-BLOCK 7ssl"
+.TH OSSL-GUIDE-TLS-CLIENT-BLOCK 7ssl 2024-01-30 3.2.1 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\-tls\-client\-block
+\&\- OpenSSL Guide: Writing a simple blocking TLS client
+.SH "SIMPLE BLOCKING TLS CLIENT EXAMPLE"
+.IX Header "SIMPLE BLOCKING TLS CLIENT EXAMPLE"
+This page will present various source code samples demonstrating how to write
+a simple TLS client application which connects to a server, sends an HTTP/1.0
+request to it, and reads back the response.
+.PP
+We use a blocking socket for the purposes of this example. This means that
+attempting to read data from a socket that has no data available on it to read
+will block (and the function will not return), until data becomes available.
+For example, this can happen if we have sent our request, but we are still
+waiting for the server's response. Similarly any attempts to write to a socket
+that is not able to write at the moment will block until writing is possible.
+.PP
+This blocking behaviour simplifies the implementation of a client because you do
+not have to worry about what happens if data is not yet available. The
+application will simply wait until it is available.
+.PP
+The complete source code for this example blocking TLS client is available in
+the \fBdemos/guide\fR directory of the OpenSSL source distribution in the file
+\&\fBtls\-client\-block.c\fR. It is also available online at
+<https://github.com/openssl/openssl/blob/master/demos/guide/tls\-client\-block.c>.
+.PP
+We assume that you already have OpenSSL installed on your system; that you
+already have some fundamental understanding of OpenSSL concepts and TLS (see
+\&\fBossl\-guide\-libraries\-introduction\fR\|(7) and \fBossl\-guide\-tls\-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 TCP/IP and sockets.
+.SS "Creating the SSL_CTX and SSL objects"
+.IX Subsection "Creating the SSL_CTX and SSL objects"
+The first step is to create an \fBSSL_CTX\fR object for our client. We use the
+\&\fBSSL_CTX_new\fR\|(3) function for this purpose. We could alternatively use
+\&\fBSSL_CTX_new_ex\fR\|(3) if we want to associate the \fBSSL_CTX\fR with a particular
+\&\fBOSSL_LIB_CTX\fR (see \fBossl\-guide\-libraries\-introduction\fR\|(7) to learn about
+\&\fBOSSL_LIB_CTX\fR). We pass as an argument the return value of the function
+\&\fBTLS_client_method\fR\|(3). You should use this method whenever you are writing a
+TLS client. This method will automatically use TLS version negotiation to select
+the highest version of the protocol that is mutually supported by both the
+client and the server.
+.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 TLS_client_method()
+\& * here.
+\& */
+\& ctx = SSL_CTX_new(TLS_client_method());
+\& if (ctx == NULL) {
+\& printf("Failed to create the SSL_CTX\en");
+\& goto end;
+\& }
+.Ve
+.PP
+Since we are writing a client we must ensure that we verify the server's
+certificate. We do this by calling the \fBSSL_CTX_set_verify\fR\|(3) function and
+pass the \fBSSL_VERIFY_PEER\fR value to it. The final argument to this function
+is a callback that you can optionally supply to override the default handling
+for certificate verification. Most applications do not need to do this so this
+can safely be set to NULL to get the default handling.
+.PP
+.Vb 6
+\& /*
+\& * Configure the client to abort the handshake if certificate
+\& * verification fails. Virtually all clients should do this unless you
+\& * really know what you are doing.
+\& */
+\& SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);
+.Ve
+.PP
+In order for certificate verification to be successful you must have configured
+where the trusted certificate store to be used is located (see
+\&\fBossl\-guide\-tls\-introduction\fR\|(7)). In most cases you just want to use the
+default store so we call \fBSSL_CTX_set_default_verify_paths\fR\|(3).
+.PP
+.Vb 5
+\& /* Use the default trusted certificate store */
+\& if (!SSL_CTX_set_default_verify_paths(ctx)) {
+\& printf("Failed to set the default trusted certificate store\en");
+\& goto end;
+\& }
+.Ve
+.PP
+We would also like to restrict the TLS versions that we are willing to accept to
+TLSv1.2 or above. TLS protocol versions earlier than that are generally to be
+avoided where possible. We can do that using
+\&\fBSSL_CTX_set_min_proto_version\fR\|(3):
+.PP
+.Vb 8
+\& /*
+\& * TLSv1.1 or earlier are deprecated by IETF and are generally to be
+\& * avoided if possible. We require a minimum TLS version of TLSv1.2.
+\& */
+\& if (!SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION)) {
+\& printf("Failed to set the minimum TLS protocol version\en");
+\& goto end;
+\& }
+.Ve
+.PP
+That is all the setup that we need to do for the \fBSSL_CTX\fR, so next we need to
+create an \fBSSL\fR object to represent the TLS connection. In a real application
+we might expect to be creating more than one TLS connection over time. In that
+case we would expect to reuse the \fBSSL_CTX\fR that we already created each time.
+There is no need to repeat those steps. In fact it is best not to since certain
+internal resources are cached in the \fBSSL_CTX\fR. You will get better performance
+by reusing an existing \fBSSL_CTX\fR instead of creating a new one each time.
+.PP
+Creating the \fBSSL\fR object is a simple matter of calling the \fBSSL_new\|(3)\fR
+function and passing the \fBSSL_CTX\fR we created as an argument.
+.PP
+.Vb 6
+\& /* Create an SSL object to represent the TLS connection */
+\& ssl = SSL_new(ctx);
+\& if (ssl == NULL) {
+\& printf("Failed to create the SSL object\en");
+\& goto end;
+\& }
+.Ve
+.SS "Creating the socket and BIO"
+.IX Subsection "Creating the socket and BIO"
+TLS data is transmitted over an underlying transport layer. Normally a TCP
+socket. It is the application's responsibility for ensuring that the socket is
+created and associated with an SSL object (via a BIO).
+.PP
+Socket creation for use by a client is typically a 2 step process, i.e.
+constructing the socket; and connecting the socket.
+.PP
+How to construct a socket is platform specific \- but most platforms (including
+Windows) provide a POSIX compatible interface via the \fIsocket\fR function, e.g.
+to create an IPv4 TCP socket:
+.PP
+.Vb 1
+\& int sock;
+\&
+\& sock = socket(AF_INET, SOCK_STREAM, 0);
+\& if (sock == \-1)
+\& return NULL;
+.Ve
+.PP
+Once the socket is constructed it must be connected to the remote server. Again
+the details are platform specific but most platforms (including Windows)
+provide the POSIX compatible \fIconnect\fR function. For example:
+.PP
+.Vb 2
+\& struct sockaddr_in serveraddr;
+\& struct hostent *server;
+\&
+\& server = gethostbyname("www.openssl.org");
+\& if (server == NULL) {
+\& close(sock);
+\& return NULL;
+\& }
+\&
+\& memset(&serveraddr, 0, sizeof(serveraddr));
+\& serveraddr.sin_family = server\->h_addrtype;
+\& serveraddr.sin_port = htons(443);
+\& memcpy(&serveraddr.sin_addr.s_addr, server\->h_addr, server\->h_length);
+\&
+\& if (connect(sock, (struct sockaddr *)&serveraddr,
+\& sizeof(serveraddr)) == \-1) {
+\& close(sock);
+\& return NULL;
+\& }
+.Ve
+.PP
+OpenSSL provides portable helper functions to do these tasks which also
+integrate into the OpenSSL error system to log error data, e.g.
+.PP
+.Vb 3
+\& int sock = \-1;
+\& BIO_ADDRINFO *res;
+\& const BIO_ADDRINFO *ai = NULL;
+\&
+\& /*
+\& * Lookup IP address info for the server.
+\& */
+\& if (!BIO_lookup_ex(hostname, port, BIO_LOOKUP_CLIENT, family, SOCK_STREAM, 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_STREAM, 0, 0);
+\& if (sock == \-1)
+\& continue;
+\&
+\& /* Connect the socket to the server\*(Aqs address */
+\& if (!BIO_connect(sock, BIO_ADDRINFO_address(ai), BIO_SOCK_NODELAY)) {
+\& BIO_closesocket(sock);
+\& sock = \-1;
+\& continue;
+\& }
+\&
+\& /* We have a connected socket so break out of the loop */
+\& break;
+\& }
+\&
+\& /* Free the address information resources we allocated earlier */
+\& BIO_ADDRINFO_free(res);
+.Ve
+.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) and
+\&\fBBIO_ADDRINFO_free\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". Note also the use of the family variable, which
+can take the values of AF_INET or AF_INET6 based on the command line \-6 option,
+to allow specific connections to an ipv4 or ipv6 enabled host.
+.PP
+Sockets created using the methods described above will automatically be blocking
+sockets \- which is exactly what we want for this example.
+.PP
+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_socket());
+\& 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
+See \fBBIO_new\fR\|(3), \fBBIO_s_socket\fR\|(3) and \fBBIO_set_fd\fR\|(3) for further
+information on these functions.
+.PP
+Finally we associate the \fBSSL\fR object we created earlier with the \fBBIO\fR using
+the \fBSSL_set_bio\fR\|(3) function. Note that this passes ownership of the \fBBIO\fR
+object to the \fBSSL\fR object. Once ownership is passed the SSL object is
+responsible for its management and will free it automatically when the \fBSSL\fR is
+freed. So, once \fBSSL_set_bio\fR\|(3) has been been called, you should not call
+\&\fBBIO_free\fR\|(3) on the \fBBIO\fR.
+.PP
+.Vb 1
+\& SSL_set_bio(ssl, bio, bio);
+.Ve
+.SS "Setting the server's hostname"
+.IX Subsection "Setting the server's hostname"
+We have already connected our underlying socket to the server, but the client
+still needs to know the server's hostname. It uses this information for 2 key
+purposes and we need to set the hostname for each one.
+.PP
+Firstly, the server's hostname is included in the initial ClientHello message
+sent by the client. This is known as the Server Name Indication (SNI). This is
+important because it is common for multiple hostnames to be fronted by a single
+server that handles requests for all of them. In other words a single server may
+have multiple hostnames associated with it and it is important to indicate which
+one we want to connect to. Without this information we may get a handshake
+failure, or we may get connected to the "default" server which may not be the
+one we were expecting.
+.PP
+To set the SNI hostname data we call the \fBSSL_set_tlsext_host_name\fR\|(3) function
+like this:
+.PP
+.Vb 8
+\& /*
+\& * Tell the server during the handshake which hostname we are attempting
+\& * to connect to in case the server supports multiple hosts.
+\& */
+\& if (!SSL_set_tlsext_host_name(ssl, hostname)) {
+\& printf("Failed to set the SNI hostname\en");
+\& goto end;
+\& }
+.Ve
+.PP
+Here the \f(CW\*(C`hostname\*(C'\fR argument is a string representing the hostname of the
+server, e.g. "www.example.com".
+.PP
+Secondly, we need to tell OpenSSL what hostname we expect to see in the
+certificate coming back from the server. This is almost always the same one that
+we asked for in the original request. This is important because, without this,
+we do not verify that the hostname in the certificate is what we expect it to be
+and any certificate is acceptable unless your application explicitly checks this
+itself. We do this via the \fBSSL_set1_host\fR\|(3) function:
+.PP
+.Vb 10
+\& /*
+\& * Ensure we check during certificate verification that the server has
+\& * supplied a certificate for the hostname that we were expecting.
+\& * Virtually all clients should do this unless you really know what you
+\& * are doing.
+\& */
+\& if (!SSL_set1_host(ssl, hostname)) {
+\& printf("Failed to set the certificate verification hostname");
+\& goto end;
+\& }
+.Ve
+.PP
+All of the above steps must happen before we attempt to perform the handshake
+otherwise they will have no effect.
+.SS "Performing the handshake"
+.IX Subsection "Performing the handshake"
+Before we can start sending or receiving application data over a TLS connection
+the TLS handshake must be performed. We can do this explicitly via the
+\&\fBSSL_connect\fR\|(3) function.
+.PP
+.Vb 12
+\& /* Do the handshake with the server */
+\& if (SSL_connect(ssl) < 1) {
+\& printf("Failed to connect to the server\en");
+\& /*
+\& * If the failure is due to a verification error we can get more
+\& * information about it from SSL_get_verify_result().
+\& */
+\& if (SSL_get_verify_result(ssl) != X509_V_OK)
+\& printf("Verify error: %s\en",
+\& X509_verify_cert_error_string(SSL_get_verify_result(ssl)));
+\& goto end;
+\& }
+.Ve
+.PP
+The \fBSSL_connect\fR\|(3) function can return 1, 0 or less than 0. Only a return
+value of 1 is considered a success. For a simple blocking client we only need
+to concern ourselves with whether the call was successful or not. Anything else
+indicates that we have failed to connect to the server.
+.PP
+A common cause of failures at this stage is due to a problem verifying the
+server's certificate. For example if the certificate has expired, or it is not
+signed by a CA in our trusted certificate store. We can use the
+\&\fBSSL_get_verify_result\fR\|(3) function to find out more information about the
+verification failure. A return value of \fBX509_V_OK\fR indicates that the
+verification was successful (so the connection error must be due to some other
+cause). Otherwise we use the \fBX509_verify_cert_error_string\fR\|(3) function to get
+a human readable error message.
+.SS "Sending and receiving data"
+.IX Subsection "Sending and receiving data"
+Once the handshake is complete we are able to send and receive application data.
+Exactly what data is sent and in what order is usually controlled by some
+application level protocol. In this example we are using HTTP 1.0 which is a
+very simple request and response protocol. The client sends a request to the
+server. The server sends the response data and then immediately closes down the
+connection.
+.PP
+To send data to the server we use the \fBSSL_write_ex\fR\|(3) function and to receive
+data from the server we use the \fBSSL_read_ex\fR\|(3) function. In HTTP 1.0 the
+client always writes data first. Our HTTP request will include the hostname that
+we are connecting to. For simplicity, we write the HTTP request in three
+chunks. First we write the start of the request. Secondly we write the hostname
+we are sending the request to. Finally we send the end of the request.
+.PP
+.Vb 3
+\& size_t written;
+\& const char *request_start = "GET / HTTP/1.0\er\enConnection: close\er\enHost: ";
+\& const char *request_end = "\er\en\er\en";
+\&
+\& /* Write an HTTP GET request to the peer */
+\& if (!SSL_write_ex(ssl, request_start, strlen(request_start), &written)) {
+\& printf("Failed to write start of HTTP request\en");
+\& goto end;
+\& }
+\& if (!SSL_write_ex(ssl, hostname, strlen(hostname), &written)) {
+\& printf("Failed to write hostname in HTTP request\en");
+\& goto end;
+\& }
+\& if (!SSL_write_ex(ssl, request_end, strlen(request_end), &written)) {
+\& printf("Failed to write end of HTTP request\en");
+\& goto end;
+\& }
+.Ve
+.PP
+The \fBSSL_write_ex\fR\|(3) function returns 0 if it fails and 1 if it is successful.
+If it is successful then we can proceed to waiting for a response from the
+server.
+.PP
+.Vb 2
+\& size_t readbytes;
+\& char buf[160];
+\&
+\& /*
+\& * 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");
+.Ve
+.PP
+We use the \fBSSL_read_ex\fR\|(3) function to read the response. We don't know
+exactly how much data we are going to receive back so we enter a loop reading
+blocks of data from the server and printing each block that we receive to the
+screen. The loop ends as soon as \fBSSL_read_ex\fR\|(3) returns 0 \- meaning that it
+failed to read any data.
+.PP
+A failure to read data could mean that there has been some error, or it could
+simply mean that server has sent all the data that it wants to send and has
+indicated that it has finished by sending a "close_notify" alert. This alert is
+a TLS protocol level message indicating that the endpoint has finished sending
+all of its data and it will not send any more. Both of these conditions result
+in a 0 return value from \fBSSL_read_ex\fR\|(3) and we need to use the function
+\&\fBSSL_get_error\fR\|(3) to determine the cause of the 0 return value.
+.PP
+.Vb 10
+\& /*
+\& * 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.
+\& */
+\& if (SSL_get_error(ssl, 0) != SSL_ERROR_ZERO_RETURN) {
+\& /*
+\& * Some error occurred other than a graceful close down by the
+\& * peer
+\& */
+\& printf ("Failed reading remaining data\en");
+\& goto end;
+\& }
+.Ve
+.PP
+If \fBSSL_get_error\fR\|(3) returns \fBSSL_ERROR_ZERO_RETURN\fR then we know that the
+server has finished sending its data. Otherwise an error has occurred.
+.SS "Shutting down the connection"
+.IX Subsection "Shutting down the connection"
+Once we have finished reading data from the server then we are ready to close
+the connection down. We do this via the \fBSSL_shutdown\fR\|(3) function which has
+the effect of sending a TLS protocol level message (a "close_notify" alert) to
+the server saying that we have finished writing data:
+.PP
+.Vb 10
+\& /*
+\& * The peer already shutdown gracefully (we know this because of the
+\& * SSL_ERROR_ZERO_RETURN above). We should do the same back.
+\& */
+\& ret = SSL_shutdown(ssl);
+\& if (ret < 1) {
+\& /*
+\& * ret < 0 indicates an error. ret == 0 would be unexpected here
+\& * because that means "we\*(Aqve sent a close_notify and we\*(Aqre waiting
+\& * for one back". But we already know we got one from the peer
+\& * because of the SSL_ERROR_ZERO_RETURN above.
+\& */
+\& printf("Error shutting down\en");
+\& goto end;
+\& }
+.Ve
+.PP
+The \fBSSL_shutdown\fR\|(3) function will either return 1, 0, or less than 0. A
+return value of 1 is a success, and a return value less than 0 is an error. More
+precisely a return value of 1 means that we have sent a "close_notify" alert to
+the server, and that we have also received one back. A return value of 0 means
+that we have sent a "close_notify" alert to the server, but we have not yet
+received one back. Usually in this scenario you would call \fBSSL_shutdown\fR\|(3)
+again which (with a blocking socket) would block until the "close_notify" is
+received. However in this case we already know that the server has sent us a
+"close_notify" because of the SSL_ERROR_ZERO_RETURN that we received from the
+call to \fBSSL_read_ex\fR\|(3). So this scenario should never happen in practice. We
+just treat it as an error in this example.
+.SS "Final clean up"
+.IX Subsection "Final clean up"
+Before the application exits we have to clean up some memory that we allocated.
+If we are exiting due to an error we might also want to display further
+information about that error if it is available to the user:
+.PP
+.Vb 10
+\& /* Success! */
+\& res = EXIT_SUCCESS;
+\& end:
+\& /*
+\& * If something bad happened then we will dump the contents of the
+\& * OpenSSL error stack to stderr. There might be some useful diagnostic
+\& * information there.
+\& */
+\& if (res == EXIT_FAILURE)
+\& ERR_print_errors_fp(stderr);
+\&
+\& /*
+\& * Free the resources we allocated. We do not free the BIO object here
+\& * because ownership of it was immediately transferred to the SSL object
+\& * via SSL_set_bio(). The BIO will be freed when we free the SSL object.
+\& */
+\& SSL_free(ssl);
+\& SSL_CTX_free(ctx);
+\& return res;
+.Ve
+.PP
+To display errors we make use of the \fBERR_print_errors_fp\fR\|(3) function which
+simply dumps out the contents of any errors on the OpenSSL error stack to the
+specified location (in this case \fIstderr\fR).
+.PP
+We need to free up the \fBSSL\fR object that we created for the connection via the
+\&\fBSSL_free\fR\|(3) function. Also, since we are not going to be creating any more
+TLS connections we must also free up the \fBSSL_CTX\fR via a call to
+\&\fBSSL_CTX_free\fR\|(3).
+.SH TROUBLESHOOTING
+.IX Header "TROUBLESHOOTING"
+There are a number of things that might go wrong when running the demo
+application. This section describes some common things you might encounter.
+.SS "Failure to connect the underlying socket"
+.IX Subsection "Failure to connect the underlying socket"
+This could occur for numerous reasons. For example if there is a problem in the
+network route between the client and the server; or a firewall is blocking the
+communication; or the server is not in DNS. Check the network configuration.
+.SS "Verification failure of the server certificate"
+.IX Subsection "Verification failure of the server certificate"
+A verification failure of the server certificate would result in a failure when
+running the \fBSSL_connect\fR\|(3) function. \fBERR_print_errors_fp\fR\|(3) would display
+an error which would look something like this:
+.PP
+.Vb 2
+\& Verify error: unable to get local issuer certificate
+\& 40E74AF1F47F0000:error:0A000086:SSL routines:tls_post_process_server_certificate:certificate verify failed:ssl/statem/statem_clnt.c:2069:
+.Ve
+.PP
+A server certificate verification failure could be caused for a number of
+reasons. For example
+.IP "Failure to correctly setup the trusted certificate store" 4
+.IX Item "Failure to correctly setup the trusted certificate store"
+See the page \fBossl\-guide\-tls\-introduction\fR\|(7) and check that your trusted
+certificate store is correctly configured
+.IP "Unrecognised CA" 4
+.IX Item "Unrecognised CA"
+If the CA used by the server's certificate is not in the trusted certificate
+store for the client then this will cause a verification failure during
+connection. Often this can occur if the server is using a self-signed
+certificate (i.e. a test certificate that has not been signed by a CA at all).
+.IP "Missing intermediate CAs" 4
+.IX Item "Missing intermediate CAs"
+This is a server misconfiguration where the client has the relevant root CA in
+its trust store, but the server has not supplied all of the intermediate CA
+certificates between that root CA and the server's own certificate. Therefore
+a trust chain cannot be established.
+.IP "Mismatched hostname" 4
+.IX Item "Mismatched hostname"
+If for some reason the hostname of the server that the client is expecting does
+not match the hostname in the certificate then this will cause verification to
+fail.
+.IP "Expired certificate" 4
+.IX Item "Expired certificate"
+The date that the server's certificate is valid to has passed.
+.PP
+The "unable to get local issuer certificate" we saw in the example above means
+that we have been unable to find the issuer of the server's certificate (or one
+of its intermediate CA certificates) in our trusted certificate store (e.g.
+because the trusted certificate store is misconfigured, or there are missing
+intermediate CAs, or the issuer is simply unrecognised).
+.SH "FURTHER READING"
+.IX Header "FURTHER READING"
+See \fBossl\-guide\-tls\-client\-non\-block\fR\|(7) to read a tutorial on how to modify
+the client developed on this page to support a nonblocking socket.
+.PP
+See \fBossl\-guide\-quic\-client\-block\fR\|(7) to read a tutorial on how to modify the
+client developed on this page to support QUIC instead of TLS.
+.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\-non\-block\fR\|(7), \fBossl\-guide\-quic\-client\-block\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>.