xref: /freebsd/crypto/openssl/doc/man7/ossl-guide-tls-server-block.pod (revision e7be843b4a162e68651d3911f0357ed464915629)
1*e7be843bSPierre Pronchery=pod
2*e7be843bSPierre Pronchery
3*e7be843bSPierre Pronchery=begin comment
4*e7be843bSPierre Pronchery
5*e7be843bSPierre ProncheryNB: Changes to the source code samples in this file should also be reflected in
6*e7be843bSPierre Proncherydemos/guide/tls-server-block.c
7*e7be843bSPierre Pronchery
8*e7be843bSPierre Pronchery=end comment
9*e7be843bSPierre Pronchery
10*e7be843bSPierre Pronchery=head1 NAME
11*e7be843bSPierre Pronchery
12*e7be843bSPierre Proncheryossl-guide-tls-server-block
13*e7be843bSPierre Pronchery- OpenSSL Guide: Writing a simple blocking TLS server
14*e7be843bSPierre Pronchery
15*e7be843bSPierre Pronchery=head1 SIMPLE BLOCKING TLS SERVER EXAMPLE
16*e7be843bSPierre Pronchery
17*e7be843bSPierre ProncheryThis page will present various source code samples demonstrating how to write a
18*e7be843bSPierre Proncherysimple, non-concurrent, TLS "echo" server application which accepts one client
19*e7be843bSPierre Proncheryconnection at a time, echoing input from the client back to the same client.
20*e7be843bSPierre ProncheryOnce the current client disconnects, the next client connection is accepted.
21*e7be843bSPierre Pronchery
22*e7be843bSPierre ProncheryBoth the acceptor socket and client connections are "blocking".  A more typical
23*e7be843bSPierre Proncheryserver might use nonblocking sockets with an event loop and callbacks for I/O
24*e7be843bSPierre Proncheryevents.
25*e7be843bSPierre Pronchery
26*e7be843bSPierre ProncheryThe complete source code for this example blocking TLS server is available in
27*e7be843bSPierre Proncherythe B<demos/guide> directory of the OpenSSL source distribution in the file
28*e7be843bSPierre ProncheryB<tls-server-block.c>. It is also available online at
29*e7be843bSPierre ProncheryL<https://github.com/openssl/openssl/blob/master/demos/guide/tls-server-block.c>.
30*e7be843bSPierre Pronchery
31*e7be843bSPierre ProncheryWe assume that you already have OpenSSL installed on your system; that you
32*e7be843bSPierre Proncheryalready have some fundamental understanding of OpenSSL concepts and TLS (see
33*e7be843bSPierre ProncheryL<ossl-guide-libraries-introduction(7)> and L<ossl-guide-tls-introduction(7)>);
34*e7be843bSPierre Proncheryand that you know how to write and build C code and link it against the
35*e7be843bSPierre Proncherylibcrypto and libssl libraries that are provided by OpenSSL. It also assumes
36*e7be843bSPierre Proncherythat you have a basic understanding of TCP/IP and sockets.
37*e7be843bSPierre Pronchery
38*e7be843bSPierre Pronchery=head2 Creating the SSL_CTX and SSL objects
39*e7be843bSPierre Pronchery
40*e7be843bSPierre ProncheryThe first step is to create an B<SSL_CTX> object for our server. We use the
41*e7be843bSPierre ProncheryL<SSL_CTX_new(3)> function for this purpose. We could alternatively use
42*e7be843bSPierre ProncheryL<SSL_CTX_new_ex(3)> if we want to associate the B<SSL_CTX> with a particular
43*e7be843bSPierre ProncheryB<OSSL_LIB_CTX> (see L<ossl-guide-libraries-introduction(7)> to learn about
44*e7be843bSPierre ProncheryB<OSSL_LIB_CTX>). We pass as an argument the return value of the function
45*e7be843bSPierre ProncheryL<TLS_server_method(3)>. You should use this method whenever you are writing a
46*e7be843bSPierre ProncheryTLS server. This method will automatically use TLS version negotiation to select
47*e7be843bSPierre Proncherythe highest version of the protocol that is mutually supported by both the
48*e7be843bSPierre Proncheryserver and the client.
49*e7be843bSPierre Pronchery
50*e7be843bSPierre Pronchery    /*
51*e7be843bSPierre Pronchery     * An SSL_CTX holds shared configuration information for multiple
52*e7be843bSPierre Pronchery     * subsequent per-client SSL connections.
53*e7be843bSPierre Pronchery     */
54*e7be843bSPierre Pronchery    ctx = SSL_CTX_new(TLS_server_method());
55*e7be843bSPierre Pronchery    if (ctx == NULL) {
56*e7be843bSPierre Pronchery        ERR_print_errors_fp(stderr);
57*e7be843bSPierre Pronchery        errx(res, "Failed to create server SSL_CTX");
58*e7be843bSPierre Pronchery    }
59*e7be843bSPierre Pronchery
60*e7be843bSPierre ProncheryWe would also like to restrict the TLS versions that we are willing to accept to
61*e7be843bSPierre ProncheryTLSv1.2 or above. TLS protocol versions earlier than that are generally to be
62*e7be843bSPierre Proncheryavoided where possible. We can do that using
63*e7be843bSPierre ProncheryL<SSL_CTX_set_min_proto_version(3)>:
64*e7be843bSPierre Pronchery
65*e7be843bSPierre Pronchery    /*
66*e7be843bSPierre Pronchery     * TLS versions older than TLS 1.2 are deprecated by IETF and SHOULD
67*e7be843bSPierre Pronchery     * be avoided if possible.
68*e7be843bSPierre Pronchery     */
69*e7be843bSPierre Pronchery    if (!SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION)) {
70*e7be843bSPierre Pronchery        SSL_CTX_free(ctx);
71*e7be843bSPierre Pronchery        ERR_print_errors_fp(stderr);
72*e7be843bSPierre Pronchery        errx(res, "Failed to set the minimum TLS protocol version");
73*e7be843bSPierre Pronchery    }
74*e7be843bSPierre Pronchery
75*e7be843bSPierre ProncheryNext we configure some option flags, see L<SSL_CTX_set_options(3)> for details:
76*e7be843bSPierre Pronchery
77*e7be843bSPierre Pronchery    /*
78*e7be843bSPierre Pronchery     * Tolerate clients hanging up without a TLS "shutdown".  Appropriate in all
79*e7be843bSPierre Pronchery     * application protocols which perform their own message "framing", and
80*e7be843bSPierre Pronchery     * don't rely on TLS to defend against "truncation" attacks.
81*e7be843bSPierre Pronchery     */
82*e7be843bSPierre Pronchery    opts = SSL_OP_IGNORE_UNEXPECTED_EOF;
83*e7be843bSPierre Pronchery
84*e7be843bSPierre Pronchery    /*
85*e7be843bSPierre Pronchery     * Block potential CPU-exhaustion attacks by clients that request frequent
86*e7be843bSPierre Pronchery     * renegotiation.  This is of course only effective if there are existing
87*e7be843bSPierre Pronchery     * limits on initial full TLS handshake or connection rates.
88*e7be843bSPierre Pronchery     */
89*e7be843bSPierre Pronchery    opts |= SSL_OP_NO_RENEGOTIATION;
90*e7be843bSPierre Pronchery
91*e7be843bSPierre Pronchery    /*
92*e7be843bSPierre Pronchery     * Most servers elect to use their own cipher preference rather than that of
93*e7be843bSPierre Pronchery     * the client.
94*e7be843bSPierre Pronchery     */
95*e7be843bSPierre Pronchery    opts |= SSL_OP_CIPHER_SERVER_PREFERENCE;
96*e7be843bSPierre Pronchery
97*e7be843bSPierre Pronchery    /* Apply the selection options */
98*e7be843bSPierre Pronchery    SSL_CTX_set_options(ctx, opts);
99*e7be843bSPierre Pronchery
100*e7be843bSPierre ProncheryServers need a private key and certificate.  Though anonymous ciphers (no
101*e7be843bSPierre Proncheryserver certificate) are possible in TLS 1.2, they are rarely applicable, and
102*e7be843bSPierre Proncheryare not currently defined for TLS 1.3.  Additional intermediate issuer CA
103*e7be843bSPierre Proncherycertificates are often also required, and both the server (end-entity or EE)
104*e7be843bSPierre Proncherycertificate and the issuer ("chain") certificates are most easily configured in
105*e7be843bSPierre Proncherya single "chain file".  Below we load such a chain file (the EE certificate
106*e7be843bSPierre Proncherymust appear first), and then load the corresponding private key, checking that
107*e7be843bSPierre Proncheryit matches the server certificate.  No checks are performed to check the
108*e7be843bSPierre Proncheryintegrity of the chain (CA signatures or certificate expiration dates, for
109*e7be843bSPierre Proncheryexample).
110*e7be843bSPierre Pronchery
111*e7be843bSPierre Pronchery    /*
112*e7be843bSPierre Pronchery     * Load the server's certificate *chain* file (PEM format), which includes
113*e7be843bSPierre Pronchery     * not only the leaf (end-entity) server certificate, but also any
114*e7be843bSPierre Pronchery     * intermediate issuer-CA certificates.  The leaf certificate must be the
115*e7be843bSPierre Pronchery     * first certificate in the file.
116*e7be843bSPierre Pronchery     *
117*e7be843bSPierre Pronchery     * In advanced use-cases this can be called multiple times, once per public
118*e7be843bSPierre Pronchery     * key algorithm for which the server has a corresponding certificate.
119*e7be843bSPierre Pronchery     * However, the corresponding private key (see below) must be loaded first,
120*e7be843bSPierre Pronchery     * *before* moving on to the next chain file.
121*e7be843bSPierre Pronchery     */
122*e7be843bSPierre Pronchery    if (SSL_CTX_use_certificate_chain_file(ctx, "chain.pem") <= 0) {
123*e7be843bSPierre Pronchery        SSL_CTX_free(ctx);
124*e7be843bSPierre Pronchery        ERR_print_errors_fp(stderr);
125*e7be843bSPierre Pronchery        errx(res, "Failed to load the server certificate chain file");
126*e7be843bSPierre Pronchery    }
127*e7be843bSPierre Pronchery
128*e7be843bSPierre Pronchery    /*
129*e7be843bSPierre Pronchery     * Load the corresponding private key, this also checks that the private
130*e7be843bSPierre Pronchery     * key matches the just loaded end-entity certificate.  It does not check
131*e7be843bSPierre Pronchery     * whether the certificate chain is valid, the certificates could be
132*e7be843bSPierre Pronchery     * expired, or may otherwise fail to form a chain that a client can validate.
133*e7be843bSPierre Pronchery     */
134*e7be843bSPierre Pronchery    if (SSL_CTX_use_PrivateKey_file(ctx, "pkey.pem", SSL_FILETYPE_PEM) <= 0) {
135*e7be843bSPierre Pronchery        SSL_CTX_free(ctx);
136*e7be843bSPierre Pronchery        ERR_print_errors_fp(stderr);
137*e7be843bSPierre Pronchery        errx(res, "Error loading the server private key file, "
138*e7be843bSPierre Pronchery                  "possible key/cert mismatch???");
139*e7be843bSPierre Pronchery    }
140*e7be843bSPierre Pronchery
141*e7be843bSPierre ProncheryNext we enable session caching, which makes it possible for clients to more
142*e7be843bSPierre Proncheryefficiently make additional TLS connections after completing an initial full
143*e7be843bSPierre ProncheryTLS handshake.  With TLS 1.3, session resumption typically still performs a fresh
144*e7be843bSPierre Proncherykey agreement, but the certificate exchange is avoided.
145*e7be843bSPierre Pronchery
146*e7be843bSPierre Pronchery    /*
147*e7be843bSPierre Pronchery     * Servers that want to enable session resumption must specify a cache id
148*e7be843bSPierre Pronchery     * byte array, that identifies the server application, and reduces the
149*e7be843bSPierre Pronchery     * chance of inappropriate cache sharing.
150*e7be843bSPierre Pronchery     */
151*e7be843bSPierre Pronchery    SSL_CTX_set_session_id_context(ctx, (void *)cache_id, sizeof(cache_id));
152*e7be843bSPierre Pronchery    SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_SERVER);
153*e7be843bSPierre Pronchery
154*e7be843bSPierre Pronchery    /*
155*e7be843bSPierre Pronchery     * How many client TLS sessions to cache.  The default is
156*e7be843bSPierre Pronchery     * SSL_SESSION_CACHE_MAX_SIZE_DEFAULT (20k in recent OpenSSL versions),
157*e7be843bSPierre Pronchery     * which may be too small or too large.
158*e7be843bSPierre Pronchery     */
159*e7be843bSPierre Pronchery    SSL_CTX_sess_set_cache_size(ctx, 1024);
160*e7be843bSPierre Pronchery
161*e7be843bSPierre Pronchery    /*
162*e7be843bSPierre Pronchery     * Sessions older than this are considered a cache miss even if still in
163*e7be843bSPierre Pronchery     * the cache.  The default is two hours.  Busy servers whose clients make
164*e7be843bSPierre Pronchery     * many connections in a short burst may want a shorter timeout, on lightly
165*e7be843bSPierre Pronchery     * loaded servers with sporadic connections from any given client, a longer
166*e7be843bSPierre Pronchery     * time may be appropriate.
167*e7be843bSPierre Pronchery     */
168*e7be843bSPierre Pronchery    SSL_CTX_set_timeout(ctx, 3600);
169*e7be843bSPierre Pronchery
170*e7be843bSPierre ProncheryMost servers, including this one, do not solicit client certificates.  We
171*e7be843bSPierre Proncherytherefore do not need a "trust store" and allow the handshake to complete even
172*e7be843bSPierre Proncherywhen the client does not present a certificate.  Note: Even if a client did
173*e7be843bSPierre Proncherypresent a trusted ceritificate, for it to be useful, the server application
174*e7be843bSPierre Proncherywould still need custom code to use the verified identity to grant nondefault
175*e7be843bSPierre Proncheryaccess to that particular client.  Some servers grant access to all clients
176*e7be843bSPierre Proncherywith certificates from a private CA, this then requires processing of
177*e7be843bSPierre Proncherycertificate revocation lists to deauthorise a client.  It is often simpler and
178*e7be843bSPierre Proncherymore secure to instead keep a list of authorised public keys.
179*e7be843bSPierre Pronchery
180*e7be843bSPierre ProncheryThough this is the default setting, we explicitly call the
181*e7be843bSPierre ProncheryL<SSL_CTX_set_verify(3)> function and pass the B<SSL_VERIFY_NONE> value to it.
182*e7be843bSPierre ProncheryThe final argument to this function is a callback that you can optionally
183*e7be843bSPierre Proncherysupply to override the default handling for certificate verification. Most
184*e7be843bSPierre Proncheryapplications do not need to do this so this can safely be set to NULL to get
185*e7be843bSPierre Proncherythe default handling.
186*e7be843bSPierre Pronchery
187*e7be843bSPierre Pronchery    /*
188*e7be843bSPierre Pronchery     * Clients rarely employ certificate-based authentication, and so we don't
189*e7be843bSPierre Pronchery     * require "mutual" TLS authentication (indeed there's no way to know
190*e7be843bSPierre Pronchery     * whether or how the client authenticated the server, so the term "mutual"
191*e7be843bSPierre Pronchery     * is potentially misleading).
192*e7be843bSPierre Pronchery     *
193*e7be843bSPierre Pronchery     * Since we're not soliciting or processing client certificates, we don't
194*e7be843bSPierre Pronchery     * need to configure a trusted-certificate store, so no call to
195*e7be843bSPierre Pronchery     * SSL_CTX_set_default_verify_paths() is needed.  The server's own
196*e7be843bSPierre Pronchery     * certificate chain is assumed valid.
197*e7be843bSPierre Pronchery     */
198*e7be843bSPierre Pronchery    SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL);
199*e7be843bSPierre Pronchery
200*e7be843bSPierre ProncheryThat is all the setup that we need to do for the B<SSL_CTX>.  Next we create an
201*e7be843bSPierre Proncheryacceptor BIO on which to accept client connections.  This just records the
202*e7be843bSPierre Proncheryintended port (and optional "host:" prefix), without actually creating the
203*e7be843bSPierre Proncherysocket.  This delayed processing allows the programmer to specify additional
204*e7be843bSPierre Proncherybehaviours before the listening socket is actually created.
205*e7be843bSPierre Pronchery
206*e7be843bSPierre Pronchery    /*
207*e7be843bSPierre Pronchery     * Create a listener socket wrapped in a BIO.
208*e7be843bSPierre Pronchery     * The first call to BIO_do_accept() initialises the socket
209*e7be843bSPierre Pronchery     */
210*e7be843bSPierre Pronchery    acceptor_bio = BIO_new_accept(hostport);
211*e7be843bSPierre Pronchery    if (acceptor_bio == NULL) {
212*e7be843bSPierre Pronchery        SSL_CTX_free(ctx);
213*e7be843bSPierre Pronchery        ERR_print_errors_fp(stderr);
214*e7be843bSPierre Pronchery        errx(res, "Error creating acceptor bio");
215*e7be843bSPierre Pronchery    }
216*e7be843bSPierre Pronchery
217*e7be843bSPierre ProncheryServers almost always want to use the "SO_REUSEADDR" option to avoid startup
218*e7be843bSPierre Proncheryfailures if there are still lingering client connections, so we do that before
219*e7be843bSPierre Proncherymaking the B<first> call to L<BIO_do_accept(3)> which creates the listening
220*e7be843bSPierre Proncherysocket, without accepting a client connection.  Subsequent calls to the same
221*e7be843bSPierre Proncheryfunction will accept new connections.
222*e7be843bSPierre Pronchery
223*e7be843bSPierre Pronchery    BIO_set_bind_mode(acceptor_bio, BIO_BIND_REUSEADDR);
224*e7be843bSPierre Pronchery    if (BIO_do_accept(acceptor_bio) <= 0) {
225*e7be843bSPierre Pronchery        SSL_CTX_free(ctx);
226*e7be843bSPierre Pronchery        ERR_print_errors_fp(stderr);
227*e7be843bSPierre Pronchery        errx(res, "Error setting up acceptor socket");
228*e7be843bSPierre Pronchery    }
229*e7be843bSPierre Pronchery
230*e7be843bSPierre Pronchery=head2 Server loop
231*e7be843bSPierre Pronchery
232*e7be843bSPierre ProncheryThe server now enters a "forever" loop handling one client connection at a
233*e7be843bSPierre Proncherytime.  Before each connection we clear the OpenSSL error stack, so that any
234*e7be843bSPierre Proncheryerror reports are related to just the new connection.
235*e7be843bSPierre Pronchery
236*e7be843bSPierre Pronchery    /* Pristine error stack for each new connection */
237*e7be843bSPierre Pronchery    ERR_clear_error();
238*e7be843bSPierre Pronchery
239*e7be843bSPierre ProncheryAt this point the server blocks to accept the next client:
240*e7be843bSPierre Pronchery
241*e7be843bSPierre Pronchery    /* Wait for the next client to connect */
242*e7be843bSPierre Pronchery    if (BIO_do_accept(acceptor_bio) <= 0) {
243*e7be843bSPierre Pronchery        /* Client went away before we accepted the connection */
244*e7be843bSPierre Pronchery        continue;
245*e7be843bSPierre Pronchery    }
246*e7be843bSPierre Pronchery
247*e7be843bSPierre ProncheryOn success the accepted client connection has been wrapped in a fresh BIO and
248*e7be843bSPierre Proncherypushed onto the end of the acceptor BIO chain.  We pop it off returning the
249*e7be843bSPierre Proncheryacceptor BIO to its initial state.
250*e7be843bSPierre Pronchery
251*e7be843bSPierre Pronchery    /* Pop the client connection from the BIO chain */
252*e7be843bSPierre Pronchery    client_bio = BIO_pop(acceptor_bio);
253*e7be843bSPierre Pronchery    fprintf(stderr, "New client connection accepted\n");
254*e7be843bSPierre Pronchery
255*e7be843bSPierre ProncheryNext, we create an B<SSL> object by calling the B<SSL_new(3)> function and
256*e7be843bSPierre Proncherypassing the B<SSL_CTX> we created as an argument.  The client connection BIO is
257*e7be843bSPierre Proncheryconfigured as the I/O conduit for this SSL handle.  SSL_set_bio transfers
258*e7be843bSPierre Proncheryownership of the BIO or BIOs involved (our B<client_bio>) to the SSL handle.
259*e7be843bSPierre Pronchery
260*e7be843bSPierre Pronchery    /* Associate a new SSL handle with the new connection */
261*e7be843bSPierre Pronchery    if ((ssl = SSL_new(ctx)) == NULL) {
262*e7be843bSPierre Pronchery        ERR_print_errors_fp(stderr);
263*e7be843bSPierre Pronchery        warnx("Error creating SSL handle for new connection");
264*e7be843bSPierre Pronchery        BIO_free(client_bio);
265*e7be843bSPierre Pronchery        continue;
266*e7be843bSPierre Pronchery    }
267*e7be843bSPierre Pronchery    SSL_set_bio(ssl, client_bio, client_bio);
268*e7be843bSPierre Pronchery
269*e7be843bSPierre ProncheryAnd now we're ready to attempt the SSL handshake.  With a blocking socket
270*e7be843bSPierre ProncheryOpenSSL will perform all the read and write operations required to complete the
271*e7be843bSPierre Proncheryhandshake (or detect and report a failure) before returning.
272*e7be843bSPierre Pronchery
273*e7be843bSPierre Pronchery    /* Attempt an SSL handshake with the client */
274*e7be843bSPierre Pronchery    if (SSL_accept(ssl) <= 0) {
275*e7be843bSPierre Pronchery        ERR_print_errors_fp(stderr);
276*e7be843bSPierre Pronchery        warnx("Error performing SSL handshake with client");
277*e7be843bSPierre Pronchery        SSL_free(ssl);
278*e7be843bSPierre Pronchery        continue;
279*e7be843bSPierre Pronchery    }
280*e7be843bSPierre Pronchery
281*e7be843bSPierre ProncheryWith the handshake complete, the server loops echoing client input back to the
282*e7be843bSPierre Proncheryclient:
283*e7be843bSPierre Pronchery
284*e7be843bSPierre Pronchery    while (SSL_read_ex(ssl, buf, sizeof(buf), &nread) > 0) {
285*e7be843bSPierre Pronchery        if (SSL_write_ex(ssl, buf, nread, &nwritten) > 0 &&
286*e7be843bSPierre Pronchery            nwritten == nread) {
287*e7be843bSPierre Pronchery            total += nwritten;
288*e7be843bSPierre Pronchery            continue;
289*e7be843bSPierre Pronchery        }
290*e7be843bSPierre Pronchery        warnx("Error echoing client input");
291*e7be843bSPierre Pronchery        break;
292*e7be843bSPierre Pronchery    }
293*e7be843bSPierre Pronchery
294*e7be843bSPierre ProncheryOnce the client closes its connection, we report the number of bytes sent to
295*e7be843bSPierre ProncheryB<stderr> and free the SSL handle, which also frees the B<client_bio> and
296*e7be843bSPierre Proncherycloses the underlying socket.
297*e7be843bSPierre Pronchery
298*e7be843bSPierre Pronchery    fprintf(stderr, "Client connection closed, %zu bytes sent\n", total);
299*e7be843bSPierre Pronchery    SSL_free(ssl);
300*e7be843bSPierre Pronchery
301*e7be843bSPierre ProncheryThe server is now ready to accept the next client connection.
302*e7be843bSPierre Pronchery
303*e7be843bSPierre Pronchery=head2 Final clean up
304*e7be843bSPierre Pronchery
305*e7be843bSPierre ProncheryIf the server could somehow manage to break out of the infinite loop, and
306*e7be843bSPierre Proncherybe ready to exit, it would first deallocate the constructed B<SSL_CTX>.
307*e7be843bSPierre Pronchery
308*e7be843bSPierre Pronchery    /*
309*e7be843bSPierre Pronchery     * Unreachable placeholder cleanup code, the above loop runs forever.
310*e7be843bSPierre Pronchery     */
311*e7be843bSPierre Pronchery    SSL_CTX_free(ctx);
312*e7be843bSPierre Pronchery    return EXIT_SUCCESS;
313*e7be843bSPierre Pronchery
314*e7be843bSPierre Pronchery=head1 SEE ALSO
315*e7be843bSPierre Pronchery
316*e7be843bSPierre ProncheryL<ossl-guide-introduction(7)>, L<ossl-guide-libraries-introduction(7)>,
317*e7be843bSPierre ProncheryL<ossl-guide-libssl-introduction(7)>, L<ossl-guide-tls-introduction(7)>,
318*e7be843bSPierre ProncheryL<ossl-guide-tls-client-non-block(7)>, L<ossl-guide-quic-client-block(7)>
319*e7be843bSPierre Pronchery
320*e7be843bSPierre Pronchery=head1 COPYRIGHT
321*e7be843bSPierre Pronchery
322*e7be843bSPierre ProncheryCopyright 2024 The OpenSSL Project Authors. All Rights Reserved.
323*e7be843bSPierre Pronchery
324*e7be843bSPierre ProncheryLicensed under the Apache License 2.0 (the "License").  You may not use
325*e7be843bSPierre Proncherythis file except in compliance with the License.  You can obtain a copy
326*e7be843bSPierre Proncheryin the file LICENSE in the source distribution or at
327*e7be843bSPierre ProncheryL<https://www.openssl.org/source/license.html>.
328*e7be843bSPierre Pronchery
329*e7be843bSPierre Pronchery=cut
330