]>
git.ipfire.org Git - thirdparty/openssl.git/blob - demos/guide/tls-client-non-block.c
05db0f529e66b9036832e20261240cd964e46c9f
2 * Copyright 2023 The OpenSSL Project Authors. All Rights Reserved.
4 * Licensed under the Apache License 2.0 (the "License"). You may not use
5 * this file except in compliance with the License. You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
11 * NB: Changes to this file should also be reflected in
12 * doc/man7/ossl-guide-tls-client-non-block.pod
17 /* Include the appropriate header file for SOCK_STREAM */
18 #ifdef _WIN32 /* Windows */
19 # include <winsock2.h>
20 #else /* Linux/Unix */
21 # include <sys/socket.h>
22 # include <sys/select.h>
25 #include <openssl/bio.h>
26 #include <openssl/ssl.h>
27 #include <openssl/err.h>
29 /* Helper function to create a BIO connected to the server */
30 static BIO
*create_socket_bio(const char *hostname
, const char *port
)
34 const BIO_ADDRINFO
*ai
= NULL
;
38 * Lookup IP address info for the server.
40 if (!BIO_lookup_ex(hostname
, port
, BIO_LOOKUP_CLIENT
, 0, SOCK_STREAM
, 0,
45 * Loop through all the possible addresses for the server and find one
48 for (ai
= res
; ai
!= NULL
; ai
= BIO_ADDRINFO_next(ai
)) {
50 * Create a TCP socket. We could equally use non-OpenSSL calls such
51 * as "socket" here for this and the subsequent connect and close
52 * functions. But for portability reasons and also so that we get
53 * errors on the OpenSSL stack in the event of a failure we use
54 * OpenSSL's versions of these functions.
56 sock
= BIO_socket(BIO_ADDRINFO_family(ai
), SOCK_STREAM
, 0, 0);
60 /* Connect the socket to the server's address */
61 if (!BIO_connect(sock
, BIO_ADDRINFO_address(ai
), BIO_SOCK_NODELAY
)) {
62 BIO_closesocket(sock
);
67 /* Set to nonblocking mode */
68 if (!BIO_socket_nbio(sock
, 1)) {
73 /* We have a connected socket so break out of the loop */
77 /* Free the address information resources we allocated earlier */
78 BIO_ADDRINFO_free(res
);
80 /* If sock is -1 then we've been unable to connect to the server */
84 /* Create a BIO to wrap the socket*/
85 bio
= BIO_new(BIO_s_socket());
87 BIO_closesocket(sock
);
90 * Associate the newly created BIO with the underlying socket. By
91 * passing BIO_CLOSE here the socket will be automatically closed when
92 * the BIO is freed. Alternatively you can use BIO_NOCLOSE, in which
93 * case you must close the socket explicitly when it is no longer
96 BIO_set_fd(bio
, sock
, BIO_CLOSE
);
101 static void wait_for_activity(SSL
*ssl
, int write
)
106 /* Get hold of the underlying file descriptor for the socket */
107 sock
= SSL_get_fd(ssl
);
114 * Wait until the socket is writeable or readable. We use select here for
115 * the sake of simplicity and portability, but you could equally use
116 * poll/epoll or similar functions
119 select(width
, NULL
, &fds
, NULL
, NULL
);
121 select(width
, &fds
, NULL
, NULL
, NULL
);
124 static int handle_io_failure(SSL
*ssl
, int res
)
126 switch (SSL_get_error(ssl
, res
)) {
127 case SSL_ERROR_WANT_READ
:
128 /* Temporary failure. Wait until we can read and try again */
129 wait_for_activity(ssl
, 0);
132 case SSL_ERROR_WANT_WRITE
:
133 /* Temporary failure. Wait until we can write and try again */
134 wait_for_activity(ssl
, 1);
137 case SSL_ERROR_ZERO_RETURN
:
141 case SSL_ERROR_SYSCALL
:
146 * If the failure is due to a verification error we can get more
147 * information about it from SSL_get_verify_result().
149 if (SSL_get_verify_result(ssl
) != X509_V_OK
)
150 printf("Verify error: %s\n",
151 X509_verify_cert_error_string(SSL_get_verify_result(ssl
)));
159 /* Server hostname and port details. Must be in quotes */
161 # define HOSTNAME "www.example.com"
168 * Simple application to send a basic HTTP/1.0 request to a server and
169 * print the response on the screen.
176 int res
= EXIT_FAILURE
;
178 const char *request
=
179 "GET / HTTP/1.0\r\nConnection: close\r\nHost: "HOSTNAME
"\r\n\r\n";
180 size_t written
, readbytes
;
185 * Create an SSL_CTX which we can use to create SSL objects from. We
186 * want an SSL_CTX for creating clients so we use TLS_client_method()
189 ctx
= SSL_CTX_new(TLS_client_method());
191 printf("Failed to create the SSL_CTX\n");
196 * Configure the client to abort the handshake if certificate
197 * verification fails. Virtually all clients should do this unless you
198 * really know what you are doing.
200 SSL_CTX_set_verify(ctx
, SSL_VERIFY_PEER
, NULL
);
202 /* Use the default trusted certificate store */
203 if (!SSL_CTX_set_default_verify_paths(ctx
)) {
204 printf("Failed to set the default trusted certificate store\n");
209 * TLSv1.1 or earlier are deprecated by IETF and are generally to be
210 * avoided if possible. We require a minimum TLS version of TLSv1.2.
212 if (!SSL_CTX_set_min_proto_version(ctx
, TLS1_2_VERSION
)) {
213 printf("Failed to set the minimum TLS protocol version\n");
217 /* Create an SSL object to represent the TLS connection */
220 printf("Failed to create the SSL object\n");
225 * Create the underlying transport socket/BIO and associate it with the
228 bio
= create_socket_bio(HOSTNAME
, PORT
);
230 printf("Failed to crete the BIO\n");
233 SSL_set_bio(ssl
, bio
, bio
);
236 * Tell the server during the handshake which hostname we are attempting
237 * to connect to in case the server supports multiple hosts.
239 if (!SSL_set_tlsext_host_name(ssl
, HOSTNAME
)) {
240 printf("Failed to set the SNI hostname\n");
245 * Ensure we check during certificate verification that the server has
246 * supplied a certificate for the hostname that we were expecting.
247 * Virtually all clients should do this unless you really know what you
250 if (!SSL_set1_host(ssl
, HOSTNAME
)) {
251 printf("Failed to set the certificate verification hostname");
255 /* Do the handshake with the server */
256 while ((ret
= SSL_connect(ssl
)) != 1) {
257 if (handle_io_failure(ssl
, ret
) == 1)
258 continue; /* Retry */
259 printf("Failed to connect to server\n");
260 goto end
; /* Cannot retry: error */
263 /* Write an HTTP GET request to the peer */
264 while (!SSL_write_ex(ssl
, request
, strlen(request
), &written
)) {
265 if (handle_io_failure(ssl
, 0) == 1)
266 continue; /* Retry */
267 printf("Failed to write HTTP request\n");
268 goto end
; /* Cannot retry: error */
273 * Get up to sizeof(buf) bytes of the response. We keep reading until
274 * the server closes the connection.
276 while (!eof
&& !SSL_read_ex(ssl
, buf
, sizeof(buf
), &readbytes
)) {
277 switch (handle_io_failure(ssl
, 0)) {
279 continue; /* Retry */
285 printf("Failed reading remaining data\n");
286 goto end
; /* Cannot retry: error */
290 * OpenSSL does not guarantee that the returned data is a string or
291 * that it is NUL terminated so we use fwrite() to write the exact
292 * number of bytes that we read. The data could be non-printable or
293 * have NUL characters in the middle of it. For this simple example
294 * we're going to print it to stdout anyway.
297 fwrite(buf
, 1, readbytes
, stdout
);
299 /* In case the response didn't finish with a newline we add one now */
303 * The peer already shutdown gracefully (we know this because of the
304 * SSL_ERROR_ZERO_RETURN (i.e. EOF) above). We should do the same back.
306 while ((ret
= SSL_shutdown(ssl
)) != 1) {
307 if (ret
< 0 && handle_io_failure(ssl
, ret
) == 1)
308 continue; /* Retry */
310 * ret == 0 is unexpected here because that means "we've sent a
311 * close_notify and we're waiting for one back". But we already know
312 * we got one from the peer because of the SSL_ERROR_ZERO_RETURN
315 printf("Error shutting down\n");
316 goto end
; /* Cannot retry: error */
323 * If something bad happened then we will dump the contents of the
324 * OpenSSL error stack to stderr. There might be some useful diagnostic
327 if (res
== EXIT_FAILURE
)
328 ERR_print_errors_fp(stderr
);
331 * Free the resources we allocated. We do not free the BIO object here
332 * because ownership of it was immediately transferred to the SSL object
333 * via SSL_set_bio(). The BIO will be freed when we free the SSL object.