Kea 2.7.0
openssl_tls.cc
Go to the documentation of this file.
1// Copyright (C) 2021-2022 Internet Systems Consortium, Inc. ("ISC")
2//
3// This Source Code Form is subject to the terms of the Mozilla Public
4// License, v. 2.0. If a copy of the MPL was not distributed with this
5// file, You can obtain one at http://mozilla.org/MPL/2.0/.
6
8
9#include <config.h>
10
11#ifdef WITH_OPENSSL
12
14#include <asiolink/crypto_tls.h>
15
16#include <sys/stat.h>
17
18#include <openssl/opensslv.h>
19
20using namespace boost::asio;
21using namespace boost::asio::ssl;
22using namespace boost::system;
23using namespace isc::cryptolink;
24
25namespace isc {
26namespace asiolink {
27
28// Enforce TLS 1.2 when the generic TLS method is not available (i.e.
29// the boost version is older than 1.64.0).
30TlsContext::TlsContext(TlsRole role)
31 : TlsContextBase(role), cert_required_(true),
32#ifdef HAVE_GENERIC_TLS_METHOD
33 context_(context::method::tls)
34#else
35#ifdef HAVE_TLS_1_2_METHOD
36 context_(context::method::tlsv12)
37#else
38 context_(context::method::tlsv1)
39#endif
40#endif
41{
42 // Not leave the verify mode to OpenSSL default.
43 setCertRequired(true);
44}
45
46boost::asio::ssl::context&
47TlsContext::getContext() {
48 return (context_);
49}
50
51::SSL_CTX*
52TlsContext::getNativeContext() {
53 return (context_.native_handle());
54}
55
56void
57TlsContext::setCertRequired(bool cert_required) {
58 if (!cert_required && (getRole() == TlsRole::CLIENT)) {
60 "'cert-required' parameter must be true for a TLS client");
61 }
62 cert_required_ = cert_required;
63 error_code ec;
64 int mode = verify_peer | verify_fail_if_no_peer_cert;
65 if (!cert_required_) {
66 mode = verify_none;
67 }
68 context_.set_verify_mode(mode, ec);
69 if (ec) {
70 isc_throw(LibraryError, getErrMsg(ec));
71 }
72}
73
74bool
75TlsContext::getCertRequired() const {
76 return (cert_required_);
77}
78
79void
80TlsContext::loadCaFile(const std::string& ca_file) {
81 error_code ec;
82 context_.load_verify_file(ca_file, ec);
83 if (ec) {
84 isc_throw(LibraryError, getErrMsg(ec));
85 }
86}
87
88void
89TlsContext::loadCaPath(const std::string& ca_path) {
90 error_code ec;
91 context_.add_verify_path(ca_path, ec);
92 if (ec) {
93 isc_throw(LibraryError, getErrMsg(ec));
94 }
95}
96
97void
98TlsContext::loadCertFile(const std::string& cert_file) {
99 error_code ec;
100 context_.use_certificate_chain_file(cert_file, ec);
101 if (ec) {
102 isc_throw(LibraryError, getErrMsg(ec));
103 }
104}
105
106void
107TlsContext::loadKeyFile(const std::string& key_file) {
108 error_code ec;
109 context_.use_private_key_file(key_file, context::file_format::pem, ec);
110 if (ec) {
111 isc_throw(LibraryError, getErrMsg(ec));
112 }
113}
114
115std::string
116TlsContext::getErrMsg(error_code ec) {
117 std::string msg = ec.message();
118#ifdef ERR_SYSTEM_ERROR
119 // The SSL category message() method uses ERR_reason_error_string()
120 // which since OpenSSL 3.0 returns NULL on system errors in order
121 // to avoid a memory leak with the strerror_r() buffer.
122 // This code recovers the user-friendly message from the error code
123 // value i.e. the OpenSSL error. Layout of OpenSSL errors is detailed
124 // in the OpenSSL err.h header.
125 unsigned long err = static_cast<unsigned long>(ec.value());
126 if ((msg == "asio.ssl error") && (ERR_SYSTEM_ERROR(err))) {
127 char buf[1024];
128#ifndef __USE_GNU
129 if (strerror_r(err & ERR_SYSTEM_MASK, &buf[0], sizeof(buf)) == 0) {
130 msg = buf;
131 }
132#else
133 msg = strerror_r(err & ERR_SYSTEM_MASK, &buf[0], sizeof(buf));
134#endif
135 }
136#endif
137 return (msg);
138}
139
140} // namespace asiolink
141} // namespace isc
142
143#endif // WITH_OPENSSL
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
TLS API.
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
Defines the logger used by the top-level component of kea-lfc.