2
0
mirror of https://gitlab.isc.org/isc-projects/kea synced 2025-08-30 21:45:37 +00:00

[#1661] Revamped TLS headers

This commit is contained in:
Francis Dupont
2021-02-25 11:49:25 +01:00
parent 5df26cbf88
commit 2a2428f6f8
9 changed files with 226 additions and 113 deletions

View File

@@ -17,6 +17,8 @@ libkea_asiolink_la_LDFLAGS += $(CRYPTO_LDFLAGS)
libkea_asiolink_la_SOURCES = asiolink.h
libkea_asiolink_la_SOURCES += asio_wrapper.h
libkea_asiolink_la_SOURCES += addr_utilities.cc addr_utilities.h
libkea_asiolink_la_SOURCES += botan_tls.h
libkea_asiolink_la_SOURCES += common_tls.h
libkea_asiolink_la_SOURCES += crypto_tls.h
libkea_asiolink_la_SOURCES += dummy_io_cb.h
libkea_asiolink_la_SOURCES += interval_timer.cc interval_timer.h
@@ -28,6 +30,7 @@ libkea_asiolink_la_SOURCES += io_error.h
libkea_asiolink_la_SOURCES += io_service.h io_service.cc
libkea_asiolink_la_SOURCES += io_service_signal.cc io_service_signal.h
libkea_asiolink_la_SOURCES += io_socket.h io_socket.cc
libkea_asiolink_la_SOURCES += openssl_tls.h
libkea_asiolink_la_SOURCES += process_spawn.h process_spawn.cc
libkea_asiolink_la_SOURCES += tcp_acceptor.h
libkea_asiolink_la_SOURCES += tcp_endpoint.h
@@ -41,10 +44,10 @@ libkea_asiolink_la_SOURCES += unix_domain_socket_acceptor.h
libkea_asiolink_la_SOURCES += unix_domain_socket_endpoint.h
if HAVE_BOTAN
#libkea_asiolink_la_SOURCES += botan_tls.cc botan_tls.h
#libkea_asiolink_la_SOURCES += botan_tls.cc
endif
if HAVE_OPENSSL
libkea_asiolink_la_SOURCES += openssl_tls.cc openssl_tls.h
libkea_asiolink_la_SOURCES += openssl_tls.cc
endif
# Note: the ordering matters: -Wno-... must follow -Wextra (defined in
@@ -60,6 +63,8 @@ libkea_asiolink_include_HEADERS = \
addr_utilities.h \
asio_wrapper.h \
asiolink.h \
botan_tls.h \
common_tls.h \
crypto_tls.h \
dummy_io_cb.h \
interval_timer.h \
@@ -71,6 +76,7 @@ libkea_asiolink_include_HEADERS = \
io_service.h \
io_service_signal.h \
io_socket.h \
openssl_tls.h \
process_spawn.h \
tcp_acceptor.h \
tcp_endpoint.h \

View File

@@ -4,11 +4,18 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
// Do not include this header directly: use crypto_tls.h instead.
#ifndef BOTAN_TLS_H
#define BOTAN_TLS_H
#ifdef WITH_BOTAN
#include <asiolink/asio_wrapper.h>
#include <asiolink/io_asio_socket.h>
#include <asiolink/io_service.h>
#include <asiolink/common_tls.h>
namespace isc {
namespace asiolink {

View File

@@ -0,0 +1,170 @@
// Copyright (C) 2021 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
// Do not include this header directly: use crypto_tls.h instead.
#ifndef COMMON_TLS_H
#define COMMON_TLS_H
/// @file common_tls.h Common TLS API.
// Verify that this file was not directly included.
#ifndef CRYPTO_TLS_H
#error crypto_tls.h must be included in place of common_tls.h
#endif
#include <cryptolink/cryptolink.h>
#include <boost/noncopyable.hpp>
#include <boost/shared_ptr.hpp>
#include <netinet/in.h>
#include <sys/socket.h>
namespace isc {
namespace asiolink {
/// @brief Client and server roles.
enum TlsRole { CLIENT, SERVER };
/// @brief TLS context base class.
class TlsContextBase : private boost::noncopyable {
public:
/// @brief Destructor.
virtual ~TlsContextBase() { }
/// @brief Create a fresh context.
///
/// @param role The TLS role client or server.
explicit TlsContextBase(TlsRole role) : role_(role) { }
/// @brief Returns the role.
TlsRole getRole() const {
return (role_);
}
/// @note No need for a role set method.
/// @brief Set the peer certificate requirement mode.
///
/// @param cert_required True if peer certificates are required,
/// false if they are optional.
virtual void setCertRequired(bool cert_required) = 0;
/// @brief Get the peer certificate requirement mode.
///
/// @return True if peer certificates are required, false if they
/// are optional.
virtual bool getCertRequired() const = 0;
/// @brief Load the trust anchor aka certificate authority.
///
/// @param ca_file The certificate file name.
/// @throw isc::cryptolink::LibraryError on various errors as
/// file not found, bad format, etc.
virtual void loadCaFile(const std::string& ca_file) = 0;
/// @brief Load the trust anchor aka certificate authority.
///
/// @param ca_path The certificate directory name.
/// @throw isc::cryptolink::LibraryError on various errors as
/// file not found, bad format, etc.
virtual void loadCaPath(const std::string& ca_path) = 0;
/// @brief Load the certificate file.
///
/// @param cert_file The certificate file name.
/// @throw isc::cryptolink::LibraryError on various errors as
/// file not found, bad format, etc.
virtual void loadCertFile(const std::string& cert_file) = 0;
/// @brief Load the private key file name.
///
/// @param key_file The private key file name.
/// @throw isc::cryptolink::LibraryError on various errors as
/// file not found, bad format, etc.
virtual void loadKeyFile(const std::string& key_file) = 0;
public:
/// @brief The role i.e. client or server.
TlsRole role_;
};
/// @brief Forward declaration of OpenSSL TLS context.
class TlsContext;
/// @brief The type of shared pointers to TlsContext objects.
///
/// @note Not clear we need shared pointers but they covers more use cases...
typedef boost::shared_ptr<TlsContext> TlsContextPtr;
/// @brief TLS stream base class.
///
/// @tparam Callback The type of callbacks.
/// @tparam TlsStreamImpl The type of underlying TLS streams.
/// @tparam TlsCertificate The type of X509 certificates.
template <typename Callback, typename TlsStreamImpl, typename TlsCertificate>
class TlsStreamBase : public TlsStreamImpl {
public:
/// @brief Constructor.
///
/// @param service I/O Service object used to manage the stream.
/// @param context Pointer to the TLS context.
/// @note The caller must not provide a null pointer to the TLS context.
TlsStreamBase(IOService& service, TlsContextPtr context);
/// @brief Destructor.
virtual ~TlsStreamBase() { }
/// @brief Returns the role.
TlsRole getRole() const {
return (role_);
}
/// @brief TLS Handshake.
///
/// @param callback Callback object.
virtual void handshake(Callback& callback) = 0;
/// @brief TLS shutdown.
///
/// @param callback Callback object.
virtual void shutdown(Callback& callback) = 0;
/// @brief Clear the TLS state.
virtual void clear() = 0;
/// @brief Return the peer certificate.
///
/// @note The native_handle() method is used so it can't be made const.
/// @note Do not forget to free it when no longer used.
virtual TlsCertificate* getPeerCert() = 0;
/// @break Return the commonName part of the subjectName of
/// the peer certificate.
///
/// First commonName when there are more than one, in UTF-8.
///
/// @return The commonName part of the subjectName or the empty string.
virtual std::string getSubject() = 0;
/// @break Return the commonName part of the issuerName of
/// the peer certificate.
///
/// First commonName when there are more than one, in UTF-8.
///
/// @return The commonName part of the issuerName or the empty string.
virtual std::string getIssuer() = 0;
/// @brief The role i.e. client or server.
TlsRole role_;
};
} // namespace asiolink
} // namespace isc
#endif // COMMON_TLS_H

View File

@@ -7,86 +7,20 @@
#ifndef CRYPTO_TLS_H
#define CRYPTO_TLS_H
#include <cryptolink/cryptolink.h>
/// @file crypto_tls.h TLS API.
#include <boost/noncopyable.hpp>
#include <boost/shared_ptr.hpp>
// Verify that config.h was included.
#ifndef CONFIG_H_WAS_INCLUDED
#error config.h must be included before crypto_tls.h
#endif
#include <netinet/in.h>
#include <sys/socket.h>
// Include different versions.
#include <asiolink/botan_tls.h>
#include <asiolink/openssl_tls.h>
namespace isc {
namespace asiolink {
/// @file crypto_tls.h Common TLS API.
/// @brief Client and server roles.
enum TlsRole { CLIENT, SERVER };
/// @brief TLS context base class.
class TlsContextBase : private boost::noncopyable {
public:
/// @brief Destructor.
virtual ~TlsContextBase() { }
/// @brief Create a fresh context.
///
/// @param role The TLS role client or server.
explicit TlsContextBase(TlsRole role) : role_(role) { }
/// @brief Returns the role.
TlsRole getRole() const {
return (role_);
}
/// @note No need for a role set method.
/// @brief Set the peer certificate requirement mode.
///
/// @param cert_required True if peer certificates are required,
/// false if they are optional.
virtual void setCertRequired(bool cert_required) = 0;
/// @brief Get the peer certificate requirement mode.
///
/// @return True if peer certificates are required, false if they
/// are optional.
virtual bool getCertRequired() const = 0;
/// @brief Load the trust anchor aka certificate authority.
///
/// @param ca_file The certificate file name.
/// @throw isc::cryptolink::LibraryError on various errors as
/// file not found, bad format, etc.
virtual void loadCaFile(const std::string& ca_file) = 0;
/// @brief Load the trust anchor aka certificate authority.
///
/// @param ca_path The certificate directory name.
/// @throw isc::cryptolink::LibraryError on various errors as
/// file not found, bad format, etc.
virtual void loadCaPath(const std::string& ca_path) = 0;
/// @brief Load the certificate file.
///
/// @param cert_file The certificate file name.
/// @throw isc::cryptolink::LibraryError on various errors as
/// file not found, bad format, etc.
virtual void loadCertFile(const std::string& cert_file) = 0;
/// @brief Load the private key file name.
///
/// @param key_file The private key file name.
/// @throw isc::cryptolink::LibraryError on various errors as
/// file not found, bad format, etc.
virtual void loadKeyFile(const std::string& key_file) = 0;
public:
/// @brief The role i.e. client or server.
TlsRole role_;
};
} // namespace asiolink
} // namespace isc
// Verify that one version matched.
#ifndef COMMON_TLS_H
#error no TLS backend was found
#endif
#endif // CRYPTO_TLS_H

View File

@@ -10,7 +10,6 @@
#include <asiolink/asio_wrapper.h>
#include <asiolink/crypto_tls.h>
#include <asiolink/openssl_tls.h>
#include <sys/stat.h>

View File

@@ -4,28 +4,25 @@
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
// Do not include this header directly: use crypto_tls.h instead.
#ifndef OPENSSL_TLS_H
#define OPENSSL_TLS_H
/// @file openssl_tls.h OpenSSL implementation of the TLS API.
#ifdef WITH_OPENSSL
#include <asiolink/asio_wrapper.h>
#include <asiolink/io_asio_socket.h>
#include <asiolink/io_service.h>
#include <asiolink/common_tls.h>
#include <boost/asio/ssl.hpp>
namespace isc {
namespace asiolink {
/// @brief Forward declaration of OpenSSL TLS context.
class TlsContext;
/// @brief The type of shared pointers to TlsContext objects.
///
/// @note Not clear we need shared pointers but they covers more use cases...
typedef boost::shared_ptr<TlsContext> TlsContextPtr;
/// @brief OpenSSL TLS context.
class TlsContext : public TlsContextBase {
public:
@@ -109,40 +106,50 @@ typedef boost::asio::ssl::stream<boost::asio::ip::tcp::socket> TlsStreamImpl;
/// @brief The type of X509 certificates.
typedef ::X509 TlsCertificate;
/// @brief TlsStreamBase constructor.
/// @brief TLS stream base class.
///
/// @param Callback The type of callbacks.
/// @param TlsStreamImpl The type of underlying TLS streams.
/// @param TlsCertificate The type of X509 certificates.
template <typename Callback, typename TlsStreamImpl, typename TlsCertificate>
TlsStreamBase<Callback, TlsStreamImpl, TlsCertificate>::
TlsStreamBase(IOService& service, TlsContextPtr context)
: TlsStreamImpl(service.get_io_service(), context->getContext()),
role_(context->getRole()) {
}
/// @brief OpenSSL TLS stream.
///
/// @param callback The callback.
template <typename Callback>
class TlsStream : public TlsStreamImpl {
class TlsStream : public TlsStreamBase<Callback, TlsStreamImpl, TlsCertificate> {
public:
/// @brief Type of the base.
typedef TlsStreamBase<Callback, TlsStreamImpl, TlsCertificate> Base;
/// @brief Constructor.
///
/// @param service I/O Service object used to manage the stream.
/// @param context Pointer to the TLS context.
/// @note The caller must not provide a null pointer to the TLS context.
TlsStream(IOService& service, TlsContextPtr context)
: TlsStreamImpl(service.get_io_service(), context->getContext()),
role_(context->getRole()) {
: Base(service, context) {
}
/// @brief Destructor.
virtual ~TlsStream() { }
/// @brief Returns the role.
TlsRole getRole() const {
return (role_);
}
/// @brief TLS Handshake.
///
/// @param callback Callback object.
virtual void handshake(Callback& callback) {
using namespace boost::asio::ssl;
if (role_ == SERVER) {
async_handshake(stream_base::server, callback);
if (Base::getRole() == SERVER) {
Base::async_handshake(stream_base::server, callback);
} else {
async_handshake(stream_base::client, callback);
Base::async_handshake(stream_base::client, callback);
}
}
@@ -150,7 +157,7 @@ public:
///
/// @param callback Callback object.
virtual void shutdown(Callback& callback) {
async_shutdown(callback);
Base::async_shutdown(callback);
}
/// @brief Clear the SSL object.
@@ -166,16 +173,13 @@ public:
return (::SSL_get_peer_certificate(this->native_handle()));
}
/// @brief The role i.e. client or server.
TlsRole role_;
/// @break Return the commonName part of the subjectName of
/// the peer certificate.
///
/// First commonName when there are more than one, in UTF-8.
///
/// @return The commonName part of the subjectName or the empty string.
std::string getSubject() {
virtual std::string getSubject() {
TlsCertificate* cert = getPeerCert();
if (!cert) {
return ("");
@@ -205,7 +209,7 @@ public:
/// First commonName when there are more than one, in UTF-8.
///
/// @return The commonName part of the issuerName or the empty string.
std::string getIssuer() {
virtual std::string getIssuer() {
TlsCertificate* cert = getPeerCert();
if (!cert) {
return ("");
@@ -230,7 +234,6 @@ public:
}
};
} // namespace asiolink
} // namespace isc

View File

@@ -9,8 +9,6 @@
#include <asiolink/asio_wrapper.h>
#include <asiolink/io_service.h>
#include <asiolink/crypto_tls.h>
#include <asiolink/botan_tls.h>
#include <asiolink/openssl_tls.h>
#include <asiolink/tcp_endpoint.h>
#include <asiolink/testutils/test_tls.h>
#include <testutils/gtest_utils.h>

View File

@@ -12,8 +12,6 @@
#endif
#include <asiolink/crypto_tls.h>
#include <asiolink/botan_tls.h>
#include <asiolink/openssl_tls.h>
#include <string>

View File

@@ -12,8 +12,6 @@
#endif
#include <asiolink/crypto_tls.h>
#include <asiolink/botan_tls.h>
#include <asiolink/openssl_tls.h>
#include <asiolink/tcp_socket.h>
#include <boost/noncopyable.hpp>