1=pod 2 3=begin comment 4 5NB: Changes to the source code samples in this file should also be reflected in 6demos/guide/quic-server-block.c 7 8=end comment 9 10=head1 NAME 11 12ossl-guide-quic-server-block 13- OpenSSL Guide: Writing a simple blocking QUIC server 14 15=head1 SIMPLE BLOCKING QUIC SERVER EXAMPLE 16 17This page will present various source code samples demonstrating how to write a 18simple, non-concurrent, QUIC "echo" server application which accepts one client 19connection at a time, echoing input from the client back to the same client. 20Once the current client disconnects, the next client connection is accepted. 21 22The server only accepts HTTP/1.0 requests, which is non-standard and will not 23be supported by real world servers. This is for demonstration purposes only. 24 25Both the accepting socket and client connections are "blocking". A more typical 26server might use nonblocking sockets with an event loop and callbacks for I/O 27events. 28 29The complete source code for this example blocking QUIC server is available in 30the B<demos/guide> directory of the OpenSSL source distribution in the file 31B<quic-server-block.c>. It is also available online at 32L<https://github.com/openssl/openssl/blob/master/demos/guide/quic-server-block.c>. 33 34We assume that you already have OpenSSL installed on your system; that you 35already have some fundamental understanding of OpenSSL concepts and QUIC (see 36L<ossl-guide-libraries-introduction(7)> and L<ossl-guide-quic-introduction(7)>); 37and that you know how to write and build C code and link it against the 38libcrypto and libssl libraries that are provided by OpenSSL. It also assumes 39that you have a basic understanding of UDP/IP and sockets. 40 41=head2 Creating the SSL_CTX and SSL objects 42 43The first step is to create an B<SSL_CTX> object for our server. We use the 44L<SSL_CTX_new(3)> function for this purpose. We pass as an argument the return 45value of the function L<OSSL_QUIC_server_method(3)>. You should use this method 46whenever you are writing a QUIC server. 47 48 /* 49 * An SSL_CTX holds shared configuration information for multiple 50 * subsequent per-client SSL connections. We specifically load a QUIC 51 * server method here. 52 */ 53 ctx = SSL_CTX_new(OSSL_QUIC_server_method()); 54 if (ctx == NULL) 55 goto err; 56 57Servers need a private key and certificate. Intermediate issuer CA 58certificates are often required, and both the server (end-entity or EE) 59certificate and the issuer ("chain") certificates are most easily configured in 60a single "chain file". Below we load such a chain file (the EE certificate 61must appear first), and then load the corresponding private key, checking that 62it matches the server certificate. No checks are performed to check the 63integrity of the chain (CA signatures or certificate expiration dates, for 64example), but we do verify the consistency of the private key with the 65corresponding certificate. 66 67 /* 68 * Load the server's certificate *chain* file (PEM format), which includes 69 * not only the leaf (end-entity) server certificate, but also any 70 * intermediate issuer-CA certificates. The leaf certificate must be the 71 * first certificate in the file. 72 * 73 * In advanced use-cases this can be called multiple times, once per public 74 * key algorithm for which the server has a corresponding certificate. 75 * However, the corresponding private key (see below) must be loaded first, 76 * *before* moving on to the next chain file. 77 */ 78 if (SSL_CTX_use_certificate_chain_file(ctx, cert_path) <= 0) { 79 fprintf(stderr, "couldn't load certificate file: %s\n", cert_path); 80 goto err; 81 } 82 83 /* 84 * Load the corresponding private key, this also checks that the private 85 * key matches the just loaded end-entity certificate. It does not check 86 * whether the certificate chain is valid, the certificates could be 87 * expired, or may otherwise fail to form a chain that a client can 88 * validate. 89 */ 90 if (SSL_CTX_use_PrivateKey_file(ctx, key_path, SSL_FILETYPE_PEM) <= 0) { 91 fprintf(stderr, "couldn't load key file: %s\n", key_path); 92 goto err; 93 } 94 95Most servers, including this one, do not solicit client certificates. We 96therefore do not need a "trust store" and allow the handshake to complete even 97when the client does not present a certificate. Note: Even if a client did 98present a trusted certificate, for it to be useful, the server application 99would still need custom code to use the verified identity to grant nondefault 100access to that particular client. Some servers grant access to all clients 101with certificates from a private CA, this then requires processing of 102certificate revocation lists to deauthorise a client. It is often simpler and 103more secure to instead keep a list of authorised public keys. 104 105Though this is the default setting, we explicitly call the 106L<SSL_CTX_set_verify(3)> function and pass the B<SSL_VERIFY_NONE> value to it. 107The final argument to this function is a callback that you can optionally 108supply to override the default handling for certificate verification. Most 109applications do not need to do this so this can safely be set to NULL to get 110the default handling. 111 112 /* 113 * Clients rarely employ certificate-based authentication, and so we don't 114 * require "mutual" TLS authentication (indeed there's no way to know 115 * whether or how the client authenticated the server, so the term "mutual" 116 * is potentially misleading). 117 * 118 * Since we're not soliciting or processing client certificates, we don't 119 * need to configure a trusted-certificate store, so no call to 120 * SSL_CTX_set_default_verify_paths() is needed. The server's own 121 * certificate chain is assumed valid. 122 */ 123 SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL); 124 125QUIC also dictates using Application-Layer Protocol Negotiation (ALPN) to select 126an application protocol. We use L<SSL_CTX_set_alpn_select_cb(3)> for this 127purpose. We can pass a callback which will be called for each connection to 128select an ALPN the server considers acceptable. 129 130 /* Setup ALPN negotiation callback to decide which ALPN is accepted. */ 131 SSL_CTX_set_alpn_select_cb(ctx, select_alpn, NULL); 132 133In this case, we only accept "http/1.0" and "hq-interop". 134 135 /* 136 * ALPN strings for TLS handshake. Only 'http/1.0' and 'hq-interop' 137 * are accepted. 138 */ 139 static const unsigned char alpn_ossltest[] = { 140 8, 'h', 't', 't', 'p', '/', '1', '.', '0', 141 10, 'h', 'q', '-', 'i', 'n', 't', 'e', 'r', 'o', 'p', 142 }; 143 144 static int select_alpn(SSL *ssl, const unsigned char **out, 145 unsigned char *out_len, const unsigned char *in, 146 unsigned int in_len, void *arg) 147 { 148 if (SSL_select_next_proto((unsigned char **)out, out_len, alpn_ossltest, 149 sizeof(alpn_ossltest), in, 150 in_len) == OPENSSL_NPN_NEGOTIATED) 151 return SSL_TLSEXT_ERR_OK; 152 return SSL_TLSEXT_ERR_ALERT_FATAL; 153 } 154 155That is all the setup that we need to do for the B<SSL_CTX>. Next, we create a 156UDP socket and bind to it on localhost. 157 158 /* Retrieve the file descriptor for a new UDP socket */ 159 if ((fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) { 160 fprintf(stderr, "cannot create socket"); 161 goto err; 162 } 163 164 sa.sin_family = AF_INET; 165 sa.sin_port = htons(port); 166 167 /* Bind to the new UDP socket on localhost */ 168 if (bind(fd, (const struct sockaddr *)&sa, sizeof(sa)) < 0) { 169 fprintf(stderr, "cannot bind to %u\n", port); 170 BIO_closesocket(fd); 171 goto err; 172 } 173 174To run the QUIC server, we create an B<SSL_LISTENER> to listen for incoming 175connections. We provide it with the bound UDP port to then explicitly begin 176listening for new connections. 177 178 /* 179 * Create a new QUIC listener. Listeners, and other QUIC objects, default 180 * to operating in blocking mode. The configured behaviour is inherited by 181 * child objects. 182 */ 183 if ((listener = SSL_new_listener(ctx, 0)) == NULL) { 184 goto err; 185 } 186 187 /* Provide the listener with our UDP socket. */ 188 if (!SSL_set_fd(listener, fd)) 189 goto err; 190 191 /* Begin listening. */ 192 if (!SSL_listen(listener)) 193 goto err; 194 195=head2 Server loop 196 197The server now enters a "forever" loop, handling one client connection at a 198time. Before each connection, we clear the OpenSSL error stack so that any 199error reports are related to just the new connection. 200 201 /* Pristine error stack for each new connection */ 202 ERR_clear_error(); 203 204At this point, the server blocks to accept the next client. 205L<SSL_accept_connection(3)> will return an accepted connection within a fresh 206SSL, in which the handshake will have already occurred. 207 208 /* Block while waiting for a client connection */ 209 conn = SSL_accept_connection(listener, 0); 210 if (conn == NULL) { 211 fprintf(stderr, "error while accepting connection\n"); 212 goto err; 213 } 214 215With the handshake complete, the server echoes client input back to the client 216in a loop. 217 218 while (SSL_read_ex(conn, buf, sizeof(buf), &nread) > 0) { 219 if (SSL_write_ex(conn, buf, nread, &nwritten) > 0 && 220 nwritten == nread) { 221 continue; 222 } 223 fprintf(stderr, "Error echoing client input"); 224 break; 225 } 226 227Once the client closes its connection, we signal the end of the stream by using 228L<SSL_stream_conclude(3)>. This will send a final Finished packet to the 229client. 230 231 /* Signal the end of the stream. */ 232 if (SSL_stream_conclude(conn, 0) != 1) { 233 fprintf(stderr, "Unable to conclude stream\n"); 234 SSL_free(conn); 235 goto err; 236 } 237 238We then shut down the connection with L<SSL_shutdown_ex(3)>, which may need 239to be called multiple times to ensure the connection is shutdown completely. 240 241 while (SSL_shutdown_ex(conn, 0, &shutdown_args, 242 sizeof(SSL_SHUTDOWN_EX_ARGS)) != 1) { 243 fprintf(stderr, "Re-attempting SSL shutdown\n"); 244 } 245 246Finally, we free the SSL connection, and the server is now ready to accept the 247next client connection. 248 249 SSL_free(conn); 250 251=head2 Final clean up 252 253If the server somehow manages to break out of the infinite loop and 254be ready to exit, it would deallocate the constructed B<SSL>. 255 256 SSL_free(listener); 257 258And in the main function, it would deallocate the constructed B<SSL_CTX>. 259 260 SSL_CTX_free(ctx); 261 BIO_closesocket(fd); 262 res = EXIT_SUCCESS; 263 return res; 264 265=head1 SEE ALSO 266 267L<ossl-guide-introduction(7)>, L<ossl-guide-libraries-introduction(7)>, 268L<ossl-guide-libssl-introduction(7)>, L<ossl-guide-quic-introduction(7)>, 269L<ossl-guide-quic-client-non-block(7)>, L<ossl-guide-quic-client-block(7)>, 270L<ossl-guide-tls-server-block(7)>, L<ossl-guide-quic-server-non-block(7)> 271 272=head1 COPYRIGHT 273 274Copyright 2024-2025 The OpenSSL Project Authors. All Rights Reserved. 275 276Licensed under the Apache License 2.0 (the "License"). You may not use 277this file except in compliance with the License. You can obtain a copy 278in the file LICENSE in the source distribution or at 279L<https://www.openssl.org/source/license.html>. 280 281=cut 282