1 | /*
|
---|
2 | * Copyright 2024 The OpenSSL Project Authors. All Rights Reserved.
|
---|
3 | *
|
---|
4 | * Licensed under the Apache License 2.0 (the "License"). You may not use
|
---|
5 | * this file except in compliance with the License. You can obtain a copy
|
---|
6 | * in the file LICENSE in the source distribution or at
|
---|
7 | * https://www.openssl.org/source/license.html
|
---|
8 | */
|
---|
9 |
|
---|
10 | /*
|
---|
11 | * NB: Changes to this file should also be reflected in
|
---|
12 | * doc/man7/ossl-guide-tls-server-block.pod
|
---|
13 | */
|
---|
14 |
|
---|
15 | #include <string.h>
|
---|
16 |
|
---|
17 | /* Include the appropriate header file for SOCK_STREAM */
|
---|
18 | #ifdef _WIN32 /* Windows */
|
---|
19 | # include <stdarg.h>
|
---|
20 | # include <winsock2.h>
|
---|
21 | #else /* Linux/Unix */
|
---|
22 | # include <err.h>
|
---|
23 | # include <sys/socket.h>
|
---|
24 | # include <sys/select.h>
|
---|
25 | #endif
|
---|
26 |
|
---|
27 | #include <openssl/bio.h>
|
---|
28 | #include <openssl/ssl.h>
|
---|
29 | #include <openssl/err.h>
|
---|
30 |
|
---|
31 | static const char cache_id[] = "OpenSSL Demo Server";
|
---|
32 |
|
---|
33 | #ifdef _WIN32
|
---|
34 | static const char *progname;
|
---|
35 |
|
---|
36 | static void vwarnx(const char *fmt, va_list ap)
|
---|
37 | {
|
---|
38 | if (progname != NULL)
|
---|
39 | fprintf(stderr, "%s: ", progname);
|
---|
40 | vfprintf(stderr, fmt, ap);
|
---|
41 | putc('\n', stderr);
|
---|
42 | }
|
---|
43 |
|
---|
44 | static void errx(int status, const char *fmt, ...)
|
---|
45 | {
|
---|
46 | va_list ap;
|
---|
47 | va_start(ap, fmt);
|
---|
48 | vwarnx(fmt, ap);
|
---|
49 | va_end(ap);
|
---|
50 | exit(status);
|
---|
51 | }
|
---|
52 |
|
---|
53 | static void warnx(const char *fmt, ...)
|
---|
54 | {
|
---|
55 | va_list ap;
|
---|
56 | va_start(ap, fmt);
|
---|
57 | vwarnx(fmt, ap);
|
---|
58 | va_end(ap);
|
---|
59 | }
|
---|
60 | #endif
|
---|
61 |
|
---|
62 | /* Minimal TLS echo server. */
|
---|
63 | int main(int argc, char *argv[])
|
---|
64 | {
|
---|
65 | int res = EXIT_FAILURE;
|
---|
66 | long opts;
|
---|
67 | const char *hostport;
|
---|
68 | SSL_CTX *ctx = NULL;
|
---|
69 | BIO *acceptor_bio;
|
---|
70 |
|
---|
71 | #ifdef _WIN32
|
---|
72 | progname = argv[0];
|
---|
73 | #endif
|
---|
74 |
|
---|
75 | if (argc != 2)
|
---|
76 | errx(res, "Usage: %s [host:]port", argv[0]);
|
---|
77 | hostport = argv[1];
|
---|
78 |
|
---|
79 | /*
|
---|
80 | * An SSL_CTX holds shared configuration information for multiple
|
---|
81 | * subsequent per-client SSL connections.
|
---|
82 | */
|
---|
83 | ctx = SSL_CTX_new(TLS_server_method());
|
---|
84 | if (ctx == NULL) {
|
---|
85 | ERR_print_errors_fp(stderr);
|
---|
86 | errx(res, "Failed to create server SSL_CTX");
|
---|
87 | }
|
---|
88 |
|
---|
89 | /*
|
---|
90 | * TLS versions older than TLS 1.2 are deprecated by IETF and SHOULD
|
---|
91 | * be avoided if possible.
|
---|
92 | */
|
---|
93 | if (!SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION)) {
|
---|
94 | SSL_CTX_free(ctx);
|
---|
95 | ERR_print_errors_fp(stderr);
|
---|
96 | errx(res, "Failed to set the minimum TLS protocol version");
|
---|
97 | }
|
---|
98 |
|
---|
99 | #if 0
|
---|
100 | /*
|
---|
101 | * In applications (e.g. SMTP) where most clients are performing
|
---|
102 | * unauthenticated opportunistic TLS it may make sense to set the security
|
---|
103 | * level to 0, allowing weaker encryption parameters, which are still
|
---|
104 | * stronger than a potential cleartext fallback.
|
---|
105 | *
|
---|
106 | * The default security level is 2 (as of OpenSSL 3.2), which is roughly
|
---|
107 | * equivalent to that of 112 bit symmetric keys, or 2048-bit RSA or
|
---|
108 | * finite-field Diffie-Hellman keys. Notably, non-zero security levels no
|
---|
109 | * longer allow the use of SHA-1 in certificate signatures, key exchange
|
---|
110 | * or in the TLS 1.[01] PRF (so TLS 1.0 and 1.1 require security level 0).
|
---|
111 | */
|
---|
112 | SSL_CTX_set_security_level(ctx, 0);
|
---|
113 | #endif
|
---|
114 |
|
---|
115 | /*
|
---|
116 | * Tolerate clients hanging up without a TLS "shutdown". Appropriate in all
|
---|
117 | * application protocols which perform their own message "framing", and
|
---|
118 | * don't rely on TLS to defend against "truncation" attacks.
|
---|
119 | */
|
---|
120 | opts = SSL_OP_IGNORE_UNEXPECTED_EOF;
|
---|
121 |
|
---|
122 | /*
|
---|
123 | * Block potential CPU-exhaustion attacks by clients that request frequent
|
---|
124 | * renegotiation. This is of course only effective if there are existing
|
---|
125 | * limits on initial full TLS handshake or connection rates.
|
---|
126 | */
|
---|
127 | opts |= SSL_OP_NO_RENEGOTIATION;
|
---|
128 |
|
---|
129 | /*
|
---|
130 | * Most servers elect to use their own cipher preference rather than that of
|
---|
131 | * the client.
|
---|
132 | */
|
---|
133 | opts |= SSL_OP_CIPHER_SERVER_PREFERENCE;
|
---|
134 |
|
---|
135 | /* Apply the selection options */
|
---|
136 | SSL_CTX_set_options(ctx, opts);
|
---|
137 |
|
---|
138 | /*
|
---|
139 | * Load the server's certificate *chain* file (PEM format), which includes
|
---|
140 | * not only the leaf (end-entity) server certificate, but also any
|
---|
141 | * intermediate issuer-CA certificates. The leaf certificate must be the
|
---|
142 | * first certificate in the file.
|
---|
143 | *
|
---|
144 | * In advanced use-cases this can be called multiple times, once per public
|
---|
145 | * key algorithm for which the server has a corresponding certificate.
|
---|
146 | * However, the corresponding private key (see below) must be loaded first,
|
---|
147 | * *before* moving on to the next chain file.
|
---|
148 | *
|
---|
149 | * The requisite files "chain.pem" and "pkey.pem" can be generated by running
|
---|
150 | * "make chain" in this directory. If the server will be executed from some
|
---|
151 | * other directory, move or copy the files there.
|
---|
152 | */
|
---|
153 | if (SSL_CTX_use_certificate_chain_file(ctx, "chain.pem") <= 0) {
|
---|
154 | SSL_CTX_free(ctx);
|
---|
155 | ERR_print_errors_fp(stderr);
|
---|
156 | errx(res, "Failed to load the server certificate chain file");
|
---|
157 | }
|
---|
158 |
|
---|
159 | /*
|
---|
160 | * Load the corresponding private key, this also checks that the private
|
---|
161 | * key matches the just loaded end-entity certificate. It does not check
|
---|
162 | * whether the certificate chain is valid, the certificates could be
|
---|
163 | * expired, or may otherwise fail to form a chain that a client can validate.
|
---|
164 | */
|
---|
165 | if (SSL_CTX_use_PrivateKey_file(ctx, "pkey.pem", SSL_FILETYPE_PEM) <= 0) {
|
---|
166 | SSL_CTX_free(ctx);
|
---|
167 | ERR_print_errors_fp(stderr);
|
---|
168 | errx(res, "Error loading the server private key file, "
|
---|
169 | "possible key/cert mismatch???");
|
---|
170 | }
|
---|
171 |
|
---|
172 | /*
|
---|
173 | * Servers that want to enable session resumption must specify a cache id
|
---|
174 | * byte array, that identifies the server application, and reduces the
|
---|
175 | * chance of inappropriate cache sharing.
|
---|
176 | */
|
---|
177 | SSL_CTX_set_session_id_context(ctx, (void *)cache_id, sizeof(cache_id));
|
---|
178 | SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_SERVER);
|
---|
179 |
|
---|
180 | /*
|
---|
181 | * How many client TLS sessions to cache. The default is
|
---|
182 | * SSL_SESSION_CACHE_MAX_SIZE_DEFAULT (20k in recent OpenSSL versions),
|
---|
183 | * which may be too small or too large.
|
---|
184 | */
|
---|
185 | SSL_CTX_sess_set_cache_size(ctx, 1024);
|
---|
186 |
|
---|
187 | /*
|
---|
188 | * Sessions older than this are considered a cache miss even if still in
|
---|
189 | * the cache. The default is two hours. Busy servers whose clients make
|
---|
190 | * many connections in a short burst may want a shorter timeout, on lightly
|
---|
191 | * loaded servers with sporadic connections from any given client, a longer
|
---|
192 | * time may be appropriate.
|
---|
193 | */
|
---|
194 | SSL_CTX_set_timeout(ctx, 3600);
|
---|
195 |
|
---|
196 | /*
|
---|
197 | * Clients rarely employ certificate-based authentication, and so we don't
|
---|
198 | * require "mutual" TLS authentication (indeed there's no way to know
|
---|
199 | * whether or how the client authenticated the server, so the term "mutual"
|
---|
200 | * is potentially misleading).
|
---|
201 | *
|
---|
202 | * Since we're not soliciting or processing client certificates, we don't
|
---|
203 | * need to configure a trusted-certificate store, so no call to
|
---|
204 | * SSL_CTX_set_default_verify_paths() is needed. The server's own
|
---|
205 | * certificate chain is assumed valid.
|
---|
206 | */
|
---|
207 | SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL);
|
---|
208 |
|
---|
209 | /*
|
---|
210 | * Create a listener socket wrapped in a BIO.
|
---|
211 | * The first call to BIO_do_accept() initialises the socket
|
---|
212 | */
|
---|
213 | acceptor_bio = BIO_new_accept(hostport);
|
---|
214 | if (acceptor_bio == NULL) {
|
---|
215 | SSL_CTX_free(ctx);
|
---|
216 | ERR_print_errors_fp(stderr);
|
---|
217 | errx(res, "Error creating acceptor bio");
|
---|
218 | }
|
---|
219 |
|
---|
220 | BIO_set_bind_mode(acceptor_bio, BIO_BIND_REUSEADDR);
|
---|
221 | if (BIO_do_accept(acceptor_bio) <= 0) {
|
---|
222 | SSL_CTX_free(ctx);
|
---|
223 | ERR_print_errors_fp(stderr);
|
---|
224 | errx(res, "Error setting up acceptor socket");
|
---|
225 | }
|
---|
226 |
|
---|
227 | /* Wait for incoming connection */
|
---|
228 | for (;;) {
|
---|
229 | BIO *client_bio;
|
---|
230 | SSL *ssl;
|
---|
231 | unsigned char buf[8192];
|
---|
232 | size_t nread;
|
---|
233 | size_t nwritten;
|
---|
234 | size_t total = 0;
|
---|
235 |
|
---|
236 | /* Pristine error stack for each new connection */
|
---|
237 | ERR_clear_error();
|
---|
238 |
|
---|
239 | /* Wait for the next client to connect */
|
---|
240 | if (BIO_do_accept(acceptor_bio) <= 0) {
|
---|
241 | /* Client went away before we accepted the connection */
|
---|
242 | continue;
|
---|
243 | }
|
---|
244 |
|
---|
245 | /* Pop the client connection from the BIO chain */
|
---|
246 | client_bio = BIO_pop(acceptor_bio);
|
---|
247 | fprintf(stderr, "New client connection accepted\n");
|
---|
248 |
|
---|
249 | /* Associate a new SSL handle with the new connection */
|
---|
250 | if ((ssl = SSL_new(ctx)) == NULL) {
|
---|
251 | ERR_print_errors_fp(stderr);
|
---|
252 | warnx("Error creating SSL handle for new connection");
|
---|
253 | BIO_free(client_bio);
|
---|
254 | continue;
|
---|
255 | }
|
---|
256 | SSL_set_bio(ssl, client_bio, client_bio);
|
---|
257 |
|
---|
258 | /* Attempt an SSL handshake with the client */
|
---|
259 | if (SSL_accept(ssl) <= 0) {
|
---|
260 | ERR_print_errors_fp(stderr);
|
---|
261 | warnx("Error performing SSL handshake with client");
|
---|
262 | SSL_free(ssl);
|
---|
263 | continue;
|
---|
264 | }
|
---|
265 |
|
---|
266 | while (SSL_read_ex(ssl, buf, sizeof(buf), &nread) > 0) {
|
---|
267 | if (SSL_write_ex(ssl, buf, nread, &nwritten) > 0 &&
|
---|
268 | nwritten == nread) {
|
---|
269 | total += nwritten;
|
---|
270 | continue;
|
---|
271 | }
|
---|
272 | warnx("Error echoing client input");
|
---|
273 | break;
|
---|
274 | }
|
---|
275 | fprintf(stderr, "Client connection closed, %zu bytes sent\n", total);
|
---|
276 | SSL_free(ssl);
|
---|
277 | }
|
---|
278 |
|
---|
279 | /*
|
---|
280 | * Unreachable placeholder cleanup code, the above loop runs forever.
|
---|
281 | */
|
---|
282 | SSL_CTX_free(ctx);
|
---|
283 | return EXIT_SUCCESS;
|
---|
284 | }
|
---|