1 /* 2 * Copyright 2023-2025 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-quic-client-non-block.pod 13 */ 14 15 #include <string.h> 16 17 /* Include the appropriate header file for SOCK_DGRAM */ 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, 31 int family, BIO_ADDR **peer_addr) 32 { 33 int sock = -1; 34 BIO_ADDRINFO *res; 35 const BIO_ADDRINFO *ai = NULL; 36 BIO *bio; 37 38 /* 39 * Lookup IP address info for the server. 40 */ 41 if (!BIO_lookup_ex(hostname, port, BIO_LOOKUP_CLIENT, family, SOCK_DGRAM, 0, 42 &res)) 43 return NULL; 44 45 /* 46 * Loop through all the possible addresses for the server and find one 47 * we can connect to. 48 */ 49 for (ai = res; ai != NULL; ai = BIO_ADDRINFO_next(ai)) { 50 /* 51 * Create a UDP socket. We could equally use non-OpenSSL calls such 52 * as "socket" here for this and the subsequent connect and close 53 * functions. But for portability reasons and also so that we get 54 * errors on the OpenSSL stack in the event of a failure we use 55 * OpenSSL's versions of these functions. 56 */ 57 sock = BIO_socket(BIO_ADDRINFO_family(ai), SOCK_DGRAM, 0, 0); 58 if (sock == -1) 59 continue; 60 61 /* Connect the socket to the server's address */ 62 if (!BIO_connect(sock, BIO_ADDRINFO_address(ai), 0)) { 63 BIO_closesocket(sock); 64 sock = -1; 65 continue; 66 } 67 68 /* Set to nonblocking mode */ 69 if (!BIO_socket_nbio(sock, 1)) { 70 BIO_closesocket(sock); 71 sock = -1; 72 continue; 73 } 74 75 break; 76 } 77 78 if (sock != -1) { 79 *peer_addr = BIO_ADDR_dup(BIO_ADDRINFO_address(ai)); 80 if (*peer_addr == NULL) { 81 BIO_closesocket(sock); 82 return NULL; 83 } 84 } 85 86 /* Free the address information resources we allocated earlier */ 87 BIO_ADDRINFO_free(res); 88 89 /* If sock is -1 then we've been unable to connect to the server */ 90 if (sock == -1) 91 return NULL; 92 93 /* Create a BIO to wrap the socket */ 94 bio = BIO_new(BIO_s_datagram()); 95 if (bio == NULL) { 96 BIO_closesocket(sock); 97 return NULL; 98 } 99 100 /* 101 * Associate the newly created BIO with the underlying socket. By 102 * passing BIO_CLOSE here the socket will be automatically closed when 103 * the BIO is freed. Alternatively you can use BIO_NOCLOSE, in which 104 * case you must close the socket explicitly when it is no longer 105 * needed. 106 */ 107 BIO_set_fd(bio, sock, BIO_CLOSE); 108 109 return bio; 110 } 111 112 static void wait_for_activity(SSL *ssl) 113 { 114 fd_set wfds, rfds; 115 int width, sock, isinfinite; 116 struct timeval tv; 117 struct timeval *tvp = NULL; 118 119 /* Get hold of the underlying file descriptor for the socket */ 120 sock = SSL_get_fd(ssl); 121 122 FD_ZERO(&wfds); 123 FD_ZERO(&rfds); 124 125 /* 126 * Find out if we would like to write to the socket, or read from it (or 127 * both) 128 */ 129 if (SSL_net_write_desired(ssl)) 130 FD_SET(sock, &wfds); 131 if (SSL_net_read_desired(ssl)) 132 FD_SET(sock, &rfds); 133 width = sock + 1; 134 135 /* 136 * Find out when OpenSSL would next like to be called, regardless of 137 * whether the state of the underlying socket has changed or not. 138 */ 139 if (SSL_get_event_timeout(ssl, &tv, &isinfinite) && !isinfinite) 140 tvp = &tv; 141 142 /* 143 * Wait until the socket is writeable or readable. We use select here 144 * for the sake of simplicity and portability, but you could equally use 145 * poll/epoll or similar functions 146 * 147 * NOTE: For the purposes of this demonstration code this effectively 148 * makes this demo block until it has something more useful to do. In a 149 * real application you probably want to go and do other work here (e.g. 150 * update a GUI, or service other connections). 151 * 152 * Let's say for example that you want to update the progress counter on 153 * a GUI every 100ms. One way to do that would be to use the timeout in 154 * the last parameter to "select" below. If the tvp value is greater 155 * than 100ms then use 100ms instead. Then, when select returns, you 156 * check if it did so because of activity on the file descriptors or 157 * because of the timeout. If the 100ms GUI timeout has expired but the 158 * tvp timeout has not then go and update the GUI and then restart the 159 * "select" (with updated timeouts). 160 */ 161 162 select(width, &rfds, &wfds, NULL, tvp); 163 } 164 165 static int handle_io_failure(SSL *ssl, int res) 166 { 167 switch (SSL_get_error(ssl, res)) { 168 case SSL_ERROR_WANT_READ: 169 case SSL_ERROR_WANT_WRITE: 170 /* Temporary failure. Wait until we can read/write and try again */ 171 wait_for_activity(ssl); 172 return 1; 173 174 case SSL_ERROR_ZERO_RETURN: 175 /* EOF */ 176 return 0; 177 178 case SSL_ERROR_SYSCALL: 179 return -1; 180 181 case SSL_ERROR_SSL: 182 /* 183 * Some stream fatal error occurred. This could be because of a 184 * stream reset - or some failure occurred on the underlying 185 * connection. 186 */ 187 switch (SSL_get_stream_read_state(ssl)) { 188 case SSL_STREAM_STATE_RESET_REMOTE: 189 printf("Stream reset occurred\n"); 190 /* 191 * The stream has been reset but the connection is still 192 * healthy. 193 */ 194 break; 195 196 case SSL_STREAM_STATE_CONN_CLOSED: 197 printf("Connection closed\n"); 198 /* Connection is already closed. */ 199 break; 200 201 default: 202 printf("Unknown stream failure\n"); 203 break; 204 } 205 /* 206 * If the failure is due to a verification error we can get more 207 * information about it from SSL_get_verify_result(). 208 */ 209 if (SSL_get_verify_result(ssl) != X509_V_OK) 210 printf("Verify error: %s\n", 211 X509_verify_cert_error_string(SSL_get_verify_result(ssl))); 212 return -1; 213 214 default: 215 return -1; 216 } 217 } 218 /* 219 * Simple application to send a basic HTTP/1.0 request to a server and 220 * print the response on the screen. Note that HTTP/1.0 over QUIC is 221 * non-standard and will not typically be supported by real world servers. This 222 * is for demonstration purposes only. 223 */ 224 int main(int argc, char *argv[]) 225 { 226 SSL_CTX *ctx = NULL; 227 SSL *ssl = NULL; 228 BIO *bio = NULL; 229 int res = EXIT_FAILURE; 230 int ret; 231 unsigned char alpn[] = { 8, 'h', 't', 't', 'p', '/', '1', '.', '0' }; 232 const char *request_start = "GET / HTTP/1.0\r\nConnection: close\r\nHost: "; 233 const char *request_end = "\r\n\r\n"; 234 size_t written, readbytes = 0; 235 char buf[160]; 236 BIO_ADDR *peer_addr = NULL; 237 int eof = 0; 238 char *hostname, *port; 239 int ipv6 = 0; 240 int argnext = 1; 241 242 if (argc < 3) { 243 printf("Usage: quic-client-non-block [-6] hostname port\n"); 244 goto end; 245 } 246 247 if (!strcmp(argv[argnext], "-6")) { 248 if (argc < 4) { 249 printf("Usage: quic-client-non-block [-6] hostname port\n"); 250 goto end; 251 } 252 ipv6 = 1; 253 argnext++; 254 } 255 hostname = argv[argnext++]; 256 port = argv[argnext]; 257 258 /* 259 * Create an SSL_CTX which we can use to create SSL objects from. We 260 * want an SSL_CTX for creating clients so we use 261 * OSSL_QUIC_client_method() here. 262 */ 263 ctx = SSL_CTX_new(OSSL_QUIC_client_method()); 264 if (ctx == NULL) { 265 printf("Failed to create the SSL_CTX\n"); 266 goto end; 267 } 268 269 /* 270 * Configure the client to abort the handshake if certificate 271 * verification fails. Virtually all clients should do this unless you 272 * really know what you are doing. 273 */ 274 SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL); 275 276 /* Use the default trusted certificate store */ 277 if (!SSL_CTX_set_default_verify_paths(ctx)) { 278 printf("Failed to set the default trusted certificate store\n"); 279 goto end; 280 } 281 282 /* Create an SSL object to represent the TLS connection */ 283 ssl = SSL_new(ctx); 284 if (ssl == NULL) { 285 printf("Failed to create the SSL object\n"); 286 goto end; 287 } 288 289 /* 290 * Create the underlying transport socket/BIO and associate it with the 291 * connection. 292 */ 293 bio = create_socket_bio(hostname, port, ipv6 ? AF_INET6 : AF_INET, 294 &peer_addr); 295 if (bio == NULL) { 296 printf("Failed to crete the BIO\n"); 297 goto end; 298 } 299 SSL_set_bio(ssl, bio, bio); 300 301 /* 302 * Tell the server during the handshake which hostname we are attempting 303 * to connect to in case the server supports multiple hosts. 304 */ 305 if (!SSL_set_tlsext_host_name(ssl, hostname)) { 306 printf("Failed to set the SNI hostname\n"); 307 goto end; 308 } 309 310 /* 311 * Ensure we check during certificate verification that the server has 312 * supplied a certificate for the hostname that we were expecting. 313 * Virtually all clients should do this unless you really know what you 314 * are doing. 315 */ 316 if (!SSL_set1_host(ssl, hostname)) { 317 printf("Failed to set the certificate verification hostname"); 318 goto end; 319 } 320 321 /* SSL_set_alpn_protos returns 0 for success! */ 322 if (SSL_set_alpn_protos(ssl, alpn, sizeof(alpn)) != 0) { 323 printf("Failed to set the ALPN for the connection\n"); 324 goto end; 325 } 326 327 /* Set the IP address of the remote peer */ 328 if (!SSL_set1_initial_peer_addr(ssl, peer_addr)) { 329 printf("Failed to set the initial peer address\n"); 330 goto end; 331 } 332 333 /* 334 * The underlying socket is always nonblocking with QUIC, but the default 335 * behaviour of the SSL object is still to block. We set it for nonblocking 336 * mode in this demo. 337 */ 338 if (!SSL_set_blocking_mode(ssl, 0)) { 339 printf("Failed to turn off blocking mode\n"); 340 goto end; 341 } 342 343 /* Do the handshake with the server */ 344 while ((ret = SSL_connect(ssl)) != 1) { 345 if (handle_io_failure(ssl, ret) == 1) 346 continue; /* Retry */ 347 printf("Failed to connect to server\n"); 348 goto end; /* Cannot retry: error */ 349 } 350 351 /* Write an HTTP GET request to the peer */ 352 while (!SSL_write_ex(ssl, request_start, strlen(request_start), &written)) { 353 if (handle_io_failure(ssl, 0) == 1) 354 continue; /* Retry */ 355 printf("Failed to write start of HTTP request\n"); 356 goto end; /* Cannot retry: error */ 357 } 358 while (!SSL_write_ex(ssl, hostname, strlen(hostname), &written)) { 359 if (handle_io_failure(ssl, 0) == 1) 360 continue; /* Retry */ 361 printf("Failed to write hostname in HTTP request\n"); 362 goto end; /* Cannot retry: error */ 363 } 364 while (!SSL_write_ex2(ssl, request_end, strlen(request_end), 365 SSL_WRITE_FLAG_CONCLUDE, &written)) { 366 if (handle_io_failure(ssl, 0) == 1) 367 continue; /* Retry */ 368 printf("Failed to write end of HTTP request\n"); 369 goto end; /* Cannot retry: error */ 370 } 371 372 do { 373 /* 374 * Get up to sizeof(buf) bytes of the response. We keep reading until 375 * the server closes the connection. 376 */ 377 while (!eof && !SSL_read_ex(ssl, buf, sizeof(buf), &readbytes)) { 378 switch (handle_io_failure(ssl, 0)) { 379 case 1: 380 continue; /* Retry */ 381 case 0: 382 eof = 1; 383 continue; 384 case -1: 385 default: 386 printf("Failed reading remaining data\n"); 387 goto end; /* Cannot retry: error */ 388 } 389 } 390 /* 391 * OpenSSL does not guarantee that the returned data is a string or 392 * that it is NUL terminated so we use fwrite() to write the exact 393 * number of bytes that we read. The data could be non-printable or 394 * have NUL characters in the middle of it. For this simple example 395 * we're going to print it to stdout anyway. 396 */ 397 if (!eof) 398 fwrite(buf, 1, readbytes, stdout); 399 } while (!eof); 400 /* In case the response didn't finish with a newline we add one now */ 401 printf("\n"); 402 403 /* 404 * Repeatedly call SSL_shutdown() until the connection is fully 405 * closed. 406 */ 407 while ((ret = SSL_shutdown(ssl)) != 1) { 408 if (ret < 0 && handle_io_failure(ssl, ret) == 1) 409 continue; /* Retry */ 410 } 411 412 /* Success! */ 413 res = EXIT_SUCCESS; 414 end: 415 /* 416 * If something bad happened then we will dump the contents of the 417 * OpenSSL error stack to stderr. There might be some useful diagnostic 418 * information there. 419 */ 420 if (res == EXIT_FAILURE) 421 ERR_print_errors_fp(stderr); 422 423 /* 424 * Free the resources we allocated. We do not free the BIO object here 425 * because ownership of it was immediately transferred to the SSL object 426 * via SSL_set_bio(). The BIO will be freed when we free the SSL object. 427 */ 428 SSL_free(ssl); 429 SSL_CTX_free(ctx); 430 BIO_ADDR_free(peer_addr); 431 return res; 432 } 433