diff options
Diffstat (limited to 'secure/lib/libcrypto/man/man7/ossl-guide-tls-server-block.7')
-rw-r--r-- | secure/lib/libcrypto/man/man7/ossl-guide-tls-server-block.7 | 405 |
1 files changed, 405 insertions, 0 deletions
diff --git a/secure/lib/libcrypto/man/man7/ossl-guide-tls-server-block.7 b/secure/lib/libcrypto/man/man7/ossl-guide-tls-server-block.7 new file mode 100644 index 000000000000..bcb0631a798d --- /dev/null +++ b/secure/lib/libcrypto/man/man7/ossl-guide-tls-server-block.7 @@ -0,0 +1,405 @@ +.\" -*- 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-TLS-SERVER-BLOCK 7ossl" +.TH OSSL-GUIDE-TLS-SERVER-BLOCK 7ossl 2025-07-01 3.5.1 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\-tls\-server\-block +\&\- OpenSSL Guide: Writing a simple blocking TLS server +.SH "SIMPLE BLOCKING TLS SERVER EXAMPLE" +.IX Header "SIMPLE BLOCKING TLS SERVER EXAMPLE" +This page will present various source code samples demonstrating how to write a +simple, non-concurrent, TLS "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 +Both the acceptor socket and client connections are "blocking". A more typical +server might use nonblocking sockets with an event loop and callbacks for I/O +events. +.PP +The complete source code for this example blocking TLS server is available in +the \fBdemos/guide\fR directory of the OpenSSL source distribution in the file +\&\fBtls\-server\-block.c\fR. It is also available online at +<https://github.com/openssl/openssl/blob/master/demos/guide/tls\-server\-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 TLS (see +\&\fBossl\-guide\-libraries\-introduction\fR\|(7) and \fBossl\-guide\-tls\-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 TCP/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 could alternatively use +\&\fBSSL_CTX_new_ex\fR\|(3) if we want to associate the \fBSSL_CTX\fR with a particular +\&\fBOSSL_LIB_CTX\fR (see \fBossl\-guide\-libraries\-introduction\fR\|(7) to learn about +\&\fBOSSL_LIB_CTX\fR). We pass as an argument the return value of the function +\&\fBTLS_server_method\fR\|(3). You should use this method whenever you are writing a +TLS server. This method will automatically use TLS version negotiation to select +the highest version of the protocol that is mutually supported by both the +server and the client. +.PP +.Vb 9 +\& /* +\& * An SSL_CTX holds shared configuration information for multiple +\& * subsequent per\-client SSL connections. +\& */ +\& ctx = SSL_CTX_new(TLS_server_method()); +\& if (ctx == NULL) { +\& ERR_print_errors_fp(stderr); +\& errx(res, "Failed to create server SSL_CTX"); +\& } +.Ve +.PP +We would also like to restrict the TLS versions that we are willing to accept to +TLSv1.2 or above. TLS protocol versions earlier than that are generally to be +avoided where possible. We can do that using +\&\fBSSL_CTX_set_min_proto_version\fR\|(3): +.PP +.Vb 9 +\& /* +\& * TLS versions older than TLS 1.2 are deprecated by IETF and SHOULD +\& * be avoided if possible. +\& */ +\& if (!SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION)) { +\& SSL_CTX_free(ctx); +\& ERR_print_errors_fp(stderr); +\& errx(res, "Failed to set the minimum TLS protocol version"); +\& } +.Ve +.PP +Next we configure some option flags, see \fBSSL_CTX_set_options\fR\|(3) for details: +.PP +.Vb 6 +\& /* +\& * Tolerate clients hanging up without a TLS "shutdown". Appropriate in all +\& * application protocols which perform their own message "framing", and +\& * don\*(Aqt rely on TLS to defend against "truncation" attacks. +\& */ +\& opts = SSL_OP_IGNORE_UNEXPECTED_EOF; +\& +\& /* +\& * Block potential CPU\-exhaustion attacks by clients that request frequent +\& * renegotiation. This is of course only effective if there are existing +\& * limits on initial full TLS handshake or connection rates. +\& */ +\& opts |= SSL_OP_NO_RENEGOTIATION; +\& +\& /* +\& * Most servers elect to use their own cipher preference rather than that of +\& * the client. +\& */ +\& opts |= SSL_OP_CIPHER_SERVER_PREFERENCE; +\& +\& /* Apply the selection options */ +\& SSL_CTX_set_options(ctx, opts); +.Ve +.PP +Servers need a private key and certificate. Though anonymous ciphers (no +server certificate) are possible in TLS 1.2, they are rarely applicable, and +are not currently defined for TLS 1.3. Additional intermediate issuer CA +certificates are often also 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). +.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, "chain.pem") <= 0) { +\& SSL_CTX_free(ctx); +\& ERR_print_errors_fp(stderr); +\& errx(res, "Failed to load the server certificate chain file"); +\& } +\& +\& /* +\& * 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, "pkey.pem", SSL_FILETYPE_PEM) <= 0) { +\& SSL_CTX_free(ctx); +\& ERR_print_errors_fp(stderr); +\& errx(res, "Error loading the server private key file, " +\& "possible key/cert mismatch???"); +\& } +.Ve +.PP +Next we enable session caching, which makes it possible for clients to more +efficiently make additional TLS connections after completing an initial full +TLS handshake. With TLS 1.3, session resumption typically still performs a fresh +key agreement, but the certificate exchange is avoided. +.PP +.Vb 7 +\& /* +\& * Servers that want to enable session resumption must specify a cache id +\& * byte array, that identifies the server application, and reduces the +\& * chance of inappropriate cache sharing. +\& */ +\& SSL_CTX_set_session_id_context(ctx, (void *)cache_id, sizeof(cache_id)); +\& SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_SERVER); +\& +\& /* +\& * How many client TLS sessions to cache. The default is +\& * SSL_SESSION_CACHE_MAX_SIZE_DEFAULT (20k in recent OpenSSL versions), +\& * which may be too small or too large. +\& */ +\& SSL_CTX_sess_set_cache_size(ctx, 1024); +\& +\& /* +\& * Sessions older than this are considered a cache miss even if still in +\& * the cache. The default is two hours. Busy servers whose clients make +\& * many connections in a short burst may want a shorter timeout, on lightly +\& * loaded servers with sporadic connections from any given client, a longer +\& * time may be appropriate. +\& */ +\& SSL_CTX_set_timeout(ctx, 3600); +.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 ceritificate, 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 +That is all the setup that we need to do for the \fBSSL_CTX\fR. Next we create an +acceptor BIO on which to accept client connections. This just records the +intended port (and optional "host:" prefix), without actually creating the +socket. This delayed processing allows the programmer to specify additional +behaviours before the listening socket is actually created. +.PP +.Vb 10 +\& /* +\& * Create a listener socket wrapped in a BIO. +\& * The first call to BIO_do_accept() initialises the socket +\& */ +\& acceptor_bio = BIO_new_accept(hostport); +\& if (acceptor_bio == NULL) { +\& SSL_CTX_free(ctx); +\& ERR_print_errors_fp(stderr); +\& errx(res, "Error creating acceptor bio"); +\& } +.Ve +.PP +Servers almost always want to use the "SO_REUSEADDR" option to avoid startup +failures if there are still lingering client connections, so we do that before +making the \fBfirst\fR call to \fBBIO_do_accept\fR\|(3) which creates the listening +socket, without accepting a client connection. Subsequent calls to the same +function will accept new connections. +.PP +.Vb 6 +\& BIO_set_bind_mode(acceptor_bio, BIO_BIND_REUSEADDR); +\& if (BIO_do_accept(acceptor_bio) <= 0) { +\& SSL_CTX_free(ctx); +\& ERR_print_errors_fp(stderr); +\& errx(res, "Error setting up acceptor socket"); +\& } +.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 +At this point the server blocks to accept the next client: +.PP +.Vb 5 +\& /* Wait for the next client to connect */ +\& if (BIO_do_accept(acceptor_bio) <= 0) { +\& /* Client went away before we accepted the connection */ +\& continue; +\& } +.Ve +.PP +On success the accepted client connection has been wrapped in a fresh BIO and +pushed onto the end of the acceptor BIO chain. We pop it off returning the +acceptor BIO to its initial state. +.PP +.Vb 3 +\& /* Pop the client connection from the BIO chain */ +\& client_bio = BIO_pop(acceptor_bio); +\& fprintf(stderr, "New client connection accepted\en"); +.Ve +.PP +Next, we create an \fBSSL\fR object by calling the \fBSSL_new\|(3)\fR function and +passing the \fBSSL_CTX\fR we created as an argument. The client connection BIO is +configured as the I/O conduit for this SSL handle. SSL_set_bio transfers +ownership of the BIO or BIOs involved (our \fBclient_bio\fR) to the SSL handle. +.PP +.Vb 8 +\& /* Associate a new SSL handle with the new connection */ +\& if ((ssl = SSL_new(ctx)) == NULL) { +\& ERR_print_errors_fp(stderr); +\& warnx("Error creating SSL handle for new connection"); +\& BIO_free(client_bio); +\& continue; +\& } +\& SSL_set_bio(ssl, client_bio, client_bio); +.Ve +.PP +And now we're ready to attempt the SSL handshake. With a blocking socket +OpenSSL will perform all the read and write operations required to complete the +handshake (or detect and report a failure) before returning. +.PP +.Vb 7 +\& /* Attempt an SSL handshake with the client */ +\& if (SSL_accept(ssl) <= 0) { +\& ERR_print_errors_fp(stderr); +\& warnx("Error performing SSL handshake with client"); +\& SSL_free(ssl); +\& continue; +\& } +.Ve +.PP +With the handshake complete, the server loops echoing client input back to the +client: +.PP +.Vb 9 +\& while (SSL_read_ex(ssl, buf, sizeof(buf), &nread) > 0) { +\& if (SSL_write_ex(ssl, buf, nread, &nwritten) > 0 && +\& nwritten == nread) { +\& total += nwritten; +\& continue; +\& } +\& warnx("Error echoing client input"); +\& break; +\& } +.Ve +.PP +Once the client closes its connection, we report the number of bytes sent to +\&\fBstderr\fR and free the SSL handle, which also frees the \fBclient_bio\fR and +closes the underlying socket. +.PP +.Vb 2 +\& fprintf(stderr, "Client connection closed, %zu bytes sent\en", total); +\& SSL_free(ssl); +.Ve +.PP +The server is now ready to accept the next client connection. +.SS "Final clean up" +.IX Subsection "Final clean up" +If the server could somehow manage to break out of the infinite loop, and +be ready to exit, it would first deallocate the constructed \fBSSL_CTX\fR. +.PP +.Vb 5 +\& /* +\& * Unreachable placeholder cleanup code, the above loop runs forever. +\& */ +\& SSL_CTX_free(ctx); +\& return EXIT_SUCCESS; +.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\-tls\-introduction\fR\|(7), +\&\fBossl\-guide\-tls\-client\-non\-block\fR\|(7), \fBossl\-guide\-quic\-client\-block\fR\|(7) +.SH COPYRIGHT +.IX Header "COPYRIGHT" +Copyright 2024 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>. |