aboutsummaryrefslogtreecommitdiff
path: root/secure/lib/libcrypto/man/man7/ossl-guide-quic-server-non-block.7
diff options
context:
space:
mode:
Diffstat (limited to 'secure/lib/libcrypto/man/man7/ossl-guide-quic-server-non-block.7')
-rw-r--r--secure/lib/libcrypto/man/man7/ossl-guide-quic-server-non-block.7447
1 files changed, 447 insertions, 0 deletions
diff --git a/secure/lib/libcrypto/man/man7/ossl-guide-quic-server-non-block.7 b/secure/lib/libcrypto/man/man7/ossl-guide-quic-server-non-block.7
new file mode 100644
index 000000000000..7f3de1c8f7b8
--- /dev/null
+++ b/secure/lib/libcrypto/man/man7/ossl-guide-quic-server-non-block.7
@@ -0,0 +1,447 @@
+.\" -*- mode: troff; coding: utf-8 -*-
+.\" Automatically generated by Pod::Man 5.0102 (Pod::Simple 3.45)
+.\"
+.\" 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-QUIC-SERVER-NON-BLOCK 7ossl"
+.TH OSSL-GUIDE-QUIC-SERVER-NON-BLOCK 7ossl 2025-09-16 3.5.3 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\-quic\-server\-non\-block
+\&\- OpenSSL Guide: Writing a simple nonblocking QUIC server
+.SH "SIMPLE NONBLOCKING QUIC SERVER EXAMPLE"
+.IX Header "SIMPLE NONBLOCKING QUIC SERVER EXAMPLE"
+This page presents various source code samples demonstrating how to write a
+simple, non-concurrent, QUIC "echo" server application which accepts one client
+connection at a time, echoing input from the client back to the same client.
+Once the current client disconnects, the next client connection is accepted.
+.PP
+The server only accepts \f(CW\*(C`http/1.0\*(C'\fR and \f(CW\*(C`hq\-interop\*(C'\fR ALPN's and doesn't actually
+implement HTTP but only does a simple echo. This is non-standard and will not
+be supported by real world servers. This is for demonstration purposes only.
+.PP
+There are various methods to test this server: \fBquic\-client\-block.c\fR and
+\&\fBquic\-client\-non\-block.c\fR will send a basic HTTP/1.0 request, which the server
+will echo back. You can also test this server by running
+\&\f(CW\*(C`openssl s_client \-connect localhost:4443 \-4 \-quic \-alpn http/1.0\*(C'\fR and entering
+text that will be echoed back by the server.
+.PP
+Both the listening socket and connected socket are "nonblocking". However,
+we use \fBselect()\fR to make the listening socket block when it cannot read/write.
+Rather than stopping and waiting, your application may need to go and do other
+tasks whilst the \fBSSL\fR object is unable to read/write. For example: updating a
+GUI or performing operations on some other connection or stream.
+.PP
+The complete source code for this example nonblocking QUIC server is available
+in the \fBdemos/guide\fR directory of the OpenSSL source distribution in the file
+\&\fBquic\-server\-non\-block.c\fR. It is also available online at
+<https://github.com/openssl/openssl/blob/master/demos/guide/quic\-server\-non\-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 QUIC (see
+\&\fBossl\-guide\-libraries\-introduction\fR\|(7) and \fBossl\-guide\-quic\-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 UDP/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 server. We use the
+\&\fBSSL_CTX_new\fR\|(3) function for this purpose. We pass as an argument the return
+value of the function \fBOSSL_QUIC_server_method\fR\|(3). You should use this method
+whenever you are writing a QUIC server.
+.PP
+.Vb 8
+\& /*
+\& * An SSL_CTX holds shared configuration information for multiple
+\& * subsequent per\-client SSL connections. We specifically load a QUIC
+\& * server method here.
+\& */
+\& ctx = SSL_CTX_new(OSSL_QUIC_server_method());
+\& if (ctx == NULL)
+\& goto err;
+.Ve
+.PP
+Servers need a private key and certificate. Intermediate issuer CA
+certificates are often required, and both the server (end-entity or EE)
+certificate and the issuer ("chain") certificates are most easily configured in
+a single "chain file". Below we load such a chain file (the EE certificate
+must appear first), and then load the corresponding private key, checking that
+it matches the server certificate. No checks are performed to check the
+integrity of the chain (CA signatures or certificate expiration dates, for
+example), but we do verify the consistency of the private key with the
+corresponding certificate.
+.PP
+.Vb 10
+\& /*
+\& * Load the server\*(Aqs certificate *chain* file (PEM format), which includes
+\& * not only the leaf (end\-entity) server certificate, but also any
+\& * intermediate issuer\-CA certificates. The leaf certificate must be the
+\& * first certificate in the file.
+\& *
+\& * In advanced use\-cases this can be called multiple times, once per public
+\& * key algorithm for which the server has a corresponding certificate.
+\& * However, the corresponding private key (see below) must be loaded first,
+\& * *before* moving on to the next chain file.
+\& */
+\& if (SSL_CTX_use_certificate_chain_file(ctx, cert_path) <= 0) {
+\& fprintf(stderr, "couldn\*(Aqt load certificate file: %s\en", cert_path);
+\& goto err;
+\& }
+\&
+\& /*
+\& * Load the corresponding private key, this also checks that the private
+\& * key matches the just loaded end\-entity certificate. It does not check
+\& * whether the certificate chain is valid, the certificates could be
+\& * expired, or may otherwise fail to form a chain that a client can
+\& * validate.
+\& */
+\& if (SSL_CTX_use_PrivateKey_file(ctx, key_path, SSL_FILETYPE_PEM) <= 0) {
+\& fprintf(stderr, "couldn\*(Aqt load key file: %s\en", key_path);
+\& goto err;
+\& }
+.Ve
+.PP
+Most servers, including this one, do not solicit client certificates. We
+therefore do not need a "trust store" and allow the handshake to complete even
+when the client does not present a certificate. Note: Even if a client did
+present a trusted certificate, for it to be useful, the server application
+would still need custom code to use the verified identity to grant nondefault
+access to that particular client. Some servers grant access to all clients
+with certificates from a private CA, this then requires processing of
+certificate revocation lists to deauthorise a client. It is often simpler and
+more secure to instead keep a list of authorised public keys.
+.PP
+Though this is the default setting, we explicitly call the
+\&\fBSSL_CTX_set_verify\fR\|(3) function and pass the \fBSSL_VERIFY_NONE\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 12
+\& /*
+\& * Clients rarely employ certificate\-based authentication, and so we don\*(Aqt
+\& * require "mutual" TLS authentication (indeed there\*(Aqs no way to know
+\& * whether or how the client authenticated the server, so the term "mutual"
+\& * is potentially misleading).
+\& *
+\& * Since we\*(Aqre not soliciting or processing client certificates, we don\*(Aqt
+\& * need to configure a trusted\-certificate store, so no call to
+\& * SSL_CTX_set_default_verify_paths() is needed. The server\*(Aqs own
+\& * certificate chain is assumed valid.
+\& */
+\& SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL);
+.Ve
+.PP
+QUIC also dictates using Application-Layer Protocol Negotiation (ALPN) to select
+an application protocol. We use \fBSSL_CTX_set_alpn_select_cb\fR\|(3) for this
+purpose. We can pass a callback which will be called for each connection to
+select an ALPN the server considers acceptable.
+.PP
+.Vb 2
+\& /* Setup ALPN negotiation callback to decide which ALPN is accepted. */
+\& SSL_CTX_set_alpn_select_cb(ctx, select_alpn, NULL);
+.Ve
+.PP
+In this case, we only accept "http/1.0" and "hq-interop".
+.PP
+.Vb 8
+\& /*
+\& * ALPN strings for TLS handshake. Only \*(Aqhttp/1.0\*(Aq and \*(Aqhq\-interop\*(Aq
+\& * are accepted.
+\& */
+\& static const unsigned char alpn_ossltest[] = {
+\& 8, \*(Aqh\*(Aq, \*(Aqt\*(Aq, \*(Aqt\*(Aq, \*(Aqp\*(Aq, \*(Aq/\*(Aq, \*(Aq1\*(Aq, \*(Aq.\*(Aq, \*(Aq0\*(Aq,
+\& 10, \*(Aqh\*(Aq, \*(Aqq\*(Aq, \*(Aq\-\*(Aq, \*(Aqi\*(Aq, \*(Aqn\*(Aq, \*(Aqt\*(Aq, \*(Aqe\*(Aq, \*(Aqr\*(Aq, \*(Aqo\*(Aq, \*(Aqp\*(Aq,
+\& };
+\&
+\& static int select_alpn(SSL *ssl, const unsigned char **out,
+\& unsigned char *out_len, const unsigned char *in,
+\& unsigned int in_len, void *arg)
+\& {
+\& if (SSL_select_next_proto((unsigned char **)out, out_len, alpn_ossltest,
+\& sizeof(alpn_ossltest), in,
+\& in_len) == OPENSSL_NPN_NEGOTIATED)
+\& return SSL_TLSEXT_ERR_OK;
+\& return SSL_TLSEXT_ERR_ALERT_FATAL;
+\& }
+.Ve
+.PP
+That is all the setup that we need to do for the \fBSSL_CTX\fR. Next, we create a
+UDP socket and bind to it on localhost.
+.PP
+.Vb 5
+\& /* Retrieve the file descriptor for a new UDP socket */
+\& if ((fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
+\& fprintf(stderr, "cannot create socket");
+\& return \-1;
+\& }
+\&
+\& sa.sin_family = AF_INET;
+\& sa.sin_port = htons(port);
+\&
+\& /* Bind to the new UDP socket on localhost */
+\& if (bind(fd, (const struct sockaddr *)&sa, sizeof(sa)) < 0) {
+\& fprintf(stderr, "cannot bind to %u\en", port);
+\& BIO_closesocket(fd);
+\& return \-1;
+\& }
+\&
+\& /* Set port to nonblocking mode */
+\& if (BIO_socket_nbio(fd, 1) <= 0) {
+\& fprintf(stderr, "Unable to set port to nonblocking mode");
+\& BIO_closesocket(fd);
+\& return \-1;
+\& }
+.Ve
+.PP
+To run the QUIC server, we create an \fBSSL_LISTENER\fR to listen for incoming
+connections. We provide it with the bound UDP port to then explicitly begin
+listening for new connections.
+.PP
+.Vb 3
+\& /* Create a new QUIC listener */
+\& if ((listener = SSL_new_listener(ctx, 0)) == NULL)
+\& goto err;
+\&
+\& /* Provide the listener with our UDP socket. */
+\& if (!SSL_set_fd(listener, fd))
+\& goto err;
+\&
+\& /* Set the listener mode to nonblocking, which is inherited by
+\& * child objects.
+\& */
+\& if (!SSL_set_blocking_mode(listener, 0))
+\& goto err;
+\&
+\& /*
+\& * Begin listening. Note that is not usually needed as SSL_accept_connection
+\& * will implicitly start listening. It is only needed if a server wishes to
+\& * ensure it has started to accept incoming connections but does not wish to
+\& * actually call SSL_accept_connection yet.
+\& */
+\& if (!SSL_listen(listener))
+\& goto err;
+.Ve
+.SS "Server loop"
+.IX Subsection "Server loop"
+The server now enters a "forever" loop, handling one client connection at a
+time. Before each connection, we clear the OpenSSL error stack so that any
+error reports are related to just the new connection.
+.PP
+.Vb 2
+\& /* Pristine error stack for each new connection */
+\& ERR_clear_error();
+.Ve
+.PP
+We then wait until a connection is ready for reading.
+It uses the select function to wait until the socket is either readable
+or writable, depending on what the SSL connection requires.
+.PP
+We then accept a new connection in which the handshake will have already
+occurred. However, since we are in nonblocking mode, \fBSSL_accept_connection\fR\|(3)
+will return immediately. Therefore, we use a helper function to essentially
+block until a connection is established.
+.PP
+.Vb 5
+\& printf("Waiting for connection\en");
+\& while ((conn = SSL_accept_connection(listener, 0)) == NULL) {
+\& wait_for_activity(listener);
+\& }
+\& printf("Accepted new connection\en");
+.Ve
+.PP
+The helper function wait_for_activity uses \fBselect()\fR to block until the file
+descriptor belonging to the passed SSL object is readable. As mentioned earlier,
+a more real-world application would likely use this time to perform other tasks.
+.PP
+.Vb 3
+\& /* Initialize the fd_set structure */
+\& FD_ZERO(&read_fd);
+\& FD_ZERO(&write_fd);
+\&
+\& /*
+\& * Determine if we would like to write to the socket, read from it, or both.
+\& */
+\& if (SSL_net_write_desired(ssl))
+\& FD_SET(sock, &write_fd);
+\& if (SSL_net_read_desired(ssl))
+\& FD_SET(sock, &read_fd);
+\&
+\& /*
+\& * Find out when OpenSSL would next like to be called, regardless of
+\& * whether the state of the underlying socket has changed or not.
+\& */
+\& if (SSL_get_event_timeout(ssl, &tv, &isinfinite) && !isinfinite)
+\& tvp = &tv;
+\&
+\& /*
+\& * Wait until the socket is writeable or readable. We use select here
+\& * for the sake of simplicity and portability, but you could equally use
+\& * poll/epoll or similar functions
+\& *
+\& * NOTE: For the purposes of this demonstration code this effectively
+\& * makes this demo block until it has something more useful to do. In a
+\& * real application you probably want to go and do other work here (e.g.
+\& * update a GUI, or service other connections).
+\& *
+\& * Let\*(Aqs say for example that you want to update the progress counter on
+\& * a GUI every 100ms. One way to do that would be to use the timeout in
+\& * the last parameter to "select" below. If the tvp value is greater
+\& * than 100ms then use 100ms instead. Then, when select returns, you
+\& * check if it did so because of activity on the file descriptors or
+\& * because of the timeout. If the 100ms GUI timeout has expired but the
+\& * tvp timeout has not then go and update the GUI and then restart the
+\& * "select" (with updated timeouts).
+\& */
+\&
+\& select(sock + 1, &read_fd, &write_fd, NULL, tvp);
+.Ve
+.PP
+With the handshake complete, the server reads all the client input.
+.PP
+.Vb 10
+\& /* Read from client until the client sends a end of stream packet */
+\& while (!eof) {
+\& ret = SSL_read_ex(conn, buf + total_read, sizeof(buf) \- total_read,
+\& &nread);
+\& total_read += nread;
+\& if (total_read >= 8192) {
+\& fprintf(stderr, "Could not fit all data into buffer\en");
+\& goto err;
+\& }
+\& switch (handle_io_failure(conn, ret)) {
+\& case 1:
+\& continue; /* Retry */
+\& case 0:
+\& /* Reached end of stream */
+\& if (!SSL_has_pending(conn))
+\& eof = 1;
+\& break;
+\& default:
+\& fprintf(stderr, "Failed reading remaining data\en");
+\& goto err;
+\& }
+\& }
+.Ve
+.PP
+Finally, we echo the received data back to the client. We can use
+\&\fBSSL_write_ex2\fR\|(3) to pass in a special flag SSL_WRITE_FLAG_CONCLUDE that will
+send a FIN packet once the write has successfully finished writing all the data
+to the peer.
+.PP
+.Vb 9
+\& /* Echo client input */
+\& while (!SSL_write_ex2(conn, buf,
+\& total_read,
+\& SSL_WRITE_FLAG_CONCLUDE, &total_written)) {
+\& if (handle_io_failure(conn, 0) == 1)
+\& continue;
+\& fprintf(stderr, "Failed to write data\en");
+\& goto err;
+\& }
+.Ve
+.PP
+We then shut down the connection with \fBSSL_shutdown\fR\|(3), which may need
+to be called multiple times to ensure the connection is shutdown completely.
+.PP
+.Vb 8
+\& /*
+\& * Shut down the connection. We may need to call this multiple times
+\& * to ensure the connection is shutdown completely.
+\& */
+\& while ((ret = SSL_shutdown(conn)) != 1) {
+\& if (ret < 0 && handle_io_failure(conn, ret) == 1)
+\& continue; /* Retry */
+\& }
+.Ve
+.PP
+Finally, we free the SSL connection, and the server is now ready to accept the
+next client connection.
+.PP
+.Vb 1
+\& SSL_free(conn);
+.Ve
+.SS "Final clean up"
+.IX Subsection "Final clean up"
+If the server somehow manages to break out of the infinite loop and
+be ready to exit, it would deallocate the constructed \fBSSL\fR.
+.PP
+.Vb 1
+\& SSL_free(listener);
+.Ve
+.PP
+And in the main function, it would deallocate the constructed \fBSSL_CTX\fR.
+.PP
+.Vb 2
+\& SSL_CTX_free(ctx);
+\& BIO_closesocket(fd);
+.Ve
+.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\-quic\-introduction\fR\|(7),
+\&\fBossl\-guide\-quic\-client\-non\-block\fR\|(7), \fBossl\-guide\-quic\-client\-block\fR\|(7),
+\&\fBossl\-guide\-tls\-server\-block\fR\|(7), \fBossl\-guide\-quic\-server\-block\fR\|(7)
+.SH COPYRIGHT
+.IX Header "COPYRIGHT"
+Copyright 2024\-2025 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>.