diff options
Diffstat (limited to 'upstream/archlinux/man7/ossl-guide-tls-client-block.7ssl')
-rw-r--r-- | upstream/archlinux/man7/ossl-guide-tls-client-block.7ssl | 649 |
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>. |