Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/crypto/openssl/demos/guide/tls-server-block.c
34876 views
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
}
285
286