| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405 |
- .\" -*- mode: troff; coding: utf-8 -*-
- .\" Automatically generated by Pod::Man 5.01 (Pod::Simple 3.43)
- .\"
- .\" 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-01-17 3.4.0 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>.
|