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