Path: blob/main/crypto/openssl/demos/guide/tls-server-block.c
34876 views
/*1* Copyright 2024 The OpenSSL Project Authors. All Rights Reserved.2*3* Licensed under the Apache License 2.0 (the "License"). You may not use4* this file except in compliance with the License. You can obtain a copy5* in the file LICENSE in the source distribution or at6* https://www.openssl.org/source/license.html7*/89/*10* NB: Changes to this file should also be reflected in11* doc/man7/ossl-guide-tls-server-block.pod12*/1314#include <string.h>1516/* Include the appropriate header file for SOCK_STREAM */17#ifdef _WIN32 /* Windows */18# include <stdarg.h>19# include <winsock2.h>20#else /* Linux/Unix */21# include <err.h>22# include <sys/socket.h>23# include <sys/select.h>24#endif2526#include <openssl/bio.h>27#include <openssl/ssl.h>28#include <openssl/err.h>2930static const char cache_id[] = "OpenSSL Demo Server";3132#ifdef _WIN3233static const char *progname;3435static void vwarnx(const char *fmt, va_list ap)36{37if (progname != NULL)38fprintf(stderr, "%s: ", progname);39vfprintf(stderr, fmt, ap);40putc('\n', stderr);41}4243static void errx(int status, const char *fmt, ...)44{45va_list ap;46va_start(ap, fmt);47vwarnx(fmt, ap);48va_end(ap);49exit(status);50}5152static void warnx(const char *fmt, ...)53{54va_list ap;55va_start(ap, fmt);56vwarnx(fmt, ap);57va_end(ap);58}59#endif6061/* Minimal TLS echo server. */62int main(int argc, char *argv[])63{64int res = EXIT_FAILURE;65long opts;66const char *hostport;67SSL_CTX *ctx = NULL;68BIO *acceptor_bio;6970#ifdef _WIN3271progname = argv[0];72#endif7374if (argc != 2)75errx(res, "Usage: %s [host:]port", argv[0]);76hostport = argv[1];7778/*79* An SSL_CTX holds shared configuration information for multiple80* subsequent per-client SSL connections.81*/82ctx = SSL_CTX_new(TLS_server_method());83if (ctx == NULL) {84ERR_print_errors_fp(stderr);85errx(res, "Failed to create server SSL_CTX");86}8788/*89* TLS versions older than TLS 1.2 are deprecated by IETF and SHOULD90* be avoided if possible.91*/92if (!SSL_CTX_set_min_proto_version(ctx, TLS1_2_VERSION)) {93SSL_CTX_free(ctx);94ERR_print_errors_fp(stderr);95errx(res, "Failed to set the minimum TLS protocol version");96}9798#if 099/*100* In applications (e.g. SMTP) where most clients are performing101* unauthenticated opportunistic TLS it may make sense to set the security102* level to 0, allowing weaker encryption parameters, which are still103* stronger than a potential cleartext fallback.104*105* The default security level is 2 (as of OpenSSL 3.2), which is roughly106* equivalent to that of 112 bit symmetric keys, or 2048-bit RSA or107* finite-field Diffie-Hellman keys. Notably, non-zero security levels no108* longer allow the use of SHA-1 in certificate signatures, key exchange109* or in the TLS 1.[01] PRF (so TLS 1.0 and 1.1 require security level 0).110*/111SSL_CTX_set_security_level(ctx, 0);112#endif113114/*115* Tolerate clients hanging up without a TLS "shutdown". Appropriate in all116* application protocols which perform their own message "framing", and117* don't rely on TLS to defend against "truncation" attacks.118*/119opts = SSL_OP_IGNORE_UNEXPECTED_EOF;120121/*122* Block potential CPU-exhaustion attacks by clients that request frequent123* renegotiation. This is of course only effective if there are existing124* limits on initial full TLS handshake or connection rates.125*/126opts |= SSL_OP_NO_RENEGOTIATION;127128/*129* Most servers elect to use their own cipher preference rather than that of130* the client.131*/132opts |= SSL_OP_CIPHER_SERVER_PREFERENCE;133134/* Apply the selection options */135SSL_CTX_set_options(ctx, opts);136137/*138* Load the server's certificate *chain* file (PEM format), which includes139* not only the leaf (end-entity) server certificate, but also any140* intermediate issuer-CA certificates. The leaf certificate must be the141* first certificate in the file.142*143* In advanced use-cases this can be called multiple times, once per public144* key algorithm for which the server has a corresponding certificate.145* However, the corresponding private key (see below) must be loaded first,146* *before* moving on to the next chain file.147*148* The requisite files "chain.pem" and "pkey.pem" can be generated by running149* "make chain" in this directory. If the server will be executed from some150* other directory, move or copy the files there.151*/152if (SSL_CTX_use_certificate_chain_file(ctx, "chain.pem") <= 0) {153SSL_CTX_free(ctx);154ERR_print_errors_fp(stderr);155errx(res, "Failed to load the server certificate chain file");156}157158/*159* Load the corresponding private key, this also checks that the private160* key matches the just loaded end-entity certificate. It does not check161* whether the certificate chain is valid, the certificates could be162* expired, or may otherwise fail to form a chain that a client can validate.163*/164if (SSL_CTX_use_PrivateKey_file(ctx, "pkey.pem", SSL_FILETYPE_PEM) <= 0) {165SSL_CTX_free(ctx);166ERR_print_errors_fp(stderr);167errx(res, "Error loading the server private key file, "168"possible key/cert mismatch???");169}170171/*172* Servers that want to enable session resumption must specify a cache id173* byte array, that identifies the server application, and reduces the174* chance of inappropriate cache sharing.175*/176SSL_CTX_set_session_id_context(ctx, (void *)cache_id, sizeof(cache_id));177SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_SERVER);178179/*180* How many client TLS sessions to cache. The default is181* SSL_SESSION_CACHE_MAX_SIZE_DEFAULT (20k in recent OpenSSL versions),182* which may be too small or too large.183*/184SSL_CTX_sess_set_cache_size(ctx, 1024);185186/*187* Sessions older than this are considered a cache miss even if still in188* the cache. The default is two hours. Busy servers whose clients make189* many connections in a short burst may want a shorter timeout, on lightly190* loaded servers with sporadic connections from any given client, a longer191* time may be appropriate.192*/193SSL_CTX_set_timeout(ctx, 3600);194195/*196* Clients rarely employ certificate-based authentication, and so we don't197* require "mutual" TLS authentication (indeed there's no way to know198* whether or how the client authenticated the server, so the term "mutual"199* is potentially misleading).200*201* Since we're not soliciting or processing client certificates, we don't202* need to configure a trusted-certificate store, so no call to203* SSL_CTX_set_default_verify_paths() is needed. The server's own204* certificate chain is assumed valid.205*/206SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL);207208/*209* Create a listener socket wrapped in a BIO.210* The first call to BIO_do_accept() initialises the socket211*/212acceptor_bio = BIO_new_accept(hostport);213if (acceptor_bio == NULL) {214SSL_CTX_free(ctx);215ERR_print_errors_fp(stderr);216errx(res, "Error creating acceptor bio");217}218219BIO_set_bind_mode(acceptor_bio, BIO_BIND_REUSEADDR);220if (BIO_do_accept(acceptor_bio) <= 0) {221SSL_CTX_free(ctx);222ERR_print_errors_fp(stderr);223errx(res, "Error setting up acceptor socket");224}225226/* Wait for incoming connection */227for (;;) {228BIO *client_bio;229SSL *ssl;230unsigned char buf[8192];231size_t nread;232size_t nwritten;233size_t total = 0;234235/* Pristine error stack for each new connection */236ERR_clear_error();237238/* Wait for the next client to connect */239if (BIO_do_accept(acceptor_bio) <= 0) {240/* Client went away before we accepted the connection */241continue;242}243244/* Pop the client connection from the BIO chain */245client_bio = BIO_pop(acceptor_bio);246fprintf(stderr, "New client connection accepted\n");247248/* Associate a new SSL handle with the new connection */249if ((ssl = SSL_new(ctx)) == NULL) {250ERR_print_errors_fp(stderr);251warnx("Error creating SSL handle for new connection");252BIO_free(client_bio);253continue;254}255SSL_set_bio(ssl, client_bio, client_bio);256257/* Attempt an SSL handshake with the client */258if (SSL_accept(ssl) <= 0) {259ERR_print_errors_fp(stderr);260warnx("Error performing SSL handshake with client");261SSL_free(ssl);262continue;263}264265while (SSL_read_ex(ssl, buf, sizeof(buf), &nread) > 0) {266if (SSL_write_ex(ssl, buf, nread, &nwritten) > 0 &&267nwritten == nread) {268total += nwritten;269continue;270}271warnx("Error echoing client input");272break;273}274fprintf(stderr, "Client connection closed, %zu bytes sent\n", total);275SSL_free(ssl);276}277278/*279* Unreachable placeholder cleanup code, the above loop runs forever.280*/281SSL_CTX_free(ctx);282return EXIT_SUCCESS;283}284285286