|
| 1 | +/** |
| 2 | + * \file |
| 3 | + * \author Jakub Antonín Štigler <[email protected]> |
| 4 | + * \brief Factory for tls connections. (source file) |
| 5 | + * \date 2025 |
| 6 | + * |
| 7 | + * Copyright: (C) 2023 CESNET, z.s.p.o. |
| 8 | + * SPDX-License-Identifier: BSD-3-Clause |
| 9 | + */ |
| 10 | + |
| 11 | +#include "DecoderFactory.hpp" |
| 12 | + |
| 13 | +#include "../Config.hpp" |
| 14 | +#include "TlsDecoder.hpp" |
| 15 | + |
| 16 | +// OpenSSL v1.1.1 compatibility. |
| 17 | +// The flag SSL_OP_IGNORE_UNEXPECTED_EOF is not supported in v1.1.1. This will define it as flag |
| 18 | +// without effect if it is not supported so that it may be used in any case. |
| 19 | +// The flag is not neccesary, but with it if peer closes the connection without sending proper TLS |
| 20 | +// message, it will not be treated as error. This is OK because can check if IPFIX messages are |
| 21 | +// complete. |
| 22 | +#ifndef SSL_OP_IGNORE_UNEXPECTED_EOF |
| 23 | +#define SSL_OP_IGNORE_UNEXPECTED_EOF 0 |
| 24 | +#endif // ifndef SSL_OP_IGNORE_UNEXPECTED_EOF |
| 25 | + |
| 26 | +namespace tcp_in { |
| 27 | +namespace tls { |
| 28 | + |
| 29 | +/** |
| 30 | + * @brief Load certificate authority based on the configuration. |
| 31 | + * @param conf Configuration of what should be load as certificate authority. |
| 32 | + * @param ctx Context to which will the ca load. |
| 33 | + */ |
| 34 | +static void load_ca(const Config &conf, SslCtx &ctx); |
| 35 | + |
| 36 | +DecoderFactory::DecoderFactory(const Config &conf) : m_ctx(TLS_server_method()) { |
| 37 | + // Cache configuration. Cache is used to speed up initial handshake for clients that were |
| 38 | + // recently connected. |
| 39 | + constexpr long CACHE_TIMEOUT_SECONDS = 3600; |
| 40 | + const std::string cache_id = "ipfixcol2"; |
| 41 | + constexpr std::size_t CACHE_SIZE = 1024; |
| 42 | + |
| 43 | + m_ctx.set_min_proto_version(TLS1_2_VERSION); |
| 44 | + m_ctx.set_options( |
| 45 | + SSL_OP_IGNORE_UNEXPECTED_EOF | SSL_OP_NO_RENEGOTIATION | SSL_OP_CIPHER_SERVER_PREFERENCE |
| 46 | + ); |
| 47 | + |
| 48 | + sleep(1); |
| 49 | + |
| 50 | + m_ctx.use_certificate_chain_file(conf.certificate_file.c_str()); |
| 51 | + m_ctx.use_private_key_file(conf.private_key_file.c_str(), SSL_FILETYPE_PEM); |
| 52 | + |
| 53 | + m_ctx.set_session_id_context(cache_id.data(), unsigned(cache_id.size())); |
| 54 | + m_ctx.set_session_cache_mode(SSL_SESS_CACHE_SERVER); |
| 55 | + m_ctx.sess_set_cache_size(CACHE_SIZE); |
| 56 | + m_ctx.sess_set_timeout(CACHE_TIMEOUT_SECONDS); |
| 57 | + |
| 58 | + if (conf.verify_peer) { |
| 59 | + m_ctx.set_verify(SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT); |
| 60 | + load_ca(conf, m_ctx); |
| 61 | + } else { |
| 62 | + m_ctx.set_verify(SSL_VERIFY_NONE); |
| 63 | + } |
| 64 | +} |
| 65 | + |
| 66 | +std::unique_ptr<Decoder> DecoderFactory::create(int fd) { |
| 67 | + return std::unique_ptr<Decoder>(new TlsDecoder(m_ctx, fd)); |
| 68 | +} |
| 69 | + |
| 70 | +static void load_ca(const Config &conf, SslCtx &ctx) { |
| 71 | + if (conf.use_default_ca) { |
| 72 | + ctx.set_default_verify_paths(); |
| 73 | + return; |
| 74 | + } |
| 75 | + |
| 76 | + if (conf.default_ca_file) { |
| 77 | + ctx.set_default_verify_file(); |
| 78 | + } else if (!conf.ca_file.empty()) { |
| 79 | + ctx.load_verify_file(conf.ca_file.c_str()); |
| 80 | + } |
| 81 | + |
| 82 | + if (conf.default_ca_dir) { |
| 83 | + ctx.set_default_verify_dir(); |
| 84 | + } else if (!conf.ca_dir.empty()) { |
| 85 | + ctx.load_verify_dir(conf.ca_dir.c_str()); |
| 86 | + } |
| 87 | + |
| 88 | + if (conf.default_ca_store) { |
| 89 | + ctx.set_default_verify_store(); |
| 90 | + } else if (!conf.ca_store.empty()) { |
| 91 | + ctx.load_verify_store(conf.ca_store.c_str()); |
| 92 | + } |
| 93 | +} |
| 94 | + |
| 95 | +} // namespace tls |
| 96 | +} // namespace tcp_in |
0 commit comments