1 /* 2 * Copyright 2023-2024 The OpenSSL Project Authors. All Rights Reserved. 3 * 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 8 */ 9 10 /* 11 * NB: Changes to this file should also be reflected in 12 * doc/man7/ossl-guide-tls-client-non-block.pod 13 */ 14 15 #include <string.h> 16 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> 23 #endif 24 25 #include <openssl/bio.h> 26 #include <openssl/ssl.h> 27 #include <openssl/err.h> 28 29 /* Helper function to create a BIO connected to the server */ 30 static BIO *create_socket_bio(const char *hostname, const char *port, int family) 31 { 32 int sock = -1; 33 BIO_ADDRINFO *res; 34 const BIO_ADDRINFO *ai = NULL; 35 BIO *bio; 36 37 /* 38 * Lookup IP address info for the server. 39 */ 40 if (!BIO_lookup_ex(hostname, port, BIO_LOOKUP_CLIENT, family, SOCK_STREAM, 0, 41 &res)) 42 return NULL; 43 44 /* 45 * Loop through all the possible addresses for the server and find one 46 * we can connect to. 47 */ 48 for (ai = res; ai != NULL; ai = BIO_ADDRINFO_next(ai)) { 49 /* 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. 55 */ 56 sock = BIO_socket(BIO_ADDRINFO_family(ai), SOCK_STREAM, 0, 0); 57 if (sock == -1) 58 continue; 59 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); 63 sock = -1; 64 continue; 65 } 66 67 /* Set to nonblocking mode */ 68 if (!BIO_socket_nbio(sock, 1)) { 69 sock = -1; 70 continue; 71 } 72 73 /* We have a connected socket so break out of the loop */ 74 break; 75 } 76 77 /* Free the address information resources we allocated earlier */ 78 BIO_ADDRINFO_free(res); 79 80 /* If sock is -1 then we've been unable to connect to the server */ 81 if (sock == -1) 82 return NULL; 83 84 /* Create a BIO to wrap the socket */ 85 bio = BIO_new(BIO_s_socket()); 86 if (bio == NULL) { 87 BIO_closesocket(sock); 88 return NULL; 89 } 90 91 /* 92 * Associate the newly created BIO with the underlying socket. By 93 * passing BIO_CLOSE here the socket will be automatically closed when 94 * the BIO is freed. Alternatively you can use BIO_NOCLOSE, in which 95 * case you must close the socket explicitly when it is no longer 96 * needed. 97 */ 98 BIO_set_fd(bio, sock, BIO_CLOSE); 99 100 return bio; 101 } 102 103 static void wait_for_activity(SSL *ssl, int write) 104 { 105 fd_set fds; 106 int width, sock; 107 108 /* Get hold of the underlying file descriptor for the socket */ 109 sock = SSL_get_fd(ssl); 110 111 FD_ZERO(&fds); 112 FD_SET(sock, &fds); 113 width = sock + 1; 114 115 /* 116 * Wait until the socket is writeable or readable. We use select here 117 * for the sake of simplicity and portability, but you could equally use 118 * poll/epoll or similar functions 119 * 120 * NOTE: For the purposes of this demonstration code this effectively 121 * makes this demo block until it has something more useful to do. In a 122 * real application you probably want to go and do other work here (e.g. 123 * update a GUI, or service other connections). 124 * 125 * Let's say for example that you want to update the progress counter on 126 * a GUI every 100ms. One way to do that would be to add a 100ms timeout 127 * in the last parameter to "select" below. Then, when select returns, 128 * you check if it did so because of activity on the file descriptors or 129 * because of the timeout. If it is due to the timeout then update the 130 * GUI and then restart the "select". 131 */ 132 if (write) 133 select(width, NULL, &fds, NULL, NULL); 134 else 135 select(width, &fds, NULL, NULL, NULL); 136 } 137 138 static int handle_io_failure(SSL *ssl, int res) 139 { 140 switch (SSL_get_error(ssl, res)) { 141 case SSL_ERROR_WANT_READ: 142 /* Temporary failure. Wait until we can read and try again */ 143 wait_for_activity(ssl, 0); 144 return 1; 145 146 case SSL_ERROR_WANT_WRITE: 147 /* Temporary failure. Wait until we can write and try again */ 148 wait_for_activity(ssl, 1); 149 return 1; 150 151 case SSL_ERROR_ZERO_RETURN: 152 /* EOF */ 153 return 0; 154 155 case SSL_ERROR_SYSCALL: 156 return -1; 157 158 case SSL_ERROR_SSL: 159 /* 160 * If the failure is due to a verification error we can get more 161 * information about it from SSL_get_verify_result(). 162 */ 163 if (SSL_get_verify_result(ssl) != X509_V_OK) 164 printf("Verify error: %s\n", 165 X509_verify_cert_error_string(SSL_get_verify_result(ssl))); 166 return -1; 167 168 default: 169 return -1; 170 } 171 } 172 173 /* 174 * Simple application to send a basic HTTP/1.0 request to a server and 175 * print the response on the screen. 176 */ 177 int main(int argc, char *argv[]) 178 { 179 SSL_CTX *ctx = NULL; 180 SSL *ssl = NULL; 181 BIO *bio = NULL; 182 int res = EXIT_FAILURE; 183 int ret; 184 const char *request_start = "GET / HTTP/1.0\r\nConnection: close\r\nHost: "; 185 const char *request_end = "\r\n\r\n"; 186 size_t written, readbytes = 0; 187 char buf[160]; 188 int eof = 0; 189 char *hostname, *port; 190 int argnext = 1; 191 int ipv6 = 0; 192 193 if (argc < 3) { 194 printf("Usage: tls-client-non-block [-6] hostname port\n"); 195 goto end; 196 } 197 198 if (!strcmp(argv[argnext], "-6")) { 199 if (argc < 4) { 200 printf("Usage: tls-client-non-block [-6] hostname port\n"); 201 goto end; 202 } 203 ipv6 = 1; 204 argnext++; 205 } 206 207 hostname = argv[argnext++]; 208 port = argv[argnext]; 209 210 /* 211 * Create an SSL_CTX which we can use to create SSL objects from. We 212 * want an SSL_CTX for creating clients so we use TLS_client_method() 213 * here. 214 */ 215 ctx = SSL_CTX_new(TLS_client_method()); 216 if (ctx == NULL) { 217 printf("Failed to create the SSL_CTX\n"); 218 goto end; 219 } 220 221 /* 222 * Configure the client to abort the handshake if certificate 223 * verification fails. Virtually all clients should do this unless you 224 * really know what you are doing. 225 */ 226 SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL); 227 228 /* Use the default trusted certificate store */ 229 if (!SSL_CTX_set_default_verify_paths(ctx)) { 230 printf("Failed to set the default trusted certificate store\n"); 231 goto end; 232 } 233 234 /* 235 * TLSv1.1 or earlier are deprecated by IETF and are generally to be 236 * avoided if possible. We require a minimum TLS version of TLSv1.2. 237 */ 238 if (!SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION)) { 239 printf("Failed to set the minimum TLS protocol version\n"); 240 goto end; 241 } 242 243 /* Create an SSL object to represent the TLS connection */ 244 ssl = SSL_new(ctx); 245 if (ssl == NULL) { 246 printf("Failed to create the SSL object\n"); 247 goto end; 248 } 249 250 /* 251 * Create the underlying transport socket/BIO and associate it with the 252 * connection. 253 */ 254 bio = create_socket_bio(hostname, port, ipv6 ? AF_INET6 : AF_INET); 255 if (bio == NULL) { 256 printf("Failed to crete the BIO\n"); 257 goto end; 258 } 259 SSL_set_bio(ssl, bio, bio); 260 261 /* 262 * Tell the server during the handshake which hostname we are attempting 263 * to connect to in case the server supports multiple hosts. 264 */ 265 if (!SSL_set_tlsext_host_name(ssl, hostname)) { 266 printf("Failed to set the SNI hostname\n"); 267 goto end; 268 } 269 270 /* 271 * Ensure we check during certificate verification that the server has 272 * supplied a certificate for the hostname that we were expecting. 273 * Virtually all clients should do this unless you really know what you 274 * are doing. 275 */ 276 if (!SSL_set1_host(ssl, hostname)) { 277 printf("Failed to set the certificate verification hostname"); 278 goto end; 279 } 280 281 /* Do the handshake with the server */ 282 while ((ret = SSL_connect(ssl)) != 1) { 283 if (handle_io_failure(ssl, ret) == 1) 284 continue; /* Retry */ 285 printf("Failed to connect to server\n"); 286 goto end; /* Cannot retry: error */ 287 } 288 289 /* Write an HTTP GET request to the peer */ 290 while (!SSL_write_ex(ssl, request_start, strlen(request_start), &written)) { 291 if (handle_io_failure(ssl, 0) == 1) 292 continue; /* Retry */ 293 printf("Failed to write start of HTTP request\n"); 294 goto end; /* Cannot retry: error */ 295 } 296 while (!SSL_write_ex(ssl, hostname, strlen(hostname), &written)) { 297 if (handle_io_failure(ssl, 0) == 1) 298 continue; /* Retry */ 299 printf("Failed to write hostname in HTTP request\n"); 300 goto end; /* Cannot retry: error */ 301 } 302 while (!SSL_write_ex(ssl, request_end, strlen(request_end), &written)) { 303 if (handle_io_failure(ssl, 0) == 1) 304 continue; /* Retry */ 305 printf("Failed to write end of HTTP request\n"); 306 goto end; /* Cannot retry: error */ 307 } 308 309 do { 310 /* 311 * Get up to sizeof(buf) bytes of the response. We keep reading until 312 * the server closes the connection. 313 */ 314 while (!eof && !SSL_read_ex(ssl, buf, sizeof(buf), &readbytes)) { 315 switch (handle_io_failure(ssl, 0)) { 316 case 1: 317 continue; /* Retry */ 318 case 0: 319 eof = 1; 320 continue; 321 case -1: 322 default: 323 printf("Failed reading remaining data\n"); 324 goto end; /* Cannot retry: error */ 325 } 326 } 327 /* 328 * OpenSSL does not guarantee that the returned data is a string or 329 * that it is NUL terminated so we use fwrite() to write the exact 330 * number of bytes that we read. The data could be non-printable or 331 * have NUL characters in the middle of it. For this simple example 332 * we're going to print it to stdout anyway. 333 */ 334 if (!eof) 335 fwrite(buf, 1, readbytes, stdout); 336 } while (!eof); 337 /* In case the response didn't finish with a newline we add one now */ 338 printf("\n"); 339 340 /* 341 * The peer already shutdown gracefully (we know this because of the 342 * SSL_ERROR_ZERO_RETURN (i.e. EOF) above). We should do the same back. 343 */ 344 while ((ret = SSL_shutdown(ssl)) != 1) { 345 if (ret < 0 && handle_io_failure(ssl, ret) == 1) 346 continue; /* Retry */ 347 /* 348 * ret == 0 is unexpected here because that means "we've sent a 349 * close_notify and we're waiting for one back". But we already know 350 * we got one from the peer because of the SSL_ERROR_ZERO_RETURN 351 * (i.e. EOF) above. 352 */ 353 printf("Error shutting down\n"); 354 goto end; /* Cannot retry: error */ 355 } 356 357 /* Success! */ 358 res = EXIT_SUCCESS; 359 end: 360 /* 361 * If something bad happened then we will dump the contents of the 362 * OpenSSL error stack to stderr. There might be some useful diagnostic 363 * information there. 364 */ 365 if (res == EXIT_FAILURE) 366 ERR_print_errors_fp(stderr); 367 368 /* 369 * Free the resources we allocated. We do not free the BIO object here 370 * because ownership of it was immediately transferred to the SSL object 371 * via SSL_set_bio(). The BIO will be freed when we free the SSL object. 372 */ 373 SSL_free(ssl); 374 SSL_CTX_free(ctx); 375 return res; 376 } 377